diff options
author | Gav Wood <i@gavwood.com> | 2014-05-27 01:41:46 +0800 |
---|---|---|
committer | Gav Wood <i@gavwood.com> | 2014-05-27 01:41:46 +0800 |
commit | 51e6c251641eef12ba93b725974faa35b514d636 (patch) | |
tree | 9113f63687347c7d5a61c5bb2db61ffe4d800da4 /Assembly.h | |
parent | 8e3e592ec6a3b39835e540766774025e3f34c590 (diff) | |
download | dexon-solidity-51e6c251641eef12ba93b725974faa35b514d636.tar.gz dexon-solidity-51e6c251641eef12ba93b725974faa35b514d636.tar.zst dexon-solidity-51e6c251641eef12ba93b725974faa35b514d636.zip |
New Assembler.
Diffstat (limited to 'Assembly.h')
-rw-r--r-- | Assembly.h | 54 |
1 files changed, 48 insertions, 6 deletions
@@ -22,6 +22,7 @@ #pragma once #include <iostream> +#include <sstream> #include <libethsupport/Common.h> #include <libethcore/Instruction.h> #include "Exceptions.h" @@ -39,14 +40,16 @@ class AssemblyItem public: AssemblyItem(u256 _push): m_type(Push), m_data(_push) {} - AssemblyItem(AssemblyItemType _type, AssemblyItem const& _tag): m_type(_type), m_data(_tag.m_data) { assert(_type == PushTag); assert(_tag.m_type == Tag); } AssemblyItem(Instruction _i): m_type(Operation), m_data((byte)_i) {} AssemblyItem(AssemblyItemType _type, u256 _data): m_type(_type), m_data(_data) {} + AssemblyItem tag() const { assert(m_type == PushTag || m_type == Tag); return AssemblyItem(Tag, m_data); } + AssemblyItem pushTag() const { assert(m_type == PushTag || m_type == Tag); return AssemblyItem(PushTag, m_data); } + AssemblyItemType type() const { return m_type; } u256 data() const { return m_data; } - std::ostream& streamOut(std::ostream& _out) const; + int deposit() const; private: AssemblyItemType m_type; @@ -57,19 +60,58 @@ class Assembly { public: AssemblyItem newTag() { return AssemblyItem(Tag, m_usedTags++); } + AssemblyItem newPushTag() { return AssemblyItem(PushTag, m_usedTags++); } AssemblyItem newData(bytes const& _data) { auto h = sha3(_data); m_data[h] = _data; return AssemblyItem(PushData, h); } - AssemblyItem newPushString(std::string const& _data) { auto b = asBytes(_data); auto h = sha3(b); m_data[h] = b; return AssemblyItem(PushString, h); } + AssemblyItem newPushString(std::string const& _data) { auto h = sha3(_data); m_strings[h] = _data; return AssemblyItem(PushString, h); } + + AssemblyItem append() { return append(newTag()); } + void append(Assembly const& _a); + void append(Assembly const& _a, int _deposit); + AssemblyItem const& append(AssemblyItem const& _i); + AssemblyItem const& append(std::string const& _data) { return append(newPushString(_data)); } + AssemblyItem const& append(bytes const& _data) { return append(newData(_data)); } + + AssemblyItem appendJump() { auto ret = append(newPushTag()); append(Instruction::JUMP); return ret; } + AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(Instruction::JUMPI); return ret; } + AssemblyItem appendJump(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMP); return ret; } + AssemblyItem appendJumpI(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMPI); return ret; } + + template <class T> Assembly& operator<<(T const& _d) { append(_d); return *this; } + + AssemblyItem const& back() { return m_items.back(); } + std::string backString() const { return m_items.back().m_type == PushString ? m_strings.at((h256)m_items.back().m_data) : std::string(); } - void append(AssemblyItem const& _i) { m_items.push_back(_i); } + void onePath() { assert(!m_totalDeposit && !m_baseDeposit); m_baseDeposit = m_deposit; m_totalDeposit = INT_MAX; } + void otherPath() { donePath(); m_totalDeposit = m_deposit; m_deposit = m_baseDeposit; } + void donePaths() { donePath(); m_totalDeposit = m_baseDeposit = 0; } + void ignored() { m_baseDeposit = m_deposit; } + void endIgnored() { m_deposit = m_baseDeposit; m_baseDeposit = 0; } + void popTo(int _deposit) { while (m_deposit > _deposit) append(Instruction::POP); } + + std::string out() const { std::stringstream ret; streamOut(ret); return ret.str(); } + int deposit() const { return m_deposit; } bytes assemble() const; - void append(Assembly const& _a); std::ostream& streamOut(std::ostream& _out) const; private: - u256 m_usedTags = 0; + void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) throw InvalidDeposit(); } + unsigned bytesRequired() const; + + unsigned m_usedTags = 0; std::vector<AssemblyItem> m_items; std::map<h256, bytes> m_data; + std::map<h256, std::string> m_strings; + + int m_deposit = 0; + int m_baseDeposit = 0; + int m_totalDeposit = 0; }; +inline std::ostream& operator<<(std::ostream& _out, Assembly const& _a) +{ + _a.streamOut(_out); + return _out; +} + } |