aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/inlineasm
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2017-05-25 00:34:19 +0800
committerchriseth <chris@ethereum.org>2017-06-08 21:52:44 +0800
commit97cc968a133247e729ed1d189d35ef2b7b53b3d4 (patch)
treec2aa552abea75a732e36e0c6b357ea879f35de54 /libsolidity/inlineasm
parent21e0b69dcb189fb52ac4e38959801582e02ca8fd (diff)
downloaddexon-solidity-97cc968a133247e729ed1d189d35ef2b7b53b3d4.tar.gz
dexon-solidity-97cc968a133247e729ed1d189d35ef2b7b53b3d4.tar.zst
dexon-solidity-97cc968a133247e729ed1d189d35ef2b7b53b3d4.zip
Initial EVM1.5 assembly implementation.
Diffstat (limited to 'libsolidity/inlineasm')
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.cpp19
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.h6
-rw-r--r--libsolidity/inlineasm/AsmCodeGen.cpp43
-rw-r--r--libsolidity/inlineasm/AsmScope.cpp8
-rw-r--r--libsolidity/inlineasm/AsmScope.h4
5 files changed, 69 insertions, 11 deletions
diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp
index 3edc01ad..b59a8527 100644
--- a/libsolidity/inlineasm/AsmAnalysis.cpp
+++ b/libsolidity/inlineasm/AsmAnalysis.cpp
@@ -25,7 +25,7 @@
#include <libsolidity/inlineasm/AsmScope.h>
#include <libsolidity/inlineasm/AsmAnalysisInfo.h>
-#include <libsolidity/interface/Exceptions.h>
+#include <libsolidity/interface/ErrorReporter.h>
#include <libsolidity/interface/Utils.h>
#include <boost/range/adaptor/reversed.hpp>
@@ -120,7 +120,10 @@ bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier)
{
size_t stackSize(-1);
if (m_resolver)
- stackSize = m_resolver(_identifier, julia::IdentifierContext::RValue);
+ {
+ bool insideFunction = m_currentScope->insideFunction();
+ stackSize = m_resolver(_identifier, julia::IdentifierContext::RValue, insideFunction);
+ }
if (stackSize == size_t(-1))
{
// Only add an error message if the callback did not do it.
@@ -200,7 +203,8 @@ bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef)
}
int const stackHeight = m_stackHeight;
- m_stackHeight = _funDef.arguments.size() + _funDef.returns.size();
+ // 1 for return label, depends on VM version
+ m_stackHeight = 1 + _funDef.arguments.size() + _funDef.returns.size();
bool success = (*this)(_funDef.body);
@@ -254,10 +258,11 @@ bool AsmAnalyzer::operator()(assembly::FunctionCall const& _funCall)
success = false;
}
}
+ m_stackHeight += 1; // Return label, but depends on backend
for (auto const& arg: _funCall.arguments | boost::adaptors::reversed)
if (!expectExpression(arg))
success = false;
- m_stackHeight += int(returns) - int(arguments);
+ m_stackHeight += int(returns) - int(arguments) - 1; // Return label, but depends on backend
m_info.stackHeightInfo[&_funCall] = m_stackHeight;
return success;
}
@@ -295,6 +300,7 @@ bool AsmAnalyzer::operator()(Switch const& _switch)
}
m_stackHeight--;
+ m_info.stackHeightInfo[&_switch] = m_stackHeight;
return success;
}
@@ -378,7 +384,10 @@ bool AsmAnalyzer::checkAssignment(assembly::Identifier const& _variable, size_t
variableSize = 1;
}
else if (m_resolver)
- variableSize = m_resolver(_variable, julia::IdentifierContext::LValue);
+ {
+ bool insideFunction = m_currentScope->insideFunction();
+ variableSize = m_resolver(_variable, julia::IdentifierContext::LValue, insideFunction);
+ }
if (variableSize == size_t(-1))
{
// Only add message if the callback did not.
diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libsolidity/inlineasm/AsmAnalysis.h
index e52e6302..d6f9de5b 100644
--- a/libsolidity/inlineasm/AsmAnalysis.h
+++ b/libsolidity/inlineasm/AsmAnalysis.h
@@ -20,7 +20,11 @@
#pragma once
-#include <libsolidity/inlineasm/AsmStack.h>
+#include <libsolidity/interface/Exceptions.h>
+
+#include <libsolidity/interface/Exceptions.h>
+
+#include <libjulia/backends/evm/AbstractAssembly.h>
#include <boost/variant.hpp>
diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp
index 11494c2d..875d7ce4 100644
--- a/libsolidity/inlineasm/AsmCodeGen.cpp
+++ b/libsolidity/inlineasm/AsmCodeGen.cpp
@@ -87,13 +87,46 @@ public:
{
m_assembly.appendLibraryAddress(_linkerSymbol);
}
+ virtual void appendJump(int _stackDiffAfter) override
+ {
+ appendInstruction(solidity::Instruction::JUMP);
+ m_assembly.adjustDeposit(_stackDiffAfter);
+ }
+ virtual void appendJumpTo(LabelID _label, int _stackDiffAfter) override
+ {
+ appendLabelReference(_label);
+ appendJump(_stackDiffAfter);
+ }
+ virtual void appendJumpToIf(LabelID _label) override
+ {
+ appendLabelReference(_label);
+ appendInstruction(solidity::Instruction::JUMPI);
+ }
+ virtual void appendBeginsub(LabelID, int) override
+ {
+ // TODO we could emulate that, though
+ solAssert(false, "BEGINSUB not implemented for EVM 1.0");
+ }
+ /// Call a subroutine.
+ virtual void appendJumpsub(LabelID, int, int) override
+ {
+ // TODO we could emulate that, though
+ solAssert(false, "JUMPSUB not implemented for EVM 1.0");
+ }
+
+ /// Return from a subroutine.
+ virtual void appendReturnsub(int) override
+ {
+ // TODO we could emulate that, though
+ solAssert(false, "RETURNSUB not implemented for EVM 1.0");
+ }
private:
- size_t assemblyTagToIdentifier(eth::AssemblyItem const& _tag) const
+ LabelID assemblyTagToIdentifier(eth::AssemblyItem const& _tag) const
{
u256 id = _tag.data();
- solAssert(id <= std::numeric_limits<size_t>::max(), "Tag id too large.");
- return size_t(id);
+ solAssert(id <= std::numeric_limits<LabelID>::max(), "Tag id too large.");
+ return LabelID(id);
}
eth::Assembly& m_assembly;
@@ -107,7 +140,7 @@ eth::Assembly assembly::CodeGenerator::assemble(
{
eth::Assembly assembly;
EthAssemblyAdapter assemblyAdapter(assembly);
- julia::CodeTransform(m_errorReporter, assemblyAdapter, _parsedData, _analysisInfo, _identifierAccess);
+ julia::CodeTransform(m_errorReporter, assemblyAdapter, _analysisInfo, false, _identifierAccess).run(_parsedData);
return assembly;
}
@@ -119,5 +152,5 @@ void assembly::CodeGenerator::assemble(
)
{
EthAssemblyAdapter assemblyAdapter(_assembly);
- julia::CodeTransform(m_errorReporter, assemblyAdapter, _parsedData, _analysisInfo, _identifierAccess);
+ julia::CodeTransform(m_errorReporter, assemblyAdapter, _analysisInfo, false, _identifierAccess).run(_parsedData);
}
diff --git a/libsolidity/inlineasm/AsmScope.cpp b/libsolidity/inlineasm/AsmScope.cpp
index e3f4615a..7a086846 100644
--- a/libsolidity/inlineasm/AsmScope.cpp
+++ b/libsolidity/inlineasm/AsmScope.cpp
@@ -79,3 +79,11 @@ bool Scope::exists(string const& _name)
else
return false;
}
+
+bool Scope::insideFunction() const
+{
+ for (Scope const* s = this; s; s = s->superScope)
+ if (s->functionScope)
+ return true;
+ return false;
+}
diff --git a/libsolidity/inlineasm/AsmScope.h b/libsolidity/inlineasm/AsmScope.h
index 498218b4..ad321f77 100644
--- a/libsolidity/inlineasm/AsmScope.h
+++ b/libsolidity/inlineasm/AsmScope.h
@@ -85,6 +85,7 @@ struct Scope
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>;
@@ -123,6 +124,9 @@ struct Scope
/// across function and assembly boundaries).
bool exists(std::string const& _name);
+ /// @returns true if this scope is inside a function.
+ bool insideFunction() const;
+
Scope* superScope = nullptr;
/// If true, variables from the super scope are not visible here (other identifiers are),
/// but they are still taken into account to prevent shadowing.