From a1d73a7befd2f3d72c18d4cb539edab5111c681f Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Fri, 14 Sep 2018 15:49:55 +0200 Subject: Split simplification rules into two functions. --- libevmasm/ExpressionClasses.cpp | 1 + libevmasm/RuleList.h | 47 +++++++++++++++++++++++++++++++++------ libevmasm/SimplificationRules.cpp | 21 ++++++++++++----- libevmasm/SimplificationRules.h | 6 +++++ 4 files changed, 62 insertions(+), 13 deletions(-) (limited to 'libevmasm') diff --git a/libevmasm/ExpressionClasses.cpp b/libevmasm/ExpressionClasses.cpp index 69b33ec5..42a1819a 100644 --- a/libevmasm/ExpressionClasses.cpp +++ b/libevmasm/ExpressionClasses.cpp @@ -184,6 +184,7 @@ string ExpressionClasses::fullDAGToString(ExpressionClasses::Id _id) const ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr) { static Rules rules; + assertThrow(rules.isInitialized(), OptimizerException, "Rule list not properly initialized."); if ( !_expr.item || diff --git a/libevmasm/RuleList.h b/libevmasm/RuleList.h index 0573856b..874a8929 100644 --- a/libevmasm/RuleList.h +++ b/libevmasm/RuleList.h @@ -44,12 +44,11 @@ template S modWorkaround(S const& _a, S const& _b) return (S)(bigint(_a) % bigint(_b)); } -/// @returns a list of simplification rules given certain match placeholders. -/// A, B and C should represent constants, X and Y arbitrary expressions. -/// The simplifications should never change the order of evaluation of -/// arbitrary operations. +// This part of simplificationRuleList below was split out to prevent +// stack overflows in the JavaScript optimizer for emscripten builds +// that affected certain browser versions. template -std::vector> simplificationRuleList( +std::vector> simplificationRuleListPart1( Pattern A, Pattern B, Pattern C, @@ -57,8 +56,7 @@ std::vector> simplificationRuleList( Pattern Y ) { - std::vector> rules; - rules += std::vector>{ + return std::vector> { // arithmetic on constants {{Instruction::ADD, {A, B}}, [=]{ return A.d() + B.d(); }, false}, {{Instruction::MUL, {A, B}}, [=]{ return A.d() * B.d(); }, false}, @@ -162,6 +160,22 @@ std::vector> simplificationRuleList( {{Instruction::OR, {X, {Instruction::NOT, {X}}}}, [=]{ return ~u256(0); }, true}, {{Instruction::OR, {{Instruction::NOT, {X}}, X}}, [=]{ return ~u256(0); }, true}, }; +} + + +// This part of simplificationRuleList below was split out to prevent +// stack overflows in the JavaScript optimizer for emscripten builds +// that affected certain browser versions. +template +std::vector> simplificationRuleListPart2( + Pattern A, + Pattern B, + Pattern, + Pattern X, + Pattern Y +) +{ + std::vector> rules; // Replace MOD X, with AND X, - 1 for (size_t i = 0; i < 256; ++i) @@ -292,5 +306,24 @@ std::vector> simplificationRuleList( return rules; } +/// @returns a list of simplification rules given certain match placeholders. +/// A, B and C should represent constants, X and Y arbitrary expressions. +/// The simplifications should never change the order of evaluation of +/// arbitrary operations. +template +std::vector> simplificationRuleList( + Pattern A, + Pattern B, + Pattern C, + Pattern X, + Pattern Y +) +{ + std::vector> rules; + rules += simplificationRuleListPart1(A, B, C, X, Y); + rules += simplificationRuleListPart2(A, B, C, X, Y); + return rules; +} + } } diff --git a/libevmasm/SimplificationRules.cpp b/libevmasm/SimplificationRules.cpp index 504dbc24..ba13a611 100644 --- a/libevmasm/SimplificationRules.cpp +++ b/libevmasm/SimplificationRules.cpp @@ -21,16 +21,19 @@ * Container for equivalence classes of expressions for use in common subexpression elimination. */ +#include + #include -#include -#include -#include -#include #include #include -#include - #include +#include + +#include +#include + +#include +#include using namespace std; using namespace dev; @@ -54,6 +57,11 @@ SimplificationRule const* Rules::findFirstMatch( return nullptr; } +bool Rules::isInitialized() const +{ + return !m_rules[byte(Instruction::ADD)].empty(); +} + void Rules::addRules(std::vector> const& _rules) { for (auto const& r: _rules) @@ -82,6 +90,7 @@ Rules::Rules() Y.setMatchGroup(5, m_matchGroups); addRules(simplificationRuleList(A, B, C, X, Y)); + assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized."); } Pattern::Pattern(Instruction _instruction, std::vector const& _arguments): diff --git a/libevmasm/SimplificationRules.h b/libevmasm/SimplificationRules.h index 53f7e595..fbe5a2b0 100644 --- a/libevmasm/SimplificationRules.h +++ b/libevmasm/SimplificationRules.h @@ -26,6 +26,8 @@ #include #include +#include + #include #include @@ -53,6 +55,10 @@ public: ExpressionClasses const& _classes ); + /// Checks whether the rulelist is non-empty. This is usually enforced + /// by the constructor, but we had some issues with static initialization. + bool isInitialized() const; + private: void addRules(std::vector> const& _rules); void addRule(SimplificationRule const& _rule); -- cgit