@@ -165,21 +165,28 @@ bool hashMatchesContent(std::string const& _hash, std::string const& _content)
165165
166166bool isArtifactRequested (Json const & _outputSelection, std::string const & _artifact, bool _wildcardMatchesExperimental)
167167{
168- static std::set<std::string> experimental{" ir" , " irAst" , " irOptimized" , " irOptimizedAst" , " yulCFGJson" };
168+ static std::set<std::string> experimental{" ir" , " irAst" , " irOptimized" , " irOptimizedAst" , " yulCFGJson" , " ethdebug " };
169169 for (auto const & selectedArtifactJson: _outputSelection)
170170 {
171171 std::string const & selectedArtifact = selectedArtifactJson.get <std::string>();
172172 if (
173173 _artifact == selectedArtifact ||
174174 boost::algorithm::starts_with (_artifact, selectedArtifact + " ." )
175175 )
176+ {
177+ if (_artifact.find (" ethdebug" ) != std::string::npos)
178+ // only accept exact matches for ethdebug, e.g. evm.bytecode.ethdebug
179+ return selectedArtifact == _artifact;
176180 return true ;
181+ }
177182 else if (selectedArtifact == " *" )
178183 {
179184 // TODO: yulCFGJson is only experimental now, so it should not be matched by "*".
180185 if (_artifact == " yulCFGJson" )
181186 return false ;
182187 // "ir", "irOptimized" can only be matched by "*" if activated.
188+ if (_artifact.find (" ethdebug" ) != std::string::npos)
189+ return false ;
183190 if (experimental.count (_artifact) == 0 || _wildcardMatchesExperimental)
184191 return true ;
185192 }
@@ -237,7 +244,7 @@ bool isArtifactRequested(Json const& _outputSelection, std::string const& _file,
237244std::vector<std::string> evmObjectComponents (std::string const & _objectKind)
238245{
239246 solAssert (_objectKind == " bytecode" || _objectKind == " deployedBytecode" , " " );
240- std::vector<std::string> components{" " , " .object" , " .opcodes" , " .sourceMap" , " .functionDebugData" , " .generatedSources" , " .linkReferences" };
247+ std::vector<std::string> components{" " , " .object" , " .opcodes" , " .sourceMap" , " .functionDebugData" , " .generatedSources" , " .linkReferences" , " .ethdebug " };
241248 if (_objectKind == " deployedBytecode" )
242249 components.push_back (" .immutableReferences" );
243250 return util::applyMap (components, [&](auto const & _s) { return " evm." + _objectKind + _s; });
@@ -253,7 +260,7 @@ bool isBinaryRequested(Json const& _outputSelection)
253260 static std::vector<std::string> const outputsThatRequireBinaries = std::vector<std::string>{
254261 " *" ,
255262 " ir" , " irAst" , " irOptimized" , " irOptimizedAst" , " yulCFGJson" ,
256- " evm.gasEstimates" , " evm.legacyAssembly" , " evm.assembly"
263+ " evm.gasEstimates" , " evm.legacyAssembly" , " evm.assembly" , " ethdebug "
257264 } + evmObjectComponents (" bytecode" ) + evmObjectComponents (" deployedBytecode" );
258265
259266 for (auto const & fileRequests: _outputSelection)
@@ -283,6 +290,21 @@ bool isEvmBytecodeRequested(Json const& _outputSelection)
283290 return false ;
284291}
285292
293+ // / @returns true if ethdebug was requested.
294+ bool isEthdebugRequested (Json const & _outputSelection)
295+ {
296+ if (!_outputSelection.is_object ())
297+ return false ;
298+
299+ for (auto const & fileRequests: _outputSelection)
300+ for (auto const & requests: fileRequests)
301+ for (auto const & request: requests)
302+ if (request == " evm.bytecode.ethdebug" || request == " evm.deployedBytecode.ethdebug" )
303+ return true ;
304+
305+ return false ;
306+ }
307+
286308// / @returns The set of selected contracts, along with their compiler pipeline configuration, based
287309// / on outputs requested in the JSON. Translates wildcards to the ones understood by CompilerStack.
288310// / Note that as an exception, '*' does not yet match "ir", "irAst", "irOptimized" or "irOptimizedAst".
@@ -1152,6 +1174,35 @@ std::variant<StandardCompiler::InputsAndSettings, Json> StandardCompiler::parseI
11521174 ret.modelCheckerSettings .timeout = modelCheckerSettings[" timeout" ].get <Json::number_unsigned_t >();
11531175 }
11541176
1177+ if ((ret.debugInfoSelection .has_value () && ret.debugInfoSelection ->ethdebug ) || isEthdebugRequested (ret.outputSelection ))
1178+ {
1179+ if (ret.language != " Solidity" && ret.language != " Yul" )
1180+ return formatFatalError (Error::Type::FatalError, " 'settings.debug.debugInfo' 'ethdebug' is only supported for languages 'Solidity' and 'Yul'." );
1181+ }
1182+
1183+ if (isEthdebugRequested (ret.outputSelection ))
1184+ {
1185+ if (ret.language == " Solidity" && !ret.viaIR )
1186+ return formatFatalError (Error::Type::FatalError, " 'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set." );
1187+
1188+ if (!ret.debugInfoSelection .has_value ())
1189+ {
1190+ ret.debugInfoSelection = DebugInfoSelection::Default ();
1191+ ret.debugInfoSelection ->enable (" ethdebug" );
1192+ }
1193+ else
1194+ {
1195+ if (!ret.debugInfoSelection ->ethdebug && ret.language == " Solidity" )
1196+ return formatFatalError (Error::Type::FatalError, " 'ethdebug' needs to be enabled in 'settings.debug.debugInfo', if 'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' was selected as output." );
1197+ }
1198+ }
1199+
1200+ if (
1201+ ret.debugInfoSelection .has_value () && ret.debugInfoSelection ->ethdebug && ret.language == " Solidity" &&
1202+ !pipelineConfig (ret.outputSelection )[" " ][" " ].irCodegen && !isEthdebugRequested (ret.outputSelection )
1203+ )
1204+ return formatFatalError (Error::Type::FatalError, " 'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' was selected." );
1205+
11551206 return {std::move (ret)};
11561207}
11571208
@@ -1235,6 +1286,8 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in
12351286 creationJSON[" functionDebugData" ] = formatFunctionDebugData (stack.object (sourceName).functionDebugData );
12361287 if (evmCreationArtifactRequested (" linkReferences" ))
12371288 creationJSON[" linkReferences" ] = formatLinkReferences (stack.object (sourceName).linkReferences );
1289+ if (evmCreationArtifactRequested (" ethdebug" ))
1290+ creationJSON[" ethdebug" ] = stack.ethdebug (sourceName, false );
12381291 evmData[" bytecode" ] = creationJSON;
12391292 }
12401293
@@ -1263,6 +1316,8 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in
12631316 deployedJSON[" linkReferences" ] = formatLinkReferences (stack.runtimeObject (sourceName).linkReferences );
12641317 if (evmDeployedArtifactRequested (" immutableReferences" ))
12651318 deployedJSON[" immutableReferences" ] = formatImmutableReferences (stack.runtimeObject (sourceName).immutableReferences );
1319+ if (evmDeployedArtifactRequested (" ethdebug" ))
1320+ deployedJSON[" ethdebug" ] = stack.ethdebug (sourceName, true );
12661321 evmData[" deployedBytecode" ] = deployedJSON;
12671322 }
12681323
@@ -1503,6 +1558,8 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu
15031558 creationJSON[" linkReferences" ] = formatLinkReferences (compilerStack.object (contractName).linkReferences );
15041559 if (evmCreationArtifactRequested (" generatedSources" ))
15051560 creationJSON[" generatedSources" ] = compilerStack.generatedSources (contractName, /* _runtime */ false );
1561+ if (evmCreationArtifactRequested (" ethdebug" ))
1562+ creationJSON[" ethdebug" ] = compilerStack.ethdebug (contractName, false );
15061563 evmData[" bytecode" ] = creationJSON;
15071564 }
15081565
@@ -1533,6 +1590,8 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu
15331590 deployedJSON[" immutableReferences" ] = formatImmutableReferences (compilerStack.runtimeObject (contractName).immutableReferences );
15341591 if (evmDeployedArtifactRequested (" generatedSources" ))
15351592 deployedJSON[" generatedSources" ] = compilerStack.generatedSources (contractName, /* _runtime */ true );
1593+ if (evmDeployedArtifactRequested (" ethdebug" ))
1594+ deployedJSON[" ethdebug" ] = compilerStack.ethdebug (contractName, true );
15361595 evmData[" deployedBytecode" ] = deployedJSON;
15371596 }
15381597
@@ -1546,6 +1605,10 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu
15461605 contractsOutput[file][name] = contractData;
15471606 }
15481607 }
1608+
1609+ if (isEthdebugRequested (_inputsAndSettings.outputSelection ))
1610+ output[" ethdebug" ] = compilerStack.ethdebug ();
1611+
15491612 if (!contractsOutput.empty ())
15501613 output[" contracts" ] = contractsOutput;
15511614
@@ -1597,6 +1660,19 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
15971660 return output;
15981661 }
15991662
1663+ for (auto const & fileRequests: _inputsAndSettings.outputSelection )
1664+ for (auto const & requests: fileRequests)
1665+ for (auto const & request: requests)
1666+ if (request == " evm.deployedBytecode.ethdebug" )
1667+ {
1668+ output[" errors" ].emplace_back (formatError (
1669+ Error::Type::JSONError,
1670+ " general" ,
1671+ " \" evm.deployedBytecode.ethdebug\" cannot be used for Yul."
1672+ ));
1673+ return output;
1674+ }
1675+
16001676 YulStack stack (
16011677 _inputsAndSettings.evmVersion ,
16021678 _inputsAndSettings.eofVersion ,
@@ -1687,6 +1763,8 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
16871763 bytecodeJSON[" functionDebugData" ] = formatFunctionDebugData (selectedObject.bytecode ->functionDebugData );
16881764 if (evmArtifactRequested (kind, " linkReferences" ))
16891765 bytecodeJSON[" linkReferences" ] = formatLinkReferences (selectedObject.bytecode ->linkReferences );
1766+ if (evmArtifactRequested (kind, " ethdebug" ))
1767+ bytecodeJSON[" ethdebug" ] = selectedObject.ethdebug ;
16901768 if (isDeployed && evmArtifactRequested (kind, " immutableReferences" ))
16911769 bytecodeJSON[" immutableReferences" ] = formatImmutableReferences (selectedObject.bytecode ->immutableReferences );
16921770 output[" contracts" ][sourceName][contractName][" evm" ][kind] = bytecodeJSON;
@@ -1700,6 +1778,9 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
17001778 if (isArtifactRequested (_inputsAndSettings.outputSelection , sourceName, contractName, " yulCFGJson" , wildcardMatchesExperimental))
17011779 output[" contracts" ][sourceName][contractName][" yulCFGJson" ] = stack.cfgJson ();
17021780
1781+ if (isEthdebugRequested (_inputsAndSettings.outputSelection ))
1782+ output[" ethdebug" ] = stack.ethdebug ();
1783+
17031784 return output;
17041785}
17051786
0 commit comments