mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
More flexible way to approach unknown stack elements.
This commit is contained in:
parent
9106d72a02
commit
3ebb7d99c4
@ -37,6 +37,7 @@ using namespace dev::eth;
|
|||||||
|
|
||||||
bool ExpressionClasses::Expression::operator<(ExpressionClasses::Expression const& _other) const
|
bool ExpressionClasses::Expression::operator<(ExpressionClasses::Expression const& _other) const
|
||||||
{
|
{
|
||||||
|
assertThrow(!!item && !!_other.item, OptimizerException, "");
|
||||||
auto type = item->type();
|
auto type = item->type();
|
||||||
auto otherType = _other.item->type();
|
auto otherType = _other.item->type();
|
||||||
return std::tie(type, item->data(), arguments, sequenceNumber) <
|
return std::tie(type, item->data(), arguments, sequenceNumber) <
|
||||||
@ -78,6 +79,15 @@ ExpressionClasses::Id ExpressionClasses::find(
|
|||||||
return exp.id;
|
return exp.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExpressionClasses::Id ExpressionClasses::newId()
|
||||||
|
{
|
||||||
|
// Note that we cannot insert it in m_expressions because this requires item to be set.
|
||||||
|
Expression exp;
|
||||||
|
exp.id = m_representatives.size();
|
||||||
|
m_representatives.push_back(exp);
|
||||||
|
return exp.id;
|
||||||
|
}
|
||||||
|
|
||||||
bool ExpressionClasses::knownToBeDifferent(ExpressionClasses::Id _a, ExpressionClasses::Id _b)
|
bool ExpressionClasses::knownToBeDifferent(ExpressionClasses::Id _a, ExpressionClasses::Id _b)
|
||||||
{
|
{
|
||||||
// Try to simplify "_a - _b" and return true iff the value is a non-zero constant.
|
// Try to simplify "_a - _b" and return true iff the value is a non-zero constant.
|
||||||
@ -122,10 +132,16 @@ string ExpressionClasses::fullDAGToString(ExpressionClasses::Id _id) const
|
|||||||
{
|
{
|
||||||
Expression const& expr = representative(_id);
|
Expression const& expr = representative(_id);
|
||||||
stringstream str;
|
stringstream str;
|
||||||
str << dec << expr.id << ":" << *expr.item << "(";
|
str << dec << expr.id << ":";
|
||||||
|
if (expr.item)
|
||||||
|
{
|
||||||
|
str << *expr.item << "(";
|
||||||
for (Id arg: expr.arguments)
|
for (Id arg: expr.arguments)
|
||||||
str << fullDAGToString(arg) << ",";
|
str << fullDAGToString(arg) << ",";
|
||||||
str << ")";
|
str << ")";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
str << " UNIQUE";
|
||||||
return str.str();
|
return str.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +295,7 @@ ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr,
|
|||||||
{
|
{
|
||||||
static Rules rules;
|
static Rules rules;
|
||||||
|
|
||||||
if (_expr.item->type() != Operation)
|
if (!_expr.item || _expr.item->type() != Operation)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for (auto const& rule: rules.rules())
|
for (auto const& rule: rules.rules())
|
||||||
@ -337,7 +353,7 @@ void Pattern::setMatchGroup(unsigned _group, map<unsigned, Expression const*>& _
|
|||||||
|
|
||||||
bool Pattern::matches(Expression const& _expr, ExpressionClasses const& _classes) const
|
bool Pattern::matches(Expression const& _expr, ExpressionClasses const& _classes) const
|
||||||
{
|
{
|
||||||
if (!matchesBaseItem(*_expr.item))
|
if (!matchesBaseItem(_expr.item))
|
||||||
return false;
|
return false;
|
||||||
if (m_matchGroup)
|
if (m_matchGroup)
|
||||||
{
|
{
|
||||||
@ -387,13 +403,15 @@ string Pattern::toString() const
|
|||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Pattern::matchesBaseItem(AssemblyItem const& _item) const
|
bool Pattern::matchesBaseItem(AssemblyItem const* _item) const
|
||||||
{
|
{
|
||||||
if (m_type == UndefinedItem)
|
if (m_type == UndefinedItem)
|
||||||
return true;
|
return true;
|
||||||
if (m_type != _item.type())
|
if (!_item)
|
||||||
return false;
|
return false;
|
||||||
if (m_requireDataMatch && m_data != _item.data())
|
if (m_type != _item->type())
|
||||||
|
return false;
|
||||||
|
if (m_requireDataMatch && m_data != _item->data())
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ public:
|
|||||||
struct Expression
|
struct Expression
|
||||||
{
|
{
|
||||||
Id id;
|
Id id;
|
||||||
AssemblyItem const* item;
|
AssemblyItem const* item = nullptr;
|
||||||
Ids arguments;
|
Ids arguments;
|
||||||
unsigned sequenceNumber; ///< Storage modification sequence, only used for SLOAD/SSTORE instructions.
|
unsigned sequenceNumber; ///< Storage modification sequence, only used for SLOAD/SSTORE instructions.
|
||||||
/// Behaves as if this was a tuple of (item->type(), item->data(), arguments, sequenceNumber).
|
/// Behaves as if this was a tuple of (item->type(), item->data(), arguments, sequenceNumber).
|
||||||
@ -68,6 +68,10 @@ public:
|
|||||||
bool _copyItem = true,
|
bool _copyItem = true,
|
||||||
unsigned _sequenceNumber = 0
|
unsigned _sequenceNumber = 0
|
||||||
);
|
);
|
||||||
|
/// @returns a new unique class id which does not and will never have a representative containing
|
||||||
|
/// an AssemblyItem, i.e. its value cannot be generated, instead it has to be assumed to be
|
||||||
|
/// already present.
|
||||||
|
Id newId();
|
||||||
/// @returns the canonical representative of an expression class.
|
/// @returns the canonical representative of an expression class.
|
||||||
Expression const& representative(Id _id) const { return m_representatives.at(_id); }
|
Expression const& representative(Id _id) const { return m_representatives.at(_id); }
|
||||||
/// @returns the number of classes.
|
/// @returns the number of classes.
|
||||||
@ -149,7 +153,7 @@ public:
|
|||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool matchesBaseItem(AssemblyItem const& _item) const;
|
bool matchesBaseItem(AssemblyItem const* _item) const;
|
||||||
Expression const& matchGroupValue() const;
|
Expression const& matchGroupValue() const;
|
||||||
|
|
||||||
AssemblyItemType m_type;
|
AssemblyItemType m_type;
|
||||||
|
@ -136,7 +136,7 @@ ExpressionClasses::Id KnownState::stackElement(int _stackHeight, SourceLocation
|
|||||||
if (m_stackElements.count(_stackHeight))
|
if (m_stackElements.count(_stackHeight))
|
||||||
return m_stackElements.at(_stackHeight);
|
return m_stackElements.at(_stackHeight);
|
||||||
// Stack element not found (not assigned yet), create new equivalence class.
|
// Stack element not found (not assigned yet), create new equivalence class.
|
||||||
return m_stackElements[_stackHeight] = initialStackElement(_stackHeight, _location);
|
return m_stackElements[_stackHeight] = m_expressionClasses->newId();
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpressionClasses::Id KnownState::initialStackElement(
|
ExpressionClasses::Id KnownState::initialStackElement(
|
||||||
|
Loading…
Reference in New Issue
Block a user