diff options
-rw-r--r-- | 05/codegen.b | 77 | ||||
-rw-r--r-- | 05/constants.b | 4 | ||||
-rw-r--r-- | 05/main.c | 7 | ||||
-rw-r--r-- | 05/parse.b | 26 |
4 files changed, 90 insertions, 24 deletions
diff --git a/05/codegen.b b/05/codegen.b index a67a9db..7701391 100644 --- a/05/codegen.b +++ b/05/codegen.b @@ -963,6 +963,40 @@ function generate_stack_sub emit_mov_qword_rsp_rax() ; mov [rsp], rax 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 ; returns pointer to end of expression function generate_push_expression @@ -988,6 +1022,8 @@ function generate_push_expression if c == EXPRESSION_SUB goto generate_sub if c == EXPRESSION_GLOBAL_VARIABLE goto generate_global_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) :str_genpushexprNI @@ -1075,9 +1111,10 @@ function generate_push_expression goto generate_logical_not_cont :generate_global_variable expr += 8 - d = *8expr ; address - expr += 8 - b = type_is_array(type) + d = *4expr ; address + expr += 4 + b = *4expr ; is array? + expr += 4 if b != 0 goto global_var_array c = type_sizeof(type) if c > 8 goto global_var_large @@ -1107,11 +1144,28 @@ function generate_push_expression emit_mov_rax_imm64(d) ; mov rax, (address) emit_push_rax() ; push rax return expr - :generate_local_variable + :generate_dereference + expr += 8 + expr = generate_push_expression(statement, expr) + generate_stack_dereference(statement, type) + return expr + :generate_subscript expr += 8 - d = *8expr ; rbp offset + 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 expr += 8 - b = type_is_array(type) + d = sign_extend_32_to_64(*4expr) ; rbp offset + expr += 4 + b = *4expr ; is array? + expr += 4 if b != 0 goto local_var_array c = type_sizeof(type) 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_push_rax() ; push rax return expr - byte 0xcc :generate_float expr += 8 emit_mov_rax_imm64(*8expr) @@ -1211,7 +1264,7 @@ function generate_statement dat1 += c dat1 = 0 - 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 :gen_local_decl_initializer @@ -1222,7 +1275,13 @@ function generate_statement generate_push_expression_casted(statement, dat3, dat2) return :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 diff --git a/05/constants.b b/05/constants.b index 79cd8e5..9a39ecd 100644 --- a/05/constants.b +++ b/05/constants.b @@ -152,8 +152,8 @@ ; uint type ; 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 local variables, the 64-bit rbp offset (number to be subtracted from rbp) -; - for global variables, the 64-bit runtime address +; - 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 32-bit runtime address, followed by 32-bit is_array ; - for constant ints, the 64-bit integral value ; - for constant floats, the 64-bit double value (even if expression has type float) ; - for unary operators, the operand @@ -1,7 +1,6 @@ static char x = -2; - long main(int argc, char **argv) { - int y = 38; - int z = y + x; - return z + x; + int y[] = {38, 55, -22}; + int *z = (y+2)[-1]; + return *z; } @@ -2641,6 +2641,7 @@ function parse_expression if *1p == TYPE_POINTER goto type_long ; pointer difference goto type_binary_left ; pointer minus integer :type_subscript + ; @NONSTANDARD: technically 1["hello"] is legal. but why type_decay_array_to_pointer_in_place(a) p = types + b if *1p > TYPE_UNSIGNED_LONG goto subscript_non_integer @@ -3075,10 +3076,13 @@ function parse_expression ; it is a global variable *1out = EXPRESSION_GLOBAL_VARIABLE 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 - *8out = c & 0xffffffff ; extract address - out += 8 return out :not_global @@ -3103,11 +3107,14 @@ function parse_expression ; it's a local variable *1out = EXPRESSION_LOCAL_VARIABLE 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 - c &= 0xffffffff - *8out = sign_extend_32_to_64(c) ; extract rbp offset - out += 8 return out :expression_integer *1out = EXPRESSION_CONSTANT_INT @@ -4100,7 +4107,8 @@ function print_expression :print_local_variable puts(.str_local_prefix) expression += 8 - putn_with_sign(*8expression) + b = sign_extend_32_to_64(*4expression) + putn_with_sign(b) putc(']) expression += 8 return expression @@ -4115,7 +4123,7 @@ function print_expression :print_global_variable puts(.str_global_at) expression += 8 - putx32(*8expression) + putx32(*4expression) expression += 8 return expression :print_cast |