mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Refactoring yul AST structures to include debugdata instead of location.
This commit is contained in:
parent
cc65b426d0
commit
0563e826b5
@ -390,7 +390,7 @@ bool ControlFlowBuilder::visit(InlineAssembly const& _inlineAssembly)
|
||||
void ControlFlowBuilder::visit(yul::Statement const& _statement)
|
||||
{
|
||||
solAssert(m_currentNode && m_inlineAssembly, "");
|
||||
m_currentNode->location = langutil::SourceLocation::smallestCovering(m_currentNode->location, locationOf(_statement));
|
||||
m_currentNode->location = langutil::SourceLocation::smallestCovering(m_currentNode->location, locationOf(_statement)->irLocation);
|
||||
ASTWalker::visit(_statement);
|
||||
}
|
||||
|
||||
@ -482,8 +482,7 @@ void ControlFlowBuilder::operator()(yul::Identifier const& _identifier)
|
||||
m_currentNode->variableOccurrences.emplace_back(
|
||||
*declaration,
|
||||
VariableOccurrence::Kind::Access,
|
||||
_identifier.location
|
||||
);
|
||||
_identifier.debugData->irLocation);
|
||||
}
|
||||
}
|
||||
|
||||
@ -498,8 +497,7 @@ void ControlFlowBuilder::operator()(yul::Assignment const& _assignment)
|
||||
m_currentNode->variableOccurrences.emplace_back(
|
||||
*declaration,
|
||||
VariableOccurrence::Kind::Assignment,
|
||||
variable.location
|
||||
);
|
||||
variable.debugData->irLocation);
|
||||
}
|
||||
|
||||
void ControlFlowBuilder::operator()(yul::FunctionCall const& _functionCall)
|
||||
|
@ -201,9 +201,9 @@ bool ReferencesResolver::visit(Return const& _return)
|
||||
|
||||
void ReferencesResolver::operator()(yul::FunctionDefinition const& _function)
|
||||
{
|
||||
validateYulIdentifierName(_function.name, _function.location);
|
||||
validateYulIdentifierName(_function.name, _function.debugData->irLocation);
|
||||
for (yul::TypedName const& varName: _function.parameters + _function.returnVariables)
|
||||
validateYulIdentifierName(varName.name, varName.location);
|
||||
validateYulIdentifierName(varName.name, varName.debugData->irLocation);
|
||||
|
||||
bool wasInsideFunction = m_yulInsideFunction;
|
||||
m_yulInsideFunction = true;
|
||||
@ -238,7 +238,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
|
||||
{
|
||||
m_errorReporter.declarationError(
|
||||
4718_error,
|
||||
_identifier.location,
|
||||
_identifier.debugData->irLocation,
|
||||
"Multiple matching identifiers. Resolving overloaded identifiers is not supported."
|
||||
);
|
||||
return;
|
||||
@ -251,7 +251,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
|
||||
)
|
||||
m_errorReporter.declarationError(
|
||||
9467_error,
|
||||
_identifier.location,
|
||||
_identifier.debugData->irLocation,
|
||||
"Identifier not found. Use \".slot\" and \".offset\" to access storage variables."
|
||||
);
|
||||
return;
|
||||
@ -261,7 +261,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
|
||||
{
|
||||
m_errorReporter.declarationError(
|
||||
6578_error,
|
||||
_identifier.location,
|
||||
_identifier.debugData->irLocation,
|
||||
"Cannot access local Solidity variables from inside an inline assembly function."
|
||||
);
|
||||
return;
|
||||
@ -275,7 +275,7 @@ void ReferencesResolver::operator()(yul::VariableDeclaration const& _varDecl)
|
||||
{
|
||||
for (auto const& identifier: _varDecl.variables)
|
||||
{
|
||||
validateYulIdentifierName(identifier.name, identifier.location);
|
||||
validateYulIdentifierName(identifier.name, identifier.debugData->irLocation);
|
||||
|
||||
|
||||
if (
|
||||
@ -289,7 +289,7 @@ void ReferencesResolver::operator()(yul::VariableDeclaration const& _varDecl)
|
||||
if (!ssl.infos.empty())
|
||||
m_errorReporter.declarationError(
|
||||
3859_error,
|
||||
identifier.location,
|
||||
identifier.debugData->irLocation,
|
||||
ssl,
|
||||
"This declaration shadows a declaration outside the inline assembly block."
|
||||
);
|
||||
|
@ -743,7 +743,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
solAssert(var->type(), "Expected variable type!");
|
||||
if (var->immutable())
|
||||
{
|
||||
m_errorReporter.typeError(3773_error, _identifier.location, "Assembly access to immutable variables is not supported.");
|
||||
m_errorReporter.typeError(3773_error, _identifier.debugData->irLocation, "Assembly access to immutable variables is not supported.");
|
||||
return false;
|
||||
}
|
||||
if (var->isConstant())
|
||||
@ -752,7 +752,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
{
|
||||
m_errorReporter.typeError(
|
||||
3558_error,
|
||||
_identifier.location,
|
||||
_identifier.debugData->irLocation,
|
||||
"Constant variable is circular."
|
||||
);
|
||||
return false;
|
||||
@ -762,24 +762,24 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
|
||||
if (var && !var->value())
|
||||
{
|
||||
m_errorReporter.typeError(3224_error, _identifier.location, "Constant has no value.");
|
||||
m_errorReporter.typeError(3224_error, _identifier.debugData->irLocation, "Constant has no value.");
|
||||
return false;
|
||||
}
|
||||
else if (_context == yul::IdentifierContext::LValue)
|
||||
{
|
||||
m_errorReporter.typeError(6252_error, _identifier.location, "Constant variables cannot be assigned to.");
|
||||
m_errorReporter.typeError(6252_error, _identifier.debugData->irLocation, "Constant variables cannot be assigned to.");
|
||||
return false;
|
||||
}
|
||||
else if (!identifierInfo.suffix.empty())
|
||||
{
|
||||
m_errorReporter.typeError(6617_error, _identifier.location, "The suffixes .offset and .slot can only be used on non-constant storage variables.");
|
||||
m_errorReporter.typeError(6617_error, _identifier.debugData->irLocation, "The suffixes .offset and .slot can only be used on non-constant storage variables.");
|
||||
return false;
|
||||
}
|
||||
else if (var && var->value() && !var->value()->annotation().type && !dynamic_cast<Literal const*>(var->value().get()))
|
||||
{
|
||||
m_errorReporter.typeError(
|
||||
2249_error,
|
||||
_identifier.location,
|
||||
_identifier.debugData->irLocation,
|
||||
"Constant variables with non-literal values cannot be forward referenced from inline assembly."
|
||||
);
|
||||
return false;
|
||||
@ -789,7 +789,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
type(*var->value())->category() != Type::Category::RationalNumber
|
||||
))
|
||||
{
|
||||
m_errorReporter.typeError(7615_error, _identifier.location, "Only direct number constants and references to such constants are supported by inline assembly.");
|
||||
m_errorReporter.typeError(7615_error, _identifier.debugData->irLocation, "Only direct number constants and references to such constants are supported by inline assembly.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -804,19 +804,19 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
{
|
||||
if (suffix != "slot" && suffix != "offset")
|
||||
{
|
||||
m_errorReporter.typeError(4656_error, _identifier.location, "State variables only support \".slot\" and \".offset\".");
|
||||
m_errorReporter.typeError(4656_error, _identifier.debugData->irLocation, "State variables only support \".slot\" and \".offset\".");
|
||||
return false;
|
||||
}
|
||||
else if (_context == yul::IdentifierContext::LValue)
|
||||
{
|
||||
if (var->isStateVariable())
|
||||
{
|
||||
m_errorReporter.typeError(4713_error, _identifier.location, "State variables cannot be assigned to - you have to use \"sstore()\".");
|
||||
m_errorReporter.typeError(4713_error, _identifier.debugData->irLocation, "State variables cannot be assigned to - you have to use \"sstore()\".");
|
||||
return false;
|
||||
}
|
||||
else if (suffix != "slot")
|
||||
{
|
||||
m_errorReporter.typeError(9739_error, _identifier.location, "Only .slot can be assigned to.");
|
||||
m_errorReporter.typeError(9739_error, _identifier.debugData->irLocation, "Only .slot can be assigned to.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -828,13 +828,13 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
{
|
||||
if (suffix != "offset" && suffix != "length")
|
||||
{
|
||||
m_errorReporter.typeError(1536_error, _identifier.location, "Calldata variables only support \".offset\" and \".length\".");
|
||||
m_errorReporter.typeError(1536_error, _identifier.debugData->irLocation, "Calldata variables only support \".offset\" and \".length\".");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_errorReporter.typeError(3622_error, _identifier.location, "The suffix \"." + suffix + "\" is not supported by this variable or type.");
|
||||
m_errorReporter.typeError(3622_error, _identifier.debugData->irLocation, "The suffix \"." + suffix + "\" is not supported by this variable or type.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -842,14 +842,14 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
{
|
||||
m_errorReporter.typeError(
|
||||
1408_error,
|
||||
_identifier.location,
|
||||
_identifier.debugData->irLocation,
|
||||
"Only local variables are supported. To access storage variables, use the \".slot\" and \".offset\" suffixes."
|
||||
);
|
||||
return false;
|
||||
}
|
||||
else if (var->type()->dataStoredIn(DataLocation::Storage))
|
||||
{
|
||||
m_errorReporter.typeError(9068_error, _identifier.location, "You have to use the \".slot\" or \".offset\" suffix to access storage reference variables.");
|
||||
m_errorReporter.typeError(9068_error, _identifier.debugData->irLocation, "You have to use the \".slot\" or \".offset\" suffix to access storage reference variables.");
|
||||
return false;
|
||||
}
|
||||
else if (var->type()->sizeOnStack() != 1)
|
||||
@ -858,18 +858,18 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
auto const* arrayType = dynamic_cast<ArrayType const*>(var->type());
|
||||
arrayType && arrayType->isDynamicallySized() && arrayType->dataStoredIn(DataLocation::CallData)
|
||||
)
|
||||
m_errorReporter.typeError(1397_error, _identifier.location, "Call data elements cannot be accessed directly. Use \".offset\" and \".length\" to access the calldata offset and length of this array and then use \"calldatacopy\".");
|
||||
m_errorReporter.typeError(1397_error, _identifier.debugData->irLocation, "Call data elements cannot be accessed directly. Use \".offset\" and \".length\" to access the calldata offset and length of this array and then use \"calldatacopy\".");
|
||||
else
|
||||
{
|
||||
solAssert(!var->type()->dataStoredIn(DataLocation::CallData), "");
|
||||
m_errorReporter.typeError(9857_error, _identifier.location, "Only types that use one stack slot are supported.");
|
||||
m_errorReporter.typeError(9857_error, _identifier.debugData->irLocation, "Only types that use one stack slot are supported.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!identifierInfo.suffix.empty())
|
||||
{
|
||||
m_errorReporter.typeError(7944_error, _identifier.location, "The suffixes \".offset\", \".slot\" and \".length\" can only be used with variables.");
|
||||
m_errorReporter.typeError(7944_error, _identifier.debugData->irLocation, "The suffixes \".offset\", \".slot\" and \".length\" can only be used with variables.");
|
||||
return false;
|
||||
}
|
||||
else if (_context == yul::IdentifierContext::LValue)
|
||||
@ -877,7 +877,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
if (dynamic_cast<MagicVariableDeclaration const*>(declaration))
|
||||
return false;
|
||||
|
||||
m_errorReporter.typeError(1990_error, _identifier.location, "Only local variables can be assigned to in inline assembly.");
|
||||
m_errorReporter.typeError(1990_error, _identifier.debugData->irLocation, "Only local variables can be assigned to in inline assembly.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -886,7 +886,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
solAssert(!!declaration->type(), "Type of declaration required but not yet determined.");
|
||||
if (dynamic_cast<FunctionDefinition const*>(declaration))
|
||||
{
|
||||
m_errorReporter.declarationError(2025_error, _identifier.location, "Access to functions is not allowed in inline assembly.");
|
||||
m_errorReporter.declarationError(2025_error, _identifier.debugData->irLocation, "Access to functions is not allowed in inline assembly.");
|
||||
return false;
|
||||
}
|
||||
else if (dynamic_cast<VariableDeclaration const*>(declaration))
|
||||
@ -896,7 +896,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
{
|
||||
if (!contract->isLibrary())
|
||||
{
|
||||
m_errorReporter.typeError(4977_error, _identifier.location, "Expected a library.");
|
||||
m_errorReporter.typeError(4977_error, _identifier.debugData->irLocation, "Expected a library.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ public:
|
||||
if (yul::EVMDialect const* dialect = dynamic_cast<decltype(dialect)>(&m_dialect))
|
||||
if (yul::BuiltinFunctionForEVM const* fun = dialect->builtin(_funCall.functionName.name))
|
||||
if (fun->instruction)
|
||||
checkInstruction(_funCall.location, *fun->instruction);
|
||||
checkInstruction(_funCall.debugData->irLocation, *fun->instruction);
|
||||
|
||||
for (auto const& arg: _funCall.arguments)
|
||||
std::visit(*this, arg);
|
||||
|
@ -175,7 +175,7 @@ void ASTJsonConverter::appendExpressionAttributes(
|
||||
Json::Value ASTJsonConverter::inlineAssemblyIdentifierToJson(pair<yul::Identifier const* ,InlineAssemblyAnnotation::ExternalIdentifierInfo> _info) const
|
||||
{
|
||||
Json::Value tuple(Json::objectValue);
|
||||
tuple["src"] = sourceLocationToString(_info.first->location);
|
||||
tuple["src"] = sourceLocationToString(_info.first->debugData->irLocation);
|
||||
tuple["declaration"] = idOrNull(_info.second.declaration);
|
||||
tuple["isSlot"] = Json::Value(_info.second.suffix == "slot");
|
||||
tuple["isOffset"] = Json::Value(_info.second.suffix == "offset");
|
||||
|
@ -426,7 +426,7 @@ void CompilerContext::appendInlineAssembly(
|
||||
if (stackDiff < 1 || stackDiff > 16)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
StackTooDeepError() <<
|
||||
errinfo_sourceLocation(_identifier.location) <<
|
||||
errinfo_sourceLocation(_identifier.debugData->irLocation) <<
|
||||
util::errinfo_comment("Stack too deep (" + to_string(stackDiff) + "), try removing local variables.")
|
||||
);
|
||||
if (_context == yul::IdentifierContext::RValue)
|
||||
|
@ -192,9 +192,9 @@ private:
|
||||
solAssert(false, "");
|
||||
|
||||
if (isdigit(value.front()))
|
||||
return yul::Literal{_identifier.location, yul::LiteralKind::Number, yul::YulString{value}, {}};
|
||||
return yul::Literal{_identifier.debugData, yul::LiteralKind::Number, yul::YulString{value}, {}};
|
||||
else
|
||||
return yul::Identifier{_identifier.location, yul::YulString{value}};
|
||||
return yul::Identifier{_identifier.debugData, yul::YulString{value}};
|
||||
}
|
||||
|
||||
|
||||
@ -3167,6 +3167,23 @@ bool IRGeneratorForStatements::visit(TryCatchClause const& _clause)
|
||||
void IRGeneratorForStatements::setLocation(ASTNode const& _node)
|
||||
{
|
||||
m_currentLocation = _node.location();
|
||||
appendCurrentLocation();
|
||||
}
|
||||
|
||||
void IRGeneratorForStatements::appendCurrentLocation()
|
||||
{
|
||||
if (m_currentLocation.isValid() && m_code.tellp() != m_lastSourceLocationPosition)
|
||||
{
|
||||
m_code <<
|
||||
"/// @origin " <<
|
||||
m_currentLocation.source->name() <<
|
||||
":" <<
|
||||
m_currentLocation.start <<
|
||||
"," <<
|
||||
m_currentLocation.end <<
|
||||
"\n";
|
||||
m_lastSourceLocationPosition = m_code.tellp();
|
||||
}
|
||||
}
|
||||
|
||||
string IRGeneratorForStatements::linkerSymbol(ContractDefinition const& _library) const
|
||||
|
@ -195,6 +195,8 @@ private:
|
||||
|
||||
void setLocation(ASTNode const& _node);
|
||||
|
||||
void appendCurrentLocation();
|
||||
|
||||
std::string linkerSymbol(ContractDefinition const& _library) const;
|
||||
|
||||
std::ostringstream m_code;
|
||||
@ -203,6 +205,7 @@ private:
|
||||
YulUtilFunctions& m_utils;
|
||||
std::optional<IRLValue> m_currentLValue;
|
||||
langutil::SourceLocation m_currentLocation;
|
||||
std::streampos m_lastSourceLocationPosition;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1302,7 +1302,7 @@ ASTPointer<InlineAssembly> Parser::parseInlineAssembly(ASTPointer<ASTString> con
|
||||
if (block == nullptr)
|
||||
BOOST_THROW_EXCEPTION(FatalError());
|
||||
|
||||
location.end = block->location.end;
|
||||
location.end = block->debugData->irLocation.end;
|
||||
return make_shared<InlineAssembly>(nextID(), location, _docString, dialect, block);
|
||||
}
|
||||
|
||||
|
46
libyul/AST.h
46
libyul/AST.h
@ -35,54 +35,62 @@ namespace solidity::yul
|
||||
|
||||
using Type = YulString;
|
||||
|
||||
struct TypedName { langutil::SourceLocation location; YulString name; Type type; };
|
||||
struct DebugData
|
||||
{
|
||||
explicit DebugData(langutil::SourceLocation _yulLocation = {}, langutil::SourceLocation _sollLocation = {}): irLocation(std::move(_yulLocation)), originLocation(std::move(_sollLocation))
|
||||
{}
|
||||
langutil::SourceLocation irLocation;
|
||||
langutil::SourceLocation originLocation;
|
||||
};
|
||||
|
||||
struct TypedName { std::shared_ptr<DebugData> debugData; YulString name; Type type; };
|
||||
using TypedNameList = std::vector<TypedName>;
|
||||
|
||||
/// Literal number or string (up to 32 bytes)
|
||||
enum class LiteralKind { Number, Boolean, String };
|
||||
struct Literal { langutil::SourceLocation location; LiteralKind kind; YulString value; Type type; };
|
||||
struct Literal { std::shared_ptr<DebugData> debugData; LiteralKind kind; YulString value; Type type; };
|
||||
/// External / internal identifier or label reference
|
||||
struct Identifier { langutil::SourceLocation location; YulString name; };
|
||||
struct Identifier { std::shared_ptr<DebugData> debugData; YulString name; };
|
||||
/// Assignment ("x := mload(20:u256)", expects push-1-expression on the right hand
|
||||
/// side and requires x to occupy exactly one stack slot.
|
||||
///
|
||||
/// Multiple assignment ("x, y := f()"), where the left hand side variables each occupy
|
||||
/// a single stack slot and expects a single expression on the right hand returning
|
||||
/// the same amount of items as the number of variables.
|
||||
struct Assignment { langutil::SourceLocation location; std::vector<Identifier> variableNames; std::unique_ptr<Expression> value; };
|
||||
struct FunctionCall { langutil::SourceLocation location; Identifier functionName; std::vector<Expression> arguments; };
|
||||
struct Assignment { std::shared_ptr<DebugData> debugData; std::vector<Identifier> variableNames; std::unique_ptr<Expression> value; };
|
||||
struct FunctionCall { std::shared_ptr<DebugData> debugData; Identifier functionName; std::vector<Expression> arguments; };
|
||||
/// Statement that contains only a single expression
|
||||
struct ExpressionStatement { langutil::SourceLocation location; Expression expression; };
|
||||
struct ExpressionStatement { std::shared_ptr<DebugData> debugData; Expression expression; };
|
||||
/// Block-scope variable declaration ("let x:u256 := mload(20:u256)"), non-hoisted
|
||||
struct VariableDeclaration { langutil::SourceLocation location; TypedNameList variables; std::unique_ptr<Expression> value; };
|
||||
struct VariableDeclaration { std::shared_ptr<DebugData> debugData; TypedNameList variables; std::unique_ptr<Expression> value; };
|
||||
/// Block that creates a scope (frees declared stack variables)
|
||||
struct Block { langutil::SourceLocation location; std::vector<Statement> statements; };
|
||||
struct Block { std::shared_ptr<DebugData> debugData; std::vector<Statement> statements; };
|
||||
/// Function definition ("function f(a, b) -> (d, e) { ... }")
|
||||
struct FunctionDefinition { langutil::SourceLocation location; YulString name; TypedNameList parameters; TypedNameList returnVariables; Block body; };
|
||||
struct FunctionDefinition { std::shared_ptr<DebugData> debugData; YulString name; TypedNameList parameters; TypedNameList returnVariables; Block body; };
|
||||
/// Conditional execution without "else" part.
|
||||
struct If { langutil::SourceLocation location; std::unique_ptr<Expression> condition; Block body; };
|
||||
struct If { std::shared_ptr<DebugData> debugData; std::unique_ptr<Expression> condition; Block body; };
|
||||
/// Switch case or default case
|
||||
struct Case { langutil::SourceLocation location; std::unique_ptr<Literal> value; Block body; };
|
||||
struct Case { std::shared_ptr<DebugData> debugData; std::unique_ptr<Literal> value; Block body; };
|
||||
/// Switch statement
|
||||
struct Switch { langutil::SourceLocation location; std::unique_ptr<Expression> expression; std::vector<Case> cases; };
|
||||
struct ForLoop { langutil::SourceLocation location; Block pre; std::unique_ptr<Expression> condition; Block post; Block body; };
|
||||
struct Switch { std::shared_ptr<DebugData> debugData; std::unique_ptr<Expression> expression; std::vector<Case> cases; };
|
||||
struct ForLoop { std::shared_ptr<DebugData> debugData; Block pre; std::unique_ptr<Expression> condition; Block post; Block body; };
|
||||
/// Break statement (valid within for loop)
|
||||
struct Break { langutil::SourceLocation location; };
|
||||
struct Break { std::shared_ptr<DebugData> debugData; };
|
||||
/// Continue statement (valid within for loop)
|
||||
struct Continue { langutil::SourceLocation location; };
|
||||
struct Continue { std::shared_ptr<DebugData> debugData; };
|
||||
/// Leave statement (valid within function)
|
||||
struct Leave { langutil::SourceLocation location; };
|
||||
struct Leave { std::shared_ptr<DebugData> debugData; };
|
||||
|
||||
struct LocationExtractor
|
||||
{
|
||||
template <class T> langutil::SourceLocation operator()(T const& _node) const
|
||||
template <class T> std::shared_ptr<DebugData> operator()(T const& _node) const
|
||||
{
|
||||
return _node.location;
|
||||
return _node.debugData;
|
||||
}
|
||||
};
|
||||
|
||||
/// Extracts the source location from an inline assembly node.
|
||||
template <class T> inline langutil::SourceLocation locationOf(T const& _node)
|
||||
template <class T> inline std::shared_ptr<DebugData> locationOf(T const& _node)
|
||||
{
|
||||
return std::visit(LocationExtractor(), _node);
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
namespace solidity::yul
|
||||
{
|
||||
|
||||
struct DebugData;
|
||||
enum class LiteralKind;
|
||||
struct Literal;
|
||||
struct Label;
|
||||
|
@ -97,22 +97,22 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect,
|
||||
|
||||
vector<YulString> AsmAnalyzer::operator()(Literal const& _literal)
|
||||
{
|
||||
expectValidType(_literal.type, _literal.location);
|
||||
expectValidType(_literal.type, _literal.debugData->irLocation);
|
||||
if (_literal.kind == LiteralKind::String && _literal.value.str().size() > 32)
|
||||
m_errorReporter.typeError(
|
||||
3069_error,
|
||||
_literal.location,
|
||||
_literal.debugData->irLocation,
|
||||
"String literal too long (" + to_string(_literal.value.str().size()) + " > 32)"
|
||||
);
|
||||
else if (_literal.kind == LiteralKind::Number && bigint(_literal.value.str()) > u256(-1))
|
||||
m_errorReporter.typeError(6708_error, _literal.location, "Number literal too large (> 256 bits)");
|
||||
m_errorReporter.typeError(6708_error, _literal.debugData->irLocation, "Number literal too large (> 256 bits)");
|
||||
else if (_literal.kind == LiteralKind::Boolean)
|
||||
yulAssert(_literal.value == "true"_yulstring || _literal.value == "false"_yulstring, "");
|
||||
|
||||
if (!m_dialect.validTypeForLiteral(_literal.kind, _literal.value, _literal.type))
|
||||
m_errorReporter.typeError(
|
||||
5170_error,
|
||||
_literal.location,
|
||||
_literal.debugData->irLocation,
|
||||
"Invalid type \"" + _literal.type.str() + "\" for literal \"" + _literal.value.str() + "\"."
|
||||
);
|
||||
|
||||
@ -132,7 +132,7 @@ vector<YulString> AsmAnalyzer::operator()(Identifier const& _identifier)
|
||||
if (!m_activeVariables.count(&_var))
|
||||
m_errorReporter.declarationError(
|
||||
4990_error,
|
||||
_identifier.location,
|
||||
_identifier.debugData->irLocation,
|
||||
"Variable " + _identifier.name.str() + " used before it was declared."
|
||||
);
|
||||
type = _var.type;
|
||||
@ -141,7 +141,7 @@ vector<YulString> AsmAnalyzer::operator()(Identifier const& _identifier)
|
||||
{
|
||||
m_errorReporter.typeError(
|
||||
6041_error,
|
||||
_identifier.location,
|
||||
_identifier.debugData->irLocation,
|
||||
"Function " + _identifier.name.str() + " used without being called."
|
||||
);
|
||||
}
|
||||
@ -159,7 +159,7 @@ vector<YulString> AsmAnalyzer::operator()(Identifier const& _identifier)
|
||||
// Only add an error message if the callback did not do it.
|
||||
m_errorReporter.declarationError(
|
||||
8198_error,
|
||||
_identifier.location,
|
||||
_identifier.debugData->irLocation,
|
||||
"Identifier \"" + _identifier.name.str() + "\" not found."
|
||||
);
|
||||
|
||||
@ -175,7 +175,7 @@ void AsmAnalyzer::operator()(ExpressionStatement const& _statement)
|
||||
if (watcher.ok() && !types.empty())
|
||||
m_errorReporter.typeError(
|
||||
3083_error,
|
||||
_statement.location,
|
||||
_statement.debugData->irLocation,
|
||||
"Top-level expressions are not supposed to return values (this expression returns " +
|
||||
to_string(types.size()) +
|
||||
" value" +
|
||||
@ -195,7 +195,7 @@ void AsmAnalyzer::operator()(Assignment const& _assignment)
|
||||
if (!variables.insert(_variableName.name).second)
|
||||
m_errorReporter.declarationError(
|
||||
9005_error,
|
||||
_assignment.location,
|
||||
_assignment.debugData->irLocation,
|
||||
"Variable " +
|
||||
_variableName.name.str() +
|
||||
" occurs multiple times on the left-hand side of the assignment."
|
||||
@ -206,7 +206,7 @@ void AsmAnalyzer::operator()(Assignment const& _assignment)
|
||||
if (types.size() != numVariables)
|
||||
m_errorReporter.declarationError(
|
||||
8678_error,
|
||||
_assignment.location,
|
||||
_assignment.debugData->irLocation,
|
||||
"Variable count for assignment to \"" +
|
||||
joinHumanReadable(applyMap(_assignment.variableNames, [](auto const& _identifier){ return _identifier.name.str(); })) +
|
||||
"\" does not match number of values (" +
|
||||
@ -228,14 +228,14 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl)
|
||||
for (auto const& variable: _varDecl.variables)
|
||||
// Call the resolver for variable declarations to allow it to raise errors on shadowing.
|
||||
m_resolver(
|
||||
yul::Identifier{variable.location, variable.name},
|
||||
yul::Identifier{variable.debugData, variable.name},
|
||||
yul::IdentifierContext::VariableDeclaration,
|
||||
m_currentScope->insideFunction()
|
||||
);
|
||||
for (auto const& variable: _varDecl.variables)
|
||||
{
|
||||
expectValidIdentifier(variable.name, variable.location);
|
||||
expectValidType(variable.type, variable.location);
|
||||
expectValidIdentifier(variable.name, variable.debugData->irLocation);
|
||||
expectValidType(variable.type, variable.debugData->irLocation);
|
||||
}
|
||||
|
||||
if (_varDecl.value)
|
||||
@ -244,7 +244,7 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl)
|
||||
if (types.size() != numVariables)
|
||||
m_errorReporter.declarationError(
|
||||
3812_error,
|
||||
_varDecl.location,
|
||||
_varDecl.debugData->irLocation,
|
||||
"Variable count mismatch for declaration of \"" +
|
||||
joinHumanReadable(applyMap(_varDecl.variables, [](auto const& _identifier){ return _identifier.name.str(); })) +
|
||||
+ "\": " +
|
||||
@ -263,7 +263,7 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl)
|
||||
if (variable.type != givenType)
|
||||
m_errorReporter.typeError(
|
||||
3947_error,
|
||||
variable.location,
|
||||
variable.debugData->irLocation,
|
||||
"Assigning value of type \"" + givenType.str() + "\" to variable of type \"" + variable.type.str() + "\"."
|
||||
);
|
||||
}
|
||||
@ -278,14 +278,14 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl)
|
||||
void AsmAnalyzer::operator()(FunctionDefinition const& _funDef)
|
||||
{
|
||||
yulAssert(!_funDef.name.empty(), "");
|
||||
expectValidIdentifier(_funDef.name, _funDef.location);
|
||||
expectValidIdentifier(_funDef.name, _funDef.debugData->irLocation);
|
||||
Block const* virtualBlock = m_info.virtualBlocks.at(&_funDef).get();
|
||||
yulAssert(virtualBlock, "");
|
||||
Scope& varScope = scope(virtualBlock);
|
||||
for (auto const& var: _funDef.parameters + _funDef.returnVariables)
|
||||
{
|
||||
expectValidIdentifier(var.name, var.location);
|
||||
expectValidType(var.type, var.location);
|
||||
expectValidIdentifier(var.name, var.debugData->irLocation);
|
||||
expectValidType(var.type, var.debugData->irLocation);
|
||||
m_activeVariables.insert(&std::get<Scope::Variable>(varScope.identifiers.at(var.name)));
|
||||
}
|
||||
|
||||
@ -314,7 +314,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
|
||||
{
|
||||
m_errorReporter.typeError(
|
||||
4202_error,
|
||||
_funCall.functionName.location,
|
||||
_funCall.functionName.debugData->irLocation,
|
||||
"Attempt to call variable instead of function."
|
||||
);
|
||||
},
|
||||
@ -328,7 +328,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
|
||||
if (!validateInstructions(_funCall))
|
||||
m_errorReporter.declarationError(
|
||||
4619_error,
|
||||
_funCall.functionName.location,
|
||||
_funCall.functionName.debugData->irLocation,
|
||||
"Function \"" + _funCall.functionName.name.str() + "\" not found."
|
||||
);
|
||||
yulAssert(!watcher.ok(), "Expected a reported error.");
|
||||
@ -337,7 +337,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
|
||||
if (parameterTypes && _funCall.arguments.size() != parameterTypes->size())
|
||||
m_errorReporter.typeError(
|
||||
7000_error,
|
||||
_funCall.functionName.location,
|
||||
_funCall.functionName.debugData->irLocation,
|
||||
"Function \"" + _funCall.functionName.name.str() + "\" expects " +
|
||||
to_string(parameterTypes->size()) +
|
||||
" arguments but got " +
|
||||
@ -357,13 +357,13 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
|
||||
if (!holds_alternative<Literal>(arg))
|
||||
m_errorReporter.typeError(
|
||||
9114_error,
|
||||
_funCall.functionName.location,
|
||||
_funCall.functionName.debugData->irLocation,
|
||||
"Function expects direct literals as arguments."
|
||||
);
|
||||
else if (*literalArgumentKind != get<Literal>(arg).kind)
|
||||
m_errorReporter.typeError(
|
||||
5859_error,
|
||||
get<Literal>(arg).location,
|
||||
get<Literal>(arg).debugData->irLocation,
|
||||
"Function expects " + to_string(*literalArgumentKind) + " literal."
|
||||
);
|
||||
else if (*literalArgumentKind == LiteralKind::String)
|
||||
@ -375,7 +375,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
|
||||
if (!m_dataNames.count(get<Literal>(arg).value))
|
||||
m_errorReporter.typeError(
|
||||
3517_error,
|
||||
get<Literal>(arg).location,
|
||||
get<Literal>(arg).debugData->irLocation,
|
||||
"Unknown data object \"" + std::get<Literal>(arg).value.str() + "\"."
|
||||
);
|
||||
argTypes.emplace_back(expectUnlimitedStringLiteral(get<Literal>(arg)));
|
||||
@ -388,7 +388,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
|
||||
|
||||
if (parameterTypes && parameterTypes->size() == argTypes.size())
|
||||
for (size_t i = 0; i < parameterTypes->size(); ++i)
|
||||
expectType((*parameterTypes)[i], argTypes[i], locationOf(_funCall.arguments[i]));
|
||||
expectType((*parameterTypes)[i], argTypes[i], locationOf(_funCall.arguments[i])->irLocation);
|
||||
|
||||
if (watcher.ok())
|
||||
{
|
||||
@ -416,7 +416,7 @@ void AsmAnalyzer::operator()(Switch const& _switch)
|
||||
if (_switch.cases.size() == 1 && !_switch.cases[0].value)
|
||||
m_errorReporter.warning(
|
||||
9592_error,
|
||||
_switch.location,
|
||||
_switch.debugData->irLocation,
|
||||
"\"switch\" statement with only a default case."
|
||||
);
|
||||
|
||||
@ -429,7 +429,7 @@ void AsmAnalyzer::operator()(Switch const& _switch)
|
||||
{
|
||||
auto watcher = m_errorReporter.errorWatcher();
|
||||
|
||||
expectType(valueType, _case.value->type, _case.value->location);
|
||||
expectType(valueType, _case.value->type, _case.value->debugData->irLocation);
|
||||
|
||||
// We cannot use "expectExpression" here because *_case.value is not an
|
||||
// Expression and would be converted to an Expression otherwise.
|
||||
@ -439,7 +439,7 @@ void AsmAnalyzer::operator()(Switch const& _switch)
|
||||
if (watcher.ok() && !cases.insert(valueOfLiteral(*_case.value)).second)
|
||||
m_errorReporter.declarationError(
|
||||
6792_error,
|
||||
_case.location,
|
||||
_case.debugData->irLocation,
|
||||
"Duplicate case \"" +
|
||||
valueOfLiteral(*_case.value).str() +
|
||||
"\" defined."
|
||||
@ -491,7 +491,7 @@ YulString AsmAnalyzer::expectExpression(Expression const& _expr)
|
||||
if (types.size() != 1)
|
||||
m_errorReporter.typeError(
|
||||
3950_error,
|
||||
locationOf(_expr),
|
||||
locationOf(_expr)->irLocation,
|
||||
"Expected expression to evaluate to one value, but got " +
|
||||
to_string(types.size()) +
|
||||
" values instead."
|
||||
@ -513,7 +513,7 @@ void AsmAnalyzer::expectBoolExpression(Expression const& _expr)
|
||||
if (type != m_dialect.boolType)
|
||||
m_errorReporter.typeError(
|
||||
1733_error,
|
||||
locationOf(_expr),
|
||||
locationOf(_expr)->irLocation,
|
||||
"Expected a value of boolean type \"" +
|
||||
m_dialect.boolType.str() +
|
||||
"\" but got \"" +
|
||||
@ -531,11 +531,11 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulString _valueT
|
||||
if (Scope::Identifier const* var = m_currentScope->lookup(_variable.name))
|
||||
{
|
||||
if (!holds_alternative<Scope::Variable>(*var))
|
||||
m_errorReporter.typeError(2657_error, _variable.location, "Assignment requires variable.");
|
||||
m_errorReporter.typeError(2657_error, _variable.debugData->irLocation, "Assignment requires variable.");
|
||||
else if (!m_activeVariables.count(&std::get<Scope::Variable>(*var)))
|
||||
m_errorReporter.declarationError(
|
||||
1133_error,
|
||||
_variable.location,
|
||||
_variable.debugData->irLocation,
|
||||
"Variable " + _variable.name.str() + " used before it was declared."
|
||||
);
|
||||
else
|
||||
@ -554,11 +554,11 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulString _valueT
|
||||
|
||||
if (!found && watcher.ok())
|
||||
// Only add message if the callback did not.
|
||||
m_errorReporter.declarationError(4634_error, _variable.location, "Variable not found or variable not lvalue.");
|
||||
m_errorReporter.declarationError(4634_error, _variable.debugData->irLocation, "Variable not found or variable not lvalue.");
|
||||
if (variableType && *variableType != _valueType)
|
||||
m_errorReporter.typeError(
|
||||
9547_error,
|
||||
_variable.location,
|
||||
_variable.debugData->irLocation,
|
||||
"Assigning a value of type \"" +
|
||||
_valueType.str() +
|
||||
"\" to a variable of type \"" +
|
||||
@ -702,5 +702,5 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio
|
||||
|
||||
bool AsmAnalyzer::validateInstructions(FunctionCall const& _functionCall)
|
||||
{
|
||||
return validateInstructions(_functionCall.functionName.name.str(), _functionCall.functionName.location);
|
||||
return validateInstructions(_functionCall.functionName.name.str(), _functionCall.functionName.debugData->irLocation);
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ namespace solidity::yul
|
||||
|
||||
Json::Value AsmJsonConverter::operator()(Block const& _node) const
|
||||
{
|
||||
Json::Value ret = createAstNode(_node.location, "YulBlock");
|
||||
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulBlock");
|
||||
ret["statements"] = vectorOfVariantsToJson(_node.statements);
|
||||
return ret;
|
||||
}
|
||||
@ -40,7 +40,7 @@ Json::Value AsmJsonConverter::operator()(Block const& _node) const
|
||||
Json::Value AsmJsonConverter::operator()(TypedName const& _node) const
|
||||
{
|
||||
yulAssert(!_node.name.empty(), "Invalid variable name.");
|
||||
Json::Value ret = createAstNode(_node.location, "YulTypedName");
|
||||
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulTypedName");
|
||||
ret["name"] = _node.name.str();
|
||||
ret["type"] = _node.type.str();
|
||||
return ret;
|
||||
@ -48,7 +48,7 @@ Json::Value AsmJsonConverter::operator()(TypedName const& _node) const
|
||||
|
||||
Json::Value AsmJsonConverter::operator()(Literal const& _node) const
|
||||
{
|
||||
Json::Value ret = createAstNode(_node.location, "YulLiteral");
|
||||
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulLiteral");
|
||||
switch (_node.kind)
|
||||
{
|
||||
case LiteralKind::Number:
|
||||
@ -73,7 +73,7 @@ Json::Value AsmJsonConverter::operator()(Literal const& _node) const
|
||||
Json::Value AsmJsonConverter::operator()(Identifier const& _node) const
|
||||
{
|
||||
yulAssert(!_node.name.empty(), "Invalid identifier");
|
||||
Json::Value ret = createAstNode(_node.location, "YulIdentifier");
|
||||
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulIdentifier");
|
||||
ret["name"] = _node.name.str();
|
||||
return ret;
|
||||
}
|
||||
@ -81,7 +81,7 @@ Json::Value AsmJsonConverter::operator()(Identifier const& _node) const
|
||||
Json::Value AsmJsonConverter::operator()(Assignment const& _node) const
|
||||
{
|
||||
yulAssert(_node.variableNames.size() >= 1, "Invalid assignment syntax");
|
||||
Json::Value ret = createAstNode(_node.location, "YulAssignment");
|
||||
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulAssignment");
|
||||
for (auto const& var: _node.variableNames)
|
||||
ret["variableNames"].append((*this)(var));
|
||||
ret["value"] = _node.value ? std::visit(*this, *_node.value) : Json::nullValue;
|
||||
@ -90,7 +90,7 @@ Json::Value AsmJsonConverter::operator()(Assignment const& _node) const
|
||||
|
||||
Json::Value AsmJsonConverter::operator()(FunctionCall const& _node) const
|
||||
{
|
||||
Json::Value ret = createAstNode(_node.location, "YulFunctionCall");
|
||||
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulFunctionCall");
|
||||
ret["functionName"] = (*this)(_node.functionName);
|
||||
ret["arguments"] = vectorOfVariantsToJson(_node.arguments);
|
||||
return ret;
|
||||
@ -98,14 +98,14 @@ Json::Value AsmJsonConverter::operator()(FunctionCall const& _node) const
|
||||
|
||||
Json::Value AsmJsonConverter::operator()(ExpressionStatement const& _node) const
|
||||
{
|
||||
Json::Value ret = createAstNode(_node.location, "YulExpressionStatement");
|
||||
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulExpressionStatement");
|
||||
ret["expression"] = std::visit(*this, _node.expression);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Json::Value AsmJsonConverter::operator()(VariableDeclaration const& _node) const
|
||||
{
|
||||
Json::Value ret = createAstNode(_node.location, "YulVariableDeclaration");
|
||||
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulVariableDeclaration");
|
||||
for (auto const& var: _node.variables)
|
||||
ret["variables"].append((*this)(var));
|
||||
|
||||
@ -117,7 +117,7 @@ Json::Value AsmJsonConverter::operator()(VariableDeclaration const& _node) const
|
||||
Json::Value AsmJsonConverter::operator()(FunctionDefinition const& _node) const
|
||||
{
|
||||
yulAssert(!_node.name.empty(), "Invalid function name.");
|
||||
Json::Value ret = createAstNode(_node.location, "YulFunctionDefinition");
|
||||
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulFunctionDefinition");
|
||||
ret["name"] = _node.name.str();
|
||||
for (auto const& var: _node.parameters)
|
||||
ret["parameters"].append((*this)(var));
|
||||
@ -130,7 +130,7 @@ Json::Value AsmJsonConverter::operator()(FunctionDefinition const& _node) const
|
||||
Json::Value AsmJsonConverter::operator()(If const& _node) const
|
||||
{
|
||||
yulAssert(_node.condition, "Invalid if condition.");
|
||||
Json::Value ret = createAstNode(_node.location, "YulIf");
|
||||
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulIf");
|
||||
ret["condition"] = std::visit(*this, *_node.condition);
|
||||
ret["body"] = (*this)(_node.body);
|
||||
return ret;
|
||||
@ -139,7 +139,7 @@ Json::Value AsmJsonConverter::operator()(If const& _node) const
|
||||
Json::Value AsmJsonConverter::operator()(Switch const& _node) const
|
||||
{
|
||||
yulAssert(_node.expression, "Invalid expression pointer.");
|
||||
Json::Value ret = createAstNode(_node.location, "YulSwitch");
|
||||
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulSwitch");
|
||||
ret["expression"] = std::visit(*this, *_node.expression);
|
||||
for (auto const& var: _node.cases)
|
||||
ret["cases"].append((*this)(var));
|
||||
@ -148,7 +148,7 @@ Json::Value AsmJsonConverter::operator()(Switch const& _node) const
|
||||
|
||||
Json::Value AsmJsonConverter::operator()(Case const& _node) const
|
||||
{
|
||||
Json::Value ret = createAstNode(_node.location, "YulCase");
|
||||
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulCase");
|
||||
ret["value"] = _node.value ? (*this)(*_node.value) : "default";
|
||||
ret["body"] = (*this)(_node.body);
|
||||
return ret;
|
||||
@ -157,7 +157,7 @@ Json::Value AsmJsonConverter::operator()(Case const& _node) const
|
||||
Json::Value AsmJsonConverter::operator()(ForLoop const& _node) const
|
||||
{
|
||||
yulAssert(_node.condition, "Invalid for loop condition.");
|
||||
Json::Value ret = createAstNode(_node.location, "YulForLoop");
|
||||
Json::Value ret = createAstNode(_node.debugData->irLocation, "YulForLoop");
|
||||
ret["pre"] = (*this)(_node.pre);
|
||||
ret["condition"] = std::visit(*this, *_node.condition);
|
||||
ret["post"] = (*this)(_node.post);
|
||||
@ -167,17 +167,17 @@ Json::Value AsmJsonConverter::operator()(ForLoop const& _node) const
|
||||
|
||||
Json::Value AsmJsonConverter::operator()(Break const& _node) const
|
||||
{
|
||||
return createAstNode(_node.location, "YulBreak");
|
||||
return createAstNode(_node.debugData->irLocation, "YulBreak");
|
||||
}
|
||||
|
||||
Json::Value AsmJsonConverter::operator()(Continue const& _node) const
|
||||
{
|
||||
return createAstNode(_node.location, "YulContinue");
|
||||
return createAstNode(_node.debugData->irLocation, "YulContinue");
|
||||
}
|
||||
|
||||
Json::Value AsmJsonConverter::operator()(Leave const& _node) const
|
||||
{
|
||||
return createAstNode(_node.location, "YulLeave");
|
||||
return createAstNode(_node.debugData->irLocation, "YulLeave");
|
||||
}
|
||||
|
||||
Json::Value AsmJsonConverter::createAstNode(langutil::SourceLocation const& _location, string _nodeType) const
|
||||
|
@ -52,9 +52,11 @@ template <class T>
|
||||
T AsmJsonImporter::createAsmNode(Json::Value const& _node)
|
||||
{
|
||||
T r;
|
||||
r.location = createSourceLocation(_node);
|
||||
r.debugData = make_shared<DebugData>(createSourceLocation(_node));
|
||||
yulAssert(
|
||||
r.location.source && 0 <= r.location.start && r.location.start <= r.location.end,
|
||||
r.debugData->irLocation.source &&
|
||||
0 <= r.debugData->irLocation.start &&
|
||||
r.debugData->irLocation.start <= r.debugData->irLocation.end,
|
||||
"Invalid source location in Asm AST"
|
||||
);
|
||||
return r;
|
||||
|
@ -70,7 +70,7 @@ Block Parser::parseBlock()
|
||||
expectToken(Token::LBrace);
|
||||
while (currentToken() != Token::RBrace)
|
||||
block.statements.emplace_back(parseStatement());
|
||||
block.location.end = currentLocation().end;
|
||||
block.debugData->irLocation.end = currentLocation().end;
|
||||
advance();
|
||||
return block;
|
||||
}
|
||||
@ -109,7 +109,7 @@ Statement Parser::parseStatement()
|
||||
fatalParserError(4904_error, "Case not allowed after default case.");
|
||||
if (_switch.cases.empty())
|
||||
fatalParserError(2418_error, "Switch statement without any cases.");
|
||||
_switch.location.end = _switch.cases.back().body.location.end;
|
||||
_switch.debugData->irLocation.end = _switch.cases.back().body.debugData->irLocation.end;
|
||||
return Statement{move(_switch)};
|
||||
}
|
||||
case Token::For:
|
||||
@ -156,7 +156,7 @@ Statement Parser::parseStatement()
|
||||
case Token::AssemblyAssign:
|
||||
{
|
||||
Assignment assignment;
|
||||
assignment.location = locationOf(elementary);
|
||||
assignment.debugData = locationOf(elementary);
|
||||
|
||||
while (true)
|
||||
{
|
||||
@ -191,7 +191,7 @@ Statement Parser::parseStatement()
|
||||
expectToken(Token::AssemblyAssign);
|
||||
|
||||
assignment.value = make_unique<Expression>(parseExpression());
|
||||
assignment.location.end = locationOf(*assignment.value).end;
|
||||
assignment.debugData->irLocation.end = locationOf(*assignment.value)->irLocation.end;
|
||||
|
||||
return Statement{move(assignment)};
|
||||
}
|
||||
@ -221,7 +221,7 @@ Case Parser::parseCase()
|
||||
else
|
||||
yulAssert(false, "Case or default case expected.");
|
||||
_case.body = parseBlock();
|
||||
_case.location.end = _case.body.location.end;
|
||||
_case.debugData->irLocation.end = _case.body.debugData->irLocation.end;
|
||||
return _case;
|
||||
}
|
||||
|
||||
@ -241,7 +241,7 @@ ForLoop Parser::parseForLoop()
|
||||
forLoop.post = parseBlock();
|
||||
m_currentForLoopComponent = ForLoopComponent::ForLoopBody;
|
||||
forLoop.body = parseBlock();
|
||||
forLoop.location.end = forLoop.body.location.end;
|
||||
forLoop.debugData->irLocation.end = forLoop.body.debugData->irLocation.end;
|
||||
|
||||
m_currentForLoopComponent = outerForLoopComponent;
|
||||
|
||||
@ -261,7 +261,7 @@ Expression Parser::parseExpression()
|
||||
if (m_dialect.builtin(_identifier.name))
|
||||
fatalParserError(
|
||||
7104_error,
|
||||
_identifier.location,
|
||||
_identifier.debugData->irLocation,
|
||||
"Builtin function \"" + _identifier.name.str() + "\" must be called."
|
||||
);
|
||||
return move(_identifier);
|
||||
@ -280,7 +280,7 @@ variant<Literal, Identifier> Parser::parseLiteralOrIdentifier()
|
||||
{
|
||||
case Token::Identifier:
|
||||
{
|
||||
Identifier identifier{currentLocation(), YulString{currentLiteral()}};
|
||||
Identifier identifier{make_shared<DebugData>(currentLocation()), YulString{currentLiteral()}};
|
||||
advance();
|
||||
return identifier;
|
||||
}
|
||||
@ -311,7 +311,7 @@ variant<Literal, Identifier> Parser::parseLiteralOrIdentifier()
|
||||
}
|
||||
|
||||
Literal literal{
|
||||
currentLocation(),
|
||||
make_shared<DebugData>(currentLocation()),
|
||||
kind,
|
||||
YulString{currentLiteral()},
|
||||
kind == LiteralKind::Boolean ? m_dialect.boolType : m_dialect.defaultType
|
||||
@ -320,7 +320,7 @@ variant<Literal, Identifier> Parser::parseLiteralOrIdentifier()
|
||||
if (currentToken() == Token::Colon)
|
||||
{
|
||||
expectToken(Token::Colon);
|
||||
literal.location.end = currentLocation().end;
|
||||
literal.debugData->irLocation.end = currentLocation().end;
|
||||
literal.type = expectAsmIdentifier();
|
||||
}
|
||||
|
||||
@ -332,7 +332,7 @@ variant<Literal, Identifier> Parser::parseLiteralOrIdentifier()
|
||||
default:
|
||||
fatalParserError(1856_error, "Literal or identifier expected.");
|
||||
}
|
||||
return {};
|
||||
return Literal{make_shared<DebugData>(), {}, {}, {}};
|
||||
}
|
||||
|
||||
VariableDeclaration Parser::parseVariableDeclaration()
|
||||
@ -352,10 +352,10 @@ VariableDeclaration Parser::parseVariableDeclaration()
|
||||
{
|
||||
expectToken(Token::AssemblyAssign);
|
||||
varDecl.value = make_unique<Expression>(parseExpression());
|
||||
varDecl.location.end = locationOf(*varDecl.value).end;
|
||||
varDecl.debugData->irLocation.end = locationOf(*varDecl.value)->irLocation.end;
|
||||
}
|
||||
else
|
||||
varDecl.location.end = varDecl.variables.back().location.end;
|
||||
varDecl.debugData->irLocation.end = varDecl.variables.back().debugData->irLocation.end;
|
||||
return varDecl;
|
||||
}
|
||||
|
||||
@ -400,7 +400,7 @@ FunctionDefinition Parser::parseFunctionDefinition()
|
||||
m_insideFunction = true;
|
||||
funDef.body = parseBlock();
|
||||
m_insideFunction = preInsideFunction;
|
||||
funDef.location.end = funDef.body.location.end;
|
||||
funDef.debugData->irLocation.end = funDef.body.debugData->irLocation.end;
|
||||
|
||||
m_currentForLoopComponent = outerForLoopComponent;
|
||||
return funDef;
|
||||
@ -415,7 +415,7 @@ FunctionCall Parser::parseCall(variant<Literal, Identifier>&& _initialOp)
|
||||
|
||||
FunctionCall ret;
|
||||
ret.functionName = std::move(std::get<Identifier>(_initialOp));
|
||||
ret.location = ret.functionName.location;
|
||||
ret.debugData = ret.functionName.debugData;
|
||||
|
||||
expectToken(Token::LParen);
|
||||
if (currentToken() != Token::RParen)
|
||||
@ -427,7 +427,7 @@ FunctionCall Parser::parseCall(variant<Literal, Identifier>&& _initialOp)
|
||||
ret.arguments.emplace_back(parseExpression());
|
||||
}
|
||||
}
|
||||
ret.location.end = currentLocation().end;
|
||||
ret.debugData->irLocation.end = currentLocation().end;
|
||||
expectToken(Token::RParen);
|
||||
return ret;
|
||||
}
|
||||
@ -440,7 +440,7 @@ TypedName Parser::parseTypedName()
|
||||
if (currentToken() == Token::Colon)
|
||||
{
|
||||
expectToken(Token::Colon);
|
||||
typedName.location.end = currentLocation().end;
|
||||
typedName.debugData->irLocation.end = currentLocation().end;
|
||||
typedName.type = expectAsmIdentifier();
|
||||
}
|
||||
else
|
||||
|
@ -70,7 +70,7 @@ protected:
|
||||
template <class T> T createWithLocation() const
|
||||
{
|
||||
T r;
|
||||
r.location = currentLocation();
|
||||
r.debugData = std::make_shared<DebugData>(currentLocation());
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -29,17 +29,17 @@ using namespace solidity::langutil;
|
||||
Literal Dialect::zeroLiteralForType(solidity::yul::YulString _type) const
|
||||
{
|
||||
if (_type == boolType && _type != defaultType)
|
||||
return {SourceLocation{}, LiteralKind::Boolean, "false"_yulstring, _type};
|
||||
return {SourceLocation{}, LiteralKind::Number, "0"_yulstring, _type};
|
||||
return {make_shared<DebugData>(), LiteralKind::Boolean, "false"_yulstring, _type};
|
||||
return {make_shared<DebugData>(), LiteralKind::Number, "0"_yulstring, _type};
|
||||
}
|
||||
|
||||
|
||||
Literal Dialect::trueLiteral() const
|
||||
{
|
||||
if (boolType != defaultType)
|
||||
return {SourceLocation{}, LiteralKind::Boolean, "true"_yulstring, boolType};
|
||||
return {make_shared<DebugData>(), LiteralKind::Boolean, "true"_yulstring, boolType};
|
||||
else
|
||||
return {SourceLocation{}, LiteralKind::Number, "1"_yulstring, defaultType};
|
||||
return {make_shared<DebugData>(), LiteralKind::Number, "1"_yulstring, defaultType};
|
||||
}
|
||||
|
||||
bool Dialect::validTypeForLiteral(LiteralKind _kind, YulString, YulString _type) const
|
||||
|
@ -53,7 +53,7 @@ bool ScopeFiller::operator()(ExpressionStatement const& _expr)
|
||||
bool ScopeFiller::operator()(VariableDeclaration const& _varDecl)
|
||||
{
|
||||
for (auto const& variable: _varDecl.variables)
|
||||
if (!registerVariable(variable, _varDecl.location, *m_currentScope))
|
||||
if (!registerVariable(variable, _varDecl.debugData->irLocation, *m_currentScope))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@ -68,7 +68,7 @@ bool ScopeFiller::operator()(FunctionDefinition const& _funDef)
|
||||
|
||||
bool success = true;
|
||||
for (auto const& var: _funDef.parameters + _funDef.returnVariables)
|
||||
if (!registerVariable(var, _funDef.location, varScope))
|
||||
if (!registerVariable(var, _funDef.debugData->irLocation, varScope))
|
||||
success = false;
|
||||
|
||||
if (!(*this)(_funDef.body))
|
||||
@ -162,7 +162,7 @@ bool ScopeFiller::registerFunction(FunctionDefinition const& _funDef)
|
||||
//@TODO secondary location
|
||||
m_errorReporter.declarationError(
|
||||
6052_error,
|
||||
_funDef.location,
|
||||
_funDef.debugData->irLocation,
|
||||
"Function name " + _funDef.name.str() + " already taken in this scope."
|
||||
);
|
||||
return false;
|
||||
|
@ -42,6 +42,7 @@ enum class Instruction: uint8_t;
|
||||
namespace solidity::yul
|
||||
{
|
||||
struct Identifier;
|
||||
struct DebugData;
|
||||
|
||||
///
|
||||
/// Assembly class that abstracts both the libevmasm assembly and the new Yul assembly.
|
||||
@ -56,7 +57,7 @@ public:
|
||||
virtual ~AbstractAssembly() = default;
|
||||
|
||||
/// Set a new source location valid starting from the next instruction.
|
||||
virtual void setSourceLocation(langutil::SourceLocation const& _location) = 0;
|
||||
virtual void setSourceLocation(std::shared_ptr<DebugData const> const& _debugData) = 0;
|
||||
/// Retrieve the current height of the stack. This does not have to be zero
|
||||
/// at the beginning.
|
||||
virtual int stackHeight() const = 0;
|
||||
|
@ -49,9 +49,9 @@ EthAssemblyAdapter::EthAssemblyAdapter(evmasm::Assembly& _assembly):
|
||||
{
|
||||
}
|
||||
|
||||
void EthAssemblyAdapter::setSourceLocation(SourceLocation const& _location)
|
||||
void EthAssemblyAdapter::setSourceLocation(shared_ptr<DebugData const> const& _debugData)
|
||||
{
|
||||
m_assembly.setSourceLocation(_location);
|
||||
m_assembly.setSourceLocation(_debugData ? _debugData->irLocation : langutil::SourceLocation{});
|
||||
}
|
||||
|
||||
int EthAssemblyAdapter::stackHeight() const
|
||||
|
@ -40,7 +40,7 @@ class EthAssemblyAdapter: public AbstractAssembly
|
||||
{
|
||||
public:
|
||||
explicit EthAssemblyAdapter(evmasm::Assembly& _assembly);
|
||||
void setSourceLocation(langutil::SourceLocation const& _location) override;
|
||||
void setSourceLocation(std::shared_ptr<DebugData const> const& _debugData) override;
|
||||
int stackHeight() const override;
|
||||
void setStackHeight(int height) override;
|
||||
void appendInstruction(evmasm::Instruction _instruction) override;
|
||||
|
@ -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> _debugData,
|
||||
std::map<u256, Representation>& _cache
|
||||
):
|
||||
m_dialect(_dialect),
|
||||
m_meter(_meter),
|
||||
m_location(std::move(_location)),
|
||||
m_debugData(std::move(_debugData)),
|
||||
m_cache(_cache)
|
||||
{}
|
||||
|
||||
@ -100,7 +100,7 @@ private:
|
||||
|
||||
EVMDialect const& m_dialect;
|
||||
GasMeter const& m_meter;
|
||||
langutil::SourceLocation m_location;
|
||||
std::shared_ptr<DebugData> m_debugData;
|
||||
/// Counter for the complexity of optimization, will stop when it reaches zero.
|
||||
size_t m_maxSteps = 10000;
|
||||
std::map<u256, Representation>& m_cache;
|
||||
|
@ -39,7 +39,7 @@ size_t constexpr assemblySizeReferenceSize = 4;
|
||||
}
|
||||
|
||||
|
||||
void EVMAssembly::setSourceLocation(SourceLocation const&)
|
||||
void EVMAssembly::setSourceLocation(shared_ptr<DebugData const> const&)
|
||||
{
|
||||
// Ignored for now;
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
~EVMAssembly() override = default;
|
||||
|
||||
/// Set a new source location valid starting from the next instruction.
|
||||
void setSourceLocation(langutil::SourceLocation const& _location) override;
|
||||
void setSourceLocation(std::shared_ptr<DebugData const> const& _debugData) override;
|
||||
/// Retrieve the current height of the stack. This does not have to be zero
|
||||
/// at the beginning.
|
||||
int stackHeight() const override { return m_stackHeight; }
|
||||
|
@ -199,13 +199,13 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl)
|
||||
}
|
||||
else
|
||||
{
|
||||
m_assembly.setSourceLocation(_varDecl.location);
|
||||
m_assembly.setSourceLocation(_varDecl.debugData);
|
||||
size_t variablesLeft = numVariables;
|
||||
while (variablesLeft--)
|
||||
m_assembly.appendConstant(u256(0));
|
||||
}
|
||||
|
||||
m_assembly.setSourceLocation(_varDecl.location);
|
||||
m_assembly.setSourceLocation(_varDecl.debugData);
|
||||
bool atTopOfStack = true;
|
||||
for (size_t varIndex = 0; varIndex < numVariables; ++varIndex)
|
||||
{
|
||||
@ -259,13 +259,13 @@ void CodeTransform::operator()(Assignment const& _assignment)
|
||||
std::visit(*this, *_assignment.value);
|
||||
expectDeposit(static_cast<int>(_assignment.variableNames.size()), height);
|
||||
|
||||
m_assembly.setSourceLocation(_assignment.location);
|
||||
m_assembly.setSourceLocation(_assignment.debugData);
|
||||
generateMultiAssignment(_assignment.variableNames);
|
||||
}
|
||||
|
||||
void CodeTransform::operator()(ExpressionStatement const& _statement)
|
||||
{
|
||||
m_assembly.setSourceLocation(_statement.location);
|
||||
m_assembly.setSourceLocation(_statement.debugData);
|
||||
std::visit(*this, _statement.expression);
|
||||
}
|
||||
|
||||
@ -279,7 +279,7 @@ void CodeTransform::operator()(FunctionCall const& _call)
|
||||
});
|
||||
else
|
||||
{
|
||||
m_assembly.setSourceLocation(_call.location);
|
||||
m_assembly.setSourceLocation(_call.debugData);
|
||||
EVMAssembly::LabelID returnLabel(numeric_limits<EVMAssembly::LabelID>::max()); // only used for evm 1.0
|
||||
|
||||
returnLabel = m_assembly.newLabelId();
|
||||
@ -294,7 +294,7 @@ void CodeTransform::operator()(FunctionCall const& _call)
|
||||
yulAssert(function->arguments.size() == _call.arguments.size(), "");
|
||||
for (auto const& arg: _call.arguments | ranges::views::reverse)
|
||||
visitExpression(arg);
|
||||
m_assembly.setSourceLocation(_call.location);
|
||||
m_assembly.setSourceLocation(_call.debugData);
|
||||
m_assembly.appendJumpTo(
|
||||
functionEntryID(_call.functionName.name, *function),
|
||||
static_cast<int>(function->returns.size() - function->arguments.size()) - 1,
|
||||
@ -306,7 +306,7 @@ void CodeTransform::operator()(FunctionCall const& _call)
|
||||
|
||||
void CodeTransform::operator()(Identifier const& _identifier)
|
||||
{
|
||||
m_assembly.setSourceLocation(_identifier.location);
|
||||
m_assembly.setSourceLocation(_identifier.debugData);
|
||||
// First search internals, then externals.
|
||||
yulAssert(m_scope, "");
|
||||
if (m_scope->lookup(_identifier.name, GenericVisitor{
|
||||
@ -338,19 +338,19 @@ void CodeTransform::operator()(Identifier const& _identifier)
|
||||
|
||||
void CodeTransform::operator()(Literal const& _literal)
|
||||
{
|
||||
m_assembly.setSourceLocation(_literal.location);
|
||||
m_assembly.setSourceLocation(_literal.debugData);
|
||||
m_assembly.appendConstant(valueOfLiteral(_literal));
|
||||
}
|
||||
|
||||
void CodeTransform::operator()(If const& _if)
|
||||
{
|
||||
visitExpression(*_if.condition);
|
||||
m_assembly.setSourceLocation(_if.location);
|
||||
m_assembly.setSourceLocation(_if.debugData);
|
||||
m_assembly.appendInstruction(evmasm::Instruction::ISZERO);
|
||||
AbstractAssembly::LabelID end = m_assembly.newLabelId();
|
||||
m_assembly.appendJumpToIf(end);
|
||||
(*this)(_if.body);
|
||||
m_assembly.setSourceLocation(_if.location);
|
||||
m_assembly.setSourceLocation(_if.debugData);
|
||||
m_assembly.appendLabel(end);
|
||||
}
|
||||
|
||||
@ -367,7 +367,7 @@ void CodeTransform::operator()(Switch const& _switch)
|
||||
if (c.value)
|
||||
{
|
||||
(*this)(*c.value);
|
||||
m_assembly.setSourceLocation(c.location);
|
||||
m_assembly.setSourceLocation(c.debugData);
|
||||
AbstractAssembly::LabelID bodyLabel = m_assembly.newLabelId();
|
||||
caseBodies[&c] = bodyLabel;
|
||||
yulAssert(m_assembly.stackHeight() == expressionHeight + 1, "");
|
||||
@ -379,24 +379,24 @@ void CodeTransform::operator()(Switch const& _switch)
|
||||
// default case
|
||||
(*this)(c.body);
|
||||
}
|
||||
m_assembly.setSourceLocation(_switch.location);
|
||||
m_assembly.setSourceLocation(_switch.debugData);
|
||||
m_assembly.appendJumpTo(end);
|
||||
|
||||
size_t numCases = caseBodies.size();
|
||||
for (auto const& c: caseBodies)
|
||||
{
|
||||
m_assembly.setSourceLocation(c.first->location);
|
||||
m_assembly.setSourceLocation(c.first->debugData);
|
||||
m_assembly.appendLabel(c.second);
|
||||
(*this)(c.first->body);
|
||||
// Avoid useless "jump to next" for the last case.
|
||||
if (--numCases > 0)
|
||||
{
|
||||
m_assembly.setSourceLocation(c.first->location);
|
||||
m_assembly.setSourceLocation(c.first->debugData);
|
||||
m_assembly.appendJumpTo(end);
|
||||
}
|
||||
}
|
||||
|
||||
m_assembly.setSourceLocation(_switch.location);
|
||||
m_assembly.setSourceLocation(_switch.debugData);
|
||||
m_assembly.appendLabel(end);
|
||||
m_assembly.appendInstruction(evmasm::Instruction::POP);
|
||||
}
|
||||
@ -417,7 +417,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
|
||||
m_context->variableStackHeights[&var] = height++;
|
||||
}
|
||||
|
||||
m_assembly.setSourceLocation(_function.location);
|
||||
m_assembly.setSourceLocation(_function.debugData);
|
||||
int const stackHeightBefore = m_assembly.stackHeight();
|
||||
|
||||
m_assembly.appendLabel(functionEntryID(_function.name, function));
|
||||
@ -542,11 +542,11 @@ void CodeTransform::operator()(ForLoop const& _forLoop)
|
||||
AbstractAssembly::LabelID postPart = m_assembly.newLabelId();
|
||||
AbstractAssembly::LabelID loopEnd = m_assembly.newLabelId();
|
||||
|
||||
m_assembly.setSourceLocation(_forLoop.location);
|
||||
m_assembly.setSourceLocation(_forLoop.debugData);
|
||||
m_assembly.appendLabel(loopStart);
|
||||
|
||||
visitExpression(*_forLoop.condition);
|
||||
m_assembly.setSourceLocation(_forLoop.location);
|
||||
m_assembly.setSourceLocation(_forLoop.debugData);
|
||||
m_assembly.appendInstruction(evmasm::Instruction::ISZERO);
|
||||
m_assembly.appendJumpToIf(loopEnd);
|
||||
|
||||
@ -554,12 +554,12 @@ void CodeTransform::operator()(ForLoop const& _forLoop)
|
||||
m_context->forLoopStack.emplace(Context::ForLoopLabels{ {postPart, stackHeightBody}, {loopEnd, stackHeightBody} });
|
||||
(*this)(_forLoop.body);
|
||||
|
||||
m_assembly.setSourceLocation(_forLoop.location);
|
||||
m_assembly.setSourceLocation(_forLoop.debugData);
|
||||
m_assembly.appendLabel(postPart);
|
||||
|
||||
(*this)(_forLoop.post);
|
||||
|
||||
m_assembly.setSourceLocation(_forLoop.location);
|
||||
m_assembly.setSourceLocation(_forLoop.debugData);
|
||||
m_assembly.appendJumpTo(loopStart);
|
||||
m_assembly.appendLabel(loopEnd);
|
||||
|
||||
@ -579,7 +579,7 @@ int CodeTransform::appendPopUntil(int _targetDepth)
|
||||
void CodeTransform::operator()(Break const& _break)
|
||||
{
|
||||
yulAssert(!m_context->forLoopStack.empty(), "Invalid break-statement. Requires surrounding for-loop in code generation.");
|
||||
m_assembly.setSourceLocation(_break.location);
|
||||
m_assembly.setSourceLocation(_break.debugData);
|
||||
|
||||
Context::JumpInfo const& jump = m_context->forLoopStack.top().done;
|
||||
m_assembly.appendJumpTo(jump.label, appendPopUntil(jump.targetStackHeight));
|
||||
@ -588,7 +588,7 @@ void CodeTransform::operator()(Break const& _break)
|
||||
void CodeTransform::operator()(Continue const& _continue)
|
||||
{
|
||||
yulAssert(!m_context->forLoopStack.empty(), "Invalid continue-statement. Requires surrounding for-loop in code generation.");
|
||||
m_assembly.setSourceLocation(_continue.location);
|
||||
m_assembly.setSourceLocation(_continue.debugData);
|
||||
|
||||
Context::JumpInfo const& jump = m_context->forLoopStack.top().post;
|
||||
m_assembly.appendJumpTo(jump.label, appendPopUntil(jump.targetStackHeight));
|
||||
@ -598,7 +598,7 @@ void CodeTransform::operator()(Leave const& _leaveStatement)
|
||||
{
|
||||
yulAssert(m_functionExitLabel, "Invalid leave-statement. Requires surrounding function in code generation.");
|
||||
yulAssert(m_functionExitStackHeight, "");
|
||||
m_assembly.setSourceLocation(_leaveStatement.location);
|
||||
m_assembly.setSourceLocation(_leaveStatement.debugData);
|
||||
m_assembly.appendJumpTo(*m_functionExitLabel, appendPopUntil(*m_functionExitStackHeight));
|
||||
}
|
||||
|
||||
@ -659,7 +659,7 @@ void CodeTransform::setupReturnVariablesAndFunctionExit()
|
||||
|
||||
// Allocate slots for return variables as if they were declared as variables in the virtual function scope.
|
||||
for (TypedName const& var: m_delayedReturnVariables)
|
||||
(*this)(VariableDeclaration{var.location, {var}, {}});
|
||||
(*this)(VariableDeclaration{var.debugData, {var}, {}});
|
||||
|
||||
m_functionExitStackHeight = ranges::max(m_delayedReturnVariables | ranges::views::transform([&](TypedName const& _name) {
|
||||
return variableStackHeight(_name.name);
|
||||
@ -729,7 +729,7 @@ void CodeTransform::visitStatements(vector<Statement> const& _statements)
|
||||
|
||||
void CodeTransform::finalizeBlock(Block const& _block, optional<int> blockStartStackHeight)
|
||||
{
|
||||
m_assembly.setSourceLocation(_block.location);
|
||||
m_assembly.setSourceLocation(_block.debugData);
|
||||
|
||||
freeUnusedVariables();
|
||||
|
||||
|
@ -52,7 +52,7 @@ void visitArguments(
|
||||
for (auto const& arg: _call.arguments | ranges::views::reverse)
|
||||
_visitExpression(arg);
|
||||
|
||||
_assembly.setSourceLocation(_call.location);
|
||||
_assembly.setSourceLocation(_call.debugData);
|
||||
}
|
||||
|
||||
|
||||
@ -256,7 +256,7 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
|
||||
_visitExpression(_call.arguments[2]);
|
||||
YulString identifier = std::get<Literal>(_call.arguments[1]).value;
|
||||
_visitExpression(_call.arguments[0]);
|
||||
_assembly.setSourceLocation(_call.location);
|
||||
_assembly.setSourceLocation(_call.debugData);
|
||||
_assembly.appendImmutableAssignment(identifier.str());
|
||||
}
|
||||
));
|
||||
|
@ -48,7 +48,7 @@ public:
|
||||
explicit NoOutputAssembly() { }
|
||||
~NoOutputAssembly() override = default;
|
||||
|
||||
void setSourceLocation(langutil::SourceLocation const&) override {}
|
||||
void setSourceLocation(std::shared_ptr<DebugData const> const&) override {}
|
||||
int stackHeight() const override { return m_stackHeight; }
|
||||
void setStackHeight(int height) override { m_stackHeight = height; }
|
||||
void appendInstruction(evmasm::Instruction _instruction) override;
|
||||
|
@ -116,8 +116,8 @@ void WordSizeTransform::operator()(Block& _block)
|
||||
vector<Statement> ret;
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
ret.emplace_back(VariableDeclaration{
|
||||
varDecl.location,
|
||||
{TypedName{varDecl.location, newLhs[i], m_targetDialect.defaultType}},
|
||||
varDecl.debugData,
|
||||
{TypedName{varDecl.debugData, newLhs[i], m_targetDialect.defaultType}},
|
||||
make_unique<Expression>(Literal{
|
||||
locationOf(*varDecl.value),
|
||||
LiteralKind::Number,
|
||||
@ -126,8 +126,8 @@ void WordSizeTransform::operator()(Block& _block)
|
||||
})
|
||||
});
|
||||
ret.emplace_back(VariableDeclaration{
|
||||
varDecl.location,
|
||||
{TypedName{varDecl.location, newLhs[3], m_targetDialect.defaultType}},
|
||||
varDecl.debugData,
|
||||
{TypedName{varDecl.debugData, newLhs[3], m_targetDialect.defaultType}},
|
||||
std::move(varDecl.value)
|
||||
});
|
||||
return {std::move(ret)};
|
||||
@ -147,8 +147,8 @@ void WordSizeTransform::operator()(Block& _block)
|
||||
vector<Statement> ret;
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
ret.emplace_back(VariableDeclaration{
|
||||
varDecl.location,
|
||||
{TypedName{varDecl.location, newLhs[i], m_targetDialect.defaultType}},
|
||||
varDecl.debugData,
|
||||
{TypedName{varDecl.debugData, newLhs[i], m_targetDialect.defaultType}},
|
||||
std::move(newRhs[i])
|
||||
}
|
||||
);
|
||||
@ -177,8 +177,8 @@ void WordSizeTransform::operator()(Block& _block)
|
||||
vector<Statement> ret;
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
ret.emplace_back(Assignment{
|
||||
assignment.location,
|
||||
{Identifier{assignment.location, newLhs[i]}},
|
||||
assignment.debugData,
|
||||
{Identifier{assignment.debugData, newLhs[i]}},
|
||||
make_unique<Expression>(Literal{
|
||||
locationOf(*assignment.value),
|
||||
LiteralKind::Number,
|
||||
@ -187,8 +187,8 @@ void WordSizeTransform::operator()(Block& _block)
|
||||
})
|
||||
});
|
||||
ret.emplace_back(Assignment{
|
||||
assignment.location,
|
||||
{Identifier{assignment.location, newLhs[3]}},
|
||||
assignment.debugData,
|
||||
{Identifier{assignment.debugData, newLhs[3]}},
|
||||
std::move(assignment.value)
|
||||
});
|
||||
return {std::move(ret)};
|
||||
@ -208,8 +208,8 @@ void WordSizeTransform::operator()(Block& _block)
|
||||
vector<Statement> ret;
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
ret.emplace_back(Assignment{
|
||||
assignment.location,
|
||||
{Identifier{assignment.location, m_variableMapping.at(lhsName)[i]}},
|
||||
assignment.debugData,
|
||||
{Identifier{assignment.debugData, m_variableMapping.at(lhsName)[i]}},
|
||||
std::move(newRhs[i])
|
||||
}
|
||||
);
|
||||
@ -258,7 +258,7 @@ void WordSizeTransform::rewriteVarDeclList(TypedNameList& _nameList)
|
||||
{
|
||||
TypedNameList ret;
|
||||
for (auto newName: generateU64IdentifierNames(_n.name))
|
||||
ret.emplace_back(TypedName{_n.location, newName, m_targetDialect.defaultType});
|
||||
ret.emplace_back(TypedName{_n.debugData, newName, m_targetDialect.defaultType});
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
@ -272,7 +272,7 @@ void WordSizeTransform::rewriteIdentifierList(vector<Identifier>& _ids)
|
||||
{
|
||||
vector<Identifier> ret;
|
||||
for (auto newId: m_variableMapping.at(_id.name))
|
||||
ret.push_back(Identifier{_id.location, newId});
|
||||
ret.push_back(Identifier{_id.debugData, newId});
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
@ -303,19 +303,20 @@ vector<Statement> WordSizeTransform::handleSwitchInternal(
|
||||
].emplace_back(std::move(c));
|
||||
}
|
||||
|
||||
auto const debugData = make_shared<DebugData>(_location);
|
||||
Switch ret{
|
||||
_location,
|
||||
make_unique<Expression>(Identifier{_location, _splitExpressions.at(_depth)}),
|
||||
debugData,
|
||||
make_unique<Expression>(Identifier{debugData, _splitExpressions.at(_depth)}),
|
||||
{}
|
||||
};
|
||||
|
||||
for (auto& c: cases)
|
||||
{
|
||||
Literal label{_location, LiteralKind::Number, YulString(c.first.str()), m_targetDialect.defaultType};
|
||||
Literal label{debugData, LiteralKind::Number, YulString(c.first.str()), m_targetDialect.defaultType};
|
||||
ret.cases.emplace_back(Case{
|
||||
c.second.front().location,
|
||||
c.second.front().debugData,
|
||||
make_unique<Literal>(std::move(label)),
|
||||
Block{_location, handleSwitchInternal(
|
||||
Block{debugData, handleSwitchInternal(
|
||||
_location,
|
||||
_splitExpressions,
|
||||
std::move(c.second),
|
||||
@ -326,13 +327,13 @@ vector<Statement> WordSizeTransform::handleSwitchInternal(
|
||||
}
|
||||
if (!_runDefaultFlag.empty())
|
||||
ret.cases.emplace_back(Case{
|
||||
_location,
|
||||
debugData,
|
||||
nullptr,
|
||||
Block{_location, make_vector<Statement>(
|
||||
Block{debugData, make_vector<Statement>(
|
||||
Assignment{
|
||||
_location,
|
||||
{{_location, _runDefaultFlag}},
|
||||
make_unique<Expression>(Literal{_location, LiteralKind::Boolean, "true"_yulstring, m_targetDialect.boolType})
|
||||
debugData,
|
||||
{{debugData, _runDefaultFlag}},
|
||||
make_unique<Expression>(Literal{debugData, LiteralKind::Boolean, "true"_yulstring, m_targetDialect.boolType})
|
||||
}
|
||||
)}
|
||||
});
|
||||
@ -356,8 +357,8 @@ std::vector<Statement> WordSizeTransform::handleSwitch(Switch& _switch)
|
||||
defaultCase = std::move(_switch.cases.back());
|
||||
_switch.cases.pop_back();
|
||||
ret.emplace_back(VariableDeclaration{
|
||||
_switch.location,
|
||||
{TypedName{_switch.location, runDefaultFlag, m_targetDialect.boolType}},
|
||||
_switch.debugData,
|
||||
{TypedName{_switch.debugData, runDefaultFlag, m_targetDialect.boolType}},
|
||||
{}
|
||||
});
|
||||
}
|
||||
@ -366,7 +367,7 @@ std::vector<Statement> WordSizeTransform::handleSwitch(Switch& _switch)
|
||||
splitExpressions.emplace_back(std::get<Identifier>(*expr).name);
|
||||
|
||||
ret += handleSwitchInternal(
|
||||
_switch.location,
|
||||
_switch.debugData->irLocation,
|
||||
splitExpressions,
|
||||
std::move(_switch.cases),
|
||||
runDefaultFlag,
|
||||
@ -374,8 +375,8 @@ std::vector<Statement> WordSizeTransform::handleSwitch(Switch& _switch)
|
||||
);
|
||||
if (!runDefaultFlag.empty())
|
||||
ret.emplace_back(If{
|
||||
_switch.location,
|
||||
make_unique<Expression>(Identifier{_switch.location, runDefaultFlag}),
|
||||
_switch.debugData,
|
||||
make_unique<Expression>(Identifier{_switch.debugData, runDefaultFlag}),
|
||||
std::move(defaultCase.body)
|
||||
});
|
||||
return ret;
|
||||
@ -397,7 +398,7 @@ array<unique_ptr<Expression>, 4> WordSizeTransform::expandValue(Expression const
|
||||
{
|
||||
auto const& id = std::get<Identifier>(_e);
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
ret[i] = make_unique<Expression>(Identifier{id.location, m_variableMapping.at(id.name)[i]});
|
||||
ret[i] = make_unique<Expression>(Identifier{id.debugData, m_variableMapping.at(id.name)[i]});
|
||||
}
|
||||
else if (holds_alternative<Literal>(_e))
|
||||
{
|
||||
@ -410,7 +411,7 @@ array<unique_ptr<Expression>, 4> WordSizeTransform::expandValue(Expression const
|
||||
val >>= 64;
|
||||
ret[exprIndexReverse] = make_unique<Expression>(
|
||||
Literal{
|
||||
lit.location,
|
||||
lit.debugData,
|
||||
LiteralKind::Number,
|
||||
YulString(currentVal.str()),
|
||||
m_targetDialect.defaultType
|
||||
|
@ -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)
|
||||
|
@ -44,8 +44,8 @@ void ConditionalSimplifier::operator()(Switch& _switch)
|
||||
(*this)(*_case.value);
|
||||
_case.body.statements.insert(_case.body.statements.begin(),
|
||||
Assignment{
|
||||
_case.body.location,
|
||||
{Identifier{_case.body.location, expr}},
|
||||
_case.body.debugData,
|
||||
{Identifier{_case.body.debugData, expr}},
|
||||
make_unique<Expression>(*_case.value)
|
||||
}
|
||||
);
|
||||
@ -72,12 +72,11 @@ void ConditionalSimplifier::operator()(Block& _block)
|
||||
)
|
||||
{
|
||||
YulString condition = std::get<Identifier>(*_if.condition).name;
|
||||
langutil::SourceLocation location = _if.location;
|
||||
return make_vector<Statement>(
|
||||
std::move(_s),
|
||||
Assignment{
|
||||
location,
|
||||
{Identifier{location, condition}},
|
||||
_if.debugData,
|
||||
{Identifier{_if.debugData, condition}},
|
||||
make_unique<Expression>(m_dialect.zeroLiteralForType(m_dialect.boolType))
|
||||
}
|
||||
);
|
||||
|
@ -43,9 +43,9 @@ ExpressionStatement makeDiscardCall(
|
||||
Expression&& _expression
|
||||
)
|
||||
{
|
||||
return {_location, FunctionCall{
|
||||
_location,
|
||||
Identifier{_location, _discardFunction.name},
|
||||
return {make_shared<DebugData>(_location), FunctionCall{
|
||||
make_shared<DebugData>(_location),
|
||||
Identifier{make_shared<DebugData>(_location), _discardFunction.name},
|
||||
{std::move(_expression)}
|
||||
}};
|
||||
}
|
||||
@ -126,7 +126,7 @@ void ControlFlowSimplifier::visit(Statement& _st)
|
||||
|
||||
if (isTerminating && m_numContinueStatements == 0 && m_numBreakStatements == 0)
|
||||
{
|
||||
If replacement{forLoop.location, std::move(forLoop.condition), std::move(forLoop.body)};
|
||||
If replacement{forLoop.debugData, std::move(forLoop.condition), std::move(forLoop.body)};
|
||||
if (controlFlow == TerminationFinder::ControlFlow::Break)
|
||||
replacement.body.statements.resize(replacement.body.statements.size() - 1);
|
||||
_st = std::move(replacement);
|
||||
@ -149,7 +149,7 @@ void ControlFlowSimplifier::simplify(std::vector<yul::Statement>& _statements)
|
||||
{
|
||||
OptionalStatements s = vector<Statement>{};
|
||||
s->emplace_back(makeDiscardCall(
|
||||
_ifStmt.location,
|
||||
_ifStmt.debugData->irLocation,
|
||||
*m_dialect.discardFunction(m_dialect.boolType),
|
||||
std::move(*_ifStmt.condition)
|
||||
));
|
||||
@ -194,7 +194,7 @@ OptionalStatements ControlFlowSimplifier::reduceNoCaseSwitch(Switch& _switchStmt
|
||||
auto loc = locationOf(*_switchStmt.expression);
|
||||
|
||||
return make_vector<Statement>(makeDiscardCall(
|
||||
loc,
|
||||
loc->irLocation,
|
||||
*discardFunction,
|
||||
std::move(*_switchStmt.expression)
|
||||
));
|
||||
@ -205,17 +205,17 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch
|
||||
yulAssert(_switchStmt.cases.size() == 1, "Expected only one case!");
|
||||
|
||||
auto& switchCase = _switchStmt.cases.front();
|
||||
auto loc = locationOf(*_switchStmt.expression);
|
||||
auto debugData = locationOf(*_switchStmt.expression);
|
||||
YulString type = m_typeInfo.typeOf(*_switchStmt.expression);
|
||||
if (switchCase.value)
|
||||
{
|
||||
if (!m_dialect.equalityFunction(type))
|
||||
return {};
|
||||
return make_vector<Statement>(If{
|
||||
std::move(_switchStmt.location),
|
||||
std::move(_switchStmt.debugData),
|
||||
make_unique<Expression>(FunctionCall{
|
||||
loc,
|
||||
Identifier{loc, m_dialect.equalityFunction(type)->name},
|
||||
debugData,
|
||||
Identifier{debugData, m_dialect.equalityFunction(type)->name},
|
||||
{std::move(*switchCase.value), std::move(*_switchStmt.expression)}
|
||||
}),
|
||||
std::move(switchCase.body)
|
||||
@ -228,7 +228,7 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch
|
||||
|
||||
return make_vector<Statement>(
|
||||
makeDiscardCall(
|
||||
loc,
|
||||
debugData->irLocation,
|
||||
*m_dialect.discardFunction(type),
|
||||
std::move(*_switchStmt.expression)
|
||||
),
|
||||
|
@ -39,5 +39,5 @@ void ExpressionSimplifier::visit(Expression& _expression)
|
||||
ASTModifier::visit(_expression);
|
||||
|
||||
while (auto const* match = SimplificationRules::findFirstMatch(_expression, m_dialect, m_value))
|
||||
_expression = match->action().toExpression(locationOf(_expression));
|
||||
_expression = match->action().toExpression(locationOf(_expression)->irLocation);
|
||||
}
|
||||
|
@ -101,15 +101,15 @@ void ExpressionSplitter::outlineExpression(Expression& _expr)
|
||||
|
||||
visit(_expr);
|
||||
|
||||
SourceLocation location = locationOf(_expr);
|
||||
auto const debugData = locationOf(_expr);
|
||||
YulString var = m_nameDispenser.newName({});
|
||||
YulString type = m_typeInfo.typeOf(_expr);
|
||||
m_statementsToPrefix.emplace_back(VariableDeclaration{
|
||||
location,
|
||||
{{TypedName{location, var, type}}},
|
||||
debugData,
|
||||
{{TypedName{debugData, var, type}}},
|
||||
make_unique<Expression>(std::move(_expr))
|
||||
});
|
||||
_expr = Identifier{location, var};
|
||||
_expr = Identifier{debugData, var};
|
||||
m_typeInfo.setVariableType(var, type);
|
||||
}
|
||||
|
||||
|
@ -39,25 +39,25 @@ void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop)
|
||||
!holds_alternative<Identifier>(*_forLoop.condition)
|
||||
)
|
||||
{
|
||||
langutil::SourceLocation const loc = locationOf(*_forLoop.condition);
|
||||
shared_ptr<DebugData> const debugData = locationOf(*_forLoop.condition);
|
||||
|
||||
_forLoop.body.statements.emplace(
|
||||
begin(_forLoop.body.statements),
|
||||
If {
|
||||
loc,
|
||||
debugData,
|
||||
make_unique<Expression>(
|
||||
FunctionCall {
|
||||
loc,
|
||||
{loc, m_dialect.booleanNegationFunction()->name},
|
||||
debugData,
|
||||
{debugData, m_dialect.booleanNegationFunction()->name},
|
||||
util::make_vector<Expression>(std::move(*_forLoop.condition))
|
||||
}
|
||||
),
|
||||
Block {loc, util::make_vector<Statement>(Break{{}})}
|
||||
Block {debugData, util::make_vector<Statement>(Break{{}})}
|
||||
}
|
||||
);
|
||||
_forLoop.condition = make_unique<Expression>(
|
||||
Literal {
|
||||
loc,
|
||||
debugData,
|
||||
LiteralKind::Boolean,
|
||||
"true"_yulstring,
|
||||
m_dialect.boolType
|
||||
|
@ -55,7 +55,7 @@ void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop)
|
||||
return;
|
||||
|
||||
YulString iszero = m_dialect.booleanNegationFunction()->name;
|
||||
langutil::SourceLocation location = locationOf(*firstStatement.condition);
|
||||
auto const debugData = locationOf(*firstStatement.condition);
|
||||
|
||||
if (
|
||||
holds_alternative<FunctionCall>(*firstStatement.condition) &&
|
||||
@ -64,8 +64,8 @@ void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop)
|
||||
_forLoop.condition = make_unique<Expression>(std::move(std::get<FunctionCall>(*firstStatement.condition).arguments.front()));
|
||||
else
|
||||
_forLoop.condition = make_unique<Expression>(FunctionCall{
|
||||
location,
|
||||
Identifier{location, iszero},
|
||||
debugData,
|
||||
Identifier{debugData, iszero},
|
||||
util::make_vector<Expression>(
|
||||
std::move(*firstStatement.condition)
|
||||
)
|
||||
|
@ -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)
|
||||
})
|
||||
});
|
||||
|
@ -37,7 +37,7 @@ void FunctionGrouper::operator()(Block& _block)
|
||||
return;
|
||||
|
||||
vector<Statement> reordered;
|
||||
reordered.emplace_back(Block{_block.location, {}});
|
||||
reordered.emplace_back(Block{_block.debugData, {}});
|
||||
|
||||
for (auto&& statement: _block.statements)
|
||||
{
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -41,11 +41,19 @@ bool KnowledgeBase::knownToBeDifferent(YulString _a, YulString _b)
|
||||
// current values to turn `sub(_a, _b)` into a nonzero constant.
|
||||
// If that fails, try `eq(_a, _b)`.
|
||||
|
||||
Expression expr1 = simplify(FunctionCall{{}, {{}, "sub"_yulstring}, util::make_vector<Expression>(Identifier{{}, _a}, Identifier{{}, _b})});
|
||||
Expression expr1 = simplify(FunctionCall{
|
||||
make_shared<DebugData>(),
|
||||
{make_shared<DebugData>(), "sub"_yulstring},
|
||||
util::make_vector<Expression>(Identifier{make_shared<DebugData>(), _a}, Identifier{make_shared<DebugData>(), _b})
|
||||
});
|
||||
if (holds_alternative<Literal>(expr1))
|
||||
return valueOfLiteral(std::get<Literal>(expr1)) != 0;
|
||||
|
||||
Expression expr2 = simplify(FunctionCall{{}, {{}, "eq"_yulstring}, util::make_vector<Expression>(Identifier{{}, _a}, Identifier{{}, _b})});
|
||||
Expression expr2 = simplify(FunctionCall{
|
||||
make_shared<DebugData>(),
|
||||
{make_shared<DebugData>(), "eq"_yulstring},
|
||||
util::make_vector<Expression>(Identifier{make_shared<DebugData>(), _a}, Identifier{{}, _b})
|
||||
});
|
||||
if (holds_alternative<Literal>(expr2))
|
||||
return valueOfLiteral(std::get<Literal>(expr2)) == 0;
|
||||
|
||||
@ -57,7 +65,11 @@ bool KnowledgeBase::knownToBeDifferentByAtLeast32(YulString _a, YulString _b)
|
||||
// Try to use the simplification rules together with the
|
||||
// current values to turn `sub(_a, _b)` into a constant whose absolute value is at least 32.
|
||||
|
||||
Expression expr1 = simplify(FunctionCall{{}, {{}, "sub"_yulstring}, util::make_vector<Expression>(Identifier{{}, _a}, Identifier{{}, _b})});
|
||||
Expression expr1 = simplify(FunctionCall{
|
||||
make_shared<DebugData>(),
|
||||
{make_shared<DebugData>(), "sub"_yulstring},
|
||||
util::make_vector<Expression>(Identifier{make_shared<DebugData>(), _a}, Identifier{make_shared<DebugData>(), _b})
|
||||
});
|
||||
if (holds_alternative<Literal>(expr1))
|
||||
{
|
||||
u256 val = valueOfLiteral(std::get<Literal>(expr1));
|
||||
@ -84,7 +96,7 @@ Expression KnowledgeBase::simplify(Expression _expression)
|
||||
arg = simplify(arg);
|
||||
|
||||
if (auto match = SimplificationRules::findFirstMatch(_expression, m_dialect, m_variableValues))
|
||||
return simplify(match->action().toExpression(locationOf(_expression)));
|
||||
return simplify(match->action().toExpression(locationOf(_expression)->irLocation));
|
||||
|
||||
return _expression;
|
||||
}
|
||||
|
@ -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,
|
||||
{},
|
||||
{},
|
||||
|
@ -80,7 +80,7 @@ void ReasoningBasedSimplifier::operator()(If& _if)
|
||||
if (result == CheckResult::UNSATISFIABLE)
|
||||
{
|
||||
Literal trueCondition = m_dialect.trueLiteral();
|
||||
trueCondition.location = locationOf(*_if.condition);
|
||||
trueCondition.debugData = locationOf(*_if.condition);
|
||||
_if.condition = make_unique<yul::Expression>(move(trueCondition));
|
||||
}
|
||||
else
|
||||
@ -92,7 +92,7 @@ void ReasoningBasedSimplifier::operator()(If& _if)
|
||||
if (result2 == CheckResult::UNSATISFIABLE)
|
||||
{
|
||||
Literal falseCondition = m_dialect.zeroLiteralForType(m_dialect.boolType);
|
||||
falseCondition.location = locationOf(*_if.condition);
|
||||
falseCondition.debugData = locationOf(*_if.condition);
|
||||
_if.condition = make_unique<yul::Expression>(move(falseCondition));
|
||||
_if.body = yul::Block{};
|
||||
// Nothing left to be done.
|
||||
|
@ -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;
|
||||
auto debugData = varDecl.debugData;
|
||||
vector<Statement> statements;
|
||||
statements.emplace_back(VariableDeclaration{loc, {}, std::move(varDecl.value)});
|
||||
statements.emplace_back(VariableDeclaration{debugData, {}, std::move(varDecl.value)});
|
||||
TypedNameList newVariables;
|
||||
for (auto const& var: varDecl.variables)
|
||||
{
|
||||
YulString oldName = var.name;
|
||||
YulString newName = m_nameDispenser.newName(oldName);
|
||||
newVariables.emplace_back(TypedName{loc, newName, var.type});
|
||||
newVariables.emplace_back(TypedName{debugData, newName, var.type});
|
||||
statements.emplace_back(VariableDeclaration{
|
||||
loc,
|
||||
{TypedName{loc, oldName, var.type}},
|
||||
make_unique<Expression>(Identifier{loc, newName})
|
||||
debugData,
|
||||
{TypedName{debugData, oldName, var.type}},
|
||||
make_unique<Expression>(Identifier{debugData, newName})
|
||||
});
|
||||
}
|
||||
std::get<VariableDeclaration>(statements.front()).variables = std::move(newVariables);
|
||||
@ -112,23 +112,23 @@ void IntroduceSSA::operator()(Block& _block)
|
||||
|
||||
// Replace "a := v" by "let a_1 := v a := v"
|
||||
// Replace "a, b := v" by "let a_1, b_1 := v a := a_1 b := b_2"
|
||||
auto loc = assignment.location;
|
||||
auto debugData = assignment.debugData;
|
||||
vector<Statement> statements;
|
||||
statements.emplace_back(VariableDeclaration{loc, {}, std::move(assignment.value)});
|
||||
statements.emplace_back(VariableDeclaration{debugData, {}, std::move(assignment.value)});
|
||||
TypedNameList newVariables;
|
||||
for (auto const& var: assignment.variableNames)
|
||||
{
|
||||
YulString oldName = var.name;
|
||||
YulString newName = m_nameDispenser.newName(oldName);
|
||||
newVariables.emplace_back(TypedName{
|
||||
loc,
|
||||
debugData,
|
||||
newName,
|
||||
m_typeInfo.typeOfVariable(oldName)
|
||||
});
|
||||
statements.emplace_back(Assignment{
|
||||
loc,
|
||||
{Identifier{loc, oldName}},
|
||||
make_unique<Expression>(Identifier{loc, newName})
|
||||
debugData,
|
||||
{Identifier{debugData, oldName}},
|
||||
make_unique<Expression>(Identifier{debugData, newName})
|
||||
});
|
||||
}
|
||||
std::get<VariableDeclaration>(statements.front()).variables = std::move(newVariables);
|
||||
@ -236,11 +236,12 @@ void IntroduceControlFlowSSA::operator()(Block& _block)
|
||||
vector<Statement> toPrepend;
|
||||
for (YulString toReassign: m_variablesToReassign)
|
||||
{
|
||||
auto const debugData(locationOf(_s));
|
||||
YulString newName = m_nameDispenser.newName(toReassign);
|
||||
toPrepend.emplace_back(VariableDeclaration{
|
||||
locationOf(_s),
|
||||
{TypedName{locationOf(_s), newName, m_typeInfo.typeOfVariable(toReassign)}},
|
||||
make_unique<Expression>(Identifier{locationOf(_s), toReassign})
|
||||
debugData,
|
||||
{TypedName{debugData, newName, m_typeInfo.typeOfVariable(toReassign)}},
|
||||
make_unique<Expression>(Identifier{debugData, toReassign})
|
||||
});
|
||||
assignedVariables.insert(toReassign);
|
||||
}
|
||||
|
@ -241,7 +241,12 @@ Expression Pattern::toExpression(SourceLocation const& _location) const
|
||||
if (m_kind == PatternKind::Constant)
|
||||
{
|
||||
assertThrow(m_data, OptimizerException, "No match group and no constant value given.");
|
||||
return Literal{_location, LiteralKind::Number, YulString{util::formatNumber(*m_data)}, {}};
|
||||
return Literal{
|
||||
make_shared<DebugData>(_location),
|
||||
LiteralKind::Number,
|
||||
YulString{util::formatNumber(*m_data)},
|
||||
{}
|
||||
};
|
||||
}
|
||||
else if (m_kind == PatternKind::Operation)
|
||||
{
|
||||
@ -252,9 +257,10 @@ Expression Pattern::toExpression(SourceLocation const& _location) const
|
||||
string name = instructionInfo(m_instruction).name;
|
||||
transform(begin(name), end(name), begin(name), [](auto _c) { return tolower(_c); });
|
||||
|
||||
auto const debugData = make_shared<DebugData>(_location);
|
||||
return FunctionCall{
|
||||
_location,
|
||||
Identifier{_location, YulString{name}},
|
||||
debugData,
|
||||
Identifier{debugData, YulString{name}},
|
||||
std::move(arguments)
|
||||
};
|
||||
}
|
||||
|
@ -36,14 +36,15 @@ vector<Statement> generateMemoryStore(
|
||||
Expression _value
|
||||
)
|
||||
{
|
||||
auto const debugData = make_shared<DebugData>(_loc);
|
||||
BuiltinFunction const* memoryStoreFunction = _dialect.memoryStoreFunction(_dialect.defaultType);
|
||||
yulAssert(memoryStoreFunction, "");
|
||||
vector<Statement> result;
|
||||
result.emplace_back(ExpressionStatement{_loc, FunctionCall{
|
||||
_loc,
|
||||
Identifier{_loc, memoryStoreFunction->name},
|
||||
result.emplace_back(ExpressionStatement{debugData, FunctionCall{
|
||||
debugData,
|
||||
Identifier{debugData, memoryStoreFunction->name},
|
||||
{
|
||||
Literal{_loc, LiteralKind::Number, _mpos, {}},
|
||||
Literal{debugData, LiteralKind::Number, _mpos, {}},
|
||||
std::move(_value)
|
||||
}
|
||||
}});
|
||||
@ -52,13 +53,14 @@ vector<Statement> generateMemoryStore(
|
||||
|
||||
FunctionCall generateMemoryLoad(Dialect const& _dialect, langutil::SourceLocation const& _loc, YulString _mpos)
|
||||
{
|
||||
auto const debugData = make_shared<DebugData>(_loc);
|
||||
BuiltinFunction const* memoryLoadFunction = _dialect.memoryLoadFunction(_dialect.defaultType);
|
||||
yulAssert(memoryLoadFunction, "");
|
||||
return FunctionCall{
|
||||
_loc,
|
||||
Identifier{_loc, memoryLoadFunction->name}, {
|
||||
debugData,
|
||||
Identifier{debugData, memoryLoadFunction->name}, {
|
||||
Literal{
|
||||
_loc,
|
||||
debugData,
|
||||
LiteralKind::Number,
|
||||
_mpos,
|
||||
{}
|
||||
@ -123,7 +125,7 @@ void StackToMemoryMover::operator()(Block& _block)
|
||||
if (!leftHandSideNeedsMoving)
|
||||
return {};
|
||||
|
||||
langutil::SourceLocation loc = _stmt.location;
|
||||
langutil::SourceLocation loc = _stmt.debugData->irLocation;
|
||||
|
||||
if (_variables.size() == 1)
|
||||
{
|
||||
@ -133,29 +135,29 @@ void StackToMemoryMover::operator()(Block& _block)
|
||||
m_context.dialect,
|
||||
loc,
|
||||
*offset,
|
||||
_stmt.value ? *std::move(_stmt.value) : Literal{loc, LiteralKind::Number, "0"_yulstring, {}}
|
||||
_stmt.value ? *std::move(_stmt.value) : Literal{_stmt.debugData, LiteralKind::Number, "0"_yulstring, {}}
|
||||
);
|
||||
}
|
||||
|
||||
VariableDeclaration tempDecl{loc, {}, std::move(_stmt.value)};
|
||||
VariableDeclaration tempDecl{_stmt.debugData, {}, std::move(_stmt.value)};
|
||||
vector<Statement> memoryAssignments;
|
||||
vector<Statement> variableAssignments;
|
||||
for (auto& var: _variables)
|
||||
{
|
||||
YulString tempVarName = m_nameDispenser.newName(var.name);
|
||||
tempDecl.variables.emplace_back(TypedName{var.location, tempVarName, {}});
|
||||
tempDecl.variables.emplace_back(TypedName{var.debugData, tempVarName, {}});
|
||||
|
||||
if (optional<YulString> offset = m_memoryOffsetTracker(var.name))
|
||||
memoryAssignments += generateMemoryStore(
|
||||
m_context.dialect,
|
||||
loc,
|
||||
*offset,
|
||||
Identifier{loc, tempVarName}
|
||||
Identifier{_stmt.debugData, tempVarName}
|
||||
);
|
||||
else
|
||||
variableAssignments.emplace_back(StatementType{
|
||||
loc, {move(var)},
|
||||
make_unique<Expression>(Identifier{loc, tempVarName})
|
||||
_stmt.debugData, {move(var)},
|
||||
make_unique<Expression>(Identifier{_stmt.debugData, tempVarName})
|
||||
});
|
||||
}
|
||||
std::vector<Statement> result;
|
||||
@ -191,7 +193,7 @@ void StackToMemoryMover::visit(Expression& _expression)
|
||||
ASTModifier::visit(_expression);
|
||||
if (Identifier* identifier = std::get_if<Identifier>(&_expression))
|
||||
if (optional<YulString> offset = m_memoryOffsetTracker(identifier->name))
|
||||
_expression = generateMemoryLoad(m_context.dialect, identifier->location, *offset);
|
||||
_expression = generateMemoryLoad(m_context.dialect, identifier->debugData->irLocation, *offset);
|
||||
}
|
||||
|
||||
optional<YulString> StackToMemoryMover::VariableMemoryOffsetTracker::operator()(YulString _variable) const
|
||||
|
@ -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,11 @@ void VarDeclInitializer::operator()(Block& _block)
|
||||
else
|
||||
{
|
||||
OptionalStatements ret{vector<Statement>{}};
|
||||
langutil::SourceLocation loc{std::move(_varDecl.location)};
|
||||
shared_ptr<DebugData> const debugData{std::move(_varDecl.debugData)};
|
||||
for (auto& var: _varDecl.variables)
|
||||
{
|
||||
unique_ptr<Expression> expr = make_unique<Expression >(m_dialect.zeroLiteralForType(var.type));
|
||||
ret->emplace_back(VariableDeclaration{loc, {std::move(var)}, std::move(expr)});
|
||||
ret->emplace_back(VariableDeclaration{debugData, {std::move(var)}, std::move(expr)});
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user