mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #11944 from ethereum/debug-info-selection
Debug info selection
This commit is contained in:
@@ -135,11 +135,15 @@ string dispenseLocationComment(langutil::SourceLocation const& _location, IRGene
|
||||
{
|
||||
solAssert(_location.sourceName, "");
|
||||
_context.markSourceUsed(*_location.sourceName);
|
||||
return "/// " + AsmPrinter::formatSourceLocation(
|
||||
|
||||
string debugInfo = AsmPrinter::formatSourceLocation(
|
||||
_location,
|
||||
_context.sourceIndices(),
|
||||
_context.debugInfoSelection(),
|
||||
_context.soliditySourceProvider()
|
||||
);
|
||||
|
||||
return debugInfo.empty() ? "" : "/// " + debugInfo;
|
||||
}
|
||||
|
||||
string dispenseLocationComment(ASTNode const& _node, IRGenerationContext& _context)
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <libsolidity/codegen/ir/Common.h>
|
||||
|
||||
#include <liblangutil/CharStreamProvider.h>
|
||||
#include <liblangutil/DebugInfoSelection.h>
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
|
||||
#include <libsolutil/Common.h>
|
||||
@@ -74,6 +75,7 @@ public:
|
||||
RevertStrings _revertStrings,
|
||||
OptimiserSettings _optimiserSettings,
|
||||
std::map<std::string, unsigned> _sourceIndices,
|
||||
langutil::DebugInfoSelection const& _debugInfoSelection,
|
||||
langutil::CharStreamProvider const* _soliditySourceProvider
|
||||
):
|
||||
m_evmVersion(_evmVersion),
|
||||
@@ -81,6 +83,7 @@ public:
|
||||
m_revertStrings(_revertStrings),
|
||||
m_optimiserSettings(std::move(_optimiserSettings)),
|
||||
m_sourceIndices(std::move(_sourceIndices)),
|
||||
m_debugInfoSelection(_debugInfoSelection),
|
||||
m_soliditySourceProvider(_soliditySourceProvider)
|
||||
{}
|
||||
|
||||
@@ -174,6 +177,7 @@ public:
|
||||
|
||||
bool immutableRegistered(VariableDeclaration const& _varDecl) const { return m_immutableVariables.count(&_varDecl); }
|
||||
|
||||
langutil::DebugInfoSelection debugInfoSelection() const { return m_debugInfoSelection; }
|
||||
langutil::CharStreamProvider const* soliditySourceProvider() const { return m_soliditySourceProvider; }
|
||||
|
||||
private:
|
||||
@@ -220,6 +224,7 @@ private:
|
||||
|
||||
std::set<ContractDefinition const*, ASTNode::CompareByID> m_subObjects;
|
||||
|
||||
langutil::DebugInfoSelection m_debugInfoSelection = {};
|
||||
langutil::CharStreamProvider const* m_soliditySourceProvider = nullptr;
|
||||
};
|
||||
|
||||
|
||||
@@ -95,7 +95,12 @@ pair<string, string> IRGenerator::run(
|
||||
{
|
||||
string const ir = yul::reindent(generate(_contract, _cborMetadata, _otherYulSources));
|
||||
|
||||
yul::AssemblyStack asmStack(m_evmVersion, yul::AssemblyStack::Language::StrictAssembly, m_optimiserSettings);
|
||||
yul::AssemblyStack asmStack(
|
||||
m_evmVersion,
|
||||
yul::AssemblyStack::Language::StrictAssembly,
|
||||
m_optimiserSettings,
|
||||
m_context.debugInfoSelection()
|
||||
);
|
||||
if (!asmStack.parseAndAnalyze("", ir))
|
||||
{
|
||||
string errorMessage;
|
||||
@@ -340,8 +345,7 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function)
|
||||
return m_context.functionCollector().createFunction(functionName, [&]() {
|
||||
m_context.resetLocalVariables();
|
||||
Whiskers t(R"(
|
||||
/// @ast-id <astID>
|
||||
<sourceLocationComment>
|
||||
<astIDComment><sourceLocationComment>
|
||||
function <functionName>(<params>)<?+retParams> -> <retParams></+retParams> {
|
||||
<retInit>
|
||||
<body>
|
||||
@@ -349,7 +353,10 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function)
|
||||
<contractSourceLocationComment>
|
||||
)");
|
||||
|
||||
t("astID", to_string(_function.id()));
|
||||
if (m_context.debugInfoSelection().astID)
|
||||
t("astIDComment", "/// @ast-id " + to_string(_function.id()) + "\n");
|
||||
else
|
||||
t("astIDComment", "");
|
||||
t("sourceLocationComment", dispenseLocationComment(_function));
|
||||
t(
|
||||
"contractSourceLocationComment",
|
||||
@@ -409,8 +416,7 @@ string IRGenerator::generateModifier(
|
||||
return m_context.functionCollector().createFunction(functionName, [&]() {
|
||||
m_context.resetLocalVariables();
|
||||
Whiskers t(R"(
|
||||
/// @ast-id <astID>
|
||||
<sourceLocationComment>
|
||||
<astIDComment><sourceLocationComment>
|
||||
function <functionName>(<params>)<?+retParams> -> <retParams></+retParams> {
|
||||
<assignRetParams>
|
||||
<evalArgs>
|
||||
@@ -418,6 +424,7 @@ string IRGenerator::generateModifier(
|
||||
}
|
||||
<contractSourceLocationComment>
|
||||
)");
|
||||
|
||||
t("functionName", functionName);
|
||||
vector<string> retParamsIn;
|
||||
for (auto const& varDecl: _function.returnParameters())
|
||||
@@ -440,7 +447,11 @@ string IRGenerator::generateModifier(
|
||||
_modifierInvocation.name().annotation().referencedDeclaration
|
||||
);
|
||||
solAssert(modifier, "");
|
||||
t("astID", to_string(modifier->id()));
|
||||
|
||||
if (m_context.debugInfoSelection().astID)
|
||||
t("astIDComment", "/// @ast-id " + to_string(modifier->id()) + "\n");
|
||||
else
|
||||
t("astIDComment", "");
|
||||
t("sourceLocationComment", dispenseLocationComment(*modifier));
|
||||
t(
|
||||
"contractSourceLocationComment",
|
||||
@@ -546,14 +557,18 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
solAssert(paramTypes.empty(), "");
|
||||
solUnimplementedAssert(type->sizeOnStack() == 1);
|
||||
return Whiskers(R"(
|
||||
/// @ast-id <astID>
|
||||
<sourceLocationComment>
|
||||
<astIDComment><sourceLocationComment>
|
||||
function <functionName>() -> rval {
|
||||
rval := loadimmutable("<id>")
|
||||
}
|
||||
<contractSourceLocationComment>
|
||||
)")
|
||||
("astID", to_string(_varDecl.id()))
|
||||
(
|
||||
"astIDComment",
|
||||
m_context.debugInfoSelection().astID ?
|
||||
"/// @ast-id " + to_string(_varDecl.id()) + "\n" :
|
||||
""
|
||||
)
|
||||
("sourceLocationComment", dispenseLocationComment(_varDecl))
|
||||
(
|
||||
"contractSourceLocationComment",
|
||||
@@ -567,14 +582,18 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
{
|
||||
solAssert(paramTypes.empty(), "");
|
||||
return Whiskers(R"(
|
||||
/// @ast-id <astID>
|
||||
<sourceLocationComment>
|
||||
<astIDComment><sourceLocationComment>
|
||||
function <functionName>() -> <ret> {
|
||||
<ret> := <constantValueFunction>()
|
||||
}
|
||||
<contractSourceLocationComment>
|
||||
)")
|
||||
("astID", to_string(_varDecl.id()))
|
||||
(
|
||||
"astIDComment",
|
||||
m_context.debugInfoSelection().astID ?
|
||||
"/// @ast-id " + to_string(_varDecl.id()) + "\n" :
|
||||
""
|
||||
)
|
||||
("sourceLocationComment", dispenseLocationComment(_varDecl))
|
||||
(
|
||||
"contractSourceLocationComment",
|
||||
@@ -691,8 +710,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
}
|
||||
|
||||
return Whiskers(R"(
|
||||
/// @ast-id <astID>
|
||||
<sourceLocationComment>
|
||||
<astIDComment><sourceLocationComment>
|
||||
function <functionName>(<params>) -> <retVariables> {
|
||||
<code>
|
||||
}
|
||||
@@ -702,7 +720,12 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
("params", joinHumanReadable(parameters))
|
||||
("retVariables", joinHumanReadable(returnVariables))
|
||||
("code", std::move(code))
|
||||
("astID", to_string(_varDecl.id()))
|
||||
(
|
||||
"astIDComment",
|
||||
m_context.debugInfoSelection().astID ?
|
||||
"/// @ast-id " + to_string(_varDecl.id()) + "\n" :
|
||||
""
|
||||
)
|
||||
("sourceLocationComment", dispenseLocationComment(_varDecl))
|
||||
(
|
||||
"contractSourceLocationComment",
|
||||
@@ -829,7 +852,7 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract)
|
||||
for (ASTPointer<VariableDeclaration> const& varDecl: contract->constructor()->parameters())
|
||||
params += m_context.addLocalVariable(*varDecl).stackSlots();
|
||||
|
||||
if (contract->constructor())
|
||||
if (m_context.debugInfoSelection().astID && contract->constructor())
|
||||
t("astIDComment", "/// @ast-id " + to_string(contract->constructor()->id()) + "\n");
|
||||
else
|
||||
t("astIDComment", "");
|
||||
@@ -1085,6 +1108,7 @@ void IRGenerator::resetContext(ContractDefinition const& _contract, ExecutionCon
|
||||
m_context.revertStrings(),
|
||||
m_optimiserSettings,
|
||||
m_context.sourceIndices(),
|
||||
m_context.debugInfoSelection(),
|
||||
m_context.soliditySourceProvider()
|
||||
);
|
||||
newContext.copyFunctionIDsFrom(m_context);
|
||||
|
||||
@@ -49,6 +49,7 @@ public:
|
||||
RevertStrings _revertStrings,
|
||||
OptimiserSettings _optimiserSettings,
|
||||
std::map<std::string, unsigned> _sourceIndices,
|
||||
langutil::DebugInfoSelection const& _debugInfoSelection,
|
||||
langutil::CharStreamProvider const* _soliditySourceProvider
|
||||
):
|
||||
m_evmVersion(_evmVersion),
|
||||
@@ -59,6 +60,7 @@ public:
|
||||
_revertStrings,
|
||||
std::move(_optimiserSettings),
|
||||
std::move(_sourceIndices),
|
||||
_debugInfoSelection,
|
||||
_soliditySourceProvider
|
||||
),
|
||||
m_utils(_evmVersion, m_context.revertStrings(), m_context.functionCollector())
|
||||
|
||||
@@ -271,6 +271,13 @@ void CompilerStack::setMetadataHash(MetadataHash _metadataHash)
|
||||
m_metadataHash = _metadataHash;
|
||||
}
|
||||
|
||||
void CompilerStack::selectDebugInfo(DebugInfoSelection _debugInfoSelection)
|
||||
{
|
||||
if (m_stackState >= CompilationSuccessful)
|
||||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must select debug info components before compilation."));
|
||||
m_debugInfoSelection = _debugInfoSelection;
|
||||
}
|
||||
|
||||
void CompilerStack::addSMTLib2Response(h256 const& _hash, string const& _response)
|
||||
{
|
||||
if (m_stackState >= ParsedAndImported)
|
||||
@@ -882,7 +889,7 @@ string CompilerStack::assemblyString(string const& _contractName, StringMap cons
|
||||
|
||||
Contract const& currentContract = contract(_contractName);
|
||||
if (currentContract.evmAssembly)
|
||||
return currentContract.evmAssembly->assemblyString(_sourceCodes);
|
||||
return currentContract.evmAssembly->assemblyString(m_debugInfoSelection, _sourceCodes);
|
||||
else
|
||||
return string();
|
||||
}
|
||||
@@ -1319,7 +1326,7 @@ void CompilerStack::generateIR(ContractDefinition const& _contract)
|
||||
for (auto const& pair: m_contracts)
|
||||
otherYulSources.emplace(pair.second.contract, pair.second.yulIR);
|
||||
|
||||
IRGenerator generator(m_evmVersion, m_revertStrings, m_optimiserSettings, sourceIndices(), this);
|
||||
IRGenerator generator(m_evmVersion, m_revertStrings, m_optimiserSettings, sourceIndices(), m_debugInfoSelection, this);
|
||||
tie(compiledContract.yulIR, compiledContract.yulIROptimized) = generator.run(
|
||||
_contract,
|
||||
createCBORMetadata(compiledContract, /* _forIR */ true),
|
||||
@@ -1342,7 +1349,12 @@ void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract)
|
||||
return;
|
||||
|
||||
// Re-parse the Yul IR in EVM dialect
|
||||
yul::AssemblyStack stack(m_evmVersion, yul::AssemblyStack::Language::StrictAssembly, m_optimiserSettings);
|
||||
yul::AssemblyStack stack(
|
||||
m_evmVersion,
|
||||
yul::AssemblyStack::Language::StrictAssembly,
|
||||
m_optimiserSettings,
|
||||
m_debugInfoSelection
|
||||
);
|
||||
stack.parseAndAnalyze("", compiledContract.yulIROptimized);
|
||||
stack.optimize();
|
||||
|
||||
@@ -1369,7 +1381,12 @@ void CompilerStack::generateEwasm(ContractDefinition const& _contract)
|
||||
return;
|
||||
|
||||
// Re-parse the Yul IR in EVM dialect
|
||||
yul::AssemblyStack stack(m_evmVersion, yul::AssemblyStack::Language::StrictAssembly, m_optimiserSettings);
|
||||
yul::AssemblyStack stack(
|
||||
m_evmVersion,
|
||||
yul::AssemblyStack::Language::StrictAssembly,
|
||||
m_optimiserSettings,
|
||||
m_debugInfoSelection
|
||||
);
|
||||
stack.parseAndAnalyze("", compiledContract.yulIROptimized);
|
||||
|
||||
stack.optimize();
|
||||
|
||||
@@ -35,10 +35,11 @@
|
||||
|
||||
#include <libsmtutil/SolverInterface.h>
|
||||
|
||||
#include <liblangutil/CharStreamProvider.h>
|
||||
#include <liblangutil/DebugInfoSelection.h>
|
||||
#include <liblangutil/ErrorReporter.h>
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
#include <liblangutil/SourceLocation.h>
|
||||
#include <liblangutil/CharStreamProvider.h>
|
||||
|
||||
#include <libevmasm/LinkerObject.h>
|
||||
|
||||
@@ -203,6 +204,9 @@ public:
|
||||
/// @param _metadataHash can be IPFS, Bzzr1, None
|
||||
void setMetadataHash(MetadataHash _metadataHash);
|
||||
|
||||
/// Select components of debug info that should be included in comments in generated assembly.
|
||||
void selectDebugInfo(langutil::DebugInfoSelection _debugInfoSelection);
|
||||
|
||||
/// Sets the sources. Must be set before parsing.
|
||||
void setSources(StringMap _sources);
|
||||
|
||||
@@ -505,6 +509,7 @@ private:
|
||||
langutil::ErrorReporter m_errorReporter;
|
||||
bool m_metadataLiteralSources = false;
|
||||
MetadataHash m_metadataHash = MetadataHash::IPFS;
|
||||
langutil::DebugInfoSelection m_debugInfoSelection = langutil::DebugInfoSelection::Default();
|
||||
bool m_parserErrorRecovery = false;
|
||||
State m_stackState = Empty;
|
||||
bool m_importedSources = false;
|
||||
|
||||
@@ -28,9 +28,13 @@
|
||||
#include <libyul/AssemblyStack.h>
|
||||
#include <libyul/Exceptions.h>
|
||||
#include <libyul/optimiser/Suite.h>
|
||||
#include <liblangutil/SourceReferenceFormatter.h>
|
||||
|
||||
#include <libevmasm/Instruction.h>
|
||||
|
||||
#include <libsmtutil/Exceptions.h>
|
||||
|
||||
#include <liblangutil/SourceReferenceFormatter.h>
|
||||
|
||||
#include <libsolutil/JSON.h>
|
||||
#include <libsolutil/Keccak256.h>
|
||||
#include <libsolutil/CommonData.h>
|
||||
@@ -793,7 +797,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
|
||||
if (settings.isMember("debug"))
|
||||
{
|
||||
if (auto result = checkKeys(settings["debug"], {"revertStrings"}, "settings.debug"))
|
||||
if (auto result = checkKeys(settings["debug"], {"revertStrings", "debugInfo"}, "settings.debug"))
|
||||
return *result;
|
||||
|
||||
if (settings["debug"].isMember("revertStrings"))
|
||||
@@ -810,6 +814,31 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
);
|
||||
ret.revertStrings = *revertStrings;
|
||||
}
|
||||
|
||||
if (settings["debug"].isMember("debugInfo"))
|
||||
{
|
||||
if (!settings["debug"]["debugInfo"].isArray())
|
||||
return formatFatalError("JSONError", "settings.debug.debugInfo must be an array.");
|
||||
|
||||
vector<string> components;
|
||||
for (Json::Value const& arrayValue: settings["debug"]["debugInfo"])
|
||||
components.push_back(arrayValue.asString());
|
||||
|
||||
optional<DebugInfoSelection> debugInfoSelection = DebugInfoSelection::fromComponents(
|
||||
components,
|
||||
true /* _acceptWildcards */
|
||||
);
|
||||
if (!debugInfoSelection.has_value())
|
||||
return formatFatalError("JSONError", "Invalid value in settings.debug.debugInfo.");
|
||||
|
||||
if (debugInfoSelection->snippet && !debugInfoSelection->location)
|
||||
return formatFatalError(
|
||||
"JSONError",
|
||||
"To use 'snippet' with settings.debug.debugInfo you must select also 'location'."
|
||||
);
|
||||
|
||||
ret.debugInfoSelection = debugInfoSelection.value();
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.isMember("remappings") && !settings["remappings"].isArray())
|
||||
@@ -1029,6 +1058,8 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
compilerStack.setRemappings(move(_inputsAndSettings.remappings));
|
||||
compilerStack.setOptimiserSettings(std::move(_inputsAndSettings.optimiserSettings));
|
||||
compilerStack.setRevertStringBehaviour(_inputsAndSettings.revertStrings);
|
||||
if (_inputsAndSettings.debugInfoSelection.has_value())
|
||||
compilerStack.selectDebugInfo(_inputsAndSettings.debugInfoSelection.value());
|
||||
compilerStack.setLibraries(_inputsAndSettings.libraries);
|
||||
compilerStack.useMetadataLiteralSources(_inputsAndSettings.metadataLiteralSources);
|
||||
compilerStack.setMetadataHash(_inputsAndSettings.metadataHash);
|
||||
@@ -1358,7 +1389,10 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
|
||||
AssemblyStack stack(
|
||||
_inputsAndSettings.evmVersion,
|
||||
AssemblyStack::Language::StrictAssembly,
|
||||
_inputsAndSettings.optimiserSettings
|
||||
_inputsAndSettings.optimiserSettings,
|
||||
_inputsAndSettings.debugInfoSelection.has_value() ?
|
||||
_inputsAndSettings.debugInfoSelection.value() :
|
||||
DebugInfoSelection::Default()
|
||||
);
|
||||
string const& sourceName = _inputsAndSettings.sources.begin()->first;
|
||||
string const& sourceContents = _inputsAndSettings.sources.begin()->second;
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include <libsolidity/interface/CompilerStack.h>
|
||||
#include <libsolutil/JSON.h>
|
||||
|
||||
#include <liblangutil/DebugInfoSelection.h>
|
||||
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
@@ -78,6 +80,7 @@ private:
|
||||
std::vector<ImportRemapper::Remapping> remappings;
|
||||
RevertStrings revertStrings = RevertStrings::Default;
|
||||
OptimiserSettings optimiserSettings = OptimiserSettings::minimal();
|
||||
std::optional<langutil::DebugInfoSelection> debugInfoSelection;
|
||||
std::map<std::string, util::h160> libraries;
|
||||
bool metadataLiteralSources = false;
|
||||
CompilerStack::MetadataHash metadataHash = CompilerStack::MetadataHash::IPFS;
|
||||
|
||||
Reference in New Issue
Block a user