diff options
author | chriseth <chris@ethereum.org> | 2017-08-25 23:04:31 +0800 |
---|---|---|
committer | Alex Beregszaszi <alex@rtfs.hu> | 2017-09-16 03:44:49 +0800 |
commit | 73771f5bb2d8aee1b71dfcc909a60aa47c591dec (patch) | |
tree | 25e580641cc09f52c11447e2045dea747f3980b3 /libevmasm | |
parent | 7dd372ce5c9ea1cacf2c70a16f0285bb74314db8 (diff) | |
download | dexon-solidity-73771f5bb2d8aee1b71dfcc909a60aa47c591dec.tar.gz dexon-solidity-73771f5bb2d8aee1b71dfcc909a60aa47c591dec.tar.zst dexon-solidity-73771f5bb2d8aee1b71dfcc909a60aa47c591dec.zip |
Named assembly labels.
Diffstat (limited to 'libevmasm')
-rw-r--r-- | libevmasm/Assembly.cpp | 11 | ||||
-rw-r--r-- | libevmasm/Assembly.h | 3 |
2 files changed, 14 insertions, 0 deletions
diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 6b4bb52b..31857c09 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -49,6 +49,8 @@ void Assembly::append(Assembly const& _a) } m_deposit = newDeposit; m_usedTags += _a.m_usedTags; + // This does not transfer the names of named tags on purpose. The tags themselves are + // transferred, but their names are only available inside the assembly. for (auto const& i: _a.m_data) m_data.insert(i); for (auto const& i: _a.m_strings) @@ -326,6 +328,14 @@ AssemblyItem const& Assembly::append(AssemblyItem const& _i) return back(); } +AssemblyItem Assembly::namedTag(string const& _name) +{ + assertThrow(!_name.empty(), AssemblyException, ""); + if (!m_namedTags.count(_name)) + m_namedTags[_name] = size_t(newTag().data()); + return AssemblyItem(Tag, m_namedTags.at(_name)); +} + AssemblyItem Assembly::newPushLibraryAddress(string const& _identifier) { h256 h(dev::keccak256(_identifier)); @@ -581,6 +591,7 @@ LinkerObject const& Assembly::assemble() const assertThrow(i.data() != 0, AssemblyException, ""); assertThrow(i.splitForeignPushTag().first == size_t(-1), AssemblyException, "Foreign tag."); assertThrow(ret.bytecode.size() < 0xffffffffL, AssemblyException, "Tag too large."); + assertThrow(m_tagPositionsInBytecode[size_t(i.data())] == size_t(-1), AssemblyException, "Duplicate tag position."); m_tagPositionsInBytecode[size_t(i.data())] = ret.bytecode.size(); ret.bytecode.push_back((byte)Instruction::JUMPDEST); break; diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index cbdd71bc..885192e4 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -47,6 +47,8 @@ public: AssemblyItem newTag() { return AssemblyItem(Tag, m_usedTags++); } AssemblyItem newPushTag() { return AssemblyItem(PushTag, m_usedTags++); } + /// Returns a tag identified by the given name. Creates it if it does not yet exist. + AssemblyItem namedTag(std::string const& _name); AssemblyItem newData(bytes const& _data) { h256 h(dev::keccak256(asString(_data))); m_data[h] = _data; return AssemblyItem(PushData, h); } AssemblyItem newSub(AssemblyPointer const& _sub) { m_subs.push_back(_sub); return AssemblyItem(PushSub, m_subs.size() - 1); } Assembly const& sub(size_t _sub) const { return *m_subs.at(_sub); } @@ -150,6 +152,7 @@ private: protected: /// 0 is reserved for exception unsigned m_usedTags = 1; + std::map<std::string, size_t> m_namedTags; AssemblyItems m_items; std::map<h256, bytes> m_data; /// Data that is appended to the very end of the contract. |