From 60a42f58a027f93ac0aa9d783d3d0f4867c2ada0 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 9 May 2019 12:00:23 +0200 Subject: [PATCH] Fix internal function calls. --- libsolidity/codegen/ir/IRGenerationContext.cpp | 2 -- libsolidity/codegen/ir/IRGenerator.cpp | 9 +++++++++ libsolidity/codegen/ir/IRGeneratorForStatements.cpp | 7 ++++--- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/libsolidity/codegen/ir/IRGenerationContext.cpp b/libsolidity/codegen/ir/IRGenerationContext.cpp index 3032fb94d..12bcba34b 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.cpp +++ b/libsolidity/codegen/ir/IRGenerationContext.cpp @@ -103,8 +103,6 @@ string IRGenerationContext::variable(Expression const& _expression) string IRGenerationContext::internalDispatch(size_t _in, size_t _out) { - // TODO can we limit the generated functions to only those visited - // in the expression context? What about creation / runtime context? string funName = "dispatch_internal_in_" + to_string(_in) + "_out_" + to_string(_out); return m_functions->createFunction(funName, [&]() { Whiskers templ(R"( diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index d4560ef25..721dd4f7d 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -94,12 +94,21 @@ string IRGenerator::generate(ContractDefinition const& _contract) t("memoryInit", memoryInit()); t("constructor", _contract.constructor() ? constructorCode(*_contract.constructor()) : ""); t("deploy", deployCode(_contract)); + // We generate code for all functions and rely on the optimizer to remove them again + // TODO it would probably be better to only generate functions when internalDispatch or + // virtualFunctionName is called - same below. + for (auto const* contract: _contract.annotation().linearizedBaseContracts) + for (auto const* fun: contract->definedFunctions()) + generateFunction(*fun); t("functions", m_context.functionCollector()->requestedFunctions()); resetContext(_contract); m_context.setInheritanceHierarchy(_contract.annotation().linearizedBaseContracts); t("RuntimeObject", runtimeObjectName(_contract)); t("dispatch", dispatchRoutine(_contract)); + for (auto const* contract: _contract.annotation().linearizedBaseContracts) + for (auto const* fun: contract->definedFunctions()) + generateFunction(*fun); t("runtimeFunctions", m_context.functionCollector()->requestedFunctions()); return t.render(); } diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 2587b8250..4f4e188fa 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -375,7 +375,6 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) solAssert(!functionType->bound(), ""); if (auto functionDef = dynamic_cast(identifier->annotation().referencedDeclaration)) { - // @TODO The function can very well return multiple vars. defineExpression(_functionCall) << m_context.virtualFunctionName(*functionDef) << "(" << @@ -385,7 +384,6 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) } } - // @TODO The function can very well return multiple vars. args = vector{m_context.variable(_functionCall.expression())} + args; defineExpression(_functionCall) << m_context.internalDispatch(functionType->parameterTypes().size(), functionType->returnParameterTypes().size()) << @@ -786,7 +784,10 @@ string IRGeneratorForStatements::expressionAsType(Expression const& _expression, ostream& IRGeneratorForStatements::defineExpression(Expression const& _expression) { - return m_code << "let " << m_context.variable(_expression) << " := "; + string vars = m_context.variable(_expression); + if (!vars.empty()) + m_code << "let " << move(vars) << " := "; + return m_code; } void IRGeneratorForStatements::appendAndOrOperatorCode(BinaryOperation const& _binOp)