From b804ef818a07d53faa3b3cdeca6914a5871cc8a9 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 20 Feb 2015 21:59:21 +0100 Subject: [PATCH] Add EVMJIT. --- All.h | 6 - CMakeLists.txt | 32 --- CodeFragment.cpp | 581 ---------------------------------------------- CodeFragment.h | 64 ----- Compiler.cpp | 95 -------- Compiler.h | 38 --- CompilerState.cpp | 82 ------- CompilerState.h | 57 ----- Exceptions.h | 44 ---- Parser.cpp | 145 ------------ Parser.h | 41 ---- 11 files changed, 1185 deletions(-) delete mode 100644 All.h delete mode 100644 CMakeLists.txt delete mode 100644 CodeFragment.cpp delete mode 100644 CodeFragment.h delete mode 100644 Compiler.cpp delete mode 100644 Compiler.h delete mode 100644 CompilerState.cpp delete mode 100644 CompilerState.h delete mode 100644 Exceptions.h delete mode 100644 Parser.cpp delete mode 100644 Parser.h diff --git a/All.h b/All.h deleted file mode 100644 index 7c4192f62..000000000 --- a/All.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include "CodeFragment.h" -#include "Compiler.h" -#include "CompilerState.h" -#include "Parser.h" diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 3b9dc6030..000000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -cmake_policy(SET CMP0015 NEW) -# this policy was introduced in cmake 3.0 -# remove if, once 3.0 will be used on unix -if (${CMAKE_MAJOR_VERSION} GREATER 2) - # old policy do not use MACOSX_RPATH - cmake_policy(SET CMP0042 OLD) -endif() -set(CMAKE_AUTOMOC OFF) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") - -aux_source_directory(. SRC_LIST) - -include_directories(BEFORE ..) -include_directories(${Boost_INCLUDE_DIRS}) - -set(EXECUTABLE lll) - -file(GLOB HEADERS "*.h") - -if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif() - -target_link_libraries(${EXECUTABLE} evmcore) -target_link_libraries(${EXECUTABLE} devcore) - -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) -install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) - diff --git a/CodeFragment.cpp b/CodeFragment.cpp deleted file mode 100644 index 1e7766434..000000000 --- a/CodeFragment.cpp +++ /dev/null @@ -1,581 +0,0 @@ -/* - 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 . -*/ -/** @file CodeFragment.cpp - * @author Gav Wood - * @date 2014 - */ - -#include "CodeFragment.h" - -#include -#include -#include -#include -#include -#include "CompilerState.h" -#include "Parser.h" -using namespace std; -using namespace dev; -using namespace dev::eth; -namespace qi = boost::spirit::qi; -namespace px = boost::phoenix; -namespace sp = boost::spirit; - -void CodeFragment::finalise(CompilerState const& _cs) -{ - if (_cs.usedAlloc && _cs.vars.size() && !m_finalised) - { - m_finalised = true; - m_asm.injectStart(Instruction::MSTORE8); - m_asm.injectStart((u256)((_cs.vars.size() + 2) * 32) - 1); - m_asm.injectStart((u256)1); - } -} - -CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowASM) -{ -/* cdebug << "CodeFragment. Locals:"; - for (auto const& i: _s.defs) - cdebug << i.first << ":" << toHex(i.second.m_code); - cdebug << "Args:"; - for (auto const& i: _s.args) - cdebug << i.first << ":" << toHex(i.second.m_code); - cdebug << "Outers:"; - for (auto const& i: _s.outers) - cdebug << i.first << ":" << toHex(i.second.m_code); - debugOutAST(cout, _t); - cout << endl << flush; -*/ - switch (_t.which()) - { - case sp::utree_type::list_type: - constructOperation(_t, _s); - break; - case sp::utree_type::string_type: - { - auto sr = _t.get, sp::utree_type::string_type>>(); - string s(sr.begin(), sr.end()); - m_asm.append(s); - break; - } - case sp::utree_type::symbol_type: - { - auto sr = _t.get, sp::utree_type::symbol_type>>(); - string s(sr.begin(), sr.end()); - string us = boost::algorithm::to_upper_copy(s); - if (_allowASM && c_instructions.count(us)) - m_asm.append(c_instructions.at(us)); - else if (_s.defs.count(s)) - m_asm.append(_s.defs.at(s).m_asm); - else if (_s.args.count(s)) - m_asm.append(_s.args.at(s).m_asm); - else if (_s.outers.count(s)) - m_asm.append(_s.outers.at(s).m_asm); - else if (us.find_first_of("1234567890") != 0 && us.find_first_not_of("QWERTYUIOPASDFGHJKLZXCVBNM1234567890_") == string::npos) - { - auto it = _s.vars.find(s); - if (it == _s.vars.end()) - { - bool ok; - tie(it, ok) = _s.vars.insert(make_pair(s, make_pair(_s.stackSize, 32))); - _s.stackSize += 32; - } - m_asm.append((u256)it->second.first); - } - else - error(); - - break; - } - case sp::utree_type::any_type: - { - bigint i = *_t.get(); - if (i < 0 || i > bigint(u256(0) - 1)) - error(); - m_asm.append((u256)i); - break; - } - default: break; - } -} - -void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) -{ - if (_t.tag() == 0 && _t.empty()) - error(); - else if (_t.tag() == 0 && _t.front().which() != sp::utree_type::symbol_type) - error(); - else - { - string s; - string us; - switch (_t.tag()) - { - case 0: - { - auto sr = _t.front().get, sp::utree_type::symbol_type>>(); - s = string(sr.begin(), sr.end()); - us = boost::algorithm::to_upper_copy(s); - break; - } - case 1: - us = "MLOAD"; - break; - case 2: - us = "SLOAD"; - break; - case 3: - us = "MSTORE"; - break; - case 4: - us = "SSTORE"; - break; - case 5: - us = "SEQ"; - break; - case 6: - us = "CALLDATALOAD"; - break; - default:; - } - - auto firstAsString = [&]() - { - auto i = *++_t.begin(); - if (i.tag()) - error(); - if (i.which() == sp::utree_type::string_type) - { - auto sr = i.get, sp::utree_type::string_type>>(); - return string(sr.begin(), sr.end()); - } - else if (i.which() == sp::utree_type::symbol_type) - { - auto sr = i.get, sp::utree_type::symbol_type>>(); - return _s.getDef(string(sr.begin(), sr.end())).m_asm.backString(); - } - return string(); - }; - - auto varAddress = [&](string const& n) - { - auto it = _s.vars.find(n); - if (it == _s.vars.end()) - { - bool ok; - tie(it, ok) = _s.vars.insert(make_pair(n, make_pair(_s.stackSize, 32))); - _s.stackSize += 32; - } - return it->second.first; - }; - - // Operations who args are not standard stack-pushers. - bool nonStandard = true; - if (us == "ASM") - { - int c = 0; - for (auto const& i: _t) - if (c++) - m_asm.append(CodeFragment(i, _s, true).m_asm); - } - else if (us == "INCLUDE") - { - if (_t.size() != 2) - error(); - m_asm.append(CodeFragment::compile(asString(contents(firstAsString())), _s).m_asm); - } - else if (us == "SET") - { - if (_t.size() != 3) - error(); - int c = 0; - for (auto const& i: _t) - if (c++ == 2) - m_asm.append(CodeFragment(i, _s, false).m_asm); - m_asm.append((u256)varAddress(firstAsString())); - m_asm.append(Instruction::MSTORE); - } - else if (us == "GET") - { - if (_t.size() != 2) - error(); - m_asm.append((u256)varAddress(firstAsString())); - m_asm.append(Instruction::MLOAD); - } - else if (us == "REF") - m_asm.append((u256)varAddress(firstAsString())); - else if (us == "DEF") - { - string n; - unsigned ii = 0; - if (_t.size() != 3 && _t.size() != 4) - error(); - vector args; - for (auto const& i: _t) - { - if (ii == 1) - { - if (i.tag()) - error(); - if (i.which() == sp::utree_type::string_type) - { - auto sr = i.get, sp::utree_type::string_type>>(); - n = string(sr.begin(), sr.end()); - } - else if (i.which() == sp::utree_type::symbol_type) - { - auto sr = i.get, sp::utree_type::symbol_type>>(); - n = _s.getDef(string(sr.begin(), sr.end())).m_asm.backString(); - } - } - else if (ii == 2) - if (_t.size() == 3) - _s.defs[n] = CodeFragment(i, _s); - else - for (auto const& j: i) - { - if (j.tag() || j.which() != sp::utree_type::symbol_type) - error(); - auto sr = j.get, sp::utree_type::symbol_type>>(); - args.push_back(string(sr.begin(), sr.end())); - } - else if (ii == 3) - { - auto k = make_pair(n, args.size()); - _s.macros[k].code = i; - _s.macros[k].env = _s.outers; - _s.macros[k].args = args; - for (auto const& i: _s.args) - _s.macros[k].env[i.first] = i.second; - for (auto const& i: _s.defs) - _s.macros[k].env[i.first] = i.second; - } - ++ii; - } - } - else if (us == "LIT") - { - if (_t.size() < 3) - error(); - unsigned ii = 0; - CodeFragment pos; - bytes data; - for (auto const& i: _t) - { - if (ii == 1) - { - pos = CodeFragment(i, _s); - if (pos.m_asm.deposit() != 1) - error(); - } - else if (ii == 2 && !i.tag() && i.which() == sp::utree_type::string_type) - { - auto sr = i.get, sp::utree_type::string_type>>(); - data = bytes((byte const*)sr.begin(), (byte const*)sr.end()); - } - else if (ii >= 2 && !i.tag() && i.which() == sp::utree_type::any_type) - { - bigint bi = *i.get(); - if (bi < 0) - error(); - else if (bi > bigint(u256(0) - 1)) - { - if (ii == 2 && _t.size() == 3) - { - // One big int - allow it as hex. - data.resize(bytesRequired(bi)); - toBigEndian(bi, data); - } - else - error(); - } - else - { - data.resize(data.size() + 32); - *(h256*)(&data.back() - 31) = (u256)bi; - } - } - else if (ii) - error(); - ++ii; - } - m_asm.append((u256)data.size()); - m_asm.append(Instruction::DUP1); - m_asm.append(data); - m_asm.append(pos.m_asm, 1); - m_asm.append(Instruction::CODECOPY); - } - else - nonStandard = false; - - if (nonStandard) - return; - - std::map const c_arith = { { "+", Instruction::ADD }, { "-", Instruction::SUB }, { "*", Instruction::MUL }, { "/", Instruction::DIV }, { "%", Instruction::MOD }, { "&", Instruction::AND }, { "|", Instruction::OR }, { "^", Instruction::XOR } }; - std::map> const c_binary = { { "<", { Instruction::LT, false } }, { "<=", { Instruction::GT, true } }, { ">", { Instruction::GT, false } }, { ">=", { Instruction::LT, true } }, { "S<", { Instruction::SLT, false } }, { "S<=", { Instruction::SGT, true } }, { "S>", { Instruction::SGT, false } }, { "S>=", { Instruction::SLT, true } }, { "=", { Instruction::EQ, false } }, { "!=", { Instruction::EQ, true } } }; - std::map const c_unary = { { "!", Instruction::ISZERO } }; - - vector code; - CompilerState ns = _s; - ns.vars.clear(); - ns.usedAlloc = false; - int c = _t.tag() ? 1 : 0; - for (auto const& i: _t) - if (c++) - { - if (us == "LLL" && c == 1) - code.push_back(CodeFragment(i, ns)); - else - code.push_back(CodeFragment(i, _s)); - } - auto requireSize = [&](unsigned s) { if (code.size() != s) error(); }; - auto requireMinSize = [&](unsigned s) { if (code.size() < s) error(); }; - auto requireMaxSize = [&](unsigned s) { if (code.size() > s) error(); }; - auto requireDeposit = [&](unsigned i, int s) { if (code[i].m_asm.deposit() != s) error(); }; - - if (_s.macros.count(make_pair(s, code.size()))) - { - Macro const& m = _s.macros.at(make_pair(s, code.size())); - CompilerState cs = _s; - for (auto const& i: m.env) - cs.outers[i.first] = i.second; - for (auto const& i: cs.defs) - cs.outers[i.first] = i.second; - cs.defs.clear(); - for (unsigned i = 0; i < m.args.size(); ++i) - { - //requireDeposit(i, 1); - cs.args[m.args[i]] = code[i]; - } - m_asm.append(CodeFragment(m.code, cs).m_asm); - for (auto const& i: cs.defs) - _s.defs[i.first] = i.second; - for (auto const& i: cs.macros) - _s.macros.insert(i); - } - else if (c_instructions.count(us)) - { - auto it = c_instructions.find(us); - int ea = instructionInfo(it->second).args; - if (ea >= 0) - requireSize(ea); - else - requireMinSize(-ea); - - for (unsigned i = code.size(); i; --i) - m_asm.append(code[i - 1].m_asm, 1); - m_asm.append(it->second); - } - else if (c_arith.count(us)) - { - auto it = c_arith.find(us); - requireMinSize(1); - for (unsigned i = code.size(); i; --i) - { - requireDeposit(i - 1, 1); - m_asm.append(code[i - 1].m_asm, 1); - } - for (unsigned i = 1; i < code.size(); ++i) - m_asm.append(it->second); - } - else if (c_binary.count(us)) - { - auto it = c_binary.find(us); - requireSize(2); - requireDeposit(0, 1); - requireDeposit(1, 1); - m_asm.append(code[1].m_asm, 1); - m_asm.append(code[0].m_asm, 1); - m_asm.append(it->second.first); - if (it->second.second) - m_asm.append(Instruction::ISZERO); - } - else if (c_unary.count(us)) - { - auto it = c_unary.find(us); - requireSize(1); - requireDeposit(0, 1); - m_asm.append(code[0].m_asm, 1); - m_asm.append(it->second); - } - else if (us == "IF") - { - requireSize(3); - requireDeposit(0, 1); - int minDep = min(code[1].m_asm.deposit(), code[2].m_asm.deposit()); - - m_asm.append(code[0].m_asm); - auto pos = m_asm.appendJumpI(); - m_asm.onePath(); - m_asm.append(code[2].m_asm, minDep); - auto end = m_asm.appendJump(); - m_asm.otherPath(); - m_asm << pos.tag(); - m_asm.append(code[1].m_asm, minDep); - m_asm << end.tag(); - m_asm.donePaths(); - } - else if (us == "WHEN" || us == "UNLESS") - { - requireSize(2); - requireDeposit(0, 1); - - m_asm.append(code[0].m_asm); - if (us == "WHEN") - m_asm.append(Instruction::ISZERO); - auto end = m_asm.appendJumpI(); - m_asm.onePath(); - m_asm.otherPath(); - m_asm.append(code[1].m_asm, 0); - m_asm << end.tag(); - m_asm.donePaths(); - } - else if (us == "WHILE") - { - requireSize(2); - requireDeposit(0, 1); - - auto begin = m_asm.append(); - m_asm.append(code[0].m_asm); - m_asm.append(Instruction::ISZERO); - auto end = m_asm.appendJumpI(); - m_asm.append(code[1].m_asm, 0); - m_asm.appendJump(begin); - m_asm << end.tag(); - } - else if (us == "FOR") - { - requireSize(4); - requireDeposit(1, 1); - - m_asm.append(code[0].m_asm, 0); - auto begin = m_asm.append(); - m_asm.append(code[1].m_asm); - m_asm.append(Instruction::ISZERO); - auto end = m_asm.appendJumpI(); - m_asm.append(code[3].m_asm, 0); - m_asm.append(code[2].m_asm, 0); - m_asm.appendJump(begin); - m_asm << end.tag(); - } - else if (us == "ALLOC") - { - requireSize(1); - requireDeposit(0, 1); - - m_asm.append(Instruction::MSIZE); - m_asm.append(u256(0)); - m_asm.append(u256(1)); - m_asm.append(code[0].m_asm, 1); - m_asm.append(Instruction::MSIZE); - m_asm.append(Instruction::ADD); - m_asm.append(Instruction::SUB); - m_asm.append(Instruction::MSTORE8); - - _s.usedAlloc = true; - } - else if (us == "LLL") - { - requireMinSize(2); - requireMaxSize(3); - requireDeposit(1, 1); - - auto subPush = m_asm.appendSubSize(code[0].assembly(ns)); - m_asm.append(Instruction::DUP1); - if (code.size() == 3) - { - requireDeposit(2, 1); - m_asm.append(code[2].m_asm, 1); - m_asm.append(Instruction::LT); - m_asm.append(Instruction::ISZERO); - m_asm.append(Instruction::MUL); - m_asm.append(Instruction::DUP1); - } - m_asm.append(subPush); - m_asm.append(code[1].m_asm, 1); - m_asm.append(Instruction::CODECOPY); - } - else if (us == "&&" || us == "||") - { - requireMinSize(1); - for (unsigned i = 0; i < code.size(); ++i) - requireDeposit(i, 1); - - auto end = m_asm.newTag(); - if (code.size() > 1) - { - m_asm.append((u256)(us == "||" ? 1 : 0)); - for (unsigned i = 1; i < code.size(); ++i) - { - // Check if true - predicate - m_asm.append(code[i - 1].m_asm, 1); - if (us == "&&") - m_asm.append(Instruction::ISZERO); - m_asm.appendJumpI(end); - } - m_asm.append(Instruction::POP); - } - - // Check if true - predicate - m_asm.append(code.back().m_asm, 1); - - // At end now. - m_asm.append(end); - } - else if (us == "~") - { - requireSize(1); - requireDeposit(0, 1); - - m_asm.append(code[0].m_asm, 1); - m_asm.append((u256)1); - m_asm.append((u256)0); - m_asm.append(Instruction::SUB); - m_asm.append(Instruction::SUB); - } - else if (us == "SEQ") - { - unsigned ii = 0; - for (auto const& i: code) - if (++ii < code.size()) - m_asm.append(i.m_asm, 0); - else - m_asm.append(i.m_asm); - } - else if (us == "RAW") - { - for (auto const& i: code) - m_asm.append(i.m_asm); - m_asm.popTo(1); - } - else if (us.find_first_of("1234567890") != 0 && us.find_first_not_of("QWERTYUIOPASDFGHJKLZXCVBNM1234567890_") == string::npos) - m_asm.append((u256)varAddress(s)); - else - error(); - } -} - -CodeFragment CodeFragment::compile(string const& _src, CompilerState& _s) -{ - CodeFragment ret; - sp::utree o; - parseTreeLLL(_src, o); - if (!o.empty()) - ret = CodeFragment(o, _s); - _s.treesToKill.push_back(o); - return ret; -} diff --git a/CodeFragment.h b/CodeFragment.h deleted file mode 100644 index 554f90b46..000000000 --- a/CodeFragment.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - 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 . -*/ -/** @file CodeFragment.h - * @author Gav Wood - * @date 2014 - */ - -#pragma once - -#include -#include -#include -#include "Exceptions.h" - -namespace boost { namespace spirit { class utree; } } -namespace sp = boost::spirit; - -namespace dev -{ -namespace eth -{ - -struct CompilerState; - -class CodeFragment -{ -public: - CodeFragment() {} - CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowASM = false); - - static CodeFragment compile(std::string const& _src, CompilerState& _s); - - /// Consolidates data and compiles code. - Assembly& assembly(CompilerState const& _cs) { finalise(_cs); return m_asm; } - -private: - void finalise(CompilerState const& _cs); - - template void error() const { BOOST_THROW_EXCEPTION(T() ); } - void constructOperation(sp::utree const& _t, CompilerState& _s); - - bool m_finalised = false; - Assembly m_asm; -}; - -static const CodeFragment NullCodeFragment; - -} -} - diff --git a/Compiler.cpp b/Compiler.cpp deleted file mode 100644 index 37fb3c340..000000000 --- a/Compiler.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - 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 . -*/ -/** @file Compiler.cpp - * @author Gav Wood - * @date 2014 - */ - -#include "Compiler.h" -#include "Parser.h" -#include "CompilerState.h" -#include "CodeFragment.h" - -using namespace std; -using namespace dev; -using namespace dev::eth; - -bytes dev::eth::compileLLL(string const& _src, bool _opt, vector* _errors) -{ - try - { - CompilerState cs; - cs.populateStandard(); - auto f = CodeFragment::compile(_src, cs); - bytes ret = f.assembly(cs).optimise(_opt).assemble(); - for (auto i: cs.treesToKill) - killBigints(i); - return ret; - } - catch (Exception const& _e) - { - if (_errors) - { - _errors->push_back("Parse error."); - _errors->push_back(diagnostic_information(_e)); - } - } - catch (std::exception) - { - if (_errors) - _errors->push_back("Parse error."); - } - return bytes(); -} - -std::string dev::eth::compileLLLToAsm(std::string const& _src, bool _opt, std::vector* _errors) -{ - try - { - CompilerState cs; - cs.populateStandard(); - string ret = CodeFragment::compile(_src, cs).assembly(cs).optimise(_opt).out(); - for (auto i: cs.treesToKill) - killBigints(i); - return ret; - } - catch (Exception const& _e) - { - if (_errors) - _errors->push_back(diagnostic_information(_e)); - } - catch (std::exception) - { - if (_errors) - _errors->push_back("Parse error."); - } - return string(); -} - -string dev::eth::parseLLL(string const& _src) -{ - sp::utree o; - try - { - parseTreeLLL(_src, o); - } - catch (...) {} - ostringstream ret; - debugOutAST(ret, o); - killBigints(o); - return ret.str(); -} diff --git a/Compiler.h b/Compiler.h deleted file mode 100644 index 0fadd2785..000000000 --- a/Compiler.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - 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 . -*/ -/** @file Compiler.h - * @author Gav Wood - * @date 2014 - */ - -#pragma once - -#include -#include -#include - -namespace dev -{ -namespace eth -{ - -std::string parseLLL(std::string const& _src); -std::string compileLLLToAsm(std::string const& _src, bool _opt = true, std::vector* _errors = nullptr); -bytes compileLLL(std::string const& _src, bool _opt = true, std::vector* _errors = nullptr); - -} -} diff --git a/CompilerState.cpp b/CompilerState.cpp deleted file mode 100644 index 63351bc4c..000000000 --- a/CompilerState.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - 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 . -*/ -/** @file CompilerState.cpp - * @author Gav Wood - * @date 2014 - */ - -#include "CompilerState.h" -#include "CodeFragment.h" - -using namespace std; -using namespace dev; -using namespace dev::eth; - -CompilerState::CompilerState() -{ -} - -CodeFragment const& CompilerState::getDef(std::string const& _s) -{ - if (defs.count(_s)) - return defs.at(_s); - else if (args.count(_s)) - return args.at(_s); - else if (outers.count(_s)) - return outers.at(_s); - else - return NullCodeFragment; -} - -void CompilerState::populateStandard() -{ - static const string s = "{" - "(def 'gav 0x51ba59315b3a95761d0863b05ccc7a7f54703d99)" - "(def 'config 0x661005d2720d855f1d9976f88bb10c1a3398c77f)" - "(def 'allgas (- (gas) 21))" - "(def 'send (to value) (call allgas to value 0 0 0 0))" - "(def 'send (gaslimit to value) (call gaslimit to value 0 0 0 0))" - "(def 'msg (gaslimit to value data datasize outsize) { (set x outsize) (set y (alloc @32)) (call gaslimit to value data datasize @0 @32) @0 })" - "(def 'msg (gaslimit to value data datasize) { (call gaslimit to value data datasize 0 32) @0 })" - "(def 'msg (gaslimit to value data) { [0]:data (msg gaslimit to value 0 32) })" - "(def 'msg (to value data) { [0]:data (msg allgas to value 0 32) })" - "(def 'msg (to data) { [0]:data (msg allgas to 0 0 32) })" - "(def 'create (value code) { [0]:(msize) (create value @0 (lll code @0)) })" - "(def 'create (code) { [0]:(msize) (create 0 @0 (lll code @0)) })" - "(def 'sha3 (val) { [0]:val (sha3 0 32) })" - "(def 'sha3pair (a b) { [0]:a [32]:b (sha3 0 64) })" - "(def 'sha3trip (a b c) { [0]:a [32]:b [64]:c (sha3 0 96) })" - "(def 'return (val) { [0]:val (return 0 32) })" - "(def 'returnlll (code) (return 0 (lll code 0)) )" - "(def 'makeperm (name pos) { (def name (sload pos)) (def name (v) (sstore pos v)) } )" - "(def 'permcount 0)" - "(def 'perm (name) { (makeperm name permcount) (def 'permcount (+ permcount 1)) } )" - "(def 'namereg (msg config 0))" - "(def 'coinreg (msg config 1))" - "(def 'gavcoin (msg config 2))" - "(def 'sendgavcoin (to value) { [32]'send [64]:to [96]:value (call allgas gavcoin 0 32 96 0 0) })" - "(def 'regname (name) { [32]'register [64]name (call allgas namereg 0 32 64 0 0) })" - "(def 'regcoin (name) { [32]name (call allgas coinreg 0 32 32 0 0) })" - "(def 'regcoin (name denom) { [32]name [64]denom (call allgas coinreg 0 32 64 0 0) })" - "(def 'ecrecover (r s v hash) { [0] r [32] s [64] v [96] hash (msg allgas 1 0 0 128) })" - "(def 'sha256 (data datasize) (msg allgas 2 0 data datasize))" - "(def 'ripemd160 (data datasize) (msg allgas 3 0 data datasize))" - "(def 'sha256 (val) { [0]:val (sha256 0 32) })" - "(def 'ripemd160 (val) { [0]:val (ripemd160 0 32) })" - "}"; - CodeFragment::compile(s, *this); -} diff --git a/CompilerState.h b/CompilerState.h deleted file mode 100644 index bfe56f927..000000000 --- a/CompilerState.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - 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 . -*/ -/** @file CompilerState.h - * @author Gav Wood - * @date 2014 - */ - -#pragma once - -#include -#include "CodeFragment.h" - -namespace dev -{ -namespace eth -{ - -struct Macro -{ - std::vector args; - boost::spirit::utree code; - std::map env; -}; - -struct CompilerState -{ - CompilerState(); - - CodeFragment const& getDef(std::string const& _s); - void populateStandard(); - - unsigned stackSize = 128; - std::map> vars; ///< maps name to stack offset & size. - std::map defs; - std::map args; - std::map outers; - std::map, Macro> macros; - std::vector treesToKill; - bool usedAlloc = false; -}; - -} -} diff --git a/Exceptions.h b/Exceptions.h deleted file mode 100644 index 1e9671b36..000000000 --- a/Exceptions.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - 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 . -*/ -/** @file Exceptions.h - * @author Gav Wood - * @date 2014 - */ - -#pragma once - -#include - -namespace dev -{ -namespace eth -{ - -/// Compile a Low-level Lisp-like Language program into EVM-code. -class CompilerException: public dev::Exception {}; -class InvalidOperation: public CompilerException {}; -class IntegerOutOfRange: public CompilerException {}; -class EmptyList: public CompilerException {}; -class DataNotExecutable: public CompilerException {}; -class IncorrectParameterCount: public CompilerException {}; -class InvalidName: public CompilerException {}; -class InvalidMacroArgs: public CompilerException {}; -class InvalidLiteral: public CompilerException {}; -class BareSymbol: public CompilerException {}; - -} -} diff --git a/Parser.cpp b/Parser.cpp deleted file mode 100644 index df30f3897..000000000 --- a/Parser.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - 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 . -*/ -/** @file Parser.cpp - * @author Gav Wood - * @date 2014 - */ - -#include "Parser.h" - -#define BOOST_RESULT_OF_USE_DECLTYPE -#define BOOST_SPIRIT_USE_PHOENIX_V3 -#include -#include -#include - -using namespace std; -using namespace dev; -using namespace dev::eth; -namespace qi = boost::spirit::qi; -namespace px = boost::phoenix; -namespace sp = boost::spirit; - -void dev::eth::killBigints(sp::utree const& _this) -{ - switch (_this.which()) - { - case sp::utree_type::list_type: for (auto const& i: _this) killBigints(i); break; - case sp::utree_type::any_type: delete _this.get(); break; - default:; - } -} - -void dev::eth::debugOutAST(ostream& _out, sp::utree const& _this) -{ - switch (_this.which()) - { - case sp::utree_type::list_type: - switch (_this.tag()) - { - case 0: _out << "( "; for (auto const& i: _this) { debugOutAST(_out, i); _out << " "; } _out << ")"; break; - case 1: _out << "@ "; debugOutAST(_out, _this.front()); break; - case 2: _out << "@@ "; debugOutAST(_out, _this.front()); break; - case 3: _out << "[ "; debugOutAST(_out, _this.front()); _out << " ] "; debugOutAST(_out, _this.back()); break; - case 4: _out << "[[ "; debugOutAST(_out, _this.front()); _out << " ]] "; debugOutAST(_out, _this.back()); break; - case 5: _out << "{ "; for (auto const& i: _this) { debugOutAST(_out, i); _out << " "; } _out << "}"; break; - case 6: _out << "$ "; debugOutAST(_out, _this.front()); break; - default:; - } - - break; - case sp::utree_type::int_type: _out << _this.get(); break; - case sp::utree_type::string_type: _out << "\"" << _this.get, sp::utree_type::string_type>>() << "\""; break; - case sp::utree_type::symbol_type: _out << _this.get, sp::utree_type::symbol_type>>(); break; - case sp::utree_type::any_type: _out << *_this.get(); break; - default: _out << "nil"; - } -} - -namespace dev { namespace eth { -namespace parseTreeLLL_ { - -template -struct tagNode -{ - void operator()(sp::utree& n, qi::rule::context_type& c) const - { - (boost::fusion::at_c<0>(c.attributes) = n).tag(N); - } -}; - -}}} - -void dev::eth::parseTreeLLL(string const& _s, sp::utree& o_out) -{ - using qi::standard::space; - using qi::standard::space_type; - using dev::eth::parseTreeLLL_::tagNode; - using symbol_type = sp::basic_string; - using it = string::const_iterator; - - static const u256 ether = u256(1000000000) * 1000000000; - static const u256 finney = u256(1000000000) * 1000000; - static const u256 szabo = u256(1000000000) * 1000; - - qi::rule element; - qi::rule str = '"' > qi::lexeme[+(~qi::char_(std::string("\"") + '\0'))] > '"'; - qi::rule strsh = '\'' > qi::lexeme[+(~qi::char_(std::string(" ;$@()[]{}:\n\t") + '\0'))]; - qi::rule symbol = qi::lexeme[+(~qi::char_(std::string(" $@[]{}:();\"\x01-\x1f\x7f") + '\0'))]; - qi::rule intstr = qi::lexeme[ qi::no_case["0x"][qi::_val = "0x"] >> *qi::char_("0-9a-fA-F")[qi::_val += qi::_1]] | qi::lexeme[+qi::char_("0-9")[qi::_val += qi::_1]]; - qi::rule integer = intstr; - qi::rule multiplier = qi::lit("wei")[qi::_val = 1] | qi::lit("szabo")[qi::_val = szabo] | qi::lit("finney")[qi::_val = finney] | qi::lit("ether")[qi::_val = ether]; - qi::rule quantity = integer[qi::_val = qi::_1] >> -multiplier[qi::_val *= qi::_1]; - qi::rule atom = quantity[qi::_val = px::construct(px::new_(qi::_1))] | (str | strsh)[qi::_val = qi::_1] | symbol[qi::_val = qi::_1]; - qi::rule seq = '{' > *element > '}'; - qi::rule mload = '@' > element; - qi::rule sload = qi::lit("@@") > element; - qi::rule mstore = '[' > element > ']' > -qi::lit(":") > element; - qi::rule sstore = qi::lit("[[") > element > qi::lit("]]") > -qi::lit(":") > element; - qi::rule calldataload = qi::lit("$") > element; - qi::rule list = '(' > *element > ')'; - - qi::rule extra = sload[tagNode<2>()] | mload[tagNode<1>()] | sstore[tagNode<4>()] | mstore[tagNode<3>()] | seq[tagNode<5>()] | calldataload[tagNode<6>()]; - element = atom | list | extra; - - string s; - s.reserve(_s.size()); - bool incomment = false; - bool instring = false; - bool insstring = false; - for (auto i: _s) - { - if (i == ';' && !instring && !insstring) - incomment = true; - else if (i == '\n') - incomment = instring = insstring = false; - else if (i == '"' && !insstring) - instring = !instring; - else if (i == '\'') - insstring = true; - else if (i == ' ') - insstring = false; - if (!incomment) - s.push_back(i); - } - auto ret = s.cbegin(); - qi::phrase_parse(ret, s.cend(), element, space, qi::skip_flag::dont_postskip, o_out); - for (auto i = ret; i != s.cend(); ++i) - if (!isspace(*i)) - BOOST_THROW_EXCEPTION(std::exception()); -} - diff --git a/Parser.h b/Parser.h deleted file mode 100644 index b21989f06..000000000 --- a/Parser.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - 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 . -*/ -/** @file Parser.h - * @author Gav Wood - * @date 2014 - */ - -#pragma once - -#include -#include -#include - -namespace boost { namespace spirit { class utree; } } -namespace sp = boost::spirit; - -namespace dev -{ -namespace eth -{ - -void killBigints(sp::utree const& _this); -void parseTreeLLL(std::string const& _s, sp::utree& o_out); -void debugOutAST(std::ostream& _out, sp::utree const& _this); - -} -}