summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-02-13 12:51:21 -0500
committerpommicket <pommicket@gmail.com>2022-02-13 12:51:21 -0500
commit5dba28b8bac76835e437091f3aed22a2578b7652 (patch)
tree7f5f30ae6ad80611543712431f49fe567db06ff8
parenta26f0d52d9f6934d792eb2e7457946a0515b9a5c (diff)
labels, goto
-rw-r--r--05/codegen.b32
-rw-r--r--05/main.c16
2 files changed, 38 insertions, 10 deletions
diff --git a/05/codegen.b b/05/codegen.b
index a75c4d4..6c8728a 100644
--- a/05/codegen.b
+++ b/05/codegen.b
@@ -2584,6 +2584,8 @@ function generate_statement
if c == STATEMENT_FOR goto gen_stmt_for
if c == STATEMENT_CONTINUE goto gen_stmt_continue
if c == STATEMENT_BREAK goto gen_stmt_break
+ if c == STATEMENT_LABEL goto gen_stmt_label
+ if c == STATEMENT_GOTO goto gen_stmt_goto
; @TODO
die(.str_genstmtNI)
@@ -2747,7 +2749,35 @@ function generate_statement
emit_jmp_rel32(0) ; jmp +0 (temporary)
add_ref(break_refs, code_output)
return
-
+ :gen_stmt_label
+ if codegen_second_pass != 0 goto gen_label_pass2
+ ident_list_add(curr_function_labels, dat1, code_output)
+ return
+ :gen_label_pass2
+ addr1 = ident_list_lookup(curr_function_labels, dat1)
+ if addr1 != code_output goto bad_label_addr
+ return
+ :bad_label_addr
+ die(.str_bad_label_addr)
+ :str_bad_label_addr
+ string Internal compiler error: Label address on 2nd pass doesn't match 1st pass.
+ byte 0
+ :gen_stmt_goto
+ if codegen_second_pass == 0 goto gen_goto_pass1
+ addr0 = ident_list_lookup(curr_function_labels, dat1)
+ if addr0 == 0 goto bad_label
+ d = addr0 - code_output
+ d -= 5 ; subtract length of jmp instruction
+ emit_jmp_rel32(d)
+ return
+ :gen_goto_pass1
+ emit_jmp_rel32(0) ; we don't know the address of the label; just use 0
+ return
+ :bad_label
+ statement_error(statement, .str_bad_label)
+ :str_bad_label
+ string Unrecognized label.
+ byte 0
function generate_function
argument function_name
argument function_statement
diff --git a/05/main.c b/05/main.c
index d36b6e6..cf2de7e 100644
--- a/05/main.c
+++ b/05/main.c
@@ -23,17 +23,15 @@ long gcd(long a, long b) {
return b;
}
+int f() {
+ lb: goto lb;
+}
+
int main(int argc, char **argv) {
int exp = 0;
- int i;
- int j;
- for (i = 0; i < 10; ++i) {
- for (j = 0; j < 10; ++j) {
- if (j >= i) break;
- exp += 1;
- }
- if (i >= 5) break;
- }
+ lb:
+ exp++;
+ if (exp < 10) goto lb;
return exp ;
}