compiler

Unnamed Compiled Systems Language Project
git clone http://frotz.net/git/compiler.git
Log | Files | Refs

commit 7297370069e8d96cc8a5b77bd53f8e7cd01bd0c2
parent 435e53aa0c52fb02d5158f63be5f20a14f5cb746
Author: Brian Swetland <swetland@frotz.net>
Date:   Sun, 15 Mar 2020 10:10:51 -0700

compiler: support logical and/or operations

- these correctly shortcut
- add test cases

Diffstat:
Msrc/compiler.c | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Atest/1031-logical-and-or.log | 27+++++++++++++++++++++++++++
Atest/1031-logical-and-or.src | 31+++++++++++++++++++++++++++++++
3 files changed, 127 insertions(+), 10 deletions(-)

diff --git a/src/compiler.c b/src/compiler.c @@ -375,6 +375,11 @@ void gen_call(Item func); // returns address to fixup u32 gen_branch_cond(Item x, bool sense); +// used by && and || on opposing code flows +// bool1 version loads val, bool2 version loads !val +void gen_load_bool1(Item x, bool val); +void gen_load_bool2(Item x); + // generate a backward branch to addr void gen_branch_back(u32 addr); @@ -1173,21 +1178,63 @@ void parse_rel_expr(Item x) { void parse_and_expr(Item x) { parse_rel_expr(x); - while (ctx.tok == tAND) { - next(); - ItemRec y; - parse_rel_expr(&y); - error("<TODO> and op"); + if (ctx.tok == tAND) { + Scope outer = push_scope(sBlock, nil); + + // if !x goto nope + gen_branch_cond(x, false); + add_scope_fixup(outer); + + while (ctx.tok == tAND) { + next(); + ItemRec y; + + // if !y goto nope + parse_rel_expr(&y); + gen_branch_cond(&y, false); + add_scope_fixup(outer); + } + // res = true, goto done + gen_load_bool1(x, true); + u32 l0_true = gen_branch_fwd(); + + // nope: res = false + pop_scope(); + gen_load_bool2(x); + + // done: + fixup_branch_fwd(l0_true); } } void parse_expr(Item x) { parse_and_expr(x); - while (ctx.tok == tOR) { - next(); - ItemRec y; - parse_and_expr(&y); - error("<TODO> or op"); + if (ctx.tok == tOR) { + Scope outer = push_scope(sBlock, nil); + + // if x goto yup + gen_branch_cond(x, true); + add_scope_fixup(outer); + + while (ctx.tok == tOR) { + next(); + ItemRec y; + + // if y goto yup + parse_rel_expr(&y); + gen_branch_cond(&y, true); + add_scope_fixup(outer); + } + // res = false, goto done + gen_load_bool1(x, false); + u32 l0_false = gen_branch_fwd(); + + // yup: res = true + pop_scope(); + gen_load_bool2(x); + + // done: + fixup_branch_fwd(l0_false); } } @@ -1512,6 +1559,7 @@ void parse_global_var() { gvar->next = ctx.scope->first; ctx.scope->first = gvar; ctx.alloc_global = ctx.alloc_global + type->size; + ctx.alloc_global = (ctx.alloc_global + 3) & (~3); // round to word if (ctx.tok == tASSIGN) { next(); @@ -2110,6 +2158,17 @@ void gen_get_ptr(Item x) { gen_trace("get_ptr<<<", x, nil); } +void gen_load_bool1(Item x, bool val) { + set_item(x, iReg, ctx.type_bool, get_reg_tmp(), val, 0); + gen_trace("load_bool1", x, nil); + emit_opi(MOV, x->r, 0, x->a); +} + +void gen_load_bool2(Item x) { + gen_trace("load_bool2", x, nil); + emit_opi(MOV, x->r, 0, !x->a); +} + u32 gen_branch_cond(Item x, bool sense) { gen_trace_n("branch_cond", sense, x, nil); u32 cc; diff --git a/test/1031-logical-and-or.log b/test/1031-logical-and-or.log @@ -0,0 +1,27 @@ +D 00000200 +D 00000201 +D 00000202 +D 00000103 +D 00000204 +D 00000205 +D 00000106 +D 00000207 +D 00000208 +D 00000109 +D 00000400 +D 00000401 +D 00000402 +D 00000303 +D 00000404 +D 00000405 +D 00000406 +D 00000307 +D 00000408 +D 00000409 +D 0000040a +D 0000040b +D 0000040c +D 0000040d +D 0000040e +D 0000040f +X 00000042 diff --git a/test/1031-logical-and-or.src b/test/1031-logical-and-or.src @@ -0,0 +1,31 @@ + + +func or_test(n i32) { + if (n == 3 || n == 6 || n == 9) { + _hexout_(n | 0x100); + } else { + _hexout_(n | 0x200); + } +} + +func and_test(n i32) { + if ((n & 1 == 1) && (n & 2 == 2) && (n < 8)) { + _hexout_(n | 0x300); + } else { + _hexout_(n | 0x400); + } +} + +func start() i32 { + var n i32 = 0; + while n < 10 { + or_test(n); + n = n + 1; + } + n = 0; + while n < 16 { + and_test(n); + n = n + 1; + } + return 0x42; +}