aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/codegen
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2016-08-16 22:27:20 +0800
committerGitHub <noreply@github.com>2016-08-16 22:27:20 +0800
commit77f442458934d2f0d9ffde34784bb58bd177b3ef (patch)
tree5443b8b9414fc21c0551dd57ee30b8c3a2ac4762 /libsolidity/codegen
parentc547f9c24b5bd57840ddd5543ab6e5288ddc5563 (diff)
downloaddexon-solidity-77f442458934d2f0d9ffde34784bb58bd177b3ef.tar.gz
dexon-solidity-77f442458934d2f0d9ffde34784bb58bd177b3ef.tar.zst
dexon-solidity-77f442458934d2f0d9ffde34784bb58bd177b3ef.zip
Provide inline assembly to the code generator. (#840)
* Directly usable inline assembly. * Add missing header.
Diffstat (limited to 'libsolidity/codegen')
-rw-r--r--libsolidity/codegen/CompilerContext.cpp48
-rw-r--r--libsolidity/codegen/CompilerContext.h9
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp1
3 files changed, 58 insertions, 0 deletions
diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp
index c1dc8dfb..3ac5bd3c 100644
--- a/libsolidity/codegen/CompilerContext.cpp
+++ b/libsolidity/codegen/CompilerContext.cpp
@@ -23,9 +23,12 @@
#include <libsolidity/codegen/CompilerContext.h>
#include <utility>
#include <numeric>
+#include <boost/algorithm/string/replace.hpp>
#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>
using namespace std;
@@ -172,6 +175,51 @@ void CompilerContext::resetVisitedNodes(ASTNode const* _node)
updateSourceLocation();
}
+void CompilerContext::appendInlineAssembly(
+ string const& _assembly,
+ vector<string> const& _localVariables,
+ map<string, string> const& _replacements
+)
+{
+ string replacedAssembly;
+ string const* assembly = &_assembly;
+ if (!_replacements.empty())
+ {
+ replacedAssembly = _assembly;
+ for (auto const& replacement: _replacements)
+ replacedAssembly = boost::algorithm::replace_all_copy(replacedAssembly, replacement.first, replacement.second);
+ assembly = &replacedAssembly;
+ }
+
+ unsigned startStackHeight = stackHeight();
+ auto identifierAccess = [&](
+ assembly::Identifier const& _identifier,
+ eth::Assembly& _assembly,
+ assembly::CodeGenerator::IdentifierContext _context
+ ) {
+ auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name);
+ if (it == _localVariables.end())
+ return false;
+ unsigned stackDepth = _localVariables.end() - it;
+ int stackDiff = _assembly.deposit() - startStackHeight + stackDepth;
+ if (stackDiff < 1 || stackDiff > 16)
+ BOOST_THROW_EXCEPTION(
+ CompilerError() <<
+ errinfo_comment("Stack too deep, try removing local variables.")
+ );
+ if (_context == assembly::CodeGenerator::IdentifierContext::RValue)
+ _assembly.append(dupInstruction(stackDiff));
+ else
+ {
+ _assembly.append(swapInstruction(stackDiff));
+ _assembly.append(Instruction::POP);
+ }
+ return true;
+ };
+
+ solAssert(assembly::InlineAssemblyStack().parseAndAssemble(*assembly, m_asm, identifierAccess), "");
+}
+
void CompilerContext::injectVersionStampIntoSub(size_t _subIndex)
{
eth::Assembly& sub = m_asm.sub(_subIndex);
diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h
index a56335ce..0c1500b0 100644
--- a/libsolidity/codegen/CompilerContext.h
+++ b/libsolidity/codegen/CompilerContext.h
@@ -132,6 +132,15 @@ public:
CompilerContext& operator<<(u256 const& _value) { m_asm.append(_value); return *this; }
CompilerContext& operator<<(bytes const& _data) { m_asm.append(_data); return *this; }
+ /// Appends inline assembly. @a _replacements are string-matching replacements that are performed
+ /// prior to parsing the inline assembly.
+ /// @param _localVariables assigns stack positions to variables with the last one being the stack top
+ void appendInlineAssembly(
+ std::string const& _assembly,
+ std::vector<std::string> const& _localVariables = std::vector<std::string>(),
+ std::map<std::string, std::string> const& _replacements = std::map<std::string, std::string>{}
+ );
+
/// Prepends "PUSH <compiler version number> POP"
void injectVersionStampIntoSub(size_t _subIndex);
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index 3fbf27ce..41c14517 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -23,6 +23,7 @@
#include <utility>
#include <numeric>
#include <boost/range/adaptor/reversed.hpp>
+#include <boost/algorithm/string/replace.hpp>
#include <libdevcore/Common.h>
#include <libdevcore/SHA3.h>
#include <libsolidity/ast/AST.h>