break, continue

This commit is contained in:
pommicket 2022-02-13 12:43:34 -05:00
parent 70523ba1bb
commit a26f0d52d9
2 changed files with 112 additions and 7 deletions

View file

@ -23,6 +23,9 @@ global functions_labels ; ident list of ident lists of label addresses
global curr_function_labels ; ident list of labels for current function (written to in 1st pass, read from in 2nd pass) global curr_function_labels ; ident list of labels for current function (written to in 1st pass, read from in 2nd pass)
global curr_function_return_type global curr_function_return_type
global break_refs ; 0-terminated array of pointers to be filled in with the break offset
global continue_refs
#define REG_RAX 0 #define REG_RAX 0
#define REG_RBX 3 #define REG_RBX 3
#define REG_RCX 1 #define REG_RCX 1
@ -2503,6 +2506,43 @@ function generate_push_expression
emit_add_rsp_imm32(args_size) emit_add_rsp_imm32(args_size)
return return
; fill in break/continue jump addresses
function handle_refs
argument p_refs
argument prev_refs
argument ref_addr
local refs
local p
local addr
local d
refs = *8p_refs
p = refs
:handle_refs_loop
if *8p == 0 goto handle_refs_loop_end
addr = *8p
p += 8
d = ref_addr - addr
addr -= 4
*4addr = d
goto handle_refs_loop
:handle_refs_loop_end
free(refs)
*8p_refs = prev_refs
return
function add_ref
argument refs
argument addr
:add_ref_loop
if *8refs == 0 goto add_ref_loop_end
refs += 8
goto add_ref_loop
:add_ref_loop_end
*8refs = addr
return
function generate_statement function generate_statement
argument statement argument statement
local dat1 local dat1
@ -2512,11 +2552,16 @@ function generate_statement
local addr0 local addr0
local addr1 local addr1
local addr2 local addr2
local prev_continue_refs
local prev_break_refs
local n local n
local p local p
local c local c
local d local d
prev_continue_refs = continue_refs
prev_break_refs = break_refs
dat1 = statement + 8 dat1 = statement + 8
dat1 = *8dat1 dat1 = *8dat1
dat2 = statement + 16 dat2 = statement + 16
@ -2528,6 +2573,7 @@ function generate_statement
c = *1statement c = *1statement
if c == STATEMENT_NOOP goto return_0
if c == STATEMENT_BLOCK goto gen_block if c == STATEMENT_BLOCK goto gen_block
if c == STATEMENT_RETURN goto gen_return if c == STATEMENT_RETURN goto gen_return
if c == STATEMENT_LOCAL_DECLARATION goto gen_local_decl if c == STATEMENT_LOCAL_DECLARATION goto gen_local_decl
@ -2535,6 +2581,9 @@ function generate_statement
if c == STATEMENT_IF goto gen_stmt_if if c == STATEMENT_IF goto gen_stmt_if
if c == STATEMENT_WHILE goto gen_stmt_while if c == STATEMENT_WHILE goto gen_stmt_while
if c == STATEMENT_DO goto gen_stmt_do if c == STATEMENT_DO goto gen_stmt_do
if c == STATEMENT_FOR goto gen_stmt_for
if c == STATEMENT_CONTINUE goto gen_stmt_continue
if c == STATEMENT_BREAK goto gen_stmt_break
; @TODO ; @TODO
die(.str_genstmtNI) die(.str_genstmtNI)
@ -2616,6 +2665,9 @@ function generate_statement
*4addr1 = d *4addr1 = d
return return
:gen_stmt_while :gen_stmt_while
continue_refs = malloc(8000)
break_refs = malloc(8000)
addr0 = code_output addr0 = code_output
p = dat1 + 4 p = dat1 + 4
generate_push_expression(statement, dat1) generate_push_expression(statement, dat1)
@ -2625,6 +2677,10 @@ function generate_statement
generate_statement(dat2) generate_statement(dat2)
emit_jmp_rel32(0) ; jmp +0 (temporary) emit_jmp_rel32(0) ; jmp +0 (temporary)
addr2 = code_output addr2 = code_output
handle_refs(&continue_refs, prev_continue_refs, addr0)
handle_refs(&break_refs, prev_break_refs, addr2)
; fill in je ; fill in je
d = addr2 - addr1 d = addr2 - addr1
p = addr1 - 4 p = addr1 - 4
@ -2635,6 +2691,9 @@ function generate_statement
*4p = d *4p = d
return return
:gen_stmt_do :gen_stmt_do
continue_refs = malloc(8000)
break_refs = malloc(8000)
addr0 = code_output addr0 = code_output
generate_statement(dat1) generate_statement(dat1)
p = dat2 + 4 p = dat2 + 4
@ -2642,10 +2701,52 @@ function generate_statement
generate_stack_compare_against_zero(statement, *4p) generate_stack_compare_against_zero(statement, *4p)
emit_jne_rel32(0) ; jne +0 (temorary) emit_jne_rel32(0) ; jne +0 (temorary)
addr1 = code_output addr1 = code_output
handle_refs(&continue_refs, prev_continue_refs, addr0)
handle_refs(&break_refs, prev_break_refs, addr1)
d = addr0 - addr1 d = addr0 - addr1
addr1 -= 4 addr1 -= 4
*4addr1 = d *4addr1 = d
return return
:gen_stmt_for
continue_refs = malloc(8000)
break_refs = malloc(8000)
generate_push_expression_casted(statement, dat1, TYPE_VOID)
emit_add_rsp_imm32(8) ; void is stored as 8 bytes
addr0 = code_output
p = dat2 + 4
generate_push_expression(statement, dat2)
generate_stack_compare_against_zero(statement, *4p)
emit_je_rel32(0) ; je +0 (temporary)
addr1 = code_output
generate_statement(dat4)
handle_refs(&continue_refs, prev_continue_refs, code_output)
generate_push_expression_casted(statement, dat3, TYPE_VOID)
emit_add_rsp_imm32(8) ; void is stored as 8 bytes
emit_jmp_rel32(0) ; jmp +0 (temporary)
addr2 = code_output
handle_refs(&break_refs, prev_break_refs, addr2)
; fill in je
d = addr2 - addr1
p = addr1 - 4
*4p = d
; fill in jmp
d = addr0 - addr2
p = addr2 - 4
*4p = d
return
:gen_stmt_continue
emit_jmp_rel32(0) ; jmp +0 (temporary)
add_ref(continue_refs, code_output)
return
:gen_stmt_break
emit_jmp_rel32(0) ; jmp +0 (temporary)
add_ref(break_refs, code_output)
return
function generate_function function generate_function
argument function_name argument function_name

View file

@ -24,12 +24,16 @@ long gcd(long a, long b) {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
double f = 1;
int exp = 0; int exp = 0;
do { int i;
f /= 2; int j;
++exp; for (i = 0; i < 10; ++i) {
} while (f); for (j = 0; j < 10; ++j) {
return exp; if (j >= i) break;
exp += 1;
}
if (i >= 5) break;
}
return exp ;
} }