Skip to content

Commit

Permalink
Merge pull request #15623 from ethereum/fix-evm-output-eager-evaluation
Browse files Browse the repository at this point in the history
Fix unecessary eager evaluation of `evm.*` outputs in Standard JSON
  • Loading branch information
cameel authored Dec 10, 2024
2 parents a62a455 + 11d8fdd commit ea52aca
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 113 deletions.
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Compiler Features:

Bugfixes:
* General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts.
* Standard JSON Interface: Fix ``generatedSources`` and ``sourceMap`` being generated internally even when not requested.


### 0.8.28 (2024-10-09)
Expand Down
212 changes: 108 additions & 104 deletions libsolidity/interface/StandardCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,33 +374,6 @@ Json formatImmutableReferences(std::map<u256, evmasm::LinkerObject::ImmutableRef
return ret;
}

Json collectEVMObject(
langutil::EVMVersion _evmVersion,
evmasm::LinkerObject const& _object,
std::string const* _sourceMap,
Json _generatedSources,
bool _runtimeObject,
std::function<bool(std::string)> const& _artifactRequested
)
{
Json output;
if (_artifactRequested("object"))
output["object"] = _object.toHex();
if (_artifactRequested("opcodes"))
output["opcodes"] = evmasm::disassemble(_object.bytecode, _evmVersion);
if (_artifactRequested("sourceMap"))
output["sourceMap"] = _sourceMap ? *_sourceMap : "";
if (_artifactRequested("functionDebugData"))
output["functionDebugData"] = StandardCompiler::formatFunctionDebugData(_object.functionDebugData);
if (_artifactRequested("linkReferences"))
output["linkReferences"] = formatLinkReferences(_object.linkReferences);
if (_runtimeObject && _artifactRequested("immutableReferences"))
output["immutableReferences"] = formatImmutableReferences(_object.immutableReferences);
if (_artifactRequested("generatedSources"))
output["generatedSources"] = std::move(_generatedSources);
return output;
}

std::optional<Json> checkKeys(Json const& _input, std::set<std::string> const& _keys, std::string const& _name)
{
if (!_input.empty() && !_input.is_object())
Expand Down Expand Up @@ -1246,22 +1219,24 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in
evmObjectComponents("bytecode"),
wildcardMatchesExperimental
))
evmData["bytecode"] = collectEVMObject(
_inputsAndSettings.evmVersion,
stack.object(sourceName),
stack.sourceMapping(sourceName),
{},
false, // _runtimeObject
[&](std::string const& _element) {
return isArtifactRequested(
_inputsAndSettings.outputSelection,
sourceName,
"",
"evm.bytecode." + _element,
wildcardMatchesExperimental
);
}
);
{
auto const evmCreationArtifactRequested = [&](std::string const& _element) {
return isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, "", "evm.bytecode." + _element, wildcardMatchesExperimental);
};

Json creationJSON;
if (evmCreationArtifactRequested("object"))
creationJSON["object"] = stack.object(sourceName).toHex();
if (evmCreationArtifactRequested("opcodes"))
creationJSON["opcodes"] = evmasm::disassemble(stack.object(sourceName).bytecode, _inputsAndSettings.evmVersion);
if (evmCreationArtifactRequested("sourceMap"))
creationJSON["sourceMap"] = stack.sourceMapping(sourceName) ? *stack.sourceMapping(sourceName) : "";
if (evmCreationArtifactRequested("functionDebugData"))
creationJSON["functionDebugData"] = formatFunctionDebugData(stack.object(sourceName).functionDebugData);
if (evmCreationArtifactRequested("linkReferences"))
creationJSON["linkReferences"] = formatLinkReferences(stack.object(sourceName).linkReferences);
evmData["bytecode"] = creationJSON;
}

if (isArtifactRequested(
_inputsAndSettings.outputSelection,
Expand All @@ -1270,22 +1245,26 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in
evmObjectComponents("deployedBytecode"),
wildcardMatchesExperimental
))
evmData["deployedBytecode"] = collectEVMObject(
_inputsAndSettings.evmVersion,
stack.runtimeObject(sourceName),
stack.runtimeSourceMapping(sourceName),
{},
true, // _runtimeObject
[&](std::string const& _element) {
return isArtifactRequested(
_inputsAndSettings.outputSelection,
sourceName,
"",
"evm.deployedBytecode." + _element,
wildcardMatchesExperimental
);
}
);
{
auto const evmDeployedArtifactRequested = [&](std::string const& _element) {
return isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, "", "evm.deployedBytecode." + _element, wildcardMatchesExperimental);
};

