From 47688e0a467dc7960740f8730539c3b806c033da Mon Sep 17 00:00:00 2001 From: pommicket Date: Sat, 12 Feb 2022 23:04:53 -0500 Subject: fix generate_function_addr; conditional expressions --- 05/codegen.b | 76 ++++++++++++++++++++++++++++++++++++++++++------------------ 05/main.c | 33 +++++++++----------------- 05/parse.b | 10 ++++++++ 3 files changed, 74 insertions(+), 45 deletions(-) diff --git a/05/codegen.b b/05/codegen.b index d30e23d..7c984da 100644 --- a/05/codegen.b +++ b/05/codegen.b @@ -1350,9 +1350,30 @@ function generate_stack_assign emit_mov_rax_qword_rsp_plus_imm32(8) ; mov rax, [rsp+8] emit_mov_qword_rbx_rax() ; mov [rbx], rax goto gen_assign_ret - - - + +; pop from the stack and compare with 0 (setting eflags appropriately) +function generate_stack_compare_against_zero + argument statement + argument type + local p + p = types + type + if *1p == TYPE_FLOAT goto cmp_zero_float + if *1p == TYPE_DOUBLE goto cmp_zero_double + emit_add_rsp_imm32(8) ; add rsp, 8 + emit_mov_rax_qword_rsp_plus_imm32(-8) ; mov rax, [rsp-8] + emit_test_rax_rax() ; test rax, rax + return + :cmp_zero_float + generate_cast_top_of_stack(statement, TYPE_FLOAT, TYPE_DOUBLE) ; cast to double for comparison + :cmp_zero_double + emit_add_rsp_imm32(8) ; add rsp, 8 + emit_zero_rax() ; xor eax, eax + emit_movq_xmm1_rax() ; movq xmm1, rax + emit_mov_rax_qword_rsp_plus_imm32(-8) ; mov rax, [rsp-8] + emit_movq_xmm0_rax() ; movq xmm0, rax + emit_comisd_xmm0_xmm1() ; comisd xmm0, xmm1 + return + ; returns pointer to end of expr function generate_push_address_of_expression argument statement ; for errors @@ -1425,13 +1446,15 @@ function generate_push_expression local c local d local p + local addr1 + local addr2 local type type = expr + 4 type = *4type c = *1expr - ; @TODO : reorder from most to least common, probably + if c == EXPRESSION_CONSTANT_INT goto generate_int if c == EXPRESSION_CONSTANT_FLOAT goto generate_float if c == EXPRESSION_FUNCTION goto generate_function_addr @@ -1460,6 +1483,7 @@ function generate_push_expression if c == EXPRESSION_COMMA goto generate_comma if c == EXPRESSION_ASSIGN goto generate_assign if c == EXPRESSION_CALL goto generate_call + if c == EXPRESSION_CONDITIONAL goto generate_conditional putnln(c) @@ -1472,7 +1496,7 @@ function generate_push_expression expr = generate_push_expression_casted(statement, expr, type) return expr :generate_function_addr - d = 0 + d = 1 ; default to address of 1, not 0 because that will be optimized to xor eax, eax expr += 8 if codegen_second_pass == 0 goto function_noaddr d = ident_list_lookup(functions_addresses, *8expr) @@ -1623,31 +1647,37 @@ function generate_push_expression :generate_unary_logical_not expr += 8 p = expr + 4 - p = types + *4p - if *1p == TYPE_FLOAT goto generate_logical_not_floating - if *1p == TYPE_DOUBLE goto generate_logical_not_floating - expr = generate_push_expression(statement, expr) - - emit_mov_rax_qword_rsp() ; mov rax, [rsp] - emit_test_rax_rax() ; test rax, rax - :generate_logical_not_cont + generate_stack_compare_against_zero(statement, *4p) emit_je_rel32(7) ; je +7 (2 bytes for xor eax, eax; 5 bytes for jmp +10) emit_zero_rax() ; xor eax, eax emit_jmp_rel32(10) ; jmp +10 (10 bytes for mov rax, 1) emit_mov_rax_imm64(1) ; mov rax, 1 - emit_mov_qword_rsp_rax() ; mov [rsp], rax + emit_push_rax() ; push rax return expr - :generate_logical_not_floating - ; we want !-0.0 to be 1, so this needs to be a separate case - expr = generate_push_expression_casted(statement, expr, TYPE_DOUBLE) ; cast floats to doubles when comparing - emit_zero_rax() ; xor eax, eax - emit_movq_xmm1_rax() ; movq xmm1, rax - emit_mov_rax_qword_rsp() ; mov rax, [rsp] - emit_movq_xmm0_rax() ; movq xmm0, rax - emit_comisd_xmm0_xmm1() ; comisd xmm0, xmm1 - goto generate_logical_not_cont + :generate_conditional + expr += 8 + p = expr + 4 + expr = generate_push_expression(statement, expr) + generate_stack_compare_against_zero(statement, *4p) + emit_je_rel32(0) ; temporary je +0 (correct offset will be filled in) + c = code_output + expr = generate_push_expression_casted(statement, expr, type) + d = code_output + ; fill in jump offset + d -= c + c -= 4 + *4c = d + 5 ; + 5 because of the jmp instruction below + emit_jmp_rel32(0) ; temporary jmp +0 (correct offset will be filled in) + c = code_output + expr = generate_push_expression_casted(statement, expr, type) + d = code_output + ; fill in jump offset + d -= c + c -= 4 + *4c = d + return expr :generate_global_variable expr += 8 d = *4expr ; address diff --git a/05/main.c b/05/main.c index 7ca2c81..f5b8167 100644 --- a/05/main.c +++ b/05/main.c @@ -1,28 +1,17 @@ -typedef struct { - long a; - long aah[810]; - long b; -} Structure; - -Structure mkstruct(int x, int y) { - Structure s; - s.a = x; - s.b = y; - return s; -} - -Structure mkstruct1(int x) { - return mkstruct(x, x*2); +long factorial(long x) { + return x ? x * factorial(x - 1) + : 1; } -Structure mkstruct_a() { - return mkstruct1(1033.3); +long fibonacci(long x) { + return x ? + x-1 ? + fibonacci(x-1) + fibonacci(x-2) + : 1 + : 0; } - -long main(int argc, char **argv) { - Structure t; - t = mkstruct_a(); - return t.b; +int main(int argc, char **argv) { + return fibonacci(30); } diff --git a/05/parse.b b/05/parse.b index 61b2418..96941b9 100644 --- a/05/parse.b +++ b/05/parse.b @@ -3075,6 +3075,11 @@ function parse_expression a = out + 4 out = parse_expression(tokens, best, out) type_decay_array_to_pointer_in_place(*4a) + + ; check type of "condition" + b = types + *4a + if *1b > TYPE_POINTER goto bad_condition_type + a = out + 4 ; type of left branch of conditional best += 16 out = parse_expression(best, p, out) @@ -3093,6 +3098,11 @@ function parse_expression ; no conversions *4type = *4a return out + :bad_condition_type + token_error(tokens, .str_bad_condition_type) + :str_bad_condition_type + string Bad condition type for conditional operator (? :). + byte 0 :parse_postincrement *1out = EXPRESSION_POST_INCREMENT p = tokens_end - 16 -- cgit v1.2.3