mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Make verbatim compatible with KnownState.
This commit is contained in:
parent
e2d8005737
commit
cb1af8b88a
@ -73,7 +73,10 @@ public:
|
||||
void appendImmutable(std::string const& _identifier) { append(newPushImmutable(_identifier)); }
|
||||
void appendImmutableAssignment(std::string const& _identifier) { append(newImmutableAssignment(_identifier)); }
|
||||
|
||||
void appendVerbatim(bytes const& _data, int _stackDifference) { append(AssemblyItem(_data, _stackDifference)); }
|
||||
void appendVerbatim(bytes _data, size_t _arguments, size_t _returnVariables)
|
||||
{
|
||||
append(AssemblyItem(std::move(_data), _arguments, _returnVariables));
|
||||
}
|
||||
|
||||
AssemblyItem appendJump() { auto ret = append(newPushTag()); append(Instruction::JUMP); return ret; }
|
||||
AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(Instruction::JUMPI); return ret; }
|
||||
|
@ -92,7 +92,7 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength) const
|
||||
else
|
||||
return 1 + (3 + 32) * 1024; // 1024 occurrences are beyond the maximum code size anyways.
|
||||
case VerbatimBytecode:
|
||||
return m_verbatimBytecode->second.size();
|
||||
return std::get<2>(*m_verbatimBytecode).size();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -103,6 +103,8 @@ size_t AssemblyItem::arguments() const
|
||||
{
|
||||
if (type() == Operation)
|
||||
return static_cast<size_t>(instructionInfo(instruction()).args);
|
||||
else if (type() == VerbatimBytecode)
|
||||
return get<0>(*m_verbatimBytecode);
|
||||
else if (type() == AssignImmutable)
|
||||
return 2;
|
||||
else
|
||||
@ -128,6 +130,8 @@ size_t AssemblyItem::returnValues() const
|
||||
return 1;
|
||||
case Tag:
|
||||
return 0;
|
||||
case VerbatimBytecode:
|
||||
return get<1>(*m_verbatimBytecode);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -244,7 +248,7 @@ string AssemblyItem::toAssemblyText(Assembly const& _assembly) const
|
||||
assertThrow(false, AssemblyException, "Invalid assembly item.");
|
||||
break;
|
||||
case VerbatimBytecode:
|
||||
text = string("verbatimbytecode_") + util::toHex(m_verbatimBytecode->second);
|
||||
text = string("verbatimbytecode_") + util::toHex(get<2>(*m_verbatimBytecode));
|
||||
break;
|
||||
default:
|
||||
assertThrow(false, InvalidOpcode, "");
|
||||
|
@ -77,10 +77,10 @@ public:
|
||||
else
|
||||
m_data = std::make_shared<u256>(std::move(_data));
|
||||
}
|
||||
explicit AssemblyItem(bytes const& _verbatimData, int _deposit):
|
||||
explicit AssemblyItem(bytes _verbatimData, size_t _arguments, size_t _returnVariables):
|
||||
m_type(VerbatimBytecode),
|
||||
m_instruction{},
|
||||
m_verbatimBytecode{{_deposit, _verbatimData}}
|
||||
m_verbatimBytecode{{_arguments, _returnVariables, std::move(_verbatimData)}}
|
||||
{}
|
||||
|
||||
AssemblyItem(AssemblyItem const&) = default;
|
||||
@ -103,7 +103,7 @@ public:
|
||||
u256 const& data() const { assertThrow(m_type != Operation, util::Exception, ""); return *m_data; }
|
||||
void setData(u256 const& _data) { assertThrow(m_type != Operation, util::Exception, ""); m_data = std::make_shared<u256>(_data); }
|
||||
|
||||
bytes const& verbatimData() const { assertThrow(m_type == VerbatimBytecode, util::Exception, ""); return m_verbatimBytecode->second; }
|
||||
bytes const& verbatimData() const { assertThrow(m_type == VerbatimBytecode, util::Exception, ""); return std::get<2>(*m_verbatimBytecode); }
|
||||
|
||||
/// @returns the instruction of this item (only valid if type() == Operation)
|
||||
Instruction instruction() const { assertThrow(m_type == Operation, util::Exception, ""); return m_instruction; }
|
||||
@ -151,7 +151,7 @@ public:
|
||||
size_t bytesRequired(size_t _addressLength) const;
|
||||
size_t arguments() const;
|
||||
size_t returnValues() const;
|
||||
size_t deposit() const { return m_type == VerbatimBytecode ? static_cast<size_t>(m_verbatimBytecode->first) : returnValues() - arguments(); }
|
||||
size_t deposit() const { return returnValues() - arguments(); }
|
||||
|
||||
/// @returns true if the assembly item can be used in a functional context.
|
||||
bool canBeFunctional() const;
|
||||
@ -176,8 +176,9 @@ private:
|
||||
AssemblyItemType m_type;
|
||||
Instruction m_instruction; ///< Only valid if m_type == Operation
|
||||
std::shared_ptr<u256> m_data; ///< Only valid if m_type != Operation
|
||||
/// If m_type == VerbatimBytecode, this holds stack difference and verbatim bytecode.
|
||||
std::optional<std::pair<int, bytes>> m_verbatimBytecode;
|
||||
/// If m_type == VerbatimBytecode, this holds number of arguments, number of
|
||||
/// return variables and verbatim bytecode.
|
||||
std::optional<std::tuple<size_t, size_t, bytes>> m_verbatimBytecode;
|
||||
langutil::SourceLocation m_location;
|
||||
JumpType m_jumpType = JumpType::Ordinary;
|
||||
/// Pushed value for operations with data to be determined during assembly stage,
|
||||
|
@ -100,6 +100,24 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool
|
||||
feedItem(AssemblyItem(Instruction::POP), _copyItem);
|
||||
return feedItem(AssemblyItem(Instruction::POP), _copyItem);
|
||||
}
|
||||
else if (_item.type() == VerbatimBytecode)
|
||||
{
|
||||
m_sequenceNumber += 2;
|
||||
resetMemory();
|
||||
resetKnownKeccak256Hashes();
|
||||
resetStorage();
|
||||
// Consume all arguments and place unknown return values on the stack.
|
||||
m_stackElements.erase(
|
||||
m_stackElements.upper_bound(m_stackHeight - static_cast<int>(_item.arguments())),
|
||||
m_stackElements.end()
|
||||
);
|
||||
m_stackHeight += static_cast<int>(_item.deposit());
|
||||
for (size_t i = 0; i < _item.returnValues(); ++i)
|
||||
setStackElement(
|
||||
m_stackHeight - static_cast<int>(i),
|
||||
m_expressionClasses->newClass(_item.location())
|
||||
);
|
||||
}
|
||||
else if (_item.type() != Operation)
|
||||
{
|
||||
assertThrow(_item.deposit() == 1, InvalidDeposit, "");
|
||||
|
@ -78,7 +78,7 @@ public:
|
||||
virtual void appendLinkerSymbol(std::string const& _name) = 0;
|
||||
|
||||
/// Append raw bytes that stay untouched by the optimizer.
|
||||
virtual void appendVerbatim(bytes const& _data, int _stackDifference) = 0;
|
||||
virtual void appendVerbatim(bytes _data, size_t _arguments, size_t _returnVariables) = 0;
|
||||
|
||||
/// Append a jump instruction.
|
||||
/// @param _stackDiffAfter the stack adjustment after this instruction.
|
||||
|
@ -99,9 +99,9 @@ void EthAssemblyAdapter::appendLinkerSymbol(std::string const& _linkerSymbol)
|
||||
m_assembly.appendLibraryAddress(_linkerSymbol);
|
||||
}
|
||||
|
||||
void EthAssemblyAdapter::appendVerbatim(bytes const& _data, int _stackDifference)
|
||||
void EthAssemblyAdapter::appendVerbatim(bytes _data, size_t _arguments, size_t _returnVariables)
|
||||
{
|
||||
m_assembly.appendVerbatim(_data, _stackDifference);
|
||||
m_assembly.appendVerbatim(move(_data), _arguments, _returnVariables);
|
||||
}
|
||||
|
||||
void EthAssemblyAdapter::appendJump(int _stackDiffAfter, JumpType _jumpType)
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
size_t newLabelId() override;
|
||||
size_t namedLabel(std::string const& _name) override;
|
||||
void appendLinkerSymbol(std::string const& _linkerSymbol) override;
|
||||
void appendVerbatim(bytes const& _data, int _stackDifference) override;
|
||||
void appendVerbatim(bytes _data, size_t _arguments, size_t _returnVariables) override;
|
||||
void appendJump(int _stackDiffAfter, JumpType _jumpType) override;
|
||||
void appendJumpTo(LabelID _labelId, int _stackDiffAfter, JumpType _jumpType) override;
|
||||
void appendJumpToIf(LabelID _labelId, JumpType _jumpType) override;
|
||||
|
@ -382,8 +382,11 @@ BuiltinFunctionForEVM const* EVMDialect::verbatimFunction(size_t _arguments, siz
|
||||
for (Expression const& arg: _call.arguments | ranges::views::tail | ranges::views::reverse)
|
||||
_visitExpression(arg);
|
||||
Expression const& bytecode = _call.arguments.front();
|
||||
int diff = static_cast<int>(_returnVariables) - static_cast<int>(_arguments);
|
||||
_assembly.appendVerbatim(asBytes(std::get<Literal>(bytecode).value.str()), diff);
|
||||
_assembly.appendVerbatim(
|
||||
asBytes(std::get<Literal>(bytecode).value.str()),
|
||||
_arguments,
|
||||
_returnVariables
|
||||
);
|
||||
}
|
||||
).second;
|
||||
builtinFunction.isMSize = true;
|
||||
|
@ -69,9 +69,9 @@ void NoOutputAssembly::appendLinkerSymbol(string const&)
|
||||
yulAssert(false, "Linker symbols not yet implemented.");
|
||||
}
|
||||
|
||||
void NoOutputAssembly::appendVerbatim(bytes const&, int _stackDifference)
|
||||
void NoOutputAssembly::appendVerbatim(bytes, size_t _arguments, size_t _returnVariables)
|
||||
{
|
||||
m_stackHeight += _stackDifference;
|
||||
m_stackHeight += static_cast<int>(_returnVariables - _arguments);
|
||||
}
|
||||
|
||||
void NoOutputAssembly::appendJump(int _stackDiffAfter, JumpType)
|
||||
|
@ -58,7 +58,7 @@ public:
|
||||
LabelID newLabelId() override;
|
||||
LabelID namedLabel(std::string const& _name) override;
|
||||
void appendLinkerSymbol(std::string const& _name) override;
|
||||
void appendVerbatim(bytes const& _data, int _stackDifference) override;
|
||||
void appendVerbatim(bytes _data, size_t _arguments, size_t _returnVariables) override;
|
||||
|
||||
void appendJump(int _stackDiffAfter, JumpType _jumpType) override;
|
||||
void appendJumpTo(LabelID _labelId, int _stackDiffAfter, JumpType _jumpType) override;
|
||||
|
@ -2,6 +2,6 @@
|
||||
// The optimizer assumes verbatim could contain msize,
|
||||
// so it cannot optimize the mload away.
|
||||
let x := mload(0x2000)
|
||||
verbatim_0i_0o("")
|
||||
verbatim_0i_0o("aa")
|
||||
sstore(0, 2)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user