-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathas.hpp
More file actions
91 lines (72 loc) · 1.65 KB
/
Copy pathas.hpp
File metadata and controls
91 lines (72 loc) · 1.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#ifndef LINK_HPP
#define LINK_HPP
#include "vm.hpp"
#include <set>
#include <map>
#include <vector>
namespace as {
using label = const char*;
static label make_label(std::string name) {
static std::set<std::string> table;
return table.emplace(name).first->c_str();
}
struct line {
union {
struct {
vm::instr op;
label addr;
} instr;
vm::word data;
label addr;
} value;
enum { INSTR, DATA, ADDR } kind;
line(vm::instr op) {
kind = INSTR;
value.instr = {op, nullptr};
}
line(label addr, vm::instr op) {
kind = INSTR;
value.instr = {op, addr};
}
line(vm::word data) {
kind = DATA;
value.data = data;
}
line(label addr) {
kind = ADDR;
value.addr = addr;
}
};
static std::vector<vm::code> link(const std::vector<line>& listing) {
std::map<label, const line*> table;
for(const line& it: listing) {
// build address table
if(it.kind == line::INSTR && it.value.instr.addr) {
const auto info = table.emplace(it.value.instr.addr, &it);
if(!info.second)
throw std::runtime_error("duplicate label");
}
}
std::vector<vm::code> result;
for(const line& it: listing) {
switch(it.kind) {
case line::INSTR:
result.emplace_back(it.value.instr.op);
break;
case line::DATA:
result.emplace_back(it.value.data);
break;
case line::ADDR: {
const auto at = table.find(it.value.addr);
if(at == table.end())
throw std::runtime_error("unknown label");
const vm::word offset = at->second - ⁢
result.emplace_back(offset);
break;
}
}
}
return result;
}
} // namespace as
#endif