codegen for dereference, subscript

This commit is contained in:
pommicket 2022-02-12 13:53:35 -05:00
parent 0a14c8ca2a
commit 0ee06ac2c4
4 changed files with 90 additions and 24 deletions

View file

@ -963,6 +963,40 @@ function generate_stack_sub
emit_mov_qword_rsp_rax() ; mov [rsp], rax emit_mov_qword_rsp_rax() ; mov [rsp], rax
return return
; pop a pointer off of the stack, then push the dereferenced value according to `type`
function generate_stack_dereference
argument statement ; for errors
argument type
local size
size = type_sizeof(type)
emit_mov_rax_qword_rsp() ; mov rax, [rsp]
emit_mov_reg(REG_RBX, REG_RAX) ; mov rbx, rax
if size == 1 goto gen_deref1
if size == 2 goto gen_deref2
if size == 4 goto gen_deref4
if size == 8 goto gen_deref8
byte 0xcc ; @TODO
:gen_deref_cast
emit_push_rax()
generate_cast_top_of_stack(statement, TYPE_UNSIGNED_LONG, type)
return
:gen_deref1
emit_mov_al_byte_rbx()
goto gen_deref_cast
:gen_deref2
emit_mov_ax_word_rbx()
goto gen_deref_cast
:gen_deref4
emit_mov_eax_dword_rbx()
goto gen_deref_cast
:gen_deref8
emit_mov_rax_qword_rbx()
goto gen_deref_cast
; `statement` is used for errors ; `statement` is used for errors
; returns pointer to end of expression ; returns pointer to end of expression
function generate_push_expression function generate_push_expression
@ -988,6 +1022,8 @@ function generate_push_expression
if c == EXPRESSION_SUB goto generate_sub if c == EXPRESSION_SUB goto generate_sub
if c == EXPRESSION_GLOBAL_VARIABLE goto generate_global_variable if c == EXPRESSION_GLOBAL_VARIABLE goto generate_global_variable
if c == EXPRESSION_LOCAL_VARIABLE goto generate_local_variable if c == EXPRESSION_LOCAL_VARIABLE goto generate_local_variable
if c == EXPRESSION_DEREFERENCE goto generate_dereference
if c == EXPRESSION_SUBSCRIPT goto generate_subscript
die(.str_genpushexprNI) die(.str_genpushexprNI)
:str_genpushexprNI :str_genpushexprNI
@ -1075,9 +1111,10 @@ function generate_push_expression
goto generate_logical_not_cont goto generate_logical_not_cont
:generate_global_variable :generate_global_variable
expr += 8 expr += 8
d = *8expr ; address d = *4expr ; address
expr += 8 expr += 4
b = type_is_array(type) b = *4expr ; is array?
expr += 4
if b != 0 goto global_var_array if b != 0 goto global_var_array
c = type_sizeof(type) c = type_sizeof(type)
if c > 8 goto global_var_large if c > 8 goto global_var_large
@ -1107,11 +1144,28 @@ function generate_push_expression
emit_mov_rax_imm64(d) ; mov rax, (address) emit_mov_rax_imm64(d) ; mov rax, (address)
emit_push_rax() ; push rax emit_push_rax() ; push rax
return expr return expr
:generate_dereference
expr += 8
expr = generate_push_expression(statement, expr)
generate_stack_dereference(statement, type)
return expr
:generate_subscript
expr += 8
c = expr + 4 ; type 1
c = *4c
expr = generate_push_expression(statement, expr)
d = expr + 4 ; type 2
d = *4d
expr = generate_push_expression(statement, expr)
generate_stack_add(statement, c, d, c)
generate_stack_dereference(statement, type)
return expr
:generate_local_variable :generate_local_variable
expr += 8 expr += 8
d = *8expr ; rbp offset d = sign_extend_32_to_64(*4expr) ; rbp offset
expr += 8 expr += 4
b = type_is_array(type) b = *4expr ; is array?
expr += 4
if b != 0 goto local_var_array if b != 0 goto local_var_array
c = type_sizeof(type) c = type_sizeof(type)
if c > 8 goto local_var_large if c > 8 goto local_var_large
@ -1139,7 +1193,6 @@ function generate_push_expression
emit_lea_rax_rbp_plus_imm32(d) ; lea rax, [rbp+X] emit_lea_rax_rbp_plus_imm32(d) ; lea rax, [rbp+X]
emit_push_rax() ; push rax emit_push_rax() ; push rax
return expr return expr
byte 0xcc
:generate_float :generate_float
expr += 8 expr += 8
emit_mov_rax_imm64(*8expr) emit_mov_rax_imm64(*8expr)
@ -1211,7 +1264,7 @@ function generate_statement
dat1 += c dat1 += c
dat1 = 0 - dat1 dat1 = 0 - dat1
emit_lea_rsp_rbp_plus_imm32(dat1) emit_lea_rsp_rbp_plus_imm32(dat1)
if dat2 != 0 goto gen_local_decl_data_initializer if dat4 != 0 goto gen_local_decl_data_initializer
return return
:gen_local_decl_initializer :gen_local_decl_initializer
@ -1222,7 +1275,13 @@ function generate_statement
generate_push_expression_casted(statement, dat3, dat2) generate_push_expression_casted(statement, dat3, dat2)
return return
:gen_local_decl_data_initializer :gen_local_decl_data_initializer
byte 0xcc ; @TODO emit_mov_rax_imm64(dat4) ; mov rax, (data address)
emit_mov_reg(REG_RSI, REG_RAX) ; mov rsi, rax
emit_mov_reg(REG_RDI, REG_RSP) ; mov rdi, rsp
emit_mov_rax_imm64(c) ; mov rax, (size)
emit_mov_reg(REG_RCX, REG_RAX) ; mov rcx, rax
emit_rep_movsb() ; rep movsb
return
function generate_function function generate_function

