aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libjulia/backends/evm/EVMCodeTransform.cpp55
-rw-r--r--libjulia/backends/evm/EVMCodeTransform.h31
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.cpp8
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.h8
-rw-r--r--libsolidity/inlineasm/AsmScope.cpp2
-rw-r--r--libsolidity/inlineasm/AsmScope.h19
6 files changed, 65 insertions, 58 deletions
diff --git a/libjulia/backends/evm/EVMCodeTransform.cpp b/libjulia/backends/evm/EVMCodeTransform.cpp
index cd6fd276..7c14eb8b 100644
--- a/libjulia/backends/evm/EVMCodeTransform.cpp
+++ b/libjulia/backends/evm/EVMCodeTransform.cpp
@@ -64,8 +64,7 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl)
for (auto const& variable: _varDecl.variables)
{
auto& var = boost::get<Scope::Variable>(m_scope->identifiers.at(variable.name));
- var.stackHeight = height++;
- var.active = true;
+ m_context->variableStackHeights[&var] = height++;
}
checkStackHeight(&_varDecl);
}
@@ -91,8 +90,7 @@ void CodeTransform::operator()(Label const& _label)
solAssert(m_scope, "");
solAssert(m_scope->identifiers.count(_label.name), "");
Scope::Label& label = boost::get<Scope::Label>(m_scope->identifiers.at(_label.name));
- assignLabelIdIfUnset(label.id);
- m_assembly.appendLabel(*label.id);
+ m_assembly.appendLabel(labelID(label));
checkStackHeight(&_label);
}
@@ -120,12 +118,11 @@ void CodeTransform::operator()(FunctionCall const& _call)
for (auto const& arg: _call.arguments | boost::adaptors::reversed)
visitExpression(arg);
m_assembly.setSourceLocation(_call.location);
- assignLabelIdIfUnset(function->id);
if (m_evm15)
- m_assembly.appendJumpsub(*function->id, function->arguments.size(), function->returns.size());
+ m_assembly.appendJumpsub(functionEntryID(*function), function->arguments.size(), function->returns.size());
else
{
- m_assembly.appendJumpTo(*function->id, function->returns.size() - function->arguments.size() - 1);
+ m_assembly.appendJumpTo(functionEntryID(*function), function->returns.size() - function->arguments.size() - 1);
m_assembly.appendLabel(returnLabel);
m_stackAdjustment--;
}
@@ -181,8 +178,7 @@ void CodeTransform::operator()(assembly::Identifier const& _identifier)
},
[=](Scope::Label& _label)
{
- assignLabelIdIfUnset(_label.id);
- m_assembly.appendLabelReference(*_label.id);
+ m_assembly.appendLabelReference(labelID(_label));
},
[=](Scope::Function&)
{
@@ -282,7 +278,6 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
solAssert(m_scope, "");
solAssert(m_scope->identifiers.count(_function.name), "");
Scope::Function& function = boost::get<Scope::Function>(m_scope->identifiers.at(_function.name));
- assignLabelIdIfUnset(function.id);
int const localStackAdjustment = m_evm15 ? 0 : 1;
int height = localStackAdjustment;
@@ -292,8 +287,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
for (auto const& v: _function.arguments | boost::adaptors::reversed)
{
auto& var = boost::get<Scope::Variable>(varScope->identifiers.at(v.name));
- var.stackHeight = height++;
- var.active = true;
+ m_context->variableStackHeights[&var] = height++;
}
m_assembly.setSourceLocation(_function.location);
@@ -303,25 +297,24 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
if (m_evm15)
{
m_assembly.appendJumpTo(afterFunction, -stackHeightBefore);
- m_assembly.appendBeginsub(*function.id, _function.arguments.size());
+ m_assembly.appendBeginsub(functionEntryID(function), _function.arguments.size());
}
else
{
m_assembly.appendJumpTo(afterFunction, -stackHeightBefore + height);
- m_assembly.appendLabel(*function.id);
+ m_assembly.appendLabel(functionEntryID(function));
}
m_stackAdjustment += localStackAdjustment;
for (auto const& v: _function.returns)
{
auto& var = boost::get<Scope::Variable>(varScope->identifiers.at(v.name));
- var.stackHeight = height++;
- var.active = true;
+ m_context->variableStackHeights[&var] = height++;
// Preset stack slots for return variables to zero.
m_assembly.appendConstant(u256(0));
}
- CodeTransform(m_assembly, m_info, m_evm15, m_identifierAccess, localStackAdjustment)
+ CodeTransform(m_assembly, m_info, m_evm15, m_identifierAccess, localStackAdjustment, m_context)
.run(_function.body);
{
@@ -367,7 +360,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
void CodeTransform::operator()(Block const& _block)
{
- CodeTransform(m_assembly, m_info, m_evm15, m_identifierAccess, m_stackAdjustment).run(_block);
+ CodeTransform(m_assembly, m_info, m_evm15, m_identifierAccess, m_stackAdjustment, m_context).run(_block);
}
AbstractAssembly::LabelID CodeTransform::labelFromIdentifier(Identifier const& _identifier)
@@ -377,8 +370,7 @@ AbstractAssembly::LabelID CodeTransform::labelFromIdentifier(Identifier const& _
[=](Scope::Variable&) { solAssert(false, "Expected label"); },
[&](Scope::Label& _label)
{
- assignLabelIdIfUnset(_label.id);
- label = *_label.id;
+ label = labelID(_label);
},
[=](Scope::Function&) { solAssert(false, "Expected label"); }
)))
@@ -388,6 +380,20 @@ AbstractAssembly::LabelID CodeTransform::labelFromIdentifier(Identifier const& _
return label;
}
+AbstractAssembly::LabelID CodeTransform::labelID(Scope::Label const& _label)
+{
+ if (!m_context->labelIDs.count(&_label))
+ m_context->labelIDs[&_label] = m_assembly.newLabelId();
+ return m_context->labelIDs[&_label];
+}
+
+AbstractAssembly::LabelID CodeTransform::functionEntryID(Scope::Function const& _function)
+{
+ if (!m_context->functionEntryIDs.count(&_function))
+ m_context->functionEntryIDs[&_function] = m_assembly.newLabelId();
+ return m_context->functionEntryIDs[&_function];
+}
+
void CodeTransform::visitExpression(Statement const& _expression)
{
int height = m_assembly.stackHeight();
@@ -418,7 +424,8 @@ void CodeTransform::generateAssignment(Identifier const& _variableName)
int CodeTransform::variableHeightDiff(solidity::assembly::Scope::Variable const& _var, bool _forSwap)
{
- int heightDiff = m_assembly.stackHeight() - _var.stackHeight;
+ solAssert(m_context->variableStackHeights.count(&_var), "");
+ int heightDiff = m_assembly.stackHeight() - m_context->variableStackHeights[&_var];
if (heightDiff <= (_forSwap ? 1 : 0) || heightDiff > (_forSwap ? 17 : 16))
{
solUnimplemented(
@@ -446,9 +453,3 @@ void CodeTransform::checkStackHeight(void const* _astElement)
to_string(m_assembly.stackHeight() - m_stackAdjustment)
);
}
-
-void CodeTransform::assignLabelIdIfUnset(boost::optional<AbstractAssembly::LabelID>& _labelId)
-{
- if (!_labelId)
- _labelId.reset(m_assembly.newLabelId());
-}
diff --git a/libjulia/backends/evm/EVMCodeTransform.h b/libjulia/backends/evm/EVMCodeTransform.h
index f65948dc..202f5051 100644
--- a/libjulia/backends/evm/EVMCodeTransform.h
+++ b/libjulia/backends/evm/EVMCodeTransform.h
@@ -64,7 +64,14 @@ public:
solidity::assembly::AsmAnalysisInfo& _analysisInfo,
bool _evm15 = false,
ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess()
- ): CodeTransform(_assembly, _analysisInfo, _evm15, _identifierAccess, _assembly.stackHeight())
+ ): CodeTransform(
+ _assembly,
+ _analysisInfo,
+ _evm15,
+ _identifierAccess,
+ _assembly.stackHeight(),
+ std::make_shared<Context>()
+ )
{
}
@@ -72,18 +79,28 @@ public:
void run(solidity::assembly::Block const& _block);
protected:
+ struct Context
+ {
+ using Scope = solidity::assembly::Scope;
+ std::map<Scope::Label const*, AbstractAssembly::LabelID> labelIDs;
+ std::map<Scope::Function const*, AbstractAssembly::LabelID> functionEntryIDs;
+ std::map<Scope::Variable const*, int> variableStackHeights;
+ };
+
CodeTransform(
julia::AbstractAssembly& _assembly,
solidity::assembly::AsmAnalysisInfo& _analysisInfo,
bool _evm15,
ExternalIdentifierAccess const& _identifierAccess,
- int _stackAdjustment
+ int _stackAdjustment,
+ std::shared_ptr<Context> _context
):
m_assembly(_assembly),
m_info(_analysisInfo),
m_evm15(_evm15),
m_identifierAccess(_identifierAccess),
- m_stackAdjustment(_stackAdjustment)
+ m_stackAdjustment(_stackAdjustment),
+ m_context(_context)
{}
public:
@@ -102,6 +119,10 @@ public:
private:
AbstractAssembly::LabelID labelFromIdentifier(solidity::assembly::Identifier const& _identifier);
+ /// @returns the label ID corresponding to the given label, allocating a new one if
+ /// necessary.
+ AbstractAssembly::LabelID labelID(solidity::assembly::Scope::Label const& _label);
+ AbstractAssembly::LabelID functionEntryID(solidity::assembly::Scope::Function const& _function);
/// Generates code for an expression that is supposed to return a single value.
void visitExpression(solidity::assembly::Statement const& _expression);
@@ -116,9 +137,6 @@ private:
void checkStackHeight(void const* _astElement);
- /// Assigns the label's or function's id to a value taken from eth::Assembly if it has not yet been set.
- void assignLabelIdIfUnset(boost::optional<AbstractAssembly::LabelID>& _labelId);
-
julia::AbstractAssembly& m_assembly;
solidity::assembly::AsmAnalysisInfo& m_info;
solidity::assembly::Scope* m_scope = nullptr;
@@ -129,6 +147,7 @@ private:
/// for inline assembly and different stack heights depending on the EVM backend used
/// (EVM 1.0 or 1.5).
int m_stackAdjustment = 0;
+ std::shared_ptr<Context> m_context;
};
}
diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp
index 36ac0e75..7bcbde91 100644
--- a/libsolidity/inlineasm/AsmAnalysis.cpp
+++ b/libsolidity/inlineasm/AsmAnalysis.cpp
@@ -92,7 +92,7 @@ bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier)
if (m_currentScope->lookup(_identifier.name, Scope::Visitor(
[&](Scope::Variable const& _var)
{
- if (!_var.active)
+ if (!m_activeVariables.count(&_var))
{
m_errorReporter.declarationError(
_identifier.location,
@@ -187,7 +187,7 @@ bool AsmAnalyzer::operator()(assembly::VariableDeclaration const& _varDecl)
for (auto const& variable: _varDecl.variables)
{
expectValidType(variable.type, variable.location);
- boost::get<Scope::Variable>(m_currentScope->identifiers.at(variable.name)).active = true;
+ m_activeVariables.insert(&boost::get<Scope::Variable>(m_currentScope->identifiers.at(variable.name)));
}
m_info.stackHeightInfo[&_varDecl] = m_stackHeight;
return success;
@@ -201,7 +201,7 @@ bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef)
for (auto const& var: _funDef.arguments + _funDef.returns)
{
expectValidType(var.type, var.location);
- boost::get<Scope::Variable>(varScope.identifiers.at(var.name)).active = true;
+ m_activeVariables.insert(&boost::get<Scope::Variable>(varScope.identifiers.at(var.name)));
}
int const stackHeight = m_stackHeight;
@@ -384,7 +384,7 @@ bool AsmAnalyzer::checkAssignment(assembly::Identifier const& _variable, size_t
m_errorReporter.typeError(_variable.location, "Assignment requires variable.");
success = false;
}
- else if (!boost::get<Scope::Variable>(*var).active)
+ else if (!m_activeVariables.count(&boost::get<Scope::Variable>(*var)))
{
m_errorReporter.declarationError(
_variable.location,
diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libsolidity/inlineasm/AsmAnalysis.h
index 55b409ba..2516722a 100644
--- a/libsolidity/inlineasm/AsmAnalysis.h
+++ b/libsolidity/inlineasm/AsmAnalysis.h
@@ -22,6 +22,8 @@
#include <libsolidity/interface/Exceptions.h>
+#include <libsolidity/inlineasm/AsmScope.h>
+
#include <libjulia/backends/evm/AbstractAssembly.h>
#include <boost/variant.hpp>
@@ -51,9 +53,6 @@ struct FunctionCall;
struct Switch;
using Statement = boost::variant<Instruction, Literal, Label, StackAssignment, Identifier, Assignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Switch, Block>;
-
-struct Scope;
-
struct AsmAnalysisInfo;
/**
@@ -102,6 +101,9 @@ private:
int m_stackHeight = 0;
julia::ExternalIdentifierAccess::Resolver m_resolver;
Scope* m_currentScope = nullptr;
+ /// Variables that are active at the current point in assembly (as opposed to
+ /// "part of the scope but not yet declared")
+ std::set<Scope::Variable const*> m_activeVariables;
AsmAnalysisInfo& m_info;
ErrorReporter& m_errorReporter;
bool m_julia = false;
diff --git a/libsolidity/inlineasm/AsmScope.cpp b/libsolidity/inlineasm/AsmScope.cpp
index 7a086846..1db5ca41 100644
--- a/libsolidity/inlineasm/AsmScope.cpp
+++ b/libsolidity/inlineasm/AsmScope.cpp
@@ -46,7 +46,7 @@ bool Scope::registerFunction(string const& _name, std::vector<JuliaType> const&
{
if (exists(_name))
return false;
- identifiers[_name] = Function(_arguments, _returns);
+ identifiers[_name] = Function{_arguments, _returns};
return true;
}
diff --git a/libsolidity/inlineasm/AsmScope.h b/libsolidity/inlineasm/AsmScope.h
index ad321f77..de9119e0 100644
--- a/libsolidity/inlineasm/AsmScope.h
+++ b/libsolidity/inlineasm/AsmScope.h
@@ -65,27 +65,12 @@ struct Scope
using JuliaType = std::string;
using LabelID = size_t;
- struct Variable
- {
- /// Used during code generation to store the stack height. @todo move there.
- int stackHeight = 0;
- /// Used during analysis to check whether we already passed the declaration inside the block.
- /// @todo move there.
- bool active = false;
- JuliaType type;
- };
-
- struct Label
- {
- boost::optional<LabelID> id;
- };
-
+ struct Variable { JuliaType type; };
+ struct Label { };
struct Function
{
- Function(std::vector<JuliaType> const& _arguments, std::vector<JuliaType> const& _returns): arguments(_arguments), returns(_returns) {}
std::vector<JuliaType> arguments;
std::vector<JuliaType> returns;
- boost::optional<LabelID> id;
};
using Identifier = boost::variant<Variable, Label, Function>;