Refactoring yul AST structures to include debugdata instead of location.

This commit is contained in:
Djordje Mijovic 2021-04-14 16:40:45 +02:00
parent cc65b426d0
commit 0563e826b5
50 changed files with 371 additions and 322 deletions

View File

@ -390,7 +390,7 @@ bool ControlFlowBuilder::visit(InlineAssembly const& _inlineAssembly)
void ControlFlowBuilder::visit(yul::Statement const& _statement)
{
solAssert(m_currentNode && m_inlineAssembly, "");
m_currentNode->location = langutil::SourceLocation::smallestCovering(m_currentNode->location, locationOf(_statement));
m_currentNode->location = langutil::SourceLocation::smallestCovering(m_currentNode->location, locationOf(_statement)->irLocation);
ASTWalker::visit(_statement);
}
@ -482,8 +482,7 @@ void ControlFlowBuilder::operator()(yul::Identifier const& _identifier)
m_currentNode->variableOccurrences.emplace_back(
*declaration,
VariableOccurrence::Kind::Access,
_identifier.location
);
_identifier.debugData->irLocation);
}
}
@ -498,8 +497,7 @@ void ControlFlowBuilder::operator()(yul::Assignment const& _assignment)
m_currentNode->variableOccurrences.emplace_back(
*declaration,
VariableOccurrence::Kind::Assignment,
variable.location
);
variable.debugData->irLocation);
}
void ControlFlowBuilder::operator()(yul::FunctionCall const& _functionCall)

View File

@ -201,9 +201,9 @@ bool ReferencesResolver::visit(Return const& _return)
void ReferencesResolver::operator()(yul::FunctionDefinition const& _function)
{
validateYulIdentifierName(_function.name, _function.location);
validateYulIdentifierName(_function.name, _function.debugData->irLocation);
for (yul::TypedName const& varName: _function.parameters + _function.returnVariables)
validateYulIdentifierName(varName.name, varName.location);
validateYulIdentifierName(varName.name, varName.debugData->irLocation);
bool wasInsideFunction = m_yulInsideFunction;
m_yulInsideFunction = true;
@ -238,7 +238,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
{
m_errorReporter.declarationError(
4718_error,
_identifier.location,
_identifier.debugData->irLocation,
"Multiple matching identifiers. Resolving overloaded identifiers is not supported."
);
return;
@ -251,7 +251,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
)
m_errorReporter.declarationError(
9467_error,
_identifier.location,
_identifier.debugData->irLocation,
"Identifier not found. Use \".slot\" and \".offset\" to access storage variables."
);
return;
@ -261,7 +261,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
{
m_errorReporter.declarationError(
6578_error,
_identifier.location,
_identifier.debugData->irLocation,
"Cannot access local Solidity variables from inside an inline assembly function."
);
return;
@ -275,7 +275,7 @@ void ReferencesResolver::operator()(yul::VariableDeclaration const& _varDecl)
{
for (auto const& identifier: _varDecl.variables)
{
validateYulIdentifierName(identifier.name, identifier.location);
validateYulIdentifierName(identifier.name, identifier.debugData->irLocation);
if (
@ -289,7 +289,7 @@ void ReferencesResolver::operator()(yul::VariableDeclaration const& _varDecl)
if (!ssl.infos.empty())
m_errorReporter.declarationError(
3859_error,
identifier.location,
identifier.debugData->irLocation,
ssl,
"This declaration shadows a declaration outside the inline assembly block."
);

View File

@ -743,7 +743,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
solAssert(var->type(), "Expected variable type!");
if (var->immutable())
{
m_errorReporter.typeError(3773_error, _identifier.location, "Assembly access to immutable variables is not supported.");
m_errorReporter.typeError(3773_error, _identifier.debugData->irLocation, "Assembly access to immutable variables is not supported.");
return false;
}
if (var->isConstant())
@ -752,7 +752,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
{
m_errorReporter.typeError(
3558_error,
_identifier.location,
_identifier.debugData->irLocation,
"Constant variable is circular."
);
return false;
@ -762,24 +762,24 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
if (var && !var->value())
{
m_errorReporter.typeError(3224_error, _identifier.location, "Constant has no value.");
m_errorReporter.typeError(3224_error, _identifier.debugData->irLocation, "Constant has no value.");
return false;
}
else if (_context == yul::IdentifierContext::LValue)
{
m_errorReporter.typeError(6252_error, _identifier.location, "Constant variables cannot be assigned to.");
m_errorReporter.typeError(6252_error, _identifier.debugData->irLocation, "Constant variables cannot be assigned to.");
return false;
}
else if (!identifierInfo.suffix.empty())
{
m_errorReporter.typeError(6617_error, _identifier.location, "The suffixes .offset and .slot can only be used on non-constant storage variables.");
m_errorReporter.typeError(6617_error, _identifier.debugData->irLocation, "The suffixes .offset and .slot can only be used on non-constant storage variables.");
return false;
}
else if (var && var->value() && !var->value()->annotation().type && !dynamic_cast<Literal const*>(var->value().get()))
{
m_errorReporter.typeError(
2249_error,
_identifier.location,
_identifier.debugData->irLocation,
"Constant variables with non-literal values cannot be forward referenced from inline assembly."
);
return false;
@ -789,7 +789,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
type(*var->value())->category() != Type::Category::RationalNumber
))
{
m_errorReporter.typeError(7615_error, _identifier.location, "Only direct number constants and references to such constants are supported by inline assembly.");
m_errorReporter.typeError(7615_error, _identifier.debugData->irLocation, "Only direct number constants and references to such constants are supported by inline assembly.");
return false;
}
}
@ -804,19 +804,19 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
{
if (suffix != "slot" && suffix != "offset")
{
m_errorReporter.typeError(4656_error, _identifier.location, "State variables only support \".slot\" and \".offset\".");
m_errorReporter.typeError(4656_error, _identifier.debugData->irLocation, "State variables only support \".slot\" and \".offset\".");
return false;
}
else if (_context == yul::IdentifierContext::LValue)
{
if (var->isStateVariable())
{
m_errorReporter.typeError(4713_error, _identifier.location, "State variables cannot be assigned to - you have to use \"sstore()\".");
m_errorReporter.typeError(4713_error, _identifier.debugData->irLocation, "State variables cannot be assigned to - you have to use \"sstore()\".");
return false;
}
else if (suffix != "slot")
{
m_errorReporter.typeError(9739_error, _identifier.location, "Only .slot can be assigned to.");
m_errorReporter.typeError(9739_error, _identifier.debugData->irLocation, "Only .slot can be assigned to.");
return false;
}
}
@ -828,13 +828,13 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
{
if (suffix != "offset" && suffix != "length")
{
m_errorReporter.typeError(1536_error, _identifier.location, "Calldata variables only support \".offset\" and \".length\".");
m_errorReporter.typeError(1536_error, _identifier.debugData->irLocation, "Calldata variables only support \".offset\" and \".length\".");
return false;
}
}
else
{
m_errorReporter.typeError(3622_error, _identifier.location, "The suffix \"." + suffix + "\" is not supported by this variable or type.");
m_errorReporter.typeError(3622_error, _identifier.debugData->irLocation, "The suffix \"." + suffix + "\" is not supported by this variable or type.");
return false;
}
}
@ -842,14 +842,14 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
{
m_errorReporter.typeError(
1408_error,
_identifier.location,
_identifier.debugData->irLocation,
"Only local variables are supported. To access storage variables, use the \".slot\" and \".offset\" suffixes."
);
return false;
}
else if (var->type()->dataStoredIn(DataLocation::Storage))
{
m_errorReporter.typeError(9068_error, _identifier.location, "You have to use the \".slot\" or \".offset\" suffix to access storage reference variables.");
m_errorReporter.typeError(9068_error, _identifier.debugData->irLocation, "You have to use the \".slot\" or \".offset\" suffix to access storage reference variables.");
return false;
}
else if (var->type()->sizeOnStack() != 1)
@ -858,18 +858,18 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
auto const* arrayType = dynamic_cast<ArrayType const*>(var->type());
arrayType && arrayType->isDynamicallySized() && arrayType->dataStoredIn(DataLocation::CallData)
)
m_errorReporter.typeError(1397_error, _identifier.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\".");
m_errorReporter.typeError(1397_error, _identifier.debugData->irLocation, "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\".");
else
{
solAssert(!var->type()->dataStoredIn(DataLocation::CallData), "");
m_errorReporter.typeError(9857_error, _identifier.location, "Only types that use one stack slot are supported.");
m_errorReporter.typeError(9857_error, _identifier.debugData->irLocation, "Only types that use one stack slot are supported.");
}
return false;
}
}
else if (!identifierInfo.suffix.empty())
{
m_errorReporter.typeError(7944_error, _identifier.location, "The suffixes \".offset\", \".slot\" and \".length\" can only be used with variables.");
m_errorReporter.typeError(7944_error, _identifier.debugData->irLocation, "The suffixes \".offset\", \".slot\" and \".length\" can only be used with variables.");
return false;
}
else if (_context == yul::IdentifierContext::LValue)
@ -877,7 +877,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
if (dynamic_cast<MagicVariableDeclaration const*>(declaration))
return false;
m_errorReporter.typeError(1990_error, _identifier.location, "Only local variables can be assigned to in inline assembly.");
m_errorReporter.typeError(1990_error, _identifier.debugData->irLocation, "Only local variables can be assigned to in inline assembly.");
return false;
}
@ -886,7 +886,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
solAssert(!!declaration->type(), "Type of declaration required but not yet determined.");
if (dynamic_cast<FunctionDefinition const*>(declaration))
{
m_errorReporter.declarationError(2025_error, _identifier.location, "Access to functions is not allowed in inline assembly.");
m_errorReporter.declarationError(2025_error, _identifier.debugData->irLocation, "Access to functions is not allowed in inline assembly.");
return false;
}
else if (dynamic_cast<VariableDeclaration const*>(declaration))
@ -896,7 +896,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
{
if (!contract->isLibrary())
{
m_errorReporter.typeError(4977_error, _identifier.location, "Expected a library.");
m_errorReporter.typeError(4977_error, _identifier.debugData->irLocation, "Expected a library.");
return false;
}
}

View File

@ -69,7 +69,7 @@ public:
if (yul::EVMDialect const* dialect = dynamic_cast<decltype(dialect)>(&m_dialect))
if (yul::BuiltinFunctionForEVM const* fun = dialect->builtin(_funCall.functionName.name))
if (fun->instruction)
checkInstruction(_funCall.location, *fun->instruction);
checkInstruction(_funCall.debugData->irLocation, *fun->instruction);
for (auto const& arg: _funCall.arguments)
std::visit(*this, arg);

View File

