code wiki / (root) / nx_compiler_bounds_cli_gate.nx

nx_compiler_bounds_cli_gate.nx source

↩ module page · 154 lines · 11805 B

1// End-to-end CLI qualification of the staged compiler against a supplied incumbent. 2// Uses existing timed capture, per-run exclusive fixtures and complete artifact byte comparisons. 3import "nx_wat_refuse_gate.nx" 4import "nx_gate_verdict.nx" 5const BC_PAGE: i64=65536 6const BC_PRIVATE: i64=448 7const BC_I64_MAX: i64=9223372036854775807 8static bc_timeout: i64 9static bc_case_id: i64 10static bc_output: *u8 11static bc_output_n: i64 12func bc_number(s: *u8) -> i64 { 13 var n: i64=0;var i: i64=0 14 while s[i]!=(0 as u8) {let d: i64=s[i] as i64-48;if d<0 || d>9{return 0-1};if n>(BC_I64_MAX-d)/10{return 0-1};n=n*10+d;i=i+1} 15 if i==0 || n==0{return 0-1};return n 16} 17func bc_read(path: *u8,out: *u8) -> i64 { 18 let fd: i64=sys_openat_rd(path);if fd<0{return 0-1} 19 var n: i64=0;var eof: i64=0 20 while n<WR_CAP-1 {let got: i64=sys_read(fd,((out as i64)+n) as *u8,WR_CAP-1-n);if got==0{eof=1;break};if got<0{break};n=n+got} 21 let closed: i64=sys_close(fd);if eof!=1 || closed!=0{return 0-1};out[n]=0 as u8;return n 22} 23func bc_equal(a: *u8,an: i64,b: *u8,bn: i64) -> i64 { 24 if an<1 || an!=bn{return 0};var i: i64=0 25 while i<an{if a[i]!=b[i]{return 0};i=i+1};return 1 26} 27// All invocations use the SAME input path; fresh numbered outputs avoid stale-success evidence. 28func bc_run(subject: *u8,dir: *u8,source: *u8,options: *i64,noptions: i64,want: i64,cause: *u8,label: *u8,c: *i64) -> i64 { 29 gv_puts("case=" as *u8);gv_puts(label);gv_puts("\n" as *u8) 30 bc_output_n=0;bc_case_id=bc_case_id+1 31 let input: *u8=sys_mmap(WR_PATH);let output: *u8=sys_mmap(WR_PATH) 32 let avbytes: i64=(noptions+4)*WR_SPAN 33 let av: *i64=sys_mmap(avbytes) as *i64;let log: *u8=sys_mmap(WR_CAP) 34 let count: *i64=sys_mmap(WR_SPAN) as *i64;let truncated: *i64=sys_mmap(WR_SPAN) as *i64 35 if (input as i64)<=0 || (output as i64)<=0 || (av as i64)<=0 || (log as i64)<=0 || (count as i64)<=0 || (truncated as i64)<=0 {gv_check("case buffers allocated" as *u8,0,c);return 0} 36 gk_join(input,dir,"subject.nx" as *u8) 37 var p: i64=gk_cat(output,0,dir);p=gk_cat(output,p,"/output-" as *u8);p=gk_catn(output,p,bc_case_id);p=gk_cat(output,p,".wat" as *u8);output[p]=0 as u8 38 let written: i64=gk_write(input,source) 39 gv_check("entire fixture written" as *u8,written==gk_len(source),c) 40 if written!=gk_len(source){return 0} 41 av[0]=subject as i64;av[1]=input as i64;av[2]=output as i64 42 var k: i64=0;while k<noptions{av[3+k]=options[k];k=k+1};av[3+noptions]=0 43 let rc: i64=tr_run_capture_tr(subject,av,log,WR_CAP-1,count,bc_timeout,truncated) 44 if count[0]>=0 && count[0]<WR_CAP{log[count[0]]=0 as u8} 45 gv_check("compiler capture completed without truncation" as *u8,count[0]>=0 && count[0]<WR_CAP-1 && truncated[0]==0,c) 46 gv_check("compiler exit matches exact expected status" as *u8,rc==want,c) 47 if want==0 { 48 bc_output_n=bc_read(output,bc_output) 49 gv_check("artifact read fully to EOF" as *u8,bc_output_n>0,c) 50 gv_check("successful artifact contains module" as *u8,bc_output_n>0 && gk_has(bc_output,"(module\n" as *u8)==1,c) 51 if gk_len(cause)>0{gv_check("successful artifact contains required layout witness" as *u8,bc_output_n>0 && gk_has(bc_output,cause)==1,c)} 52 }else{ 53 gv_check("refusal names expected cause" as *u8,count[0]>0 && gk_has(log,cause)==1,c) 54 gv_check("refusal creates no artifact" as *u8,gk_exists(output)==0,c) 55 } 56 gv_values_head();gv_kv("case_index" as *u8,bc_case_id);gv_kv("compiler_exit" as *u8,rc);gv_kv("artifact_bytes" as *u8,bc_output_n) 57 sys_munmap(input,WR_PATH);sys_munmap(output,WR_PATH);sys_munmap(av as *u8,avbytes);sys_munmap(log,WR_CAP);sys_munmap(count as *u8,WR_SPAN);sys_munmap(truncated as *u8,WR_SPAN) 58 return rc==want 59} 60func bc_save(dst: *u8) -> i64 {var i: i64=0;while i<bc_output_n{dst[i]=bc_output[i];i=i+1};return bc_output_n} 61func bc_literal(characters: i64) -> *u8 { 62 let prefix: *u8="func main() -> *u8 { return \"" as *u8 63 let suffix: *u8="\" }\n" as *u8 64 let n: i64=gk_len(prefix)+characters+gk_len(suffix)+1 65 let out: *u8=sys_mmap(n);if (out as i64)<=0{return 0 as *u8} 66 var p: i64=gk_cat(out,0,prefix);var k: i64=0 67 while k<characters{out[p]=97 as u8;p=p+1;k=k+1} 68 p=gk_cat(out,p,suffix);out[p]=0 as u8;return out 69} 70func main(argc: i64,argv: **u8) -> i64 { 71 if argc!=5{gv_puts("usage: compiler-bounds-cli-gate <incumbent> <staged> /tmp/fresh-root timeout-ms\n" as *u8);return 3} 72 let old: *u8=argv[1] as *u8;let subject: *u8=argv[2] as *u8;let dir: *u8=argv[3] as *u8 73 bc_timeout=bc_number(argv[4] as *u8);if bc_timeout<1{return 3} 74 let dn: i64=gk_len(dir);if dn<=5 || dn>=WR_PATH/2{return 3} 75 if dir[0]!=(47 as u8)||dir[1]!=(116 as u8)||dir[2]!=(109 as u8)||dir[3]!=(112 as u8)||dir[4]!=(47 as u8)||dir[5]==(46 as u8){return 3} 76 var i: i64=5;while i<dn{if dir[i]==(47 as u8)||dir[i]<=(32 as u8){return 3};i=i+1} 77 let c: *i64=gv_ctr();gv_head("COMPILER-BOUNDS-CLI / actual staged and incumbent binaries" as *u8) 78 gv_need("incumbent compiler present" as *u8,gk_exists(old),c);gv_need("staged compiler present" as *u8,gk_exists(subject),c) 79 let made: i64=sys_mkdir(dir,BC_PRIVATE);gv_check("exclusive private fixture root" as *u8,made==0,c) 80 if made!=0{return gv_verdict("COMPILER-BOUNDS-CLI" as *u8,c,"fixture isolation refused" as *u8)} 81 bc_output=sys_mmap(WR_CAP);let saved: *u8=sys_mmap(WR_CAP);let opts: *i64=sys_mmap(WR_SPAN*8) as *i64 82 if (bc_output as i64)<=0||(saved as i64)<=0||(opts as i64)<=0{gv_check("gate buffers allocated" as *u8,0,c);return gv_verdict("COMPILER-BOUNDS-CLI" as *u8,c,"allocation failed" as *u8)} 83 // Bind pointer literals before indexed stores: current native analyzer requires this form. 84 let arena_option: *u8="--arena-pages" as *u8 85 let limit_option: *u8="--static-limit-pages" as *u8 86 let shared_option: *u8="--shared" as *u8 87 let pages_one: *u8="1" as *u8 88 let pages_two: *u8="2" as *u8 89 let pages_three: *u8="3" as *u8 90 let pages_four: *u8="4" as *u8 91 let source_value: *u8="source" as *u8 92 let bad_suffix: *u8="1x" as *u8 93 let bad_plus: *u8="+1" as *u8 94 let bad_negative: *u8="-1" as *u8 95 let bad_zero: *u8="0" as *u8 96 let bad_range: *u8="65537" as *u8 97 let bad_overflow: *u8="9223372036854775808" as *u8 98 let bad_empty: *u8="" as *u8 99 let tiny: *u8="func main() -> *u8 { return \"abc\" }\n" as *u8 100 bc_run(old,dir,tiny,opts,0,0,"" as *u8,"incumbent no flags" as *u8,c);let oldn: i64=bc_save(saved) 101 bc_run(subject,dir,tiny,opts,0,0,"" as *u8,"staged no flags" as *u8,c) 102 gv_check("no-flags complete output byte parity" as *u8,bc_equal(saved,oldn,bc_output,bc_output_n),c) 103 opts[0]=arena_option as i64;opts[1]=pages_one as i64;opts[2]=limit_option as i64;opts[3]=pages_two as i64 104 bc_run(subject,dir,tiny,opts,4,0,"(data (i32.const 65536)" as *u8,"plain arena then limit" as *u8,c);let plainn: i64=bc_save(saved) 105 opts[0]=limit_option as i64;opts[1]=pages_two as i64;opts[2]=arena_option as i64;opts[3]=pages_one as i64 106 bc_run(subject,dir,tiny,opts,4,0,"(data (i32.const 65536)" as *u8,"plain limit then arena" as *u8,c) 107 gv_check("plain option ordering preserves all emitted bytes" as *u8,bc_equal(saved,plainn,bc_output,bc_output_n),c) 108 opts[4]=shared_option as i64;opts[5]=pages_three as i64;opts[6]=pages_four as i64 109 bc_run(subject,dir,tiny,opts,7,0,"(memory 3 4 shared)" as *u8,"shared limit then arena" as *u8,c);let sharedn: i64=bc_save(saved) 110 opts[0]=arena_option as i64;opts[1]=pages_one as i64;opts[2]=limit_option as i64;opts[3]=pages_two as i64 111 bc_run(subject,dir,tiny,opts,7,0,"(memory 3 4 shared)" as *u8,"shared arena then limit" as *u8,c) 112 gv_check("shared option ordering preserves all emitted bytes" as *u8,bc_equal(saved,sharedn,bc_output,bc_output_n),c) 113 opts[0]=shared_option as i64;opts[1]=pages_three as i64;opts[2]=pages_four as i64 114 opts[3]=arena_option as i64;opts[4]=pages_one as i64;opts[5]=limit_option as i64;opts[6]=pages_two as i64 115 bc_run(subject,dir,tiny,opts,7,0,"(memory 3 4 shared)" as *u8,"numeric shared first then bounds" as *u8,c) 116 gv_check("shared-first numeric ordering preserves all emitted bytes" as *u8,bc_equal(saved,sharedn,bc_output,bc_output_n),c) 117 let source_pages: *u8="static nx_wasm_pages_req: i64 = 3\nfunc main() -> *u8 { return \"abc\" }\n" as *u8 118 opts[1]=source_value as i64 119 bc_run(subject,dir,source_pages,opts,7,0,"(memory 3 4 shared)" as *u8,"source-derived shared first then bounds" as *u8,c);let sourcen: i64=bc_save(saved) 120 opts[0]=arena_option as i64;opts[1]=pages_one as i64;opts[2]=limit_option as i64;opts[3]=pages_two as i64 121 opts[4]=shared_option as i64;opts[5]=source_value as i64;opts[6]=pages_four as i64 122 bc_run(subject,dir,source_pages,opts,7,0,"(memory 3 4 shared)" as *u8,"bounds first then source-derived shared" as *u8,c) 123 gv_check("source-derived shared ordering preserves all emitted bytes" as *u8,bc_equal(saved,sourcen,bc_output,bc_output_n),c) 124 let bad: *i64=sys_mmap(WR_SPAN*7) as *i64 125 if (bad as i64)<=0{gv_check("invalid-value table allocated" as *u8,0,c);return gv_verdict("COMPILER-BOUNDS-CLI" as *u8,c,"allocation failed" as *u8)} 126 bad[0]=bad_suffix as i64;bad[1]=bad_plus as i64;bad[2]=bad_negative as i64;bad[3]=bad_zero as i64;bad[4]=bad_range as i64;bad[5]=bad_overflow as i64;bad[6]=bad_empty as i64 127 var flag: i64=0 128 while flag<2{ 129 opts[0]=arena_option as i64;if flag==1{opts[0]=limit_option as i64} 130 var k: i64=0 131 while k<7{ 132 opts[1]=bad[k];gv_puts("flag=" as *u8);gv_puts(opts[0] as *u8);gv_puts(" value=" as *u8);gv_puts(opts[1] as *u8);gv_puts("\n" as *u8) 133 bc_run(subject,dir,tiny,opts,2,11,"must be complete positive decimal integers within wasm32" as *u8,"malformed page value" as *u8,c);k=k+1 134 } 135 bc_run(subject,dir,tiny,opts,1,11,"requires one positive decimal page count" as *u8,"missing page value" as *u8,c);flag=flag+1 136 } 137 opts[0]=arena_option as i64;opts[1]=pages_two as i64;opts[2]=limit_option as i64;opts[3]=pages_one as i64 138 let extent_cause: *u8="static layout exceeds supplied limit or limit is below arena base" as *u8 139 bc_run(subject,dir,tiny,opts,4,65,extent_cause,"limit below arena" as *u8,c) 140 opts[1]=pages_one as i64 141 bc_run(subject,dir,tiny,opts,4,65,extent_cause,"nonempty static data beyond zero-width reservation" as *u8,c) 142 opts[3]=pages_two as i64 143 let exact_plain: *u8=bc_literal(BC_PAGE-1);let over_plain: *u8=bc_literal(BC_PAGE) 144 let exact_shared: *u8=bc_literal(BC_PAGE-1-WR_SPAN);let over_shared: *u8=bc_literal(BC_PAGE-WR_SPAN) 145 if (exact_plain as i64)<=0||(over_plain as i64)<=0||(exact_shared as i64)<=0||(over_shared as i64)<=0{gv_check("exact-reservation fixtures allocated" as *u8,0,c);return gv_verdict("COMPILER-BOUNDS-CLI" as *u8,c,"allocation failed" as *u8)} 146 bc_run(subject,dir,exact_plain,opts,4,0,"(data (i32.const 65536)" as *u8,"plain exact page including string terminator" as *u8,c) 147 bc_run(subject,dir,over_plain,opts,4,65,extent_cause,"plain one byte over reservation" as *u8,c) 148 opts[4]=shared_option as i64;opts[5]=pages_three as i64;opts[6]=pages_four as i64 149 bc_run(subject,dir,exact_shared,opts,7,0,"(memory 3 4 shared)" as *u8,"shared exact page including aligned initialization cell" as *u8,c) 150 bc_run(subject,dir,over_shared,opts,7,65,extent_cause,"shared payload one byte over exact reservation" as *u8,c) 151 gv_values_head();gv_kv("subject_invocations" as *u8,bc_case_id) 152 gv_puts("retained_fixture=" as *u8);gv_puts(dir);gv_puts("\n" as *u8) 153 return gv_verdict("COMPILER-BOUNDS-CLI" as *u8,c,"actual CLI plain/shared order parity; strict syntax exit11; bounds exit65; exact reservations and incumbent no-flags parity; native fixture qualification only" as *u8) 154}