mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Inline each function separately.
This commit is contained in:
parent
a435a14e13
commit
2ab6430303
@ -50,7 +50,6 @@ FullInliner::FullInliner(Block& _ast):
|
|||||||
assertThrow(m_ast.statements.at(i).type() == typeid(FunctionDefinition), OptimizerException, "");
|
assertThrow(m_ast.statements.at(i).type() == typeid(FunctionDefinition), OptimizerException, "");
|
||||||
FunctionDefinition& fun = boost::get<FunctionDefinition>(m_ast.statements.at(i));
|
FunctionDefinition& fun = boost::get<FunctionDefinition>(m_ast.statements.at(i));
|
||||||
m_functions[fun.name] = &fun;
|
m_functions[fun.name] = &fun;
|
||||||
m_functionsToVisit.insert(&fun);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,17 +58,8 @@ void FullInliner::run()
|
|||||||
assertThrow(m_ast.statements[0].type() == typeid(Block), OptimizerException, "");
|
assertThrow(m_ast.statements[0].type() == typeid(Block), OptimizerException, "");
|
||||||
|
|
||||||
handleBlock("", boost::get<Block>(m_ast.statements[0]));
|
handleBlock("", boost::get<Block>(m_ast.statements[0]));
|
||||||
while (!m_functionsToVisit.empty())
|
for (auto const& fun: m_functions)
|
||||||
handleFunction(**m_functionsToVisit.begin());
|
handleBlock(fun.second->name, fun.second->body);
|
||||||
}
|
|
||||||
|
|
||||||
void FullInliner::handleFunction(FunctionDefinition& _fun)
|
|
||||||
{
|
|
||||||
if (!m_functionsToVisit.count(&_fun))
|
|
||||||
return;
|
|
||||||
m_functionsToVisit.erase(&_fun);
|
|
||||||
|
|
||||||
handleBlock(_fun.name, _fun.body);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FullInliner::handleBlock(string const& _currentFunctionName, Block& _block)
|
void FullInliner::handleBlock(string const& _currentFunctionName, Block& _block)
|
||||||
@ -102,28 +92,27 @@ boost::optional<vector<Statement>> InlineModifier::tryInlineStatement(Statement&
|
|||||||
), *e);
|
), *e);
|
||||||
if (funCall)
|
if (funCall)
|
||||||
{
|
{
|
||||||
FunctionDefinition& fun = m_driver.function(funCall->functionName.name);
|
|
||||||
m_driver.handleFunction(fun);
|
|
||||||
|
|
||||||
// TODO: Insert good heuristic here. Perhaps implement that inside the driver.
|
// TODO: Insert good heuristic here. Perhaps implement that inside the driver.
|
||||||
bool doInline = funCall->functionName.name != m_currentFunction;
|
bool doInline = funCall->functionName.name != m_currentFunction;
|
||||||
|
|
||||||
if (doInline)
|
if (doInline)
|
||||||
return performInline(_statement, *funCall, fun);
|
return performInline(_statement, *funCall);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionCall& _funCall, FunctionDefinition& _function)
|
vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionCall& _funCall)
|
||||||
{
|
{
|
||||||
vector<Statement> newStatements;
|
vector<Statement> newStatements;
|
||||||
map<string, string> variableReplacements;
|
map<string, string> variableReplacements;
|
||||||
|
|
||||||
|
FunctionDefinition& function = m_driver.function(_funCall.functionName.name);
|
||||||
|
|
||||||
// helper function to create a new variable that is supposed to model
|
// helper function to create a new variable that is supposed to model
|
||||||
// an existing variable.
|
// an existing variable.
|
||||||
auto newVariable = [&](TypedName const& _existingVariable, Expression* _value) {
|
auto newVariable = [&](TypedName const& _existingVariable, Expression* _value) {
|
||||||
string newName = m_nameDispenser.newName(_function.name + "_" + _existingVariable.name);
|
string newName = m_nameDispenser.newName(function.name + "_" + _existingVariable.name);
|
||||||
variableReplacements[_existingVariable.name] = newName;
|
variableReplacements[_existingVariable.name] = newName;
|
||||||
VariableDeclaration varDecl{_funCall.location, {{_funCall.location, newName, _existingVariable.type}}, {}};
|
VariableDeclaration varDecl{_funCall.location, {{_funCall.location, newName, _existingVariable.type}}, {}};
|
||||||
if (_value)
|
if (_value)
|
||||||
@ -132,11 +121,11 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
|
|||||||
};
|
};
|
||||||
|
|
||||||
for (size_t i = 0; i < _funCall.arguments.size(); ++i)
|
for (size_t i = 0; i < _funCall.arguments.size(); ++i)
|
||||||
newVariable(_function.parameters[i], &_funCall.arguments[i]);
|
newVariable(function.parameters[i], &_funCall.arguments[i]);
|
||||||
for (auto const& var: _function.returnVariables)
|
for (auto const& var: function.returnVariables)
|
||||||
newVariable(var, nullptr);
|
newVariable(var, nullptr);
|
||||||
|
|
||||||
Statement newBody = BodyCopier(m_nameDispenser, _function.name + "_", variableReplacements)(_function.body);
|
Statement newBody = BodyCopier(m_nameDispenser, function.name + "_", variableReplacements)(function.body);
|
||||||
newStatements += std::move(boost::get<Block>(newBody).statements);
|
newStatements += std::move(boost::get<Block>(newBody).statements);
|
||||||
|
|
||||||
boost::apply_visitor(GenericFallbackVisitor<Assignment, VariableDeclaration>{
|
boost::apply_visitor(GenericFallbackVisitor<Assignment, VariableDeclaration>{
|
||||||
@ -148,7 +137,7 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
|
|||||||
{_assignment.variableNames[i]},
|
{_assignment.variableNames[i]},
|
||||||
make_shared<Expression>(Identifier{
|
make_shared<Expression>(Identifier{
|
||||||
_assignment.location,
|
_assignment.location,
|
||||||
variableReplacements.at(_function.returnVariables[i].name)
|
variableReplacements.at(function.returnVariables[i].name)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -160,7 +149,7 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
|
|||||||
{std::move(_varDecl.variables[i])},
|
{std::move(_varDecl.variables[i])},
|
||||||
make_shared<Expression>(Identifier{
|
make_shared<Expression>(Identifier{
|
||||||
_varDecl.location,
|
_varDecl.location,
|
||||||
variableReplacements.at(_function.returnVariables[i].name)
|
variableReplacements.at(function.returnVariables[i].name)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -75,9 +75,6 @@ public:
|
|||||||
|
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
/// Perform inlining operations inside the given function.
|
|
||||||
void handleFunction(FunctionDefinition& _function);
|
|
||||||
|
|
||||||
FunctionDefinition& function(std::string _name) { return *m_functions.at(_name); }
|
FunctionDefinition& function(std::string _name) { return *m_functions.at(_name); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -87,7 +84,6 @@ private:
|
|||||||
/// we store pointers to functions.
|
/// we store pointers to functions.
|
||||||
Block& m_ast;
|
Block& m_ast;
|
||||||
std::map<std::string, FunctionDefinition*> m_functions;
|
std::map<std::string, FunctionDefinition*> m_functions;
|
||||||
std::set<FunctionDefinition*> m_functionsToVisit;
|
|
||||||
NameDispenser m_nameDispenser;
|
NameDispenser m_nameDispenser;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -108,7 +104,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
boost::optional<std::vector<Statement>> tryInlineStatement(Statement& _statement);
|
boost::optional<std::vector<Statement>> tryInlineStatement(Statement& _statement);
|
||||||
std::vector<Statement> performInline(Statement& _statement, FunctionCall& _funCall, FunctionDefinition& _function);
|
std::vector<Statement> performInline(Statement& _statement, FunctionCall& _funCall);
|
||||||
|
|
||||||
std::string newName(std::string const& _prefix);
|
std::string newName(std::string const& _prefix);
|
||||||
|
|
||||||
|
@ -14,10 +14,7 @@
|
|||||||
// let g_b := f_x
|
// let g_b := f_x
|
||||||
// let g_c := _1
|
// let g_c := _1
|
||||||
// let g_y
|
// let g_y
|
||||||
// let g_f_a_1 := g_b
|
// g_y := mul(mload(g_c), f(g_b))
|
||||||
// let g_f_x_1
|
|
||||||
// g_f_x_1 := add(g_f_a_1, g_f_a_1)
|
|
||||||
// g_y := mul(mload(g_c), g_f_x_1)
|
|
||||||
// let y_1 := g_y
|
// let y_1 := g_y
|
||||||
// }
|
// }
|
||||||
// function f(a) -> x
|
// function f(a) -> x
|
||||||
|
@ -27,23 +27,11 @@
|
|||||||
// {
|
// {
|
||||||
// {
|
// {
|
||||||
// {
|
// {
|
||||||
// let f_x_1 := 100
|
// let f_x := 100
|
||||||
// mstore(0, f_x_1)
|
// mstore(0, f_x)
|
||||||
// let f_h_t
|
// mstore(7, h())
|
||||||
// f_h_t := 2
|
// g(10)
|
||||||
// mstore(7, f_h_t)
|
// mstore(1, f_x)
|
||||||
// let f__5 := 10
|
|
||||||
// let f_g_x_1 := f__5
|
|
||||||
// let f_g_f_x := 1
|
|
||||||
// let
|
|
||||||
// mstore()
|
|
||||||
// let f_g_f_ := h()
|
|
||||||
// let
|
|
||||||
// mstore()
|
|
||||||
// let
|
|
||||||
// g(f__5)
|
|
||||||
// mstore(1, f_g_f_x)
|
|
||||||
// mstore(1, f_x_1)
|
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// function f(x)
|
// function f(x)
|
||||||
@ -52,30 +40,20 @@
|
|||||||
// let h_t
|
// let h_t
|
||||||
// h_t := 2
|
// h_t := 2
|
||||||
// mstore(7, h_t)
|
// mstore(7, h_t)
|
||||||
// let _5 := 10
|
// let g_x_1 := 10
|
||||||
// let g_x_1 := _5
|
// f(1)
|
||||||
// let g_f_x := 1
|
|
||||||
// let
|
|
||||||
// mstore()
|
|
||||||
// let g_f_ := h()
|
|
||||||
// let
|
|
||||||
// mstore()
|
|
||||||
// let
|
|
||||||
// g(_5)
|
|
||||||
// mstore(1, g_f_x)
|
|
||||||
// mstore(1, x)
|
// mstore(1, x)
|
||||||
// }
|
// }
|
||||||
// function g(x_1)
|
// function g(x_1)
|
||||||
// {
|
// {
|
||||||
// let f_x := 1
|
// let f_x_1 := 1
|
||||||
// let
|
// mstore(0, f_x_1)
|
||||||
// mstore()
|
// let f_h_t
|
||||||
// let f_ := h()
|
// f_h_t := 2
|
||||||
// let
|
// mstore(7, f_h_t)
|
||||||
// mstore()
|
// let f_g_x_1 := 10
|
||||||
// let
|
// f(1)
|
||||||
// g(_5)
|
// mstore(1, f_x_1)
|
||||||
// mstore(1, f_x)
|
|
||||||
// }
|
// }
|
||||||
// function h() -> t
|
// function h() -> t
|
||||||
// {
|
// {
|
||||||
|
Loading…
Reference in New Issue
Block a user