Skip to content

Commit 4032b59

Browse files
committed
Add DebugData to AssemblyItem.
1 parent 5fe3173 commit 4032b59

37 files changed

+289
-223
lines changed

libevmasm/Assembly.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ AssemblyItem Assembly::createAssemblyItemFromJSON(Json::Value const& _json, std:
180180

181181
if (c_instructions.count(name))
182182
{
183-
AssemblyItem item{c_instructions.at(name), location};
183+
AssemblyItem item{c_instructions.at(name), langutil::DebugData::create(location)};
184184
if (!jumpType.empty())
185185
{
186186
if (item.instruction() == Instruction::JUMP || item.instruction() == Instruction::JUMPI)

libevmasm/AssemblyItem.h

+34-11
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424

2525
#include <libevmasm/Instruction.h>
2626
#include <libevmasm/Exceptions.h>
27-
#include <liblangutil/SourceLocation.h>
27+
#include <liblangutil/DebugData.h>
28+
#include <liblangutil/Exceptions.h>
2829
#include <libsolutil/Common.h>
2930
#include <libsolutil/Numeric.h>
3031
#include <libsolutil/Assertions.h>
@@ -64,16 +65,16 @@ class AssemblyItem
6465
public:
6566
enum class JumpType { Ordinary, IntoFunction, OutOfFunction };
6667

67-
AssemblyItem(u256 _push, langutil::SourceLocation _location = langutil::SourceLocation()):
68-
AssemblyItem(Push, std::move(_push), std::move(_location)) { }
69-
AssemblyItem(Instruction _i, langutil::SourceLocation _location = langutil::SourceLocation()):
68+
AssemblyItem(u256 _push, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()):
69+
AssemblyItem(Push, std::move(_push), std::move(_debugData)) { }
70+
AssemblyItem(Instruction _i, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()):
7071
m_type(Operation),
7172
m_instruction(_i),
72-
m_location(std::move(_location))
73+
m_debugData(std::move(_debugData))
7374
{}
74-
AssemblyItem(AssemblyItemType _type, u256 _data = 0, langutil::SourceLocation _location = langutil::SourceLocation()):
75+
AssemblyItem(AssemblyItemType _type, u256 _data = 0, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()):
7576
m_type(_type),
76-
m_location(std::move(_location))
77+
m_debugData(std::move(_debugData))
7778
{
7879
if (m_type == Operation)
7980
m_instruction = Instruction(uint8_t(_data));
@@ -83,7 +84,8 @@ class AssemblyItem
8384
explicit AssemblyItem(bytes _verbatimData, size_t _arguments, size_t _returnVariables):
8485
m_type(VerbatimBytecode),
8586
m_instruction{},
86-
m_verbatimBytecode{{_arguments, _returnVariables, std::move(_verbatimData)}}
87+
m_verbatimBytecode{{_arguments, _returnVariables, std::move(_verbatimData)}},
88+
m_debugData{langutil::DebugData::create()}
8789
{}
8890

8991
AssemblyItem(AssemblyItem const&) = default;
@@ -170,8 +172,29 @@ class AssemblyItem
170172
/// @returns true if the assembly item can be used in a functional context.
171173
bool canBeFunctional() const;
172174

173-
void setLocation(langutil::SourceLocation const& _location) { m_location = _location; }
174-
langutil::SourceLocation const& location() const { return m_location; }
175+
void setLocation(langutil::SourceLocation const& _location)
176+
{
177+
solAssert(m_debugData);
178+
m_debugData = langutil::DebugData::create(
179+
_location,
180+
m_debugData->originLocation,
181+
m_debugData->astID
182+
);
183+
}
184+
185+
langutil::SourceLocation const& location() const
186+
{
187+
solAssert(m_debugData);
188+
return m_debugData->nativeLocation;
189+
}
190+
191+
void setDebugData(langutil::DebugData::ConstPtr _debugData)
192+
{
193+
solAssert(_debugData);
194+
m_debugData = std::move(_debugData);
195+
}
196+
197+
langutil::DebugData::ConstPtr debugData() const { return m_debugData; }
175198

176199
void setJumpType(JumpType _jumpType) { m_jumpType = _jumpType; }
177200
static std::optional<JumpType> parseJumpType(std::string const& _jumpType);
@@ -196,7 +219,7 @@ class AssemblyItem
196219
/// If m_type == VerbatimBytecode, this holds number of arguments, number of
197220
/// return variables and verbatim bytecode.
198221
std::optional<std::tuple<size_t, size_t, bytes>> m_verbatimBytecode;
199-
langutil::SourceLocation m_location;
222+
langutil::DebugData::ConstPtr m_debugData;
200223
JumpType m_jumpType = JumpType::Ordinary;
201224
/// Pushed value for operations with data to be determined during assembly stage,
202225
/// e.g. PushSubSize, PushTag, PushSub, etc.

libevmasm/CommonSubexpressionEliminator.cpp

+39-37
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <libsolutil/StackTooDeepString.h>
3030

3131
#include <range/v3/view/reverse.hpp>
32+
#include <utility>
3233

3334
using namespace solidity;
3435
using namespace solidity::evmasm;
@@ -57,9 +58,9 @@ std::vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems()
5758
if (!m_state.stackElements().empty())
5859
minHeight = std::min(minHeight, m_state.stackElements().begin()->first);
5960
for (int height = minHeight; height <= m_initialState.stackHeight(); ++height)
60-
initialStackContents[height] = m_initialState.stackElement(height, SourceLocation());
61+
initialStackContents[height] = m_initialState.stackElement(height, langutil::DebugData::create());
6162
for (int height = minHeight; height <= m_state.stackHeight(); ++height)
62-
targetStackContents[height] = m_state.stackElement(height, SourceLocation());
63+
targetStackContents[height] = m_state.stackElement(height, langutil::DebugData::create());
6364

6465
AssemblyItems items = CSECodeGenerator(m_state.expressionClasses(), m_storeOperations).generateCode(
6566
m_initialState.sequenceNumber(),
@@ -87,36 +88,37 @@ void CommonSubexpressionEliminator::optimizeBreakingItem()
8788

8889
ExpressionClasses& classes = m_state.expressionClasses();
8990
SourceLocation const& itemLocation = m_breakingItem->location();
91+
langutil::DebugData::ConstPtr debugData{langutil::DebugData::create(itemLocation)};
9092
if (*m_breakingItem == AssemblyItem(Instruction::JUMPI))
9193
{
9294
AssemblyItem::JumpType jumpType = m_breakingItem->getJumpType();
9395

94-
Id condition = m_state.stackElement(m_state.stackHeight() - 1, itemLocation);
96+
Id condition = m_state.stackElement(m_state.stackHeight() - 1, debugData);
9597
if (classes.knownNonZero(condition))
9698
{
97-
feedItem(AssemblyItem(Instruction::SWAP1, itemLocation), true);
98-
feedItem(AssemblyItem(Instruction::POP, itemLocation), true);
99+
feedItem(AssemblyItem(Instruction::SWAP1, debugData), true);
100+
feedItem(AssemblyItem(Instruction::POP, debugData), true);
99101

100-
AssemblyItem item(Instruction::JUMP, itemLocation);
102+
AssemblyItem item(Instruction::JUMP, debugData);
101103
item.setJumpType(jumpType);
102104
m_breakingItem = classes.storeItem(item);
103105
}
104106
else if (classes.knownZero(condition))
105107
{
106-
AssemblyItem it(Instruction::POP, itemLocation);
108+
AssemblyItem it(Instruction::POP, debugData);
107109
feedItem(it, true);
108110
feedItem(it, true);
109111
m_breakingItem = nullptr;
110112
}
111113
}
112114
else if (*m_breakingItem == AssemblyItem(Instruction::RETURN))
113115
{
114-
Id size = m_state.stackElement(m_state.stackHeight() - 1, itemLocation);
116+
Id size = m_state.stackElement(m_state.stackHeight() - 1, debugData);
115117
if (classes.knownZero(size))
116118
{
117-
feedItem(AssemblyItem(Instruction::POP, itemLocation), true);
118-
feedItem(AssemblyItem(Instruction::POP, itemLocation), true);
119-
AssemblyItem item(Instruction::STOP, itemLocation);
119+
feedItem(AssemblyItem(Instruction::POP, debugData), true);
120+
feedItem(AssemblyItem(Instruction::POP, debugData), true);
121+
AssemblyItem item(Instruction::STOP, debugData);
120122
m_breakingItem = classes.storeItem(item);
121123
}
122124
}
@@ -181,16 +183,16 @@ AssemblyItems CSECodeGenerator::generateCode(
181183
assertThrow(!m_classPositions[targetItem.second].empty(), OptimizerException, "");
182184
if (m_classPositions[targetItem.second].count(targetItem.first))
183185
continue;
184-
SourceLocation sourceLocation;
186+
langutil::DebugData::ConstPtr debugData;
185187
if (m_expressionClasses.representative(targetItem.second).item)
186-
sourceLocation = m_expressionClasses.representative(targetItem.second).item->location();
188+
debugData = m_expressionClasses.representative(targetItem.second).item->debugData();
187189
int position = classElementPosition(targetItem.second);
188190
if (position < targetItem.first)
189191
// it is already at its target, we need another copy
190-
appendDup(position, sourceLocation);
192+
appendDup(position, debugData);
191193
else
192-
appendOrRemoveSwap(position, sourceLocation);
193-
appendOrRemoveSwap(targetItem.first, sourceLocation);
194+
appendOrRemoveSwap(position, debugData);
195+
appendOrRemoveSwap(targetItem.first, debugData);
194196
}
195197

196198
// remove surplus elements
@@ -263,7 +265,7 @@ void CSECodeGenerator::addDependencies(Id _c)
263265
case Instruction::KECCAK256:
264266
{
265267
Id length = expr.arguments.at(1);
266-
AssemblyItem offsetInstr(Instruction::SUB, expr.item->location());
268+
AssemblyItem offsetInstr(Instruction::SUB, expr.item->debugData());
267269
Id offsetToStart = m_expressionClasses.find(offsetInstr, {slot, slotToLoadFrom});
268270
u256 const* o = m_expressionClasses.knownConstant(offsetToStart);
269271
u256 const* l = m_expressionClasses.knownConstant(length);
@@ -334,50 +336,50 @@ void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
334336
for (Id arg: arguments | ranges::views::reverse)
335337
generateClassElement(arg);
336338

337-
SourceLocation const& itemLocation = expr.item->location();
339+
langutil::DebugData::ConstPtr itemDebugData = expr.item->debugData();
338340
// The arguments are somewhere on the stack now, so it remains to move them at the correct place.
339341
// This is quite difficult as sometimes, the values also have to removed in this process
340342
// (if canBeRemoved() returns true) and the two arguments can be equal. For now, this is
341343
// implemented for every single case for combinations of up to two arguments manually.
342344
if (arguments.size() == 1)
343345
{
344346
if (canBeRemoved(arguments[0], _c))
345-
appendOrRemoveSwap(classElementPosition(arguments[0]), itemLocation);
347+
appendOrRemoveSwap(classElementPosition(arguments[0]), itemDebugData);
346348
else
347-
appendDup(classElementPosition(arguments[0]), itemLocation);
349+
appendDup(classElementPosition(arguments[0]), itemDebugData);
348350
}
349351
else if (arguments.size() == 2)
350352
{
351353
if (canBeRemoved(arguments[1], _c))
352354
{
353-
appendOrRemoveSwap(classElementPosition(arguments[1]), itemLocation);
355+
appendOrRemoveSwap(classElementPosition(arguments[1]), itemDebugData);
354356
if (arguments[0] == arguments[1])
355-
appendDup(m_stackHeight, itemLocation);
357+
appendDup(m_stackHeight, itemDebugData);
356358
else if (canBeRemoved(arguments[0], _c))
357359
{
358-
appendOrRemoveSwap(m_stackHeight - 1, itemLocation);
359-
appendOrRemoveSwap(classElementPosition(arguments[0]), itemLocation);
360+
appendOrRemoveSwap(m_stackHeight - 1, itemDebugData);
361+
appendOrRemoveSwap(classElementPosition(arguments[0]), itemDebugData);
360362
}
361363
else
362-
appendDup(classElementPosition(arguments[0]), itemLocation);
364+
appendDup(classElementPosition(arguments[0]), itemDebugData);
363365
}
364366
else
365367
{
366368
if (arguments[0] == arguments[1])
367369
{
368-
appendDup(classElementPosition(arguments[0]), itemLocation);
369-
appendDup(m_stackHeight, itemLocation);
370+
appendDup(classElementPosition(arguments[0]), itemDebugData);
371+
appendDup(m_stackHeight, itemDebugData);
370372
}
371373
else if (canBeRemoved(arguments[0], _c))
372374
{
373-
appendOrRemoveSwap(classElementPosition(arguments[0]), itemLocation);
374-
appendDup(classElementPosition(arguments[1]), itemLocation);
375-
appendOrRemoveSwap(m_stackHeight - 1, itemLocation);
375+
appendOrRemoveSwap(classElementPosition(arguments[0]), itemDebugData);
376+
appendDup(classElementPosition(arguments[1]), itemDebugData);
377+
appendOrRemoveSwap(m_stackHeight - 1, itemDebugData);
376378
}
377379
else
378380
{
379-
appendDup(classElementPosition(arguments[1]), itemLocation);
380-
appendDup(classElementPosition(arguments[0]), itemLocation);
381+
appendDup(classElementPosition(arguments[1]), itemDebugData);
382+
appendDup(classElementPosition(arguments[0]), itemDebugData);
381383
}
382384
}
383385
}
@@ -398,7 +400,7 @@ void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
398400
!m_generatedItems.empty() &&
399401
m_generatedItems.back() == AssemblyItem(Instruction::SWAP1))
400402
// this will not append a swap but remove the one that is already there
401-
appendOrRemoveSwap(m_stackHeight - 1, itemLocation);
403+
appendOrRemoveSwap(m_stackHeight - 1, itemDebugData);
402404
for (size_t i = 0; i < arguments.size(); ++i)
403405
{
404406
m_classPositions[m_stack[m_stackHeight - static_cast<int>(i)]].erase(m_stackHeight - static_cast<int>(i));
@@ -467,26 +469,26 @@ bool CSECodeGenerator::removeStackTopIfPossible()
467469
return true;
468470
}
469471

470-
void CSECodeGenerator::appendDup(int _fromPosition, SourceLocation const& _location)
472+
void CSECodeGenerator::appendDup(int _fromPosition, langutil::DebugData::ConstPtr _debugData)
471473
{
472474
assertThrow(_fromPosition != c_invalidPosition, OptimizerException, "");
473475
int instructionNum = 1 + m_stackHeight - _fromPosition;
474476
assertThrow(instructionNum <= 16, StackTooDeepException, util::stackTooDeepString);
475477
assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access.");
476-
appendItem(AssemblyItem(dupInstruction(static_cast<unsigned>(instructionNum)), _location));
478+
appendItem(AssemblyItem(dupInstruction(static_cast<unsigned>(instructionNum)), std::move(_debugData)));
477479
m_stack[m_stackHeight] = m_stack[_fromPosition];
478480
m_classPositions[m_stack[m_stackHeight]].insert(m_stackHeight);
479481
}
480482

481-
void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, SourceLocation const& _location)
483+
void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, langutil::DebugData::ConstPtr _debugData)
482484
{
483485
assertThrow(_fromPosition != c_invalidPosition, OptimizerException, "");
484486
if (_fromPosition == m_stackHeight)
485487
return;
486488
int instructionNum = m_stackHeight - _fromPosition;
487489
assertThrow(instructionNum <= 16, StackTooDeepException, util::stackTooDeepString);
488490
assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access.");
489-
appendItem(AssemblyItem(swapInstruction(static_cast<unsigned>(instructionNum)), _location));
491+
appendItem(AssemblyItem(swapInstruction(static_cast<unsigned>(instructionNum)), std::move(_debugData)));
490492

491493
if (m_stack[m_stackHeight] != m_stack[_fromPosition])
492494
{

libevmasm/CommonSubexpressionEliminator.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,10 @@ class CSECodeGenerator
142142
bool removeStackTopIfPossible();
143143

144144
/// Appends a dup instruction to m_generatedItems to retrieve the element at the given stack position.
145-
void appendDup(int _fromPosition, langutil::SourceLocation const& _location);
145+
void appendDup(int _fromPosition, langutil::DebugData::ConstPtr _debugData);
146146
/// Appends a swap instruction to m_generatedItems to retrieve the element at the given stack position.
147147
/// @note this might also remove the last item if it exactly the same swap instruction.
148-
void appendOrRemoveSwap(int _fromPosition, langutil::SourceLocation const& _location);
148+
void appendOrRemoveSwap(int _fromPosition, langutil::DebugData::ConstPtr _debugData);
149149
/// Appends the given assembly item.
150150
void appendItem(AssemblyItem const& _item);
151151

libevmasm/ControlFlowGraph.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ void ControlFlowGraph::gatherKnowledge()
275275
//@todo in the case of JUMPI, add knowledge about the condition to the state
276276
// (for both values of the condition)
277277
std::set<u256> tags = state->tagsInExpression(
278-
state->stackElement(state->stackHeight(), langutil::SourceLocation{})
278+
state->stackElement(state->stackHeight(), langutil::DebugData::create())
279279
);
280280
state->feedItem(m_items.at(pc++));
281281

libevmasm/ExpressionClasses.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <functional>
3434
#include <limits>
3535
#include <tuple>
36+
#include <utility>
3637

3738
using namespace solidity;
3839
using namespace solidity::evmasm;
@@ -134,11 +135,11 @@ void ExpressionClasses::forceEqual(
134135
m_expressions.insert(exp);
135136
}
136137

137-
ExpressionClasses::Id ExpressionClasses::newClass(SourceLocation const& _location)
138+
ExpressionClasses::Id ExpressionClasses::newClass(langutil::DebugData::ConstPtr _debugData)
138139
{
139140
Expression exp;
140141
exp.id = static_cast<Id>(m_representatives.size());
141-
exp.item = storeItem(AssemblyItem(UndefinedItem, (u256(1) << 255) + exp.id, _location));
142+
exp.item = storeItem(AssemblyItem(UndefinedItem, (u256(1) << 255) + exp.id, std::move(_debugData)));
142143
m_representatives.push_back(exp);
143144
m_expressions.insert(exp);
144145
return exp.id;
@@ -226,7 +227,7 @@ ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr)
226227
std::cout << "to " << match->action().toString() << std::endl;
227228
}
228229

229-
return rebuildExpression(ExpressionTemplate(match->action(), _expr.item->location()));
230+
return rebuildExpression(ExpressionTemplate(match->action(), _expr.item->debugData()));
230231
}
231232

232233
return std::numeric_limits<unsigned>::max();

libevmasm/ExpressionClasses.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ class ExpressionClasses
9292
void forceEqual(Id _id, AssemblyItem const& _item, Ids const& _arguments, bool _copyItem = true);
9393

9494
/// @returns the id of a new class which is different to all other classes.
95-
Id newClass(langutil::SourceLocation const& _location);
95+
Id newClass(langutil::DebugData::ConstPtr _debugData);
9696

9797
/// @returns true if the values of the given classes are known to be different (on every input).
9898
/// @note that this function might still return false for some different inputs.

0 commit comments

Comments
 (0)