https://github.com/akkartik/mu/blob/master/subx/040---tests.cc
1
2
3
4
5
6
7
8
9
10
11
12 :(after "Begin Transforms")
13
14 Transform.push_back(create_test_function);
15
16
17 :(scenario run_test)
18 % Reg[ESP].u = 0x100;
19 == 0x1
20 main:
21 e8/call run-tests/disp32
22 f4/halt
23
24 test-foo:
25 01 d8
26 c3/return
27
28
29 +run: 0x00000007 opcode: 01
30
31 :(code)
32 void create_test_function(program& p) {
33 if (p.segments.empty()) return;
34 segment& code = p.segments.at(0);
35 trace(3, "transform") << "-- create 'run-tests'" << end();
36 vector<line> new_insts;
37 for (int i = 0; i < SIZE(code.lines); ++i) {
38 line& inst = code.lines.at(i);
39 for (int j = 0; j < SIZE(inst.words); ++j) {
40 const word& curr = inst.words.at(j);
41 if (*curr.data.rbegin() != ':') continue;
42 if (!starts_with(curr.data, "test-")) continue;
43 string fn = drop_last(curr.data);
44 new_insts.push_back(call(fn));
45 }
46 }
47 if (new_insts.empty()) return;
48 code.lines.push_back(label("run-tests"));
49 code.lines.insert(code.lines.end(), new_insts.begin(), new_insts.end());
50 code.lines.push_back(ret());
51 }
52
53 string to_string(const segment& s) {
54 ostringstream out;
55 for (int i = 0; i < SIZE(s.lines); ++i) {
56 const line& l = s.lines.at(i);
57 for (int j = 0; j < SIZE(l.words); ++j) {
58 if (j > 0) out << ' ';
59 out << to_string(l.words.at(j));
60 }
61 out << '\n';
62 }
63 return out.str();
64 }
65
66 line call(string s) {
67 line result;
68 result.words.push_back(call());
69 result.words.push_back(disp32(s));
70 return result;
71 }
72
73 word call() {
74 word result;
75 result.data = "e8";
76 result.metadata.push_back("call");
77 return result;
78 }
79
80 word disp32(string s) {
81 word result;
82 result.data = s;
83 result.metadata.push_back("disp32");
84 return result;
85 }
86
87 line ret() {
88 line result;
89 result.words.push_back(word());
90 result.words.back().data = "c3";
91 result.words.back().metadata.push_back("return");
92 return result;
93 }