Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[yul] Transport debug data to assembly. #14969

Draft
wants to merge 2 commits into
base: yul_parse_debugdata_attributes
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions libevmasm/Assembly.cpp
Expand Up @@ -62,6 +62,7 @@ AssemblyItem const& Assembly::append(AssemblyItem _i)
if (!m_items.back().location().isValid() && m_currentSourceLocation.isValid())
m_items.back().setLocation(m_currentSourceLocation);
m_items.back().m_modifierDepth = m_currentModifierDepth;
m_items.back().setDebugAttributes(m_currentDebugAttributes);
return m_items.back();
}

Expand Down Expand Up @@ -314,6 +315,9 @@ class Functionalizer

std::string expression = _item.toAssemblyText(m_assembly);

if (!_item.debugData()->attributes.empty())
expression += m_prefix + " // @debug.set " + _item.debugData()->attributes.dump();

if (!(
_item.canBeFunctional() &&
_item.returnValues() <= 1 &&
Expand Down
6 changes: 6 additions & 0 deletions libevmasm/Assembly.h
Expand Up @@ -111,6 +111,11 @@ class Assembly
/// Changes the source location used for each appended item.
void setSourceLocation(langutil::SourceLocation const& _location) { m_currentSourceLocation = _location; }
langutil::SourceLocation const& currentSourceLocation() const { return m_currentSourceLocation; }

/// Changes debug data used for each appended item.
void setDebugAttributes(Json const& _debugAttributes) { m_currentDebugAttributes = _debugAttributes; }
Json currentDebugAttributes() const { return m_currentDebugAttributes; }

langutil::EVMVersion const& evmVersion() const { return m_evmVersion; }

/// Assembles the assembly into bytecode. The assembly should not be modified after this call, since the assembled version is cached.
Expand Down Expand Up @@ -246,6 +251,7 @@ class Assembly
/// currently
std::string m_name;
langutil::SourceLocation m_currentSourceLocation;
Json m_currentDebugAttributes;

// FIXME: This being static means that the strings won't be freed when they're no longer needed
static std::map<std::string, std::shared_ptr<std::string const>> s_sharedSourceNames;
Expand Down
9 changes: 9 additions & 0 deletions libevmasm/AssemblyItem.h
Expand Up @@ -194,6 +194,15 @@ class AssemblyItem
m_debugData = std::move(_debugData);
}

void setDebugAttributes(Json const& _debugAttributes)
{
if (!m_debugData)
m_debugData = langutil::DebugData::create({}, {}, {}, _debugAttributes);
else
m_debugData = langutil::DebugData::create(m_debugData->nativeLocation, m_debugData->originLocation, m_debugData->astID, _debugAttributes);
}


langutil::DebugData::ConstPtr debugData() const { return m_debugData; }

void setJumpType(JumpType _jumpType) { m_jumpType = _jumpType; }
Expand Down
49 changes: 41 additions & 8 deletions libyul/AsmPrinter.cpp
Expand Up @@ -45,7 +45,8 @@ using namespace solidity::yul;
std::string AsmPrinter::operator()(Literal const& _literal)
{
std::string const locationComment = formatDebugData(_literal);

if ( _literal.debugData)
m_currentDebugAttributes = _literal.debugData->attributes;
switch (_literal.kind)
{
case LiteralKind::Number:
Expand All @@ -64,19 +65,24 @@ std::string AsmPrinter::operator()(Literal const& _literal)
std::string AsmPrinter::operator()(Identifier const& _identifier)
{
yulAssert(!_identifier.name.empty(), "Invalid identifier.");
if (_identifier.debugData)
m_currentDebugAttributes = _identifier.debugData->attributes;
return formatDebugData(_identifier) + _identifier.name.str();
}

std::string AsmPrinter::operator()(ExpressionStatement const& _statement)
{
std::string const locationComment = formatDebugData(_statement);

if (_statement.debugData)
m_currentDebugAttributes = _statement.debugData->attributes;
return locationComment + std::visit(*this, _statement.expression);
}

std::string AsmPrinter::operator()(Assignment const& _assignment)
{
std::string const locationComment = formatDebugData(_assignment);
if (_assignment.debugData)
m_currentDebugAttributes = _assignment.debugData->attributes;

yulAssert(_assignment.variableNames.size() >= 1, "");
std::string variables = (*this)(_assignment.variableNames.front());
Expand All @@ -89,7 +95,8 @@ std::string AsmPrinter::operator()(Assignment const& _assignment)
std::string AsmPrinter::operator()(VariableDeclaration const& _variableDeclaration)
{
std::string out = formatDebugData(_variableDeclaration);

if (_variableDeclaration.debugData)
m_currentDebugAttributes = _variableDeclaration.debugData->attributes;
out += "let ";
out += boost::algorithm::join(
_variableDeclaration.variables | ranges::views::transform(
Expand All @@ -108,7 +115,8 @@ std::string AsmPrinter::operator()(VariableDeclaration const& _variableDeclarati
std::string AsmPrinter::operator()(FunctionDefinition const& _functionDefinition)
{
yulAssert(!_functionDefinition.name.empty(), "Invalid function name.");

if (_functionDefinition.debugData)
m_currentDebugAttributes = _functionDefinition.debugData->attributes;
std::string out = formatDebugData(_functionDefinition);
out += "function " + _functionDefinition.name.str() + "(";
out += boost::algorithm::join(
Expand Down Expand Up @@ -136,6 +144,8 @@ std::string AsmPrinter::operator()(FunctionCall const& _functionCall)
{
std::string const locationComment = formatDebugData(_functionCall);
std::string const functionName = (*this)(_functionCall.functionName);
if (_functionCall.debugData)
m_currentDebugAttributes = _functionCall.debugData->attributes;
return
locationComment +
functionName + "(" +
Expand All @@ -148,7 +158,8 @@ std::string AsmPrinter::operator()(FunctionCall const& _functionCall)
std::string AsmPrinter::operator()(If const& _if)
{
yulAssert(_if.condition, "Invalid if condition.");

if (_if.debugData)
m_currentDebugAttributes = _if.debugData->attributes;
std::string out = formatDebugData(_if);
out += "if " + std::visit(*this, *_if.condition);

Expand All @@ -163,7 +174,8 @@ std::string AsmPrinter::operator()(If const& _if)
std::string AsmPrinter::operator()(Switch const& _switch)
{
yulAssert(_switch.expression, "Invalid expression pointer.");

if (_switch.debugData)
m_currentDebugAttributes = _switch.debugData->attributes;
std::string out = formatDebugData(_switch);
out += "switch " + std::visit(*this, *_switch.expression);

Expand All @@ -181,6 +193,8 @@ std::string AsmPrinter::operator()(Switch const& _switch)
std::string AsmPrinter::operator()(ForLoop const& _forLoop)
{
yulAssert(_forLoop.condition, "Invalid for loop condition.");
if (_forLoop.debugData)
m_currentDebugAttributes = _forLoop.debugData->attributes;
std::string const locationComment = formatDebugData(_forLoop);

std::string pre = (*this)(_forLoop.pre);
Expand All @@ -202,24 +216,31 @@ std::string AsmPrinter::operator()(ForLoop const& _forLoop)

std::string AsmPrinter::operator()(Break const& _break)
{
if (_break.debugData)
m_currentDebugAttributes = _break.debugData->attributes;
return formatDebugData(_break) + "break";
}

std::string AsmPrinter::operator()(Continue const& _continue)
{
if (_continue.debugData)
m_currentDebugAttributes = _continue.debugData->attributes;
return formatDebugData(_continue) + "continue";
}

// '_leave' and '__leave' is reserved in VisualStudio
std::string AsmPrinter::operator()(Leave const& leave_)
{
if (leave_.debugData)
m_currentDebugAttributes = leave_.debugData->attributes;
return formatDebugData(leave_) + "leave";
}

std::string AsmPrinter::operator()(Block const& _block)
{
std::string const locationComment = formatDebugData(_block);

if (_block.debugData)
m_currentDebugAttributes = _block.debugData->attributes;
if (_block.statements.empty())
return locationComment + "{ }";
std::string body = boost::algorithm::join(
Expand All @@ -238,6 +259,8 @@ std::string AsmPrinter::operator()(Block const& _block)
std::string AsmPrinter::formatTypedName(TypedName _variable)
{
yulAssert(!_variable.name.empty(), "Invalid variable name.");
if (_variable.debugData)
m_currentDebugAttributes = _variable.debugData->attributes;
return formatDebugData(_variable) + _variable.name.str() + appendTypeName(_variable.type);
}

Expand Down Expand Up @@ -329,7 +352,17 @@ std::string AsmPrinter::formatDebugData(langutil::DebugData::ConstPtr const& _de
m_soliditySourceProvider
));
}

// if (m_currentDebugAttributes != _debugData->attributes)
// {
// Json diff = Json::diff(m_currentDebugAttributes, _debugData->attributes);
// if (!diff.empty())
// items.emplace_back("@debug.patch " + diff.dump());
// }
if (m_currentDebugAttributes != _debugData->attributes)
{
if (!_debugData->attributes.empty())
items.emplace_back("@debug.set " + _debugData->attributes.dump());
}
std::string commentBody = joinHumanReadable(items, " ");
if (commentBody.empty())
return "";
Expand Down
1 change: 1 addition & 0 deletions libyul/AsmPrinter.h
Expand Up @@ -106,6 +106,7 @@ class AsmPrinter
langutil::SourceLocation m_lastLocation = {};
langutil::DebugInfoSelection m_debugInfoSelection = {};
langutil::CharStreamProvider const* m_soliditySourceProvider = nullptr;
Json m_currentDebugAttributes;
};

}
4 changes: 3 additions & 1 deletion libyul/backends/evm/AbstractAssembly.h
Expand Up @@ -26,9 +26,9 @@
#include <libyul/ASTForward.h>

#include <libsolutil/Common.h>
#include <libsolutil/CommonData.h>
#include <libsolutil/Numeric.h>
#include <liblangutil/EVMVersion.h>
#include <liblangutil/DebugData.h>

#include <functional>
#include <memory>
Expand Down Expand Up @@ -62,6 +62,8 @@ class AbstractAssembly

/// Set a new source location valid starting from the next instruction.
virtual void setSourceLocation(langutil::SourceLocation const& _location) = 0;
/// Set a new debug attributes for next instruction.
virtual void setDebugAttributes(Json const& _debugAttributes) = 0;
/// Retrieve the current height of the stack. This does not have to be zero
/// at the beginning.
virtual int stackHeight() const = 0;
Expand Down