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) {
40 for (
size_t j = dataStart; j < lines.size(); ++j) {
41 if (lines[j].find(
'}') != std::string::npos) {
47 if (!codeStart && lines[i].find(
"section code {") != std::string::npos) {
49 for (
size_t j = codeStart; j < lines.size(); ++j) {
50 if (lines[j].find(
'}') != std::string::npos) {
56 if (dataStart && dataEnd && codeStart && codeEnd)
60 static std::unordered_set<std::string>
collect_used(
const std::vector<std::string> &lines,
61 size_t codeStart,
size_t codeEnd) {
63 for (
size_t i = codeStart; i <= codeEnd && i < lines.size(); ++i) {
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));
75 size_t dS = 0, dE = 0, cS = 0, cE = 0;
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) {
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))
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);
170 for (
size_t i = 0; i < code.size(); ++i) {
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))
179 std::string cmpOp = isFcmp ?
"fcmp" :
"cmp";
181 std::string jCC, trueLabel;
182 if (!
parseJump(mat[1].second, jCC, trueLabel))
185 std::string reg, zero;
186 if (!
parse2(mat[2].second,
"mov", reg, zero) || zero !=
"0")
189 std::string endLabel;
190 if (!
parse1(mat[3].second,
"jmp", endLabel))
197 if (!
parse2(mat[5].second,
"mov", r5, one) || r5 != reg || one !=
"1")
205 for (
size_t j = 0; j + 1 < rest.size(); ++j) {
206 if (rest[j].second.back() ==
':')
208 std::string wdst, wsrc;
209 if (
parse2(rest[j].second,
"mov", wdst, wsrc) && wdst == reg)
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;
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)
226 if (!t.empty() && t.back() !=
':' && t.find(trueLabel) != std::string::npos) {
227 labelUsedElsewhere =
true;
231 if (labelUsedElsewhere)
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] =
"";
257 for (
size_t i = 0; i < code.size(); ++i) {
263 if (!
parse2(seq[0].second,
"cmp", r1, z0) || z0 !=
"0")
265 std::string j1, zeroLabel;
266 if (!
parse1(seq[1].second,
"je", zeroLabel))
269 if (!
parse2(seq[2].second,
"cmp", r2, z2) || z2 !=
"0")
272 if (!
parse1(seq[3].second,
"je", zl3) || zl3 != zeroLabel)
275 if (!
parse2(seq[4].second,
"mov", r3, one) || one !=
"1")
277 std::string endLabel;
278 if (!
parse1(seq[5].second,
"jmp", endLabel))
283 if (!
parse2(seq[7].second,
"mov", r7, z7) || r7 != r3 || z7 !=
"0")
288 if (!
parse2(seq[9].second,
"cmp", r9, z9) || r9 != r3 || z9 !=
"0")
291 if (!
parse1(seq[10].second,
"je", target))
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] =
"";
310 for (
size_t i = 0; i < code.size(); ++i) {
316 if (!
parse2(seq[0].second,
"cmp", r1, z0) || z0 !=
"0")
318 std::string oneLabel;
319 if (!
parse1(seq[1].second,
"jne", oneLabel))
322 if (!
parse2(seq[2].second,
"cmp", r2, z2) || z2 !=
"0")
325 if (!
parse1(seq[3].second,
"jne", ol3) || ol3 != oneLabel)
328 if (!
parse2(seq[4].second,
"mov", r3, z4) || z4 !=
"0")
330 std::string endLabel;
331 if (!
parse1(seq[5].second,
"jmp", endLabel))
336 if (!
parse2(seq[7].second,
"mov", r7, o7) || r7 != r3 || o7 !=
"1")
341 if (!
parse2(seq[9].second,
"cmp", r9, z9) || r9 != r3 || z9 !=
"0")
344 if (!
parse1(seq[10].second,
"je", target))
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] =
"";
377 static const std::unordered_set<std::string> twoOpInstructions = {
378 "add",
"sub",
"mul",
"div",
"mod",
"cmp",
"fcmp",
"mov",
"and",
"or",
"xor"};
382 for (
size_t i = 0; i < code.size(); ++i) {
387 std::string movDst, movSrc;
388 if (!
parse2(t0,
"mov", movDst, movSrc))
390 if (movDst == movSrc) {
399 if (j >= code.size())
403 if (!t1.empty() && t1.back() ==
':')
406 auto sp = t1.find(
' ');
407 if (sp == std::string::npos)
409 std::string op = t1.substr(0, sp);
411 if (twoOpInstructions.find(op) == twoOpInstructions.end())
414 std::string arg1, arg2;
415 if (!
parse2(t1, op, arg1, arg2))
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) {
429 if (std::regex_search(tk, wordPat)) {
433 if (!tk.empty() && tk.find(
"function ") != std::string::npos)
438 std::string ttk =
trim(tk);
448 if (op ==
"cmp" || op ==
"fcmp") {
449 code[j] =
"\t\t" + op +
" " + movSrc +
", " + arg2;
463 if (!movSrc.empty() && (std::isdigit((
unsigned char)movSrc[0]) || movSrc[0] ==
'-' || movSrc[0] ==
'"' || movSrc[0] ==
'\''))
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) {
473 if (std::regex_search(tk, srcPat)) {
477 if (!tk.empty() && tk.find(
"function ") != std::string::npos)
482 code[j] =
"\t\t" + op +
" " + movSrc +
", " + arg2;
502 static const std::unordered_set<std::string> arithOps = {
503 "add",
"sub",
"mul",
"div",
"mod",
"and",
"or",
"xor"};
507 for (
size_t i = 0; i + 2 < code.size(); ++i) {
511 std::string mDst, mSrc;
512 if (!
parse2(t0,
"mov", mDst, mSrc))
520 if (j >= code.size())
523 if (t1.empty() || t1.back() ==
':')
525 auto sp = t1.find(
' ');
526 if (sp == std::string::npos)
528 std::string op = t1.substr(0, sp);
529 if (arithOps.find(op) == arithOps.end())
532 if (!
parse2(t1, op, a1, a2))
542 if (k >= code.size())
545 std::string m2Dst, m2Src;
546 if (!
parse2(t2,
"mov", m2Dst, m2Src))
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) {
560 if (std::regex_search(tw, wordPat)) {
564 if (tw.find(
"function ") != std::string::npos)
570 code[i] =
"\t\tmov " + m2Dst +
", " + mSrc;
571 code[j] =
"\t\t" + op +
" " + m2Dst +
", " + a2;
589 std::string
mxvmOpt(
const std::string &text) {
590 std::vector<std::string> lines;
592 std::istringstream is(text);
594 while (std::getline(is, ln))
598 size_t dataStart = 0, dataEnd = 0, codeStart = 0, codeEnd = 0;
602 for (
auto &ln : lines)
611 for (
auto &ln : lines)
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]);
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);
626 for (
size_t i = 0; i < code.size();) {
627 std::string raw0 = code[i];
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());
641 if (k < code.size()) {
642 std::string raw1 = code[k];
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);
655 pass1.push_back(raw0);
659 pass1.push_back(raw0);
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);
667 for (
size_t i = 0; i < pass1.size(); ++i) {
668 std::string raw = pass1[i];
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) {
677 if (!nxt.empty() && std::regex_search(nxt, word)) {
685 std::string tnxt =
trim(nxt);
695 pass2.push_back(raw);
700 std::vector<std::string> pass3;
701 pass3.reserve(pass2.size());
702 for (
auto &ln : pass2)
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());
715 for (
auto &ln : finalLines)