From 7d2292fbafa7f8c9ae2640612c976c9a45dac02d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 14 May 2020 15:57:46 +0200 Subject: [PATCH 1/4] Rename IRGenerationContext::internalDispatch() to generateInternalDispatchFunction() --- libsolidity/codegen/ir/IRGenerationContext.cpp | 2 +- libsolidity/codegen/ir/IRGenerationContext.h | 2 +- libsolidity/codegen/ir/IRGeneratorForStatements.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libsolidity/codegen/ir/IRGenerationContext.cpp b/libsolidity/codegen/ir/IRGenerationContext.cpp index d5a926a0d..6612fc1ac 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.cpp +++ b/libsolidity/codegen/ir/IRGenerationContext.cpp @@ -121,7 +121,7 @@ string IRGenerationContext::newYulVariable() return "_" + to_string(++m_varCounter); } -string IRGenerationContext::internalDispatch(YulArity const& _arity) +string IRGenerationContext::generateInternalDispatchFunction(YulArity const& _arity) { string funName = "dispatch_internal_in_" + to_string(_arity.in) + "_out_" + to_string(_arity.out); return m_functions.createFunction(funName, [&]() { diff --git a/libsolidity/codegen/ir/IRGenerationContext.h b/libsolidity/codegen/ir/IRGenerationContext.h index 2ae63ab2d..42cdddcb0 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.h +++ b/libsolidity/codegen/ir/IRGenerationContext.h @@ -102,7 +102,7 @@ public: std::string newYulVariable(); - std::string internalDispatch(YulArity const& _arity); + std::string generateInternalDispatchFunction(YulArity const& _arity); /// @returns a new copy of the utility function generator (but using the same function set). YulUtilFunctions utils(); diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 788498c06..b91ed9f2b 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -695,8 +695,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) { YulArity arity = YulArity::fromType(*functionType); define(_functionCall) << - // NOTE: internalDispatch() takes care of adding the function to function generation queue - m_context.internalDispatch(arity) << + // NOTE: generateInternalDispatchFunction() takes care of adding the function to function generation queue + m_context.generateInternalDispatchFunction(arity) << "(" << IRVariable(_functionCall.expression()).part("functionIdentifier").name() << joinHumanReadablePrefixed(args) << From 22c0568d348aedff78a741202c15965dfa3b617d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 14 May 2020 11:39:19 +0200 Subject: [PATCH 2/4] IRGenerationContext::internalDispatch(): Remove unused local YulUtilFunctions instance --- libsolidity/codegen/ir/IRGenerationContext.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libsolidity/codegen/ir/IRGenerationContext.cpp b/libsolidity/codegen/ir/IRGenerationContext.cpp index 6612fc1ac..a6a8c2b05 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.cpp +++ b/libsolidity/codegen/ir/IRGenerationContext.cpp @@ -139,7 +139,6 @@ string IRGenerationContext::generateInternalDispatchFunction(YulArity const& _ar )"); templ("functionName", funName); templ("comma", _arity.in > 0 ? "," : ""); - YulUtilFunctions utils(m_evmVersion, m_revertStrings, m_functions); templ("in", suffixedVariableNameList("in_", 0, _arity.in)); templ("arrow", _arity.out > 0 ? "->" : ""); templ("assignment_op", _arity.out > 0 ? ":=" : ""); From bd75543900073b5e75a936ec585572b324e3487d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 28 Apr 2020 13:20:39 +0200 Subject: [PATCH 3/4] Add IRNames::internalDispatch() and use it in IRGenerationContext --- libsolidity/codegen/ir/Common.cpp | 7 +++++++ libsolidity/codegen/ir/Common.h | 1 + libsolidity/codegen/ir/IRGenerationContext.cpp | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/libsolidity/codegen/ir/Common.cpp b/libsolidity/codegen/ir/Common.cpp index dba6aee07..1f1cc1cfe 100644 --- a/libsolidity/codegen/ir/Common.cpp +++ b/libsolidity/codegen/ir/Common.cpp @@ -53,6 +53,13 @@ string IRNames::runtimeObject(ContractDefinition const& _contract) return _contract.name() + "_" + toString(_contract.id()) + "_deployed"; } +string IRNames::internalDispatch(YulArity const& _arity) +{ + return "dispatch_internal" + "_in_" + to_string(_arity.in) + + "_out_" + to_string(_arity.out); +} + string IRNames::implicitConstructor(ContractDefinition const& _contract) { return "constructor_" + _contract.name() + "_" + to_string(_contract.id()); diff --git a/libsolidity/codegen/ir/Common.h b/libsolidity/codegen/ir/Common.h index 96e2a86ea..f1235553b 100644 --- a/libsolidity/codegen/ir/Common.h +++ b/libsolidity/codegen/ir/Common.h @@ -50,6 +50,7 @@ struct IRNames static std::string function(VariableDeclaration const& _varDecl); static std::string creationObject(ContractDefinition const& _contract); static std::string runtimeObject(ContractDefinition const& _contract); + static std::string internalDispatch(YulArity const& _arity); static std::string implicitConstructor(ContractDefinition const& _contract); static std::string constantValueFunction(VariableDeclaration const& _constant); static std::string localVariable(VariableDeclaration const& _declaration); diff --git a/libsolidity/codegen/ir/IRGenerationContext.cpp b/libsolidity/codegen/ir/IRGenerationContext.cpp index a6a8c2b05..313aff40d 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.cpp +++ b/libsolidity/codegen/ir/IRGenerationContext.cpp @@ -123,7 +123,7 @@ string IRGenerationContext::newYulVariable() string IRGenerationContext::generateInternalDispatchFunction(YulArity const& _arity) { - string funName = "dispatch_internal_in_" + to_string(_arity.in) + "_out_" + to_string(_arity.out); + string funName = IRNames::internalDispatch(_arity); return m_functions.createFunction(funName, [&]() { Whiskers templ(R"( function (fun ) { From 6c6a8a74e8700478b6348423da063ccf99538eba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 14 May 2020 20:34:59 +0200 Subject: [PATCH 4/4] IRGenerationContext: Extract code for enumerating dispatchable functions from generateInternalDispatch() into a separate function --- .../codegen/ir/IRGenerationContext.cpp | 57 ++++++++++++------- libsolidity/codegen/ir/IRGenerationContext.h | 2 + 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/libsolidity/codegen/ir/IRGenerationContext.cpp b/libsolidity/codegen/ir/IRGenerationContext.cpp index 313aff40d..3fa403272 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.cpp +++ b/libsolidity/codegen/ir/IRGenerationContext.cpp @@ -144,29 +144,27 @@ string IRGenerationContext::generateInternalDispatchFunction(YulArity const& _ar templ("assignment_op", _arity.out > 0 ? ":=" : ""); templ("out", suffixedVariableNameList("out_", 0, _arity.out)); - // UNIMPLEMENTED: Internal library calls via pointers are not implemented yet. - // We're not generating code for internal library functions here even though it's possible - // to call them via pointers. Right now such calls end up triggering the `default` case in - // the switch above. - vector> functions; - for (auto const& contract: mostDerivedContract().annotation().linearizedBaseContracts) - for (FunctionDefinition const* function: contract->definedFunctions()) - if ( - !function->isConstructor() && - YulArity::fromType(*TypeProvider::function(*function, FunctionType::Kind::Internal)) == _arity - ) - { - // 0 is reserved for uninitialized function pointers - solAssert(function->id() != 0, "Unexpected function ID: 0"); + vector> cases; + for (FunctionDefinition const* function: collectFunctionsOfArity(_arity)) + { + solAssert(function, ""); + solAssert( + YulArity::fromType(*TypeProvider::function(*function, FunctionType::Kind::Internal)) == _arity, + "A single dispatch function can only handle functions of one arity" + ); + solAssert(!function->isConstructor(), ""); + // 0 is reserved for uninitialized function pointers + solAssert(function->id() != 0, "Unexpected function ID: 0"); - functions.emplace_back(map { - { "funID", to_string(function->id()) }, - { "name", IRNames::function(*function)} - }); + cases.emplace_back(map{ + {"funID", to_string(function->id())}, + {"name", IRNames::function(*function)} + }); - enqueueFunctionForCodeGeneration(*function); - } - templ("cases", move(functions)); + enqueueFunctionForCodeGeneration(*function); + } + + templ("cases", move(cases)); return templ.render(); }); } @@ -186,3 +184,20 @@ std::string IRGenerationContext::revertReasonIfDebug(std::string const& _message return YulUtilFunctions::revertReasonIfDebug(m_revertStrings, _message); } +set IRGenerationContext::collectFunctionsOfArity(YulArity const& _arity) +{ + // UNIMPLEMENTED: Internal library calls via pointers are not implemented yet. + // We're not returning any internal library functions here even though it's possible + // to call them via pointers. Right now such calls end will up triggering the `default` case in + // the switch in the generated dispatch function. + set functions; + for (auto const& contract: mostDerivedContract().annotation().linearizedBaseContracts) + for (FunctionDefinition const* function: contract->definedFunctions()) + if ( + !function->isConstructor() && + YulArity::fromType(*TypeProvider::function(*function, FunctionType::Kind::Internal)) == _arity + ) + functions.insert(function); + + return functions; +} diff --git a/libsolidity/codegen/ir/IRGenerationContext.h b/libsolidity/codegen/ir/IRGenerationContext.h index 42cdddcb0..30aa5e220 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.h +++ b/libsolidity/codegen/ir/IRGenerationContext.h @@ -120,6 +120,8 @@ public: std::set& subObjectsCreated() { return m_subObjects; } private: + std::set collectFunctionsOfArity(YulArity const& _arity); + langutil::EVMVersion m_evmVersion; RevertStrings m_revertStrings; OptimiserSettings m_optimiserSettings;