@ -175,7 +175,7 @@ void ASTJsonConverter::appendExpressionAttributes(
Json::Value ASTJsonConverter::inlineAssemblyIdentifierToJson(pair<yul::Identifier const* ,InlineAssemblyAnnotation::ExternalIdentifierInfo> _info) const
{
Json::Value tuple(Json::objectValue);
tuple["src"] = sourceLocationToString(_info.first->location);
tuple["src"] = sourceLocationToString(_info.first->debugData->irLocation);
tuple["declaration"] = idOrNull(_info.second.declaration);
tuple["isSlot"] = Json::Value(_info.second.suffix == "slot");
tuple["isOffset"] = Json::Value(_info.second.suffix == "offset");

View File

@ -426,7 +426,7 @@ void CompilerContext::appendInlineAssembly(
if (stackDiff < 1 || stackDiff > 16)
BOOST_THROW_EXCEPTION(
StackTooDeepError() <<
errinfo_sourceLocation(_identifier.location) <<
errinfo_sourceLocation(_identifier.debugData->irLocation) <<
util::errinfo_comment("Stack too deep (" + to_string(stackDiff) + "), try removing local variables.")
);
if (_context == yul::IdentifierContext::RValue)

View File

@ -192,9 +192,9 @@ private:
solAssert(false, "");
if (isdigit(value.front()))
return yul::Literal{_identifier.location, yul::LiteralKind::Number, yul::YulString{value}, {}};
return yul::Literal{_identifier.debugData, yul::LiteralKind::Number, yul::YulString{value}, {}};
else
return yul::Identifier{_identifier.location, yul::YulString{value}};
return yul::Identifier{_identifier.debugData, yul::YulString{value}};
}
@ -3167,6 +3167,23 @@ bool IRGeneratorForStatements::visit(TryCatchClause const& _clause)
void IRGeneratorForStatements::setLocation(ASTNode const& _node)
{
m_currentLocation = _node.location();
appendCurrentLocation();
}
void IRGeneratorForStatements::appendCurrentLocation()
{
if (m_currentLocation.isValid() && m_code.tellp() != m_lastSourceLocationPosition)
{
m_code <<
"/// @origin " <<
m_currentLocation.source->name() <<
":" <<
m_currentLocation.start <<
"," <<
m_currentLocation.end <<
"\n";
m_lastSourceLocationPosition = m_code.tellp();
}
}
string IRGeneratorForStatements::linkerSymbol(ContractDefinition const& _library) const

View File

@ -195,6 +195,8 @@ private:
void setLocation(ASTNode const& _node);
void appendCurrentLocation();
std::string linkerSymbol(ContractDefinition const& _library) const;
std::ostringstream m_code;
@ -203,6 +205,7 @@ private:
YulUtilFunctions& m_utils;
std::optional<IRLValue> m_currentLValue;
langutil::SourceLocation m_currentLocation;
std::streampos m_lastSourceLocationPosition;
};
}

View File

@ -1302,7 +1302,7 @@ ASTPointer<InlineAssembly> Parser::parseInlineAssembly(ASTPointer<ASTString> con
if (block == nullptr)
BOOST_THROW_EXCEPTION(FatalError());
location.end = block->location.end;
location.end = block->debugData->irLocation.end;
return make_shared<InlineAssembly>(nextID(), location, _docString, dialect, block);
}

View File

@ -35,54 +35,62 @@ namespace solidity::yul
using Type = YulString;
struct TypedName { langutil::SourceLocation location; YulString name; Type type; };
struct DebugData
{
explicit DebugData(langutil::SourceLocation _yulLocation = {}, langutil::SourceLocation _sollLocation = {}): irLocation(std::move(_yulLocation)), originLocation(std::move(_sollLocation))
{}
langutil::SourceLocation irLocation;
langutil::SourceLocation originLocation;
};
struct TypedName { std::shared_ptr<DebugData> debugData; YulString name; Type type; };
using TypedNameList = std::vector<TypedName>;
/// Literal number or string (up to 32 bytes)
enum class LiteralKind { Number, Boolean, String };
struct Literal { langutil::SourceLocation location; LiteralKind kind; YulString value; Type type; };
struct Literal { std::shared_ptr<DebugData> debugData; LiteralKind kind; YulString value; Type type; };
/// External / internal identifier or label reference
struct Identifier { langutil::SourceLocation location; YulString name; };
struct Identifier { std::shared_ptr<DebugData> debugData; YulString name; };
/// Assignment ("x := mload(20:u256)", expects push-1-expression on the right hand
/// side and requires x to occupy exactly one stack slot.
///
/// Multiple assignment ("x, y := f()"), where the left hand side variables each occupy
/// a single stack slot and expects a single expression on the right hand returning
/// the same amount of items as the number of variables.
struct Assignment { langutil::SourceLocation location; std::vector<Identifier> variableNames; std::unique_ptr<Expression> value; };
struct FunctionCall { langutil::SourceLocation location; Identifier functionName; std::vector<Expression> arguments; };
struct Assignment { std::shared_ptr<DebugData> debugData; std::vector<Identifier> variableNames; std::unique_ptr<Expression> value; };
struct FunctionCall { std::shared_ptr<DebugData> debugData; Identifier functionName; std::vector<Expression> arguments; };
/// Statement that contains only a single expression
struct ExpressionStatement { langutil::SourceLocation location; Expression expression; };
struct ExpressionStatement { std::shared_ptr<DebugData> debugData; Expression expression; };
/// Block-scope variable declaration ("let x:u256 := mload(20:u256)"), non-hoisted
struct VariableDeclaration { langutil::SourceLocation location; TypedNameList variables; std::unique_ptr<Expression> value; };
struct VariableDeclaration { std::shared_ptr<DebugData> debugData; TypedNameList variables; std::unique_ptr<Expression> value; };
/// Block that creates a scope (frees declared stack variables)
struct Block { langutil::SourceLocation location; std::vector<Statement> statements; };
struct Block { std::shared_ptr<DebugData> debugData; std::vector<Statement> statements; };
/// Function definition ("function f(a, b) -> (d, e) { ... }")
struct FunctionDefinition { langutil::SourceLocation location; YulString name; TypedNameList parameters; TypedNameList returnVariables; Block body; };
struct FunctionDefinition { std::shared_ptr<DebugData> debugData; YulString name; TypedNameList parameters; TypedNameList returnVariables; Block body; };
/// Conditional execution without "else" part.
struct If { langutil::SourceLocation location; std::unique_ptr<Expression> condition; Block body; };
struct If { std::shared_ptr<DebugData> debugData; std::unique_ptr<Expression> condition; Block body; };
/// Switch case or default case
struct Case { langutil::SourceLocation location; std::unique_ptr<Literal> value; Block body; };
struct Case { std::shared_ptr<DebugData> debugData; std::unique_ptr<Literal> value; Block body; };
/// Switch statement
struct Switch { langutil::SourceLocation location; std::unique_ptr<Expression> expression; std::vector<Case> cases; };
struct ForLoop { langutil::SourceLocation location; Block pre; std::unique_ptr<Expression> condition; Block post; Block body; };
struct Switch { std::shared_ptr<DebugData> debugData; std::unique_ptr<Expression> expression; std::vector<Case> cases; };
struct ForLoop { std::shared_ptr<DebugData> debugData; Block pre; std::unique_ptr<Expression> condition; Block post; Block body; };
/// Break statement (valid within for loop)
struct Break { langutil::SourceLocation location; };
struct Break { std::shared_ptr<DebugData> debugData; };
/// Continue statement (valid within for loop)
struct Continue { langutil::SourceLocation location; };
struct Continue { std::shared_ptr<DebugData> debugData; };
/// Leave statement (valid within function)
struct Leave { langutil::SourceLocation location; };
struct Leave { std::shared_ptr<DebugData> debugData; };
struct LocationExtractor
{
template <class T> langutil::SourceLocation operator()(T const& _node) const
template <class T> std::shared_ptr<DebugData> operator()(T const& _node) const
{
return _node.location;
return _node.debugData;
}
};
/// Extracts the source location from an inline assembly node.
template <class T> inline langutil::SourceLocation locationOf(T const& _node)
template <class T> inline std::shared_ptr<DebugData> locationOf(T const& _node)
{
return std::visit(LocationExtractor(), _node);
}

View File

