dangerous: resize width field on Operand
This commit is contained in:
parent
6dff42cfa5
commit
d46837903b
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue