mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Yul Backend: Get rid of heuristics for finding the matching runtime
This commit is contained in:
parent
d393624384
commit
e4f1257c83
@ -44,6 +44,8 @@ using AssemblyPointer = std::shared_ptr<Assembly>;
|
||||
class Assembly
|
||||
{
|
||||
public:
|
||||
explicit Assembly(std::string _name = std::string()):m_name(std::move(_name)) { }
|
||||
|
||||
AssemblyItem newTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(Tag, m_usedTags++); }
|
||||
AssemblyItem newPushTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(PushTag, m_usedTags++); }
|
||||
/// Returns a tag identified by the given name. Creates it if it does not yet exist.
|
||||
@ -95,6 +97,7 @@ public:
|
||||
int deposit() const { return m_deposit; }
|
||||
void adjustDeposit(int _adjustment) { m_deposit += _adjustment; assertThrow(m_deposit >= 0, InvalidDeposit, ""); }
|
||||
void setDeposit(int _deposit) { m_deposit = _deposit; assertThrow(m_deposit >= 0, InvalidDeposit, ""); }
|
||||
std::string const& name() const { return m_name; }
|
||||
|
||||
/// Changes the source location used for each appended item.
|
||||
void setSourceLocation(langutil::SourceLocation const& _location) { m_currentSourceLocation = _location; }
|
||||
@ -193,6 +196,9 @@ protected:
|
||||
mutable std::vector<size_t> m_tagPositionsInBytecode;
|
||||
|
||||
int m_deposit = 0;
|
||||
/// Internal name of the assembly object, only used with the Yul backend
|
||||
/// currently
|
||||
std::string m_name;
|
||||
|
||||
langutil::SourceLocation m_currentSourceLocation;
|
||||
public:
|
||||
|
@ -1302,7 +1302,7 @@ void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract)
|
||||
// TODO: use stack.assemble here!
|
||||
yul::MachineAssemblyObject init;
|
||||
yul::MachineAssemblyObject runtime;
|
||||
std::tie(init, runtime) = stack.assembleAndGuessRuntime();
|
||||
std::tie(init, runtime) = stack.assembleWithDeployed(IRNames::runtimeObject(_contract));
|
||||
compiledContract.object = std::move(*init.bytecode);
|
||||
compiledContract.runtimeObject = std::move(*runtime.bytecode);
|
||||
// TODO: refactor assemblyItems, runtimeAssemblyItems, generatedSources,
|
||||
|
@ -1273,7 +1273,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
|
||||
|
||||
MachineAssemblyObject object;
|
||||
MachineAssemblyObject runtimeObject;
|
||||
tie(object, runtimeObject) = stack.assembleAndGuessRuntime();
|
||||
tie(object, runtimeObject) = stack.assembleWithDeployed();
|
||||
|
||||
if (object.bytecode)
|
||||
object.bytecode->link(_inputsAndSettings.libraries);
|
||||
|
@ -199,7 +199,7 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const
|
||||
switch (_machine)
|
||||
{
|
||||
case Machine::EVM:
|
||||
return assembleAndGuessRuntime().first;
|
||||
return assembleWithDeployed().first;
|
||||
case Machine::EVM15:
|
||||
{
|
||||
MachineAssemblyObject object;
|
||||
@ -226,7 +226,7 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const
|
||||
return MachineAssemblyObject();
|
||||
}
|
||||
|
||||
pair<MachineAssemblyObject, MachineAssemblyObject> AssemblyStack::assembleAndGuessRuntime() const
|
||||
std::pair<MachineAssemblyObject, MachineAssemblyObject> AssemblyStack::assembleWithDeployed(optional<string_view> _deployName) const
|
||||
{
|
||||
yulAssert(m_analysisSuccessful, "");
|
||||
yulAssert(m_parserResult, "");
|
||||
@ -248,22 +248,39 @@ pair<MachineAssemblyObject, MachineAssemblyObject> AssemblyStack::assembleAndGue
|
||||
)
|
||||
);
|
||||
|
||||
MachineAssemblyObject runtimeObject;
|
||||
// Heuristic: If there is a single sub-assembly, this is likely the runtime object.
|
||||
if (assembly.numSubs() == 1)
|
||||
MachineAssemblyObject deployedObject;
|
||||
optional<size_t> subIndex;
|
||||
|
||||
// Pick matching assembly if name was given
|
||||
if (_deployName.has_value())
|
||||
{
|
||||
evmasm::Assembly& runtimeAssembly = assembly.sub(0);
|
||||
runtimeObject.bytecode = make_shared<evmasm::LinkerObject>(runtimeAssembly.assemble());
|
||||
runtimeObject.assembly = runtimeAssembly.assemblyString();
|
||||
runtimeObject.sourceMappings = make_unique<string>(
|
||||
for (size_t i = 0; i < assembly.numSubs(); i++)
|
||||
if (assembly.sub(i).name() == _deployName)
|
||||
{
|
||||
subIndex = i;
|
||||
break;
|
||||
}
|
||||
|
||||
solAssert(subIndex.has_value(), "Failed to find object to be deployed.");
|
||||
}
|
||||
// Otherwise use heuristic: If there is a single sub-assembly, this is likely the object to be deployed.
|
||||
else if (assembly.numSubs() == 1)
|
||||
subIndex = 0;
|
||||
|
||||
if (subIndex.has_value())
|
||||
{
|
||||
evmasm::Assembly& runtimeAssembly = assembly.sub(*subIndex);
|
||||
deployedObject.bytecode = make_shared<evmasm::LinkerObject>(runtimeAssembly.assemble());
|
||||
deployedObject.assembly = runtimeAssembly.assemblyString();
|
||||
deployedObject.sourceMappings = make_unique<string>(
|
||||
evmasm::AssemblyItem::computeSourceMapping(
|
||||
runtimeAssembly.items(),
|
||||
{{scanner().charStream() ? scanner().charStream()->name() : "", 0}}
|
||||
)
|
||||
);
|
||||
}
|
||||
return {std::move(creationObject), std::move(runtimeObject)};
|
||||
|
||||
return {std::move(creationObject), std::move(deployedObject)};
|
||||
}
|
||||
|
||||
string AssemblyStack::print() const
|
||||
|
@ -95,6 +95,12 @@ public:
|
||||
/// Only available for EVM.
|
||||
std::pair<MachineAssemblyObject, MachineAssemblyObject> assembleAndGuessRuntime() const;
|
||||
|
||||
/// Run the assembly step (should only be called after parseAndAnalyze).
|
||||
/// In addition to the value returned by @a assemble, returns
|
||||
/// a second object that is the runtime code.
|
||||
/// Only available for EVM.
|
||||
std::pair<MachineAssemblyObject, MachineAssemblyObject> assembleWithDeployed(std::optional<std::string_view> _deployeName = {}) const;
|
||||
|
||||
/// @returns the errors generated during parsing, analysis (and potentially assembly).
|
||||
langutil::ErrorList const& errors() const { return m_errors; }
|
||||
|
||||
|
@ -100,7 +100,7 @@ public:
|
||||
/// Append the assembled size as a constant.
|
||||
virtual void appendAssemblySize() = 0;
|
||||
/// Creates a new sub-assembly, which can be referenced using dataSize and dataOffset.
|
||||
virtual std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly() = 0;
|
||||
virtual std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly(std::string _name = "") = 0;
|
||||
/// Appends the offset of the given sub-assembly or data.
|
||||
virtual void appendDataOffset(std::vector<SubID> const& _subPath) = 0;
|
||||
/// Appends the size of the given sub-assembly or data.
|
||||
|
@ -140,9 +140,9 @@ void EthAssemblyAdapter::appendAssemblySize()
|
||||
m_assembly.appendProgramSize();
|
||||
}
|
||||
|
||||
pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> EthAssemblyAdapter::createSubAssembly()
|
||||
pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> EthAssemblyAdapter::createSubAssembly(string _name)
|
||||
{
|
||||
shared_ptr<evmasm::Assembly> assembly{make_shared<evmasm::Assembly>()};
|
||||
shared_ptr<evmasm::Assembly> assembly{make_shared<evmasm::Assembly>(std::move(_name))};
|
||||
auto sub = m_assembly.newSub(assembly);
|
||||
return {make_shared<EthAssemblyAdapter>(*assembly), static_cast<size_t>(sub.data())};
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ public:
|
||||
void appendJumpsub(LabelID, int, int) override;
|
||||
void appendReturnsub(int, int) override;
|
||||
void appendAssemblySize() override;
|
||||
std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly() override;
|
||||
std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly(std::string _name = {}) override;
|
||||
void appendDataOffset(std::vector<SubID> const& _subPath) override;
|
||||
void appendDataSize(std::vector<SubID> const& _subPath) override;
|
||||
SubID appendData(bytes const& _data) override;
|
||||
|
@ -196,7 +196,7 @@ void EVMAssembly::appendAssemblySize()
|
||||
m_bytecode += bytes(assemblySizeReferenceSize);
|
||||
}
|
||||
|
||||
pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> EVMAssembly::createSubAssembly()
|
||||
pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> EVMAssembly::createSubAssembly(string)
|
||||
{
|
||||
yulAssert(false, "Sub assemblies not implemented.");
|
||||
return {};
|
||||
|
@ -79,7 +79,7 @@ public:
|
||||
|
||||
/// Append the assembled size as a constant.
|
||||
void appendAssemblySize() override;
|
||||
std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly() override;
|
||||
std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly(std::string _name = "") override;
|
||||
void appendDataOffset(std::vector<SubID> const& _subPath) override;
|
||||
void appendDataSize(std::vector<SubID> const& _subPath) override;
|
||||
SubID appendData(bytes const& _data) override;
|
||||
|
@ -42,10 +42,11 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize)
|
||||
BuiltinContext context;
|
||||
context.currentObject = &_object;
|
||||
|
||||
|
||||
for (auto const& subNode: _object.subObjects)
|
||||
if (auto* subObject = dynamic_cast<Object*>(subNode.get()))
|
||||
{
|
||||
auto subAssemblyAndID = m_assembly.createSubAssembly();
|
||||
auto subAssemblyAndID = m_assembly.createSubAssembly(subObject->name.str());
|
||||
context.subIDs[subObject->name] = subAssemblyAndID.second;
|
||||
subObject->subId = subAssemblyAndID.second;
|
||||
compile(*subObject, *subAssemblyAndID.first, m_dialect, m_evm15, _optimize);
|
||||
|
@ -127,7 +127,7 @@ void NoOutputAssembly::appendAssemblySize()
|
||||
appendInstruction(evmasm::Instruction::PUSH1);
|
||||
}
|
||||
|
||||
pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> NoOutputAssembly::createSubAssembly()
|
||||
pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> NoOutputAssembly::createSubAssembly(std::string)
|
||||
{
|
||||
yulAssert(false, "Sub assemblies not implemented.");
|
||||
return {};
|
||||
|
@ -67,7 +67,7 @@ public:
|
||||
void appendReturnsub(int _returns, int _stackDiffAfter) override;
|
||||
|
||||
void appendAssemblySize() override;
|
||||
std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly() override;
|
||||
std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly(std::string _name = "") override;
|
||||
void appendDataOffset(std::vector<SubID> const& _subPath) override;
|
||||
void appendDataSize(std::vector<SubID> const& _subPath) override;
|
||||
SubID appendData(bytes const& _data) override;
|
||||
|
Loading…
Reference in New Issue
Block a user