diff options
-rw-r--r-- | Compiler.cpp | 13 | ||||
-rw-r--r-- | Compiler.h | 2 | ||||
-rw-r--r-- | CompilerContext.h | 4 | ||||
-rw-r--r-- | CompilerStack.cpp | 49 | ||||
-rw-r--r-- | CompilerStack.h | 43 | ||||
-rw-r--r-- | Scanner.cpp | 5 | ||||
-rw-r--r-- | Scanner.h | 3 |
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) @@ -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; @@ -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); |