aboutsummaryrefslogtreecommitdiffstats
path: root/libyul/optimiser/FullInliner.h
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2018-10-02 16:46:59 +0800
committerchriseth <chris@ethereum.org>2018-10-16 23:16:03 +0800
commite2e4a9fe81656724111c444cbf253d39bbb2b67b (patch)
treebf6b303303ac1c3ab106caeaee476e9c973a9df0 /libyul/optimiser/FullInliner.h
parent72b1bb00bd86ea3c647b3f327c416ab8f3421166 (diff)
downloaddexon-solidity-e2e4a9fe81656724111c444cbf253d39bbb2b67b.tar
dexon-solidity-e2e4a9fe81656724111c444cbf253d39bbb2b67b.tar.gz
dexon-solidity-e2e4a9fe81656724111c444cbf253d39bbb2b67b.tar.bz2
dexon-solidity-e2e4a9fe81656724111c444cbf253d39bbb2b67b.tar.lz
dexon-solidity-e2e4a9fe81656724111c444cbf253d39bbb2b67b.tar.xz
dexon-solidity-e2e4a9fe81656724111c444cbf253d39bbb2b67b.tar.zst
dexon-solidity-e2e4a9fe81656724111c444cbf253d39bbb2b67b.zip
New full inliner.
Diffstat (limited to 'libyul/optimiser/FullInliner.h')
-rw-r--r--libyul/optimiser/FullInliner.h71
1 files changed, 22 insertions, 49 deletions
diff --git a/libyul/optimiser/FullInliner.h b/libyul/optimiser/FullInliner.h
index 8112fb4b..b69350a6 100644
--- a/libyul/optimiser/FullInliner.h
+++ b/libyul/optimiser/FullInliner.h
@@ -42,29 +42,31 @@ class NameCollector;
/**
- * Optimiser component that modifies an AST in place, inlining arbitrary functions.
+ * Optimiser component that modifies an AST in place, inlining functions.
+ * Expressions are expected to be split, i.e. the component will only inline
+ * function calls that are at the root of the expression and that only contains
+ * variables as arguments. More specifically, it will inline
+ * - let x1, ..., xn := f(a1, ..., am)
+ * - x1, ..., xn := f(a1, ..., am)
+ * f(a1, ..., am)
*
- * Code of the form
+ * The transform changes code of the form
*
* function f(a, b) -> c { ... }
- * h(g(x(...), f(arg1(...), arg2(...)), y(...)), z(...))
+ * let z := f(x, y)
*
- * is transformed into
+ * into
*
* function f(a, b) -> c { ... }
*
- * let z1 := z(...) let y1 := y(...) let a2 := arg2(...) let a1 := arg1(...)
- * let c1 := 0
- * { code of f, with replacements: a -> a1, b -> a2, c -> c1, d -> d1 }
- * h(g(x(...), c1, y1), z1)
+ * let f_a := x
+ * let f_b := y
+ * let f_c
+ * code of f, with replacements: a -> f_a, b -> f_b, c -> f_c
+ * let z := f_c
*
- * No temporary variable is created for expressions that are "movable"
- * (i.e. they are "pure", have no side-effects and also do not depend on other code
- * that might have side-effects).
- *
- * This component can only be used on sources with unique names and with hoisted functions,
- * i.e. the root node has to be a block that itself contains a single block followed by all
- * function definitions.
+ * Prerequisites: Disambiguator, Function Hoister
+ * More efficient if run after: Expression Splitter
*/
class FullInliner: public ASTModifier
{
@@ -79,6 +81,8 @@ public:
FunctionDefinition& function(std::string _name) { return *m_functions.at(_name); }
private:
+ void handleBlock(std::string const& _currentFunctionName, Block& _block);
+
/// The AST to be modified. The root block itself will not be modified, because
/// we store pointers to functions.
Block& m_ast;
@@ -99,46 +103,15 @@ public:
m_driver(_driver),
m_nameDispenser(_nameDispenser)
{ }
- ~InlineModifier()
- {
- assertThrow(m_statementsToPrefix.empty(), OptimizerException, "");
- }
-
- virtual void operator()(FunctionalInstruction&) override;
- virtual void operator()(FunctionCall&) override;
- virtual void operator()(ForLoop&) override;
- virtual void operator()(Block& _block) override;
- using ASTModifier::visit;
- virtual void visit(Expression& _expression) override;
- virtual void visit(Statement& _st) override;
+ virtual void operator()(Block& _block) override;
private:
-
- /// Visits a list of expressions (usually an argument list to a function call) and tries
- /// to inline them. If one of them is inlined, all right of it have to be moved to the front
- /// (to keep the order of evaluation). If @a _moveToFront is true, all elements are moved
- /// to the front. @a _nameHints and @_types are used for the newly created variables, but
- /// both can be empty.
- void visitArguments(
- std::vector<Expression>& _arguments,
- std::vector<std::string> const& _nameHints = {},
- std::vector<std::string> const& _types = {},
- bool _moveToFront = false
- );
-
- /// Visits an expression, but saves and restores the current statements to prefix and returns
- /// the statements that should be prefixed for @a _expression.
- std::vector<Statement> visitRecursively(Expression& _expression);
+ boost::optional<std::vector<Statement>> tryInlineStatement(Statement& _statement);
+ std::vector<Statement> performInline(Statement& _statement, FunctionCall& _funCall, FunctionDefinition& _function);
std::string newName(std::string const& _prefix);
- /// @returns an expression returning nothing.
- Expression noop(SourceLocation const& _location);
-
- /// List of statements that should go in front of the currently visited AST element,
- /// at the statement level.
- std::vector<Statement> m_statementsToPrefix;
std::string m_currentFunction;
FullInliner& m_driver;
NameDispenser& m_nameDispenser;