Json deployedJSON;
if (evmDeployedArtifactRequested("object"))
deployedJSON["object"] = stack.runtimeObject(sourceName).toHex();
if (evmDeployedArtifactRequested("opcodes"))
deployedJSON["opcodes"] = evmasm::disassemble(stack.runtimeObject(sourceName).bytecode, _inputsAndSettings.evmVersion);
if (evmDeployedArtifactRequested("sourceMap"))
deployedJSON["sourceMap"] = stack.runtimeSourceMapping(sourceName) ? *stack.runtimeSourceMapping(sourceName) : "";
if (evmDeployedArtifactRequested("functionDebugData"))
deployedJSON["functionDebugData"] = formatFunctionDebugData(stack.runtimeObject(sourceName).functionDebugData);
if (evmDeployedArtifactRequested("linkReferences"))
deployedJSON["linkReferences"] = formatLinkReferences(stack.runtimeObject(sourceName).linkReferences);
if (evmDeployedArtifactRequested("immutableReferences"))
deployedJSON["immutableReferences"] = formatImmutableReferences(stack.runtimeObject(sourceName).immutableReferences);
evmData["deployedBytecode"] = deployedJSON;
}

Json contractData;
if (!evmData.empty())
Expand Down Expand Up @@ -1506,20 +1485,26 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu
evmObjectComponents("bytecode"),
wildcardMatchesExperimental
))
evmData["bytecode"] = collectEVMObject(
_inputsAndSettings.evmVersion,
compilerStack.object(contractName),
compilerStack.sourceMapping(contractName),
compilerStack.generatedSources(contractName),
false,
[&](std::string const& _element) { return isArtifactRequested(
_inputsAndSettings.outputSelection,
file,
name,
"evm.bytecode." + _element,
wildcardMatchesExperimental
); }
);
{
auto const evmCreationArtifactRequested = [&](std::string const& _element) {
return isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.bytecode." + _element, wildcardMatchesExperimental);
};

Json creationJSON;
if (evmCreationArtifactRequested("object"))
creationJSON["object"] = compilerStack.object(contractName).toHex();
if (evmCreationArtifactRequested("opcodes"))
creationJSON["opcodes"] = evmasm::disassemble(compilerStack.object(contractName).bytecode, _inputsAndSettings.evmVersion);
if (evmCreationArtifactRequested("sourceMap"))
creationJSON["sourceMap"] = compilerStack.sourceMapping(contractName) ? *compilerStack.sourceMapping(contractName) : "";
if (evmCreationArtifactRequested("functionDebugData"))
creationJSON["functionDebugData"] = formatFunctionDebugData(compilerStack.object(contractName).functionDebugData);
if (evmCreationArtifactRequested("linkReferences"))
creationJSON["linkReferences"] = formatLinkReferences(compilerStack.object(contractName).linkReferences);
if (evmCreationArtifactRequested("generatedSources"))
creationJSON["generatedSources"] = compilerStack.generatedSources(contractName, /* _runtime */ false);
evmData["bytecode"] = creationJSON;
}

if (compilationSuccess && isArtifactRequested(
_inputsAndSettings.outputSelection,
Expand All @@ -1528,20 +1513,28 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu
evmObjectComponents("deployedBytecode"),
wildcardMatchesExperimental
))
evmData["deployedBytecode"] = collectEVMObject(
_inputsAndSettings.evmVersion,
compilerStack.runtimeObject(contractName),
compilerStack.runtimeSourceMapping(contractName),
compilerStack.generatedSources(contractName, true),
true,
[&](std::string const& _element) { return isArtifactRequested(
_inputsAndSettings.outputSelection,
file,
name,
"evm.deployedBytecode." + _element,
wildcardMatchesExperimental
); }
);
{
auto const evmDeployedArtifactRequested = [&](std::string const& _element) {
return isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.deployedBytecode." + _element, wildcardMatchesExperimental);
};

Json deployedJSON;
if (evmDeployedArtifactRequested("object"))
deployedJSON["object"] = compilerStack.runtimeObject(contractName).toHex();
if (evmDeployedArtifactRequested("opcodes"))
deployedJSON["opcodes"] = evmasm::disassemble(compilerStack.runtimeObject(contractName).bytecode, _inputsAndSettings.evmVersion);
if (evmDeployedArtifactRequested("sourceMap"))
deployedJSON["sourceMap"] = compilerStack.runtimeSourceMapping(contractName) ? *compilerStack.runtimeSourceMapping(contractName) : "";
if (evmDeployedArtifactRequested("functionDebugData"))
deployedJSON["functionDebugData"] = formatFunctionDebugData(compilerStack.runtimeObject(contractName).functionDebugData);
if (evmDeployedArtifactRequested("linkReferences"))
deployedJSON["linkReferences"] = formatLinkReferences(compilerStack.runtimeObject(contractName).linkReferences);
if (evmDeployedArtifactRequested("immutableReferences"))
deployedJSON["immutableReferences"] = formatImmutableReferences(compilerStack.runtimeObject(contractName).immutableReferences);
if (evmDeployedArtifactRequested("generatedSources"))
deployedJSON["generatedSources"] = compilerStack.generatedSources(contractName, /* _runtime */ true);
evmData["deployedBytecode"] = deployedJSON;
}

