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