-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Yul interpreter: Changes required before merging Redundant store eliminator #12276
Conversation
test/libyul/YulInterpreterTest.cpp
Outdated
@@ -94,13 +94,13 @@ string YulInterpreterTest::interpret() | |||
state.maxExprNesting = 64; | |||
try | |||
{ | |||
Interpreter::run(state, EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{}), *m_ast); | |||
Interpreter::run(state, EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{}), *m_ast, false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Memory tracing is enabled (last argument = false
) for Yul interpreter tests. This may be changed to true
if tests pass only without memory tracing.
test/libyul/EwasmTranslationTest.cpp
Outdated
@@ -108,13 +108,13 @@ string EwasmTranslationTest::interpret() | |||
state.maxExprNesting = 64; | |||
try | |||
{ | |||
Interpreter::run(state, WasmDialect{}, *m_object->code); | |||
Interpreter::run(state, WasmDialect{}, *m_object->code, false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Memory tracing is enabled (last argument = false
) for Ewasm->Yul tests. This may be changed to true
if tests pass only without memory tracing.
} | ||
catch (InterpreterTerminatedGeneric const&) | ||
{ | ||
} | ||
|
||
stringstream result; | ||
state.dumpTraceAndState(result); | ||
state.dumpTraceAndState(result, false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Memory tracing enabled.
@@ -204,6 +205,7 @@ u256 EVMInstructionInterpreter::eval( | |||
case Instruction::CALLDATASIZE: | |||
return m_state.calldata.size(); | |||
case Instruction::CALLDATACOPY: | |||
logTrace(_instruction, true, arg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logTrace(instruction, true, arg)
means interpret instruction I
whose args are A...
and tell the tracer that this instruction may write to memory.
If the interpreter is configured to disable memory tracing, this information (whether an instruction writes to memory or not) is useful in deciding whether to append the instruction to execution trace or not.
@@ -99,6 +99,7 @@ u256 EVMInstructionInterpreter::eval( | |||
switch (_instruction) | |||
{ | |||
case Instruction::STOP: | |||
logTrace(_instruction, false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For instructions that do not write to memory such as stop()
, the second argument is false
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering - shouldn't we use some utility to infer this fact from the opcode itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds reasonable to me. More concretely, would it be a static look up table per opcode or an annotation to the opcode itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think SemanticInformation::memory
would be suitable. It is a slight problem since we cannot test this function here anymore, but I guess it's better to use constants here all the time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think SemanticInformation::memory
would be suitable. It is a slight problem since we cannot test this function here anymore, but I guess it's better to use constants here all the time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to make use of SemanticInformation::memory
. If there are any mistaken assumptions, the fuzzer would report a bug which we could later investigate.
ecc80c6
to
9bf34de
Compare
Can you summarize the change? Do we at least compare the data in storage at the end? |
|
bd97e62
to
e203708
Compare
@bshastry How is that done? I have a feeling that might not be enough for something like {
let x := calldataload(0)
let y := sload(x)
// both of these can be removed
sstore(x, y)
sstore(x, y)
let a := x
let b := mload(a)
// both of these can be removed
mstore(a, b)
mstore(a, b)
}
// ----
// step: equalStoreEliminator
//
// {
// let x := calldataload(0)
// let y := sload(x)
// let a := x
// let b := mload(a)
// } |
Essentially the following
Since storage writes are always preserved in map, they may be compared pre/post optimisation. OTOH, memory may not be compared. |
…ing. Model revert in yul interpreter. Add logTrace for a few more instructions and clear trace on revert.
state, | ||
EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{}), | ||
*m_ast, | ||
/*disableMemoryTracing=*/false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe avoid the negation and call it enableMemoryTracing
?
@@ -339,12 +344,18 @@ u256 EVMInstructionInterpreter::eval( | |||
case Instruction::REVERT: | |||
accessMemory(arg[0], arg[1]); | |||
logTrace(_instruction, arg); | |||
m_state.storage.clear(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How "correct" is this interpreter? Shouldn't it only clear the changes to storage? Should we extract this change into its own PR?
Could be merged like this. |
Required to fuzz #11352