mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #4983 from ethereum/optimizerEmscriptenBug
Fix weird Optimizer Emscripten Bug
This commit is contained in:
commit
4b656420ac
@ -102,6 +102,7 @@ Bugfixes:
|
|||||||
* Commandline Interface: Correctly handle paths with backslashes on windows.
|
* Commandline Interface: Correctly handle paths with backslashes on windows.
|
||||||
* Fix NatSpec json output for `@notice` and `@dev` tags on contract definitions.
|
* Fix NatSpec json output for `@notice` and `@dev` tags on contract definitions.
|
||||||
* Optimizer: Correctly estimate gas costs of constants for special cases.
|
* Optimizer: Correctly estimate gas costs of constants for special cases.
|
||||||
|
* Optimizer: Fix simplification rule initialization bug that appeared on some emscripten platforms.
|
||||||
* References Resolver: Do not crash on using ``_slot`` and ``_offset`` suffixes on their own.
|
* References Resolver: Do not crash on using ``_slot`` and ``_offset`` suffixes on their own.
|
||||||
* References Resolver: Enforce ``storage`` as data location for mappings.
|
* References Resolver: Enforce ``storage`` as data location for mappings.
|
||||||
* References Resolver: Properly handle invalid references used together with ``_slot`` and ``_offset``.
|
* References Resolver: Properly handle invalid references used together with ``_slot`` and ``_offset``.
|
||||||
|
@ -184,6 +184,7 @@ string ExpressionClasses::fullDAGToString(ExpressionClasses::Id _id) const
|
|||||||
ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr)
|
ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr)
|
||||||
{
|
{
|
||||||
static Rules rules;
|
static Rules rules;
|
||||||
|
assertThrow(rules.isInitialized(), OptimizerException, "Rule list not properly initialized.");
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!_expr.item ||
|
!_expr.item ||
|
||||||
|
@ -44,12 +44,11 @@ template <class S> S modWorkaround(S const& _a, S const& _b)
|
|||||||
return (S)(bigint(_a) % bigint(_b));
|
return (S)(bigint(_a) % bigint(_b));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns a list of simplification rules given certain match placeholders.
|
// This part of simplificationRuleList below was split out to prevent
|
||||||
/// A, B and C should represent constants, X and Y arbitrary expressions.
|
// stack overflows in the JavaScript optimizer for emscripten builds
|
||||||
/// The simplifications should never change the order of evaluation of
|
// that affected certain browser versions.
|
||||||
/// arbitrary operations.
|
|
||||||
template <class Pattern>
|
template <class Pattern>
|
||||||
std::vector<SimplificationRule<Pattern>> simplificationRuleList(
|
std::vector<SimplificationRule<Pattern>> simplificationRuleListPart1(
|
||||||
Pattern A,
|
Pattern A,
|
||||||
Pattern B,
|
Pattern B,
|
||||||
Pattern C,
|
Pattern C,
|
||||||
@ -57,8 +56,7 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleList(
|
|||||||
Pattern Y
|
Pattern Y
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
std::vector<SimplificationRule<Pattern>> rules;
|
return std::vector<SimplificationRule<Pattern>> {
|
||||||
rules += std::vector<SimplificationRule<Pattern>>{
|
|
||||||
// arithmetic on constants
|
// arithmetic on constants
|
||||||
{{Instruction::ADD, {A, B}}, [=]{ return A.d() + B.d(); }, false},
|
{{Instruction::ADD, {A, B}}, [=]{ return A.d() + B.d(); }, false},
|
||||||
{{Instruction::MUL, {A, B}}, [=]{ return A.d() * B.d(); }, false},
|
{{Instruction::MUL, {A, B}}, [=]{ return A.d() * B.d(); }, false},
|
||||||
@ -162,6 +160,22 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleList(
|
|||||||
{{Instruction::OR, {X, {Instruction::NOT, {X}}}}, [=]{ return ~u256(0); }, true},
|
{{Instruction::OR, {X, {Instruction::NOT, {X}}}}, [=]{ return ~u256(0); }, true},
|
||||||
{{Instruction::OR, {{Instruction::NOT, {X}}, 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 <class Pattern>
|
||||||
|
std::vector<SimplificationRule<Pattern>> simplificationRuleListPart2(
|
||||||
|
Pattern A,
|
||||||
|
Pattern B,
|
||||||
|
Pattern,
|
||||||
|
Pattern X,
|
||||||
|
Pattern Y
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<SimplificationRule<Pattern>> rules;
|
||||||
|
|
||||||
// Replace MOD X, <power-of-two> with AND X, <power-of-two> - 1
|
// Replace MOD X, <power-of-two> with AND X, <power-of-two> - 1
|
||||||
for (size_t i = 0; i < 256; ++i)
|
for (size_t i = 0; i < 256; ++i)
|
||||||
@ -292,5 +306,24 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleList(
|
|||||||
return rules;
|
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 <class Pattern>
|
||||||
|
std::vector<SimplificationRule<Pattern>> simplificationRuleList(
|
||||||
|
Pattern A,
|
||||||
|
Pattern B,
|
||||||
|
Pattern C,
|
||||||
|
Pattern X,
|
||||||
|
Pattern Y
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<SimplificationRule<Pattern>> rules;
|
||||||
|
rules += simplificationRuleListPart1(A, B, C, X, Y);
|
||||||
|
rules += simplificationRuleListPart2(A, B, C, X, Y);
|
||||||
|
return rules;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,16 +21,19 @@
|
|||||||
* Container for equivalence classes of expressions for use in common subexpression elimination.
|
* Container for equivalence classes of expressions for use in common subexpression elimination.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libevmasm/ExpressionClasses.h>
|
|
||||||
#include <utility>
|
|
||||||
#include <functional>
|
|
||||||
#include <boost/range/adaptor/reversed.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
#include <libevmasm/Assembly.h>
|
|
||||||
#include <libevmasm/CommonSubexpressionEliminator.h>
|
|
||||||
#include <libevmasm/SimplificationRules.h>
|
#include <libevmasm/SimplificationRules.h>
|
||||||
|
|
||||||
|
#include <libevmasm/ExpressionClasses.h>
|
||||||
|
#include <libevmasm/Assembly.h>
|
||||||
|
#include <libevmasm/CommonSubexpressionEliminator.h>
|
||||||
#include <libevmasm/RuleList.h>
|
#include <libevmasm/RuleList.h>
|
||||||
|
#include <libdevcore/Assertions.h>
|
||||||
|
|
||||||
|
#include <boost/range/adaptor/reversed.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace dev;
|
using namespace dev;
|
||||||
@ -54,6 +57,11 @@ SimplificationRule<Pattern> const* Rules::findFirstMatch(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Rules::isInitialized() const
|
||||||
|
{
|
||||||
|
return !m_rules[byte(Instruction::ADD)].empty();
|
||||||
|
}
|
||||||
|
|
||||||
void Rules::addRules(std::vector<SimplificationRule<Pattern>> const& _rules)
|
void Rules::addRules(std::vector<SimplificationRule<Pattern>> const& _rules)
|
||||||
{
|
{
|
||||||
for (auto const& r: _rules)
|
for (auto const& r: _rules)
|
||||||
@ -82,6 +90,7 @@ Rules::Rules()
|
|||||||
Y.setMatchGroup(5, m_matchGroups);
|
Y.setMatchGroup(5, m_matchGroups);
|
||||||
|
|
||||||
addRules(simplificationRuleList(A, B, C, X, Y));
|
addRules(simplificationRuleList(A, B, C, X, Y));
|
||||||
|
assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Pattern::Pattern(Instruction _instruction, std::vector<Pattern> const& _arguments):
|
Pattern::Pattern(Instruction _instruction, std::vector<Pattern> const& _arguments):
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
#include <libevmasm/ExpressionClasses.h>
|
#include <libevmasm/ExpressionClasses.h>
|
||||||
#include <libevmasm/SimplificationRule.h>
|
#include <libevmasm/SimplificationRule.h>
|
||||||
|
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -53,6 +55,10 @@ public:
|
|||||||
ExpressionClasses const& _classes
|
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:
|
private:
|
||||||
void addRules(std::vector<SimplificationRule<Pattern>> const& _rules);
|
void addRules(std::vector<SimplificationRule<Pattern>> const& _rules);
|
||||||
void addRule(SimplificationRule<Pattern> const& _rule);
|
void addRule(SimplificationRule<Pattern> const& _rule);
|
||||||
|
@ -40,6 +40,7 @@ SimplificationRule<Pattern> const* SimplificationRules::findFirstMatch(Expressio
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
static SimplificationRules rules;
|
static SimplificationRules rules;
|
||||||
|
assertThrow(rules.isInitialized(), OptimizerException, "Rule list not properly initialized.");
|
||||||
|
|
||||||
FunctionalInstruction const& instruction = boost::get<FunctionalInstruction>(_expr);
|
FunctionalInstruction const& instruction = boost::get<FunctionalInstruction>(_expr);
|
||||||
for (auto const& rule: rules.m_rules[byte(instruction.instruction)])
|
for (auto const& rule: rules.m_rules[byte(instruction.instruction)])
|
||||||
@ -51,6 +52,11 @@ SimplificationRule<Pattern> const* SimplificationRules::findFirstMatch(Expressio
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SimplificationRules::isInitialized() const
|
||||||
|
{
|
||||||
|
return !m_rules[byte(solidity::Instruction::ADD)].empty();
|
||||||
|
}
|
||||||
|
|
||||||
void SimplificationRules::addRules(vector<SimplificationRule<Pattern>> const& _rules)
|
void SimplificationRules::addRules(vector<SimplificationRule<Pattern>> const& _rules)
|
||||||
{
|
{
|
||||||
for (auto const& r: _rules)
|
for (auto const& r: _rules)
|
||||||
@ -79,6 +85,7 @@ SimplificationRules::SimplificationRules()
|
|||||||
Y.setMatchGroup(5, m_matchGroups);
|
Y.setMatchGroup(5, m_matchGroups);
|
||||||
|
|
||||||
addRules(simplificationRuleList(A, B, C, X, Y));
|
addRules(simplificationRuleList(A, B, C, X, Y));
|
||||||
|
assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Pattern::Pattern(solidity::Instruction _instruction, vector<Pattern> const& _arguments):
|
Pattern::Pattern(solidity::Instruction _instruction, vector<Pattern> const& _arguments):
|
||||||
|
@ -51,6 +51,9 @@ public:
|
|||||||
/// groups accordingly.
|
/// groups accordingly.
|
||||||
static SimplificationRule<Pattern> const* findFirstMatch(Expression const& _expr);
|
static SimplificationRule<Pattern> const* findFirstMatch(Expression const& _expr);
|
||||||
|
|
||||||
|
/// 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:
|
private:
|
||||||
void addRules(std::vector<SimplificationRule<Pattern>> const& _rules);
|
void addRules(std::vector<SimplificationRule<Pattern>> const& _rules);
|
||||||
void addRule(SimplificationRule<Pattern> const& _rule);
|
void addRule(SimplificationRule<Pattern> const& _rule);
|
||||||
|
Loading…
Reference in New Issue
Block a user