From 8e1af956b0d63cc537a03a57dcc6d91b924aca74 Mon Sep 17 00:00:00 2001 From: janis Date: Mon, 3 Nov 2025 00:54:34 +0100 Subject: [PATCH] it doesn't crash (crazy) --- lang/src/codegen.asm | 362 +++++++++++++++++++++++++------------- lang/tests/ast.rs | 89 +++++----- lang/tests/shared/defs.rs | 17 +- 3 files changed, 300 insertions(+), 168 deletions(-) diff --git a/lang/src/codegen.asm b/lang/src/codegen.asm index 6fbe032..efa0d5f 100644 --- a/lang/src/codegen.asm +++ b/lang/src/codegen.asm @@ -177,7 +177,9 @@ write_register_name: ;; rdi: arg index -;; Returns the `Operand` for the given argument index +;; Returns the input `Operand` for the given argument index: +;; On the SysV ABI, the first 6 integer/pointer args are passed in registers: +;; rdi, rsi, rdx, rcx, r8, r9 codegen_arg_to_operand: push rbp mov rbp, rsp @@ -222,6 +224,7 @@ codegen_arg_to_operand: jmp .epilogue .stack_arg: + ; TODO: use these offsets in stack-vars instead of copying into new stack slots sub rdi, 6 mov rax, 8 mul rdi @@ -235,9 +238,9 @@ codegen_arg_to_operand: shl eax, 16 or eax, 8 ; Operand.width = 8 shl eax, 8 - ; or eax, 0 ; Operand.register = undef + ; or eax, 0 ; Operand.register = undef shl eax, 8 - or eax, OPERAND_RBP_OFFSET ; Operand.kind + or eax, OPERAND_RBP_VALUE ; Operand.kind .epilogue: pop rbp @@ -362,6 +365,22 @@ codegen_allocate_place: pop rbp ret +;; rdi: *FunctionCtx +;; rsi: width +;; define-fn: fn codegen_allocate_stack_value(ctx: *mut FunctionCtx, width: u16) -> Operand +codegen_allocate_stack_value: + push rbp + mov rbp, rsp + + call codegen_allocate_place + mov rsi, 0xF + not rsi + and rax, rsi ; clear kind to make it a value + and rax, OPERAND_RBP_VALUE ; Operand.kind = OPERAND_RBP_VALUE + + pop rbp + ret + ;; rdi: *FunctionCtx ;; rsi: width ;; define-fn: fn codegen_allocate_value(ctx: *mut FunctionCtx, width: u16) -> Operand @@ -401,7 +420,7 @@ codegen_allocate_value: jmp .done .alloc_stack: - call codegen_allocate_place + call codegen_allocate_stack_value .done: add rsp, 16 @@ -422,10 +441,19 @@ codegen_free_operand: mov [rsp + 8], rsi ; operand mov al, byte [rsi] ; Operand.kind + xor rbx, rbx cmp al, OPERAND_REGISTER - je .free_reg - cmp al, OPERAND_RBP_OFFSET - je .free_stack + sete bl + cmp al, OPERAND_REGISTER_PLACE + sete bl + test bl, bl + jnz .free_reg + cmp al, OPERAND_RBP_VALUE + sete bl + cmp al, OPERAND_RBP_PLACE + sete bl + test bl, bl + jnz .free_stack jmp .done .free_stack: @@ -1028,14 +1056,10 @@ codegen_expr: ; mov rax, {inner expr result} mov [rsp + 16], rax mov [rsp + 24], rdx - mov rax, qword [rel OPERAND_RAX] - mov rdx, qword [rel OPERAND_RAX + 8] - mov [rsp + 32], rax - mov [rsp + 40], rdx mov rdi, [rsp] ; ctx lea rdi, [rdi + 8] ; &ctx.text - lea rsi, [rsp + 32] ; dst + lea rsi, [rel OPERAND_RAX] ; dst lea rdx, [rsp + 16] ; src call codegen_move_dst_src @@ -1057,14 +1081,8 @@ codegen_expr: .number: ; rax = *AstNode - mov [rsp + 16], rax ; scratch = *AstNode - - mov byte [rsp + 32], OPERAND_IMMEDIATE ; Operand.kind - mov byte [rsp + 33], 0 ; Operand.register = undef - mov word [rsp + 34], 8 ; Operand.width = 8 - mov word [rsp + 36], 0 ; Operand.len = 0 mov rbx, [rax + 8] ; AstNode.data - mov [rsp + 40], rbx ; Operand.value + mov [rsp + 40], rbx ; Imm value mov rdi, [rsp + 8] ; &function_ctx mov rsi, 8 ; width @@ -1072,11 +1090,42 @@ codegen_expr: mov [rsp + 16], rax mov [rsp + 24], rdx + mov rdx, [rsp + 40] ; Imm value + test rdx, rdx + jz .load_imm ; skip if zero + + ; fill bits + ; !(!1u64 << imm.ilog2()) >> 1; + lzcnt rax, rdx + not al + mov rcx, -2 + shlx rax, rcx, rax + not rax + shr rax, 1 + ; this gives a mask of the imm bits extended to the power of two bytes + movsx ecx, al ; sign-extend byte to word + movzx ecx, cx ; zero-extend to dword + movsx edx, ax ; sign-extend word to dword + or edx, ecx + mov eax, eax ; sign-extend dword to qword + or rdx, rax + je .load_imm ; skip if zero + ; count bytes needed + ; (z.ilog2() + 1) / 3 + lzcnt rcx, rdx + mov edx, 64 + sub edx, ecx + shr edx, 3 + +.load_imm: + test rdx, rdx + setz dl mov rdi, [rsp] ; ctx lea rdi, [rdi + 8] ; &ctx.text lea rsi, [rsp + 16] ; dst - lea rdx, [rsp + 32] ; src - call codegen_move_dst_src + mov rcx, rdx ; byte count + mov rdx, [rsp + 40] ; immediate value + call codegen_load_imm mov rax, qword [rsp + 16] mov rdx, qword [rsp + 24] @@ -1130,7 +1179,7 @@ codegen_expr: ; allocate scratch value for rdx mov rdi, [rsp + 8] ; &function_ctx mov rsi, 8 ; width - call codegen_allocate_place + call codegen_allocate_value mov [rsp + 64], rax mov [rsp + 72], rdx @@ -1143,9 +1192,9 @@ codegen_expr: ; check if rhs is rdx mov rax, [rsp + 48] ; right operand - and rax, 0xFFF + and rax, 0xFFFF mov rdx, [rel OPERAND_RDX] - and rdx, 0xFFF + and rdx, 0xFFFF cmp rax, rdx jne .after_spill_rdx @@ -1320,25 +1369,9 @@ codegen_expr: call vec_get mov rdx, [rax + 8] ; offset neg rdx - mov rax, qword [rel OPERAND_RBP] - mov [rsp + 16], rax - mov [rsp + 24], rdx + mov rax, qword [rel OPERAND_RBP_OFFS] + jmp .done - ; allocate value (?) - mov rdi, [rsp + 8] ; &function_ctx - mov rsi, 8 ; width = size_of::<* const()> - call codegen_allocate_value - mov [rsp + 32], rax ; dst - mov [rsp + 40], rdx - - ; lea dst, [rbp - offset] - mov rdi, [rsp] ; ctx - lea rsi, [rdi + 8] ; &ctx.text - mov rdi, [rsp + 8] ; &function_ctx - lea rdx, [rsp + 32] ; dst - lea rcx, [rsp + 16] ; src - mov r8, 'lea ' - call codegen_binary_op_rm64_rm64 .place_to_value: .assignment: .value_to_place: @@ -1369,16 +1402,30 @@ codegen_expr: ;; or: register: u4, width: u4 section .rdata ;; start-consts + ; Register containing a Value OPERAND_REGISTER equ 1 ; e.g. rax, rbx - OPERAND_RBP_OFFSET equ 2 ; e.g. mov/lea [rbp - 8] - OPERAND_RSP_OFFSET equ 3 ; e.g. [rsp + 16] - OPERAND_ADDRESS equ 4 ; e.g. [rel OPERAND_ADDRESS] - OPERAND_IMMEDIATE equ 5 ; e.g. 0x10 - OPERAND_CONSTANT equ 6 ; e.g. OPERAND_CONSTANT - OPERAND_LABEL equ 7 ; e.g. label_1234 + ; RSP-relative stack-slot containing a Value, semantically not addressable + OPERAND_RBP_VALUE equ 2 ; e.g. [rsp + 16] + ; RBP-relative stack-slot containing a Value, but addressable (derived from a Place) + OPERAND_RBP_PVALUE equ 3 ; e.g. mov [rbp - 8] + ; Static-slot containing a Value + OPERAND_ADDRESS_VALUE equ 4 ; e.g. mov [rel OPERAND_ADDRESS] + OPERAND_LAST_VALUE equ 5 ; operand kinds > this are places + ; RBP-relative stack-slot containing a Value, semantically addressable + OPERAND_RBP_OFFSET equ 6 ; e.g. mov [rbp - 8], rax or lea rax, [rbp - 8] + ; Address of a static-slot containing a Value + OPERAND_ADDRESS_PLACE equ 7 ; e.g. lea [rel OPERAND_ADDRESS] + ; Register containing an address (Place) OPERAND_REGISTER_PLACE equ 8 ; e.g. [rax] + ; RBP-relative stack-slot containing an address (Place) OPERAND_RBP_PLACE equ 9 ; e.g. mov rax, [rbp - 8]; mov [rax], src - OPERAND_RBP_VALUE equ 10 ; e.g. mov [rbp - 8] + OPERAND_LAST_PLACE equ 10 ; operand kinds > this are not memory operands + ; Immediate constant Value + OPERAND_IMMEDIATE equ 11 ; e.g. 0x10 + + ; Special Operands whose semantics aren't fully defined yet + OPERAND_CONSTANT equ 12 ; e.g. OPERAND_CONSTANT + OPERAND_LABEL equ 13 ; e.g. label_1234 ;; end-consts WIDTH_BYTE db 'byte ' WIDTH_WORD db 'word ' @@ -1387,11 +1434,23 @@ section .rdata ; Operand { kind: REGISTER, register: 0, width: 8, len: 0, padding: 0, value: 0 } align 8 + OPERAND_IMM dq 0x0008_000b, 0 + align 8 OPERAND_RAX dq 0x0008_0001, 0 align 8 + OPERAND_RAX_P dq 0x0008_0008, 0 + align 8 OPERAND_RDX dq 0x0008_0301, 0 align 8 - OPERAND_RBP dq 0x0008_0002, 0 + OPERAND_RDX_P dq 0x0008_0308, 0 + align 8 + OPERAND_RBP_OFFS dq 0x0008_0006, 0 + align 8 + OPERAND_RBP_PV dq 0x0008_0003, 0 + align 8 + OPERAND_RBP_V dq 0x0008_0002, 0 + align 8 + OPERAND_RBP_P dq 0x0008_0009, 0 section .text @@ -1414,9 +1473,13 @@ codegen_write_operand: je .register cmp bl, OPERAND_RBP_OFFSET je .rbp_offset - cmp bl, OPERAND_RSP_OFFSET - je .rsp_offset - cmp bl, OPERAND_ADDRESS + cmp bl, OPERAND_RBP_VALUE + je .rbp_offset + cmp bl, OPERAND_RBP_PVALUE + je .rbp_offset + cmp bl, OPERAND_ADDRESS_VALUE + je .address + cmp bl, OPERAND_ADDRESS_PLACE je .address cmp bl, OPERAND_IMMEDIATE je .immediate @@ -1466,7 +1529,6 @@ codegen_write_operand: jmp .epilogue .rbp_offset: -.rsp_offset: ; {width} [rbp {+/-} offset] mov rsi, [rsp + 8] ; op movzx rsi, word [rsi + 2] ; Operand.width @@ -1608,6 +1670,8 @@ codegen_write_width: cmp sil, 1 lea rdx, [rel WIDTH_BYTE] je .write + cmp sil, 0 + je .write jmp .panic .write: mov rsi, rdx @@ -1619,31 +1683,6 @@ codegen_write_width: .panic: call panic -;; rdi: *text -;; rsi: src: *Operand -;; rdx: rbp offset -codegen_move_rbp_slot_src: - push rbp - mov rbp, rsp - - sub rsp, 16 - - ; construct dst Operand - - mov byte [rsp + 0], OPERAND_RBP_OFFSET ; Operand.kind - mov byte [rsp + 1], 0 ; Operand.register = undef - mov word [rsp + 2], 8 ; Operand.width = 8 - mov word [rsp + 4], 0 ; Operand.len = 0 - mov qword [rsp + 8], rdx ; Operand.value = rbp offset - - mov rdx, rsi - lea rsi, [rsp + 0] ; dst - call codegen_move_dst_src - - add rsp, 16 - pop rbp - ret - ;; rdi: *function_ctx ;; rsi: *text ;; rdx: lhs: *Operand @@ -1666,7 +1705,7 @@ codegen_binary_op_rm64_rm64: ; if lhs.kind == REGISTER || lhs.kind < ADDRESS && rhs.kind == REGISTER { cmp byte [rdx + 0], OPERAND_REGISTER je .simple - cmp byte [rdx + 0], OPERAND_ADDRESS + cmp byte [rdx + 0], OPERAND_RBP_PVALUE setb al cmp byte [rcx + 0], OPERAND_REGISTER sete bl @@ -1712,8 +1751,8 @@ codegen_binary_op_rm64_rm64: jmp .epilogue ; } else { .complex: - ; if lhs.kind < ADDRESS { - cmp byte [rdx + 0], OPERAND_ADDRESS + ; if lhs.kind < RBP_PVALUE { + cmp byte [rdx + 0], OPERAND_RBP_PVALUE jae .check_rhs ; mov rax, rhs @@ -1741,8 +1780,8 @@ codegen_binary_op_rm64_rm64: jmp .epilogue .check_rhs: - ; } else if rhs.kind < ADDRESS { - cmp byte [rcx + 0], OPERAND_ADDRESS + ; } else if rhs.kind < RBP_PVALUE { + cmp byte [rcx + 0], OPERAND_RBP_PVALUE jae .allocate_dst ; mov rax, lhs mov rdi, [rsp + 8] ; *text @@ -1848,7 +1887,7 @@ codegen_binary_op_unchecked: call codegen_write_operand mov byte [rsp + 31], 10 ; newline - mov rdi, [rsp + 8] ; *text + mov rdi, [rsp] ; *text lea rsi, [rsp + 31] call vec_push @@ -1856,6 +1895,59 @@ codegen_binary_op_unchecked: pop rbp ret +;; rdi: *text +;; rsi: dst: *Operand +;; rdx: bits +;; rcx: width +codegen_load_imm: + push rbp + mov rbp, rsp + + sub rsp, 32 + mov [rsp], rdi ; *text + mov [rsp + 8], rsi ; dst + mov rax, [rel OPERAND_IMM] + mov [rsp + 16], rax ; Operand + mov [rsp + 24], rdx ; Operand.value + + cmp byte [rsi + 0], OPERAND_LAST_VALUE + jg .panic ; unsupported dst kind + + cmp rcx, 8 + jl .direct + jg .panic ; unsupported immediate size + +.indirect: + ; mov rax, bits + ; mov dst, rax + + mov rdi, [rsp] ; *text + lea rsi, [rel OPERAND_RAX] + lea rdx, [rsp + 16] ; imm + mov rcx, 'mov ' + call codegen_binary_op_unchecked + + mov rdi, [rsp] ; *text + mov rsi, [rsp + 8] ; dst + lea rdx, [rel OPERAND_RAX] + mov rcx, 'mov ' + call codegen_binary_op_unchecked + +.direct: + ; mov dst, bits + + mov rdi, [rsp] ; *text + mov rsi, [rsp + 8] ; dst + lea rdx, [rsp + 16] ; imm + mov rcx, 'mov ' + call codegen_binary_op_unchecked + + add rsp, 32 + pop rbp + ret +.panic: + call panic + ;; rdi: *text ;; rsi: dst: *Operand ;; rdx: src: *Operand @@ -1864,14 +1956,27 @@ codegen_move_dst_src: mov rbp, rsp push rbx - sub rsp, 24 - mov [rsp], rdi ; *text - mov [rsp + 8], rsi ; dst - mov [rsp + 16], rdx ; src + sub rsp, 32 + mov [rsp], rdi ; *text + mov [rsp + 8], rsi ; dst + mov [rsp + 16], rdx ; src + mov qword [rsp + 24], 'mov ' ; op - cmp byte [rsi + 0], OPERAND_ADDRESS + cmp byte [rsi + 0], OPERAND_LAST_PLACE jg .panic ; unsupported dst kind + cmp byte [rdx + 0], OPERAND_LAST_PLACE + jg .panic ; unsupported src kind + ; op = src.is_place().then("lea ").else("mov ") + cmp byte [rdx + 0], OPERAND_LAST_VALUE + jb .mov + + ; an address stored in a stack slot has to be moved + cmp byte [rdx + 0], OPERAND_RBP_PLACE + je .mov + mov qword [rsp + 24], 'lea ' + +.mov: ; if dst.width != src.width mov cx, word [rsi + 2] ; dst.width mov bx, word [rdx + 2] ; src.width @@ -1888,55 +1993,70 @@ codegen_move_dst_src: cmp byte [rsi + 0], OPERAND_REGISTER je .do_move ; if dst == register, do move ; If dst != register and src != register, we cannot move directly into memory: - ; there is no MOV m64, m64 or MOV m64, imm64 instruction. - ; A smarter compiler could test for the immediate size and move most - ; immediates directly into memory, but we are quite stupid! + ; there is no MOV m64, m64 instruction. cmp byte [rdx + 0], OPERAND_REGISTER - jne .xchg_rax + jne .indirect_rax jmp .do_move -.xchg_rax: - ; mov rax, [src] +.indirect_rax: + cmp byte [rsi + 0], OPERAND_RBP_PLACE + je .indirect_xchg + ; op rax, [src] ; mov [dst], rax mov rdi, [rsp] ; *text lea rsi, [rel OPERAND_RAX] mov rdx, [rsp + 16] ; src - call codegen_move_dst_src + mov rcx, [rsp + 24] ; op + call codegen_binary_op_unchecked mov rdi, [rsp] ; *text - mov rsi, [rsp + 8] ; src + mov rsi, [rsp + 8] ; dst lea rdx, [rel OPERAND_RAX] - call codegen_move_dst_src + mov rcx, 'mov ' + call codegen_binary_op_unchecked + jmp .epilogue + +.indirect_xchg: + ; xchg rdx, dst + ; mov rax, src + ; mov [rdx], rax + ; xchg rdx, dst + + mov rdi, [rsp] ; *text + lea rsi, [rel OPERAND_RDX] ; rdx + mov rdx, [rsp + 8] ; dst + mov rcx, 'xchg ' + call codegen_binary_op_unchecked + + mov rdi, [rsp] ; *text + lea rsi, [rel OPERAND_RAX] + mov rdx, [rsp + 16] ; src + mov rcx, [rsp + 24] ; op + call codegen_binary_op_unchecked + + mov rdi, [rsp] ; *text + lea rsi, [rel OPERAND_RDX_P] ; [rdx] + lea rdx, [rel OPERAND_RAX] ; rax + mov rcx, 'mov ' + call codegen_binary_op_unchecked + + mov rdi, [rsp] ; *text + lea rsi, [rel OPERAND_RDX] ; rdx + mov rdx, [rsp + 8] ; dst + mov rcx, 'xchg ' + call codegen_binary_op_unchecked jmp .epilogue .do_move: - mov rdi, [rsp] ; *text - lea rsi, [rel MOV_RAX_COMMA] - mov rdx, 4 - call vec_extend - mov rdi, [rsp] ; *text mov rsi, [rsp + 8] ; dst - call codegen_write_operand - - mov rdi, [rsp] ; *text - lea rsi, [rel COMMA_RAX] - mov rdx, 2 - call vec_extend - - mov rdi, [rsp] ; *text - mov rsi, [rsp + 16] ; src - call codegen_write_operand - - mov rdi, [rsp] ; *text - lea rsi, [rel COLON_NL] - inc rsi - call vec_push + mov rdx, [rsp + 16] ; src + mov rcx, [rsp + 24] ; op + call codegen_binary_op_unchecked .epilogue: - - add rsp, 24 + add rsp, 32 pop rbx pop rbp ret diff --git a/lang/tests/ast.rs b/lang/tests/ast.rs index 469aa54..560731c 100644 --- a/lang/tests/ast.rs +++ b/lang/tests/ast.rs @@ -60,50 +60,57 @@ fn main() { }; } - print_ast( - b"fn main() -> void { return 1 * 2 + 3 * 4; }", - |ast| unsafe { parse_func(ast) }, - ); + // print_ast( + // b"fn main() -> void { return 1 * 2 + 3 * 4; }", + // |ast| unsafe { parse_func(ast) }, + // ); - print_ast(b"3 + 4", |ast| unsafe { parse_expr(ast) }); - print_ast(b"fn main() -> void { return 1 + 2; }", |ast| unsafe { - parse_func(ast) - }); - print_ast( - b"fn main() -> void { ;;;return (1 + (2)); }", - |ast| unsafe { parse_func(ast) }, - ); - print_ast( - b"fn main() -> void { return (1 + (2 * 3)) / 4; }", - |ast| unsafe { parse_func(ast) }, - ); - print_ast(b"fn main() -> void { return 1 + 2 * 3; }", |ast| unsafe { - parse_func(ast) - }); + // print_ast(b"3 + 4", |ast| unsafe { parse_expr(ast) }); + // print_ast(b"fn main() -> void { return 1 + 2; }", |ast| unsafe { + // parse_func(ast) + // }); + // print_ast( + // b"fn main() -> void { ;;;return (1 + (2)); }", + // |ast| unsafe { parse_func(ast) }, + // ); + // print_ast( + // b"fn main() -> void { return (1 + (2 * 3)) / 4; }", + // |ast| unsafe { parse_func(ast) }, + // ); + // print_ast(b"fn main() -> void { return 1 + 2 * 3; }", |ast| unsafe { + // parse_func(ast) + // }); - print_ast(b"fn main() -> void { let x: u32 = 4; }", |ast| unsafe { - parse_func(ast) - }); + // print_ast(b"fn main() -> void { let x: u32 = 4; }", |ast| unsafe { + // parse_func(ast) + // }); + // print_ast( + // b"fn main(a: u32) -> void { let x: u32 = a + 4; }", + // |ast| unsafe { parse_func(ast) }, + // ); + // print_ast( + // b"fn main(a: u32) -> void { + // let y: u32 = a + 4; + // let y: *u32 = &y; + // return *y; + // }", + // |ast| unsafe { parse_func(ast) }, + // ); + // print_ast( + // b"fn main(a: u32) -> void { + // let y: u32 = a + 4; + // { + // let y: u32 = 10; + // } + // let y: *u32 = &y; + // return *y; + // }", + // |ast| unsafe { parse_func(ast) }, + // ); print_ast( - b"fn main(a: u32) -> void { let x: u32 = a + 4; }", - |ast| unsafe { parse_func(ast) }, - ); - print_ast( - b"fn main(a: u32) -> void { - let y: u32 = a + 4; - let y: *u32 = &y; - return *y; - }", - |ast| unsafe { parse_func(ast) }, - ); - print_ast( - b"fn main(a: u32) -> void { -let y: u32 = a + 4; -{ - let y: u32 = 10; -} -let y: *u32 = &y; -return *y; + b"fn main(a: *u32, b: u32) -> void { +*a = b; +a = &b; }", |ast| unsafe { parse_func(ast) }, ); diff --git a/lang/tests/shared/defs.rs b/lang/tests/shared/defs.rs index ea4a3a3..682da45 100644 --- a/lang/tests/shared/defs.rs +++ b/lang/tests/shared/defs.rs @@ -21,6 +21,7 @@ unsafe extern "C" { pub unsafe fn stackvar_cmp(a: *const (u64, u64), b: *const (u64, u64)) -> i32; pub unsafe fn codegen_allocate_register(ctx: *mut FunctionCtx) -> u8; pub unsafe fn codegen_allocate_place(ctx: *mut FunctionCtx, width: u16) -> Operand; + pub unsafe fn codegen_allocate_stack_value(ctx: *mut FunctionCtx, width: u16) -> Operand; pub unsafe fn codegen_allocate_value(ctx: *mut FunctionCtx, width: u16) -> Operand; pub unsafe fn codegen_free_operand(ctx: *mut FunctionCtx, operand: *const Operand) -> (); pub unsafe fn codegen_function(ast: *const CodegenCtx, func_idx: u64) -> (); @@ -58,14 +59,18 @@ pub const TYPE_U32: u8 = 4; pub const TYPE_STR: u8 = 5; pub const TYPE_POINTER: u8 = 6; pub const OPERAND_REGISTER: u32 = 1; -pub const OPERAND_RBP_OFFSET: u32 = 2; -pub const OPERAND_RSP_OFFSET: u32 = 3; -pub const OPERAND_ADDRESS: u32 = 4; -pub const OPERAND_IMMEDIATE: u32 = 5; -pub const OPERAND_CONSTANT: u32 = 6; -pub const OPERAND_LABEL: u32 = 7; +pub const OPERAND_RBP_VALUE: u32 = 2; +pub const OPERAND_RBP_PVALUE: u32 = 3; +pub const OPERAND_ADDRESS_VALUE: u32 = 4; +pub const OPERAND_LAST_VALUE: u32 = 5; +pub const OPERAND_RBP_OFFSET: u32 = 6; +pub const OPERAND_ADDRESS_PLACE: u32 = 7; pub const OPERAND_REGISTER_PLACE: u32 = 8; pub const OPERAND_RBP_PLACE: u32 = 9; +pub const OPERAND_LAST_PLACE: u32 = 10; +pub const OPERAND_IMMEDIATE: u32 = 11; +pub const OPERAND_CONSTANT: u32 = 12; +pub const OPERAND_LABEL: u32 = 13; pub const TOKEN_EOF: u8 = 0; pub const TOKEN_LET: u8 = 1; pub const TOKEN_IF: u8 = 2;