code wiki / (root) / rvv_regname_test.nx

rvv_regname_test.nx source

↩ module page · 107 lines · 3928 B

1// rvv_regname_test.nx -- reg_name + vbinop lowering dispatch. 2// 3// Exercises the RVV branch added to reg_name() AND the vadd.vv / 4// vfadd.vv emission from rv_emit_vbinop. Full vector codegen lands 5// when the IR + allocator are wired end-to-end; for now this 6// confirms the naming + mnemonic surface is correct. 7 8import "syscalls.nx" 9import "types.nx" 10import "ir.nx" 11import "outbuf.nx" 12import "regalloc.nx" 13import "riscv.nx" 14 15func buf_contains(buf: *u8, n: i64, needle: *u8) -> i64 { 16 var needle_len: i64 = 0 17 while needle[needle_len] != 0 { needle_len = needle_len + 1 } 18 if needle_len == 0 { return 1 } 19 var i: i64 = 0 20 while i + needle_len <= n { 21 var j: i64 = 0 22 var hit: i64 = 1 23 while j < needle_len { 24 if buf[i + j] != needle[j] { hit = 0; j = needle_len } 25 j = j + 1 26 } 27 if hit == 1 { return 1 } 28 i = i + 1 29 } 30 return 0 31} 32 33func main() -> i64 { 34 // v0 at index 300 35 let o0: *OutBuf = out_new(32) 36 reg_name(o0, 300) 37 if o0.pos != 2 { return __syscall(93, 10, 0, 0, 0, 0, 0) } 38 if o0.buf[0] != 0x76 { return __syscall(93, 11, 0, 0, 0, 0, 0) } // 'v' 39 if o0.buf[1] != 0x30 { return __syscall(93, 12, 0, 0, 0, 0, 0) } // '0' 40 41 // v7 at index 307 42 let o1: *OutBuf = out_new(32) 43 reg_name(o1, 307) 44 if o1.buf[0] != 0x76 { return __syscall(93, 20, 0, 0, 0, 0, 0) } 45 if o1.buf[1] != 0x37 { return __syscall(93, 21, 0, 0, 0, 0, 0) } // '7' 46 47 // v31 at index 331 48 let o2: *OutBuf = out_new(32) 49 reg_name(o2, 331) 50 if o2.buf[0] != 0x76 { return __syscall(93, 30, 0, 0, 0, 0, 0) } 51 if o2.buf[1] != 0x33 { return __syscall(93, 31, 0, 0, 0, 0, 0) } // '3' 52 if o2.buf[2] != 0x31 { return __syscall(93, 32, 0, 0, 0, 0, 0) } // '1' 53 54 // is_vec_reg discriminator 55 if is_vec_reg(299) != 0 { return __syscall(93, 40, 0, 0, 0, 0, 0) } 56 if is_vec_reg(300) != 1 { return __syscall(93, 41, 0, 0, 0, 0, 0) } 57 if is_vec_reg(331) != 1 { return __syscall(93, 42, 0, 0, 0, 0, 0) } 58 // fs-regs (200..211) must NOT register as vec. 59 if is_vec_reg(200) != 0 { return __syscall(93, 43, 0, 0, 0, 0, 0) } 60 61 // Mnemonic dispatch sanity. 62 let m1: *OutBuf = out_new(64) 63 emit_vbinop_mnem(m1, OP_VADD) 64 if buf_contains(m1.buf, m1.pos, "vadd.vv" as *u8) != 1 { 65 return __syscall(93, 50, 0, 0, 0, 0, 0) 66 } 67 let m2: *OutBuf = out_new(64) 68 emit_vbinop_mnem(m2, OP_VFMUL) 69 if buf_contains(m2.buf, m2.pos, "vfmul.vv" as *u8) != 1 { 70 return __syscall(93, 51, 0, 0, 0, 0, 0) 71 } 72 73 // Full vbinop lowering: build a 3-value FADD-style IR with 74 // v4/v5/v6 homing and check the asm output contains 75 // 'vadd.vv v6, v4, v5'. 76 let m_raw: *u8 = sys_mmap(256) 77 let mm: *Module = m_raw as *Module 78 mm.name = "vtest" as *u8 79 mm.functions = 0 as *Function 80 mm.n_functions = 0 81 let f: *Function = ir_function_new(mm, "vadd_demo" as *u8, 9, ir_type_i64()) 82 let b: *BasicBlock = ir_block_new(f) 83 let v0: i64 = alloc_value(f, VK_PARAM, ir_type_i64()) 84 let v1: i64 = alloc_value(f, VK_PARAM, ir_type_i64()) 85 let rid: i64 = ir_emit_binop(b, OP_VADD, v0, v1, ir_type_i64()) 86 let add: *Instr = b.tail 87 88 let locs_raw: *u8 = sys_mmap(256) 89 let locs: *ValueLoc = locs_raw as *ValueLoc 90 let l0: *ValueLoc = loc_at(locs, v0) 91 l0.kind = VL_REGISTER 92 l0.idx = 304 // v4 93 let l1: *ValueLoc = loc_at(locs, v1) 94 l1.kind = VL_REGISTER 95 l1.idx = 305 // v5 96 let lr: *ValueLoc = loc_at(locs, rid) 97 lr.kind = VL_REGISTER 98 lr.idx = 306 // v6 99 100 let o_em: *OutBuf = out_new(256) 101 rv_emit_vbinop(f, locs, o_em, add) 102 if buf_contains(o_em.buf, o_em.pos, "vadd.vv v6, v4, v5" as *u8) != 1 { 103 return __syscall(93, 60, 0, 0, 0, 0, 0) 104 } 105 106 return 0 107}