codegen for address of
This commit is contained in:
parent
0ee06ac2c4
commit
864b23702a
3 changed files with 79 additions and 4 deletions
67
05/codegen.b
67
05/codegen.b
|
@ -997,6 +997,68 @@ function generate_stack_dereference
|
||||||
emit_mov_rax_qword_rbx()
|
emit_mov_rax_qword_rbx()
|
||||||
goto gen_deref_cast
|
goto gen_deref_cast
|
||||||
|
|
||||||
|
; returns pointer to end of expr
|
||||||
|
function generate_push_address_of_expression
|
||||||
|
argument statement ; for errors
|
||||||
|
argument expr
|
||||||
|
|
||||||
|
local c
|
||||||
|
local d
|
||||||
|
|
||||||
|
c = *1expr
|
||||||
|
|
||||||
|
if c == EXPRESSION_GLOBAL_VARIABLE goto addrof_global_var
|
||||||
|
if c == EXPRESSION_LOCAL_VARIABLE goto addrof_local_var
|
||||||
|
if c == EXPRESSION_DEREFERENCE goto addrof_dereference
|
||||||
|
if c == EXPRESSION_SUBSCRIPT goto addrof_subscript
|
||||||
|
if c == EXPRESSION_DOT goto addrof_dot
|
||||||
|
if c == EXPRESSION_ARROW goto addrof_arrow
|
||||||
|
|
||||||
|
statement_error(statement, .str_bad_lvalue)
|
||||||
|
:str_bad_lvalue
|
||||||
|
string Bad l-value.
|
||||||
|
byte 0
|
||||||
|
:addrof_global_var
|
||||||
|
expr += 8
|
||||||
|
emit_mov_rax_imm64(*4expr)
|
||||||
|
emit_push_rax()
|
||||||
|
expr += 8
|
||||||
|
return expr
|
||||||
|
:addrof_local_var
|
||||||
|
expr += 8
|
||||||
|
emit_lea_rax_rbp_plus_imm32(*4expr)
|
||||||
|
emit_push_rax()
|
||||||
|
expr += 8
|
||||||
|
return expr
|
||||||
|
:addrof_dereference
|
||||||
|
expr += 8
|
||||||
|
return generate_push_expression(statement, expr)
|
||||||
|
:addrof_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)
|
||||||
|
return expr
|
||||||
|
:addrof_dot
|
||||||
|
expr += 8
|
||||||
|
expr = generate_push_address_of_expression(statement, expr)
|
||||||
|
goto addrof_dot_cont
|
||||||
|
:addrof_arrow
|
||||||
|
expr += 8
|
||||||
|
expr = generate_push_expression(statement, expr)
|
||||||
|
:addrof_dot_cont
|
||||||
|
emit_mov_rax_qword_rsp() ; mov rax, [rsp]
|
||||||
|
emit_mov_reg(REG_RBX, REG_RAX) ; mov rbx, rax
|
||||||
|
emit_mov_rax_imm64(*8expr) ; mov rax, (offset to member)
|
||||||
|
emit_add_rax_rbx() ; add rax, rbx
|
||||||
|
emit_mov_qword_rsp_rax() ; mov [rsp], rax
|
||||||
|
expr += 8
|
||||||
|
return expr
|
||||||
|
|
||||||
; `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
|
||||||
|
@ -1024,6 +1086,7 @@ function generate_push_expression
|
||||||
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_DEREFERENCE goto generate_dereference
|
||||||
if c == EXPRESSION_SUBSCRIPT goto generate_subscript
|
if c == EXPRESSION_SUBSCRIPT goto generate_subscript
|
||||||
|
if c == EXPRESSION_ADDRESS_OF goto generate_address_of
|
||||||
|
|
||||||
die(.str_genpushexprNI)
|
die(.str_genpushexprNI)
|
||||||
:str_genpushexprNI
|
:str_genpushexprNI
|
||||||
|
@ -1065,6 +1128,10 @@ function generate_push_expression
|
||||||
emit_mov_qword_rsp_rax() ; mov [rsp], rax
|
emit_mov_qword_rsp_rax() ; mov [rsp], rax
|
||||||
generate_cast_top_of_stack(statement, TYPE_UNSIGNED_LONG, type)
|
generate_cast_top_of_stack(statement, TYPE_UNSIGNED_LONG, type)
|
||||||
return expr
|
return expr
|
||||||
|
:generate_address_of
|
||||||
|
expr += 8
|
||||||
|
expr = generate_push_address_of_expression(statement, expr)
|
||||||
|
return expr
|
||||||
:generate_add
|
:generate_add
|
||||||
expr += 8
|
expr += 8
|
||||||
c = expr + 4 ; type of 1st operand
|
c = expr + 4 ; type of 1st operand
|
||||||
|
|
|
@ -160,7 +160,6 @@
|
||||||
; - for casts, the operand (type is given by type member)
|
; - for casts, the operand (type is given by type member)
|
||||||
; - for binary operators, the first operand followed by the second
|
; - for binary operators, the first operand followed by the second
|
||||||
; - for the operators . and ->, the first argument is the expression on the left-hand side, and the second argument is a 64-bit offset.
|
; - for the operators . and ->, the first argument is the expression on the left-hand side, and the second argument is a 64-bit offset.
|
||||||
; we could use a 32-bit offset but that would cause things to be unaligned.
|
|
||||||
; - for the ternary operator ? :, the first followed by the second followed by the third
|
; - for the ternary operator ? :, the first followed by the second followed by the third
|
||||||
; - for function calls, the function, followed by each of the arguments to the function, followed by 8 bytes of zeros
|
; - for function calls, the function, followed by each of the arguments to the function, followed by 8 bytes of zeros
|
||||||
; File/line number are not stored in expressions.
|
; File/line number are not stored in expressions.
|
||||||
|
|
15
05/main.c
15
05/main.c
|
@ -1,6 +1,15 @@
|
||||||
static char x = -2;
|
static char x = -2;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int x;
|
||||||
|
char y;
|
||||||
|
int z;
|
||||||
|
} Structure;
|
||||||
|
|
||||||
|
|
||||||
long main(int argc, char **argv) {
|
long main(int argc, char **argv) {
|
||||||
int y[] = {38, 55, -22};
|
Structure s[] = {3, 5, -88,6,9,12};
|
||||||
int *z = (y+2)[-1];
|
Structure *ps = s;
|
||||||
return *z;
|
int *p = &ps->z;
|
||||||
|
return *p;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue