aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Compiler.cpp13
-rw-r--r--Compiler.h2
-rw-r--r--CompilerContext.h4
-rw-r--r--CompilerStack.cpp49
-rw-r--r--CompilerStack.h43
-rw-r--r--Scanner.cpp5
-rw-r--r--Scanner.h3
7 files changed, 113 insertions, 6 deletions
diff --git a/Compiler.cpp b/Compiler.cpp
index 7e40db15..b1e3c3da 100644
--- a/Compiler.cpp
+++ b/Compiler.cpp
@@ -46,9 +46,22 @@ void Compiler::compileContract(ContractDefinition& _contract)
for (ASTPointer<FunctionDefinition> const& function: _contract.getDefinedFunctions())
m_context.addFunction(*function);
+
appendFunctionSelector(_contract.getDefinedFunctions());
for (ASTPointer<FunctionDefinition> const& function: _contract.getDefinedFunctions())
function->accept(*this);
+
+ packIntoContractCreator();
+}
+
+void Compiler::packIntoContractCreator()
+{
+ CompilerContext creatorContext;
+ eth::AssemblyItem sub = creatorContext.addSubroutine(m_context.getAssembly());
+ // stack contains sub size
+ creatorContext << eth::Instruction::DUP1 << sub << u256(0) << eth::Instruction::CODECOPY;
+ creatorContext << u256(0) << eth::Instruction::RETURN;
+ swap(m_context, creatorContext);
}
void Compiler::appendFunctionSelector(vector<ASTPointer<FunctionDefinition>> const& _functions)
diff --git a/Compiler.h b/Compiler.h
index ebd78665..d10374a9 100644
--- a/Compiler.h
+++ b/Compiler.h
@@ -40,6 +40,8 @@ public:
static bytes compile(ContractDefinition& _contract);
private:
+ /// Creates a new compiler context / assembly and packs the current code into the data part.
+ void packIntoContractCreator();
void appendFunctionSelector(std::vector<ASTPointer<FunctionDefinition> > const& _functions);
void appendFunctionCallSection(FunctionDefinition const& _function);
void appendCalldataUnpacker(FunctionDefinition const& _function);
diff --git a/CompilerContext.h b/CompilerContext.h
index cce5838e..46c4c72a 100644
--- a/CompilerContext.h
+++ b/CompilerContext.h
@@ -63,6 +63,9 @@ public:
eth::AssemblyItem pushNewTag() { return m_asm.append(m_asm.newPushTag()).tag(); }
/// @returns a new tag without pushing any opcodes or data
eth::AssemblyItem newTag() { return m_asm.newTag(); }
+ /// Adds a subroutine to the code (in the data section) and pushes its size (via a tag)
+ /// on the stack. @returns the assembly item corresponding to the pushed subroutine, i.e. its offset.
+ eth::AssemblyItem addSubroutine(eth::Assembly const& _assembly) { return m_asm.appendSubSize(_assembly); }
/// Append elements to the current instruction list and adjust @a m_stackOffset.
CompilerContext& operator<<(eth::AssemblyItem const& _item) { m_asm.append(_item); return *this; }
@@ -70,6 +73,7 @@ public:
CompilerContext& operator<<(u256 const& _value) { m_asm.append(_value); return *this; }
CompilerContext& operator<<(bytes const& _data) { m_asm.append(_data); return *this; }
+ eth::Assembly const& getAssembly() const { return m_asm; }
void streamAssembly(std::ostream& _stream) const { _stream << m_asm; }
bytes getAssembledBytecode() const { return m_asm.assemble(); }
private:
diff --git a/CompilerStack.cpp b/CompilerStack.cpp
new file mode 100644
index 00000000..bbd693ae
--- /dev/null
+++ b/CompilerStack.cpp
@@ -0,0 +1,49 @@
+/*
+ This file is part of cpp-ethereum.
+
+ cpp-ethereum is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ cpp-ethereum is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @author Christian <c@ethdev.com>
+ * @date 2014
+ * Full-stack compiler that converts a source code string to bytecode.
+ */
+
+#include <libsolidity/AST.h>
+#include <libsolidity/Scanner.h>
+#include <libsolidity/Parser.h>
+#include <libsolidity/NameAndTypeResolver.h>
+#include <libsolidity/Compiler.h>
+#include <libsolidity/CompilerStack.h>
+
+using namespace std;
+
+namespace dev
+{
+namespace solidity
+{
+
+bytes CompilerStack::compile(std::string const& _sourceCode, shared_ptr<Scanner> _scanner)
+{
+ if (!_scanner)
+ _scanner = make_shared<Scanner>();
+ _scanner->reset(CharStream(_sourceCode));
+
+ ASTPointer<ContractDefinition> contract = Parser().parse(_scanner);
+ NameAndTypeResolver().resolveNamesAndTypes(*contract);
+ return Compiler::compile(*contract);
+}
+
+}
+}
diff --git a/CompilerStack.h b/CompilerStack.h
new file mode 100644
index 00000000..9f3f81c0
--- /dev/null
+++ b/CompilerStack.h
@@ -0,0 +1,43 @@
+/*
+ This file is part of cpp-ethereum.
+
+ cpp-ethereum is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ cpp-ethereum is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @author Christian <c@ethdev.com>
+ * @date 2014
+ * Full-stack compiler that converts a source code string to bytecode.
+ */
+
+#pragma once
+
+#include <string>
+#include <memory>
+#include <libdevcore/Common.h>
+
+namespace dev {
+namespace solidity {
+
+class Scanner; // forward
+
+class CompilerStack
+{
+public:
+ /// Compile the given @a _sourceCode to bytecode. If a scanner is provided, it is used for
+ /// scanning the source code - this is useful for printing exception information.
+ static bytes compile(std::string const& _sourceCode, std::shared_ptr<Scanner> _scanner = std::shared_ptr<Scanner>());
+};
+
+}
+}
diff --git a/Scanner.cpp b/Scanner.cpp
index 3148de52..d8defb50 100644
--- a/Scanner.cpp
+++ b/Scanner.cpp
@@ -103,11 +103,6 @@ int HexValue(char c)
}
} // end anonymous namespace
-Scanner::Scanner(CharStream const& _source)
-{
- reset(_source);
-}
-
void Scanner::reset(CharStream const& _source)
{
m_source = _source;
diff --git a/Scanner.h b/Scanner.h
index fbaba9ed..7754d71b 100644
--- a/Scanner.h
+++ b/Scanner.h
@@ -110,7 +110,8 @@ public:
bool complete_;
};
- explicit Scanner(CharStream const& _source);
+ Scanner() { reset(CharStream()); }
+ explicit Scanner(CharStream const& _source) { reset(_source); }
/// Resets the scanner as if newly constructed with _input as input.
void reset(CharStream const& _source);