mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8912 from ethereum/runtimeYul
Provide runtime object in Yul mode.
This commit is contained in:
commit
c3d87a0091
@ -52,6 +52,7 @@ public:
|
|||||||
AssemblyItem newSub(AssemblyPointer const& _sub) { m_subs.push_back(_sub); return AssemblyItem(PushSub, m_subs.size() - 1); }
|
AssemblyItem newSub(AssemblyPointer const& _sub) { m_subs.push_back(_sub); return AssemblyItem(PushSub, m_subs.size() - 1); }
|
||||||
Assembly const& sub(size_t _sub) const { return *m_subs.at(_sub); }
|
Assembly const& sub(size_t _sub) const { return *m_subs.at(_sub); }
|
||||||
Assembly& sub(size_t _sub) { return *m_subs.at(_sub); }
|
Assembly& sub(size_t _sub) { return *m_subs.at(_sub); }
|
||||||
|
size_t numSubs() const { return m_subs.size(); }
|
||||||
AssemblyItem newPushSubSize(u256 const& _subId) { return AssemblyItem(PushSubSize, _subId); }
|
AssemblyItem newPushSubSize(u256 const& _subId) { return AssemblyItem(PushSubSize, _subId); }
|
||||||
AssemblyItem newPushLibraryAddress(std::string const& _identifier);
|
AssemblyItem newPushLibraryAddress(std::string const& _identifier);
|
||||||
AssemblyItem newPushImmutable(std::string const& _identifier);
|
AssemblyItem newPushImmutable(std::string const& _identifier);
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <libevmasm/Instruction.h>
|
#include <libevmasm/Instruction.h>
|
||||||
#include <libsolutil/JSON.h>
|
#include <libsolutil/JSON.h>
|
||||||
#include <libsolutil/Keccak256.h>
|
#include <libsolutil/Keccak256.h>
|
||||||
|
#include <libsolutil/CommonData.h>
|
||||||
|
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
|
||||||
@ -1127,16 +1128,29 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
|
|||||||
|
|
||||||
stack.optimize();
|
stack.optimize();
|
||||||
|
|
||||||
MachineAssemblyObject object = stack.assemble(AssemblyStack::Machine::EVM);
|
MachineAssemblyObject object;
|
||||||
|
MachineAssemblyObject runtimeObject;
|
||||||
|
tie(object, runtimeObject) = stack.assembleAndGuessRuntime();
|
||||||
|
|
||||||
if (isArtifactRequested(
|
for (string const& objectKind: vector<string>{"bytecode", "deployedBytecode"})
|
||||||
_inputsAndSettings.outputSelection,
|
{
|
||||||
sourceName,
|
auto artifacts = util::applyMap(
|
||||||
contractName,
|
vector<string>{"", ".object", ".opcodes", ".sourceMap", ".linkReferences"},
|
||||||
{ "evm.bytecode", "evm.bytecode.object", "evm.bytecode.opcodes", "evm.bytecode.sourceMap", "evm.bytecode.linkReferences" },
|
[&](auto const& _s) { return "evm." + objectKind + _s; }
|
||||||
wildcardMatchesExperimental
|
);
|
||||||
))
|
if (isArtifactRequested(
|
||||||
output["contracts"][sourceName][contractName]["evm"]["bytecode"] = collectEVMObject(*object.bytecode, object.sourceMappings.get(), false);
|
_inputsAndSettings.outputSelection,
|
||||||
|
sourceName,
|
||||||
|
contractName,
|
||||||
|
artifacts,
|
||||||
|
wildcardMatchesExperimental
|
||||||
|
))
|
||||||
|
{
|
||||||
|
MachineAssemblyObject const& o = objectKind == "bytecode" ? object : runtimeObject;
|
||||||
|
if (o.bytecode)
|
||||||
|
output["contracts"][sourceName][contractName]["evm"][objectKind] = collectEVMObject(*o.bytecode, o.sourceMappings.get(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "irOptimized", wildcardMatchesExperimental))
|
if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "irOptimized", wildcardMatchesExperimental))
|
||||||
output["contracts"][sourceName][contractName]["irOptimized"] = stack.print();
|
output["contracts"][sourceName][contractName]["irOptimized"] = stack.print();
|
||||||
|
@ -198,22 +198,7 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const
|
|||||||
switch (_machine)
|
switch (_machine)
|
||||||
{
|
{
|
||||||
case Machine::EVM:
|
case Machine::EVM:
|
||||||
{
|
return assembleAndGuessRuntime().first;
|
||||||
MachineAssemblyObject object;
|
|
||||||
evmasm::Assembly assembly;
|
|
||||||
EthAssemblyAdapter adapter(assembly);
|
|
||||||
compileEVM(adapter, false, m_optimiserSettings.optimizeStackAllocation);
|
|
||||||
object.bytecode = make_shared<evmasm::LinkerObject>(assembly.assemble());
|
|
||||||
yulAssert(object.bytecode->immutableReferences.empty(), "Leftover immutables.");
|
|
||||||
object.assembly = assembly.assemblyString();
|
|
||||||
object.sourceMappings = make_unique<string>(
|
|
||||||
evmasm::AssemblyItem::computeSourceMapping(
|
|
||||||
assembly.items(),
|
|
||||||
{{scanner().charStream() ? scanner().charStream()->name() : "", 0}}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
case Machine::EVM15:
|
case Machine::EVM15:
|
||||||
{
|
{
|
||||||
MachineAssemblyObject object;
|
MachineAssemblyObject object;
|
||||||
@ -240,6 +225,46 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const
|
|||||||
return MachineAssemblyObject();
|
return MachineAssemblyObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pair<MachineAssemblyObject, MachineAssemblyObject> AssemblyStack::assembleAndGuessRuntime() const
|
||||||
|
{
|
||||||
|
yulAssert(m_analysisSuccessful, "");
|
||||||
|
yulAssert(m_parserResult, "");
|
||||||
|
yulAssert(m_parserResult->code, "");
|
||||||
|
yulAssert(m_parserResult->analysisInfo, "");
|
||||||
|
|
||||||
|
evmasm::Assembly assembly;
|
||||||
|
EthAssemblyAdapter adapter(assembly);
|
||||||
|
compileEVM(adapter, false, m_optimiserSettings.optimizeStackAllocation);
|
||||||
|
|
||||||
|
MachineAssemblyObject creationObject;
|
||||||
|
creationObject.bytecode = make_shared<evmasm::LinkerObject>(assembly.assemble());
|
||||||
|
yulAssert(creationObject.bytecode->immutableReferences.empty(), "Leftover immutables.");
|
||||||
|
creationObject.assembly = assembly.assemblyString();
|
||||||
|
creationObject.sourceMappings = make_unique<string>(
|
||||||
|
evmasm::AssemblyItem::computeSourceMapping(
|
||||||
|
assembly.items(),
|
||||||
|
{{scanner().charStream() ? scanner().charStream()->name() : "", 0}}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
MachineAssemblyObject runtimeObject;
|
||||||
|
// Heuristic: If there is a single sub-assembly, this is likely the runtime object.
|
||||||
|
if (assembly.numSubs() == 1)
|
||||||
|
{
|
||||||
|
evmasm::Assembly& runtimeAssembly = assembly.sub(0);
|
||||||
|
runtimeObject.bytecode = make_shared<evmasm::LinkerObject>(runtimeAssembly.assemble());
|
||||||
|
runtimeObject.assembly = runtimeAssembly.assemblyString();
|
||||||
|
runtimeObject.sourceMappings = make_unique<string>(
|
||||||
|
evmasm::AssemblyItem::computeSourceMapping(
|
||||||
|
runtimeAssembly.items(),
|
||||||
|
{{scanner().charStream() ? scanner().charStream()->name() : "", 0}}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return {std::move(creationObject), std::move(runtimeObject)};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
string AssemblyStack::print() const
|
string AssemblyStack::print() const
|
||||||
{
|
{
|
||||||
yulAssert(m_parserResult, "");
|
yulAssert(m_parserResult, "");
|
||||||
|
@ -88,6 +88,12 @@ public:
|
|||||||
/// Run the assembly step (should only be called after parseAndAnalyze).
|
/// Run the assembly step (should only be called after parseAndAnalyze).
|
||||||
MachineAssemblyObject assemble(Machine _machine) const;
|
MachineAssemblyObject assemble(Machine _machine) 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 guessed to be the runtime code.
|
||||||
|
/// Only available for EVM.
|
||||||
|
std::pair<MachineAssemblyObject, MachineAssemblyObject> assembleAndGuessRuntime() const;
|
||||||
|
|
||||||
/// @returns the errors generated during parsing, analysis (and potentially assembly).
|
/// @returns the errors generated during parsing, analysis (and potentially assembly).
|
||||||
langutil::ErrorList const& errors() const { return m_errors; }
|
langutil::ErrorList const& errors() const { return m_errors; }
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ sub_0: assembly {
|
|||||||
/* \"A\":137:149 */
|
/* \"A\":137:149 */
|
||||||
revert
|
revert
|
||||||
}
|
}
|
||||||
","bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}},"ir":"object \"NamedObject\" {
|
","bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"},"deployedBytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}},"ir":"object \"NamedObject\" {
|
||||||
code {
|
code {
|
||||||
let x := dataoffset(\"DataName\")
|
let x := dataoffset(\"DataName\")
|
||||||
sstore(add(x, 0), 0)
|
sstore(add(x, 0), 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user