code wiki / (root) / nx_outbuf.nx

nx_outbuf.nx source

↩ module page · 99 lines · 2569 B

1// outbuf.nx -- growable output buffer shared by code-gen backends. 2// 3// Extracted from riscv.nx so wasm.nx (and any future backend) can 4// reuse the same bump-pointer string buffer without dragging in the 5// full RV64 emitter. Writes are bounded by a fixed cap picked at 6// out_new; overruns are silently clamped for now. 7 8// nx_safety_envelope: 9// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 10// sil_target: SIL1 11// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 12// verdict: NOT_YET_EVALUATED 13 14import "nx_syscalls.nx" 15 16struct OutBuf { 17 buf: *u8, 18 pos: i64, 19 cap: i64, 20} 21 22func out_new(cap: i64) -> *OutBuf { 23 let raw: *u8 = sys_mmap(cap + 64) 24 let o: *OutBuf = raw as *OutBuf 25 o.buf = (raw as i64 + 64) as *u8 26 o.pos = 0 27 o.cap = cap 28 return o 29} 30 31func out_char(o: *OutBuf, c: i64) -> i64 { 32 if o.pos < o.cap { 33 o.buf[o.pos] = c 34 o.pos = o.pos + 1 35 } 36 return 0 37} 38 39func out_str(o: *OutBuf, s: *u8) -> i64 { 40 var i: i64 = 0 41 while s[i] != 0 { 42 out_char(o, s[i]) 43 i = i + 1 44 } 45 return 0 46} 47 48// Emit decimal integer (signed). 10-digit buffer is ample for i64. 49func out_i64(o: *OutBuf, n: i64) -> i64 { 50 if n == 0 { 51 out_char(o, 0x30) 52 return 0 53 } 54 var v: i64 = n 55 if v < 0 { 56 out_char(o, 0x2D) 57 let neg_v: i64 = 0 - v 58 // S-class INT64_MIN fix 2026-05-27: negating INT64_MIN 59 // overflows in two's complement (wraps to itself: still 60 // negative). Detect via post-negate sign check + emit the 61 // 19-digit magnitude (9223372036854775808) directly. 62 // Bug surfaced when native codegen emitted `movabsq $-,` 63 // (truncated to bare '-') for source constants like 64 // `var mask: i64 = 0x8000000000000000` in nx_bits_clz64_soft. 65 if neg_v < 0 { 66 let s: *u8 = "9223372036854775808" as *u8 67 var i: i64 = 0 68 while i < 19 { 69 out_char(o, s[i]) 70 i = i + 1 71 } 72 return 0 73 } 74 v = neg_v 75 } 76 let buf_raw: *u8 = sys_mmap(32) 77 let buf: *u8 = buf_raw 78 var k: i64 = 0 79 while v > 0 { 80 buf[k] = 0x30 + (v % 10) 81 v = v / 10 82 k = k + 1 83 } 84 while k > 0 { 85 k = k - 1 86 out_char(o, buf[k]) 87 } 88 return 0 89} 90 91// Emit N spaces of indentation. 92func out_indent(o: *OutBuf, n: i64) -> i64 { 93 var i: i64 = 0 94 while i < n { 95 out_char(o, 0x20) 96 i = i + 1 97 } 98 return 0 99}