From 870b656eda5f854ecece7c06d093a7292c72fd59 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Fri, 18 Jan 2019 12:34:36 +0100 Subject: Split up rule list generation further to prevent issues in browsers with the emscripten build. --- Changelog.md | 1 + libevmasm/RuleList.h | 102 +++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 91 insertions(+), 12 deletions(-) diff --git a/Changelog.md b/Changelog.md index bdfd9746..0562426d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,7 @@ Compiler Features: Bugfixes: + * Emscripten: Split simplification rule initialization up further to work around issues with soljson.js in some browsers. * TypeChecker: Return type error if fixed point encoding is attempted instead of throwing ``UnimplementedFeatureError``. * Yul: Check that arguments to ``dataoffset`` and ``datasize`` are literals at parse time and properly take this into account in the optimizer. * Yul: Parse number literals for detecting duplicate switch cases. diff --git a/libevmasm/RuleList.h b/libevmasm/RuleList.h index 874a8929..01e9b984 100644 --- a/libevmasm/RuleList.h +++ b/libevmasm/RuleList.h @@ -44,7 +44,7 @@ template S modWorkaround(S const& _a, S const& _b) return (S)(bigint(_a) % bigint(_b)); } -// This part of simplificationRuleList below was split out to prevent +// simplificationRuleList below was split up into parts to prevent // stack overflows in the JavaScript optimizer for emscripten builds // that affected certain browser versions. template @@ -52,8 +52,8 @@ std::vector> simplificationRuleListPart1( Pattern A, Pattern B, Pattern C, - Pattern X, - Pattern Y + Pattern, + Pattern ) { return std::vector> { @@ -96,8 +96,20 @@ std::vector> simplificationRuleListPart1( 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}, @@ -128,7 +140,19 @@ std::vector> simplificationRuleListPart1( {{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 }, + }; +} +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}, @@ -139,8 +163,20 @@ std::vector> simplificationRuleListPart1( {{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}, @@ -163,16 +199,13 @@ std::vector> simplificationRuleListPart1( } -// 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, +std::vector> simplificationRuleListPart5( + Pattern, + Pattern, Pattern, Pattern X, - Pattern Y + Pattern ) { std::vector> rules; @@ -207,7 +240,19 @@ std::vector> simplificationRuleListPart2( 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, @@ -234,6 +279,19 @@ std::vector> simplificationRuleListPart2( 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()}, @@ -274,6 +332,20 @@ std::vector> simplificationRuleListPart2( } } + return rules; +} + +template +std::vector> simplificationRuleListPart8( + Pattern A, + Pattern, + Pattern, + Pattern X, + Pattern Y +) +{ + std::vector> rules; + // move constants across subtractions rules += std::vector>{ { @@ -322,6 +394,12 @@ std::vector> simplificationRuleList( 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; } -- cgit v1.2.3