diff options
author | chriseth <chris@ethereum.org> | 2017-05-25 00:34:19 +0800 |
---|---|---|
committer | chriseth <chris@ethereum.org> | 2017-06-08 21:52:44 +0800 |
commit | 97cc968a133247e729ed1d189d35ef2b7b53b3d4 (patch) | |
tree | c2aa552abea75a732e36e0c6b357ea879f35de54 /libsolidity/inlineasm | |
parent | 21e0b69dcb189fb52ac4e38959801582e02ca8fd (diff) | |
download | dexon-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.cpp | 19 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysis.h | 6 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmCodeGen.cpp | 43 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmScope.cpp | 8 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmScope.h | 4 |
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. |