fix generate_function_addr; conditional expressions
This commit is contained in:
parent
e0495afd42
commit
47688e0a46
3 changed files with 74 additions and 45 deletions
72
05/codegen.b
72
05/codegen.b
|
@ -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
|
||||||
|
|
33
05/main.c
33
05/main.c
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
05/parse.b
10
05/parse.b
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue