From f38cf85482b9a5bd8aedc5b92ed55f129302e7f6 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 7 May 2020 17:29:42 +0200 Subject: [PATCH] Use vector of slots. --- libsolidity/codegen/ir/IRGenerator.cpp | 54 +++++++++---------- libsolidity/codegen/ir/IRGenerator.h | 5 +- .../codegen/ir/IRGeneratorForStatements.cpp | 44 +++++++-------- libsolidity/codegen/ir/IRVariable.h | 3 +- .../standard_ir_requested/output.json | 2 +- .../yul_string_format_ascii/output.json | 2 +- .../output.json | 2 +- .../output.json | 2 +- .../yul_string_format_ascii_long/output.json | 2 +- .../yul_string_format_hex/output.json | 2 +- .../constructor_arguments_internal.sol | 2 + 11 files changed, 57 insertions(+), 63 deletions(-) diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index bfd8ce2d1..3211fb4df 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -169,24 +169,24 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function) string functionName = m_context.functionName(_function); return m_context.functionCollector().createFunction(functionName, [&]() { Whiskers t(R"( - function () { + function () -> { } )"); t("functionName", functionName); - string params; + vector params; for (auto const& varDecl: _function.parameters()) - params += (params.empty() ? "" : ", ") + m_context.addLocalVariable(*varDecl).commaSeparatedList(); - t("params", params); - string retParams; + params += m_context.addLocalVariable(*varDecl).stackSlots(); + t("params", joinHumanReadable(params)); + vector retParams; string retInit; for (auto const& varDecl: _function.returnParameters()) { - retParams += (retParams.empty() ? "" : ", ") + m_context.addLocalVariable(*varDecl).commaSeparatedList(); + retParams += m_context.addLocalVariable(*varDecl).stackSlots(); retInit += generateInitialAssignment(*varDecl); } - t("returns", retParams.empty() ? "" : " -> " + retParams); + t("retParams", joinHumanReadable(retParams)); t("initReturnVariables", retInit); t("body", generate(_function.body())); return t.render(); @@ -300,17 +300,17 @@ string IRGenerator::generateInitialAssignment(VariableDeclaration const& _varDec return generator.code(); } -pair> IRGenerator::evaluateConstructorArguments( +pair>> IRGenerator::evaluateConstructorArguments( ContractDefinition const& _contract ) { - map constructorParams; + map> constructorParams; vector>const *>> baseConstructorArguments; for (ASTPointer const& base: _contract.baseContracts()) if (FunctionDefinition const* baseConstructor = dynamic_cast( base->name().annotation().referencedDeclaration - )->constructor(); baseConstructor && base->arguments()) + )->constructor(); baseConstructor && base->arguments()) baseConstructorArguments.emplace_back( dynamic_cast(baseConstructor->scope()), base->arguments() @@ -338,11 +338,11 @@ pair> IRGenerator::evaluateConstr { vector params; for (size_t i = 0; i < arguments->size(); ++i) - params.emplace_back(generator.evaluateExpression( - *(arguments->at(i)), - *(baseContract->constructor()->parameters()[i]->type()) - ).commaSeparatedList()); - constructorParams[baseContract] = joinHumanReadable(params); + params += generator.evaluateExpression( + *(arguments->at(i)), + *(baseContract->constructor()->parameters()[i]->type()) + ).stackSlots(); + constructorParams[baseContract] = std::move(params); } } @@ -363,16 +363,16 @@ string IRGenerator::initStateVariables(ContractDefinition const& _contract) void IRGenerator::generateImplicitConstructors(ContractDefinition const& _contract) { auto listAllParams = [&]( - map const& baseParams) -> string + map> const& baseParams) -> vector { vector params; for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts) if (baseParams.count(contract)) - params.emplace_back(baseParams.at(contract)); - return joinHumanReadable(params); + params += baseParams.at(contract); + return params; }; - map baseConstructorParams; + map> baseConstructorParams; for (size_t i = 0; i < _contract.annotation().linearizedBaseContracts.size(); ++i) { ContractDefinition const* contract = _contract.annotation().linearizedBaseContracts[i]; @@ -387,16 +387,16 @@ void IRGenerator::generateImplicitConstructors(ContractDefinition const& _contra } )"); - string params; + vector params; if (contract->constructor()) for (ASTPointer const& varDecl: contract->constructor()->parameters()) - params += (params.empty() ? "" : ", ") + m_context.addLocalVariable(*varDecl).commaSeparatedList(); - t("params", params); - string baseParamsString = listAllParams(baseConstructorParams); - t("baseParams", baseParamsString); - t("comma", !params.empty() && !baseParamsString.empty() ? ", " : ""); + params += m_context.addLocalVariable(*varDecl).stackSlots(); + t("params", joinHumanReadable(params)); + vector baseParams = listAllParams(baseConstructorParams); + t("baseParams", joinHumanReadable(baseParams)); + t("comma", !params.empty() && !baseParams.empty() ? ", " : ""); t("functionName", implicitConstructorName(*contract)); - pair> evaluatedArgs = evaluateConstructorArguments(*contract); + pair>> evaluatedArgs = evaluateConstructorArguments(*contract); baseConstructorParams.insert(evaluatedArgs.second.begin(), evaluatedArgs.second.end()); t("evalBaseArguments", evaluatedArgs.first); if (i < _contract.annotation().linearizedBaseContracts.size() - 1) @@ -404,7 +404,7 @@ void IRGenerator::generateImplicitConstructors(ContractDefinition const& _contra t("hasNextConstructor", true); ContractDefinition const* nextContract = _contract.annotation().linearizedBaseContracts[i + 1]; t("nextConstructor", implicitConstructorName(*nextContract)); - t("nextParams", listAllParams(baseConstructorParams)); + t("nextParams", joinHumanReadable(listAllParams(baseConstructorParams))); } else t("hasNextConstructor", false); diff --git a/libsolidity/codegen/ir/IRGenerator.h b/libsolidity/codegen/ir/IRGenerator.h index a4298a902..642cfcdfb 100644 --- a/libsolidity/codegen/ir/IRGenerator.h +++ b/libsolidity/codegen/ir/IRGenerator.h @@ -81,9 +81,8 @@ private: /// Evaluates constructor's arguments for all base contracts (listed in inheritance specifiers) of /// @a _contract /// @returns Pair of expressions needed to evaluate params and list of parameters in a map contract -> params - std::pair> evaluateConstructorArguments( - ContractDefinition const& _contract - ); + std::pair>> + evaluateConstructorArguments(ContractDefinition const& _contract); /// Initializes state variables of /// @a _contract diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 10761fd35..7415a0977 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -637,13 +637,6 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) break; case FunctionType::Kind::Internal: { - vector args; - for (size_t i = 0; i < arguments.size(); ++i) - if (functionType->takesArbitraryParameters()) - args.emplace_back(IRVariable(*arguments[i]).commaSeparatedList()); - else - args.emplace_back(convert(*arguments[i], *parameterTypes[i]).commaSeparatedList()); - optional functionDef; if (auto memberAccess = dynamic_cast(&_functionCall.expression())) { @@ -681,6 +674,13 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) solAssert(functionDef.has_value(), ""); solAssert(functionDef.value() == nullptr || functionDef.value()->isImplemented(), ""); + vector args; + for (size_t i = 0; i < arguments.size(); ++i) + if (functionType->takesArbitraryParameters()) + args += IRVariable(*arguments[i]).stackSlots(); + else + args += convert(*arguments[i], *parameterTypes[i]).stackSlots(); + if (functionDef.value() != nullptr) define(_functionCall) << m_context.enqueueFunctionForCodeGeneration(*functionDef.value()) << @@ -716,7 +716,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) ABIFunctions abi(m_context.evmVersion(), m_context.revertStrings(), m_context.functionCollector()); vector indexedArgs; - string nonIndexedArgs; + vector nonIndexedArgs; TypePointers nonIndexedArgTypes; TypePointers nonIndexedParamTypes; if (!event.isAnonymous()) @@ -739,9 +739,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) } else { - string vars = IRVariable(arg).commaSeparatedList(); - if (!vars.empty()) - nonIndexedArgs += ", " + move(vars); + nonIndexedArgs += IRVariable(arg).stackSlots(); nonIndexedArgTypes.push_back(arg.annotation().type); nonIndexedParamTypes.push_back(paramTypes[i]); } @@ -756,7 +754,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) templ("end", m_context.newYulVariable()); templ("freeMemory", freeMemory()); templ("encode", abi.tupleEncoder(nonIndexedArgTypes, nonIndexedParamTypes)); - templ("nonIndexedArgs", nonIndexedArgs); + templ("nonIndexedArgs", joinHumanReadablePrefixed(nonIndexedArgs)); templ("log", "log" + to_string(indexedArgs.size())); templ("indexedArgs", joinHumanReadablePrefixed(indexedArgs | boost::adaptors::transformed([&](auto const& _arg) { return _arg.commaSeparatedList(); @@ -813,8 +811,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) templ("allocateTemporary", m_utils.allocationTemporaryMemoryFunction()); templ( "argumentVars", - (type(*arguments.front()).sizeOnStack() > 0 ? ", " : "") + - IRVariable{*arguments.front()}.commaSeparatedList() + joinHumanReadablePrefixed(IRVariable{*arguments.front()}.stackSlots()) ); templ("encode", m_context.abiFunctions().tupleEncoder( {&type(*arguments.front())}, @@ -991,11 +988,11 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) ); TypePointers argumentTypes; - string constructorParams; + vector constructorParams; for (ASTPointer const& arg: arguments) { argumentTypes.push_back(arg->annotation().type); - constructorParams += ", " + IRVariable{*arg}.commaSeparatedList(); + constructorParams += IRVariable{*arg}.stackSlots(); } ContractDefinition const* contract = @@ -1023,7 +1020,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) t("abiEncode", m_context.abiFunctions().tupleEncoder(argumentTypes, functionType->parameterTypes(), false) ); - t("constructorParams", constructorParams); + t("constructorParams", joinHumanReadablePrefixed(constructorParams)); t("value", functionType->valueSet() ? IRVariable(_functionCall.expression()).part("value").name() : "0"); t("saltSet", functionType->saltSet()); if (functionType->saltSet()) @@ -1398,14 +1395,11 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess) solAssert(keyType.sizeOnStack() <= 1, ""); string slot = m_context.newYulVariable(); - Whiskers templ("let := ( )\n"); + Whiskers templ("let := (,)\n"); templ("slot", slot); templ("indexAccess", m_utils.mappingIndexAccessFunction(mappingType, keyType)); templ("base", IRVariable(_indexAccess.baseExpression()).commaSeparatedList()); - if (keyType.sizeOnStack() == 0) - templ("key", ""); - else - templ("key", ", " + IRVariable(*_indexAccess.indexExpression()).commaSeparatedList()); + templ("key", IRVariable(*_indexAccess.indexExpression()).commaSeparatedList()); m_code << templ.render(); setLValue(_indexAccess, IRLValue{ *_indexAccess.annotation().type, @@ -1678,10 +1672,8 @@ void IRGeneratorForStatements::appendExternalFunctionCall( for (auto const& arg: _arguments) { argumentTypes.emplace_back(&type(*arg)); - if (IRVariable(*arg).type().sizeOnStack() > 0) - argumentStrings.emplace_back(IRVariable(*arg).commaSeparatedList()); + argumentStrings += IRVariable(*arg).stackSlots(); } - string argumentString = argumentStrings.empty() ? ""s : (", " + joinHumanReadable(argumentStrings)); solUnimplementedAssert(funKind != FunctionType::Kind::ECRecover, ""); @@ -1796,7 +1788,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall( } else templ("encodeArgs", abi.tupleEncoder(argumentTypes, funType.parameterTypes(), encodeForLibraryCall)); - templ("argumentString", argumentString); + templ("argumentString", joinHumanReadablePrefixed(argumentStrings)); // Output data will replace input data, unless we have ECRecover (then, output // area will be 32 bytes just before input area). diff --git a/libsolidity/codegen/ir/IRVariable.h b/libsolidity/codegen/ir/IRVariable.h index ba4b1b93a..dbf37704c 100644 --- a/libsolidity/codegen/ir/IRVariable.h +++ b/libsolidity/codegen/ir/IRVariable.h @@ -69,10 +69,11 @@ public: /// The returned IRVariable is itself typed with the type of the stack slot as defined /// in ``m_type.stackItems()`` and may again occupy multiple stack slots. IRVariable part(std::string const& _slot) const; -private: + /// @returns a vector containing the names of the stack slots of the variable. std::vector stackSlots() const; +private: /// @returns a name consisting of the base name appended with an underscore and @æ _suffix, /// unless @a _suffix is empty, in which case the base name itself is returned. std::string suffixedName(std::string const& _suffix) const; diff --git a/test/cmdlineTests/standard_ir_requested/output.json b/test/cmdlineTests/standard_ir_requested/output.json index 69b95a683..f63075090 100644 --- a/test/cmdlineTests/standard_ir_requested/output.json +++ b/test/cmdlineTests/standard_ir_requested/output.json @@ -65,7 +65,7 @@ object \"C_6\" { mstore(64, newFreePtr) } - function fun_f_5() { + function fun_f_5() { } diff --git a/test/cmdlineTests/yul_string_format_ascii/output.json b/test/cmdlineTests/yul_string_format_ascii/output.json index 83511d5d6..0609704c5 100644 --- a/test/cmdlineTests/yul_string_format_ascii/output.json +++ b/test/cmdlineTests/yul_string_format_ascii/output.json @@ -107,7 +107,7 @@ object \"C_10\" { } } - function fun_f_9() -> vloc__4_mpos { + function fun_f_9() -> vloc__4_mpos { let zero_value_for_type_t_string_memory_ptr_1_mpos := zero_value_for_split_t_string_memory_ptr() vloc__4_mpos := zero_value_for_type_t_string_memory_ptr_1_mpos diff --git a/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json b/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json index 69c2091dc..1bc00b338 100644 --- a/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json @@ -79,7 +79,7 @@ object \"C_10\" { converted := 0x6162636162630000000000000000000000000000000000000000000000000000 } - function fun_f_9() -> vloc__4 { + function fun_f_9() -> vloc__4 { let zero_value_for_type_t_bytes32_1 := zero_value_for_split_t_bytes32() vloc__4 := zero_value_for_type_t_bytes32_1 diff --git a/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json b/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json index 8742ef645..fdef77781 100644 --- a/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json @@ -83,7 +83,7 @@ object \"C_10\" { converted := shift_left_224(cleanup_t_rational_1633837924_by_1(value)) } - function fun_f_9() -> vloc__4 { + function fun_f_9() -> vloc__4 { let zero_value_for_type_t_bytes4_1 := zero_value_for_split_t_bytes4() vloc__4 := zero_value_for_type_t_bytes4_1 diff --git a/test/cmdlineTests/yul_string_format_ascii_long/output.json b/test/cmdlineTests/yul_string_format_ascii_long/output.json index 4e6b565d0..2a845796d 100644 --- a/test/cmdlineTests/yul_string_format_ascii_long/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_long/output.json @@ -111,7 +111,7 @@ object \"C_10\" { } } - function fun_f_9() -> vloc__4_mpos { + function fun_f_9() -> vloc__4_mpos { let zero_value_for_type_t_string_memory_ptr_1_mpos := zero_value_for_split_t_string_memory_ptr() vloc__4_mpos := zero_value_for_type_t_string_memory_ptr_1_mpos diff --git a/test/cmdlineTests/yul_string_format_hex/output.json b/test/cmdlineTests/yul_string_format_hex/output.json index f98417556..784baf2f4 100644 --- a/test/cmdlineTests/yul_string_format_hex/output.json +++ b/test/cmdlineTests/yul_string_format_hex/output.json @@ -83,7 +83,7 @@ object \"C_10\" { converted := shift_left_224(cleanup_t_rational_2864434397_by_1(value)) } - function fun_f_9() -> vloc__4 { + function fun_f_9() -> vloc__4 { let zero_value_for_type_t_bytes4_1 := zero_value_for_split_t_bytes4() vloc__4 := zero_value_for_type_t_bytes4_1 diff --git a/test/libsolidity/semanticTests/constructor/constructor_arguments_internal.sol b/test/libsolidity/semanticTests/constructor/constructor_arguments_internal.sol index 756478e34..b29498083 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_arguments_internal.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_arguments_internal.sol @@ -33,6 +33,8 @@ contract Main { } } +// ==== +// compileViaYul: also // ---- // getFlag() -> true // getName() -> "abc"