@ -28,6 +28,7 @@
namespace solidity::yul
{
struct DebugData;
enum class LiteralKind;
struct Literal;
struct Label;

View File

@ -97,22 +97,22 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect,
vector<YulString> AsmAnalyzer::operator()(Literal const& _literal)
{
expectValidType(_literal.type, _literal.location);
expectValidType(_literal.type, _literal.debugData->irLocation);
if (_literal.kind == LiteralKind::String && _literal.value.str().size() > 32)
m_errorReporter.typeError(
3069_error,
_literal.location,
_literal.debugData->irLocation,
"String literal too long (" + to_string(_literal.value.str().size()) + " > 32)"
);
else if (_literal.kind == LiteralKind::Number && bigint(_literal.value.str()) > u256(-1))
m_errorReporter.typeError(6708_error, _literal.location, "Number literal too large (> 256 bits)");
m_errorReporter.typeError(6708_error, _literal.debugData->irLocation, "Number literal too large (> 256 bits)");
else if (_literal.kind == LiteralKind::Boolean)
yulAssert(_literal.value == "true"_yulstring || _literal.value == "false"_yulstring, "");
if (!m_dialect.validTypeForLiteral(_literal.kind, _literal.value, _literal.type))
m_errorReporter.typeError(
5170_error,
_literal.location,
_literal.debugData->irLocation,
"Invalid type \"" + _literal.type.str() + "\" for literal \"" + _literal.value.str() + "\"."
);
@ -132,7 +132,7 @@ vector<YulString> AsmAnalyzer::operator()(Identifier const& _identifier)
if (!m_activeVariables.count(&_var))
m_errorReporter.declarationError(
4990_error,
_identifier.location,
_identifier.debugData->irLocation,
"Variable " + _identifier.name.str() + " used before it was declared."
);
type = _var.type;
@ -141,7 +141,7 @@ vector<YulString> AsmAnalyzer::operator()(Identifier const& _identifier)
{
m_errorReporter.typeError(
6041_error,
_identifier.location,
_identifier.debugData->irLocation,
"Function " + _identifier.name.str() + " used without being called."
);
}
@ -159,7 +159,7 @@ vector<YulString> AsmAnalyzer::operator()(Identifier const& _identifier)
// Only add an error message if the callback did not do it.
m_errorReporter.declarationError(
8198_error,
_identifier.location,
_identifier.debugData->irLocation,
"Identifier \"" + _identifier.name.str() + "\" not found."
);
@ -175,7 +175,7 @@ void AsmAnalyzer::operator()(ExpressionStatement const& _statement)
if (watcher.ok() && !types.empty())
m_errorReporter.typeError(
3083_error,
_statement.location,
_statement.debugData->irLocation,
"Top-level expressions are not supposed to return values (this expression returns " +
to_string(types.size()) +
" value" +
@ -195,7 +195,7 @@ void AsmAnalyzer::operator()(Assignment const& _assignment)
if (!variables.insert(_variableName.name).second)
m_errorReporter.declarationError(
9005_error,
_assignment.location,
_assignment.debugData->irLocation,
"Variable " +
_variableName.name.str() +
" occurs multiple times on the left-hand side of the assignment."
@ -206,7 +206,7 @@ void AsmAnalyzer::operator()(Assignment const& _assignment)
if (types.size() != numVariables)
m_errorReporter.declarationError(
8678_error,
_assignment.location,
_assignment.debugData->irLocation,
"Variable count for assignment to \"" +
joinHumanReadable(applyMap(_assignment.variableNames, [](auto const& _identifier){ return _identifier.name.str(); })) +
"\" does not match number of values (" +
@ -228,14 +228,14 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl)
for (auto const& variable: _varDecl.variables)
// Call the resolver for variable declarations to allow it to raise errors on shadowing.
m_resolver(
yul::Identifier{variable.location, variable.name},
yul::Identifier{variable.debugData, variable.name},
yul::IdentifierContext::VariableDeclaration,
m_currentScope->insideFunction()
);
for (auto const& variable: _varDecl.variables)
{
expectValidIdentifier(variable.name, variable.location);
expectValidType(variable.type, variable.location);
expectValidIdentifier(variable.name, variable.debugData->irLocation);
expectValidType(variable.type, variable.debugData->irLocation);
}
if (_varDecl.value)
@ -244,7 +244,7 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl)
if (types.size() != numVariables)
m_errorReporter.declarationError(
3812_error,
_varDecl.location,
_varDecl.debugData->irLocation,
"Variable count mismatch for declaration of \"" +
joinHumanReadable(applyMap(_varDecl.variables, [](auto const& _identifier){ return _identifier.name.str(); })) +
+ "\": " +
@ -263,7 +263,7 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl)
if (variable.type != givenType)
m_errorReporter.typeError(
3947_error,
variable.location,
variable.debugData->irLocation,
"Assigning value of type \"" + givenType.str() + "\" to variable of type \"" + variable.type.str() + "\"."
);
}
@ -278,14 +278,14 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl)
void AsmAnalyzer::operator()(FunctionDefinition const& _funDef)
{
yulAssert(!_funDef.name.empty(), "");
expectValidIdentifier(_funDef.name, _funDef.location);
expectValidIdentifier(_funDef.name, _funDef.debugData->irLocation);
Block const* virtualBlock = m_info.virtualBlocks.at(&_funDef).get();
yulAssert(virtualBlock, "");
Scope& varScope = scope(virtualBlock);
for (auto const& var: _funDef.parameters + _funDef.returnVariables)
{
expectValidIdentifier(var.name, var.location);
expectValidType(var.type, var.location);
expectValidIdentifier(var.name, var.debugData->irLocation);
expectValidType(var.type, var.debugData->irLocation);
m_activeVariables.insert(&std::get<Scope::Variable>(varScope.identifiers.at(var.name)));
}
@ -314,7 +314,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
{
m_errorReporter.typeError(
4202_error,
_funCall.functionName.location,
_funCall.functionName.debugData->irLocation,
"Attempt to call variable instead of function."
);
},
@ -328,7 +328,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
if (!validateInstructions(_funCall))
m_errorReporter.declarationError(
4619_error,
_funCall.functionName.location,
_funCall.functionName.debugData->irLocation,
"Function \"" + _funCall.functionName.name.str() + "\" not found."
);
yulAssert(!watcher.ok(), "Expected a reported error.");
@ -337,7 +337,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
if (parameterTypes && _funCall.arguments.size() != parameterTypes->size())
m_errorReporter.typeError(
7000_error,
_funCall.functionName.location,
_funCall.functionName.debugData->irLocation,
"Function \"" + _funCall.functionName.name.str() + "\" expects " +
to_string(parameterTypes->size()) +
" arguments but got " +
@ -357,13 +357,13 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
if (!holds_alternative<Literal>(arg))
m_errorReporter.typeError(
9114_error,
_funCall.functionName.location,
_funCall.functionName.debugData->irLocation,
"Function expects direct literals as arguments."
);
else if (*literalArgumentKind != get<Literal>(arg).kind)
m_errorReporter.typeError(
5859_error,
get<Literal>(arg).location,
get<Literal>(arg).debugData->irLocation,
"Function expects " + to_string(*literalArgumentKind) + " literal."
);
else if (*literalArgumentKind == LiteralKind::String)
@ -375,7 +375,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
if (!m_dataNames.count(get<Literal>(arg).value))
m_errorReporter.typeError(
3517_error,
get<Literal>(arg).location,
get<Literal>(arg).debugData->irLocation,
"Unknown data object \"" + std::get<Literal>(arg).value.str() + "\"."
);
argTypes.emplace_back(expectUnlimitedStringLiteral(get<Literal>(arg)));
@ -388,7 +388,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
if (parameterTypes && parameterTypes->size() == argTypes.size())
for (size_t i = 0; i < parameterTypes->size(); ++i)
expectType((*parameterTypes)[i], argTypes[i], locationOf(_funCall.arguments[i]));
expectType((*parameterTypes)[i], argTypes[i], locationOf(_funCall.arguments[i])->irLocation);
if (watcher.ok())
{
@ -416,7 +416,7 @@ void AsmAnalyzer::operator()(Switch const& _switch)
if (_switch.cases.size() == 1 && !_switch.cases[0].value)
m_errorReporter.warning(
9592_error,
_switch.location,
_switch.debugData->irLocation,
"\"switch\" statement with only a default case."
);
@ -429,7 +429,7 @@ void AsmAnalyzer::operator()(Switch const& _switch)
{
auto watcher = m_errorReporter.errorWatcher();
expectType(valueType, _case.value->type, _case.value->location);
expectType(valueType, _case.value->type, _case.value->debugData->irLocation);
// We cannot use "expectExpression" here because *_case.value is not an
// Expression and would be converted to an Expression otherwise.
@ -439,7 +439,7 @@ void AsmAnalyzer::operator()(Switch const& _switch)
if (watcher.ok() && !cases.insert(valueOfLiteral(*_case.value)).second)
m_errorReporter.declarationError(
6792_error,
_case.location,
_case.debugData->irLocation,
"Duplicate case \"" +
valueOfLiteral(*_case.value).str() +
"\" defined."
@ -491,7 +491,7 @@ YulString AsmAnalyzer::expectExpression(Expression const& _expr)
if (types.size() != 1)
m_errorReporter.typeError(
3950_error,
locationOf(_expr),
locationOf(_expr)->irLocation,
"Expected expression to evaluate to one value, but got " +
to_string(types.size()) +
" values instead."
@ -513,7 +513,7 @@ void AsmAnalyzer::expectBoolExpression(Expression const& _expr)
if (type != m_dialect.boolType)
m_errorReporter.typeError(
1733_error,
locationOf(_expr),
locationOf(_expr)->irLocation,
"Expected a value of boolean type \"" +
m_dialect.boolType.str() +
"\" but got \"" +
@ -531,11 +531,11 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulString _valueT
if (Scope::Identifier const* var = m_currentScope->lookup(_variable.name))
{
if (!holds_alternative<Scope::Variable>(*var))
m_errorReporter.typeError(2657_error, _variable.location, "Assignment requires variable.");
m_errorReporter.typeError(2657_error, _variable.debugData->irLocation, "Assignment requires variable.");
else if (!m_activeVariables.count(&std::get<Scope::Variable>(*var)))
m_errorReporter.declarationError(
1133_error,
_variable.location,
_variable.debugData->irLocation,
"Variable " + _variable.name.str() + " used before it was declared."
);
else
@ -554,11 +554,11 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulString _valueT
if (!found && watcher.ok())
// Only add message if the callback did not.
m_errorReporter.declarationError(4634_error, _variable.location, "Variable not found or variable not lvalue.");
m_errorReporter.declarationError(4634_error, _variable.debugData->irLocation, "Variable not found or variable not lvalue.");
if (variableType && *variableType != _valueType)
m_errorReporter.typeError(
9547_error,
_variable.location,
_variable.debugData->irLocation,
"Assigning a value of type \"" +
_valueType.str() +
"\" to a variable of type \"" +
@ -702,5 +702,5 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio
bool AsmAnalyzer::validateInstructions(FunctionCall const& _functionCall)
{
return validateInstructions(_functionCall.functionName.name.str(), _functionCall.functionName.location);
return validateInstructions(_functionCall.functionName.name.str(), _functionCall.functionName.debugData->irLocation);
}

View File

@ -32,7 +32,7 @@ namespace solidity::yul
Json::Value AsmJsonConverter::operator()(Block const& _node) const
{
Json::Value ret = createAstNode(_node.location, "YulBlock");
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulBlock");
ret["statements"] = vectorOfVariantsToJson(_node.statements);
return ret;
}
@ -40,7 +40,7 @@ Json::Value AsmJsonConverter::operator()(Block const& _node) const
Json::Value AsmJsonConverter::operator()(TypedName const& _node) const
{
yulAssert(!_node.name.empty(), "Invalid variable name.");
Json::Value ret = createAstNode(_node.location, "YulTypedName");
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulTypedName");
ret["name"] = _node.name.str();
ret["type"] = _node.type.str();
return ret;
@ -48,7 +48,7 @@ Json::Value AsmJsonConverter::operator()(TypedName const& _node) const
Json::Value AsmJsonConverter::operator()(Literal const& _node) const
{
Json::Value ret = createAstNode(_node.location, "YulLiteral");
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulLiteral");
switch (_node.kind)
{
case LiteralKind::Number:
@ -73,7 +73,7 @@ Json::Value AsmJsonConverter::operator()(Literal const& _node) const
Json::Value AsmJsonConverter::operator()(Identifier const& _node) const
{
yulAssert(!_node.name.empty(), "Invalid identifier");
Json::Value ret = createAstNode(_node.location, "YulIdentifier");
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulIdentifier");
ret["name"] = _node.name.str();
return ret;
}
@ -81,7 +81,7 @@ Json::Value AsmJsonConverter::operator()(Identifier const& _node) const
Json::Value AsmJsonConverter::operator()(Assignment const& _node) const
{
yulAssert(_node.variableNames.size() >= 1, "Invalid assignment syntax");
Json::Value ret = createAstNode(_node.location, "YulAssignment");
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulAssignment");
for (auto const& var: _node.variableNames)
ret["variableNames"].append((*this)(var));
ret["value"] = _node.value ? std::visit(*this, *_node.value) : Json::nullValue;
@ -90,7 +90,7 @@ Json::Value AsmJsonConverter::operator()(Assignment const& _node) const
Json::Value AsmJsonConverter::operator()(FunctionCall const& _node) const
{
Json::Value ret = createAstNode(_node.location, "YulFunctionCall");
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulFunctionCall");
ret["functionName"] = (*this)(_node.functionName);
ret["arguments"] = vectorOfVariantsToJson(_node.arguments);
return ret;
@ -98,14 +98,14 @@ Json::Value AsmJsonConverter::operator()(FunctionCall const& _node) const
Json::Value AsmJsonConverter::operator()(ExpressionStatement const& _node) const
{
Json::Value ret = createAstNode(_node.location, "YulExpressionStatement");
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulExpressionStatement");
ret["expression"] = std::visit(*this, _node.expression);
return ret;
}
Json::Value AsmJsonConverter::operator()(VariableDeclaration const& _node) const
{
Json::Value ret = createAstNode(_node.location, "YulVariableDeclaration");
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulVariableDeclaration");
for (auto const& var: _node.variables)
ret["variables"].append((*this)(var));
@ -117,7 +117,7 @@ Json::Value AsmJsonConverter::operator()(VariableDeclaration const& _node) const
Json::Value AsmJsonConverter::operator()(FunctionDefinition const& _node) const
{
yulAssert(!_node.name.empty(), "Invalid function name.");
Json::Value ret = createAstNode(_node.location, "YulFunctionDefinition");
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulFunctionDefinition");
ret["name"] = _node.name.str();
for (auto const& var: _node.parameters)
ret["parameters"].append((*this)(var));
@ -130,7 +130,7 @@ Json::Value AsmJsonConverter::operator()(FunctionDefinition const& _node) const
Json::Value AsmJsonConverter::operator()(If const& _node) const
{
yulAssert(_node.condition, "Invalid if condition.");
Json::Value ret = createAstNode(_node.location, "YulIf");
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulIf");
ret["condition"] = std::visit(*this, *_node.condition);
ret["body"] = (*this)(_node.body);
return ret;
@ -139,7 +139,7 @@ Json::Value AsmJsonConverter::operator()(If const& _node) const
Json::Value AsmJsonConverter::operator()(Switch const& _node) const
{
yulAssert(_node.expression, "Invalid expression pointer.");
Json::Value ret = createAstNode(_node.location, "YulSwitch");
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulSwitch");
ret["expression"] = std::visit(*this, *_node.expression);
for (auto const& var: _node.cases)
ret["cases"].append((*this)(var));
@ -148,7 +148,7 @@ Json::Value AsmJsonConverter::operator()(Switch const& _node) const
Json::Value AsmJsonConverter::operator()(Case const& _node) const
{
Json::Value ret = createAstNode(_node.location, "YulCase");
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulCase");
ret["value"] = _node.value ? (*this)(*_node.value) : "default";
ret["body"] = (*this)(_node.body);
return ret;
@ -157,7 +157,7 @@ Json::Value AsmJsonConverter::operator()(Case const& _node) const
Json::Value AsmJsonConverter::operator()(ForLoop const& _node) const
{
yulAssert(_node.condition, "Invalid for loop condition.");
Json::Value ret = createAstNode(_node.location, "YulForLoop");
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulForLoop");
ret["pre"] = (*this)(_node.pre);
ret["condition"] = std::visit(*this, *_node.condition);
ret["post"] = (*this)(_node.post);
@ -167,17 +167,17 @@ Json::Value AsmJsonConverter::operator()(ForLoop const& _node) const
Json::Value AsmJsonConverter::operator()(Break const& _node) const
{
return createAstNode(_node.location, "YulBreak");
return createAstNode(_node.debugData->irLocation, "YulBreak");
}
Json::Value AsmJsonConverter::operator()(Continue const& _node) const
{
return createAstNode(_node.location, "YulContinue");
return createAstNode(_node.debugData->irLocation, "YulContinue");
}
Json::Value AsmJsonConverter::operator()(Leave const& _node) const
{
return createAstNode(_node.location, "YulLeave");
return createAstNode(_node.debugData->irLocation, "YulLeave");
}
Json::Value AsmJsonConverter::createAstNode(langutil::SourceLocation const& _location, string _nodeType) const

View File

@ -52,9 +52,11 @@ template <class T>
T AsmJsonImporter::createAsmNode(Json::Value const& _node)
{
T r;
r.location = createSourceLocation(_node);
r.debugData = make_shared<DebugData>(createSourceLocation(_node));
yulAssert(
r.location.source && 0 <= r.location.start && r.location.start <= r.location.end,
r.debugData->irLocation.source &&
0 <= r.debugData->irLocation.start &&
r.debugData->irLocation.start <= r.debugData->irLocation.end,
"Invalid source location in Asm AST"
);
return r;

View File

@ -70,7 +70,7 @@ Block Parser::parseBlock()
expectToken(Token::LBrace);
while (currentToken() != Token::RBrace)
block.statements.emplace_back(parseStatement());
block.location.end = currentLocation().end;
block.debugData->irLocation.end = currentLocation().end;
advance();
return block;
}
@ -109,7 +109,7 @@ Statement Parser::parseStatement()
fatalParserError(4904_error, "Case not allowed after default case.");
if (_switch.cases.empty())
fatalParserError(2418_error, "Switch statement without any cases.");
_switch.location.end = _switch.cases.back().body.location.end;
_switch.debugData->irLocation.end = _switch.cases.back().body.debugData->irLocation.end;
return Statement{move(_switch)};
}
case Token::For:
@ -156,7 +156,7 @@ Statement Parser::parseStatement()
case Token::AssemblyAssign:
{
Assignment assignment;
assignment.location = locationOf(elementary);
assignment.debugData = locationOf(elementary);
while (true)
{
@ -191,7 +191,7 @@ Statement Parser::parseStatement()
expectToken(Token::AssemblyAssign);
assignment.value = make_unique<Expression>(parseExpression());
assignment.location.end = locationOf(*assignment.value).end;
assignment.debugData->irLocation.end = locationOf(*assignment.value)->irLocation.end;
return Statement{move(assignment)};
}
@ -221,7 +221,7 @@ Case Parser::parseCase()
else
yulAssert(false, "Case or default case expected.");
_case.body = parseBlock();
_case.location.end = _case.body.location.end;
_case.debugData->irLocation.end = _case.body.debugData->irLocation.end;
return _case;
}
@ -241,7 +241,7 @@ ForLoop Parser::parseForLoop()
forLoop.post = parseBlock();
m_currentForLoopComponent = ForLoopComponent::ForLoopBody;
forLoop.body = parseBlock();
forLoop.location.end = forLoop.body.location.end;
forLoop.debugData->irLocation.end = forLoop.body.debugData->irLocation.end;
m_currentForLoopComponent = outerForLoopComponent;
@ -261,7 +261,7 @@ Expression Parser::parseExpression()
if (m_dialect.builtin(_identifier.name))
fatalParserError(
7104_error,
_identifier.location,
_identifier.debugData->irLocation,
"Builtin function \"" + _identifier.name.str() + "\" must be called."
);
return move(_identifier);
@ -280,7 +280,7 @@ variant<Literal, Identifier> Parser::parseLiteralOrIdentifier()
{
case Token::Identifier:
{
Identifier identifier{currentLocation(), YulString{currentLiteral()}};
Identifier identifier{make_shared<DebugData>(currentLocation()), YulString{currentLiteral()}};
advance();
return identifier;
}
@ -311,7 +311,7 @@ variant<Literal, Identifier> Parser::parseLiteralOrIdentifier()
}
Literal literal{
currentLocation(),
make_shared<DebugData>(currentLocation()),
kind,
YulString{currentLiteral()},
kind == LiteralKind::Boolean ? m_dialect.boolType : m_dialect.defaultType
@ -320,7 +320,7 @@ variant<Literal, Identifier> Parser::parseLiteralOrIdentifier()
if (currentToken() == Token::Colon)
{
expectToken(Token::Colon);
literal.location.end = currentLocation().end;
literal.debugData->irLocation.end = currentLocation().end;
literal.type = expectAsmIdentifier();
}
@ -332,7 +332,7 @@ variant<Literal, Identifier> Parser::parseLiteralOrIdentifier()
default:
fatalParserError(1856_error, "Literal or identifier expected.");
}
return {};
return Literal{make_shared<DebugData>(), {}, {}, {}};
}
VariableDeclaration Parser::parseVariableDeclaration()
@ -352,10 +352,10 @@ VariableDeclaration Parser::parseVariableDeclaration()
{
expectToken(Token::AssemblyAssign);
varDecl.value = make_unique<Expression>(parseExpression());
varDecl.location.end = locationOf(*varDecl.value).end;
varDecl.debugData->irLocation.end = locationOf(*varDecl.value)->irLocation.end;
}
else
varDecl.location.end = varDecl.variables.back().location.end;
varDecl.debugData->irLocation.end = varDecl.variables.back().debugData->irLocation.end;
return varDecl;
}
@ -400,7 +400,7 @@ FunctionDefinition Parser::parseFunctionDefinition()
m_insideFunction = true;
funDef.body = parseBlock();
m_insideFunction = preInsideFunction;
funDef.location.end = funDef.body.location.end;
funDef.debugData->irLocation.end = funDef.body.debugData->irLocation.end;
m_currentForLoopComponent = outerForLoopComponent;
return funDef;
@ -415,7 +415,7 @@ FunctionCall Parser::parseCall(variant<Literal, Identifier>&& _initialOp)
FunctionCall ret;
ret.functionName = std::move(std::get<Identifier>(_initialOp));
ret.location = ret.functionName.location;
ret.debugData = ret.functionName.debugData;
expectToken(Token::LParen);
if (currentToken() != Token::RParen)
@ -427,7 +427,7 @@ FunctionCall Parser::parseCall(variant<Literal, Identifier>&& _initialOp)
ret.arguments.emplace_back(parseExpression());
}
}
ret.location.end = currentLocation().end;
ret.debugData->irLocation.end = currentLocation().end;
expectToken(Token::RParen);
return ret;
}
@ -440,7 +440,7 @@ TypedName Parser::parseTypedName()
if (currentToken() == Token::Colon)
{
expectToken(Token::Colon);
typedName.location.end = currentLocation().end;
typedName.debugData->irLocation.end = currentLocation().end;
typedName.type = expectAsmIdentifier();
}
else

View File

@ -70,7 +70,7 @@ protected:
template <class T> T createWithLocation() const
{
T r;
r.location = currentLocation();
r.debugData = std::make_shared<DebugData>(currentLocation());
return r;
}

View File

@ -29,17 +29,17 @@ using namespace solidity::langutil;
Literal Dialect::zeroLiteralForType(solidity::yul::YulString _type) const
{
if (_type == boolType && _type != defaultType)
return {SourceLocation{}, LiteralKind::Boolean, "false"_yulstring, _type};
return {SourceLocation{}, LiteralKind::Number, "0"_yulstring, _type};
return {make_shared<DebugData>(), LiteralKind::Boolean, "false"_yulstring, _type};
return {make_shared<DebugData>(), LiteralKind::Number, "0"_yulstring, _type};
}
Literal Dialect::trueLiteral() const
{
if (boolType != defaultType)
return {SourceLocation{}, LiteralKind::Boolean, "true"_yulstring, boolType};
return {make_shared<DebugData>(), LiteralKind::Boolean, "true"_yulstring, boolType};
else
return {SourceLocation{}, LiteralKind::Number, "1"_yulstring, defaultType};
return {make_shared<DebugData>(), LiteralKind::Number, "1"_yulstring, defaultType};
}
bool Dialect::validTypeForLiteral(LiteralKind _kind, YulString, YulString _type) const

View File

@ -53,7 +53,7 @@ bool ScopeFiller::operator()(ExpressionStatement const& _expr)
bool ScopeFiller::operator()(VariableDeclaration const& _varDecl)
{
for (auto const& variable: _varDecl.variables)
if (!registerVariable(variable, _varDecl.location, *m_currentScope))
if (!registerVariable(variable, _varDecl.debugData->irLocation, *m_currentScope))
return false;
return true;
}
@ -68,7 +68,7 @@ bool ScopeFiller::operator()(FunctionDefinition const& _funDef)
bool success = true;
for (auto const& var: _funDef.parameters + _funDef.returnVariables)
if (!registerVariable(var, _funDef.location, varScope))
if (!registerVariable(var, _funDef.debugData->irLocation, varScope))
success = false;
if (!(*this)(_funDef.body))
@ -162,7 +162,7 @@ bool ScopeFiller::registerFunction(FunctionDefinition const& _funDef)
//@TODO secondary location
m_errorReporter.declarationError(
6052_error,
_funDef.location,
_funDef.debugData->irLocation,
"Function name " + _funDef.name.str() + " already taken in this scope."
);
return false;

View File

@ -42,6 +42,7 @@ enum class Instruction: uint8_t;
namespace solidity::yul
{
struct Identifier;
struct DebugData;
///
/// Assembly class that abstracts both the libevmasm assembly and the new Yul assembly.
@ -56,7 +57,7 @@ public:
virtual ~AbstractAssembly() = default;
/// Set a new source location valid starting from the next instruction.
virtual void setSourceLocation(langutil::SourceLocation const& _location) = 0;
virtual void setSourceLocation(std::shared_ptr<DebugData const> const& _debugData) = 0;
/// Retrieve the current height of the stack. This does not have to be zero
/// at the beginning.
virtual int stackHeight() const = 0;

View File

@ -49,9 +49,9 @@ EthAssemblyAdapter::EthAssemblyAdapter(evmasm::Assembly& _assembly):
{
}
void EthAssemblyAdapter::setSourceLocation(SourceLocation const& _location)
void EthAssemblyAdapter::setSourceLocation(shared_ptr<DebugData const> const& _debugData)
{
m_assembly.setSourceLocation(_location);
m_assembly.setSourceLocation(_debugData ? _debugData->irLocation : langutil::SourceLocation{});
}
int EthAssemblyAdapter::stackHeight() const

View File

@ -40,7 +40,7 @@ class EthAssemblyAdapter: public AbstractAssembly
{
public:
explicit EthAssemblyAdapter(evmasm::Assembly& _assembly);
void setSourceLocation(langutil::SourceLocation const& _location) override;
void setSourceLocation(std::shared_ptr<DebugData const> const& _debugData) override;
int stackHeight() const override;
void setStackHeight(int height) override;
void appendInstruction(evmasm::Instruction _instruction) override;

View File

@ -180,7 +180,7 @@ Representation const& RepresentationFinder::findRepresentation(u256 const& _valu
Representation RepresentationFinder::represent(u256 const& _value) const
{
Representation repr;
repr.expression = make_unique<Expression>(Literal{m_location, LiteralKind::Number, YulString{formatNumber(_value)}, {}});
repr.expression = make_unique<Expression>(Literal{m_debugData, LiteralKind::Number, YulString{formatNumber(_value)}, {}});
repr.cost = m_meter.costs(*repr.expression);
return repr;
}
@ -192,8 +192,8 @@ Representation RepresentationFinder::represent(
{
Representation repr;
repr.expression = make_unique<Expression>(FunctionCall{
m_location,
Identifier{m_location, _instruction},
m_debugData,
Identifier{m_debugData, _instruction},
{ASTCopier{}.translate(*_argument.expression)}
});
repr.cost = _argument.cost + m_meter.instructionCosts(*m_dialect.builtin(_instruction)->instruction);
@ -208,8 +208,8 @@ Representation RepresentationFinder::represent(
{
Representation repr;
repr.expression = make_unique<Expression>(FunctionCall{
m_location,
Identifier{m_location, _instruction},
m_debugData,
Identifier{m_debugData, _instruction},
{ASTCopier{}.translate(*_arg1.expression), ASTCopier{}.translate(*_arg2.expression)}
});
repr.cost = m_meter.instructionCosts(*m_dialect.builtin(_instruction)->instruction) + _arg1.cost + _arg2.cost;

View File

@ -74,12 +74,12 @@ public:
RepresentationFinder(
EVMDialect const& _dialect,
GasMeter const& _meter,
langutil::SourceLocation _location,
std::shared_ptr<DebugData> _debugData,
std::map<u256, Representation>& _cache
):
m_dialect(_dialect),
m_meter(_meter),
m_location(std::move(_location)),
m_debugData(std::move(_debugData)),
m_cache(_cache)
{}
@ -100,7 +100,7 @@ private:
EVMDialect const& m_dialect;
GasMeter const& m_meter;
langutil::SourceLocation m_location;
std::shared_ptr<DebugData> m_debugData;
/// Counter for the complexity of optimization, will stop when it reaches zero.
size_t m_maxSteps = 10000;
std::map<u256, Representation>& m_cache;

View File

@ -39,7 +39,7 @@ size_t constexpr assemblySizeReferenceSize = 4;
}
void EVMAssembly::setSourceLocation(SourceLocation const&)
void EVMAssembly::setSourceLocation(shared_ptr<DebugData const> const&)
{
// Ignored for now;
}

View File

@ -42,7 +42,7 @@ public:
~EVMAssembly() override = default;
/// Set a new source location valid starting from the next instruction.
void setSourceLocation(langutil::SourceLocation const& _location) override;
void setSourceLocation(std::shared_ptr<DebugData const> const& _debugData) override;
/// Retrieve the current height of the stack. This does not have to be zero
/// at the beginning.
int stackHeight() const override { return m_stackHeight; }

View File

@ -199,13 +199,13 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl)
}
else
{
m_assembly.setSourceLocation(_varDecl.location);
m_assembly.setSourceLocation(_varDecl.debugData);
size_t variablesLeft = numVariables;
while (variablesLeft--)
m_assembly.appendConstant(u256(0));
}
m_assembly.setSourceLocation(_varDecl.location);
m_assembly.setSourceLocation(_varDecl.debugData);
bool atTopOfStack = true;
for (size_t varIndex = 0; varIndex < numVariables; ++varIndex)
{
@ -259,13 +259,13 @@ void CodeTransform::operator()(Assignment const& _assignment)
std::visit(*this, *_assignment.value);
expectDeposit(static_cast<int>(_assignment.variableNames.size()), height);
m_assembly.setSourceLocation(_assignment.location);
m_assembly.setSourceLocation(_assignment.debugData);
generateMultiAssignment(_assignment.variableNames);
}
void CodeTransform::operator()(ExpressionStatement const& _statement)
{
m_assembly.setSourceLocation(_statement.location);
m_assembly.setSourceLocation(_statement.debugData);
std::visit(*this, _statement.expression);
}
@ -279,7 +279,7 @@ void CodeTransform::operator()(FunctionCall const& _call)
});
else
{
m_assembly.setSourceLocation(_call.location);
m_assembly.setSourceLocation(_call.debugData);
EVMAssembly::LabelID returnLabel(numeric_limits<EVMAssembly::LabelID>::max()); // only used for evm 1.0
returnLabel = m_assembly.newLabelId();
@ -294,7 +294,7 @@ void CodeTransform::operator()(FunctionCall const& _call)
yulAssert(function->arguments.size() == _call.arguments.size(), "");
for (auto const& arg: _call.arguments | ranges::views::reverse)
visitExpression(arg);
m_assembly.setSourceLocation(_call.location);
m_assembly.setSourceLocation(_call.debugData);
m_assembly.appendJumpTo(
functionEntryID(_call.functionName.name, *function),
static_cast<int>(function->returns.size() - function->arguments.size()) - 1,
@ -306,7 +306,7 @@ void CodeTransform::operator()(FunctionCall const& _call)
void CodeTransform::operator()(Identifier const& _identifier)
{
m_assembly.setSourceLocation(_identifier.location);
m_assembly.setSourceLocation(_identifier.debugData);
// First search internals, then externals.
yulAssert(m_scope, "");
if (m_scope->lookup(_identifier.name, GenericVisitor{
@ -338,19 +338,19 @@ void CodeTransform::operator()(Identifier const& _identifier)
void CodeTransform::operator()(Literal const& _literal)
{
m_assembly.setSourceLocation(_literal.location);
m_assembly.setSourceLocation(_literal.debugData);
m_assembly.appendConstant(valueOfLiteral(_literal));
}
void CodeTransform::operator()(If const& _if)
{
visitExpression(*_if.condition);
m_assembly.setSourceLocation(_if.location);
m_assembly.setSourceLocation(_if.debugData);
m_assembly.appendInstruction(evmasm::Instruction::ISZERO);
AbstractAssembly::LabelID end = m_assembly.newLabelId();
m_assembly.appendJumpToIf(end);
(*this)(_if.body);
m_assembly.setSourceLocation(_if.location);
m_assembly.setSourceLocation(_if.debugData);
m_assembly.appendLabel(end);
}
@ -367,7 +367,7 @@ void CodeTransform::operator()(Switch const& _switch)
if (c.value)
{
(*this)(*c.value);
m_assembly.setSourceLocation(c.location);
m_assembly.setSourceLocation(c.debugData);
AbstractAssembly::LabelID bodyLabel = m_assembly.newLabelId();
caseBodies[&c] = bodyLabel;
yulAssert(m_assembly.stackHeight() == expressionHeight + 1, "");
@ -379,24 +379,24 @@ void CodeTransform::operator()(Switch const& _switch)
// default case
(*this)(c.body);
}
m_assembly.setSourceLocation(_switch.location);
m_assembly.setSourceLocation(_switch.debugData);
m_assembly.appendJumpTo(end);
size_t numCases = caseBodies.size();
for (auto const& c: caseBodies)
{
m_assembly.setSourceLocation(c.first->location);
m_assembly.setSourceLocation(c.first->debugData);
m_assembly.appendLabel(c.second);
(*this)(c.first->body);
// Avoid useless "jump to next" for the last case.
if (--numCases > 0)
{
m_assembly.setSourceLocation(c.first->location);
m_assembly.setSourceLocation(c.first->debugData);
m_assembly.appendJumpTo(end);
}
}
m_assembly.setSourceLocation(_switch.location);
m_assembly.setSourceLocation(_switch.debugData);
m_assembly.appendLabel(end);
m_assembly.appendInstruction(evmasm::Instruction::POP);
}
@ -417,7 +417,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
m_context->variableStackHeights[&var] = height++;
}
m_assembly.setSourceLocation(_function.location);
m_assembly.setSourceLocation(_function.debugData);
int const stackHeightBefore = m_assembly.stackHeight();
m_assembly.appendLabel(functionEntryID(_function.name, function));
@ -542,11 +542,11 @@ void CodeTransform::operator()(ForLoop const& _forLoop)
AbstractAssembly::LabelID postPart = m_assembly.newLabelId();
AbstractAssembly::LabelID loopEnd = m_assembly.newLabelId();
m_assembly.setSourceLocation(_forLoop.location);
m_assembly.setSourceLocation(_forLoop.debugData);
m_assembly.appendLabel(loopStart);
visitExpression(*_forLoop.condition);
m_assembly.setSourceLocation(_forLoop.location);
m_assembly.setSourceLocation(_forLoop.debugData);
m_assembly.appendInstruction(evmasm::Instruction::ISZERO);
m_assembly.appendJumpToIf(loopEnd);
@ -554,12 +554,12 @@ void CodeTransform::operator()(ForLoop const& _forLoop)
m_context->forLoopStack.emplace(Context::ForLoopLabels{ {postPart, stackHeightBody}, {loopEnd, stackHeightBody} });
(*this)(_forLoop.body);
m_assembly.setSourceLocation(_forLoop.location);
m_assembly.setSourceLocation(_forLoop.debugData);
m_assembly.appendLabel(postPart);
(*this)(_forLoop.post);
m_assembly.setSourceLocation(_forLoop.location);
m_assembly.setSourceLocation(_forLoop.debugData);
m_assembly.appendJumpTo(loopStart);
m_assembly.appendLabel(loopEnd);
@ -579,7 +579,7 @@ int CodeTransform::appendPopUntil(int _targetDepth)
void CodeTransform::operator()(Break const& _break)
{
yulAssert(!m_context->forLoopStack.empty(), "Invalid break-statement. Requires surrounding for-loop in code generation.");
m_assembly.setSourceLocation(_break.location);
m_assembly.setSourceLocation(_break.debugData);
Context::JumpInfo const& jump = m_context->forLoopStack.top().done;
m_assembly.appendJumpTo(jump.label, appendPopUntil(jump.targetStackHeight));
@ -588,7 +588,7 @@ void CodeTransform::operator()(Break const& _break)
void CodeTransform::operator()(Continue const& _continue)
{
yulAssert(!m_context->forLoopStack.empty(), "Invalid continue-statement. Requires surrounding for-loop in code generation.");
m_assembly.setSourceLocation(_continue.location);
m_assembly.setSourceLocation(_continue.debugData);
Context::JumpInfo const& jump = m_context->forLoopStack.top().post;
m_assembly.appendJumpTo(jump.label, appendPopUntil(jump.targetStackHeight));
@ -598,7 +598,7 @@ void CodeTransform::operator()(Leave const& _leaveStatement)
{
yulAssert(m_functionExitLabel, "Invalid leave-statement. Requires surrounding function in code generation.");
yulAssert(m_functionExitStackHeight, "");
m_assembly.setSourceLocation(_leaveStatement.location);
m_assembly.setSourceLocation(_leaveStatement.debugData);
m_assembly.appendJumpTo(*m_functionExitLabel, appendPopUntil(*m_functionExitStackHeight));
}
@ -659,7 +659,7 @@ void CodeTransform::setupReturnVariablesAndFunctionExit()
// Allocate slots for return variables as if they were declared as variables in the virtual function scope.
for (TypedName const& var: m_delayedReturnVariables)
(*this)(VariableDeclaration{var.location, {var}, {}});
(*this)(VariableDeclaration{var.debugData, {var}, {}});
m_functionExitStackHeight = ranges::max(m_delayedReturnVariables | ranges::views::transform([&](TypedName const& _name) {
return variableStackHeight(_name.name);
@ -729,7 +729,7 @@ void CodeTransform::visitStatements(vector<Statement> const& _statements)
void CodeTransform::finalizeBlock(Block const& _block, optional<int> blockStartStackHeight)
{
m_assembly.setSourceLocation(_block.location);
m_assembly.setSourceLocation(_block.debugData);
freeUnusedVariables();

View File

@ -52,7 +52,7 @@ void visitArguments(
for (auto const& arg: _call.arguments | ranges::views::reverse)
_visitExpression(arg);
_assembly.setSourceLocation(_call.location);
_assembly.setSourceLocation(_call.debugData);
}
@ -256,7 +256,7 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
_visitExpression(_call.arguments[2]);
YulString identifier = std::get<Literal>(_call.arguments[1]).value;
_visitExpression(_call.arguments[0]);
_assembly.setSourceLocation(_call.location);
_assembly.setSourceLocation(_call.debugData);
_assembly.appendImmutableAssignment(identifier.str());
}
));

View File

@ -48,7 +48,7 @@ public:
explicit NoOutputAssembly() { }
~NoOutputAssembly() override = default;
void setSourceLocation(langutil::SourceLocation const&) override {}
void setSourceLocation(std::shared_ptr<DebugData const> const&) override {}
int stackHeight() const override { return m_stackHeight; }
void setStackHeight(int height) override { m_stackHeight = height; }
void appendInstruction(evmasm::Instruction _instruction) override;

View File

@ -116,8 +116,8 @@ void WordSizeTransform::operator()(Block& _block)
vector<Statement> ret;
for (size_t i = 0; i < 3; i++)
ret.emplace_back(VariableDeclaration{
varDecl.location,
{TypedName{varDecl.location, newLhs[i], m_targetDialect.defaultType}},
varDecl.debugData,
{TypedName{varDecl.debugData, newLhs[i], m_targetDialect.defaultType}},
make_unique<Expression>(Literal{
locationOf(*varDecl.value),
LiteralKind::Number,
@ -126,8 +126,8 @@ void WordSizeTransform::operator()(Block& _block)
})
});
ret.emplace_back(VariableDeclaration{
varDecl.location,
{TypedName{varDecl.location, newLhs[3], m_targetDialect.defaultType}},
varDecl.debugData,
{TypedName{varDecl.debugData, newLhs[3], m_targetDialect.defaultType}},
std::move(varDecl.value)
});
return {std::move(ret)};
@ -147,8 +147,8 @@ void WordSizeTransform::operator()(Block& _block)
vector<Statement> ret;
for (size_t i = 0; i < 4; i++)
ret.emplace_back(VariableDeclaration{
varDecl.location,
{TypedName{varDecl.location, newLhs[i], m_targetDialect.defaultType}},
varDecl.debugData,
{TypedName{varDecl.debugData, newLhs[i], m_targetDialect.defaultType}},
std::move(newRhs[i])
}
);
@ -177,8 +177,8 @@ void WordSizeTransform::operator()(Block& _block)
vector<Statement> ret;
for (size_t i = 0; i < 3; i++)
ret.emplace_back(Assignment{
assignment.location,
{Identifier{assignment.location, newLhs[i]}},
assignment.debugData,
{Identifier{assignment.debugData, newLhs[i]}},
make_unique<Expression>(Literal{
locationOf(*assignment.value),
LiteralKind::Number,
@ -187,8 +187,8 @@ void WordSizeTransform::operator()(Block& _block)
})
});
ret.emplace_back(Assignment{
assignment.location,
{Identifier{assignment.location, newLhs[3]}},
assignment.debugData,
{Identifier{assignment.debugData, newLhs[3]}},
std::move(assignment.value)
});
return {std::move(ret)};
@ -208,8 +208,8 @@ void WordSizeTransform::operator()(Block& _block)
vector<Statement> ret;
for (size_t i = 0; i < 4; i++)
ret.emplace_back(Assignment{
assignment.location,
{Identifier{assignment.location, m_variableMapping.at(lhsName)[i]}},
assignment.debugData,
{Identifier{assignment.debugData, m_variableMapping.at(lhsName)[i]}},
std::move(newRhs[i])
}
);
@ -258,7 +258,7 @@ void WordSizeTransform::rewriteVarDeclList(TypedNameList& _nameList)
{
TypedNameList ret;
for (auto newName: generateU64IdentifierNames(_n.name))
ret.emplace_back(TypedName{_n.location, newName, m_targetDialect.defaultType});
ret.emplace_back(TypedName{_n.debugData, newName, m_targetDialect.defaultType});
return ret;
}
);
@ -272,7 +272,7 @@ void WordSizeTransform::rewriteIdentifierList(vector<Identifier>& _ids)
{
vector<Identifier> ret;
for (auto newId: m_variableMapping.at(_id.name))
ret.push_back(Identifier{_id.location, newId});
ret.push_back(Identifier{_id.debugData, newId});
return ret;
}
);
@ -303,19 +303,20 @@ vector<Statement> WordSizeTransform::handleSwitchInternal(
].emplace_back(std::move(c));
}
auto const debugData = make_shared<DebugData>(_location);
Switch ret{
_location,
make_unique<Expression>(Identifier{_location, _splitExpressions.at(_depth)}),
debugData,
make_unique<Expression>(Identifier{debugData, _splitExpressions.at(_depth)}),
{}
};
for (auto& c: cases)
{
Literal label{_location, LiteralKind::Number, YulString(c.first.str()), m_targetDialect.defaultType};
Literal label{debugData, LiteralKind::Number, YulString(c.first.str()), m_targetDialect.defaultType};
ret.cases.emplace_back(Case{
c.second.front().location,
c.second.front().debugData,
make_unique<Literal>(std::move(label)),
Block{_location, handleSwitchInternal(
Block{debugData, handleSwitchInternal(
_location,
_splitExpressions,
std::move(c.second),
@ -326,13 +327,13 @@ vector<Statement> WordSizeTransform::handleSwitchInternal(
}
if (!_runDefaultFlag.empty())
ret.cases.emplace_back(Case{
_location,
debugData,
nullptr,
Block{_location, make_vector<Statement>(
Block{debugData, make_vector<Statement>(
Assignment{
_location,
{{_location, _runDefaultFlag}},
make_unique<Expression>(Literal{_location, LiteralKind::Boolean, "true"_yulstring, m_targetDialect.boolType})
debugData,
{{debugData, _runDefaultFlag}},
make_unique<Expression>(Literal{debugData, LiteralKind::Boolean, "true"_yulstring, m_targetDialect.boolType})
}
)}
});
@ -356,8 +357,8 @@ std::vector<Statement> WordSizeTransform::handleSwitch(Switch& _switch)
defaultCase = std::move(_switch.cases.back());
_switch.cases.pop_back();
ret.emplace_back(VariableDeclaration{
_switch.location,
{TypedName{_switch.location, runDefaultFlag, m_targetDialect.boolType}},
_switch.debugData,
{TypedName{_switch.debugData, runDefaultFlag, m_targetDialect.boolType}},
{}
});
}
@ -366,7 +367,7 @@ std::vector<Statement> WordSizeTransform::handleSwitch(Switch& _switch)
splitExpressions.emplace_back(std::get<Identifier>(*expr).name);
ret += handleSwitchInternal(
_switch.location,
_switch.debugData->irLocation,
splitExpressions,
std::move(_switch.cases),
runDefaultFlag,
@ -374,8 +375,8 @@ std::vector<Statement> WordSizeTransform::handleSwitch(Switch& _switch)
);
if (!runDefaultFlag.empty())
ret.emplace_back(If{
_switch.location,
make_unique<Expression>(Identifier{_switch.location, runDefaultFlag}),
_switch.debugData,
make_unique<Expression>(Identifier{_switch.debugData, runDefaultFlag}),
std::move(defaultCase.body)
});
return ret;
@ -397,7 +398,7 @@ array<unique_ptr<Expression>, 4> WordSizeTransform::expandValue(Expression const
{
auto const& id = std::get<Identifier>(_e);
for (size_t i = 0; i < 4; i++)
ret[i] = make_unique<Expression>(Identifier{id.location, m_variableMapping.at(id.name)[i]});
ret[i] = make_unique<Expression>(Identifier{id.debugData, m_variableMapping.at(id.name)[i]});
}
else if (holds_alternative<Literal>(_e))
{
@ -410,7 +411,7 @@ array<unique_ptr<Expression>, 4> WordSizeTransform::expandValue(Expression const
val >>= 64;
ret[exprIndexReverse] = make_unique<Expression>(
Literal{
lit.location,
lit.debugData,
LiteralKind::Number,
YulString(currentVal.str()),
m_targetDialect.defaultType

View File

@ -34,13 +34,13 @@ using namespace solidity::util;
Statement ASTCopier::operator()(ExpressionStatement const& _statement)
{
return ExpressionStatement{ _statement.location, translate(_statement.expression) };
return ExpressionStatement{ _statement.debugData, translate(_statement.expression) };
}
Statement ASTCopier::operator()(VariableDeclaration const& _varDecl)
{
return VariableDeclaration{
_varDecl.location,
_varDecl.debugData,
translateVector(_varDecl.variables),
translate(_varDecl.value)
};
@ -49,7 +49,7 @@ Statement ASTCopier::operator()(VariableDeclaration const& _varDecl)
Statement ASTCopier::operator()(Assignment const& _assignment)
{
return Assignment{
_assignment.location,
_assignment.debugData,
translateVector(_assignment.variableNames),
translate(_assignment.value)
};
@ -58,7 +58,7 @@ Statement ASTCopier::operator()(Assignment const& _assignment)
Expression ASTCopier::operator()(FunctionCall const& _call)
{
return FunctionCall{
_call.location,
_call.debugData,
translate(_call.functionName),
translateVector(_call.arguments)
};
@ -76,12 +76,12 @@ Expression ASTCopier::operator()(Literal const& _literal)
Statement ASTCopier::operator()(If const& _if)
{
return If{_if.location, translate(_if.condition), translate(_if.body)};
return If{_if.debugData, translate(_if.condition), translate(_if.body)};
}
Statement ASTCopier::operator()(Switch const& _switch)
{
return Switch{_switch.location, translate(_switch.expression), translateVector(_switch.cases)};
return Switch{_switch.debugData, translate(_switch.expression), translateVector(_switch.cases)};
}
Statement ASTCopier::operator()(FunctionDefinition const& _function)
@ -92,7 +92,7 @@ Statement ASTCopier::operator()(FunctionDefinition const& _function)
ScopeGuard g([&]() { this->leaveFunction(_function); });
return FunctionDefinition{
_function.location,
_function.debugData,
translatedName,
translateVector(_function.parameters),
translateVector(_function.returnVariables),
@ -106,7 +106,7 @@ Statement ASTCopier::operator()(ForLoop const& _forLoop)
ScopeGuard g([&]() { this->leaveScope(_forLoop.pre); });
return ForLoop{
_forLoop.location,
_forLoop.debugData,
translate(_forLoop.pre),
translate(_forLoop.condition),
translate(_forLoop.post),
@ -148,17 +148,17 @@ Block ASTCopier::translate(Block const& _block)
enterScope(_block);
ScopeGuard g([&]() { this->leaveScope(_block); });
return Block{_block.location, translateVector(_block.statements)};
return Block{_block.debugData, translateVector(_block.statements)};
}
Case ASTCopier::translate(Case const& _case)
{
return Case{_case.location, translate(_case.value), translate(_case.body)};
return Case{_case.debugData, translate(_case.value), translate(_case.body)};
}
Identifier ASTCopier::translate(Identifier const& _identifier)
{
return Identifier{_identifier.location, translateIdentifier(_identifier.name)};
return Identifier{_identifier.debugData, translateIdentifier(_identifier.name)};
}
Literal ASTCopier::translate(Literal const& _literal)
@ -168,7 +168,7 @@ Literal ASTCopier::translate(Literal const& _literal)
TypedName ASTCopier::translate(TypedName const& _typedName)
{
return TypedName{_typedName.location, translateIdentifier(_typedName.name), _typedName.type};
return TypedName{_typedName.debugData, translateIdentifier(_typedName.name), _typedName.type};
}
YulString FunctionCopier::translateIdentifier(YulString _name)

View File

@ -44,8 +44,8 @@ void ConditionalSimplifier::operator()(Switch& _switch)
(*this)(*_case.value);
_case.body.statements.insert(_case.body.statements.begin(),
Assignment{
_case.body.location,
{Identifier{_case.body.location, expr}},
_case.body.debugData,
{Identifier{_case.body.debugData, expr}},
make_unique<Expression>(*_case.value)
}
);
@ -72,12 +72,11 @@ void ConditionalSimplifier::operator()(Block& _block)
)
{
YulString condition = std::get<Identifier>(*_if.condition).name;
langutil::SourceLocation location = _if.location;
return make_vector<Statement>(
std::move(_s),
Assignment{
location,
{Identifier{location, condition}},
_if.debugData,
{Identifier{_if.debugData, condition}},
make_unique<Expression>(m_dialect.zeroLiteralForType(m_dialect.boolType))
}
);

View File

@ -43,9 +43,9 @@ ExpressionStatement makeDiscardCall(
Expression&& _expression
)
{
return {_location, FunctionCall{
_location,
Identifier{_location, _discardFunction.name},
return {make_shared<DebugData>(_location), FunctionCall{
make_shared<DebugData>(_location),
Identifier{make_shared<DebugData>(_location), _discardFunction.name},
{std::move(_expression)}
}};
}
@ -126,7 +126,7 @@ void ControlFlowSimplifier::visit(Statement& _st)
if (isTerminating && m_numContinueStatements == 0 && m_numBreakStatements == 0)
{
If replacement{forLoop.location, std::move(forLoop.condition), std::move(forLoop.body)};
If replacement{forLoop.debugData, std::move(forLoop.condition), std::move(forLoop.body)};
if (controlFlow == TerminationFinder::ControlFlow::Break)
replacement.body.statements.resize(replacement.body.statements.size() - 1);
_st = std::move(replacement);
@ -149,7 +149,7 @@ void ControlFlowSimplifier::simplify(std::vector<yul::Statement>& _statements)
{
OptionalStatements s = vector<Statement>{};
s->emplace_back(makeDiscardCall(
_ifStmt.location,
_ifStmt.debugData->irLocation,
*m_dialect.discardFunction(m_dialect.boolType),
std::move(*_ifStmt.condition)
));
@ -194,7 +194,7 @@ OptionalStatements ControlFlowSimplifier::reduceNoCaseSwitch(Switch& _switchStmt
auto loc = locationOf(*_switchStmt.expression);
return make_vector<Statement>(makeDiscardCall(
loc,
loc->irLocation,
*discardFunction,
std::move(*_switchStmt.expression)
));
@ -205,17 +205,17 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch
yulAssert(_switchStmt.cases.size() == 1, "Expected only one case!");
auto& switchCase = _switchStmt.cases.front();
auto loc = locationOf(*_switchStmt.expression);
auto debugData = locationOf(*_switchStmt.expression);
YulString type = m_typeInfo.typeOf(*_switchStmt.expression);
if (switchCase.value)
{
if (!m_dialect.equalityFunction(type))
return {};
return make_vector<Statement>(If{
std::move(_switchStmt.location),
std::move(_switchStmt.debugData),
make_unique<Expression>(FunctionCall{
loc,
Identifier{loc, m_dialect.equalityFunction(type)->name},
debugData,
Identifier{debugData, m_dialect.equalityFunction(type)->name},
{std::move(*switchCase.value), std::move(*_switchStmt.expression)}
}),
std::move(switchCase.body)
@ -228,7 +228,7 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch
return make_vector<Statement>(
makeDiscardCall(
loc,
debugData->irLocation,
*m_dialect.discardFunction(type),
std::move(*_switchStmt.expression)
),

View File

@ -39,5 +39,5 @@ void ExpressionSimplifier::visit(Expression& _expression)
ASTModifier::visit(_expression);
while (auto const* match = SimplificationRules::findFirstMatch(_expression, m_dialect, m_value))
_expression = match->action().toExpression(locationOf(_expression));
_expression = match->action().toExpression(locationOf(_expression)->irLocation);
}

View File

@ -101,15 +101,15 @@ void ExpressionSplitter::outlineExpression(Expression& _expr)
visit(_expr);
SourceLocation location = locationOf(_expr);
auto const debugData = locationOf(_expr);
YulString var = m_nameDispenser.newName({});
YulString type = m_typeInfo.typeOf(_expr);
m_statementsToPrefix.emplace_back(VariableDeclaration{
location,
{{TypedName{location, var, type}}},
debugData,
{{TypedName{debugData, var, type}}},
make_unique<Expression>(std::move(_expr))
});
_expr = Identifier{location, var};
_expr = Identifier{debugData, var};
m_typeInfo.setVariableType(var, type);
}

View File

@ -39,25 +39,25 @@ void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop)
!holds_alternative<Identifier>(*_forLoop.condition)
)
{
langutil::SourceLocation const loc = locationOf(*_forLoop.condition);
shared_ptr<DebugData> const debugData = locationOf(*_forLoop.condition);
_forLoop.body.statements.emplace(
begin(_forLoop.body.statements),
If {
loc,
debugData,
make_unique<Expression>(
FunctionCall {
loc,
{loc, m_dialect.booleanNegationFunction()->name},
debugData,
{debugData, m_dialect.booleanNegationFunction()->name},
util::make_vector<Expression>(std::move(*_forLoop.condition))
}
),
Block {loc, util::make_vector<Statement>(Break{{}})}
Block {debugData, util::make_vector<Statement>(Break{{}})}
}
);
_forLoop.condition = make_unique<Expression>(
Literal {
loc,
debugData,
LiteralKind::Boolean,
"true"_yulstring,
m_dialect.boolType

View File

@ -55,7 +55,7 @@ void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop)
return;
YulString iszero = m_dialect.booleanNegationFunction()->name;
langutil::SourceLocation location = locationOf(*firstStatement.condition);
auto const debugData = locationOf(*firstStatement.condition);
if (
holds_alternative<FunctionCall>(*firstStatement.condition) &&
@ -64,8 +64,8 @@ void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop)
_forLoop.condition = make_unique<Expression>(std::move(std::get<FunctionCall>(*firstStatement.condition).arguments.front()));
else
_forLoop.condition = make_unique<Expression>(FunctionCall{
location,
Identifier{location, iszero},
debugData,
Identifier{debugData, iszero},
util::make_vector<Expression>(
std::move(*firstStatement.condition)
)

View File

@ -268,7 +268,7 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
auto newVariable = [&](TypedName const& _existingVariable, Expression* _value) {
YulString newName = m_nameDispenser.newName(_existingVariable.name);
variableReplacements[_existingVariable.name] = newName;
VariableDeclaration varDecl{_funCall.location, {{_funCall.location, newName, _existingVariable.type}}, {}};
VariableDeclaration varDecl{_funCall.debugData, {{_funCall.debugData, newName, _existingVariable.type}}, {}};
if (_value)
varDecl.value = make_unique<Expression>(std::move(*_value));
else
@ -290,10 +290,10 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
{
for (size_t i = 0; i < _assignment.variableNames.size(); ++i)
newStatements.emplace_back(Assignment{
_assignment.location,
_assignment.debugData,
{_assignment.variableNames[i]},
make_unique<Expression>(Identifier{
_assignment.location,
_assignment.debugData,
variableReplacements.at(function->returnVariables[i].name)
})
});
@ -302,10 +302,10 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
{
for (size_t i = 0; i < _varDecl.variables.size(); ++i)
newStatements.emplace_back(VariableDeclaration{
_varDecl.location,
_varDecl.debugData,
{std::move(_varDecl.variables[i])},
make_unique<Expression>(Identifier{
_varDecl.location,
_varDecl.debugData,
variableReplacements.at(function->returnVariables[i].name)
})
});

View File

@ -37,7 +37,7 @@ void FunctionGrouper::operator()(Block& _block)
return;
vector<Statement> reordered;
reordered.emplace_back(Block{_block.location, {}});
reordered.emplace_back(Block{_block.debugData, {}});
for (auto&& statement: _block.statements)
{

View File

@ -41,7 +41,7 @@ void FunctionHoister::operator()(Block& _block)
if (holds_alternative<FunctionDefinition>(statement))
{
m_functions.emplace_back(std::move(statement));
statement = Block{_block.location, {}};
statement = Block{_block.debugData, {}};
}
}
removeEmptyBlocks(_block);

View File

@ -104,7 +104,7 @@ FunctionDefinition FunctionSpecializer::specialize(
if (argument)
missingVariableDeclarations.emplace_back(
VariableDeclaration{
_f.location,
_f.debugData,
vector<TypedName>{newFunction.parameters[index]},
make_unique<Expression>(move(*argument))
}

View File

@ -41,11 +41,19 @@ bool KnowledgeBase::knownToBeDifferent(YulString _a, YulString _b)
// current values to turn `sub(_a, _b)` into a nonzero constant.
// If that fails, try `eq(_a, _b)`.
Expression expr1 = simplify(FunctionCall{{}, {{}, "sub"_yulstring}, util::make_vector<Expression>(Identifier{{}, _a}, Identifier{{}, _b})});
Expression expr1 = simplify(FunctionCall{
make_shared<DebugData>(),
{make_shared<DebugData>(), "sub"_yulstring},
util::make_vector<Expression>(Identifier{make_shared<DebugData>(), _a}, Identifier{make_shared<DebugData>(), _b})
});
if (holds_alternative<Literal>(expr1))
return valueOfLiteral(std::get<Literal>(expr1)) != 0;
Expression expr2 = simplify(FunctionCall{{}, {{}, "eq"_yulstring}, util::make_vector<Expression>(Identifier{{}, _a}, Identifier{{}, _b})});
Expression expr2 = simplify(FunctionCall{
make_shared<DebugData>(),
{make_shared<DebugData>(), "eq"_yulstring},
util::make_vector<Expression>(Identifier{make_shared<DebugData>(), _a}, Identifier{{}, _b})
});
if (holds_alternative<Literal>(expr2))
return valueOfLiteral(std::get<Literal>(expr2)) == 0;
@ -57,7 +65,11 @@ bool KnowledgeBase::knownToBeDifferentByAtLeast32(YulString _a, YulString _b)
// Try to use the simplification rules together with the
// current values to turn `sub(_a, _b)` into a constant whose absolute value is at least 32.
Expression expr1 = simplify(FunctionCall{{}, {{}, "sub"_yulstring}, util::make_vector<Expression>(Identifier{{}, _a}, Identifier{{}, _b})});
Expression expr1 = simplify(FunctionCall{
make_shared<DebugData>(),
{make_shared<DebugData>(), "sub"_yulstring},
util::make_vector<Expression>(Identifier{make_shared<DebugData>(), _a}, Identifier{make_shared<DebugData>(), _b})
});
if (holds_alternative<Literal>(expr1))
{
u256 val = valueOfLiteral(std::get<Literal>(expr1));
@ -84,7 +96,7 @@ Expression KnowledgeBase::simplify(Expression _expression)
arg = simplify(arg);
if (auto match = SimplificationRules::findFirstMatch(_expression, m_dialect, m_variableValues))
return simplify(match->action().toExpression(locationOf(_expression)));
return simplify(match->action().toExpression(locationOf(_expression)->irLocation));
return _expression;
}

View File

@ -44,7 +44,7 @@ void MainFunction::operator()(Block& _block)
Block& block = std::get<Block>(_block.statements[0]);
FunctionDefinition main{
block.location,
block.debugData,
"main"_yulstring,
{},
{},

View File

@ -80,7 +80,7 @@ void ReasoningBasedSimplifier::operator()(If& _if)
if (result == CheckResult::UNSATISFIABLE)
{
Literal trueCondition = m_dialect.trueLiteral();
trueCondition.location = locationOf(*_if.condition);
trueCondition.debugData = locationOf(*_if.condition);
_if.condition = make_unique<yul::Expression>(move(trueCondition));
}
else
@ -92,7 +92,7 @@ void ReasoningBasedSimplifier::operator()(If& _if)
if (result2 == CheckResult::UNSATISFIABLE)
{
Literal falseCondition = m_dialect.zeroLiteralForType(m_dialect.boolType);
falseCondition.location = locationOf(*_if.condition);
falseCondition.debugData = locationOf(*_if.condition);
_if.condition = make_unique<yul::Expression>(move(falseCondition));
_if.body = yul::Block{};
// Nothing left to be done.

View File

@ -66,12 +66,12 @@ void SSAReverser::operator()(Block& _block)
else
return util::make_vector<Statement>(
Assignment{
std::move(assignment->location),
std::move(assignment->debugData),
assignment->variableNames,
std::move(varDecl->value)
},
VariableDeclaration{
std::move(varDecl->location),
std::move(varDecl->debugData),
std::move(varDecl->variables),
std::make_unique<Expression>(assignment->variableNames.front())
}
@ -97,17 +97,17 @@ void SSAReverser::operator()(Block& _block)
)
{
auto varIdentifier2 = std::make_unique<Expression>(Identifier{
varDecl2->variables.front().location,
varDecl2->variables.front().debugData,
varDecl2->variables.front().name
});
return util::make_vector<Statement>(
VariableDeclaration{
std::move(varDecl2->location),
std::move(varDecl2->debugData),
std::move(varDecl2->variables),
std::move(varDecl->value)
},
VariableDeclaration{
std::move(varDecl->location),
std::move(varDecl->debugData),
std::move(varDecl->variables),
std::move(varIdentifier2)
}

View File

@ -85,19 +85,19 @@ void IntroduceSSA::operator()(Block& _block)
// Replace "let a := v" by "let a_1 := v let a := a_1"
// Replace "let a, b := v" by "let a_1, b_1 := v let a := a_1 let b := b_2"
auto loc = varDecl.location;
auto debugData = varDecl.debugData;
vector<Statement> statements;
statements.emplace_back(VariableDeclaration{loc, {}, std::move(varDecl.value)});
statements.emplace_back(VariableDeclaration{debugData, {}, std::move(varDecl.value)});
TypedNameList newVariables;
for (auto const& var: varDecl.variables)
{
YulString oldName = var.name;
YulString newName = m_nameDispenser.newName(oldName);
newVariables.emplace_back(TypedName{loc, newName, var.type});
newVariables.emplace_back(TypedName{debugData, newName, var.type});
statements.emplace_back(VariableDeclaration{
loc,
{TypedName{loc, oldName, var.type}},
make_unique<Expression>(Identifier{loc, newName})
debugData,
{TypedName{debugData, oldName, var.type}},
make_unique<Expression>(Identifier{debugData, newName})
});
}
std::get<VariableDeclaration>(statements.front()).variables = std::move(newVariables);
@ -112,23 +112,23 @@ void IntroduceSSA::operator()(Block& _block)
// Replace "a := v" by "let a_1 := v a := v"
// Replace "a, b := v" by "let a_1, b_1 := v a := a_1 b := b_2"
auto loc = assignment.location;
auto debugData = assignment.debugData;
vector<Statement> statements;
statements.emplace_back(VariableDeclaration{loc, {}, std::move(assignment.value)});
statements.emplace_back(VariableDeclaration{debugData, {}, std::move(assignment.value)});
TypedNameList newVariables;
for (auto const& var: assignment.variableNames)
{
YulString oldName = var.name;
YulString newName = m_nameDispenser.newName(oldName);
newVariables.emplace_back(TypedName{
loc,
debugData,
newName,
m_typeInfo.typeOfVariable(oldName)
});
statements.emplace_back(Assignment{
loc,
{Identifier{loc, oldName}},
make_unique<Expression>(Identifier{loc, newName})
debugData,
{Identifier{debugData, oldName}},
make_unique<Expression>(Identifier{debugData, newName})
});
}
std::get<VariableDeclaration>(statements.front()).variables = std::move(newVariables);
@ -236,11 +236,12 @@ void IntroduceControlFlowSSA::operator()(Block& _block)
vector<Statement> toPrepend;
for (YulString toReassign: m_variablesToReassign)
{
auto const debugData(locationOf(_s));
YulString newName = m_nameDispenser.newName(toReassign);
toPrepend.emplace_back(VariableDeclaration{
locationOf(_s),
{TypedName{locationOf(_s), newName, m_typeInfo.typeOfVariable(toReassign)}},
make_unique<Expression>(Identifier{locationOf(_s), toReassign})
debugData,
{TypedName{debugData, newName, m_typeInfo.typeOfVariable(toReassign)}},
make_unique<Expression>(Identifier{debugData, toReassign})
});
assignedVariables.insert(toReassign);
}

View File

@ -241,7 +241,12 @@ Expression Pattern::toExpression(SourceLocation const& _location) const
if (m_kind == PatternKind::Constant)
{
assertThrow(m_data, OptimizerException, "No match group and no constant value given.");
return Literal{_location, LiteralKind::Number, YulString{util::formatNumber(*m_data)}, {}};
return Literal{
make_shared<DebugData>(_location),
LiteralKind::Number,
YulString{util::formatNumber(*m_data)},
{}
};
}
else if (m_kind == PatternKind::Operation)
{
@ -252,9 +257,10 @@ Expression Pattern::toExpression(SourceLocation const& _location) const
string name = instructionInfo(m_instruction).name;
transform(begin(name), end(name), begin(name), [](auto _c) { return tolower(_c); });
auto const debugData = make_shared<DebugData>(_location);
return FunctionCall{
_location,
Identifier{_location, YulString{name}},
debugData,
Identifier{debugData, YulString{name}},
std::move(arguments)
};
}

View File

@ -36,14 +36,15 @@ vector<Statement> generateMemoryStore(
Expression _value
)
{
auto const debugData = make_shared<DebugData>(_loc);
BuiltinFunction const* memoryStoreFunction = _dialect.memoryStoreFunction(_dialect.defaultType);
yulAssert(memoryStoreFunction, "");
vector<Statement> result;
result.emplace_back(ExpressionStatement{_loc, FunctionCall{
_loc,
Identifier{_loc, memoryStoreFunction->name},
result.emplace_back(ExpressionStatement{debugData, FunctionCall{
debugData,
Identifier{debugData, memoryStoreFunction->name},
{
Literal{_loc, LiteralKind::Number, _mpos, {}},
Literal{debugData, LiteralKind::Number, _mpos, {}},
std::move(_value)
}
}});
@ -52,13 +53,14 @@ vector<Statement> generateMemoryStore(
FunctionCall generateMemoryLoad(Dialect const& _dialect, langutil::SourceLocation const& _loc, YulString _mpos)
{
auto const debugData = make_shared<DebugData>(_loc);
BuiltinFunction const* memoryLoadFunction = _dialect.memoryLoadFunction(_dialect.defaultType);
yulAssert(memoryLoadFunction, "");
return FunctionCall{
_loc,
Identifier{_loc, memoryLoadFunction->name}, {
debugData,
Identifier{debugData, memoryLoadFunction->name}, {
Literal{
_loc,
debugData,
LiteralKind::Number,
_mpos,
{}
@ -123,7 +125,7 @@ void StackToMemoryMover::operator()(Block& _block)
if (!leftHandSideNeedsMoving)
return {};
langutil::SourceLocation loc = _stmt.location;
langutil::SourceLocation loc = _stmt.debugData->irLocation;
if (_variables.size() == 1)
{
@ -133,29 +135,29 @@ void StackToMemoryMover::operator()(Block& _block)
m_context.dialect,
loc,
*offset,
_stmt.value ? *std::move(_stmt.value) : Literal{loc, LiteralKind::Number, "0"_yulstring, {}}
_stmt.value ? *std::move(_stmt.value) : Literal{_stmt.debugData, LiteralKind::Number, "0"_yulstring, {}}
);
}
VariableDeclaration tempDecl{loc, {}, std::move(_stmt.value)};
VariableDeclaration tempDecl{_stmt.debugData, {}, std::move(_stmt.value)};
vector<Statement> memoryAssignments;
vector<Statement> variableAssignments;
for (auto& var: _variables)
{
YulString tempVarName = m_nameDispenser.newName(var.name);
tempDecl.variables.emplace_back(TypedName{var.location, tempVarName, {}});
tempDecl.variables.emplace_back(TypedName{var.debugData, tempVarName, {}});
if (optional<YulString> offset = m_memoryOffsetTracker(var.name))
memoryAssignments += generateMemoryStore(
m_context.dialect,
loc,
*offset,
Identifier{loc, tempVarName}
Identifier{_stmt.debugData, tempVarName}
);
else
variableAssignments.emplace_back(StatementType{
loc, {move(var)},
make_unique<Expression>(Identifier{loc, tempVarName})
_stmt.debugData, {move(var)},
make_unique<Expression>(Identifier{_stmt.debugData, tempVarName})
});
}
std::vector<Statement> result;
@ -191,7 +193,7 @@ void StackToMemoryMover::visit(Expression& _expression)
ASTModifier::visit(_expression);
if (Identifier* identifier = std::get_if<Identifier>(&_expression))
if (optional<YulString> offset = m_memoryOffsetTracker(identifier->name))
_expression = generateMemoryLoad(m_context.dialect, identifier->location, *offset);
_expression = generateMemoryLoad(m_context.dialect, identifier->debugData->irLocation, *offset);
}
optional<YulString> StackToMemoryMover::VariableMemoryOffsetTracker::operator()(YulString _variable) const

View File

@ -40,33 +40,31 @@ FunctionDefinition unusedFunctionsCommon::createLinkingFunction(
auto generateTypedName = [&](TypedName t)
{
return TypedName{
t.location,
t.debugData,
_nameDispenser.newName(t.name),
t.type
};
};
langutil::SourceLocation loc = _original.location;
FunctionDefinition linkingFunction{
loc,
_original.debugData,
_linkingFunctionName,
util::applyMap(_original.parameters, generateTypedName),
util::applyMap(_original.returnVariables, generateTypedName),
{loc, {}} // body
{_original.debugData, {}} // body
};
FunctionCall call{loc, Identifier{loc, _originalFunctionName}, {}};
FunctionCall call{_original.debugData, Identifier{_original.debugData, _originalFunctionName}, {}};
for (auto const& p: filter(linkingFunction.parameters, _usedParametersAndReturns.first))
call.arguments.emplace_back(Identifier{loc, p.name});
call.arguments.emplace_back(Identifier{_original.debugData, p.name});
Assignment assignment{loc, {}, nullptr};
Assignment assignment{_original.debugData, {}, nullptr};
for (auto const& r: filter(linkingFunction.returnVariables, _usedParametersAndReturns.second))
assignment.variableNames.emplace_back(Identifier{loc, r.name});
assignment.variableNames.emplace_back(Identifier{_original.debugData, r.name});
if (assignment.variableNames.empty())
linkingFunction.body.statements.emplace_back(ExpressionStatement{loc, std::move(call)});
linkingFunction.body.statements.emplace_back(ExpressionStatement{_original.debugData, std::move(call)});
else
{
assignment.value = std::make_unique<Expression>(std::move(call));

View File

@ -72,7 +72,7 @@ void UnusedPruner::operator()(Block& _block)
if (!used(funDef.name))
{
subtractReferences(ReferencesCounter::countReferences(funDef.body));
statement = Block{std::move(funDef.location), {}};
statement = Block{std::move(funDef.debugData), {}};
}
}
else if (holds_alternative<VariableDeclaration>(statement))
@ -90,19 +90,19 @@ void UnusedPruner::operator()(Block& _block)
))
{
if (!varDecl.value)
statement = Block{std::move(varDecl.location), {}};
statement = Block{std::move(varDecl.debugData), {}};
else if (
SideEffectsCollector(m_dialect, *varDecl.value, m_functionSideEffects).
canBeRemoved(m_allowMSizeOptimization)
)
{
subtractReferences(ReferencesCounter::countReferences(*varDecl.value));
statement = Block{std::move(varDecl.location), {}};
statement = Block{std::move(varDecl.debugData), {}};
}
else if (varDecl.variables.size() == 1 && m_dialect.discardFunction(varDecl.variables.front().type))
statement = ExpressionStatement{varDecl.location, FunctionCall{
varDecl.location,
{varDecl.location, m_dialect.discardFunction(varDecl.variables.front().type)->name},
statement = ExpressionStatement{varDecl.debugData, FunctionCall{
varDecl.debugData,
{varDecl.debugData, m_dialect.discardFunction(varDecl.variables.front().type)->name},
{*std::move(varDecl.value)}
}};
}
@ -116,7 +116,7 @@ void UnusedPruner::operator()(Block& _block)
)
{
subtractReferences(ReferencesCounter::countReferences(exprStmt.expression));
statement = Block{std::move(exprStmt.location), {}};
statement = Block{std::move(exprStmt.debugData), {}};
}
}

View File

@ -47,11 +47,11 @@ void VarDeclInitializer::operator()(Block& _block)
else
{
OptionalStatements ret{vector<Statement>{}};
langutil::SourceLocation loc{std::move(_varDecl.location)};
shared_ptr<DebugData> const debugData{std::move(_varDecl.debugData)};
for (auto& var: _varDecl.variables)
{
unique_ptr<Expression> expr = make_unique<Expression >(m_dialect.zeroLiteralForType(var.type));
ret->emplace_back(VariableDeclaration{loc, {std::move(var)}, std::move(expr)});
ret->emplace_back(VariableDeclaration{debugData, {std::move(var)}, std::move(expr)});
}
return ret;
}