summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--05/codegen.b76
-rw-r--r--05/main.c33
-rw-r--r--05/parse.b10
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