w6c+w6c_ww: free() compiles to a no-op (ww has no free) (fix #27)

The free(x) builtin lowered to CALL ffi_resolve("free") in cstage and
fell through to a generic CALL free in wwstage (which had no free arm
at all) -- an undefined reference at w6l unless an @symbol decl
happened to be in scope. ww has no free by design (rt/alloc.s:30 --
the bump allocator cannot reclaim a mid-chunk pointer; process exit
does), so both stages now evaluate the operand for side effects
(Hare's free(expr) evaluates expr) and emit nothing else, letting
Hare code that calls free() port verbatim (regex fold-2b calls it at
4+ sites). The 2-arg os.free(p, n) public API is untouched: the
builtin gate requires exactly one bare-ident-callee arg.

930_free_noop_run pins per row: w6c/w6c_ww byte-id, no free symbol
in the .s, deref-after-free validity, and the operand side effect
running once per free() via a global counter.
This commit is contained in:
2026-06-04 06:07:18 +09:00
parent 64f6cc90f2
commit 9732061a7e
6 changed files with 302 additions and 23 deletions

View File

@@ -317,6 +317,7 @@ TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \
$(BIN)/test_modcall_widen_slice \
$(BIN)/test_match_4arm_cross_module \
$(BIN)/test_match_4arm_cross_module_run \
$(BIN)/test_free_noop_run \
$(BIN)/test_variant_typekey_run \
$(BIN)/test_enum_modshadow \
$(BIN)/test_struct_modshadow \
@@ -1525,6 +1526,12 @@ $(BIN)/test_match_4arm_cross_module_run: test/wcc/929_match_4arm_cross_module_ru
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
$(BIN)/test_free_noop_run: test/wcc/930_free_noop_run.c \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
$(BIN)/test_variant_typekey_run: test/wcc/931_variant_typekey_run.c \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \