MCPcopy Create free account
hub / github.com/D7EAD/mkPIVM / BytecodeBuilder

Class BytecodeBuilder

include/mkpivm/bytecode.h:13–114  ·  view source on GitHub ↗

accumulates plaintext bytecode. tracks branch fixups

Source from the content-addressed store, hash-verified

11namespace mkpivm {
12 // accumulates plaintext bytecode. tracks branch fixups
13 class BytecodeBuilder {
14 public:
15 std::size_t pos() const noexcept { return buf_.size(); }
16 void u8 (std::uint8_t v) { buf_.push_back(v); }
17
18 void u16(std::uint16_t v) {
19 buf_.push_back(static_cast<std::uint8_t>(v));
20 buf_.push_back(static_cast<std::uint8_t>(v >> 8));
21 }
22
23 void u32(std::uint32_t v) {
24 for (int i = 0; i < 4; ++i) buf_.push_back(static_cast<std::uint8_t>(v >> (8*i)));
25 }
26
27 void u64(std::uint64_t v) {
28 for (int i = 0; i < 8; ++i) buf_.push_back(static_cast<std::uint8_t>(v >> (8*i)));
29 }
30
31 void bytes(const std::uint8_t* p, std::size_t n) { buf_.insert(buf_.end(), p, p+n); }
32
33 // record this cursor as the start of IR block_id
34 void mark_block(std::uint32_t block_id) {
35 block_offsets_[block_id] = buf_.size();
36 }
37
38 std::uint32_t block_offset(std::uint32_t block_id) const {
39 auto it = block_offsets_.find(block_id);
40 if (it == block_offsets_.end()) throw Error("block_offset: unbound id");
41 return static_cast<std::uint32_t>(it->second);
42 }
43
44 // placeholder rel32 to a target block. resolved later to target_off
45 // minus end_of_field
46 void emit_branch_rel32(std::uint32_t target_block_id) {
47 branch_fixups_.push_back({buf_.size(), target_block_id});
48 u32(0);
49 }
50
51 // walk the fixup list once every block has an offset
52 void resolve_branches() {
53 for (const auto& f : branch_fixups_) {
54 auto it = block_offsets_.find(f.target_block_id);
55
56 if (it == block_offsets_.end()) throw Error("resolve_branches: missing block");
57 const std::int64_t rel = static_cast<std::int64_t>(it->second) - (static_cast<std::int64_t>(f.patch_pos) + 4);
58
59 if (rel < INT32_MIN || rel > INT32_MAX) throw Error("resolve_branches: oob");
60 const std::uint32_t v = static_cast<std::uint32_t>(static_cast<std::int32_t>(rel));
61
62 for (int i = 0; i < 4; ++i) {
63 buf_[f.patch_pos + i] = static_cast<std::uint8_t>(v >> (8*i));
64 }
65 }
66 branch_fixups_.clear();
67 }
68
69 // placeholder offset into the data island for an original VA. encoder
70 // fills it in using the IRProgram data map

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected