Skip to content

Commit

Permalink
[yul] Initial transport of debug data to assembly.
Browse files Browse the repository at this point in the history
  • Loading branch information
aarlt committed Mar 27, 2024
1 parent 6396d56 commit 6118469
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 9 deletions.
5 changes: 5 additions & 0 deletions libevmasm/Assembly.cpp
Expand Up @@ -62,6 +62,8 @@ 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;
if (m_currentDebugData)
m_items.back().setDebugData(m_currentDebugData);
return m_items.back();
}

Expand Down Expand Up @@ -314,6 +316,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 setDebugData(langutil::DebugData::ConstPtr _debugData) { m_currentDebugData = std::move(_debugData); }
langutil::DebugData::ConstPtr currentDebugData() { return m_currentDebugData; }

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;
langutil::DebugData::ConstPtr m_currentDebugData;

// 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
34 changes: 26 additions & 8 deletions libyul/AsmPrinter.cpp
Expand Up @@ -45,7 +45,7 @@ using namespace solidity::yul;
std::string AsmPrinter::operator()(Literal const& _literal)
{
std::string const locationComment = formatDebugData(_literal);

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

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

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);
m_currentDebugAttributes = _assignment.debugData->attributes;

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

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

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 +138,7 @@ std::string AsmPrinter::operator()(FunctionCall const& _functionCall)
{
std::string const locationComment = formatDebugData(_functionCall);
std::string const functionName = (*this)(_functionCall.functionName);
m_currentDebugAttributes = _functionCall.debugData->attributes;
return
locationComment +
functionName + "(" +
Expand All @@ -148,7 +151,7 @@ std::string AsmPrinter::operator()(FunctionCall const& _functionCall)
std::string AsmPrinter::operator()(If const& _if)
{
yulAssert(_if.condition, "Invalid if condition.");

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

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

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

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

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

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

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

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

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

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

Expand Down Expand Up @@ -329,7 +337,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 data for next instruction.
virtual void setDebugData(langutil::DebugData::ConstPtr _debugData) = 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

0 comments on commit 6118469

Please sign in to comment.