stage2 提供c后端 提交stage1的测试

This commit is contained in:
zzy committed 2026-09-20 17:56:11 +08:00
1 parent 846f441e3a
commit 51d408d524
82 files changed
+6872 -65

No files matched your search

+193 -3
View File
@@ -46,6 +46,65 @@ static const char *splc0_srcs[] = {
"stage1/vm_opt.c",
"stage0/spl_mcode.c",
};
static const char* splc1_deps[] = {
"stage2/sys/exit.spl",
"stage2/sys/file.spl",
"stage2/sys/mem.spl",
"stage2/sys/spl_rt.h",
"stage2/sys/spl_vm_embed.h",
"stage2/sys/time.spl",
"stage2/sys/vm.spl",
"stage2/utils/algorithm.spl",
"stage2/utils/arena.spl",
"stage2/utils/ascii.spl",
"stage2/utils/byte_buffer.spl",
"stage2/utils/byte_view.spl",
"stage2/utils/error.spl",
"stage2/utils/fmt.spl",
"stage2/utils/hash.spl",
"stage2/utils/io.spl",
"stage2/utils/json.spl",
"stage2/utils/log.spl",
"stage2/utils/lsp_frame.spl",
"stage2/utils/map.spl",
"stage2/utils/memory.spl",
"stage2/utils/mp.spl",
"stage2/utils/path.spl",
"stage2/utils/profile.spl",
"stage2/utils/set.spl",
"stage2/utils/source.spl",
"stage2/utils/str.spl",
"stage2/utils/utf8.spl",
"stage2/utils/value.spl",
"stage2/utils/vec.spl",
"stage2/ast.spl",
"stage2/ast2ir.spl",
"stage2/attr.spl",
"stage2/def.spl",
"stage2/diag.spl",
"stage2/eval.spl",
"stage2/intrin.spl",
"stage2/ir.spl",
"stage2/ir2c.spl",
"stage2/ir2vm.spl",
"stage2/ir_builder.spl",
"stage2/lang_type.spl",
"stage2/layout.spl",
"stage2/lexer.spl",
"stage2/mcode.spl",
"stage2/parser.spl",
"stage2/scope.spl",
"stage2/sema.spl",
"stage2/splc1.spl",
"stage2/token.spl",
"stage2/type_table.spl",
};
static const char* splc2_deps[] = {
};
/* clang-format on */
static const char *obj_path(const char *src) {
@@ -76,6 +135,8 @@ static const char *sir_path(const char *name) {
return nob_temp_sprintf(BUILD_FOLDER "%s.sir", name);
}
static const char *c_path(const char *name) { return nob_temp_sprintf(BUILD_FOLDER "%s.c", name); }
static bool sync_cflags_stamp(void) {
Nob_String_View cflags = nob_sv_from_cstr(CFLAGS_STR);
Nob_String_Builder old = {0};
@@ -107,6 +168,7 @@ typedef struct build {
BUILD_EXE,
BUILD_EXE_WITH_OPTIMIZATION,
BUILD_SIR,
BUILD_NATIVE,
} kind;
union {
struct {
@@ -118,7 +180,15 @@ typedef struct build {
struct {
const char *src;
const char *compiler;
const char **deps;
size_t deps_count;
} sir;
struct {
const char *src;
const char *compiler;
const char **deps;
size_t deps_count;
} native;
};
} build_t;
@@ -201,6 +271,60 @@ defer:
return NULL;
}
static const char *build_native(const char *name) {
const char *exe = exe_path(name);
const char *cli = build_target("spl_cli");
const char *sir = build_target("splc1");
if (!cli || !sir) {
nob_log(NOB_ERROR, "failed to build prerequisites for `%s`", name);
return NULL;
}
const char *cpath = BUILD_FOLDER "splc1.c";
const char *inputs[] = {sir,
"stage2/sys/spl_rt.h",
"stage2/sys/spl_vm_embed.h",
"stage2/sys/spl_vm_embed.c",
"stage0/spl_vm.c",
"stage0/spl_mcode.c",
"stage0/spl_syscall.c",
"stage0/spl_vm.h",
"stage0/spl_mcode.h"};
int needs = nob_needs_rebuild(exe, inputs, NOB_ARRAY_LEN(inputs));
if (needs < 0)
return NULL;
if (needs == 0)
return exe;
Nob_Cmd cmd = {0};
if (nob_file_exists(exe)) {
// 已有原生编译器:用原生自举重新生成 C(0.1s 级)
nob_cmd_append(&cmd, exe, "--dump", "c", "stage2/splc1.spl", cpath);
} else {
// 冷启动:用 VM 版 splc1 生成 C
nob_cmd_append(&cmd, cli, sir, "--dump", "c", "stage2/splc1.spl", cpath);
}
if (!nob_cmd_run(&cmd)) {
nob_log(NOB_ERROR, "ir2c C generation failed");
nob_cmd_free(cmd);
return NULL;
}
cmd.count = 0;
nob_cc(&cmd);
nob_cc_inputs(&cmd, cpath);
nob_cc_inputs(&cmd, "stage2/sys/spl_vm_embed.c");
nob_cc_inputs(&cmd, "stage0/spl_vm.c");
nob_cc_inputs(&cmd, "stage0/spl_mcode.c");
nob_cc_inputs(&cmd, "stage0/spl_syscall.c");
nob_cc_output(&cmd, exe);
if (!nob_cmd_run(&cmd)) {
nob_log(NOB_ERROR, "native link failed");
nob_cmd_free(cmd);
return NULL;
}
nob_cmd_free(cmd);
return exe;
}
static build_t targets[] = {
{
"spl_cli",
@@ -237,17 +361,50 @@ static build_t targets[] = {
{
"splc1",
BUILD_SIR,
.sir = {.src = "stage2/splc1.spl", .compiler = "splc0"},
.sir = {.src = "stage2/splc1.spl",
.compiler = "splc0",
.deps = splc1_deps,
.deps_count = NOB_ARRAY_LEN(splc1_deps)},
},
{
"splc1s",
BUILD_SIR,
.sir = {.src = "stage2/splc1.spl", .compiler = "splc1"},
.sir = {.src = "stage2/splc1.spl",
.compiler = "splc1",
.deps = splc1_deps,
.deps_count = NOB_ARRAY_LEN(splc1_deps)},
},
{
"splc1r",
BUILD_SIR,
.sir = {.src = "stage2/splc1.spl", .compiler = "splc1s"},
.sir = {.src = "stage2/splc1.spl",
.compiler = "splc1s",
.deps = splc1_deps,
.deps_count = NOB_ARRAY_LEN(splc1_deps)},
},
{
"splc1n",
BUILD_NATIVE,
.native = {.src = "stage2/splc1.spl",
.compiler = "splc1",
.deps = splc1_deps,
.deps_count = NOB_ARRAY_LEN(splc1_deps)},
},
{
"splc2",
BUILD_SIR,
.sir = {.src = "stage3/splc2.spl",
.compiler = "splc1n",
.deps = splc2_deps,
.deps_count = NOB_ARRAY_LEN(splc2_deps)},
},
{
"splc2n",
BUILD_NATIVE,
.native = {.src = "stage3/splc2.spl",
.compiler = "splc1n",
.deps = splc2_deps,
.deps_count = NOB_ARRAY_LEN(splc2_deps)},
},
};
@@ -276,6 +433,38 @@ const char *build_target(const char *name) {
nob_cmd_free(cmd);
return target_sir;
}
case BUILD_NATIVE: {
Nob_Cmd cmd = {0};
const char *target_exe = exe_path(name);
const char *target_c = c_path(name);
// TODO need_rebuild
int needs =
nob_needs_rebuild(target_exe, target->native.deps, target->native.deps_count);
if (needs < 0)
return NULL;
if (needs == 0)
return target_exe;
nob_cmd_append(&cmd, "--dump", "c", target->native.src, target_c);
if (!run_target(target->native.compiler, &cmd)) {
nob_log(NOB_ERROR, "failed to build `%s`", name);
nob_cmd_free(cmd);
return NULL;
}
cmd.count = 0;
nob_cc(&cmd);
nob_cmd_append(&cmd, "-I./stage2/sys", "-O2", "-D_CRT_SECURE_NO_WARNINGS");
nob_cc_inputs(&cmd, target_c);
nob_cc_output(&cmd, target_exe);
if (!nob_cmd_run(&cmd)) {
nob_log(NOB_ERROR, "failed to build `%s`", name);
nob_cmd_free(cmd);
return NULL;
}
nob_cmd_free(cmd);
return target_exe;
}
default:
NOB_UNREACHABLE("build_t.kind");
}
@@ -287,6 +476,7 @@ const char *build_target(const char *name) {
static run_t runs[] = {
{"spl_cli", NULL}, {"vm_test", NULL}, {"splc0", NULL},
{"splc1", "spl_cli"}, {"splc1r", "spl_cli"}, {"splc1s", "spl_cli"},
{"splc1n", NULL}, {"splc2", "spl_cli"}, {"splc2n", NULL},
};
bool run_target_dry(const char *name, Nob_Cmd *args, Nob_Cmd *result) {