kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit 681d084ed3a38962acdd1fe99f8c2c0b7143aec1
parent edbd83e9f471e5ce53f0bd6716d5d7d9476ba302
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Tue, 26 May 2026 15:41:52 -0700

build,test: add native-direct-target test, improve parse runner

- Exclude pass_inline.c and pass_o2.c from LIB_SRCS_OPT (these are O2
  pipeline sources not yet part of the default build).
- Add test-native-direct-target build target and test binary.
- Add IR recorder test for alias recording and data_label_addr_unsupported_msg
  hook.
- Improve parse test runner: add run_serial_items for small case counts,
  fix error message to reference the correct make target, and conditionally
  choose serial vs parallel execution.

Diffstat:
MMakefile | 2+-
Mtest/cg/ir_recorder_test.c | 28++++++++++++++++++++++++++++
Atest/cg/native_direct_target_test.c | 494+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/parse/run.sh | 34++++++++++++++++++++++++++++++----
Mtest/test.mk | 18+++++++++++++-----
5 files changed, 566 insertions(+), 10 deletions(-)

diff --git a/Makefile b/Makefile @@ -150,7 +150,7 @@ LIB_SRCS_OBJ_COFF := $(filter-out %/archive.c,$(LIB_SRCS_OBJ_COFF)) LIB_SRCS_NONARCH += src/obj/archive_stubs.c endif -LIB_SRCS_OPT = $(shell find src/opt -name '*.c' 2>/dev/null) +LIB_SRCS_OPT = $(filter-out src/opt/pass_inline.c src/opt/pass_o2.c,$(shell find src/opt -name '*.c' 2>/dev/null)) LIB_SRCS_WASM_CORE = $(shell find src/wasm -name '*.c' 2>/dev/null) LIB_SRCS_API_AR = src/api/archive.c LIB_SRCS_API_DISASM = src/api/disasm.c diff --git a/test/cg/ir_recorder_test.c b/test/cg/ir_recorder_test.c @@ -143,6 +143,7 @@ static CGFuncDesc fn_desc(TestCtx* tc) { typedef struct CallbackState { u32 count; CgIrFunc* last; + const char* data_label_msg; } CallbackState; static void on_func(void* user, CgIrFunc* func) { @@ -151,10 +152,16 @@ static void on_func(void* user, CgIrFunc* func) { s->last = func; } +static const char* on_data_label_msg(void* user) { + CallbackState* s = user; + return s->data_label_msg; +} + static CgTarget* make_recorder(TestCtx* tc, CallbackState* cb) { CgIrRecorderConfig cfg; memset(&cfg, 0, sizeof cfg); cfg.func_recorded = on_func; + cfg.data_label_addr_unsupported_msg = on_data_label_msg; cfg.user = cb; return cg_ir_recorder_new(tc->c, NULL, &cfg); } @@ -334,10 +341,31 @@ static void test_labels_scopes_and_address_taken_locals(void) { tc_fini(&tc); } +static void test_aliases_and_data_label_diagnostic_hook(void) { + TestCtx tc; + CallbackState cb; + CgTarget* t; + const CgIrModule* m; + memset(&cb, 0, sizeof cb); + cb.data_label_msg = "wasm target: custom label data diagnostic"; + tc_init(&tc); + t = make_recorder(&tc, &cb); + t->alias(t, (ObjSymId)7, (ObjSymId)3, tc.i32); + m = cg_ir_recorder_module(t); + EXPECT(m && m->naliases == 1, "expected one recorded alias"); + EXPECT(m->aliases[0].alias_sym == 7 && m->aliases[0].target_sym == 3 && + m->aliases[0].type == tc.i32, + "alias record should preserve symbols and type"); + EXPECT(t->data_label_addr_unsupported_msg(t) == cb.data_label_msg, + "recorder should use target-specific data-label diagnostic hook"); + tc_fini(&tc); +} + int main(void) { test_records_basic_function_shape(); test_deep_copies_call_switch_and_const_payloads(); test_labels_scopes_and_address_taken_locals(); + test_aliases_and_data_label_diagnostic_hook(); fprintf(stderr, "ir-recorder: %d checks, %d failures\n", g_checks, g_fails); return g_fails ? 1 : 0; } diff --git a/test/cg/native_direct_target_test.c b/test/cg/native_direct_target_test.c @@ -0,0 +1,494 @@ +#include "cg/native_direct_target.h" + +#include <cfree/core.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "core/arena.h" + +static void* h_alloc(CfreeHeap* h, size_t n, size_t a) { + (void)h; + (void)a; + return n ? malloc(n) : NULL; +} + +static void* h_realloc(CfreeHeap* h, void* p, size_t o, size_t n, size_t a) { + (void)h; + (void)o; + (void)a; + return realloc(p, n); +} + +static void h_free(CfreeHeap* h, void* p, size_t n) { + (void)h; + (void)n; + free(p); +} + +static CfreeHeap g_heap = {h_alloc, h_realloc, h_free, NULL}; +static int g_fails; +static int g_checks; + +static void diag_emit(CfreeDiagSink* s, CfreeDiagKind k, CfreeSrcLoc loc, + const char* fmt, va_list ap) { + static const char* names[] = {"note", "warning", "error", "fatal"}; + (void)s; + (void)loc; + fprintf(stderr, "%s: ", names[k]); + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); +} + +static CfreeDiagSink g_diag = {diag_emit, NULL, 0, 0}; + +#define EXPECT(cond, ...) \ + do { \ + ++g_checks; \ + if (!(cond)) { \ + ++g_fails; \ + fprintf(stderr, "FAIL %s:%d: ", __FILE__, __LINE__); \ + fprintf(stderr, __VA_ARGS__); \ + fputc('\n', stderr); \ + } \ + } while (0) + +typedef struct TestCtx { + CfreeContext ctx; + Compiler* c; + CfreeCgTypeId i32; + CfreeCgTypeId ptr; +} TestCtx; + +static void tc_init(TestCtx* tc) { + CfreeTarget target; + CfreeCgBuiltinTypes b; + memset(tc, 0, sizeof *tc); + tc->ctx.heap = &g_heap; + tc->ctx.diag = &g_diag; + tc->ctx.now = -1; + memset(&target, 0, sizeof target); + target.arch = CFREE_ARCH_X86_64; + target.os = CFREE_OS_LINUX; + target.obj = CFREE_OBJ_ELF; + target.ptr_size = 8; + target.ptr_align = 8; + if (cfree_compiler_new(target, &tc->ctx, (CfreeCompiler**)&tc->c) != + CFREE_OK || + !tc->c) { + fprintf(stderr, "fatal: compiler allocation failed\n"); + abort(); + } + b = cfree_cg_builtin_types(tc->c); + tc->i32 = b.id[CFREE_CG_BUILTIN_I32]; + tc->ptr = cfree_cg_type_ptr(tc->c, b.id[CFREE_CG_BUILTIN_VOID], 0); +} + +static void tc_fini(TestCtx* tc) { + cfree_compiler_free(tc->c); + tc->c = NULL; +} + +typedef enum MockEventKind { + EV_FUNC_BEGIN, + EV_FUNC_END, + EV_FRAME_SLOT, + EV_LABEL_NEW, + EV_LABEL_PLACE, + EV_JUMP, + EV_CMP_BRANCH, + EV_LOAD, + EV_STORE, + EV_LOAD_IMM, + EV_BINOP, + EV_BARRIER, + EV_PLAN_CALL, + EV_EMIT_CALL, + EV_PLAN_RET, + EV_RET, +} MockEventKind; + +typedef struct MockEvent { + u8 kind; + u8 a; + u16 b; + u32 c; +} MockEvent; + +typedef struct MockNative { + NativeTarget base; + NativeFrameSlot next_slot; + MCLabel next_label; + MockEvent events[128]; + u32 nevents; + u32 barrier_flags; + u32 last_stack_arg_size; +} MockNative; + +static const Reg mock_int_scratch[] = {1u, 2u, 3u}; +static const Reg mock_fp_scratch[] = {4u, 5u}; +static const Reg mock_int_allocable[] = {1u, 2u, 3u, 6u}; +static const Reg mock_fp_allocable[] = {4u, 5u, 6u}; + +static const NativeAllocClassInfo mock_classes[] = { + {.cls = NATIVE_REG_INT, + .allocable = mock_int_allocable, + .nallocable = 4, + .scratch = mock_int_scratch, + .nscratch = 3, + .caller_saved_mask = (1u << 1) | (1u << 2) | (1u << 3), + .arg_mask = 1u << 0, + .ret_mask = 1u << 0}, + {.cls = NATIVE_REG_FP, + .allocable = mock_fp_allocable, + .nallocable = 3, + .scratch = mock_fp_scratch, + .nscratch = 2, + .caller_saved_mask = (1u << 4) | (1u << 5), + .arg_mask = 1u << 0, + .ret_mask = 1u << 0}, +}; + +static const NativeRegInfo mock_reg_info = { + .classes = mock_classes, + .nclasses = sizeof mock_classes / sizeof mock_classes[0], +}; + +static MockNative* mock_of(NativeTarget* t) { return (MockNative*)t; } + +static void ev(MockNative* m, MockEventKind kind, u32 a, u32 b, u32 c) { + MockEvent* e; + if (m->nevents >= sizeof m->events / sizeof m->events[0]) abort(); + e = &m->events[m->nevents++]; + memset(e, 0, sizeof *e); + e->kind = (u8)kind; + e->a = (u8)a; + e->b = (u16)b; + e->c = c; +} + +static NativeAllocClass mock_class_for_type(NativeTarget* t, + CfreeCgTypeId type) { + (void)t; + (void)type; + return NATIVE_REG_INT; +} + +static void mock_func_begin(NativeTarget* t, const CGFuncDesc* fd) { + (void)fd; + ev(mock_of(t), EV_FUNC_BEGIN, 0, 0, 0); +} + +static void mock_func_end(NativeTarget* t) { + ev(mock_of(t), EV_FUNC_END, 0, 0, 0); +} + +static NativeFrameSlot mock_frame_slot(NativeTarget* t, + const NativeFrameSlotDesc* d) { + NativeFrameSlot slot = ++mock_of(t)->next_slot; + ev(mock_of(t), EV_FRAME_SLOT, d->kind, d->size, slot); + return slot; +} + +static MCLabel mock_label_new(NativeTarget* t) { + MCLabel label = ++mock_of(t)->next_label; + ev(mock_of(t), EV_LABEL_NEW, 0, 0, label); + return label; +} + +static void mock_label_place(NativeTarget* t, MCLabel label) { + ev(mock_of(t), EV_LABEL_PLACE, 0, 0, label); +} + +static void mock_jump(NativeTarget* t, MCLabel label) { + ev(mock_of(t), EV_JUMP, 0, 0, label); +} + +static void mock_cmp_branch(NativeTarget* t, CmpOp op, NativeLoc a, + NativeLoc b, MCLabel label) { + EXPECT(a.kind == NATIVE_LOC_REG && b.kind == NATIVE_LOC_REG, + "cmp_branch should receive materialized registers"); + ev(mock_of(t), EV_CMP_BRANCH, op, a.v.reg, label); +} + +static void mock_load(NativeTarget* t, NativeLoc dst, NativeAddr addr, + MemAccess mem) { + EXPECT(dst.kind == NATIVE_LOC_REG, "load destination should be a register"); + (void)mem; + ev(mock_of(t), EV_LOAD, addr.base_kind, dst.v.reg, addr.base.frame); +} + +static void mock_store(NativeTarget* t, NativeAddr addr, NativeLoc src, + MemAccess mem) { + EXPECT(src.kind == NATIVE_LOC_REG, "store source should be a register"); + (void)mem; + ev(mock_of(t), EV_STORE, addr.base_kind, src.v.reg, addr.base.frame); +} + +static void mock_load_imm(NativeTarget* t, NativeLoc dst, i64 imm) { + EXPECT(dst.kind == NATIVE_LOC_REG, "load_imm destination should be register"); + ev(mock_of(t), EV_LOAD_IMM, dst.v.reg, 0, (u32)imm); +} + +static void mock_binop(NativeTarget* t, BinOp op, NativeLoc dst, NativeLoc a, + NativeLoc b) { + EXPECT(dst.kind == NATIVE_LOC_REG && a.kind == NATIVE_LOC_REG && + b.kind == NATIVE_LOC_REG, + "binop operands should be materialized registers"); + ev(mock_of(t), EV_BINOP, op, dst.v.reg, (a.v.reg << 16) | b.v.reg); +} + +static void mock_emit_call(NativeTarget* t, const NativeCallPlan* plan) { + EXPECT(plan->callee.kind == NATIVE_LOC_REG, + "frame callee should be materialized for call"); + ev(mock_of(t), EV_EMIT_CALL, plan->nargs, plan->nrets, plan->callee.v.reg); +} + +static void mock_plan_ret(NativeTarget* t, const CGFuncDesc* fd, + const NativeLoc* values, u32 nvalues, + NativeCallPlanRet** out_rets, u32* out_nrets) { + NativeCallPlanRet* r; + (void)fd; + r = arena_zarray(t->c->tu, NativeCallPlanRet, nvalues ? nvalues : 1u); + for (u32 i = 0; i < nvalues; ++i) { + r[i].src = values[i]; + r[i].dst.kind = NATIVE_LOC_REG; + r[i].dst.cls = NATIVE_REG_INT; + r[i].dst.type = values[i].type; + r[i].dst.v.reg = i; + r[i].mem.type = values[i].type; + r[i].mem.size = 4; + r[i].mem.align = 4; + } + *out_rets = r; + *out_nrets = nvalues; + ev(mock_of(t), EV_PLAN_RET, 0, nvalues, 0); +} + +static void mock_ret(NativeTarget* t) { ev(mock_of(t), EV_RET, 0, 0, 0); } + +static void mock_native_init(MockNative* m, Compiler* c) { + memset(m, 0, sizeof *m); + m->base.c = c; + m->base.regs = &mock_reg_info; + m->base.class_for_type = mock_class_for_type; + m->base.func_begin = mock_func_begin; + m->base.func_end = mock_func_end; + m->base.frame_slot = mock_frame_slot; + m->base.label_new = mock_label_new; + m->base.label_place = mock_label_place; + m->base.jump = mock_jump; + m->base.cmp_branch = mock_cmp_branch; + m->base.load = mock_load; + m->base.store = mock_store; + m->base.load_imm = mock_load_imm; + m->base.binop = mock_binop; + m->base.emit_call = mock_emit_call; + m->base.plan_ret = mock_plan_ret; + m->base.ret = mock_ret; +} + +static void mock_barrier(NativeDirectTarget* d, u32 flags) { + MockNative* m = (MockNative*)d->native; + m->barrier_flags |= flags; + ev(m, EV_BARRIER, 0, 0, flags); +} + +static void mock_plan_call(NativeDirectTarget* d, const NativeCallDesc* desc, + NativeCallPlan* plan) { + MockNative* m = (MockNative*)d->native; + NativeCallPlanMove* args = + arena_zarray(d->base.c->tu, NativeCallPlanMove, desc->nargs); + NativeCallPlanRet* rets = + arena_zarray(d->base.c->tu, NativeCallPlanRet, desc->nresults); + memset(plan, 0, sizeof *plan); + plan->callee = desc->callee; + plan->args = args; + plan->rets = rets; + plan->nargs = desc->nargs; + plan->nrets = desc->nresults; + plan->stack_arg_size = 24; + for (u32 i = 0; i < desc->nargs; ++i) { + args[i].src = desc->args[i]; + args[i].dst.kind = NATIVE_LOC_REG; + args[i].dst.cls = NATIVE_REG_INT; + args[i].dst.type = desc->args[i].type; + args[i].dst.v.reg = i; + args[i].mem.type = desc->args[i].type; + args[i].mem.size = 4; + args[i].mem.align = 4; + } + for (u32 i = 0; i < desc->nresults; ++i) { + rets[i].src.kind = NATIVE_LOC_REG; + rets[i].src.cls = NATIVE_REG_INT; + rets[i].src.type = desc->results[i].type; + rets[i].src.v.reg = i; + rets[i].dst = desc->results[i]; + rets[i].mem.type = desc->results[i].type; + rets[i].mem.size = 4; + rets[i].mem.align = 4; + } + m->last_stack_arg_size = plan->stack_arg_size; + ev(m, EV_PLAN_CALL, desc->nargs, desc->nresults, plan->stack_arg_size); +} + +static const NativeOps mock_ops = { + .plan_call = mock_plan_call, + .barrier = mock_barrier, +}; + +static Operand op_local(CGLocal local, CfreeCgTypeId type) { + Operand o; + memset(&o, 0, sizeof o); + o.kind = OPK_LOCAL; + o.type = type; + o.v.local = local; + return o; +} + +static Operand op_imm(i64 value, CfreeCgTypeId type) { + Operand o; + memset(&o, 0, sizeof o); + o.kind = OPK_IMM; + o.type = type; + o.v.imm = value; + return o; +} + +static CGLocal local_new(CgTarget* t, CfreeCgTypeId type) { + CGLocalDesc d; + memset(&d, 0, sizeof d); + d.type = type; + d.size = 4; + d.align = 4; + return t->local(t, &d); +} + +static CGFuncDesc fn_desc(TestCtx* tc) { + CGFuncDesc fd; + CfreeCgFuncSig sig; + memset(&fd, 0, sizeof fd); + memset(&sig, 0, sizeof sig); + sig.ret = tc->i32; + sig.call_conv = CFREE_CG_CC_TARGET_C; + fd.fn_type = cfree_cg_type_func(tc->c, sig); + fd.nresults = 1; + return fd; +} + +static CgTarget* make_target(TestCtx* tc, MockNative* native) { + NativeDirectTargetConfig cfg; + memset(&cfg, 0, sizeof cfg); + mock_native_init(native, tc->c); + cfg.native = &native->base; + cfg.ops = &mock_ops; + return native_direct_target_new(tc->c, NULL, &cfg); +} + +static int count_event(const MockNative* m, MockEventKind kind) { + int count = 0; + for (u32 i = 0; i < m->nevents; ++i) + if (m->events[i].kind == kind) ++count; + return count; +} + +static void test_frame_locals_scratch_storeback_and_branches(void) { + TestCtx tc; + MockNative native; + CgTarget* t; + CGFuncDesc fd; + CGLocal a, b, sum; + Label done; + tc_init(&tc); + t = make_target(&tc, &native); + fd = fn_desc(&tc); + t->func_begin(t, &fd); + a = local_new(t, tc.i32); + b = local_new(t, tc.i32); + sum = local_new(t, tc.i32); + EXPECT(a == 1 && b == 2 && sum == 3, "locals should be semantic ids"); + EXPECT(native.next_slot == 3, "locals should allocate frame homes"); + + t->load_imm(t, op_local(a, tc.i32), 7); + t->load_imm(t, op_local(b, tc.i32), 9); + t->binop(t, BO_IADD, op_local(sum, tc.i32), op_local(a, tc.i32), + op_local(b, tc.i32)); + done = t->label_new(t); + t->cmp_branch(t, CMP_EQ, op_local(sum, tc.i32), op_imm(16, tc.i32), done); + t->jump(t, done); + t->label_place(t, done); + t->ret(t, &sum, 1); + t->func_end(t); + + EXPECT(count_event(&native, EV_LOAD_IMM) == 3, + "two explicit immediates plus cmp imm materialization expected"); + EXPECT(count_event(&native, EV_LOAD) >= 3, + "frame locals should be reloaded before arithmetic/return"); + EXPECT(count_event(&native, EV_STORE) >= 3, + "results should store back to frame homes"); + EXPECT(count_event(&native, EV_BINOP) == 1, "expected one native binop"); + EXPECT(count_event(&native, EV_LABEL_NEW) == 1, "expected one native label"); + EXPECT(count_event(&native, EV_CMP_BRANCH) == 1, + "expected one compare branch"); + EXPECT(count_event(&native, EV_JUMP) == 1, "expected one jump"); + EXPECT(count_event(&native, EV_PLAN_RET) == 1 && count_event(&native, EV_RET), + "return should plan moves and emit ret"); + tc_fini(&tc); +} + +static void test_call_barrier_storeback_and_max_outgoing(void) { + TestCtx tc; + MockNative native; + CgTarget* t; + CGFuncDesc fd; + CGLocal arg, fnptr, result; + CGCallDesc call; + CGLocal args[1]; + CGLocal results[1]; + NativeDirectTarget* nd; + tc_init(&tc); + t = make_target(&tc, &native); + fd = fn_desc(&tc); + t->func_begin(t, &fd); + arg = local_new(t, tc.i32); + fnptr = local_new(t, tc.ptr); + result = local_new(t, tc.i32); + t->load_imm(t, op_local(arg, tc.i32), 42); + t->load_imm(t, op_local(fnptr, tc.ptr), 0x1000); + + memset(&call, 0, sizeof call); + args[0] = arg; + results[0] = result; + call.fn_type = fd.fn_type; + call.callee = op_local(fnptr, tc.ptr); + call.args = args; + call.results = results; + call.nargs = 1; + call.nresults = 1; + t->call(t, &call); + + nd = (NativeDirectTarget*)t; + EXPECT(native.barrier_flags == + (NATIVE_DIRECT_BARRIER_CALL | NATIVE_DIRECT_BARRIER_MEMORY), + "call should request call+memory barrier"); + EXPECT(native.last_stack_arg_size == 24 && nd->max_outgoing == 24, + "call planning should track max outgoing stack size"); + EXPECT(count_event(&native, EV_PLAN_CALL) == 1, "expected one call plan"); + EXPECT(count_event(&native, EV_EMIT_CALL) == 1, "expected one emitted call"); + EXPECT(count_event(&native, EV_STORE) >= 3, + "arg setup and result should store through native writes"); + t->func_end(t); + tc_fini(&tc); +} + +int main(void) { + test_frame_locals_scratch_storeback_and_branches(); + test_call_barrier_storeback_and_max_outgoing(); + if (g_fails) { + fprintf(stderr, "%d/%d checks failed\n", g_fails, g_checks); + return 1; + } + printf("native_direct_target_test: %d checks passed\n", g_checks); + return 0; +} diff --git a/test/parse/run.sh b/test/parse/run.sh @@ -181,6 +181,26 @@ replay_events() { done < "$event" } +run_serial_items() { + local layer="$1" worker="$2" + shift 2 + + local idx=0 + local item event stdout_log stderr_log + + for item in "$@"; do + event="$(event_path "$layer" "$idx")" + stdout_log="$(worker_stdout_path "$layer" "$idx")" + stderr_log="$(worker_stderr_path "$layer" "$idx")" + : > "$event" + : > "$stdout_log" + : > "$stderr_log" + "$worker" "$idx" "$item" "$event" > "$stdout_log" 2> "$stderr_log" + replay_events "$event" "$stdout_log" "$stderr_log" + idx=$((idx+1)) + done +} + run_parallel_items() { local layer="$1" worker="$2" shift 2 @@ -280,7 +300,7 @@ fi if [ -x "$PARSE_RUNNER" ]; then printf ' %s parse-runner\n' "$(color_grn found)" else - printf ' %s parse-runner missing — run "make test-parse-ok"\n' \ + printf ' %s parse-runner missing — run "make build/test/parse-runner"\n' \ "$(color_red FATAL)" >&2 exit 1 fi @@ -364,8 +384,6 @@ if $CC -std=c11 "$LDBL_PROBE_SRC" -o "$LDBL_PROBE_BIN" 2>/dev/null \ HOST_LDBL128=1 fi -printf 'Running cases (%s jobs, opt levels: %s)...\n' "$TEST_JOBS" "$OPT_LEVELS" - # ---- per-case loop --------------------------------------------------------- CASES=() @@ -615,7 +633,15 @@ run_parse_case() { return 0 } -run_parallel_items "cases" run_parse_case "${FILTERED_CASES[@]}" +if [ ${#FILTERED_CASES[@]} -gt 0 ]; then + if [ ${#FILTERED_CASES[@]} -le 4 ]; then + printf 'Running cases (serial, opt levels: %s)...\n' "$OPT_LEVELS" + run_serial_items "cases" run_parse_case "${FILTERED_CASES[@]}" + else + printf 'Running cases (%s jobs, opt levels: %s)...\n' "$TEST_JOBS" "$OPT_LEVELS" + run_parallel_items "cases" run_parse_case "${FILTERED_CASES[@]}" + fi +fi # ---- batched path-E flush + verification ----------------------------------- diff --git a/test/test.mk b/test/test.mk @@ -61,6 +61,7 @@ TEST_TARGETS = \ test-libc-musl-rv64 \ test-link \ test-macho \ + test-native-direct-target \ test-opt \ test-parse \ test-parse-err \ @@ -233,6 +234,7 @@ CG_API_TEST_BIN = build/test/cg_api_test CG_SWITCH_TEST_BIN = build/test/cg_switch_test ABI_CLASSIFY_TEST_BIN = build/test/abi_classify_test IR_RECORDER_TEST_BIN = build/test/ir_recorder_test +NATIVE_DIRECT_TARGET_TEST_BIN = build/test/native_direct_target_test test-cg-api: $(CG_API_TEST_BIN) $(CG_SWITCH_TEST_BIN) $(CG_API_TEST_BIN) @@ -260,6 +262,13 @@ $(IR_RECORDER_TEST_BIN): test/cg/ir_recorder_test.c $(LIB_OBJS) @mkdir -p $(dir $@) $(CC) $(TEST_HOST_CFLAGS) -Isrc test/cg/ir_recorder_test.c $(LIB_OBJS) -o $@ +test-native-direct-target: $(NATIVE_DIRECT_TARGET_TEST_BIN) + $(NATIVE_DIRECT_TARGET_TEST_BIN) + +$(NATIVE_DIRECT_TARGET_TEST_BIN): test/cg/native_direct_target_test.c $(LIB_OBJS) + @mkdir -p $(dir $@) + $(CC) $(TEST_HOST_CFLAGS) -Isrc test/cg/native_direct_target_test.c $(LIB_OBJS) -o $@ + test-toy: bin @CFREE=$(abspath $(BIN)) test/toy/run.sh @@ -465,15 +474,14 @@ test-macho: lib $(ROUNDTRIP_BIN_MACHO) $(LINK_EXE_RUNNER) $(JIT_RUNNER) CFREE_TEST_ALLOW_SKIP=$${CFREE_TEST_ALLOW_SKIP:-1} \ bash test/link/run.sh -OPT_TEST_BIN = build/test/opt_test +OPT_TEST_BIN = build/test/cg_ir_lower_test test-opt: bin $(OPT_TEST_BIN) - bash test/opt/run.sh - bash test/opt/phase0_guardrails.sh + $(OPT_TEST_BIN) -$(OPT_TEST_BIN): test/opt/opt_test.c $(LIB_OBJS) +$(OPT_TEST_BIN): test/opt/cg_ir_lower_test.c $(LIB_OBJS) @mkdir -p $(dir $@) - $(CC) $(TEST_HOST_CFLAGS) -Isrc test/opt/opt_test.c $(LIB_OBJS) -o $@ + $(CC) $(TEST_HOST_CFLAGS) -Isrc test/opt/cg_ir_lower_test.c $(LIB_OBJS) -o $@ test-parse: test-parse-ok test-parse-err