mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8958 from ethereum/evm-version-dependent-rules
[yul] Add support for EVM version-dependent rules.
This commit is contained in:
commit
a06ac0f39f
@ -29,6 +29,10 @@
|
|||||||
|
|
||||||
#include <boost/multiprecision/detail/min_max.hpp>
|
#include <boost/multiprecision/detail/min_max.hpp>
|
||||||
|
|
||||||
|
#include <libyul/Dialect.h>
|
||||||
|
#include <libyul/backends/evm/EVMDialect.h>
|
||||||
|
#include <liblangutil/EVMVersion.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
@ -657,12 +661,37 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart9(
|
|||||||
return rules;
|
return rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Pattern>
|
||||||
|
std::vector<SimplificationRule<Pattern>> evmRuleList(
|
||||||
|
langutil::EVMVersion _evmVersion,
|
||||||
|
Pattern,
|
||||||
|
Pattern,
|
||||||
|
Pattern,
|
||||||
|
Pattern,
|
||||||
|
Pattern,
|
||||||
|
Pattern,
|
||||||
|
Pattern
|
||||||
|
)
|
||||||
|
{
|
||||||
|
using Builtins = typename Pattern::Builtins;
|
||||||
|
std::vector<SimplificationRule<Pattern>> rules;
|
||||||
|
|
||||||
|
if (_evmVersion.hasSelfBalance())
|
||||||
|
rules.push_back({
|
||||||
|
Builtins::BALANCE(Instruction::ADDRESS),
|
||||||
|
[]() -> Pattern { return Instruction::SELFBALANCE; }, false
|
||||||
|
});
|
||||||
|
|
||||||
|
return rules;
|
||||||
|
}
|
||||||
|
|
||||||
/// @returns a list of simplification rules given certain match placeholders.
|
/// @returns a list of simplification rules given certain match placeholders.
|
||||||
/// A, B and C should represent constants, W, X, Y, and Z arbitrary expressions.
|
/// A, B and C should represent constants, W, X, Y, and Z arbitrary expressions.
|
||||||
/// The simplifications should never change the order of evaluation of
|
/// The simplifications should never change the order of evaluation of
|
||||||
/// arbitrary operations.
|
/// arbitrary operations.
|
||||||
template <class Pattern>
|
template <class Pattern>
|
||||||
std::vector<SimplificationRule<Pattern>> simplificationRuleList(
|
std::vector<SimplificationRule<Pattern>> simplificationRuleList(
|
||||||
|
std::optional<langutil::EVMVersion> _evmVersion,
|
||||||
Pattern A,
|
Pattern A,
|
||||||
Pattern B,
|
Pattern B,
|
||||||
Pattern C,
|
Pattern C,
|
||||||
@ -691,6 +720,10 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleList(
|
|||||||
rules += simplificationRuleListPart7(A, B, C, W, X);
|
rules += simplificationRuleListPart7(A, B, C, W, X);
|
||||||
rules += simplificationRuleListPart8(A, B, C, W, X);
|
rules += simplificationRuleListPart8(A, B, C, W, X);
|
||||||
rules += simplificationRuleListPart9(A, B, C, W, X, Y, Z);
|
rules += simplificationRuleListPart9(A, B, C, W, X, Y, Z);
|
||||||
|
|
||||||
|
if (_evmVersion.has_value())
|
||||||
|
rules += evmRuleList(*_evmVersion, A, B, C, W, X, Y, Z);
|
||||||
|
|
||||||
return rules;
|
return rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ Rules::Rules()
|
|||||||
Y.setMatchGroup(6, m_matchGroups);
|
Y.setMatchGroup(6, m_matchGroups);
|
||||||
Z.setMatchGroup(7, m_matchGroups);
|
Z.setMatchGroup(7, m_matchGroups);
|
||||||
|
|
||||||
addRules(simplificationRuleList(A, B, C, W, X, Y, Z));
|
addRules(simplificationRuleList(nullopt, A, B, C, W, X, Y, Z));
|
||||||
assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized.");
|
assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ using namespace solidity::evmasm;
|
|||||||
using namespace solidity::langutil;
|
using namespace solidity::langutil;
|
||||||
using namespace solidity::yul;
|
using namespace solidity::yul;
|
||||||
|
|
||||||
SimplificationRule<yul::Pattern> const* SimplificationRules::findFirstMatch(
|
SimplificationRules::Rule const* SimplificationRules::findFirstMatch(
|
||||||
Expression const& _expr,
|
Expression const& _expr,
|
||||||
Dialect const& _dialect,
|
Dialect const& _dialect,
|
||||||
map<YulString, AssignedValue> const& _ssaValues
|
map<YulString, AssignedValue> const& _ssaValues
|
||||||
@ -46,7 +46,16 @@ SimplificationRule<yul::Pattern> const* SimplificationRules::findFirstMatch(
|
|||||||
if (!instruction)
|
if (!instruction)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
static SimplificationRules rules;
|
static std::map<std::optional<EVMVersion>, std::unique_ptr<SimplificationRules>> evmRules;
|
||||||
|
|
||||||
|
std::optional<EVMVersion> version;
|
||||||
|
if (yul::EVMDialect const* evmDialect = dynamic_cast<yul::EVMDialect const*>(&_dialect))
|
||||||
|
version = evmDialect->evmVersion();
|
||||||
|
|
||||||
|
if (!evmRules[version])
|
||||||
|
evmRules[version] = std::make_unique<SimplificationRules>(version);
|
||||||
|
|
||||||
|
SimplificationRules& rules = *evmRules[version];
|
||||||
assertThrow(rules.isInitialized(), OptimizerException, "Rule list not properly initialized.");
|
assertThrow(rules.isInitialized(), OptimizerException, "Rule list not properly initialized.");
|
||||||
|
|
||||||
for (auto const& rule: rules.m_rules[uint8_t(instruction->first)])
|
for (auto const& rule: rules.m_rules[uint8_t(instruction->first)])
|
||||||
@ -76,18 +85,18 @@ std::optional<std::pair<evmasm::Instruction, vector<Expression> const*>>
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimplificationRules::addRules(vector<SimplificationRule<Pattern>> const& _rules)
|
void SimplificationRules::addRules(std::vector<Rule> const& _rules)
|
||||||
{
|
{
|
||||||
for (auto const& r: _rules)
|
for (auto const& r: _rules)
|
||||||
addRule(r);
|
addRule(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimplificationRules::addRule(SimplificationRule<Pattern> const& _rule)
|
void SimplificationRules::addRule(Rule const& _rule)
|
||||||
{
|
{
|
||||||
m_rules[uint8_t(_rule.pattern.instruction())].push_back(_rule);
|
m_rules[uint8_t(_rule.pattern.instruction())].push_back(_rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
SimplificationRules::SimplificationRules()
|
SimplificationRules::SimplificationRules(std::optional<langutil::EVMVersion> _evmVersion)
|
||||||
{
|
{
|
||||||
// Multiple occurrences of one of these inside one rule must match the same equivalence class.
|
// Multiple occurrences of one of these inside one rule must match the same equivalence class.
|
||||||
// Constants.
|
// Constants.
|
||||||
@ -107,7 +116,7 @@ SimplificationRules::SimplificationRules()
|
|||||||
Y.setMatchGroup(6, m_matchGroups);
|
Y.setMatchGroup(6, m_matchGroups);
|
||||||
Z.setMatchGroup(7, m_matchGroups);
|
Z.setMatchGroup(7, m_matchGroups);
|
||||||
|
|
||||||
addRules(simplificationRuleList(A, B, C, W, X, Y, Z));
|
addRules(simplificationRuleList(_evmVersion, A, B, C, W, X, Y, Z));
|
||||||
assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized.");
|
assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
#include <libsolutil/CommonData.h>
|
#include <libsolutil/CommonData.h>
|
||||||
|
|
||||||
|
#include <liblangutil/EVMVersion.h>
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -45,12 +47,14 @@ class Pattern;
|
|||||||
class SimplificationRules: public boost::noncopyable
|
class SimplificationRules: public boost::noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SimplificationRules();
|
using Rule = evmasm::SimplificationRule<Pattern>;
|
||||||
|
|
||||||
|
explicit SimplificationRules(std::optional<langutil::EVMVersion> _evmVersion = std::nullopt);
|
||||||
|
|
||||||
/// @returns a pointer to the first matching pattern and sets the match
|
/// @returns a pointer to the first matching pattern and sets the match
|
||||||
/// groups accordingly.
|
/// groups accordingly.
|
||||||
/// @param _ssaValues values of variables that are assigned exactly once.
|
/// @param _ssaValues values of variables that are assigned exactly once.
|
||||||
static evmasm::SimplificationRule<Pattern> const* findFirstMatch(
|
static Rule const* findFirstMatch(
|
||||||
Expression const& _expr,
|
Expression const& _expr,
|
||||||
Dialect const& _dialect,
|
Dialect const& _dialect,
|
||||||
std::map<YulString, AssignedValue> const& _ssaValues
|
std::map<YulString, AssignedValue> const& _ssaValues
|
||||||
@ -64,8 +68,8 @@ public:
|
|||||||
instructionAndArguments(Dialect const& _dialect, Expression const& _expr);
|
instructionAndArguments(Dialect const& _dialect, Expression const& _expr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addRules(std::vector<evmasm::SimplificationRule<Pattern>> const& _rules);
|
void addRules(std::vector<Rule> const& _rules);
|
||||||
void addRule(evmasm::SimplificationRule<Pattern> const& _rule);
|
void addRule(Rule const& _rule);
|
||||||
|
|
||||||
void resetMatchGroups() { m_matchGroups.clear(); }
|
void resetMatchGroups() { m_matchGroups.clear(); }
|
||||||
|
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
let ret := balance(address())
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: <istanbul
|
||||||
|
// ----
|
||||||
|
// step: expressionSimplifier
|
||||||
|
//
|
||||||
|
// { let ret := balance(address()) }
|
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
let a := address()
|
||||||
|
let ret := balance(a)
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >=istanbul
|
||||||
|
// ----
|
||||||
|
// step: expressionSimplifier
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// let a := address()
|
||||||
|
// let ret := selfbalance()
|
||||||
|
// }
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
let ret := balance(address())
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >=istanbul
|
||||||
|
// ----
|
||||||
|
// step: expressionSimplifier
|
||||||
|
//
|
||||||
|
// { let ret := selfbalance() }
|
Loading…
Reference in New Issue
Block a user