dangerous: resize width field on Operand

This commit is contained in:
janis 2025-11-02 17:27:30 +01:00
parent 6dff42cfa5
commit d46837903b
Signed by: janis
SSH key fingerprint: SHA256:bB1qbbqmDXZNT0KKD5c2Dfjg53JGhj7B3CFcLIzSqq8
2 changed files with 79 additions and 63 deletions

View file

@ -213,11 +213,11 @@ codegen_arg_to_operand:
xor rax, rax
mov eax, 0 ; Operand.len = 0
shl eax, 16
or eax, 8 ; Operand.width = 8
shl eax, 4
or eax, edi ; Operand.register
or eax, 8 ; Operand.width = 8
shl eax, 8
or eax, OPERAND_REGISTER ; Operand.kind
or eax, edi ; Operand.register
shl eax, 8
or eax, OPERAND_REGISTER ; Operand.kind
mov rdx, 0 ; Operand.value = 0
jmp .epilogue
@ -233,8 +233,8 @@ codegen_arg_to_operand:
xor rax, rax
mov eax, 0 ; Operand.len = 0
shl eax, 16
or eax, 8 ; Operand.width = 8
shl eax, 4
or eax, 8 ; Operand.width = 8
shl eax, 8
; or eax, 0 ; Operand.register = undef
shl eax, 8
or eax, OPERAND_RBP_OFFSET ; Operand.kind
@ -352,7 +352,7 @@ codegen_allocate_place:
mov eax, 0 ; Operand.len = 0
shl eax, 16
or eax, esi ; Operand.width
shl eax, 4
shl eax, 8
; or eax, 0 ; Operand.register = undef
shl eax, 8
or eax, OPERAND_RBP_OFFSET ; Operand.kind
@ -393,7 +393,7 @@ codegen_allocate_value:
shl eax, 16
mov rsi, [rsp + 8] ; width
or eax, esi ; Operand.width
shl eax, 4
shl eax, 8
or eax, ebx ; Operand.register
shl eax, 8
or eax, OPERAND_REGISTER ; Operand.kind
@ -435,17 +435,13 @@ codegen_free_operand:
cmp rbx, rax
jne .done ; operand not at top of stack, can't free
mov al, byte [rsi + 1] ; Operand.width
shr al, 4
movzx rax, al
movzx rax, word [rsi + 2] ; Operand.width
sub rbx, rax
mov dword [rdi + 0], ebx ; current_stack_size -= width
jmp .done
.free_reg:
xor rax, rax
mov al, byte [rsi + 1] ; Operand.register_and_width
and al, 0x0F ; get register index
movzx rax, byte [rsi + 1] ; Operand.register
mov bx, word [rdi + 48] ; register_bitset
btr bx, ax
jnc .panic ; trying to free unallocated register
@ -1055,14 +1051,7 @@ codegen_expr:
call vec_extend
; construct return operand
; Operand { kind: REGISTER, register_and_width: (register | (width << 4)), len: 0, value: 0 }
mov eax, 0 ; len = 0
shl eax, 16
or eax, 8 ; width = 8
shl eax, 4
or eax, 0 ; register = rax
shl eax, 8
or eax, OPERAND_REGISTER ; kind
mov rax, [rel OPERAND_RAX]
mov rdx, 0 ; value = 0
jmp .done
@ -1071,10 +1060,9 @@ codegen_expr:
mov [rsp + 16], rax ; scratch = *AstNode
mov byte [rsp + 32], OPERAND_IMMEDIATE ; Operand.kind
mov bl, 8 ; width = 8
shl bl, 4 ; register = undef
mov byte [rsp + 33], bl ; Operand.register_and_width
mov word [rsp + 34], 0 ; Operand.len = 0
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
@ -1166,10 +1154,10 @@ codegen_expr:
lea rsi, [rsp + 48] ; right operand
call codegen_free_operand
mov rdx, [rsp + 48] ; right operand
and rdx, 0xF000 ; Operand.width
; move scratch to rhs, but preserve width
movzx rdx, word [rsp + 48 + 2] ; rhs.width
mov word [rsp + 64 + 2], dx ; scratch.width
mov rax, [rsp + 64] ; scratch value
or rax, rdx ; preserve width
mov rdx, [rsp + 72]
mov [rsp + 48], rax ; right operand
mov [rsp + 56], rdx
@ -1332,7 +1320,7 @@ codegen_expr:
call vec_get
mov rdx, [rax + 8] ; offset
neg rdx
mov rax, qword [rel OPERAND_RBP_OFFSET]
mov rax, qword [rel OPERAND_RBP]
mov [rsp + 16], rax
mov [rsp + 24], rdx
@ -1372,7 +1360,8 @@ codegen_expr:
;; start-structs
;; struct Operand {
;; kind: u8
;; register_and_width: u8,
;; register: u8,
;; width: u16,
;; len: u16,
;; value: u64,
;; }
@ -1387,12 +1376,22 @@ section .rdata
OPERAND_IMMEDIATE equ 5 ; e.g. 0x10
OPERAND_CONSTANT equ 6 ; e.g. OPERAND_CONSTANT
OPERAND_LABEL equ 7 ; e.g. label_1234
OPERAND_REGISTER_PLACE equ 8 ; e.g. [rax]
OPERAND_RBP_PLACE equ 9 ; e.g. mov rax, [rbp - 8]; mov [rax], src
;; end-consts
WIDTH_BYTE db 'byte '
WIDTH_WORD db 'word '
WIDTH_DWORD db 'dword '
WIDTH_QWORD db 'qword '
; Operand { kind: REGISTER, register: 0, width: 8, len: 0, padding: 0, value: 0 }
align 8
OPERAND_RAX dq 0x0008_0001, 0
align 8
OPERAND_RDX dq 0x0008_0301, 0
align 8
OPERAND_RBP dq 0x0008_0002, 0
section .text
;; rdi: *text
@ -1424,14 +1423,39 @@ codegen_write_operand:
je .constant
cmp bl, OPERAND_LABEL
je .label
cmp bl, OPERAND_REGISTER_PLACE
je .reg_p
cmp bl, OPERAND_RBP_PLACE
je .rbp_offset
jmp .panic
.reg_p:
mov rbx, rsi
mov byte [rsp + 16], '['
mov rdi, [rsp] ; *text
lea rsi, [rsp + 16]
call vec_push
movzx rdi, byte [rbx + 1] ; Operand.register
movzx rsi, word [rbx + 2] ; Operand.width
lea rdx, [rsp + 16] ; buffer
call get_register_name
mov rdi, [rsp] ; *text
mov rsi, rax ; buffer
call vec_extend
mov byte [rsp + 16], ']'
mov rdi, [rsp] ; *text
lea rsi, [rsp + 16]
call vec_push
.register:
mov rbx, rsi
mov rdi, [rbx + 1] ; register_and_width
mov rsi, rdi
and dil, 0x0F ; low 4 bits = register
shr rsi, 4 ; high 4 bits = width
movzx rdi, byte [rbx + 1] ; Operand.register
movzx rsi, word [rbx + 2] ; Operand.width
lea rdx, [rsp + 16] ; buffer
call get_register_name
@ -1444,8 +1468,7 @@ codegen_write_operand:
.rsp_offset:
; {width} [rbp {+/-} offset]
mov rsi, [rsp + 8] ; op
mov sil, byte [rsi + 1] ; Operand.register_and_width
shr sil, 4 ; width
movzx rsi, word [rsi + 2] ; Operand.width
mov rdi, [rsp] ; *text
call codegen_write_width
mov rbx, rax
@ -1521,8 +1544,8 @@ codegen_write_operand:
; write address name
mov rax, [rsp + 8] ; op
mov rdi, [rsp] ; *text
mov rsi, [rax + 8] ; op.value
mov rdx, [rax + 2] ; op.len
mov rsi, [rax + 8] ; Operand.value
mov rdx, [rax + 4] ; Operand.len
mov dx, dx ; low 16 bits
call vec_extend
@ -1607,10 +1630,10 @@ codegen_move_rbp_slot_src:
; construct dst Operand
mov byte [rsp + 0], OPERAND_RBP_OFFSET ; Operand.kind
mov byte [rsp + 1], 0x80 ; Operand.register_and_width (width=8)
mov word [rsp + 2], 0 ; Operand.len = 0
mov dword [rsp + 4], 0 ; padding
mov qword [rsp + 8], rdx ; Operand.value = rbp offset
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
@ -1849,19 +1872,17 @@ codegen_move_dst_src:
jg .panic ; unsupported dst kind
; if dst.width != src.width
mov cl, byte [rsi + 1] ; dst.register_and_width
mov bl, byte [rdx + 1] ; src.register_and_width
shr cl, 4
shr bl, 4
cmp cl, bl
mov cx, word [rsi + 2] ; dst.width
mov bx, word [rdx + 2] ; src.width
cmp cx, bx
jne .panic ; mismatched widths
; if dst.width == 8 && src.kind == OPERAND_ADDRESS
xor rbx, rbx
cmp cl, 8
cmovne rbx, [rdx + 0]
cmp bl, OPERAND_ADDRESS
je .panic ; address can only be moved to full-sized destinations
; ; if dst.width == 8 && src.kind == OPERAND_ADDRESS
; xor rbx, rbx
; cmp cx, 8
; cmovne rbx, [rdx + 0]
; cmp bl, OPERAND_ADDRESS
; je .panic ; address can only be moved to full-sized destinations
cmp byte [rsi + 0], OPERAND_REGISTER
je .do_move ; if dst == register, do move
@ -1935,11 +1956,3 @@ section .rdata
MUL_ dq "mul "
DIV_ dq "div "
; Operand { kind: REGISTER, register: 0, width: 8, len: 0, padding: 0, value: 0 }
align 8
OPERAND_RAX dq 0x0000_8001, 0
align 8
OPERAND_RDX dq 0x0000_8301, 0
align 8
OPERAND_RBP_OFFSET dq 0x0000_8002, 0

View file

@ -64,6 +64,8 @@ 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_REGISTER_PLACE: u32 = 8;
pub const OPERAND_RBP_PLACE: u32 = 9;
pub const TOKEN_EOF: u8 = 0;
pub const TOKEN_LET: u8 = 1;
pub const TOKEN_IF: u8 = 2;
@ -247,7 +249,8 @@ pub struct FunctionCtx {
#[derive(Debug)]
pub struct Operand {
pub kind: u8,
pub register_and_width: u8,
pub register: u8,
pub width: u16,
pub len: u16,
pub value: u64,
}