From 1f6e3651362bdcdaa39773156875c36053d5f6be Mon Sep 17 00:00:00 2001 From: Christian Date: Sun, 15 Feb 2015 00:11:51 +0100 Subject: [PATCH] Move code to loadFromMemory. --- Compiler.cpp | 36 +++++++++------------------------ CompilerUtils.cpp | 45 +++++++++++++++++++++--------------------- CompilerUtils.h | 9 ++++----- ExpressionCompiler.cpp | 7 ++----- 4 files changed, 38 insertions(+), 59 deletions(-) diff --git a/Compiler.cpp b/Compiler.cpp index 4dbcbbfe6..e14935873 100644 --- a/Compiler.cpp +++ b/Compiler.cpp @@ -147,7 +147,7 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract) // retrieve the function signature hash from the calldata if (!interfaceFunctions.empty()) - CompilerUtils(m_context).loadFromMemory(0, 4, false, true); + CompilerUtils(m_context).loadFromMemory(0, IntegerType(CompilerUtils::dataStartOffset * 8), true); // stack now is: 1 0 for (auto const& it: interfaceFunctions) @@ -182,18 +182,10 @@ unsigned Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, b { // We do not check the calldata size, everything is zero-padded. unsigned dataOffset = CompilerUtils::dataStartOffset; // the 4 bytes of the function hash signature - //@todo this can be done more efficiently, saving some CALLDATALOAD calls + + bool const c_padToWords = true; for (TypePointer const& type: _typeParameters) - { - unsigned const c_numBytes = type->getCalldataEncodedSize(); - if (c_numBytes > 32) - BOOST_THROW_EXCEPTION(CompilerError() - << errinfo_comment("Type " + type->toString() + " not yet supported.")); - bool const c_leftAligned = type->getCategory() == Type::Category::String; - bool const c_padToWords = true; - dataOffset += CompilerUtils(m_context).loadFromMemory(dataOffset, c_numBytes, c_leftAligned, - !_fromMemory, c_padToWords); - } + dataOffset += CompilerUtils(m_context).loadFromMemory(dataOffset, *type, !_fromMemory, c_padToWords); return dataOffset; } @@ -255,22 +247,12 @@ bool Compiler::visit(FunctionDefinition const& _function) // stack upon entry: [return address] [arg0] [arg1] ... [argn] // reserve additional slots: [retarg0] ... [retargm] [localvar0] ... [localvarp] - if (_function.getVisibility() != Declaration::Visibility::External) + unsigned parametersSize = CompilerUtils::getSizeOnStack(_function.getParameters()); + m_context.adjustStackOffset(parametersSize); + for (ASTPointer const& variable: _function.getParameters()) { - unsigned parametersSize = CompilerUtils::getSizeOnStack(_function.getParameters()); - m_context.adjustStackOffset(parametersSize); - for (ASTPointer const& variable: _function.getParameters()) - { - m_context.addVariable(*variable, parametersSize); - parametersSize -= variable->getType()->getSizeOnStack(); - } - } - else - { - unsigned calldataPos = CompilerUtils::dataStartOffset; - // calldatapos is _always_ dynamic. - for (ASTPointer const& variable: _function.getParameters()) - m_context.addCalldataVariable(*variable, calldataPos); + m_context.addVariable(*variable, parametersSize); + parametersSize -= variable->getType()->getSizeOnStack(); } for (ASTPointer const& variable: _function.getReturnParameters()) m_context.addAndInitializeVariable(*variable); diff --git a/CompilerUtils.cpp b/CompilerUtils.cpp index dda1736d6..6f99dc7c2 100644 --- a/CompilerUtils.cpp +++ b/CompilerUtils.cpp @@ -33,33 +33,34 @@ namespace solidity const unsigned int CompilerUtils::dataStartOffset = 4; -unsigned CompilerUtils::loadFromMemory(unsigned _offset, unsigned _bytes, bool _leftAligned, - bool _fromCalldata, bool _padToWordBoundaries) +unsigned CompilerUtils::loadFromMemory(unsigned _offset, Type const& _type, + bool _fromCalldata, bool _padToWordBoundaries) { - if (_bytes == 0) - { + solAssert(_type.getCategory() != Type::Category::ByteArray, "Unable to statically load dynamic type."); + unsigned _encodedSize = _type.getCalldataEncodedSize(); + unsigned numBytes = _padToWordBoundaries ? getPaddedSize(_encodedSize) : _encodedSize; + bool leftAligned = _type.getCategory() == Type::Category::String; + if (numBytes == 0) m_context << u256(0); - return 0; - } - eth::Instruction load = _fromCalldata ? eth::Instruction::CALLDATALOAD : eth::Instruction::MLOAD; - solAssert(_bytes <= 32, "Memory load of more than 32 bytes requested."); - if (_bytes == 32 || _padToWordBoundaries) - { - m_context << u256(_offset) << load; - return 32; - } else { - // load data and add leading or trailing zeros by dividing/multiplying depending on alignment - u256 shiftFactor = u256(1) << ((32 - _bytes) * 8); - m_context << shiftFactor; - if (_leftAligned) - m_context << eth::Instruction::DUP1; - m_context << u256(_offset) << load << eth::Instruction::DIV; - if (_leftAligned) - m_context << eth::Instruction::MUL; - return _bytes; + eth::Instruction load = _fromCalldata ? eth::Instruction::CALLDATALOAD : eth::Instruction::MLOAD; + solAssert(numBytes <= 32, "Static memory load of more than 32 bytes requested."); + if (numBytes == 32) + m_context << u256(_offset) << load; + else + { + // load data and add leading or trailing zeros by dividing/multiplying depending on alignment + u256 shiftFactor = u256(1) << ((32 - numBytes) * 8); + m_context << shiftFactor; + if (leftAligned) + m_context << eth::Instruction::DUP1; + m_context << u256(_offset) << load << eth::Instruction::DIV; + if (leftAligned) + m_context << eth::Instruction::MUL; + } } + return numBytes; } unsigned CompilerUtils::storeInMemory(unsigned _offset, Type const& _type, bool _padToWordBoundaries) diff --git a/CompilerUtils.h b/CompilerUtils.h index fe28ceadf..89973b6be 100644 --- a/CompilerUtils.h +++ b/CompilerUtils.h @@ -37,14 +37,13 @@ public: /// Loads data from memory to the stack. /// @param _offset offset in memory (or calldata) - /// @param _bytes number of bytes to load - /// @param _leftAligned if true, store left aligned on stack (otherwise right aligned) + /// @param _type data type to load /// @param _fromCalldata if true, load from calldata, not from memory /// @param _padToWordBoundaries if true, assume the data is padded to word (32 byte) boundaries /// @returns the number of bytes consumed in memory (can be different from _bytes if - /// _padToWordBoundaries is true) - unsigned loadFromMemory(unsigned _offset, unsigned _bytes = 32, bool _leftAligned = false, - bool _fromCalldata = false, bool _padToWordBoundaries = false); + /// _padToWordBoundaries is true) + unsigned loadFromMemory(unsigned _offset, Type const& _type = IntegerType(256), + bool _fromCalldata = false, bool _padToWordBoundaries = false); /// Stores data from stack in memory. /// @param _offset offset in memory /// @param _type type of the data on the stack diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index 0f0e94f21..7128459a4 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -885,11 +885,8 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio m_context << eth::Instruction::POP; m_context << eth::Instruction::POP; // pop contract address - if (retSize > 0) - { - bool const c_leftAligned = firstType->getCategory() == Type::Category::String; - CompilerUtils(m_context).loadFromMemory(0, retSize, c_leftAligned, false, true); - } + if (firstType) + CompilerUtils(m_context).loadFromMemory(0, *firstType, false, true); } void ExpressionCompiler::appendArgumentsCopyToMemory(vector> const& _arguments,