diff options
Diffstat (limited to 'libsolidity/codegen')
-rw-r--r-- | libsolidity/codegen/ABIFunctions.cpp | 37 | ||||
-rw-r--r-- | libsolidity/codegen/ABIFunctions.h | 6 | ||||
-rw-r--r-- | libsolidity/codegen/ArrayUtils.cpp | 3 | ||||
-rw-r--r-- | libsolidity/codegen/CompilerContext.cpp | 21 | ||||
-rw-r--r-- | libsolidity/codegen/ExpressionCompiler.cpp | 14 |
5 files changed, 49 insertions, 32 deletions
diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index 756148e7..080be359 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -87,7 +87,7 @@ string ABIFunctions::tupleEncoder( ); elementTempl("values", valueNames); elementTempl("pos", to_string(headPos)); - elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], _encodeAsLibraryTypes, false)); + elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], _encodeAsLibraryTypes, true)); encodeElements += elementTempl.render(); headPos += dynamic ? 0x20 : _targetTypes[i]->calldataEncodedSize(); } @@ -371,7 +371,7 @@ string ABIFunctions::abiEncodingFunction( Type const& _from, Type const& _to, bool _encodeAsLibraryTypes, - bool _compacted + bool _fromStack ) { solUnimplementedAssert( @@ -415,7 +415,7 @@ string ABIFunctions::abiEncodingFunction( dynamic_cast<FunctionType const&>(_from), to, _encodeAsLibraryTypes, - _compacted + _fromStack ); solAssert(_from.sizeOnStack() == 1, ""); @@ -542,7 +542,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray( mstore(pos, sub(tail, headStart)) tail := <encodeToMemoryFun>(<arrayElementAccess>, tail) srcPtr := <nextArrayElement>(srcPtr) - pos := add(pos, <elementEncodedSize>) + pos := add(pos, 0x20) } pos := tail <assignEnd> @@ -580,7 +580,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray( *_from.baseType(), *_to.baseType(), _encodeAsLibraryTypes, - true + false )); templ("arrayElementAccess", inMemory ? "mload(srcPtr)" : _from.baseType()->isValueType() ? "sload(srcPtr)" : "srcPtr" ); templ("nextArrayElement", nextArrayElementFunction(_from)); @@ -729,7 +729,7 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray( *_from.baseType(), *_to.baseType(), _encodeAsLibraryTypes, - true + false ); templ("encodeToMemoryFun", encodeToMemoryFun); std::vector<std::map<std::string, std::string>> items(itemsPerSlot); @@ -925,7 +925,7 @@ string ABIFunctions::abiEncodingFunctionFunctionType( FunctionType const& _from, Type const& _to, bool _encodeAsLibraryTypes, - bool _compacted + bool _fromStack ) { solAssert(_from.kind() == FunctionType::Kind::External, ""); @@ -936,35 +936,31 @@ string ABIFunctions::abiEncodingFunctionFunctionType( _from.identifier() + "_to_" + _to.identifier() + - (_compacted ? "_compacted" : "") + + (_fromStack ? "_fromStack" : "") + (_encodeAsLibraryTypes ? "_library" : ""); - if (_compacted) - { + if (_fromStack) return createFunction(functionName, [&]() { return Whiskers(R"( - function <functionName>(addr_and_function_id, pos) { - mstore(pos, <cleanExtFun>(addr_and_function_id)) + function <functionName>(addr, function_id, pos) { + mstore(pos, <combineExtFun>(addr, function_id)) } )") ("functionName", functionName) - ("cleanExtFun", cleanupCombinedExternalFunctionIdFunction()) + ("combineExtFun", combineExternalFunctionIdFunction()) .render(); }); - } else - { return createFunction(functionName, [&]() { return Whiskers(R"( - function <functionName>(addr, function_id, pos) { - mstore(pos, <combineExtFun>(addr, function_id)) + function <functionName>(addr_and_function_id, pos) { + mstore(pos, <cleanExtFun>(addr_and_function_id)) } )") ("functionName", functionName) - ("combineExtFun", combineExternalFunctionIdFunction()) + ("cleanExtFun", cleanupCombinedExternalFunctionIdFunction()) .render(); }); - } } string ABIFunctions::copyToMemoryFunction(bool _fromCalldata) @@ -1212,10 +1208,7 @@ size_t ABIFunctions::headSize(TypePointers const& _targetTypes) if (t->isDynamicallyEncoded()) headSize += 0x20; else - { - solAssert(t->calldataEncodedSize() > 0, ""); headSize += t->calldataEncodedSize(); - } } return headSize; diff --git a/libsolidity/codegen/ABIFunctions.h b/libsolidity/codegen/ABIFunctions.h index de2a140a..e61f68bc 100644 --- a/libsolidity/codegen/ABIFunctions.h +++ b/libsolidity/codegen/ABIFunctions.h @@ -89,13 +89,13 @@ private: /// @returns the name of the ABI encoding function with the given type /// and queues the generation of the function to the requested functions. - /// @param _compacted if true, the input value was just loaded from storage + /// @param _fromStack if false, the input value was just loaded from storage /// or memory and thus might be compacted into a single slot (depending on the type). std::string abiEncodingFunction( Type const& _givenType, Type const& _targetType, bool _encodeAsLibraryTypes, - bool _compacted + bool _fromStack ); /// Part of @a abiEncodingFunction for array target type and given calldata array. std::string abiEncodingFunctionCalldataArray( @@ -143,7 +143,7 @@ private: FunctionType const& _from, Type const& _to, bool _encodeAsLibraryTypes, - bool _compacted + bool _fromStack ); /// @returns a function that copies raw bytes of dynamic length from calldata diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index e17188c2..ce8cbb5f 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -291,8 +291,11 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord CompilerUtils utils(m_context); unsigned baseSize = 1; if (!_sourceType.isByteArray()) + { // We always pad the elements, regardless of _padToWordBoundaries. baseSize = _sourceType.baseType()->calldataEncodedSize(); + solAssert(baseSize >= 0x20, ""); + } if (_sourceType.location() == DataLocation::CallData) { diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index d87c7be5..ce9c3b7f 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -38,6 +38,13 @@ #include <utility> #include <numeric> +// Change to "define" to output all intermediate code +#undef SOL_OUTPUT_ASM +#ifdef SOL_OUTPUT_ASM +#include <libsolidity/inlineasm/AsmPrinter.h> +#endif + + using namespace std; namespace dev @@ -313,10 +320,17 @@ void CompilerContext::appendInlineAssembly( ErrorReporter errorReporter(errors); auto scanner = make_shared<Scanner>(CharStream(_assembly), "--CODEGEN--"); auto parserResult = assembly::Parser(errorReporter).parse(scanner); - if (!parserResult || !errorReporter.errors().empty()) +#ifdef SOL_OUTPUT_ASM + cout << assembly::AsmPrinter()(*parserResult) << endl; +#endif + assembly::AsmAnalysisInfo analysisInfo; + bool analyzerResult = false; + if (parserResult) + analyzerResult = assembly::AsmAnalyzer(analysisInfo, errorReporter, false, identifierAccess.resolve).analyze(*parserResult); + if (!parserResult || !errorReporter.errors().empty() || !analyzerResult) { string message = - "Error parsing inline assembly block:\n" + "Error parsing/analyzing inline assembly block:\n" "------------------ Input: -----------------\n" + _assembly + "\n" "------------------ Errors: ----------------\n"; @@ -331,9 +345,6 @@ void CompilerContext::appendInlineAssembly( solAssert(false, message); } - assembly::AsmAnalysisInfo analysisInfo; - assembly::AsmAnalyzer analyzer(analysisInfo, errorReporter, false, identifierAccess.resolve); - solAssert(analyzer.analyze(*parserResult), "Failed to analyze inline assembly block."); solAssert(errorReporter.errors().empty(), "Failed to analyze inline assembly block."); assembly::CodeGenerator::assemble(*parserResult, analysisInfo, *m_asm, identifierAccess, _system); } diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index c2bf0f5c..bb8c4a94 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -858,8 +858,15 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) m_context << Instruction::DUP1 << Instruction::DUP3 << Instruction::MSTORE; // Stack: memptr requested_length // update free memory pointer - m_context << Instruction::DUP1 << arrayType.baseType()->memoryHeadSize(); - m_context << Instruction::MUL << u256(32) << Instruction::ADD; + m_context << Instruction::DUP1; + // Stack: memptr requested_length requested_length + if (arrayType.isByteArray()) + // Round up to multiple of 32 + m_context << u256(31) << Instruction::ADD << u256(31) << Instruction::NOT << Instruction::AND; + else + m_context << arrayType.baseType()->memoryHeadSize() << Instruction::MUL; + // stacK: memptr requested_length data_size + m_context << u256(32) << Instruction::ADD; m_context << Instruction::DUP3 << Instruction::ADD; utils().storeFreeMemoryPointer(); // Stack: memptr requested_length @@ -1714,6 +1721,9 @@ void ExpressionCompiler::appendExternalFunctionCall( if (_functionType.gasSet()) m_context << dupInstruction(m_context.baseToCurrentStackOffset(gasStackPos)); + else if (m_context.experimentalFeatureActive(ExperimentalFeature::V050)) + // Send all gas (requires tangerine whistle EVM) + m_context << Instruction::GAS; else { // send all gas except the amount needed to execute "SUB" and "CALL" |