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 <libyul/Dialect.h>
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
@ -657,12 +661,37 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart9(
|
||||
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.
|
||||
/// A, B and C should represent constants, W, X, Y, and Z arbitrary expressions.
|
||||
/// The simplifications should never change the order of evaluation of
|
||||
/// arbitrary operations.
|
||||
template <class Pattern>
|
||||
std::vector<SimplificationRule<Pattern>> simplificationRuleList(
|
||||
std::optional<langutil::EVMVersion> _evmVersion,
|
||||
Pattern A,
|
||||
Pattern B,
|
||||
Pattern C,
|
||||
@ -691,6 +720,10 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleList(
|
||||
rules += simplificationRuleListPart7(A, B, C, W, X);
|
||||
rules += simplificationRuleListPart8(A, B, C, W, X);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ Rules::Rules()
|
||||
Y.setMatchGroup(6, 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.");
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ using namespace solidity::evmasm;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::yul;
|
||||
|
||||
SimplificationRule<yul::Pattern> const* SimplificationRules::findFirstMatch(
|
||||
SimplificationRules::Rule const* SimplificationRules::findFirstMatch(
|
||||
Expression const& _expr,
|
||||
Dialect const& _dialect,
|
||||
map<YulString, AssignedValue> const& _ssaValues
|
||||
@ -46,7 +46,16 @@ SimplificationRule<yul::Pattern> const* SimplificationRules::findFirstMatch(
|
||||
if (!instruction)
|
||||
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.");
|
||||
|
||||
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 {};
|
||||
}
|
||||
|
||||
void SimplificationRules::addRules(vector<SimplificationRule<Pattern>> const& _rules)
|
||||
void SimplificationRules::addRules(std::vector<Rule> const& _rules)
|
||||
{
|
||||
for (auto const& r: _rules)
|
||||
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);
|
||||
}
|
||||
|
||||
SimplificationRules::SimplificationRules()
|
||||
SimplificationRules::SimplificationRules(std::optional<langutil::EVMVersion> _evmVersion)
|
||||
{
|
||||
// Multiple occurrences of one of these inside one rule must match the same equivalence class.
|
||||
// Constants.
|
||||
@ -107,7 +116,7 @@ SimplificationRules::SimplificationRules()
|
||||
Y.setMatchGroup(6, 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.");
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,8 @@
|
||||
|
||||
#include <libsolutil/CommonData.h>
|
||||
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include <functional>
|
||||
@ -45,12 +47,14 @@ class Pattern;
|
||||
class SimplificationRules: public boost::noncopyable
|
||||
{
|
||||
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
|
||||
/// groups accordingly.
|
||||
/// @param _ssaValues values of variables that are assigned exactly once.
|
||||
static evmasm::SimplificationRule<Pattern> const* findFirstMatch(
|
||||
static Rule const* findFirstMatch(
|
||||
Expression const& _expr,
|
||||
Dialect const& _dialect,
|
||||
std::map<YulString, AssignedValue> const& _ssaValues
|
||||
@ -64,8 +68,8 @@ public:
|
||||
instructionAndArguments(Dialect const& _dialect, Expression const& _expr);
|
||||
|
||||
private:
|
||||
void addRules(std::vector<evmasm::SimplificationRule<Pattern>> const& _rules);
|
||||
void addRule(evmasm::SimplificationRule<Pattern> const& _rule);
|
||||
void addRules(std::vector<Rule> const& _rules);
|
||||
void addRule(Rule const& _rule);
|
||||
|
||||
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