diff options
Diffstat (limited to 'libsolidity/codegen/CompilerContext.cpp')
-rw-r--r-- | libsolidity/codegen/CompilerContext.cpp | 79 |
1 files changed, 76 insertions, 3 deletions
diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index c14ab845..a8316109 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -21,15 +21,18 @@ */ #include <libsolidity/codegen/CompilerContext.h> -#include <utility> -#include <numeric> -#include <boost/algorithm/string/replace.hpp> +#include <libsolidity/codegen/CompilerUtils.h> #include <libsolidity/ast/AST.h> #include <libsolidity/codegen/Compiler.h> #include <libsolidity/interface/Version.h> #include <libsolidity/inlineasm/AsmData.h> #include <libsolidity/inlineasm/AsmStack.h> +#include <boost/algorithm/string/replace.hpp> + +#include <utility> +#include <numeric> + using namespace std; namespace dev @@ -57,6 +60,62 @@ void CompilerContext::startFunction(Declaration const& _function) *this << functionEntryLabel(_function); } +void CompilerContext::callLowLevelFunction( + string const& _name, + unsigned _inArgs, + unsigned _outArgs, + function<void(CompilerContext&)> const& _generator +) +{ + eth::AssemblyItem retTag = pushNewTag(); + CompilerUtils(*this).moveIntoStack(_inArgs); + + *this << lowLevelFunctionTag(_name, _inArgs, _outArgs, _generator); + + appendJump(eth::AssemblyItem::JumpType::IntoFunction); + adjustStackOffset(int(_outArgs) - 1 - _inArgs); + *this << retTag.tag(); +} + +eth::AssemblyItem CompilerContext::lowLevelFunctionTag( + string const& _name, + unsigned _inArgs, + unsigned _outArgs, + function<void(CompilerContext&)> const& _generator +) +{ + auto it = m_lowLevelFunctions.find(_name); + if (it == m_lowLevelFunctions.end()) + { + eth::AssemblyItem tag = newTag().pushTag(); + m_lowLevelFunctions.insert(make_pair(_name, tag)); + m_lowLevelFunctionGenerationQueue.push(make_tuple(_name, _inArgs, _outArgs, _generator)); + return tag; + } + else + return it->second; +} + +void CompilerContext::appendMissingLowLevelFunctions() +{ + while (!m_lowLevelFunctionGenerationQueue.empty()) + { + string name; + unsigned inArgs; + unsigned outArgs; + function<void(CompilerContext&)> generator; + tie(name, inArgs, outArgs, generator) = m_lowLevelFunctionGenerationQueue.front(); + m_lowLevelFunctionGenerationQueue.pop(); + + setStackOffset(inArgs + 1); + *this << m_lowLevelFunctions.at(name).tag(); + generator(*this); + CompilerUtils(*this).moveToStackTop(outArgs); + appendJump(eth::AssemblyItem::JumpType::OutOfFunction); + solAssert(stackHeight() == outArgs, "Invalid stack height in low-level function " + name + "."); + } +} + void CompilerContext::addVariable(VariableDeclaration const& _declaration, unsigned _offsetToCurrent) { @@ -167,6 +226,20 @@ CompilerContext& CompilerContext::appendJump(eth::AssemblyItem::JumpType _jumpTy return *this << item; } +CompilerContext& CompilerContext::appendInvalid() +{ + return *this << Instruction::INVALID; +} + +CompilerContext& CompilerContext::appendConditionalInvalid() +{ + *this << Instruction::ISZERO; + eth::AssemblyItem afterTag = appendConditionalJump(); + *this << Instruction::INVALID; + *this << afterTag; + return *this; +} + void CompilerContext::resetVisitedNodes(ASTNode const* _node) { stack<ASTNode const*> newStack; |