fix generate_function_addr; conditional expressions

This commit is contained in:
pommicket 2022-02-12 23:04:53 -05:00
parent e0495afd42
commit 47688e0a46
3 changed files with 74 additions and 45 deletions

View file

@ -1351,7 +1351,28 @@ function generate_stack_assign
emit_mov_qword_rbx_rax() ; mov [rbx], rax emit_mov_qword_rbx_rax() ; mov [rbx], rax
goto gen_assign_ret 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 ; returns pointer to end of expr
function generate_push_address_of_expression function generate_push_address_of_expression
@ -1425,13 +1446,15 @@ function generate_push_expression
local c local c
local d local d
local p local p
local addr1
local addr2
local type local type
type = expr + 4 type = expr + 4
type = *4type type = *4type
c = *1expr c = *1expr
; @TODO : reorder from most to least common, probably
if c == EXPRESSION_CONSTANT_INT goto generate_int if c == EXPRESSION_CONSTANT_INT goto generate_int
if c == EXPRESSION_CONSTANT_FLOAT goto generate_float if c == EXPRESSION_CONSTANT_FLOAT goto generate_float
if c == EXPRESSION_FUNCTION goto generate_function_addr 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_COMMA goto generate_comma
if c == EXPRESSION_ASSIGN goto generate_assign if c == EXPRESSION_ASSIGN goto generate_assign
if c == EXPRESSION_CALL goto generate_call if c == EXPRESSION_CALL goto generate_call
if c == EXPRESSION_CONDITIONAL goto generate_conditional
putnln(c) putnln(c)
@ -1472,7 +1496,7 @@ function generate_push_expression
expr = generate_push_expression_casted(statement, expr, type) expr = generate_push_expression_casted(statement, expr, type)
return expr return expr
:generate_function_addr :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 expr += 8
if codegen_second_pass == 0 goto function_noaddr if codegen_second_pass == 0 goto function_noaddr
d = ident_list_lookup(functions_addresses, *8expr) d = ident_list_lookup(functions_addresses, *8expr)
@ -1623,31 +1647,37 @@ function generate_push_expression
:generate_unary_logical_not :generate_unary_logical_not
expr += 8 expr += 8
p = expr + 4 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) expr = generate_push_expression(statement, expr)
generate_stack_compare_against_zero(statement, *4p)
emit_mov_rax_qword_rsp() ; mov rax, [rsp]
emit_test_rax_rax() ; test rax, rax
:generate_logical_not_cont
emit_je_rel32(7) ; je +7 (2 bytes for xor eax, eax; 5 bytes for jmp +10) emit_je_rel32(7) ; je +7 (2 bytes for xor eax, eax; 5 bytes for jmp +10)
emit_zero_rax() ; xor eax, eax emit_zero_rax() ; xor eax, eax
emit_jmp_rel32(10) ; jmp +10 (10 bytes for mov rax, 1) emit_jmp_rel32(10) ; jmp +10 (10 bytes for mov rax, 1)
emit_mov_rax_imm64(1) ; 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 return expr
:generate_logical_not_floating :generate_conditional
; we want !-0.0 to be 1, so this needs to be a separate case expr += 8
expr = generate_push_expression_casted(statement, expr, TYPE_DOUBLE) ; cast floats to doubles when comparing p = expr + 4
emit_zero_rax() ; xor eax, eax expr = generate_push_expression(statement, expr)
emit_movq_xmm1_rax() ; movq xmm1, rax generate_stack_compare_against_zero(statement, *4p)
emit_mov_rax_qword_rsp() ; mov rax, [rsp] emit_je_rel32(0) ; temporary je +0 (correct offset will be filled in)
emit_movq_xmm0_rax() ; movq xmm0, rax c = code_output
emit_comisd_xmm0_xmm1() ; comisd xmm0, xmm1 expr = generate_push_expression_casted(statement, expr, type)
goto generate_logical_not_cont 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 :generate_global_variable
expr += 8 expr += 8
d = *4expr ; address d = *4expr ; address

View file

@ -1,28 +1,17 @@
typedef struct { long factorial(long x) {
long a; return x ? x * factorial(x - 1)
long aah[810]; : 1;
long b;
} Structure;
Structure mkstruct(int x, int y) {
Structure s;
s.a = x;
s.b = y;
return s;
} }
Structure mkstruct1(int x) { long fibonacci(long x) {
return mkstruct(x, x*2); return x ?
x-1 ?
fibonacci(x-1) + fibonacci(x-2)
: 1
: 0;
} }
Structure mkstruct_a() { int main(int argc, char **argv) {
return mkstruct1(1033.3); return fibonacci(30);
}
long main(int argc, char **argv) {
Structure t;
t = mkstruct_a();
return t.b;
} }

View file

@ -3075,6 +3075,11 @@ function parse_expression
a = out + 4 a = out + 4
out = parse_expression(tokens, best, out) out = parse_expression(tokens, best, out)
type_decay_array_to_pointer_in_place(*4a) 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 a = out + 4 ; type of left branch of conditional
best += 16 best += 16
out = parse_expression(best, p, out) out = parse_expression(best, p, out)
@ -3093,6 +3098,11 @@ function parse_expression
; no conversions ; no conversions
*4type = *4a *4type = *4a
return out 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 :parse_postincrement
*1out = EXPRESSION_POST_INCREMENT *1out = EXPRESSION_POST_INCREMENT
p = tokens_end - 16 p = tokens_end - 16