Skip to content

Commit 6fcae57

Browse files
committed
Separate DebugData fields for Solidity and Yul source locations
1 parent 2c3322c commit 6fcae57

File tree

16 files changed

+234
-207
lines changed

16 files changed

+234
-207
lines changed

libsolidity/analysis/ControlFlowBuilder.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ bool ControlFlowBuilder::visit(InlineAssembly const& _inlineAssembly)
409409
void ControlFlowBuilder::visit(yul::Statement const& _statement)
410410
{
411411
solAssert(m_currentNode && m_inlineAssembly, "");
412-
m_currentNode->location = langutil::SourceLocation::smallestCovering(m_currentNode->location, locationOf(_statement));
412+
m_currentNode->location = langutil::SourceLocation::smallestCovering(m_currentNode->location, irLocationOf(_statement));
413413
ASTWalker::visit(_statement);
414414
}
415415

@@ -501,7 +501,7 @@ void ControlFlowBuilder::operator()(yul::Identifier const& _identifier)
501501
m_currentNode->variableOccurrences.emplace_back(
502502
*declaration,
503503
VariableOccurrence::Kind::Access,
504-
_identifier.debugData->location
504+
_identifier.debugData->irLocation
505505
);
506506
}
507507
}
@@ -517,7 +517,7 @@ void ControlFlowBuilder::operator()(yul::Assignment const& _assignment)
517517
m_currentNode->variableOccurrences.emplace_back(
518518
*declaration,
519519
VariableOccurrence::Kind::Assignment,
520-
variable.debugData->location
520+
variable.debugData->irLocation
521521
);
522522
}
523523

libsolidity/analysis/ReferencesResolver.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,9 @@ bool ReferencesResolver::visit(Return const& _return)
201201

