mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Refactoring yul source locations.
This commit is contained in:
parent
fe4822a1d2
commit
e404b6e7a6
@ -482,7 +482,7 @@ void ControlFlowBuilder::operator()(yul::Identifier const& _identifier)
|
||||
m_currentNode->variableOccurrences.emplace_back(
|
||||
*declaration,
|
||||
VariableOccurrence::Kind::Access,
|
||||
_identifier.location
|
||||
_identifier.debugData->location
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -498,7 +498,7 @@ void ControlFlowBuilder::operator()(yul::Assignment const& _assignment)
|
||||
m_currentNode->variableOccurrences.emplace_back(
|
||||
*declaration,
|
||||
VariableOccurrence::Kind::Assignment,
|
||||
variable.location
|
||||
variable.debugData->location
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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->location);
|
||||
for (yul::TypedName const& varName: _function.parameters + _function.returnVariables)
|
||||
validateYulIdentifierName(varName.name, varName.location);
|
||||
validateYulIdentifierName(varName.name, varName.debugData->location);
|
||||
|
||||
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->location,
|
||||
"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->location,
|
||||
"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->location,
|
||||
"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->location);
|
||||
|
||||
|
||||
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->location,
|
||||
ssl,
|
||||
"This declaration shadows a declaration outside the inline assembly block."
|
||||
);
|
||||
|
@ -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->location, "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->location,
|
||||
"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->location, "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->location, "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->location, "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->location,
|
||||
"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->location, "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->location, "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->location, "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->location, "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->location, "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->location, "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->location,
|
||||
"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->location, "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->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\".");
|
||||
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->location, "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->location, "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->location, "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->location, "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->location, "Expected a library.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -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->location, *fun->instruction);
|
||||
|
||||
for (auto const& arg: _funCall.arguments)
|
||||
std::visit(*this, arg);
|
||||
|
@ -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->location);
|
||||
tuple["declaration"] = idOrNull(_info.second.declaration);
|
||||
tuple["isSlot"] = Json::Value(_info.second.suffix == "slot");
|
||||
tuple["isOffset"] = Json::Value(_info.second.suffix == "offset");
|
||||
|
@ -24,12 +24,10 @@
|
||||
#include <libsolidity/ast/ASTJsonImporter.h>
|
||||
|
||||
#include <libyul/AsmJsonImporter.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/AST.h>
|
||||
#include <libyul/Dialect.h>
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
|
||||
#include <liblangutil/ErrorReporter.h>
|
||||
#include <liblangutil/Exceptions.h>
|
||||
#include <liblangutil/Scanner.h>
|
||||
#include <liblangutil/SourceLocation.h>
|
||||
|
@ -28,11 +28,11 @@
|
||||
#include <libsolidity/codegen/CompilerUtils.h>
|
||||
#include <libsolidity/interface/Version.h>
|
||||
|
||||
#include <libyul/AST.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/AsmPrinter.h>
|
||||
#include <libyul/AsmAnalysis.h>
|
||||
#include <libyul/AsmAnalysisInfo.h>
|
||||
#include <libyul/AST.h>
|
||||
#include <libyul/backends/evm/AsmCodeGen.h>
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
#include <libyul/backends/evm/EVMMetrics.h>
|
||||
@ -426,7 +426,7 @@ void CompilerContext::appendInlineAssembly(
|
||||
if (stackDiff < 1 || stackDiff > 16)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
StackTooDeepError() <<
|
||||
errinfo_sourceLocation(_identifier.location) <<
|
||||
errinfo_sourceLocation(_identifier.debugData->location) <<
|
||||
util::errinfo_comment("Stack too deep (" + to_string(stackDiff) + "), try removing local variables.")
|
||||
);
|
||||
if (_context == yul::IdentifierContext::RValue)
|
||||
|
@ -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}};
|
||||
}
|
||||
|
||||
|
||||
|
@ -61,8 +61,8 @@
|
||||
#include <libyul/AsmPrinter.h>
|
||||
#include <libyul/AsmJsonConverter.h>
|
||||
#include <libyul/AssemblyStack.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/AST.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
|
||||
#include <liblangutil/Scanner.h>
|
||||
#include <liblangutil/SemVerHandler.h>
|
||||
|
@ -24,8 +24,8 @@
|
||||
#include <libsolidity/parsing/Parser.h>
|
||||
|
||||
#include <libsolidity/interface/Version.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/AST.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
#include <liblangutil/ErrorReporter.h>
|
||||
#include <liblangutil/Scanner.h>
|
||||
@ -1299,7 +1299,7 @@ ASTPointer<InlineAssembly> Parser::parseInlineAssembly(ASTPointer<ASTString> con
|
||||
if (block == nullptr)
|
||||
BOOST_THROW_EXCEPTION(FatalError());
|
||||
|
||||
location.end = block->location.end;
|
||||
location.end = block->debugData->location.end;
|
||||
return make_shared<InlineAssembly>(nextID(), location, _docString, dialect, block);
|
||||
}
|
||||
|
||||
|
60
libyul/AST.h
60
libyul/AST.h
@ -35,56 +35,80 @@ namespace solidity::yul
|
||||
|
||||
using Type = YulString;
|
||||
|
||||
struct TypedName { langutil::SourceLocation location; YulString name; Type type; };
|
||||
struct DebugData
|
||||
{
|
||||
explicit DebugData(langutil::SourceLocation _location): location(std::move(_location)) {}
|
||||
langutil::SourceLocation location;
|
||||
static std::shared_ptr<DebugData const> create(langutil::SourceLocation _location = {})
|
||||
{
|
||||
return std::make_shared<DebugData const>(_location);
|
||||
}
|
||||
};
|
||||
|
||||
struct TypedName { std::shared_ptr<DebugData const> 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 const> 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 const> 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 const> debugData; std::vector<Identifier> variableNames; std::unique_ptr<Expression> value; };
|
||||
struct FunctionCall { std::shared_ptr<DebugData const> 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 const> 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 const> 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 const> 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 const> 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 const> 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 const> 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 const> debugData; std::unique_ptr<Expression> expression; std::vector<Case> cases; };
|
||||
struct ForLoop { std::shared_ptr<DebugData const> 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 const> debugData; };
|
||||
/// Continue statement (valid within for loop)
|
||||
struct Continue { langutil::SourceLocation location; };
|
||||
struct Continue { std::shared_ptr<DebugData const> debugData; };
|
||||
/// Leave statement (valid within function)
|
||||
struct Leave { langutil::SourceLocation location; };
|
||||
struct Leave { std::shared_ptr<DebugData const> debugData; };
|
||||
|
||||
struct LocationExtractor
|
||||
{
|
||||
template <class T> langutil::SourceLocation operator()(T const& _node) const
|
||||
{
|
||||
return _node.location;
|
||||
return _node.debugData ? _node.debugData->location : langutil::SourceLocation{};
|
||||
}
|
||||
};
|
||||
|
||||
/// Extracts the source location from an inline assembly node.
|
||||
/// Extracts the source location from a Yul node.
|
||||
template <class T> inline langutil::SourceLocation locationOf(T const& _node)
|
||||
{
|
||||
return std::visit(LocationExtractor(), _node);
|
||||
}
|
||||
|
||||
struct DebugDataExtractor
|
||||
{
|
||||
template <class T> std::shared_ptr<DebugData const> const& operator()(T const& _node) const
|
||||
{
|
||||
return _node.debugData;
|
||||
}
|
||||
};
|
||||
|
||||
/// Extracts the debug data from a Yul node.
|
||||
template <class T> inline std::shared_ptr<DebugData const> const& debugDataOf(T const& _node)
|
||||
{
|
||||
return std::visit(DebugDataExtractor(), _node);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
namespace solidity::yul
|
||||
{
|
||||
|
||||
struct DebugData;
|
||||
enum class LiteralKind;
|
||||
struct Literal;
|
||||
struct Label;
|
||||
|
@ -98,22 +98,22 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect,
|
||||
|
||||
vector<YulString> AsmAnalyzer::operator()(Literal const& _literal)
|
||||
{
|
||||
expectValidType(_literal.type, _literal.location);
|
||||
expectValidType(_literal.type, _literal.debugData->location);
|
||||
if (_literal.kind == LiteralKind::String && _literal.value.str().size() > 32)
|
||||
m_errorReporter.typeError(
|
||||
3069_error,
|
||||
_literal.location,
|
||||
_literal.debugData->location,
|
||||
"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->location, "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->location,
|
||||
"Invalid type \"" + _literal.type.str() + "\" for literal \"" + _literal.value.str() + "\"."
|
||||
);
|
||||
|
||||
@ -133,7 +133,7 @@ vector<YulString> AsmAnalyzer::operator()(Identifier const& _identifier)
|
||||
if (!m_activeVariables.count(&_var))
|
||||
m_errorReporter.declarationError(
|
||||
4990_error,
|
||||
_identifier.location,
|
||||
_identifier.debugData->location,
|
||||
"Variable " + _identifier.name.str() + " used before it was declared."
|
||||
);
|
||||
type = _var.type;
|
||||
@ -142,7 +142,7 @@ vector<YulString> AsmAnalyzer::operator()(Identifier const& _identifier)
|
||||
{
|
||||
m_errorReporter.typeError(
|
||||
6041_error,
|
||||
_identifier.location,
|
||||
_identifier.debugData->location,
|
||||
"Function " + _identifier.name.str() + " used without being called."
|
||||
);
|
||||
}
|
||||
@ -160,7 +160,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->location,
|
||||
"Identifier \"" + _identifier.name.str() + "\" not found."
|
||||
);
|
||||
|
||||
@ -176,7 +176,7 @@ void AsmAnalyzer::operator()(ExpressionStatement const& _statement)
|
||||
if (watcher.ok() && !types.empty())
|
||||
m_errorReporter.typeError(
|
||||
3083_error,
|
||||
_statement.location,
|
||||
_statement.debugData->location,
|
||||
"Top-level expressions are not supposed to return values (this expression returns " +
|
||||
to_string(types.size()) +
|
||||
" value" +
|
||||
@ -196,7 +196,7 @@ void AsmAnalyzer::operator()(Assignment const& _assignment)
|
||||
if (!variables.insert(_variableName.name).second)
|
||||
m_errorReporter.declarationError(
|
||||
9005_error,
|
||||
_assignment.location,
|
||||
_assignment.debugData->location,
|
||||
"Variable " +
|
||||
_variableName.name.str() +
|
||||
" occurs multiple times on the left-hand side of the assignment."
|
||||
@ -207,7 +207,7 @@ void AsmAnalyzer::operator()(Assignment const& _assignment)
|
||||
if (types.size() != numVariables)
|
||||
m_errorReporter.declarationError(
|
||||
8678_error,
|
||||
_assignment.location,
|
||||
_assignment.debugData->location,
|
||||
"Variable count for assignment to \"" +
|
||||
joinHumanReadable(applyMap(_assignment.variableNames, [](auto const& _identifier){ return _identifier.name.str(); })) +
|
||||
"\" does not match number of values (" +
|
||||
@ -229,14 +229,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->location);
|
||||
expectValidType(variable.type, variable.debugData->location);
|
||||
}
|
||||
|
||||
if (_varDecl.value)
|
||||
@ -245,7 +245,7 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl)
|
||||
if (types.size() != numVariables)
|
||||
m_errorReporter.declarationError(
|
||||
3812_error,
|
||||
_varDecl.location,
|
||||
_varDecl.debugData->location,
|
||||
"Variable count mismatch for declaration of \"" +
|
||||
joinHumanReadable(applyMap(_varDecl.variables, [](auto const& _identifier){ return _identifier.name.str(); })) +
|
||||
+ "\": " +
|
||||
@ -264,7 +264,7 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl)
|
||||
if (variable.type != givenType)
|
||||
m_errorReporter.typeError(
|
||||
3947_error,
|
||||
variable.location,
|
||||
variable.debugData->location,
|
||||
"Assigning value of type \"" + givenType.str() + "\" to variable of type \"" + variable.type.str() + "\"."
|
||||
);
|
||||
}
|
||||
@ -279,14 +279,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->location);
|
||||
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->location);
|
||||
expectValidType(var.type, var.debugData->location);
|
||||
m_activeVariables.insert(&std::get<Scope::Variable>(varScope.identifiers.at(var.name)));
|
||||
}
|
||||
|
||||
@ -315,7 +315,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
|
||||
{
|
||||
m_errorReporter.typeError(
|
||||
4202_error,
|
||||
_funCall.functionName.location,
|
||||
_funCall.functionName.debugData->location,
|
||||
"Attempt to call variable instead of function."
|
||||
);
|
||||
},
|
||||
@ -329,7 +329,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
|
||||
if (!validateInstructions(_funCall))
|
||||
m_errorReporter.declarationError(
|
||||
4619_error,
|
||||
_funCall.functionName.location,
|
||||
_funCall.functionName.debugData->location,
|
||||
"Function \"" + _funCall.functionName.name.str() + "\" not found."
|
||||
);
|
||||
yulAssert(!watcher.ok(), "Expected a reported error.");
|
||||
@ -338,7 +338,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->location,
|
||||
"Function \"" + _funCall.functionName.name.str() + "\" expects " +
|
||||
to_string(parameterTypes->size()) +
|
||||
" arguments but got " +
|
||||
@ -358,13 +358,13 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
|
||||
if (!holds_alternative<Literal>(arg))
|
||||
m_errorReporter.typeError(
|
||||
9114_error,
|
||||
_funCall.functionName.location,
|
||||
_funCall.functionName.debugData->location,
|
||||
"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->location,
|
||||
"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->location,
|
||||
"Unknown data object \"" + std::get<Literal>(arg).value.str() + "\"."
|
||||
);
|
||||
}
|
||||
@ -384,7 +384,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
|
||||
if (get<Literal>(arg).value.empty())
|
||||
m_errorReporter.typeError(
|
||||
1844_error,
|
||||
get<Literal>(arg).location,
|
||||
get<Literal>(arg).debugData->location,
|
||||
"The \"verbatim_*\" builtins cannot be used with empty bytecode."
|
||||
);
|
||||
}
|
||||
@ -427,7 +427,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->location,
|
||||
"\"switch\" statement with only a default case."
|
||||
);
|
||||
|
||||
@ -440,7 +440,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->location);
|
||||
|
||||
// We cannot use "expectExpression" here because *_case.value is not an
|
||||
// Expression and would be converted to an Expression otherwise.
|
||||
@ -450,7 +450,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->location,
|
||||
"Duplicate case \"" +
|
||||
valueOfLiteral(*_case.value).str() +
|
||||
"\" defined."
|
||||
@ -542,11 +542,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->location, "Assignment requires variable.");
|
||||
else if (!m_activeVariables.count(&std::get<Scope::Variable>(*var)))
|
||||
m_errorReporter.declarationError(
|
||||
1133_error,
|
||||
_variable.location,
|
||||
_variable.debugData->location,
|
||||
"Variable " + _variable.name.str() + " used before it was declared."
|
||||
);
|
||||
else
|
||||
@ -565,11 +565,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->location, "Variable not found or variable not lvalue.");
|
||||
if (variableType && *variableType != _valueType)
|
||||
m_errorReporter.typeError(
|
||||
9547_error,
|
||||
_variable.location,
|
||||
_variable.debugData->location,
|
||||
"Assigning a value of type \"" +
|
||||
_valueType.str() +
|
||||
"\" to a variable of type \"" +
|
||||
@ -713,5 +713,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->location);
|
||||
}
|
||||
|
@ -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->location, "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->location, "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->location, "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->location, "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->location, "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->location, "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->location, "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->location, "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->location, "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->location, "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->location, "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->location, "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->location, "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->location, "YulBreak");
|
||||
}
|
||||
|
||||
Json::Value AsmJsonConverter::operator()(Continue const& _node) const
|
||||
{
|
||||
return createAstNode(_node.location, "YulContinue");
|
||||
return createAstNode(_node.debugData->location, "YulContinue");
|
||||
}
|
||||
|
||||
Json::Value AsmJsonConverter::operator()(Leave const& _node) const
|
||||
{
|
||||
return createAstNode(_node.location, "YulLeave");
|
||||
return createAstNode(_node.debugData->location, "YulLeave");
|
||||
}
|
||||
|
||||
Json::Value AsmJsonConverter::createAstNode(langutil::SourceLocation const& _location, string _nodeType) const
|
||||
|
@ -52,11 +52,12 @@ template <class T>
|
||||
T AsmJsonImporter::createAsmNode(Json::Value const& _node)
|
||||
{
|
||||
T r;
|
||||
r.location = createSourceLocation(_node);
|
||||
SourceLocation location = createSourceLocation(_node);
|
||||
yulAssert(
|
||||
r.location.source && 0 <= r.location.start && r.location.start <= r.location.end,
|
||||
location.source && 0 <= location.start && location.start <= location.end,
|
||||
"Invalid source location in Asm AST"
|
||||
);
|
||||
r.debugData = DebugData::create(location);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,8 @@
|
||||
* Solidity inline assembly parser.
|
||||
*/
|
||||
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/AST.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/Exceptions.h>
|
||||
#include <liblangutil/Scanner.h>
|
||||
#include <liblangutil/ErrorReporter.h>
|
||||
@ -40,6 +40,21 @@ using namespace solidity::util;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::yul;
|
||||
|
||||
namespace {
|
||||
|
||||
[[nodiscard]]
|
||||
shared_ptr<DebugData const> updateLocationEndFrom(
|
||||
shared_ptr<DebugData const> const& _debugData,
|
||||
langutil::SourceLocation const& _location
|
||||
)
|
||||
{
|
||||
SourceLocation updatedLocation = _debugData->location;
|
||||
updatedLocation.end = _location.end;
|
||||
return make_shared<DebugData const>(updatedLocation);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
unique_ptr<Block> Parser::parse(std::shared_ptr<Scanner> const& _scanner, bool _reuseScanner)
|
||||
{
|
||||
m_recursionDepth = 0;
|
||||
@ -70,7 +85,7 @@ Block Parser::parseBlock()
|
||||
expectToken(Token::LBrace);
|
||||
while (currentToken() != Token::RBrace)
|
||||
block.statements.emplace_back(parseStatement());
|
||||
block.location.end = currentLocation().end;
|
||||
block.debugData = updateLocationEndFrom(block.debugData, currentLocation());
|
||||
advance();
|
||||
return block;
|
||||
}
|
||||
@ -109,7 +124,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 = updateLocationEndFrom(_switch.debugData, _switch.cases.back().body.debugData->location);
|
||||
return Statement{move(_switch)};
|
||||
}
|
||||
case Token::For:
|
||||
@ -150,13 +165,13 @@ Statement Parser::parseStatement()
|
||||
case Token::LParen:
|
||||
{
|
||||
Expression expr = parseCall(std::move(elementary));
|
||||
return ExpressionStatement{locationOf(expr), move(expr)};
|
||||
return ExpressionStatement{debugDataOf(expr), move(expr)};
|
||||
}
|
||||
case Token::Comma:
|
||||
case Token::AssemblyAssign:
|
||||
{
|
||||
Assignment assignment;
|
||||
assignment.location = locationOf(elementary);
|
||||
assignment.debugData = debugDataOf(elementary);
|
||||
|
||||
while (true)
|
||||
{
|
||||
@ -191,7 +206,7 @@ Statement Parser::parseStatement()
|
||||
expectToken(Token::AssemblyAssign);
|
||||
|
||||
assignment.value = make_unique<Expression>(parseExpression());
|
||||
assignment.location.end = locationOf(*assignment.value).end;
|
||||
assignment.debugData = updateLocationEndFrom(assignment.debugData, locationOf(*assignment.value));
|
||||
|
||||
return Statement{move(assignment)};
|
||||
}
|
||||
@ -221,7 +236,7 @@ Case Parser::parseCase()
|
||||
else
|
||||
yulAssert(false, "Case or default case expected.");
|
||||
_case.body = parseBlock();
|
||||
_case.location.end = _case.body.location.end;
|
||||
_case.debugData = updateLocationEndFrom(_case.debugData, _case.body.debugData->location);
|
||||
return _case;
|
||||
}
|
||||
|
||||
@ -241,7 +256,7 @@ ForLoop Parser::parseForLoop()
|
||||
forLoop.post = parseBlock();
|
||||
m_currentForLoopComponent = ForLoopComponent::ForLoopBody;
|
||||
forLoop.body = parseBlock();
|
||||
forLoop.location.end = forLoop.body.location.end;
|
||||
forLoop.debugData = updateLocationEndFrom(forLoop.debugData, forLoop.body.debugData->location);
|
||||
|
||||
m_currentForLoopComponent = outerForLoopComponent;
|
||||
|
||||
@ -261,7 +276,7 @@ Expression Parser::parseExpression()
|
||||
if (m_dialect.builtin(_identifier.name))
|
||||
fatalParserError(
|
||||
7104_error,
|
||||
_identifier.location,
|
||||
_identifier.debugData->location,
|
||||
"Builtin function \"" + _identifier.name.str() + "\" must be called."
|
||||
);
|
||||
return move(_identifier);
|
||||
@ -280,7 +295,7 @@ variant<Literal, Identifier> Parser::parseLiteralOrIdentifier()
|
||||
{
|
||||
case Token::Identifier:
|
||||
{
|
||||
Identifier identifier{currentLocation(), YulString{currentLiteral()}};
|
||||
Identifier identifier{DebugData::create(currentLocation()), YulString{currentLiteral()}};
|
||||
advance();
|
||||
return identifier;
|
||||
}
|
||||
@ -311,7 +326,7 @@ variant<Literal, Identifier> Parser::parseLiteralOrIdentifier()
|
||||
}
|
||||
|
||||
Literal literal{
|
||||
currentLocation(),
|
||||
DebugData::create(currentLocation()),
|
||||
kind,
|
||||
YulString{currentLiteral()},
|
||||
kind == LiteralKind::Boolean ? m_dialect.boolType : m_dialect.defaultType
|
||||
@ -320,7 +335,7 @@ variant<Literal, Identifier> Parser::parseLiteralOrIdentifier()
|
||||
if (currentToken() == Token::Colon)
|
||||
{
|
||||
expectToken(Token::Colon);
|
||||
literal.location.end = currentLocation().end;
|
||||
literal.debugData = updateLocationEndFrom(literal.debugData, currentLocation());
|
||||
literal.type = expectAsmIdentifier();
|
||||
}
|
||||
|
||||
@ -352,10 +367,11 @@ VariableDeclaration Parser::parseVariableDeclaration()
|
||||
{
|
||||
expectToken(Token::AssemblyAssign);
|
||||
varDecl.value = make_unique<Expression>(parseExpression());
|
||||
varDecl.location.end = locationOf(*varDecl.value).end;
|
||||
varDecl.debugData = updateLocationEndFrom(varDecl.debugData, locationOf(*varDecl.value));
|
||||
}
|
||||
else
|
||||
varDecl.location.end = varDecl.variables.back().location.end;
|
||||
varDecl.debugData = updateLocationEndFrom(varDecl.debugData, varDecl.variables.back().debugData->location);
|
||||
|
||||
return varDecl;
|
||||
}
|
||||
|
||||
@ -400,7 +416,7 @@ FunctionDefinition Parser::parseFunctionDefinition()
|
||||
m_insideFunction = true;
|
||||
funDef.body = parseBlock();
|
||||
m_insideFunction = preInsideFunction;
|
||||
funDef.location.end = funDef.body.location.end;
|
||||
funDef.debugData = updateLocationEndFrom(funDef.debugData, funDef.body.debugData->location);
|
||||
|
||||
m_currentForLoopComponent = outerForLoopComponent;
|
||||
return funDef;
|
||||
@ -415,7 +431,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 +443,7 @@ FunctionCall Parser::parseCall(variant<Literal, Identifier>&& _initialOp)
|
||||
ret.arguments.emplace_back(parseExpression());
|
||||
}
|
||||
}
|
||||
ret.location.end = currentLocation().end;
|
||||
ret.debugData = updateLocationEndFrom(ret.debugData, currentLocation());
|
||||
expectToken(Token::RParen);
|
||||
return ret;
|
||||
}
|
||||
@ -440,7 +456,7 @@ TypedName Parser::parseTypedName()
|
||||
if (currentToken() == Token::Colon)
|
||||
{
|
||||
expectToken(Token::Colon);
|
||||
typedName.location.end = currentLocation().end;
|
||||
typedName.debugData = updateLocationEndFrom(typedName.debugData, currentLocation());
|
||||
typedName.type = expectAsmIdentifier();
|
||||
}
|
||||
else
|
||||
|
@ -70,7 +70,7 @@ protected:
|
||||
template <class T> T createWithLocation() const
|
||||
{
|
||||
T r;
|
||||
r.location = currentLocation();
|
||||
r.debugData = DebugData::create(currentLocation());
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
#include <libyul/AsmAnalysis.h>
|
||||
#include <libyul/AsmAnalysisInfo.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/AsmPrinter.h>
|
||||
#include <libyul/backends/evm/EthAssemblyAdapter.h>
|
||||
#include <libyul/backends/evm/EVMAssembly.h>
|
||||
|
@ -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 {DebugData::create(), LiteralKind::Boolean, "false"_yulstring, _type};
|
||||
return {DebugData::create(), LiteralKind::Number, "0"_yulstring, _type};
|
||||
}
|
||||
|
||||
|
||||
Literal Dialect::trueLiteral() const
|
||||
{
|
||||
if (boolType != defaultType)
|
||||
return {SourceLocation{}, LiteralKind::Boolean, "true"_yulstring, boolType};
|
||||
return {DebugData::create(), LiteralKind::Boolean, "true"_yulstring, boolType};
|
||||
else
|
||||
return {SourceLocation{}, LiteralKind::Number, "1"_yulstring, defaultType};
|
||||
return {DebugData::create(), LiteralKind::Number, "1"_yulstring, defaultType};
|
||||
}
|
||||
|
||||
bool Dialect::validTypeForLiteral(LiteralKind _kind, YulString, YulString _type) const
|
||||
|
@ -19,10 +19,10 @@
|
||||
* Parser for Yul code and data object container.
|
||||
*/
|
||||
|
||||
#include <libyul/AST.h>
|
||||
#include <libyul/ObjectParser.h>
|
||||
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/AST.h>
|
||||
#include <libyul/Exceptions.h>
|
||||
|
||||
#include <liblangutil/Token.h>
|
||||
|
@ -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->location, *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->location, 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->location,
|
||||
"Function name " + _funDef.name.str() + " already taken in this scope."
|
||||
);
|
||||
return false;
|
||||
|
@ -23,6 +23,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <libyul/ASTForward.h>
|
||||
|
||||
#include <libsolutil/Common.h>
|
||||
#include <libsolutil/CommonData.h>
|
||||
|
||||
|
@ -100,7 +100,7 @@ void ConstantOptimiser::visit(Expression& _e)
|
||||
|
||||
if (
|
||||
Expression const* repr =
|
||||
RepresentationFinder(m_dialect, m_meter, locationOf(_e), m_cache)
|
||||
RepresentationFinder(m_dialect, m_meter, debugDataOf(_e), m_cache)
|
||||
.tryFindRepresentation(valueOfLiteral(literal))
|
||||
)
|
||||
_e = ASTCopier{}.translate(*repr);
|
||||
@ -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;
|
||||
|
@ -74,12 +74,12 @@ public:
|
||||
RepresentationFinder(
|
||||
EVMDialect const& _dialect,
|
||||
GasMeter const& _meter,
|
||||
langutil::SourceLocation _location,
|
||||
std::shared_ptr<DebugData const> _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 const> 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;
|
||||
|
@ -39,7 +39,7 @@ size_t constexpr assemblySizeReferenceSize = 4;
|
||||
}
|
||||
|
||||
|
||||
void EVMAssembly::setSourceLocation(SourceLocation const&)
|
||||
void EVMAssembly::setSourceLocation(langutil::SourceLocation const&)
|
||||
{
|
||||
// Ignored for now;
|
||||
}
|
||||
|
@ -44,6 +44,16 @@ using namespace solidity;
|
||||
using namespace solidity::yul;
|
||||
using namespace solidity::util;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
langutil::SourceLocation extractSourceLocationFromDebugData(shared_ptr<DebugData const> const& _debugData)
|
||||
{
|
||||
return _debugData ? _debugData->location : langutil::SourceLocation{};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CodeTransform::CodeTransform(
|
||||
AbstractAssembly& _assembly,
|
||||
AsmAnalysisInfo& _analysisInfo,
|
||||
@ -145,13 +155,13 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl)
|
||||
}
|
||||
else
|
||||
{
|
||||
m_assembly.setSourceLocation(_varDecl.location);
|
||||
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(_varDecl.debugData));
|
||||
size_t variablesLeft = numVariables;
|
||||
while (variablesLeft--)
|
||||
m_assembly.appendConstant(u256(0));
|
||||
}
|
||||
|
||||
m_assembly.setSourceLocation(_varDecl.location);
|
||||
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(_varDecl.debugData));
|
||||
bool atTopOfStack = true;
|
||||
for (size_t varIndex = 0; varIndex < numVariables; ++varIndex)
|
||||
{
|
||||
@ -205,13 +215,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(extractSourceLocationFromDebugData(_assignment.debugData));
|
||||
generateMultiAssignment(_assignment.variableNames);
|
||||
}
|
||||
|
||||
void CodeTransform::operator()(ExpressionStatement const& _statement)
|
||||
{
|
||||
m_assembly.setSourceLocation(_statement.location);
|
||||
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(_statement.debugData));
|
||||
std::visit(*this, _statement.expression);
|
||||
}
|
||||
|
||||
@ -225,7 +235,7 @@ void CodeTransform::operator()(FunctionCall const& _call)
|
||||
});
|
||||
else
|
||||
{
|
||||
m_assembly.setSourceLocation(_call.location);
|
||||
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(_call.debugData));
|
||||
EVMAssembly::LabelID returnLabel(numeric_limits<EVMAssembly::LabelID>::max()); // only used for evm 1.0
|
||||
|
||||
returnLabel = m_assembly.newLabelId();
|
||||
@ -240,7 +250,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(extractSourceLocationFromDebugData(_call.debugData));
|
||||
m_assembly.appendJumpTo(
|
||||
functionEntryID(_call.functionName.name, *function),
|
||||
static_cast<int>(function->returns.size() - function->arguments.size()) - 1,
|
||||
@ -252,7 +262,7 @@ void CodeTransform::operator()(FunctionCall const& _call)
|
||||
|
||||
void CodeTransform::operator()(Identifier const& _identifier)
|
||||
{
|
||||
m_assembly.setSourceLocation(_identifier.location);
|
||||
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(_identifier.debugData));
|
||||
// First search internals, then externals.
|
||||
yulAssert(m_scope, "");
|
||||
if (m_scope->lookup(_identifier.name, GenericVisitor{
|
||||
@ -284,19 +294,19 @@ void CodeTransform::operator()(Identifier const& _identifier)
|
||||
|
||||
void CodeTransform::operator()(Literal const& _literal)
|
||||
{
|
||||
m_assembly.setSourceLocation(_literal.location);
|
||||
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(_literal.debugData));
|
||||
m_assembly.appendConstant(valueOfLiteral(_literal));
|
||||
}
|
||||
|
||||
void CodeTransform::operator()(If const& _if)
|
||||
{
|
||||
visitExpression(*_if.condition);
|
||||
m_assembly.setSourceLocation(_if.location);
|
||||
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(_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(extractSourceLocationFromDebugData(_if.debugData));
|
||||
m_assembly.appendLabel(end);
|
||||
}
|
||||
|
||||
@ -313,7 +323,7 @@ void CodeTransform::operator()(Switch const& _switch)
|
||||
if (c.value)
|
||||
{
|
||||
(*this)(*c.value);
|
||||
m_assembly.setSourceLocation(c.location);
|
||||
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(c.debugData));
|
||||
AbstractAssembly::LabelID bodyLabel = m_assembly.newLabelId();
|
||||
caseBodies[&c] = bodyLabel;
|
||||
yulAssert(m_assembly.stackHeight() == expressionHeight + 1, "");
|
||||
@ -325,24 +335,24 @@ void CodeTransform::operator()(Switch const& _switch)
|
||||
// default case
|
||||
(*this)(c.body);
|
||||
}
|
||||
m_assembly.setSourceLocation(_switch.location);
|
||||
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(_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(extractSourceLocationFromDebugData(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(extractSourceLocationFromDebugData(c.first->debugData));
|
||||
m_assembly.appendJumpTo(end);
|
||||
}
|
||||
}
|
||||
|
||||
m_assembly.setSourceLocation(_switch.location);
|
||||
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(_switch.debugData));
|
||||
m_assembly.appendLabel(end);
|
||||
m_assembly.appendInstruction(evmasm::Instruction::POP);
|
||||
}
|
||||
@ -363,7 +373,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
|
||||
m_context->variableStackHeights[&var] = height++;
|
||||
}
|
||||
|
||||
m_assembly.setSourceLocation(_function.location);
|
||||
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(_function.debugData));
|
||||
int const stackHeightBefore = m_assembly.stackHeight();
|
||||
|
||||
m_assembly.appendLabel(functionEntryID(_function.name, function));
|
||||
@ -488,11 +498,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(extractSourceLocationFromDebugData(_forLoop.debugData));
|
||||
m_assembly.appendLabel(loopStart);
|
||||
|
||||
visitExpression(*_forLoop.condition);
|
||||
m_assembly.setSourceLocation(_forLoop.location);
|
||||
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(_forLoop.debugData));
|
||||
m_assembly.appendInstruction(evmasm::Instruction::ISZERO);
|
||||
m_assembly.appendJumpToIf(loopEnd);
|
||||
|
||||
@ -500,12 +510,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(extractSourceLocationFromDebugData(_forLoop.debugData));
|
||||
m_assembly.appendLabel(postPart);
|
||||
|
||||
(*this)(_forLoop.post);
|
||||
|
||||
m_assembly.setSourceLocation(_forLoop.location);
|
||||
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(_forLoop.debugData));
|
||||
m_assembly.appendJumpTo(loopStart);
|
||||
m_assembly.appendLabel(loopEnd);
|
||||
|
||||
@ -525,7 +535,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(extractSourceLocationFromDebugData(_break.debugData));
|
||||
|
||||
Context::JumpInfo const& jump = m_context->forLoopStack.top().done;
|
||||
m_assembly.appendJumpTo(jump.label, appendPopUntil(jump.targetStackHeight));
|
||||
@ -534,7 +544,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(extractSourceLocationFromDebugData(_continue.debugData));
|
||||
|
||||
Context::JumpInfo const& jump = m_context->forLoopStack.top().post;
|
||||
m_assembly.appendJumpTo(jump.label, appendPopUntil(jump.targetStackHeight));
|
||||
@ -544,7 +554,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(extractSourceLocationFromDebugData(_leaveStatement.debugData));
|
||||
m_assembly.appendJumpTo(*m_functionExitLabel, appendPopUntil(*m_functionExitStackHeight));
|
||||
}
|
||||
|
||||
@ -605,7 +615,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);
|
||||
@ -654,7 +664,7 @@ void CodeTransform::visitStatements(vector<Statement> const& _statements)
|
||||
auto const* functionDefinition = std::get_if<FunctionDefinition>(&statement);
|
||||
if (functionDefinition && !jumpTarget)
|
||||
{
|
||||
m_assembly.setSourceLocation(locationOf(statement));
|
||||
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(functionDefinition->debugData));
|
||||
jumpTarget = m_assembly.newLabelId();
|
||||
m_assembly.appendJumpTo(*jumpTarget, 0);
|
||||
}
|
||||
@ -675,7 +685,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(extractSourceLocationFromDebugData(_block.debugData));
|
||||
|
||||
freeUnusedVariables();
|
||||
|
||||
|
@ -39,6 +39,7 @@ class ErrorReporter;
|
||||
|
||||
namespace solidity::yul
|
||||
{
|
||||
|
||||
struct AsmAnalysisInfo;
|
||||
class EVMAssembly;
|
||||
|
||||
|
@ -55,7 +55,7 @@ void visitArguments(
|
||||
for (auto const& arg: _call.arguments | ranges::views::reverse)
|
||||
_visitExpression(arg);
|
||||
|
||||
_assembly.setSourceLocation(_call.location);
|
||||
_assembly.setSourceLocation(_call.debugData->location);
|
||||
}
|
||||
|
||||
|
||||
@ -259,7 +259,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->location);
|
||||
_assembly.appendImmutableAssignment(identifier.str());
|
||||
}
|
||||
));
|
||||
|
@ -32,10 +32,10 @@
|
||||
#include <libyul/optimiser/OptimiserStep.h>
|
||||
#include <libyul/optimiser/ForLoopConditionIntoBody.h>
|
||||
|
||||
#include <libyul/AST.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/AsmAnalysis.h>
|
||||
#include <libyul/AsmAnalysisInfo.h>
|
||||
#include <libyul/AST.h>
|
||||
#include <libyul/Object.h>
|
||||
|
||||
#include <liblangutil/ErrorReporter.h>
|
||||
|
@ -65,8 +65,8 @@ void WordSizeTransform::operator()(FunctionCall& _fc)
|
||||
void WordSizeTransform::operator()(If& _if)
|
||||
{
|
||||
_if.condition = make_unique<Expression>(FunctionCall{
|
||||
locationOf(*_if.condition),
|
||||
Identifier{locationOf(*_if.condition), "or_bool"_yulstring},
|
||||
debugDataOf(*_if.condition),
|
||||
Identifier{debugDataOf(*_if.condition), "or_bool"_yulstring},
|
||||
expandValueToVector(*_if.condition)
|
||||
});
|
||||
(*this)(_if.body);
|
||||
@ -81,8 +81,8 @@ void WordSizeTransform::operator()(ForLoop& _for)
|
||||
{
|
||||
(*this)(_for.pre);
|
||||
_for.condition = make_unique<Expression>(FunctionCall{
|
||||
locationOf(*_for.condition),
|
||||
Identifier{locationOf(*_for.condition), "or_bool"_yulstring},
|
||||
debugDataOf(*_for.condition),
|
||||
Identifier{debugDataOf(*_for.condition), "or_bool"_yulstring},
|
||||
expandValueToVector(*_for.condition)
|
||||
});
|
||||
(*this)(_for.post);
|
||||
@ -116,18 +116,18 @@ 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),
|
||||
debugDataOf(*varDecl.value),
|
||||
LiteralKind::Number,
|
||||
"0"_yulstring,
|
||||
m_targetDialect.defaultType
|
||||
})
|
||||
});
|
||||
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,18 +177,18 @@ 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),
|
||||
debugDataOf(*assignment.value),
|
||||
LiteralKind::Number,
|
||||
"0"_yulstring,
|
||||
m_targetDialect.defaultType
|
||||
})
|
||||
});
|
||||
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,14 +272,14 @@ 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;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
vector<Statement> WordSizeTransform::handleSwitchInternal(
|
||||
langutil::SourceLocation const& _location,
|
||||
shared_ptr<DebugData const> const& _debugData,
|
||||
vector<YulString> const& _splitExpressions,
|
||||
vector<Case> _cases,
|
||||
YulString _runDefaultFlag,
|
||||
@ -304,19 +304,19 @@ vector<Statement> WordSizeTransform::handleSwitchInternal(
|
||||
}
|
||||
|
||||
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(
|
||||
_location,
|
||||
Block{_debugData, handleSwitchInternal(
|
||||
_debugData,
|
||||
_splitExpressions,
|
||||
std::move(c.second),
|
||||
_runDefaultFlag,
|
||||
@ -326,13 +326,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 +356,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 +366,7 @@ std::vector<Statement> WordSizeTransform::handleSwitch(Switch& _switch)
|
||||
splitExpressions.emplace_back(std::get<Identifier>(*expr).name);
|
||||
|
||||
ret += handleSwitchInternal(
|
||||
_switch.location,
|
||||
_switch.debugData,
|
||||
splitExpressions,
|
||||
std::move(_switch.cases),
|
||||
runDefaultFlag,
|
||||
@ -374,8 +374,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 +397,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 +410,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
|
||||
|
@ -87,7 +87,7 @@ private:
|
||||
|
||||
std::vector<Statement> handleSwitch(Switch& _switch);
|
||||
std::vector<Statement> handleSwitchInternal(
|
||||
langutil::SourceLocation const& _location,
|
||||
std::shared_ptr<DebugData const> const& _debugData,
|
||||
std::vector<YulString> const& _splitExpressions,
|
||||
std::vector<Case> _cases,
|
||||
YulString _runDefaultFlag,
|
||||
|
@ -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)
|
||||
|
@ -95,13 +95,13 @@ void CommonSubexpressionEliminator::visit(Expression& _e)
|
||||
|
||||
if (Identifier const* identifier = get_if<Identifier>(&_e))
|
||||
{
|
||||
YulString name = identifier->name;
|
||||
if (m_value.count(name))
|
||||
YulString identifierName = identifier->name;
|
||||
if (m_value.count(identifierName))
|
||||
{
|
||||
assertThrow(m_value.at(name).value, OptimizerException, "");
|
||||
if (Identifier const* value = get_if<Identifier>(m_value.at(name).value))
|
||||
assertThrow(m_value.at(identifierName).value, OptimizerException, "");
|
||||
if (Identifier const* value = get_if<Identifier>(m_value.at(identifierName).value))
|
||||
if (inScope(value->name))
|
||||
_e = Identifier{locationOf(_e), value->name};
|
||||
_e = Identifier{debugDataOf(_e), value->name};
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -120,7 +120,7 @@ void CommonSubexpressionEliminator::visit(Expression& _e)
|
||||
continue;
|
||||
if (SyntacticallyEqual{}(_e, *value.value) && inScope(variable))
|
||||
{
|
||||
_e = Identifier{locationOf(_e), variable};
|
||||
_e = Identifier{debugDataOf(_e), variable};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -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,12 @@ void ConditionalSimplifier::operator()(Block& _block)
|
||||
)
|
||||
{
|
||||
YulString condition = std::get<Identifier>(*_if.condition).name;
|
||||
langutil::SourceLocation location = _if.location;
|
||||
std::shared_ptr<DebugData const> debugData = _if.debugData;
|
||||
return make_vector<Statement>(
|
||||
std::move(_s),
|
||||
Assignment{
|
||||
location,
|
||||
{Identifier{location, condition}},
|
||||
debugData,
|
||||
{Identifier{debugData, condition}},
|
||||
make_unique<Expression>(m_dialect.zeroLiteralForType(m_dialect.boolType))
|
||||
}
|
||||
);
|
||||
|
@ -38,14 +38,14 @@ namespace
|
||||
{
|
||||
|
||||
ExpressionStatement makeDiscardCall(
|
||||
langutil::SourceLocation const& _location,
|
||||
std::shared_ptr<DebugData const> const& _debugData,
|
||||
BuiltinFunction const& _discardFunction,
|
||||
Expression&& _expression
|
||||
)
|
||||
{
|
||||
return {_location, FunctionCall{
|
||||
_location,
|
||||
Identifier{_location, _discardFunction.name},
|
||||
return {_debugData, FunctionCall{
|
||||
_debugData,
|
||||
Identifier{_debugData, _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,
|
||||
*m_dialect.discardFunction(m_dialect.boolType),
|
||||
std::move(*_ifStmt.condition)
|
||||
));
|
||||
@ -191,10 +191,8 @@ OptionalStatements ControlFlowSimplifier::reduceNoCaseSwitch(Switch& _switchStmt
|
||||
if (!discardFunction)
|
||||
return {};
|
||||
|
||||
auto loc = locationOf(*_switchStmt.expression);
|
||||
|
||||
return make_vector<Statement>(makeDiscardCall(
|
||||
loc,
|
||||
debugDataOf(*_switchStmt.expression),
|
||||
*discardFunction,
|
||||
std::move(*_switchStmt.expression)
|
||||
));
|
||||
@ -205,17 +203,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);
|
||||
shared_ptr<DebugData const> debugData = debugDataOf(*_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 +226,7 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch
|
||||
|
||||
return make_vector<Statement>(
|
||||
makeDiscardCall(
|
||||
loc,
|
||||
debugData,
|
||||
*m_dialect.discardFunction(type),
|
||||
std::move(*_switchStmt.expression)
|
||||
),
|
||||
|
@ -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(debugDataOf(_expression));
|
||||
}
|
||||
|
@ -101,15 +101,15 @@ void ExpressionSplitter::outlineExpression(Expression& _expr)
|
||||
|
||||
visit(_expr);
|
||||
|
||||
SourceLocation location = locationOf(_expr);
|
||||
shared_ptr<DebugData const> debugData = debugDataOf(_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);
|
||||
}
|
||||
|
||||
|
@ -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 = debugDataOf(*_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
|
||||
|
@ -55,7 +55,7 @@ void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop)
|
||||
return;
|
||||
|
||||
YulString iszero = m_dialect.booleanNegationFunction()->name;
|
||||
langutil::SourceLocation location = locationOf(*firstStatement.condition);
|
||||
shared_ptr<DebugData const> debugData = debugDataOf(*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)
|
||||
)
|
||||
|
@ -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)
|
||||
})
|
||||
});
|
||||
|
@ -35,7 +35,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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -84,7 +84,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(debugDataOf(_expression)));
|
||||
|
||||
return _expression;
|
||||
}
|
||||
|
@ -85,12 +85,12 @@ void LoadResolver::tryResolve(
|
||||
{
|
||||
if (auto value = util::valueOrNullptr(m_storage, key))
|
||||
if (inScope(*value))
|
||||
_e = Identifier{locationOf(_e), *value};
|
||||
_e = Identifier{debugDataOf(_e), *value};
|
||||
}
|
||||
else if (!m_containsMSize && _location == StoreLoadLocation::Memory)
|
||||
if (auto value = util::valueOrNullptr(m_memory, key))
|
||||
if (inScope(*value))
|
||||
_e = Identifier{locationOf(_e), *value};
|
||||
_e = Identifier{debugDataOf(_e), *value};
|
||||
}
|
||||
|
||||
void LoadResolver::tryEvaluateKeccak(
|
||||
@ -140,7 +140,7 @@ void LoadResolver::tryEvaluateKeccak(
|
||||
bytes contentAsBytes = toBigEndian(*memoryContent);
|
||||
contentAsBytes.resize(static_cast<size_t>(*byteLength));
|
||||
_e = Literal{
|
||||
locationOf(_e),
|
||||
debugDataOf(_e),
|
||||
LiteralKind::Number,
|
||||
YulString{u256(keccak256(contentAsBytes)).str()},
|
||||
m_dialect.defaultType
|
||||
|
@ -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,
|
||||
{},
|
||||
{},
|
||||
|
@ -79,7 +79,7 @@ void ReasoningBasedSimplifier::operator()(If& _if)
|
||||
if (result == CheckResult::UNSATISFIABLE)
|
||||
{
|
||||
Literal trueCondition = m_dialect.trueLiteral();
|
||||
trueCondition.location = locationOf(*_if.condition);
|
||||
trueCondition.debugData = debugDataOf(*_if.condition);
|
||||
_if.condition = make_unique<yul::Expression>(move(trueCondition));
|
||||
}
|
||||
else
|
||||
@ -91,7 +91,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 = debugDataOf(*_if.condition);
|
||||
_if.condition = make_unique<yul::Expression>(move(falseCondition));
|
||||
_if.body = yul::Block{};
|
||||
// Nothing left to be done.
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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;
|
||||
shared_ptr<DebugData const> 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,22 @@ 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;
|
||||
std::shared_ptr<DebugData const> 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,
|
||||
newVariables.emplace_back(TypedName{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);
|
||||
@ -238,9 +237,9 @@ void IntroduceControlFlowSSA::operator()(Block& _block)
|
||||
{
|
||||
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})
|
||||
debugDataOf(_s),
|
||||
{TypedName{debugDataOf(_s), newName, m_typeInfo.typeOfVariable(toReassign)}},
|
||||
make_unique<Expression>(Identifier{debugDataOf(_s), toReassign})
|
||||
});
|
||||
assignedVariables.insert(toReassign);
|
||||
}
|
||||
|
@ -234,27 +234,26 @@ evmasm::Instruction Pattern::instruction() const
|
||||
return m_instruction;
|
||||
}
|
||||
|
||||
Expression Pattern::toExpression(SourceLocation const& _location) const
|
||||
Expression Pattern::toExpression(shared_ptr<DebugData const> const& _debugData) const
|
||||
{
|
||||
if (matchGroup())
|
||||
return ASTCopier().translate(matchGroupValue());
|
||||
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{_debugData, LiteralKind::Number, YulString{util::formatNumber(*m_data)}, {}};
|
||||
}
|
||||
else if (m_kind == PatternKind::Operation)
|
||||
{
|
||||
vector<Expression> arguments;
|
||||
for (auto const& arg: m_arguments)
|
||||
arguments.emplace_back(arg.toExpression(_location));
|
||||
arguments.emplace_back(arg.toExpression(_debugData));
|
||||
|
||||
string name = instructionInfo(m_instruction).name;
|
||||
transform(begin(name), end(name), begin(name), [](auto _c) { return tolower(_c); });
|
||||
|
||||
return FunctionCall{
|
||||
_location,
|
||||
Identifier{_location, YulString{name}},
|
||||
return FunctionCall{_debugData,
|
||||
Identifier{_debugData, YulString{name}},
|
||||
std::move(arguments)
|
||||
};
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ public:
|
||||
|
||||
/// Turns this pattern into an actual expression. Should only be called
|
||||
/// for patterns resulting from an action, i.e. with match groups assigned.
|
||||
Expression toExpression(langutil::SourceLocation const& _location) const;
|
||||
Expression toExpression(std::shared_ptr<DebugData const> const& _debugData) const;
|
||||
|
||||
private:
|
||||
Expression const& matchGroupValue() const;
|
||||
|
@ -31,7 +31,7 @@ namespace
|
||||
{
|
||||
vector<Statement> generateMemoryStore(
|
||||
Dialect const& _dialect,
|
||||
langutil::SourceLocation const& _loc,
|
||||
shared_ptr<DebugData const> const& _debugData,
|
||||
YulString _mpos,
|
||||
Expression _value
|
||||
)
|
||||
@ -39,26 +39,26 @@ vector<Statement> generateMemoryStore(
|
||||
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)
|
||||
}
|
||||
}});
|
||||
return result;
|
||||
}
|
||||
|
||||
FunctionCall generateMemoryLoad(Dialect const& _dialect, langutil::SourceLocation const& _loc, YulString _mpos)
|
||||
FunctionCall generateMemoryLoad(Dialect const& _dialect, std::shared_ptr<DebugData const> const& _debugData, YulString _mpos)
|
||||
{
|
||||
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,39 +123,38 @@ void StackToMemoryMover::operator()(Block& _block)
|
||||
if (!leftHandSideNeedsMoving)
|
||||
return {};
|
||||
|
||||
langutil::SourceLocation loc = _stmt.location;
|
||||
|
||||
if (_variables.size() == 1)
|
||||
{
|
||||
optional<YulString> offset = m_memoryOffsetTracker(_variables.front().name);
|
||||
yulAssert(offset, "");
|
||||
return generateMemoryStore(
|
||||
m_context.dialect,
|
||||
loc,
|
||||
_stmt.debugData,
|
||||
*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,
|
||||
_stmt.debugData,
|
||||
*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 +190,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, *offset);
|
||||
}
|
||||
|
||||
optional<YulString> StackToMemoryMover::VariableMemoryOffsetTracker::operator()(YulString _variable) const
|
||||
|
@ -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));
|
||||
|
@ -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), {}};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,11 +47,10 @@ void VarDeclInitializer::operator()(Block& _block)
|
||||
else
|
||||
{
|
||||
OptionalStatements ret{vector<Statement>{}};
|
||||
langutil::SourceLocation loc{std::move(_varDecl.location)};
|
||||
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{std::move(_varDecl.debugData), {std::move(var)}, std::move(expr)});
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include <liblangutil/SourceReferenceFormatter.h>
|
||||
|
||||
#include <libyul/optimiser/Disambiguator.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/AsmAnalysis.h>
|
||||
#include <libyul/AsmPrinter.h>
|
||||
#include <libyul/AssemblyStack.h>
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
#include <libyul/backends/wasm/WasmDialect.h>
|
||||
#include <libyul/backends/wasm/EVMToEwasmTranslator.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/AssemblyStack.h>
|
||||
#include <libyul/AsmAnalysisInfo.h>
|
||||
#include <libyul/AST.h>
|
||||
|
@ -24,11 +24,11 @@
|
||||
#include <test/libsolidity/ErrorCheck.h>
|
||||
#include <test/libyul/Common.h>
|
||||
|
||||
#include <libyul/AST.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/AsmPrinter.h>
|
||||
#include <libyul/AsmAnalysis.h>
|
||||
#include <libyul/AsmAnalysisInfo.h>
|
||||
#include <libyul/AST.h>
|
||||
#include <libyul/Dialect.h>
|
||||
#include <liblangutil/Scanner.h>
|
||||
#include <liblangutil/ErrorReporter.h>
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
#include <libyul/AsmAnalysis.h>
|
||||
#include <libyul/AsmAnalysisInfo.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
#include <liblangutil/Exceptions.h>
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include <test/Common.h>
|
||||
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/AssemblyStack.h>
|
||||
#include <libyul/AsmAnalysisInfo.h>
|
||||
|
||||
|
@ -17,14 +17,12 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
#include <libyul/AsmAnalysisInfo.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/AsmAnalysis.h>
|
||||
#include <libyul/Dialect.h>
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
#include <libyul/AssemblyStack.h>
|
||||
|
||||
#include <liblangutil/Exceptions.h>
|
||||
#include <liblangutil/ErrorReporter.h>
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
|
||||
#include <libsolutil/CommonIO.h>
|
||||
|
@ -22,14 +22,12 @@
|
||||
#include <test/tools/yulInterpreter/Interpreter.h>
|
||||
|
||||
#include <libyul/AsmAnalysisInfo.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/AsmAnalysis.h>
|
||||
#include <libyul/Dialect.h>
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
#include <libyul/AssemblyStack.h>
|
||||
|
||||
#include <liblangutil/Exceptions.h>
|
||||
#include <liblangutil/ErrorReporter.h>
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
#include <liblangutil/SourceReferenceFormatter.h>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user