code wiki / (root) / _a2a_selfhost_binop.nx

_a2a_selfhost_binop.nx source

↩ module page · 142 lines · 4271 B

1// Self-host pipeline exercising binary operators. 2// Source: `func main() -> i64 { return 2 + 3 * 4 }` 3// Expected: IR with CONST_I64(2), CONST_I64(3), CONST_I64(4), MUL, ADD, RETURN 4 5import "syscalls.nx" 6import "nx_nlex.nx" 7import "nx_nparse.nx" 8import "nx_nir.nx" 9import "nx_nx86.nx" 10 11func main() -> i64 { 12 let src: *u8 = sys_mmap(64) 13 src[0] = 102 as u8 // f 14 src[1] = 117 as u8 15 src[2] = 110 as u8 16 src[3] = 99 as u8 17 src[4] = 32 as u8 18 src[5] = 109 as u8 19 src[6] = 97 as u8 20 src[7] = 105 as u8 21 src[8] = 110 as u8 22 src[9] = 40 as u8 23 src[10] = 41 as u8 24 src[11] = 32 as u8 25 src[12] = 45 as u8 26 src[13] = 62 as u8 27 src[14] = 32 as u8 28 src[15] = 105 as u8 29 src[16] = 54 as u8 30 src[17] = 52 as u8 31 src[18] = 32 as u8 32 src[19] = 123 as u8 33 src[20] = 32 as u8 34 src[21] = 114 as u8 35 src[22] = 101 as u8 36 src[23] = 116 as u8 37 src[24] = 117 as u8 38 src[25] = 114 as u8 39 src[26] = 110 as u8 40 src[27] = 32 as u8 41 src[28] = 50 as u8 // 2 42 src[29] = 32 as u8 43 src[30] = 43 as u8 // + 44 src[31] = 32 as u8 45 src[32] = 51 as u8 // 3 46 src[33] = 32 as u8 47 src[34] = 42 as u8 // * 48 src[35] = 32 as u8 49 src[36] = 52 as u8 // 4 50 src[37] = 32 as u8 51 src[38] = 125 as u8 // } 52 53 let lex: *NxNLexer = nx_nlex_new(src, 39, 64) 54 let n_tok: i64 = nx_nlex_run(lex) 55 56 let parser: *NxNParser = nx_nparse_new(lex, 64) 57 let func_idx: i64 = nx_nparse_run(parser) 58 if func_idx < 0 { return 2 } 59 60 let ir: *NxIrFunc = nx_nir_lower_func(parser, func_idx, 64) 61 if ir == (0 as *NxIrFunc) { return 3 } 62 63 // Expected IR for `2 + 3 * 4`: 64 // v0 = CONST 2 65 // v1 = CONST 3 66 // v2 = CONST 4 67 // v3 = MUL v1 v2 (3 * 4) 68 // v4 = ADD v0 v3 (2 + (3*4)) 69 // v5 = RETURN v4 70 // Total 6 instructions. 71 if ir.n_instrs != 6 { return 4 } 72 73 let i0: *NxInstr = nx_nir_instr_at(ir, 0) 74 if i0.opcode != NX_IR_CONST_I64 { return 5 } 75 if i0.op0 != 2 { return 6 } 76 77 let i1: *NxInstr = nx_nir_instr_at(ir, 1) 78 if i1.opcode != NX_IR_CONST_I64 { return 7 } 79 if i1.op0 != 3 { return 8 } 80 81 let i2: *NxInstr = nx_nir_instr_at(ir, 2) 82 if i2.opcode != NX_IR_CONST_I64 { return 9 } 83 if i2.op0 != 4 { return 10 } 84 85 let i3: *NxInstr = nx_nir_instr_at(ir, 3) 86 if i3.opcode != NX_IR_MUL { return 11 } 87 if i3.op0 != 1 { return 12 } // refers v1 88 if i3.op1 != 2 { return 13 } // refers v2 89 90 let i4: *NxInstr = nx_nir_instr_at(ir, 4) 91 if i4.opcode != NX_IR_ADD { return 14 } 92 if i4.op0 != 0 { return 15 } // refers v0 93 if i4.op1 != 3 { return 16 } // refers v3 (MUL) 94 95 let i5: *NxInstr = nx_nir_instr_at(ir, 5) 96 if i5.opcode != NX_IR_RETURN { return 17 } 97 98 // Stage 4: emit asm + verify it contains 'imulq', 'addq', 'popq', 'ret' 99 let asm: *NxAsmBuf = nx_asm_new(4096) 100 nx_nx86_emit_func(asm, src, ir) 101 var found_imul: i64 = 0 102 var found_add: i64 = 0 103 var found_ret: i64 = 0 104 var i: i64 = 0 105 while i < asm.len - 5 { 106 if asm.buf[i] as i64 == 105 { // 'i' 107 if asm.buf[i+1] as i64 == 109 { // 'm' 108 if asm.buf[i+2] as i64 == 117 { // 'u' 109 if asm.buf[i+3] as i64 == 108 { // 'l' 110 if asm.buf[i+4] as i64 == 113 { // 'q' 111 found_imul = 1 112 } 113 } 114 } 115 } 116 } 117 if asm.buf[i] as i64 == 97 { // 'a' 118 if asm.buf[i+1] as i64 == 100 { // 'd' 119 if asm.buf[i+2] as i64 == 100 { // 'd' 120 if asm.buf[i+3] as i64 == 113 { // 'q' 121 found_add = 1 122 } 123 } 124 } 125 } 126 if asm.buf[i] as i64 == 114 { // 'r' 127 if asm.buf[i+1] as i64 == 101 { // 'e' 128 if asm.buf[i+2] as i64 == 116 { // 't' 129 if asm.buf[i+3] as i64 == 10 { 130 found_ret = 1 131 } 132 } 133 } 134 } 135 i = i + 1 136 } 137 if found_imul != 1 { return 20 } 138 if found_add != 1 { return 21 } 139 if found_ret != 1 { return 22 } 140 141 return 0 142}