12.8 切片 1:寄存器码骨架(MOVE/LOADK/RET)。
- Codegen.h/cpp:帧寄存器(0 起声明序)、常量表、函数表、小端映像拼装 - 切片 1 范围:PROGRAM 标量 + 字面量 LOADK + 变量 MOVE + RET;其余构造报 codegen error - codegen_test:23 断言(用例 01 空 MAIN 出 RET、02 LOADK r0/r1 + 常量表),ctest 9/9
This commit is contained in:
@@ -67,3 +67,14 @@ target_compile_definitions(typecheck_test PRIVATE
|
||||
|
||||
add_test(NAME typecheck_types
|
||||
COMMAND typecheck_test)
|
||||
|
||||
# 寄存器码测试(12.8 切片 1):用例 01/02 出映像(REPO_ROOT 注入源目录绝对路径)
|
||||
add_executable(codegen_test
|
||||
./src/codegen_test.cpp)
|
||||
|
||||
target_link_libraries(codegen_test PRIVATE compiler)
|
||||
target_compile_definitions(codegen_test PRIVATE
|
||||
REPO_ROOT="${CMAKE_SOURCE_DIR}")
|
||||
|
||||
add_test(NAME codegen_slice1
|
||||
COMMAND codegen_test)
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* @file codegen_test.cpp
|
||||
* @brief 寄存器码测试(12.8 切片 1):用例 01/02 出映像
|
||||
* @author
|
||||
* @date 2026-08-21
|
||||
*/
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "compiler/Codegen.h"
|
||||
#include "compiler/Linker.h"
|
||||
#include "compiler/Project.h"
|
||||
#include "compiler/Typecheck.h"
|
||||
#include "isa/Encode.h"
|
||||
#include "isa/Image.h"
|
||||
|
||||
#ifndef REPO_ROOT
|
||||
#define REPO_ROOT "."
|
||||
#endif
|
||||
|
||||
static int g_checks = 0;
|
||||
|
||||
#define CHECK(cond) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
std::printf("FAIL %s:%d: %s\n", __FILE__, __LINE__, #cond); \
|
||||
return false; \
|
||||
} \
|
||||
++g_checks; \
|
||||
} while (0)
|
||||
|
||||
// 从用例目录走完整编译管线(解析 → 链接 → 类型检查 → 代码生成)
|
||||
static bool compile_case(const char* dir, std::vector<uint8_t>* image, std::string* err) {
|
||||
using namespace compiler;
|
||||
const std::string toml = std::string(REPO_ROOT) + "/tests/cases/" + dir + "/project.toml";
|
||||
Project p;
|
||||
if (!parse_project(toml, &p, err)) {
|
||||
return false;
|
||||
}
|
||||
std::vector<SourceUnit> units;
|
||||
for (const std::string& f : compile_files(p)) {
|
||||
SourceUnit u;
|
||||
if (!load_unit(p.base_dir + "/" + f, &u, err)) {
|
||||
return false;
|
||||
}
|
||||
units.push_back(std::move(u));
|
||||
}
|
||||
LinkResult link;
|
||||
if (!link_project(p, units, &link, err)) {
|
||||
return false;
|
||||
}
|
||||
if (!check_project(p, units, link, err)) {
|
||||
return false;
|
||||
}
|
||||
return codegen_project(p, units, link, image, err);
|
||||
}
|
||||
|
||||
// ---- 1. 用例 01:空 MAIN + RET ----
|
||||
|
||||
static bool test_case01() {
|
||||
std::vector<uint8_t> img;
|
||||
std::string err;
|
||||
CHECK(compile_case("01_empty_main", &img, &err));
|
||||
|
||||
const isa::ImageView v = isa::ImageView::from(img);
|
||||
CHECK(v.ok());
|
||||
CHECK(v.header().cycle_limit == 1000);
|
||||
CHECK(v.header().dt_ms == 10);
|
||||
CHECK(v.header().entry_fn_id == 0);
|
||||
CHECK(v.header().n_funcs == 1);
|
||||
CHECK(v.header().n_consts == 0);
|
||||
CHECK(v.header().n_globals == 0);
|
||||
CHECK(v.header().project_hash != isa::kFnvBasis);
|
||||
|
||||
const isa::FuncRow r = v.func_row(0);
|
||||
CHECK(r.nregs == 0);
|
||||
CHECK(r.code_len == 1);
|
||||
|
||||
char buf[32];
|
||||
isa::disasm(v.code_bytes()[0], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "RET") == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---- 2. 用例 02:BOOL 赋值(TRUE / FALSE → LOADK)----
|
||||
|
||||
static bool test_case02() {
|
||||
std::vector<uint8_t> img;
|
||||
std::string err;
|
||||
CHECK(compile_case("02_bool_assign", &img, &err));
|
||||
|
||||
const isa::ImageView v = isa::ImageView::from(img);
|
||||
CHECK(v.ok());
|
||||
CHECK(v.header().n_funcs == 1);
|
||||
CHECK(v.header().n_consts == 2); // TRUE 与 FALSE
|
||||
|
||||
const isa::FuncRow r = v.func_row(0);
|
||||
CHECK(r.nregs == 2); // a, b
|
||||
CHECK(r.code_len == 3);
|
||||
|
||||
// 从字节码段取指令(按函数行 code_offset 定位)
|
||||
const uint8_t* base = v.code_bytes();
|
||||
char buf[64];
|
||||
isa::disasm(reinterpret_cast<const uint32_t*>(base)[0], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOADK r0, 0") == 0); // a := TRUE(常量 0)
|
||||
isa::disasm(reinterpret_cast<const uint32_t*>(base)[1], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOADK r1, 1") == 0); // b := FALSE(常量 1)
|
||||
isa::disasm(reinterpret_cast<const uint32_t*>(base)[2], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "RET") == 0);
|
||||
|
||||
// 常量表:0 = BOOL 1,1 = BOOL 0
|
||||
const isa::ConstEntry c0 = v.const_entry(0);
|
||||
CHECK(c0.tag == isa::types::Bool && c0.value == 1);
|
||||
const isa::ConstEntry c1 = v.const_entry(1);
|
||||
CHECK(c1.tag == isa::types::Bool && c1.value == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
if (!test_case01()) return 1;
|
||||
if (!test_case02()) return 1;
|
||||
std::printf("codegen_test: %d checks passed\n", g_checks);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user