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}