diff --git a/Changelog.md b/Changelog.md index e75e2c710..c938c44b0 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ Language Features: Compiler Features: * Yul Optimizer: Remove ``mstore`` and ``sstore`` operations if the slot already contains the same value. + * Yul: Emit immutable references for pure yul code when requested. diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 39ed7c10f..5ccf2d447 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1461,36 +1461,36 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) stack.optimize(); MachineAssemblyObject object; - MachineAssemblyObject runtimeObject; - tie(object, runtimeObject) = stack.assembleWithDeployed(); + MachineAssemblyObject deployedObject; + tie(object, deployedObject) = stack.assembleWithDeployed(); if (object.bytecode) object.bytecode->link(_inputsAndSettings.libraries); - if (runtimeObject.bytecode) - runtimeObject.bytecode->link(_inputsAndSettings.libraries); + if (deployedObject.bytecode) + deployedObject.bytecode->link(_inputsAndSettings.libraries); - for (string const& objectKind: vector{"bytecode", "deployedBytecode"}) + for (auto&& [kind, isDeployed]: {make_pair("bytecode"s, false), make_pair("deployedBytecode"s, true)}) if (isArtifactRequested( _inputsAndSettings.outputSelection, sourceName, contractName, - evmObjectComponents(objectKind), + evmObjectComponents(kind), wildcardMatchesExperimental )) { - MachineAssemblyObject const& o = objectKind == "bytecode" ? object : runtimeObject; + MachineAssemblyObject const& o = isDeployed ? deployedObject : object; if (o.bytecode) - output["contracts"][sourceName][contractName]["evm"][objectKind] = + output["contracts"][sourceName][contractName]["evm"][kind] = collectEVMObject( *o.bytecode, o.sourceMappings.get(), Json::arrayValue, - false, - [&](string const& _element) { return isArtifactRequested( + isDeployed, + [&, kind = kind](string const& _element) { return isArtifactRequested( _inputsAndSettings.outputSelection, sourceName, contractName, - "evm." + objectKind + "." + _element, + "evm." + kind + "." + _element, wildcardMatchesExperimental ); } ); diff --git a/test/cmdlineTests/standard_yul_immutable_references/args b/test/cmdlineTests/standard_yul_immutable_references/args new file mode 100644 index 000000000..d13a8ac44 --- /dev/null +++ b/test/cmdlineTests/standard_yul_immutable_references/args @@ -0,0 +1 @@ +--pretty-json diff --git a/test/cmdlineTests/standard_yul_immutable_references/input.json b/test/cmdlineTests/standard_yul_immutable_references/input.json new file mode 100644 index 000000000..aedbae868 --- /dev/null +++ b/test/cmdlineTests/standard_yul_immutable_references/input.json @@ -0,0 +1,22 @@ +{ + "language": "Yul", + "sources": + { + "A": + { + "content": "object \"YulTest\" { code { let size := datasize(\"runtime\") datacopy(0, dataoffset(\"runtime\"), size) setimmutable(0, \"test\", 1) return(0, size) } object \"runtime\" { code { mstore(0, loadimmutable(\"test\")) return(0, 0x20) } }}" + } + }, + "settings": + { + "outputSelection": { + "A": { + "*": [ + "evm.deployedBytecode.immutableReferences", + "evm.bytecode", + "evm.deployedBytecode" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_yul_immutable_references/output.json b/test/cmdlineTests/standard_yul_immutable_references/output.json new file mode 100644 index 000000000..42361097d --- /dev/null +++ b/test/cmdlineTests/standard_yul_immutable_references/output.json @@ -0,0 +1,52 @@ +{ + "contracts": + { + "A": + { + "YulTest": + { + "evm": + { + "bytecode": + { + "functionDebugData": {}, + "generatedSources": [], + "linkReferences": {}, + "object": "60298060156000396001600060010152806000f3fe7f000000000000000000000000000000000000000000000000000000000000000060005260206000f3", + "opcodes": "PUSH1 0x29 DUP1 PUSH1 0x15 PUSH1 0x0 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH1 0x1 ADD MSTORE DUP1 PUSH1 0x0 RETURN INVALID PUSH32 0x0 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 RETURN ", + "sourceMap": "42:19:0:-:0;100:4;77:21;74:1;65:40;133:1;122;109:26;;;149:4;146:1;139:15" + }, + "deployedBytecode": + { + "functionDebugData": {}, + "generatedSources": [], + "immutableReferences": + { + "test": + [ + { + "length": 32, + "start": 1 + } + ] + }, + "linkReferences": {}, + "object": "7f000000000000000000000000000000000000000000000000000000000000000060005260206000f3", + "opcodes": "PUSH32 0x0 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 RETURN ", + "sourceMap": "203:21:0:-:0;200:1;193:32;241:4;238:1;231:15" + } + } + } + } + }, + "errors": + [ + { + "component": "general", + "formattedMessage": "Yul is still experimental. Please use the output with care.", + "message": "Yul is still experimental. Please use the output with care.", + "severity": "warning", + "type": "Warning" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_object_name/output.json b/test/cmdlineTests/standard_yul_object_name/output.json index f2e85ed7c..45280c8a1 100644 --- a/test/cmdlineTests/standard_yul_object_name/output.json +++ b/test/cmdlineTests/standard_yul_object_name/output.json @@ -23,7 +23,7 @@ sub_0: assembly { /* \"A\":137:149 */ revert } -","bytecode":{"functionDebugData":{},"generatedSources":[],"linkReferences":{},"object":"","opcodes":"","sourceMap":""},"deployedBytecode":{"functionDebugData":{},"generatedSources":[],"linkReferences":{},"object":"","opcodes":"","sourceMap":""}},"ir":"object \"NamedObject\" { +","bytecode":{"functionDebugData":{},"generatedSources":[],"linkReferences":{},"object":"","opcodes":"","sourceMap":""},"deployedBytecode":{"functionDebugData":{},"generatedSources":[],"immutableReferences":{},"linkReferences":{},"object":"","opcodes":"","sourceMap":""}},"ir":"object \"NamedObject\" { code { let x := dataoffset(\"DataName\") sstore(add(x, 0), 0)