From 91428c0122235b609d203b2003872f078ac92915 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 25 Apr 2019 10:46:00 +0200 Subject: [PATCH] Split up rule list. --- Changelog.md | 6 ++ libevmasm/RuleList.h | 136 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 129 insertions(+), 13 deletions(-) diff --git a/Changelog.md b/Changelog.md index bfe82f8c0..39c79ec22 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,9 @@ +### 0.4.26 (unreleased) + +Bugfixes: + * General: Split rule list such that JavaScript environments with small stacks can use the compiler. + + ### 0.4.25 (2018-09-12) Important Bugfixes: diff --git a/libevmasm/RuleList.h b/libevmasm/RuleList.h index 2b7da01ba..1cfb3a0be 100644 --- a/libevmasm/RuleList.h +++ b/libevmasm/RuleList.h @@ -44,22 +44,20 @@ 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 neven change the order of evaluation of -/// arbitrary operations. +// simplificationRuleList below was split up into parts 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, - Pattern X, - Pattern Y + Pattern, + Pattern ) { - std::vector> rules; - rules += std::vector>{ - // arithmetics on constants + 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}, {{Instruction::SUB, {A, B}}, [=]{ return A.d() - B.d(); }, false}, @@ -98,8 +96,20 @@ std::vector> simplificationRuleList( if (A.d() > 255) return u256(0); return B.d() >> unsigned(A.d()); - }, false}, + }, false} + }; +} +template +std::vector> simplificationRuleListPart2( + Pattern, + Pattern, + Pattern, + Pattern X, + Pattern +) +{ + return std::vector> { // invariants involving known constants {{Instruction::ADD, {X, 0}}, [=]{ return X; }, false}, {{Instruction::ADD, {0, X}}, [=]{ return X; }, false}, @@ -129,8 +139,20 @@ std::vector> simplificationRuleList( {{Instruction::MOD, {X, 0}}, [=]{ return u256(0); }, true}, {{Instruction::MOD, {0, X}}, [=]{ return u256(0); }, true}, {{Instruction::EQ, {X, 0}}, [=]() -> Pattern { return {Instruction::ISZERO, {X}}; }, false }, - {{Instruction::EQ, {0, X}}, [=]() -> Pattern { return {Instruction::ISZERO, {X}}; }, false }, + {{Instruction::EQ, {0, X}}, [=]() -> Pattern { return {Instruction::ISZERO, {X}}; }, false } + }; +} +template +std::vector> simplificationRuleListPart3( + Pattern, + Pattern, + Pattern, + Pattern X, + Pattern +) +{ + return std::vector> { // operations involving an expression and itself {{Instruction::AND, {X, X}}, [=]{ return X; }, true}, {{Instruction::OR, {X, X}}, [=]{ return X; }, true}, @@ -141,8 +163,20 @@ std::vector> simplificationRuleList( {{Instruction::SLT, {X, X}}, [=]{ return u256(0); }, true}, {{Instruction::GT, {X, X}}, [=]{ return u256(0); }, true}, {{Instruction::SGT, {X, X}}, [=]{ return u256(0); }, true}, - {{Instruction::MOD, {X, X}}, [=]{ return u256(0); }, true}, + {{Instruction::MOD, {X, X}}, [=]{ return u256(0); }, true} + }; +} +template +std::vector> simplificationRuleListPart4( + Pattern, + Pattern, + Pattern, + Pattern X, + Pattern Y +) +{ + return std::vector> { // logical instruction combinations {{Instruction::NOT, {{Instruction::NOT, {X}}}}, [=]{ return X; }, false}, {{Instruction::XOR, {X, {Instruction::XOR, {X, Y}}}}, [=]{ return Y; }, true}, @@ -162,6 +196,19 @@ std::vector> simplificationRuleList( {{Instruction::OR, {X, {Instruction::NOT, {X}}}}, [=]{ return ~u256(0); }, true}, {{Instruction::OR, {{Instruction::NOT, {X}}, X}}, [=]{ return ~u256(0); }, true}, }; +} + + +template +std::vector> simplificationRuleListPart5( + Pattern, + Pattern, + Pattern, + Pattern X, + Pattern +) +{ + std::vector> rules; // Replace MOD X, with AND X, - 1 for (size_t i = 0; i < 256; ++i) @@ -193,7 +240,19 @@ std::vector> simplificationRuleList( false }); } + return rules; +} +template +std::vector> simplificationRuleListPart6( + Pattern, + Pattern, + Pattern, + Pattern X, + Pattern Y +) +{ + std::vector> rules; // Double negation of opcodes with boolean result for (auto const& op: std::vector{ Instruction::EQ, @@ -220,6 +279,19 @@ std::vector> simplificationRuleList( false }); + return rules; +} + +template +std::vector> simplificationRuleListPart7( + Pattern A, + Pattern B, + Pattern, + Pattern X, + Pattern Y +) +{ + std::vector> rules; // Associative operations for (auto const& opFun: std::vector>>{ {Instruction::ADD, std::plus()}, @@ -259,6 +331,19 @@ std::vector> simplificationRuleList( }}; } } + return rules; +} + +template +std::vector> simplificationRuleListPart8( + Pattern A, + Pattern, + Pattern, + Pattern X, + Pattern Y +) +{ + std::vector> rules; // move constants across subtractions rules += std::vector>{ @@ -292,5 +377,30 @@ 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); + rules += simplificationRuleListPart3(A, B, C, X, Y); + rules += simplificationRuleListPart4(A, B, C, X, Y); + rules += simplificationRuleListPart5(A, B, C, X, Y); + rules += simplificationRuleListPart6(A, B, C, X, Y); + rules += simplificationRuleListPart7(A, B, C, X, Y); + rules += simplificationRuleListPart8(A, B, C, X, Y); + return rules; +} + } }