aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-04-30 21:31:16 +0800
committerchriseth <c@ethdev.com>2015-05-06 17:11:16 +0800
commita2e3bcbd0c45a79a9709dc8a69858765ab904805 (patch)
tree1201a25150145a991ef11c5f62465986c6b27dea
parent867101e40981db56d8b72fd363e4f9e376991284 (diff)
downloaddexon-solidity-a2e3bcbd0c45a79a9709dc8a69858765ab904805.tar.gz
dexon-solidity-a2e3bcbd0c45a79a9709dc8a69858765ab904805.tar.zst
dexon-solidity-a2e3bcbd0c45a79a9709dc8a69858765ab904805.zip
Make KnownState work with all instructions.
-rw-r--r--ExpressionClasses.cpp19
-rw-r--r--KnownState.cpp7
-rw-r--r--SemanticInformation.cpp54
-rw-r--r--SemanticInformation.h9
4 files changed, 83 insertions, 6 deletions
diff --git a/ExpressionClasses.cpp b/ExpressionClasses.cpp
index e62f7526..cfbeba7f 100644
--- a/ExpressionClasses.cpp
+++ b/ExpressionClasses.cpp
@@ -57,12 +57,15 @@ ExpressionClasses::Id ExpressionClasses::find(
exp.arguments = _arguments;
exp.sequenceNumber = _sequenceNumber;
- if (SemanticInformation::isCommutativeOperation(_item))
- sort(exp.arguments.begin(), exp.arguments.end());
+ if (SemanticInformation::isDeterministic(_item))
+ {
+ if (SemanticInformation::isCommutativeOperation(_item))
+ sort(exp.arguments.begin(), exp.arguments.end());
- auto it = m_expressions.find(exp);
- if (it != m_expressions.end())
- return it->id;
+ auto it = m_expressions.find(exp);
+ if (it != m_expressions.end())
+ return it->id;
+ }
if (_copyItem)
exp.item = storeItem(_item);
@@ -286,7 +289,11 @@ ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr,
{
static Rules rules;
- if (!_expr.item || _expr.item->type() != Operation)
+ if (
+ !_expr.item ||
+ _expr.item->type() != Operation ||
+ !SemanticInformation::isDeterministic(*_expr.item)
+ )
return -1;
for (auto const& rule: rules.rules())
diff --git a/KnownState.cpp b/KnownState.cpp
index 02c6ee13..632777c8 100644
--- a/KnownState.cpp
+++ b/KnownState.cpp
@@ -101,6 +101,7 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool
vector<Id> arguments(info.args);
for (int i = 0; i < info.args; ++i)
arguments[i] = stackElement(m_stackHeight - i, _item.getLocation());
+
if (_item.instruction() == Instruction::SSTORE)
op = storeInStorage(arguments[0], arguments[1], _item.getLocation());
else if (_item.instruction() == Instruction::SLOAD)
@@ -121,10 +122,16 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool
applySha3(arguments.at(0), arguments.at(1), _item.getLocation())
);
else
+ {
+ if (SemanticInformation::invalidatesMemory(_item.instruction()))
+ resetMemory();
+ if (SemanticInformation::invalidatesStorage(_item.instruction()))
+ resetStorage();
setStackElement(
m_stackHeight + _item.deposit(),
m_expressionClasses->find(_item, arguments, _copyItem)
);
+ }
}
m_stackHeight += _item.deposit();
}
diff --git a/SemanticInformation.cpp b/SemanticInformation.cpp
index 83d59efc..40c36f9e 100644
--- a/SemanticInformation.cpp
+++ b/SemanticInformation.cpp
@@ -122,3 +122,57 @@ bool SemanticInformation::altersControlFlow(AssemblyItem const& _item)
return false;
}
}
+
+
+bool SemanticInformation::isDeterministic(AssemblyItem const& _item)
+{
+ if (_item.type() != Operation)
+ return true;
+ assertThrow(!altersControlFlow(_item), OptimizerException, "");
+
+ switch (_item.instruction())
+ {
+ case Instruction::CALL:
+ case Instruction::CALLCODE:
+ case Instruction::CREATE:
+ case Instruction::GAS:
+ case Instruction::PC:
+ case Instruction::MSIZE: // depends on previous writes and reads, not only on content
+ case Instruction::BALANCE: // depends on previous calls
+ case Instruction::EXTCODESIZE:
+ return false;
+ default:
+ return true;
+ }
+}
+
+bool SemanticInformation::invalidatesMemory(Instruction _instruction)
+{
+ switch (_instruction)
+ {
+ case Instruction::CALLDATACOPY:
+ case Instruction::CODECOPY:
+ case Instruction::EXTCODECOPY:
+ case Instruction::MSTORE:
+ case Instruction::MSTORE8:
+ case Instruction::CALL:
+ case Instruction::CALLCODE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool SemanticInformation::invalidatesStorage(Instruction _instruction)
+{
+ switch (_instruction)
+ {
+ case Instruction::CALL:
+ case Instruction::CALLCODE:
+ case Instruction::CREATE:
+ case Instruction::SSTORE:
+ return true;
+ default:
+ return false;
+ }
+}
diff --git a/SemanticInformation.h b/SemanticInformation.h
index 27aa6f1a..b14ddb65 100644
--- a/SemanticInformation.h
+++ b/SemanticInformation.h
@@ -23,6 +23,7 @@
#pragma once
+#include <libevmcore/Instruction.h>
namespace dev
{
@@ -45,6 +46,14 @@ struct SemanticInformation
static bool isSwapInstruction(AssemblyItem const& _item);
static bool isJumpInstruction(AssemblyItem const& _item);
static bool altersControlFlow(AssemblyItem const& _item);
+ /// @returns false if the value put on the stack by _item depends on anything else than
+ /// the information in the current block header, memory, storage or stack.
+ /// @note should not be called for instructions that alter the control flow.
+ static bool isDeterministic(AssemblyItem const& _item);
+ /// @returns true if the given instruction modifies memory.
+ static bool invalidatesMemory(Instruction _instruction);
+ /// @returns true if the given instruction modifies storage (even indirectly).
+ static bool invalidatesStorage(Instruction _instruction);
};
}