diff options
author | chriseth <c@ethdev.com> | 2015-02-09 07:14:13 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2015-02-09 07:14:13 +0800 |
commit | a66db516fb1025b406c8fcdb694b7fb760f84695 (patch) | |
tree | 269aaf7b54e7e75fc0c76854502926b366b22e44 /ExpressionCompiler.cpp | |
parent | 5c58aa041d06e7e640f12c0060d18947ac5e8952 (diff) | |
parent | afe1d9a592446dd403b9ed349529098b71309756 (diff) | |
download | dexon-solidity-a66db516fb1025b406c8fcdb694b7fb760f84695.tar.gz dexon-solidity-a66db516fb1025b406c8fcdb694b7fb760f84695.tar.zst dexon-solidity-a66db516fb1025b406c8fcdb694b7fb760f84695.zip |
Merge pull request #937 from LefterisJP/sol_MultiArgSHA3
Solidity multiple arg sha3
Diffstat (limited to 'ExpressionCompiler.cpp')
-rw-r--r-- | ExpressionCompiler.cpp | 54 |
1 files changed, 37 insertions, 17 deletions
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index f0c3af22..4a1110db 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -206,7 +206,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) TypePointers const& parameterTypes = function.getParameterTypes(); vector<ASTPointer<Expression const>> const& callArguments = _functionCall.getArguments(); vector<ASTPointer<ASTString>> const& callArgumentNames = _functionCall.getNames(); - solAssert(callArguments.size() == parameterTypes.size(), ""); + if (function.getLocation() != Location::SHA3) + solAssert(callArguments.size() == parameterTypes.size(), ""); vector<ASTPointer<Expression const>> arguments; if (callArgumentNames.empty()) @@ -274,7 +275,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) m_context << u256(0) << eth::Instruction::CODECOPY; unsigned length = bytecode.size(); - length += appendArgumentCopyToMemory(function.getParameterTypes(), arguments, length); + length += appendArgumentsCopyToMemory(arguments, function.getParameterTypes(), length); // size, offset, endowment m_context << u256(length) << u256(0); if (function.valueSet()) @@ -325,9 +326,11 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) m_context << eth::Instruction::SUICIDE; break; case Location::SHA3: - appendExpressionCopyToMemory(*function.getParameterTypes().front(), *arguments.front()); - m_context << u256(32) << u256(0) << eth::Instruction::SHA3; + { + unsigned length = appendArgumentsCopyToMemory(arguments); + m_context << u256(length) << u256(0) << eth::Instruction::SHA3; break; + } case Location::LOG0: case Location::LOG1: case Location::LOG2: @@ -797,7 +800,7 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio // reserve space for the function identifier unsigned dataOffset = bare ? 0 : CompilerUtils::dataStartOffset; - dataOffset += appendArgumentCopyToMemory(_functionType.getParameterTypes(), _arguments, dataOffset); + dataOffset += appendArgumentsCopyToMemory(_arguments, _functionType.getParameterTypes(), dataOffset); //@todo only return the first return value for now Type const* firstType = _functionType.getReturnParameterTypes().empty() ? nullptr : @@ -833,28 +836,45 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio } } -unsigned ExpressionCompiler::appendArgumentCopyToMemory(TypePointers const& _types, - vector<ASTPointer<Expression const>> const& _arguments, - unsigned _memoryOffset) +unsigned ExpressionCompiler::appendArgumentsCopyToMemory(vector<ASTPointer<Expression const>> const& _arguments, + TypePointers const& _types, + unsigned _memoryOffset) { unsigned length = 0; + if (!_types.empty()) + { + for (unsigned i = 0; i < _arguments.size(); ++i) + length += appendExpressionCopyToMemory(*_types[i], *_arguments[i], _memoryOffset + length); + return length; + } + + // without type conversion for (unsigned i = 0; i < _arguments.size(); ++i) - length += appendExpressionCopyToMemory(*_types[i], *_arguments[i], _memoryOffset + length); + { + const bool wantPadding = false; + _arguments[i]->accept(*this); + length += moveTypeToMemory(*_arguments[i]->getType()->getRealType(), _arguments[i]->getLocation(), _memoryOffset + length, wantPadding); + } return length; } -unsigned ExpressionCompiler::appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type, - Location const& _location, unsigned _memoryOffset) +unsigned ExpressionCompiler::moveTypeToMemory(Type const& _type, Location const& _location, unsigned _memoryOffset, bool _padToWordBoundaries) { - appendTypeConversion(_type, _expectedType, true); - unsigned const c_numBytes = CompilerUtils::getPaddedSize(_expectedType.getCalldataEncodedSize()); + unsigned const c_encodedSize = _type.getCalldataEncodedSize(); + unsigned const c_numBytes = _padToWordBoundaries ? CompilerUtils::getPaddedSize(c_encodedSize) : c_encodedSize; if (c_numBytes == 0 || c_numBytes > 32) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_location) - << errinfo_comment("Type " + _expectedType.toString() + " not yet supported.")); - bool const c_leftAligned = _expectedType.getCategory() == Type::Category::STRING; - bool const c_padToWords = true; - return CompilerUtils(m_context).storeInMemory(_memoryOffset, c_numBytes, c_leftAligned, c_padToWords); + << errinfo_comment("Type " + _type.toString() + " not yet supported.")); + bool const c_leftAligned = _type.getCategory() == Type::Category::STRING; + return CompilerUtils(m_context).storeInMemory(_memoryOffset, c_numBytes, c_leftAligned, _padToWordBoundaries); +} + +unsigned ExpressionCompiler::appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type, + Location const& _location, unsigned _memoryOffset) +{ + appendTypeConversion(_type, _expectedType, true); + return moveTypeToMemory(_expectedType, _location, _memoryOffset); } unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, |