From 9547c4563c09fa816330ccd539d393344ac03fb4 Mon Sep 17 00:00:00 2001 From: LianaHus Date: Wed, 23 Sep 2015 17:31:37 +0200 Subject: fixed-sized arrays as return type Conflicts: test/libsolidity/SolidityEndToEndTest.cpp --- libsolidity/CompilerUtils.cpp | 25 ++++++++++++++++++------- libsolidity/ExpressionCompiler.cpp | 10 +++++++--- libsolidity/Types.cpp | 8 ++++++++ libsolidity/Types.h | 2 ++ 4 files changed, 35 insertions(+), 10 deletions(-) (limited to 'libsolidity') diff --git a/libsolidity/CompilerUtils.cpp b/libsolidity/CompilerUtils.cpp index b9b554e8..a77e6536 100644 --- a/libsolidity/CompilerUtils.cpp +++ b/libsolidity/CompilerUtils.cpp @@ -86,16 +86,27 @@ void CompilerUtils::loadFromMemoryDynamic( bool _padToWordBoundaries, bool _keepUpdatedMemoryOffset ) -{ - solAssert(_type.category() != Type::Category::Array, "Arrays not yet implemented."); +{ if (_keepUpdatedMemoryOffset) m_context << eth::Instruction::DUP1; - unsigned numBytes = loadFromMemoryHelper(_type, _fromCalldata, _padToWordBoundaries); - if (_keepUpdatedMemoryOffset) + + if (auto arrayType = dynamic_cast(&_type)) { - // update memory counter - moveToStackTop(_type.sizeOnStack()); - m_context << u256(numBytes) << eth::Instruction::ADD; + solAssert(!arrayType->isDynamicallySized(), ""); + solAssert(!_fromCalldata, ""); + solAssert(_padToWordBoundaries, ""); + if (_keepUpdatedMemoryOffset) + m_context << arrayType->memorySize() << eth::Instruction::ADD; + } + else + { + unsigned numBytes = loadFromMemoryHelper(_type, _fromCalldata, _padToWordBoundaries); + if (_keepUpdatedMemoryOffset) + { + // update memory counter + moveToStackTop(_type.sizeOnStack()); + m_context << u256(numBytes) << eth::Instruction::ADD; + } } } diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 65706602..49bf2559 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -1256,10 +1256,14 @@ void ExpressionCompiler::appendExternalFunctionCall( } else if (firstReturnType) { - //@todo manually update free memory pointer if we accept returning memory-stored objects utils().fetchFreeMemoryPointer(); - utils().loadFromMemoryDynamic(*firstReturnType, false, true, false); - + if (dynamic_cast(firstReturnType)) + { + utils().loadFromMemoryDynamic(*firstReturnType, false, true, true); + utils().storeFreeMemoryPointer(); + } + else + utils().loadFromMemoryDynamic(*firstReturnType, false, true, false); } } diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 68e8e91d..43120ce5 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -853,6 +853,14 @@ TypePointer ArrayType::externalType() const return std::make_shared(DataLocation::Memory, baseExt, m_length); } +u256 ArrayType::memorySize() const +{ + solAssert(!isDynamicallySized(), ""); + solAssert(m_location == DataLocation::Memory, ""); + + return m_length * m_baseType->memoryHeadSize(); +} + TypePointer ArrayType::copyForLocation(DataLocation _location, bool _isPointer) const { auto copy = make_shared(_location); diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 11218b7a..60281723 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -501,9 +501,11 @@ public: bool isString() const { return m_arrayKind == ArrayKind::String; } TypePointer const& baseType() const { solAssert(!!m_baseType, ""); return m_baseType;} u256 const& length() const { return m_length; } + u256 memorySize() const; TypePointer copyForLocation(DataLocation _location, bool _isPointer) const override; + private: /// String is interpreted as a subtype of Bytes. enum class ArrayKind { Ordinary, Bytes, String }; -- cgit v1.2.3