202202
void ReferencesResolver::operator()(yul::FunctionDefinition const& _function)
203203
{
204-
validateYulIdentifierName(_function.name, _function.debugData->location);
204+
validateYulIdentifierName(_function.name, irLocationOf(_function));
205205
for (yul::TypedName const& varName: _function.parameters + _function.returnVariables)
206-
validateYulIdentifierName(varName.name, varName.debugData->location);
206+
validateYulIdentifierName(varName.name, irLocationOf(varName));
207207

208208
bool wasInsideFunction = m_yulInsideFunction;
209209
m_yulInsideFunction = true;
@@ -238,7 +238,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
238238
{
239239
m_errorReporter.declarationError(
240240
4718_error,
241-
_identifier.debugData->location,
241+
irLocationOf(_identifier),
242242
"Multiple matching identifiers. Resolving overloaded identifiers is not supported."
243243
);
244244
return;
@@ -251,7 +251,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
251251
)
252252
m_errorReporter.declarationError(
253253
9467_error,
254-
_identifier.debugData->location,
254+
irLocationOf(_identifier),
255255
"Identifier not found. Use \".slot\" and \".offset\" to access storage variables."
256256
);
257257
return;
@@ -261,7 +261,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
261261
{
262262
m_errorReporter.declarationError(
263263
6578_error,
264-
_identifier.debugData->location,
264+
irLocationOf(_identifier),
265265
"Cannot access local Solidity variables from inside an inline assembly function."
266266
);
267267
return;
@@ -275,7 +275,7 @@ void ReferencesResolver::operator()(yul::VariableDeclaration const& _varDecl)
275275
{
276276
for (auto const& identifier: _varDecl.variables)
277277
{
278-
validateYulIdentifierName(identifier.name, identifier.debugData->location);
278+
validateYulIdentifierName(identifier.name, irLocationOf(identifier));
279279

280280

281281
if (
@@ -289,7 +289,7 @@ void ReferencesResolver::operator()(yul::VariableDeclaration const& _varDecl)
289289
if (!ssl.infos.empty())
290290
m_errorReporter.declarationError(
291291
3859_error,
292-
identifier.debugData->location,
292+
irLocationOf(identifier),
293293
ssl,
294294
"This declaration shadows a declaration outside the inline assembly block."
295295
);

libsolidity/analysis/TypeChecker.cpp

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
772772
solAssert(var->type(), "Expected variable type!");
773773
if (var->immutable())
774774
{
775-
m_errorReporter.typeError(3773_error, _identifier.debugData->location, "Assembly access to immutable variables is not supported.");
775+
m_errorReporter.typeError(3773_error, irLocationOf(_identifier), "Assembly access to immutable variables is not supported.");
776776
return false;
777777
}
778778
if (var->isConstant())
@@ -781,7 +781,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
781781
{
782782
m_errorReporter.typeError(
783783
3558_error,
784-
_identifier.debugData->location,
784+
irLocationOf(_identifier),
785785
"Constant variable is circular."
786786
);
787787
return false;
@@ -791,24 +791,24 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
791791

792792
if (var && !var->value())
793793
{
794-
m_errorReporter.typeError(3224_error, _identifier.debugData->location, "Constant has no value.");
794+
m_errorReporter.typeError(3224_error, irLocationOf(_identifier), "Constant has no value.");
795795
return false;
796796
}
797797
else if (_context == yul::IdentifierContext::LValue)
798798
{
799-
m_errorReporter.typeError(6252_error, _identifier.debugData->location, "Constant variables cannot be assigned to.");
799+
m_errorReporter.typeError(6252_error, irLocationOf(_identifier), "Constant variables cannot be assigned to.");
800800
return false;
801801
}
802802
else if (!identifierInfo.suffix.empty())
803803
{
804-
m_errorReporter.typeError(6617_error, _identifier.debugData->location, "The suffixes .offset and .slot can only be used on non-constant storage variables.");
804+
m_errorReporter.typeError(6617_error, irLocationOf(_identifier), "The suffixes .offset and .slot can only be used on non-constant storage variables.");
805805
return false;
806806
}
807807
else if (var && var->value() && !var->value()->annotation().type && !dynamic_cast<Literal const*>(var->value().get()))
808808
{
809809
m_errorReporter.typeError(
810810
2249_error,
811-
_identifier.debugData->location,
811+
irLocationOf(_identifier),
812812
"Constant variables with non-literal values cannot be forward referenced from inline assembly."
813813
);
814814
return false;
@@ -818,7 +818,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
818818
type(*var->value())->category() != Type::Category::RationalNumber
819819
))
820820
{
821-
m_errorReporter.typeError(7615_error, _identifier.debugData->location, "Only direct number constants and references to such constants are supported by inline assembly.");
821+
m_errorReporter.typeError(7615_error, irLocationOf(_identifier), "Only direct number constants and references to such constants are supported by inline assembly.");
822822
return false;
823823
}
824824
}
@@ -833,19 +833,19 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
833833
{
834834
if (suffix != "slot" && suffix != "offset")
835835
{
836-
m_errorReporter.typeError(4656_error, _identifier.debugData->location, "State variables only support \".slot\" and \".offset\".");
836+
m_errorReporter.typeError(4656_error, irLocationOf(_identifier), "State variables only support \".slot\" and \".offset\".");
837837
return false;
838838
}
839839
else if (_context == yul::IdentifierContext::LValue)
840840
{
841841
if (var->isStateVariable())
842842
{
843-
m_errorReporter.typeError(4713_error, _identifier.debugData->location, "State variables cannot be assigned to - you have to use \"sstore()\".");
843+
m_errorReporter.typeError(4713_error, irLocationOf(_identifier), "State variables cannot be assigned to - you have to use \"sstore()\".");
844844
return false;
845845
}
846846
else if (suffix != "slot")
847847
{
848-
m_errorReporter.typeError(9739_error, _identifier.debugData->location, "Only .slot can be assigned to.");
848+
m_errorReporter.typeError(9739_error, irLocationOf(_identifier), "Only .slot can be assigned to.");
849849
return false;
850850
}
851851
}
@@ -857,28 +857,28 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
857857
{
858858
if (suffix != "offset" && suffix != "length")
859859
{
860-
m_errorReporter.typeError(1536_error, _identifier.debugData->location, "Calldata variables only support \".offset\" and \".length\".");
860+
m_errorReporter.typeError(1536_error, irLocationOf(_identifier), "Calldata variables only support \".offset\" and \".length\".");
861861
return false;
862862
}
863863
}
864864
else
865865
{
866-
m_errorReporter.typeError(3622_error, _identifier.debugData->location, "The suffix \"." + suffix + "\" is not supported by this variable or type.");
866+
m_errorReporter.typeError(3622_error, irLocationOf(_identifier), "The suffix \"." + suffix + "\" is not supported by this variable or type.");
867867
return false;
868868
}
869869
}
870870
else if (!var->isConstant() && var->isStateVariable())
871871
{
872872
m_errorReporter.typeError(
873873
1408_error,
874-
_identifier.debugData->location,
874+
irLocationOf(_identifier),
875875
"Only local variables are supported. To access storage variables, use the \".slot\" and \".offset\" suffixes."
876876
);
877877
return false;
878878
}
879879
else if (var->type()->dataStoredIn(DataLocation::Storage))
880880
{
881-
m_errorReporter.typeError(9068_error, _identifier.debugData->location, "You have to use the \".slot\" or \".offset\" suffix to access storage reference variables.");
881+
m_errorReporter.typeError(9068_error, irLocationOf(_identifier), "You have to use the \".slot\" or \".offset\" suffix to access storage reference variables.");
882882
return false;
883883
}
884884
else if (var->type()->sizeOnStack() != 1)
@@ -887,26 +887,26 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
887887
auto const* arrayType = dynamic_cast<ArrayType const*>(var->type());
888888
arrayType && arrayType->isDynamicallySized() && arrayType->dataStoredIn(DataLocation::CallData)
889889
)
890-
m_errorReporter.typeError(1397_error, _identifier.debugData->location, "Call data elements cannot be accessed directly. Use \".offset\" and \".length\" to access the calldata offset and length of this array and then use \"calldatacopy\".");
890+
m_errorReporter.typeError(1397_error, irLocationOf(_identifier), "Call data elements cannot be accessed directly. Use \".offset\" and \".length\" to access the calldata offset and length of this array and then use \"calldatacopy\".");
891891
else
892892
{
893893
solAssert(!var->type()->dataStoredIn(DataLocation::CallData), "");
894-
m_errorReporter.typeError(9857_error, _identifier.debugData->location, "Only types that use one stack slot are supported.");
894+
m_errorReporter.typeError(9857_error, irLocationOf(_identifier), "Only types that use one stack slot are supported.");
895895
}
896896
return false;
897897
}
898898
}
899899
else if (!identifierInfo.suffix.empty())
900900
{
901-
m_errorReporter.typeError(7944_error, _identifier.debugData->location, "The suffixes \".offset\", \".slot\" and \".length\" can only be used with variables.");
901+
m_errorReporter.typeError(7944_error, irLocationOf(_identifier), "The suffixes \".offset\", \".slot\" and \".length\" can only be used with variables.");
902902
return false;
903903
}
904904
else if (_context == yul::IdentifierContext::LValue)
905905
{
906906
if (dynamic_cast<MagicVariableDeclaration const*>(declaration))
907907
return false;
908908

909-
m_errorReporter.typeError(1990_error, _identifier.debugData->location, "Only local variables can be assigned to in inline assembly.");
909+
m_errorReporter.typeError(1990_error, irLocationOf(_identifier), "Only local variables can be assigned to in inline assembly.");
910910
return false;
911911
}
912912

@@ -915,7 +915,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
915915
solAssert(!!declaration->type(), "Type of declaration required but not yet determined.");
916916
if (dynamic_cast<FunctionDefinition const*>(declaration))
917917
{
918-
m_errorReporter.declarationError(2025_error, _identifier.debugData->location, "Access to functions is not allowed in inline assembly.");
918+
m_errorReporter.declarationError(2025_error, irLocationOf(_identifier), "Access to functions is not allowed in inline assembly.");
919919
return false;
920920
}
921921
else if (dynamic_cast<VariableDeclaration const*>(declaration))
@@ -925,7 +925,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
925925
{
926926
if (!contract->isLibrary())
927927
{
928-
m_errorReporter.typeError(4977_error, _identifier.debugData->location, "Expected a library.");
928+
m_errorReporter.typeError(4977_error, irLocationOf(_identifier), "Expected a library.");
929929
return false;
930930
}
931931
}

libsolidity/analysis/ViewPureChecker.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class AssemblyViewPureChecker
6969
if (yul::EVMDialect const* dialect = dynamic_cast<decltype(dialect)>(&m_dialect))
7070
if (yul::BuiltinFunctionForEVM const* fun = dialect->builtin(_funCall.functionName.name))
7171
if (fun->instruction)
72-
checkInstruction(_funCall.debugData->location, *fun->instruction);
72+
checkInstruction(_funCall.debugData->irLocation, *fun->instruction);
7373

7474
for (auto const& arg: _funCall.arguments)
7575
std::visit(*this, arg);

libsolidity/ast/ASTJsonConverter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,10 @@ void ASTJsonConverter::appendExpressionAttributes(
171171
_attributes += exprAttributes;
172172
}
173173

174-
Json::Value ASTJsonConverter::inlineAssemblyIdentifierToJson(pair<yul::Identifier const* ,InlineAssemblyAnnotation::ExternalIdentifierInfo> _info) const
174+
Json::Value ASTJsonConverter::inlineAssemblyIdentifierToJson(pair<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo> _info) const
175175
{
176176
Json::Value tuple(Json::objectValue);
177-
tuple["src"] = sourceLocationToString(_info.first->debugData->location);
177+
tuple["src"] = sourceLocationToString(irLocationOf(*_info.first));
178178
tuple["declaration"] = idOrNull(_info.second.declaration);
179179
tuple["isSlot"] = Json::Value(_info.second.suffix == "slot");
180180
tuple["isOffset"] = Json::Value(_info.second.suffix == "offset");

libsolidity/codegen/CompilerContext.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ void CompilerContext::appendInlineAssembly(
421421
if (stackDiff < 1 || stackDiff > 16)
422422
BOOST_THROW_EXCEPTION(
423423
StackTooDeepError() <<
424-
errinfo_sourceLocation(_identifier.debugData->location) <<
424+
errinfo_sourceLocation(irLocationOf(_identifier)) <<
425425
util::errinfo_comment("Stack too deep (" + to_string(stackDiff) + "), try removing local variables.")
426426
);
427427
if (_context == yul::IdentifierContext::RValue)

libsolidity/parsing/Parser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1326,7 +1326,7 @@ ASTPointer<InlineAssembly> Parser::parseInlineAssembly(ASTPointer<ASTString> con
13261326
if (block == nullptr)
13271327
BOOST_THROW_EXCEPTION(FatalError());
13281328

1329-
location.end = block->debugData->location.end;
1329+
location.end = irLocationOf(*block).end;
13301330
return make_shared<InlineAssembly>(nextID(), location, _docString, dialect, block);
13311331
}
13321332

libyul/AST.h

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,34 @@ using Type = YulString;
3838

3939
struct DebugData
4040
{
41-
explicit DebugData(langutil::SourceLocation _location, std::optional<int64_t> _astID = {}):
42-
location(std::move(_location)),
41+
explicit DebugData(
42+
langutil::SourceLocation _irLocation,
43+
langutil::SourceLocation _originalLocation = {},
44+
std::optional<int64_t> _astID = {}
45+
):
46+
irLocation(std::move(_irLocation)),
47+
originalLocation(std::move(_originalLocation)),
4348
astID(std::move(_astID))
4449
{}
4550

4651
static std::shared_ptr<DebugData const> create(
47-
langutil::SourceLocation _location = {},
52+
langutil::SourceLocation _irLocation = {},
53+
langutil::SourceLocation _originalLocation = {},
4854
std::optional<int64_t> _astID = {}
4955
)
5056
{
51-
return std::make_shared<DebugData const>(std::move(_location), std::move(_astID));
57+
return std::make_shared<DebugData const>(
58+
std::move(_irLocation),
59+
std::move(_originalLocation),
60+
std::move(_astID)
61+
);
5262
}
5363

54-
langutil::SourceLocation location;
64+
/// Location in the Yul code.
65+
langutil::SourceLocation irLocation;
66+
/// Location in the original source that the Yul code was produced from.
67+
/// Optional. Only present if the Yul source contains location annotations.
68+
langutil::SourceLocation originalLocation;
5569
/// ID in the (Solidity) source AST.
5670
std::optional<int64_t> astID;
5771
};
@@ -94,16 +108,28 @@ struct Continue { std::shared_ptr<DebugData const> debugData; };
94108
/// Leave statement (valid within function)
95109
struct Leave { std::shared_ptr<DebugData const> debugData; };
96110

97-
/// Extracts the source location from a Yul node.
98-
template <class T> inline langutil::SourceLocation locationOf(T const& _node)
111+
/// Extracts the IR source location from a Yul node.
112+
template <class T> inline langutil::SourceLocation irLocationOf(T const& _node)
113+
{
114+
return _node.debugData ? _node.debugData->irLocation : langutil::SourceLocation{};
115+
}
116+
117+
/// Extracts the IR source location from a Yul node.
118+
template <class... Args> inline langutil::SourceLocation irLocationOf(std::variant<Args...> const& _node)
119+
{
120+
return std::visit([](auto const& _arg) { return irLocationOf(_arg); }, _node);
121+
}
122+
123+
/// Extracts the original source location from a Yul node.
124+
template <class T> inline langutil::SourceLocation originalLocationOf(T const& _node)
99125
{
100-
return _node.debugData ? _node.debugData->location : langutil::SourceLocation{};
126+
return _node.debugData ? _node.debugData->originalLocation : langutil::SourceLocation{};
101127
}
102128

103-
/// Extracts the source location from a Yul node.
104-
template <class... Args> inline langutil::SourceLocation locationOf(std::variant<Args...> const& _node)
129+
/// Extracts the original source location from a Yul node.
130+
template <class... Args> inline langutil::SourceLocation originalLocationOf(std::variant<Args...> const& _node)
105131
{
106-
return std::visit([](auto const& _arg) { return locationOf(_arg); }, _node);
132+
return std::visit([](auto const& _arg) { return originalLocationOf(_arg); }, _node);
107133
}
108134

109135
/// Extracts the debug data from a Yul node.

0 commit comments

Comments
 (0)