View file

@ -152,8 +152,8 @@
; uint type ; uint type
; immediately following the header in memory are the arguments of the expression ; immediately following the header in memory are the arguments of the expression
; - for functions, a pointer to the name of the function (we don't know where it is yet) ; - for functions, a pointer to the name of the function (we don't know where it is yet)
; - for local variables, the 64-bit rbp offset (number to be subtracted from rbp) ; - for local variables, the 32-bit rbp offset (number to be subtracted from rbp), followed by a 32-bit number, which is 1 if the variable is an array, and 0 otherwise (we can't just check `type` because that might have been decayed into a pointer)
; - for global variables, the 64-bit runtime address ; - for global variables, the 32-bit runtime address, followed by 32-bit is_array
; - for constant ints, the 64-bit integral value ; - for constant ints, the 64-bit integral value
; - for constant floats, the 64-bit double value (even if expression has type float) ; - for constant floats, the 64-bit double value (even if expression has type float)
; - for unary operators, the operand ; - for unary operators, the operand

View file

@ -1,7 +1,6 @@
static char x = -2; static char x = -2;
long main(int argc, char **argv) { long main(int argc, char **argv) {
int y = 38; int y[] = {38, 55, -22};
int z = y + x; int *z = (y+2)[-1];
return z + x; return *z;
} }

View file

@ -2641,6 +2641,7 @@ function parse_expression
if *1p == TYPE_POINTER goto type_long ; pointer difference if *1p == TYPE_POINTER goto type_long ; pointer difference
goto type_binary_left ; pointer minus integer goto type_binary_left ; pointer minus integer
:type_subscript :type_subscript
; @NONSTANDARD: technically 1["hello"] is legal. but why
type_decay_array_to_pointer_in_place(a) type_decay_array_to_pointer_in_place(a)
p = types + b p = types + b
if *1p > TYPE_UNSIGNED_LONG goto subscript_non_integer if *1p > TYPE_UNSIGNED_LONG goto subscript_non_integer
@ -3075,10 +3076,13 @@ function parse_expression
; it is a global variable ; it is a global variable
*1out = EXPRESSION_GLOBAL_VARIABLE *1out = EXPRESSION_GLOBAL_VARIABLE
out += 4 out += 4
*4out = c > 32 ; extract type a = c > 32 ; extract type
*4out = type_create_copy(a)
out += 4
*4out = c & 0xffffffff ; extract address
out += 4
*4out = type_is_array(a)
out += 4 out += 4
*8out = c & 0xffffffff ; extract address
out += 8
return out return out
:not_global :not_global
@ -3103,11 +3107,14 @@ function parse_expression
; it's a local variable ; it's a local variable
*1out = EXPRESSION_LOCAL_VARIABLE *1out = EXPRESSION_LOCAL_VARIABLE
out += 4 out += 4
*4out = c > 32 ; extract type a = c > 32 ; extract type
*4out = type_create_copy(a)
out += 4
c &= 0xffffffff ; extract rbp offset
*4out = c
out += 4
*4out = type_is_array(a)
out += 4 out += 4
c &= 0xffffffff
*8out = sign_extend_32_to_64(c) ; extract rbp offset
out += 8
return out return out
:expression_integer :expression_integer
*1out = EXPRESSION_CONSTANT_INT *1out = EXPRESSION_CONSTANT_INT
@ -4100,7 +4107,8 @@ function print_expression
:print_local_variable :print_local_variable
puts(.str_local_prefix) puts(.str_local_prefix)
expression += 8 expression += 8
putn_with_sign(*8expression) b = sign_extend_32_to_64(*4expression)
putn_with_sign(b)
putc(']) putc('])
expression += 8 expression += 8
return expression return expression
@ -4115,7 +4123,7 @@ function print_expression
:print_global_variable :print_global_variable
puts(.str_global_at) puts(.str_global_at)
expression += 8 expression += 8
putx32(*8expression) putx32(*4expression)
expression += 8 expression += 8
return expression return expression
:print_cast :print_cast