#ifndef _library__assembler__hpp__included__ #define _library__assembler__hpp__included__ #include #include "serialization.hpp" #include #include #include #include #include #include namespace assembler { typedef size_t addr_t; class label { public: label() { kind = L_LOCAL_U; } label(void* global) { kind = L_GLOBAL; addr = (addr_t)global; } label(const label& _base, int off) { switch(_base.kind) { case L_LOCAL_U: base = &_base; offset = off; kind = L_RELATIVE; break; case L_LOCAL_R: offset = _base.offset + off; kind = L_LOCAL_R; break; case L_GLOBAL: addr = _base.addr + off; kind = L_GLOBAL; break; case L_RELATIVE: base = _base.base; offset = _base.offset + off; kind = L_RELATIVE; break; } } void set(int off) { if(kind != L_LOCAL_U) throw std::runtime_error("Not undefined local label"); offset = off; kind = L_LOCAL_R; } addr_t resolve(addr_t localbase) const { switch(kind) { case L_LOCAL_U: throw std::runtime_error("Unresolved label"); case L_LOCAL_R: return localbase + offset; case L_GLOBAL: return addr; case L_RELATIVE: return base->resolve(localbase) + offset; } throw std::runtime_error("Unknown relocation type"); } private: enum _kind { L_LOCAL_U, L_LOCAL_R, L_GLOBAL, L_RELATIVE } kind; const struct label* base; addr_t addr; int offset; }; class label_list { public: operator label&(); operator label*(); label& external(void* addr); private: std::list