MXVM 1.8.1
Virtual Machine, Compiler, and Pascal Frontend
Loading...
Searching...
No Matches
icode.cpp
Go to the documentation of this file.
1
6#include "icode.hpp"
7#include <algorithm>
8#include <regex>
9#include <sstream>
10#include <string>
11#include <unordered_set>
12#include <vector>
13
14namespace pascal {
15 static inline std::string rtrim_comment(const std::string &line) {
16 auto h = line.find('#');
17 auto s = line.find("//");
18 size_t cut = std::min(h == std::string::npos ? line.size() : h,
19 s == std::string::npos ? line.size() : s);
20 std::string out = line.substr(0, cut);
21 while (!out.empty() && (unsigned char)out.back() <= ' ')
22 out.pop_back();
23 return out;
24 }
25 static inline std::string trim(const std::string &s) {
26 size_t a = 0, b = s.size();
27 while (a < b && (unsigned char)s[a] <= ' ')
28 ++a;
29 while (b > a && (unsigned char)s[b - 1] <= ' ')
30 --b;
31 return s.substr(a, b - a);
32 }
33 static void locate_sections(const std::vector<std::string> &lines,
34 size_t &dataStart, size_t &dataEnd,
35 size_t &codeStart, size_t &codeEnd) {
36 dataStart = dataEnd = codeStart = codeEnd = 0;
37 for (size_t i = 0; i < lines.size(); ++i) {
38 if (!dataStart && lines[i].find("section data {") != std::string::npos) {
39 dataStart = i + 1;
40 for (size_t j = dataStart; j < lines.size(); ++j) {
41 if (lines[j].find('}') != std::string::npos) {
42 dataEnd = j - 1;
43 break;
44 }
45 }
46 }
47 if (!codeStart && lines[i].find("section code {") != std::string::npos) {
48 codeStart = i + 1;
49 for (size_t j = codeStart; j < lines.size(); ++j) {
50 if (lines[j].find('}') != std::string::npos) {
51 codeEnd = j - 1;
52 break;
53 }
54 }
55 }
56 if (dataStart && dataEnd && codeStart && codeEnd)
57 break;
58 }
59 }
60 static std::unordered_set<std::string> collect_used(const std::vector<std::string> &lines,
61 size_t codeStart, size_t codeEnd) {
62 std::string code;
63 for (size_t i = codeStart; i <= codeEnd && i < lines.size(); ++i) {
64 code += lines[i];
65 code.push_back('\n');
66 }
67 std::unordered_set<std::string> used = {"rax", "fmt_int", "fmt_str", "fmt_chr", "fmt_float", "newline"};
68 std::regex varUsagePattern("\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b");
69 for (auto it = std::sregex_iterator(code.begin(), code.end(), varUsagePattern);
70 it != std::sregex_iterator(); ++it)
71 used.insert((*it).str(1));
72 return used;
73 }
74 static void sweep_unused_data(std::vector<std::string> &lines) {
75 size_t dS = 0, dE = 0, cS = 0, cE = 0;
76 locate_sections(lines, dS, dE, cS, cE);
77 if (!dS || !cS)
78 return;
79 auto used = collect_used(lines, cS, cE);
80 std::regex decl("^\\s*(export)?\\s*(int|string|ptr|float|double)\\s+([A-Za-z_][A-Za-z0-9_]*)");
81 std::vector<size_t> erase;
82 for (size_t i = dS; i <= dE && i < lines.size(); ++i) {
83 std::smatch m;
84 if (std::regex_search(lines[i], m, decl)) {
85 bool isExport = m[1].length() > 0;
86 std::string name = m[3];
87 if (!isExport && !used.count(name))
88 erase.push_back(i);
89 }
90 }
91 std::sort(erase.begin(), erase.end(), std::greater<size_t>());
92 for (auto idx : erase)
93 if (idx < lines.size())
94 lines.erase(lines.begin() + idx);
95 }
96
97 static std::vector<std::pair<size_t, std::string>> nextNonEmpty(
98 const std::vector<std::string> &code, size_t start, size_t n) {
99 std::vector<std::pair<size_t, std::string>> out;
100 for (size_t i = start; i < code.size() && out.size() < n; ++i) {
101 std::string t = trim(rtrim_comment(code[i]));
102 if (!t.empty())
103 out.push_back({i, t});
104 }
105 return out;
106 }
107
108 static std::string invertJump(const std::string &j) {
109 if (j == "jg")
110 return "jle";
111 else if (j == "jle")
112 return "jg";
113 else if (j == "jl")
114 return "jge";
115 else if (j == "jge")
116 return "jl";
117 else if (j == "je")
118 return "jne";
119 else if (j == "jne")
120 return "je";
121 else if (j == "ja")
122 return "jbe";
123 else if (j == "jbe")
124 return "ja";
125 else if (j == "jb")
126 return "jae";
127 else if (j == "jae")
128 return "jb";
129 return "";
130 }
131
132 static bool parse2(const std::string &line, const std::string &op,
133 std::string &a, std::string &b) {
134 if (line.size() <= op.size() || line.compare(0, op.size(), op) != 0 ||
135 line[op.size()] != ' ')
136 return false;
137 std::string rest = line.substr(op.size() + 1);
138 auto c = rest.find(',');
139 if (c == std::string::npos)
140 return false;
141 a = trim(rest.substr(0, c));
142 b = trim(rest.substr(c + 1));
143 return !a.empty() && !b.empty();
144 }
145 static bool parse1(const std::string &line, const std::string &op, std::string &a) {
146 if (line.size() <= op.size() || line.compare(0, op.size(), op) != 0 ||
147 line[op.size()] != ' ')
148 return false;
149 a = trim(line.substr(op.size() + 1));
150 return !a.empty();
151 }
152 static bool parseJump(const std::string &line, std::string &jop, std::string &label) {
153 if (line.size() < 3 || line[0] != 'j')
154 return false;
155 auto sp = line.find(' ');
156 if (sp == std::string::npos)
157 return false;
158 jop = line.substr(0, sp);
159 label = trim(line.substr(sp + 1));
160 return !label.empty() && jop != "jmp";
161 }
162 static bool isLabelDef(const std::string &line, const std::string &label) {
163 return line == label + ":";
164 }
165
166 static void foldCmpTest(std::vector<std::string> &code) {
167 bool changed = true;
168 while (changed) {
169 changed = false;
170 for (size_t i = 0; i < code.size(); ++i) {
171 auto mat = nextNonEmpty(code, i, 7);
172 if (mat.size() < 7)
173 break;
174
175 std::string cmpA, cmpB;
176 bool isFcmp = parse2(mat[0].second, "fcmp", cmpA, cmpB);
177 if (!isFcmp && !parse2(mat[0].second, "cmp", cmpA, cmpB))
178 continue;
179 std::string cmpOp = isFcmp ? "fcmp" : "cmp";
180
181 std::string jCC, trueLabel;
182 if (!parseJump(mat[1].second, jCC, trueLabel))
183 continue;
184
185 std::string reg, zero;
186 if (!parse2(mat[2].second, "mov", reg, zero) || zero != "0")
187 continue;
188
189 std::string endLabel;
190 if (!parse1(mat[3].second, "jmp", endLabel))
191 continue;
192
193 if (!isLabelDef(mat[4].second, trueLabel))
194 continue;
195
196 std::string r5, one;
197 if (!parse2(mat[5].second, "mov", r5, one) || r5 != reg || one != "1")
198 continue;
199
200 if (!isLabelDef(mat[6].second, endLabel))
201 continue;
202
203 auto rest = nextNonEmpty(code, mat[6].first + 1, 30);
204 bool found = false;
205 for (size_t j = 0; j + 1 < rest.size(); ++j) {
206 if (rest[j].second.back() == ':')
207 break;
208 std::string wdst, wsrc;
209 if (parse2(rest[j].second, "mov", wdst, wsrc) && wdst == reg)
210 break;
211
212 std::string rt, zt;
213 if (parse2(rest[j].second, "cmp", rt, zt) && rt == reg && zt == "0") {
214 std::string jTest, target;
215 if (j + 1 < rest.size() && parseJump(rest[j + 1].second, jTest, target) &&
216 (jTest == "je" || jTest == "jne")) {
217 std::string newJ = (jTest == "je") ? invertJump(jCC) : jCC;
218 if (newJ.empty())
219 break;
220
221 bool labelUsedElsewhere = false;
222 for (size_t k = 0; k < code.size(); ++k) {
223 if (k == mat[1].first || k == rest[j + 1].first)
224 continue;
225 std::string t = trim(rtrim_comment(code[k]));
226 if (!t.empty() && t.back() != ':' && t.find(trueLabel) != std::string::npos) {
227 labelUsedElsewhere = true;
228 break;
229 }
230 }
231 if (labelUsedElsewhere)
232 break;
233
234 code[mat[0].first] = "\t\t" + cmpOp + " " + cmpA + ", " + cmpB;
235 code[mat[1].first] = "\t\t" + newJ + " " + target;
236 for (int k = 2; k <= 6; ++k)
237 code[mat[k].first] = "";
238 code[rest[j].first] = "";
239 code[rest[j + 1].first] = "";
240
241 found = true;
242 changed = true;
243 }
244 break;
245 }
246 }
247 if (found)
248 break;
249 }
250 }
251 }
252
253 static void foldAndTest(std::vector<std::string> &code) {
254 bool changed = true;
255 while (changed) {
256 changed = false;
257 for (size_t i = 0; i < code.size(); ++i) {
258 auto seq = nextNonEmpty(code, i, 11);
259 if (seq.size() < 11)
260 break;
261
262 std::string r1, z0;
263 if (!parse2(seq[0].second, "cmp", r1, z0) || z0 != "0")
264 continue;
265 std::string j1, zeroLabel;
266 if (!parse1(seq[1].second, "je", zeroLabel))
267 continue;
268 std::string r2, z2;
269 if (!parse2(seq[2].second, "cmp", r2, z2) || z2 != "0")
270 continue;
271 std::string j3, zl3;
272 if (!parse1(seq[3].second, "je", zl3) || zl3 != zeroLabel)
273 continue;
274 std::string r3, one;
275 if (!parse2(seq[4].second, "mov", r3, one) || one != "1")
276 continue;
277 std::string endLabel;
278 if (!parse1(seq[5].second, "jmp", endLabel))
279 continue;
280 if (!isLabelDef(seq[6].second, zeroLabel))
281 continue;
282 std::string r7, z7;
283 if (!parse2(seq[7].second, "mov", r7, z7) || r7 != r3 || z7 != "0")
284 continue;
285 if (!isLabelDef(seq[8].second, endLabel))
286 continue;
287 std::string r9, z9;
288 if (!parse2(seq[9].second, "cmp", r9, z9) || r9 != r3 || z9 != "0")
289 continue;
290 std::string target;
291 if (!parse1(seq[10].second, "je", target))
292 continue;
293
294 code[seq[0].first] = "\t\tcmp " + r1 + ", 0";
295 code[seq[1].first] = "\t\tje " + target;
296 code[seq[2].first] = "\t\tcmp " + r2 + ", 0";
297 code[seq[3].first] = "\t\tje " + target;
298 for (int k = 4; k <= 10; ++k)
299 code[seq[k].first] = "";
300 changed = true;
301 break;
302 }
303 }
304 }
305
306 static void foldOrTest(std::vector<std::string> &code) {
307 bool changed = true;
308 while (changed) {
309 changed = false;
310 for (size_t i = 0; i < code.size(); ++i) {
311 auto seq = nextNonEmpty(code, i, 11);
312 if (seq.size() < 11)
313 break;
314
315 std::string r1, z0;
316 if (!parse2(seq[0].second, "cmp", r1, z0) || z0 != "0")
317 continue;
318 std::string oneLabel;
319 if (!parse1(seq[1].second, "jne", oneLabel))
320 continue;
321 std::string r2, z2;
322 if (!parse2(seq[2].second, "cmp", r2, z2) || z2 != "0")
323 continue;
324 std::string ol3;
325 if (!parse1(seq[3].second, "jne", ol3) || ol3 != oneLabel)
326 continue;
327 std::string r3, z4;
328 if (!parse2(seq[4].second, "mov", r3, z4) || z4 != "0")
329 continue;
330 std::string endLabel;
331 if (!parse1(seq[5].second, "jmp", endLabel))
332 continue;
333 if (!isLabelDef(seq[6].second, oneLabel))
334 continue;
335 std::string r7, o7;
336 if (!parse2(seq[7].second, "mov", r7, o7) || r7 != r3 || o7 != "1")
337 continue;
338 if (!isLabelDef(seq[8].second, endLabel))
339 continue;
340 std::string r9, z9;
341 if (!parse2(seq[9].second, "cmp", r9, z9) || r9 != r3 || z9 != "0")
342 continue;
343 std::string target;
344 if (!parse1(seq[10].second, "je", target))
345 continue;
346
347 code[seq[0].first] = "\t\tcmp " + r1 + ", 0";
348 code[seq[1].first] = "\t\tjne " + oneLabel;
349 code[seq[2].first] = "\t\tcmp " + r2 + ", 0";
350 code[seq[3].first] = "\t\tje " + target;
351 code[seq[4].first] = "\t" + oneLabel + ":";
352 for (int k = 5; k <= 10; ++k)
353 code[seq[k].first] = "";
354 changed = true;
355 break;
356 }
357 }
358 }
359
366 static bool isRegisterName(const std::string &s);
367
376 static void copyPropagation(std::vector<std::string> &code) {
377 static const std::unordered_set<std::string> twoOpInstructions = {
378 "add", "sub", "mul", "div", "mod", "cmp", "fcmp", "mov", "and", "or", "xor"};
379 bool changed = true;
380 while (changed) {
381 changed = false;
382 for (size_t i = 0; i < code.size(); ++i) {
383 std::string t0 = trim(rtrim_comment(code[i]));
384 if (t0.empty())
385 continue;
386
387 std::string movDst, movSrc;
388 if (!parse2(t0, "mov", movDst, movSrc))
389 continue;
390 if (movDst == movSrc) {
391 code[i] = "";
392 changed = true;
393 break;
394 }
395
396 size_t j = i + 1;
397 while (j < code.size() && trim(rtrim_comment(code[j])).empty())
398 ++j;
399 if (j >= code.size())
400 continue;
401
402 std::string t1 = trim(rtrim_comment(code[j]));
403 if (!t1.empty() && t1.back() == ':')
404 continue;
405
406 auto sp = t1.find(' ');
407 if (sp == std::string::npos)
408 continue;
409 std::string op = t1.substr(0, sp);
410
411 if (twoOpInstructions.find(op) == twoOpInstructions.end())
412 continue;
413
414 std::string arg1, arg2;
415 if (!parse2(t1, op, arg1, arg2))
416 continue;
417 if (arg1 != movDst)
418 continue;
419 if (arg2 == movDst)
420 continue;
421
422 bool usedLater = false;
423 std::string pattern = "\\b" + movDst + "\\b";
424 std::regex wordPat(pattern);
425 for (size_t k = j + 1; k < code.size(); ++k) {
426 std::string tk = rtrim_comment(code[k]);
427 if (tk.empty())
428 continue;
429 if (std::regex_search(tk, wordPat)) {
430 usedLater = true;
431 break;
432 }
433 if (!tk.empty() && tk.find("function ") != std::string::npos)
434 break;
435 // A ret/done ends the current procedure/program.
436 // Non-register stores before a return are observable
437 // by the caller, so treat them as live.
438 std::string ttk = trim(tk);
439 if ((ttk == "ret" || ttk == "done") && !isRegisterName(movDst)) {
440 usedLater = true;
441 break;
442 }
443 }
444
445 if (usedLater)
446 continue;
447
448 if (op == "cmp" || op == "fcmp") {
449 code[j] = "\t\t" + op + " " + movSrc + ", " + arg2;
450 code[i] = "";
451 changed = true;
452 break;
453 }
454
455 if (op == "mov") {
456 code[i] = "";
457 changed = true;
458 break;
459 }
460
461 // Arithmetic ops require a variable as operand 1 (it's the destination).
462 // Don't propagate constants into that position.
463 if (!movSrc.empty() && (std::isdigit((unsigned char)movSrc[0]) || movSrc[0] == '-' || movSrc[0] == '"' || movSrc[0] == '\''))
464 continue;
465
466 bool srcUsedLater = false;
467 std::string srcPattern = "\\b" + movSrc + "\\b";
468 std::regex srcPat(srcPattern);
469 for (size_t k = j + 1; k < code.size(); ++k) {
470 std::string tk = rtrim_comment(code[k]);
471 if (tk.empty())
472 continue;
473 if (std::regex_search(tk, srcPat)) {
474 srcUsedLater = true;
475 break;
476 }
477 if (!tk.empty() && tk.find("function ") != std::string::npos)
478 break;
479 }
480
481 if (!srcUsedLater) {
482 code[j] = "\t\t" + op + " " + movSrc + ", " + arg2;
483 code[i] = "";
484 changed = true;
485 break;
486 }
487 }
488 }
489 }
490
491 static bool isRegisterName(const std::string &s) {
492 static const std::unordered_set<std::string> regs = {
493 "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"};
494 if (regs.count(s))
495 return true;
496 if (s.size() >= 4 && s.compare(0, 3, "xmm") == 0)
497 return true;
498 return false;
499 }
500
501 static void foldMovArithMov(std::vector<std::string> &code) {
502 static const std::unordered_set<std::string> arithOps = {
503 "add", "sub", "mul", "div", "mod", "and", "or", "xor"};
504 bool changed = true;
505 while (changed) {
506 changed = false;
507 for (size_t i = 0; i + 2 < code.size(); ++i) {
508 std::string t0 = trim(rtrim_comment(code[i]));
509 if (t0.empty())
510 continue;
511 std::string mDst, mSrc;
512 if (!parse2(t0, "mov", mDst, mSrc))
513 continue;
514 if (!isRegisterName(mDst))
515 continue;
516
517 size_t j = i + 1;
518 while (j < code.size() && trim(rtrim_comment(code[j])).empty())
519 ++j;
520 if (j >= code.size())
521 continue;
522 std::string t1 = trim(rtrim_comment(code[j]));
523 if (t1.empty() || t1.back() == ':')
524 continue;
525 auto sp = t1.find(' ');
526 if (sp == std::string::npos)
527 continue;
528 std::string op = t1.substr(0, sp);
529 if (arithOps.find(op) == arithOps.end())
530 continue;
531 std::string a1, a2;
532 if (!parse2(t1, op, a1, a2))
533 continue;
534 if (a1 != mDst)
535 continue;
536 if (a2 == mDst)
537 continue;
538
539 size_t k = j + 1;
540 while (k < code.size() && trim(rtrim_comment(code[k])).empty())
541 ++k;
542 if (k >= code.size())
543 continue;
544 std::string t2 = trim(rtrim_comment(code[k]));
545 std::string m2Dst, m2Src;
546 if (!parse2(t2, "mov", m2Dst, m2Src))
547 continue;
548 if (m2Src != mDst)
549 continue;
550 if (isRegisterName(m2Dst))
551 continue;
552
553 bool usedAfter = false;
554 std::string pattern = "\\b" + mDst + "\\b";
555 std::regex wordPat(pattern);
556 for (size_t w = k + 1; w < code.size(); ++w) {
557 std::string tw = rtrim_comment(code[w]);
558 if (tw.empty())
559 continue;
560 if (std::regex_search(tw, wordPat)) {
561 usedAfter = true;
562 break;
563 }
564 if (tw.find("function ") != std::string::npos)
565 break;
566 }
567 if (usedAfter)
568 continue;
569
570 code[i] = "\t\tmov " + m2Dst + ", " + mSrc;
571 code[j] = "\t\t" + op + " " + m2Dst + ", " + a2;
572 code[k] = "";
573 changed = true;
574 break;
575 }
576 }
577 }
578
579 static void peepholeOpt(std::vector<std::string> &code) {
580 copyPropagation(code);
581 foldMovArithMov(code);
582 foldAndTest(code);
583 foldOrTest(code);
584 foldCmpTest(code);
585 foldCmpTest(code);
586 copyPropagation(code);
587 }
588
589 std::string mxvmOpt(const std::string &text) {
590 std::vector<std::string> lines;
591 {
592 std::istringstream is(text);
593 std::string ln;
594 while (std::getline(is, ln))
595 lines.push_back(ln);
596 }
597
598 size_t dataStart = 0, dataEnd = 0, codeStart = 0, codeEnd = 0;
599 locate_sections(lines, dataStart, dataEnd, codeStart, codeEnd);
600 if (!codeStart) {
601 std::string out;
602 for (auto &ln : lines)
603 out += ln + "\n";
604 return out;
605 }
606
607 sweep_unused_data(lines);
608 locate_sections(lines, dataStart, dataEnd, codeStart, codeEnd);
609 if (!codeStart) {
610 std::string out;
611 for (auto &ln : lines)
612 out += ln + "\n";
613 return out;
614 }
615
616 size_t cStart = codeStart, cEnd = std::min(codeEnd, lines.size() ? lines.size() - 1 : 0);
617 std::vector<std::string> code;
618 code.reserve(cEnd - cStart + 1);
619 for (size_t i = cStart; i <= cEnd; ++i)
620 code.push_back(lines[i]);
621
622 std::vector<std::string> pass1;
623 pass1.reserve(code.size());
624 std::regex movPat("^\\s*(\\s*)mov\\s+([^,\\s]+)\\s*,\\s*([^\\s#;]+)\\s*(?:[;#].*)?$", std::regex::icase);
625
626 for (size_t i = 0; i < code.size();) {
627 std::string raw0 = code[i];
628 std::string noCom0 = rtrim_comment(raw0);
629 std::smatch m0;
630 if (std::regex_match(noCom0, m0, movPat)) {
631 std::string indent = m0[1].str();
632 std::string dst0 = trim(m0[2].str());
633 std::string src0 = trim(m0[3].str());
634 if (dst0 == src0) {
635 ++i;
636 continue;
637 }
638 size_t k = i + 1;
639 while (k < code.size() && rtrim_comment(code[k]).empty())
640 ++k;
641 if (k < code.size()) {
642 std::string raw1 = code[k];
643 std::string noCom1 = rtrim_comment(raw1);
644 std::smatch m1;
645 if (std::regex_match(noCom1, m1, movPat)) {
646 std::string dst1 = trim(m1[2].str());
647 std::string src1 = trim(m1[3].str());
648 if (dst1 == src0 && src1 == dst0) {
649 pass1.push_back("\t\tmov " + dst0 + ", " + src0);
650 i = k + 1;
651 continue;
652 }
653 }
654 }
655 pass1.push_back(raw0);
656 ++i;
657 continue;
658 }
659 pass1.push_back(raw0);
660 ++i;
661 }
662
663 std::vector<std::string> pass2;
664 pass2.reserve(pass1.size());
665 std::regex movDstPat("^\\s*mov\\s+([A-Za-z_][A-Za-z0-9_]*)\\s*,", std::regex::icase);
666
667 for (size_t i = 0; i < pass1.size(); ++i) {
668 std::string raw = pass1[i];
669 std::string noCom = rtrim_comment(raw);
670 std::smatch mm;
671 if (std::regex_match(noCom, mm, movDstPat)) {
672 std::string dst = mm[1].str();
673 bool usedLater = false;
674 std::regex word("\\b" + dst + "\\b");
675 for (size_t j = i + 1; j < pass1.size(); ++j) {
676 std::string nxt = rtrim_comment(pass1[j]);
677 if (!nxt.empty() && std::regex_search(nxt, word)) {
678 usedLater = true;
679 break;
680 }
681 // A ret/done ends the current procedure/program.
682 // Non-register stores before a return are observable
683 // by the caller, so treat them as live.
684 if (!nxt.empty()) {
685 std::string tnxt = trim(nxt);
686 if ((tnxt == "ret" || tnxt == "done") && !isRegisterName(dst)) {
687 usedLater = true;
688 break;
689 }
690 }
691 }
692 if (!usedLater)
693 continue;
694 }
695 pass2.push_back(raw);
696 }
697
698 peepholeOpt(pass2);
699
700 std::vector<std::string> pass3;
701 pass3.reserve(pass2.size());
702 for (auto &ln : pass2)
703 if (!ln.empty())
704 pass3.push_back(ln);
705
706 std::vector<std::string> finalLines;
707 finalLines.insert(finalLines.end(), lines.begin(), lines.begin() + cStart);
708 finalLines.insert(finalLines.end(), pass3.begin(), pass3.end());
709 if (cEnd + 1 < lines.size())
710 finalLines.insert(finalLines.end(), lines.begin() + cEnd + 1, lines.end());
711
712 sweep_unused_data(finalLines);
713
714 std::string result;
715 for (auto &ln : finalLines)
716 result += ln + "\n";
717 return result;
718 }
719} // namespace pascal
Definition ast.cpp:9
static std::vector< std::pair< size_t, std::string > > nextNonEmpty(const std::vector< std::string > &code, size_t start, size_t n)
Definition icode.cpp:97
std::string mxvmOpt(const std::string &text)
Definition icode.cpp:589
static std::string invertJump(const std::string &j)
Definition icode.cpp:108
static std::unordered_set< std::string > collect_used(const std::vector< std::string > &lines, size_t codeStart, size_t codeEnd)
Definition icode.cpp:60
static void peepholeOpt(std::vector< std::string > &code)
Definition icode.cpp:579
static bool parse2(const std::string &line, const std::string &op, std::string &a, std::string &b)
Definition icode.cpp:132
static void sweep_unused_data(std::vector< std::string > &lines)
Definition icode.cpp:74
static bool parseJump(const std::string &line, std::string &jop, std::string &label)
Definition icode.cpp:152
static void copyPropagation(std::vector< std::string > &code)
Copy-propagation peephole pass.
Definition icode.cpp:376
static std::string rtrim_comment(const std::string &line)
Definition icode.cpp:15
static bool isLabelDef(const std::string &line, const std::string &label)
Definition icode.cpp:162
static void foldMovArithMov(std::vector< std::string > &code)
Definition icode.cpp:501
static std::string trim(const std::string &s)
Definition icode.cpp:25
static bool parse1(const std::string &line, const std::string &op, std::string &a)
Definition icode.cpp:145
static void foldCmpTest(std::vector< std::string > &code)
Definition icode.cpp:166
static void foldOrTest(std::vector< std::string > &code)
Definition icode.cpp:306
static void foldAndTest(std::vector< std::string > &code)
Definition icode.cpp:253
static void locate_sections(const std::vector< std::string > &lines, size_t &dataStart, size_t &dataEnd, size_t &codeStart, size_t &codeEnd)
Definition icode.cpp:33
static bool isRegisterName(const std::string &s)
Forward declaration — checks whether a name is a hardware register.
Definition icode.cpp:491
Pascal-to-MXVM code generator using the Visitor pattern over the Pascal AST.