12.8 切片 4:CMP_* 与 IF/ELSIF/ELSE 跳转。
- CMP_xx:两侧求值到临时后比较;IF 编成 <cond→t> JF t, L_next <body> JMP L_end 链 - 分支尾部 JMP 与条件 JF 双回填;无 else 时末分支 JF 直接落 L_end - codegen_test:89 断言(用例 04 完整跳转序列),ctest 9/9
This commit is contained in:
@@ -347,6 +347,56 @@ static bool test_not() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---- 9. 用例 04:IF / ELSIF / ELSE(CMP + JF + JMP 回填)----
|
||||
|
||||
static bool test_case04() {
|
||||
std::vector<uint8_t> img;
|
||||
std::string err;
|
||||
CHECK(compile_case("04_if_elsif_else", &img, &err));
|
||||
|
||||
const isa::ImageView v = isa::ImageView::from(img);
|
||||
CHECK(v.ok());
|
||||
const isa::FuncRow r = v.func_row(0);
|
||||
CHECK(r.nregs == 5); // sel out + 3 临时(CMP 目的 + 两操作数)
|
||||
CHECK(r.code_len == 14);
|
||||
|
||||
char buf[64];
|
||||
const uint8_t* base = v.code_bytes();
|
||||
const uint32_t* ins = reinterpret_cast<const uint32_t*>(base);
|
||||
// IF sel = 0 THEN:sel→r3、0→r4、CMP_EQ r2(常量序:0、10、1、20、30)
|
||||
isa::disasm(ins[0], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "MOVE r3, r0") == 0);
|
||||
isa::disasm(ins[1], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOADK r4, 0") == 0);
|
||||
isa::disasm(ins[2], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "CMP_EQ r2, r3, r4") == 0);
|
||||
isa::disasm(ins[3], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "JF r2, +2") == 0); // 假 → elsif([6])
|
||||
isa::disasm(ins[4], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOADK r1, 1") == 0); // out := 10(常量 1)
|
||||
isa::disasm(ins[5], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "JMP +7") == 0); // → end([13])
|
||||
// ELSIF sel = 1
|
||||
isa::disasm(ins[6], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "MOVE r3, r0") == 0);
|
||||
isa::disasm(ins[7], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOADK r4, 2") == 0);
|
||||
isa::disasm(ins[8], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "CMP_EQ r2, r3, r4") == 0);
|
||||
isa::disasm(ins[9], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "JF r2, +2") == 0); // 假 → else([12])
|
||||
isa::disasm(ins[10], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOADK r1, 3") == 0);
|
||||
isa::disasm(ins[11], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "JMP +1") == 0); // → end([13])
|
||||
// ELSE
|
||||
isa::disasm(ins[12], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOADK r1, 4") == 0);
|
||||
isa::disasm(ins[13], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "RET") == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
if (!test_case01()) return 1;
|
||||
if (!test_case02()) return 1;
|
||||
@@ -356,6 +406,7 @@ int main() {
|
||||
if (!test_write_input()) return 1;
|
||||
if (!test_case03()) return 1;
|
||||
if (!test_not()) return 1;
|
||||
if (!test_case04()) return 1;
|
||||
std::printf("codegen_test: %d checks passed\n", g_checks);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user