if (!evmData.empty())
contractData["evm"] = evmData;
Expand Down Expand Up @@ -1668,23 +1661,34 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
wildcardMatchesExperimental
))
{
MachineAssemblyObject const& o = isDeployed ? deployedObject : object;
if (o.bytecode)
output["contracts"][sourceName][contractName]["evm"][kind] =
collectEVMObject(
_inputsAndSettings.evmVersion,
*o.bytecode,
o.sourceMappings.get(),
Json::array(),
isDeployed,
[&, kind = kind](std::string const& _element) { return isArtifactRequested(
_inputsAndSettings.outputSelection,
sourceName,
contractName,
"evm." + kind + "." + _element,
wildcardMatchesExperimental
); }
);
auto const evmArtifactRequested = [&](std::string const& _kind, std::string const& _element) {
return isArtifactRequested(
_inputsAndSettings.outputSelection,
sourceName,
contractName,
"evm." + _kind + "." + _element,
wildcardMatchesExperimental
);
};

MachineAssemblyObject const& selectedObject = isDeployed ? deployedObject : object;
if (selectedObject.bytecode)
{
Json bytecodeJSON;
if (evmArtifactRequested(kind, "object"))
bytecodeJSON["object"] = selectedObject.bytecode->toHex();
if (evmArtifactRequested(kind, "opcodes"))
bytecodeJSON["opcodes"] = evmasm::disassemble(selectedObject.bytecode->bytecode, _inputsAndSettings.evmVersion);
if (evmArtifactRequested(kind, "sourceMap"))
bytecodeJSON["sourceMap"] = selectedObject.sourceMappings ? *selectedObject.sourceMappings : "";
if (evmArtifactRequested(kind, "functionDebugData"))
bytecodeJSON["functionDebugData"] = formatFunctionDebugData(selectedObject.bytecode->functionDebugData);
if (evmArtifactRequested(kind, "linkReferences"))
bytecodeJSON["linkReferences"] = formatLinkReferences(selectedObject.bytecode->linkReferences);
if (isDeployed && evmArtifactRequested(kind, "immutableReferences"))
bytecodeJSON["immutableReferences"] = formatImmutableReferences(selectedObject.bytecode->immutableReferences);
output["contracts"][sourceName][contractName]["evm"][kind] = bytecodeJSON;
}
}

if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "irOptimized", wildcardMatchesExperimental))
Expand Down
1 change: 0 additions & 1 deletion test/cmdlineTests/standard_yul/output.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
",
"bytecode": {
"functionDebugData": {},
"generatedSources": [],
"linkReferences": {},
"object": "<BYTECODE REMOVED>",
"opcodes":"<OPCODES REMOVED>",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@
"evm": {
"bytecode": {
"functionDebugData": {},
"generatedSources": [],
"linkReferences": {},
"object": "<BYTECODE REMOVED>",
"opcodes":"<OPCODES REMOVED>",
"sourceMap":"<SOURCEMAP REMOVED>"
},
"deployedBytecode": {
"functionDebugData": {},
"generatedSources": [],
"immutableReferences": {
"test": [
{
Expand Down
1 change: 0 additions & 1 deletion test/cmdlineTests/standard_yul_object/output.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ data_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 616263
",
"bytecode": {
"functionDebugData": {},
"generatedSources": [],
"linkReferences": {},
"object": "<BYTECODE REMOVED>",
"opcodes":"<OPCODES REMOVED>",
Expand Down
2 changes: 0 additions & 2 deletions test/cmdlineTests/standard_yul_object_name/output.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,13 @@ sub_0: assembly {
",
"bytecode": {
"functionDebugData": {},
"generatedSources": [],
"linkReferences": {},
"object": "<BYTECODE REMOVED>",
"opcodes":"<OPCODES REMOVED>",
"sourceMap":"<SOURCEMAP REMOVED>"
},
"deployedBytecode": {
"functionDebugData": {},
"generatedSources": [],
"immutableReferences": {},
"linkReferences": {},
"object": "<BYTECODE REMOVED>",
Expand Down
1 change: 0 additions & 1 deletion test/cmdlineTests/standard_yul_optimiserSteps/output.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
",
"bytecode": {
"functionDebugData": {},
"generatedSources": [],
"linkReferences": {},
"object": "<BYTECODE REMOVED>",
"opcodes":"<OPCODES REMOVED>",
Expand Down
1 change: 0 additions & 1 deletion test/cmdlineTests/standard_yul_optimized/output.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
",
"bytecode": {
"functionDebugData": {},
"generatedSources": [],
"linkReferences": {},
"object": "<BYTECODE REMOVED>",
"opcodes":"<OPCODES REMOVED>",
Expand Down
1 change: 0 additions & 1 deletion test/cmdlineTests/standard_yul_output_warning/output.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
",
"bytecode": {
"functionDebugData": {},
"generatedSources": [],
"linkReferences": {},
"object": "<BYTECODE REMOVED>",
"opcodes":"<OPCODES REMOVED>",
Expand Down

0 comments on commit ea52aca

Please sign in to comment.