code wiki / _hdl_build / nx_buildmode_gate.nx

nx_buildmode_gate.nx source

↩ module page · 112 lines · 6248 B

1// nx_buildmode_gate.nx -- THE REFEREE for nx_buildmode_lib (LN44, 2026-09-03). 2// 3// The subject decides which flags the build lane hands the compiler, so its failure modes are expensive in 4// both directions: too eager and it silently changes every artifact in the estate on adoption day; too 5// quiet and the estate keeps shipping its slowest mode. The load-bearing tooth here is therefore the 6// SAFETY property, not the feature: with NO conf present the reader must return ZERO flags and an EMPTY 7// cache-key token, so adopting the lib cannot change one byte of one artifact until somebody writes a row. 8// 9// THE CACHE-KEY TOOTH IS NOT DECORATION. nx_sov_build_run caches artifacts under a key that today encodes 10// the compiler sha, the assembler sha and the debug flag. A mode that changes emitted code without 11// entering that key would serve an artifact compiled under the OTHER mode and present it as a cache hit -- 12// silently correct-looking and wrong. So the gate asserts two different modes yield two different tokens, 13// and that no mode yields an empty one. 14// 15// Fixture is PER-RUN via gk_fixture_dir, so two concurrent runs cannot clobber each other into a false 16// SKIP -- the defect measured on nx_bck_elide_gate the same day this shipped. 17// exit: 0 GREEN . 1 RED license_tier: ORIGINAL No hw writes. 18import "nx_syscalls.nx" 19import "nx_gate_verdict.nx" 20import "nx_gatekit_lib.nx" 21import "nx_buildmode_lib.nx" 22 23const BG_PATH: i64 = 1024 24const BG_CAP: i64 = 512 25const BG_SLOTS: i64 = 16 26 27func bg_write(path: *u8, text: *u8) -> i64 { 28 let fd: i64 = sys_openat_wr(path, 420) 29 if fd < 0 { return 0 - 1 } 30 var n: i64 = 0 31 while text[n] != (0 as u8) { n = n + 1 } 32 var off: i64 = 0 33 while off < n { let r: i64 = sys_write(fd, ((text as i64) + off) as *u8, n - off); if r <= 0 { sys_close(fd); return 0 - 2 } off = off + r } 34 sys_close(fd) 35 return 0 36} 37 38func main(argc: i64, argv: *i64) -> i64 { 39 let ctr: *i64 = gv_ctr() 40 gv_head("NX-BUILDMODE-GATE: the compile mode is DATA, and an absent declaration changes nothing" as *u8) 41 42 let root: *u8 = sys_mmap(BG_PATH) 43 gk_fixture_dir("nx_buildmode_gate" as *u8, root) 44 let kdir: *u8 = sys_mmap(BG_PATH) 45 var o: i64 = gk_cat(kdir, 0, root); o = gk_cat(kdir, o, "/knowledge" as *u8) 46 gk_mkdir(kdir) 47 let conf: *u8 = sys_mmap(BG_PATH) 48 o = gk_cat(conf, 0, kdir); o = gk_cat(conf, o, "/build_modes.conf" as *u8) 49 50 let cwd: *u8 = sys_mmap(BG_PATH) 51 sys_getcwd(cwd, BG_PATH) 52 sys_chdir(root) 53 54 let f: *u8 = sys_mmap(BG_CAP) 55 let t: *u8 = sys_mmap(BG_CAP) 56 57 // ---- A: NO CONF AT ALL -- the safety property, and the reason adoption is a no-op ---- 58 let a_n: i64 = bm_flags_for("nx_anything" as *u8, f) 59 let a_k: i64 = bm_key_token("nx_anything" as *u8, t) 60 gv_check_eq("A-absent-conf-yields-ZERO-flags-so-adoption-changes-no-artifact" as *u8, a_n, 0, ctr) 61 gv_check_eq("A-absent-conf-yields-an-EMPTY-cache-key-token-so-every-existing-cache-entry-stays-valid" as *u8, a_k, 0, ctr) 62 63 // ---- B: a per-target row ---- 64 bg_write(conf, "# fixture\ntarget|nx_alpha|--bckelide\n" as *u8) 65 let b_n: i64 = bm_flags_for("nx_alpha" as *u8, f) 66 gv_check("B-target-row-returns-its-declared-flags" as *u8, gk_streq(f, "--bckelide" as *u8), ctr) 67 gv_check_eq("B-flag-length-is-nonzero" as *u8, (b_n > 0) as i64, 1, ctr) 68 let b_other: i64 = bm_flags_for("nx_beta" as *u8, f) 69 gv_check_eq("B-neg-control-an-UNDECLARED-target-still-gets-nothing" as *u8, b_other, 0, ctr) 70 71 // ---- C: `all` is the fallback, and a per-target row BEATS it ---- 72 bg_write(conf, "all|--bckelide\ntarget|nx_special|--bckelide --chkarith\n" as *u8) 73 let c_any: i64 = bm_flags_for("nx_random" as *u8, f) 74 gv_check("C-all-row-is-the-fallback-for-an-undeclared-target" as *u8, gk_streq(f, "--bckelide" as *u8), ctr) 75 gv_check_eq("C-fallback-nonempty" as *u8, (c_any > 0) as i64, 1, ctr) 76 bm_flags_for("nx_special" as *u8, f) 77 gv_check("C-a-per-target-row-BEATS-the-all-row" as *u8, gk_streq(f, "--bckelide --chkarith" as *u8), ctr) 78 79 // ---- D: comments and blanks are not rows ---- 80 bg_write(conf, "# target|nx_gamma|--bckelide\n; target|nx_gamma|--bckelide\n\n" as *u8) 81 let d_n: i64 = bm_flags_for("nx_gamma" as *u8, f) 82 gv_check_eq("D-a-commented-row-is-NOT-a-declaration" as *u8, d_n, 0, ctr) 83 84 // ---- E: THE CACHE-KEY CONTRACT. Two modes must not share a key, or a hit serves the wrong artifact ---- 85 bg_write(conf, "target|nx_k|--bckelide\n" as *u8) 86 let k1: *u8 = sys_mmap(BG_CAP) 87 bm_key_token("nx_k" as *u8, k1) 88 bg_write(conf, "target|nx_k|--chkarith\n" as *u8) 89 let k2: *u8 = sys_mmap(BG_CAP) 90 bm_key_token("nx_k" as *u8, k2) 91 gv_check_eq("E-two-different-modes-yield-DIFFERENT-cache-key-tokens" as *u8, 1 - gk_streq(k1, k2), 1, ctr) 92 gv_check_eq("E-a-declared-mode-yields-a-NONEMPTY-token" as *u8, (gk_len(k1) > 0) as i64, 1, ctr) 93 gv_bite("bite-the-key-token-separates-two-modes-and-stays-empty-when-none-is-declared" as *u8, 1 - gk_streq(k1, k2), (a_k != 0) as i64, ctr) 94 95 // ---- F: the flag list becomes SEPARATE argv tokens, never one glued string ---- 96 bg_write(conf, "target|nx_s|--bckelide --chkarith\n" as *u8) 97 bm_flags_for("nx_s" as *u8, f) 98 let store: *u8 = sys_mmap(BG_CAP) 99 let slots: *i64 = sys_mmap(BG_SLOTS * 8) as *i64 100 let nsplit: i64 = bm_split(f, store, slots, BG_SLOTS) 101 gv_check_eq("F-two-flags-split-into-TWO-argv-tokens" as *u8, nsplit, 2, ctr) 102 gv_check("F-first-token-is-exactly-the-first-flag" as *u8, gk_streq(slots[0] as *u8, "--bckelide" as *u8), ctr) 103 gv_check("F-second-token-is-exactly-the-second-flag" as *u8, gk_streq(slots[1] as *u8, "--chkarith" as *u8), ctr) 104 let zero: i64 = bm_split("" as *u8, store, slots, BG_SLOTS) 105 gv_check_eq("F-neg-control-an-empty-flag-list-splits-into-ZERO-tokens" as *u8, zero, 0, ctr) 106 107 sys_chdir(cwd) 108 gv_kv("absent_conf_flags" as *u8, a_n) 109 gv_kv("absent_conf_keylen" as *u8, a_k) 110 gv_kv("split_tokens" as *u8, nsplit) 111 return gv_verdict("nx_buildmode_gate" as *u8, ctr, "an absent declaration yields no flags and no key bytes, a declared one reaches the compiler as separate tokens, and two modes can never share a cache key" as *u8) 112}