commit 2fba18d005233ab3a053baf6a8da086a27c40f87
parent ecc6a44d87f87542ed5b3da1fb88fad2e32132b6
Author: citbl <citbl@citbl.org>
Date: Thu, 23 Oct 2025 21:18:09 +1000
if condition handling
Diffstat:
12 files changed, 94 insertions(+), 80 deletions(-)
diff --git a/ex-cond-adv1.ox b/ex-cond-adv1.ox
@@ -0,0 +1,17 @@
+// conditional to be handled
+
+int main() {
+ print("did it work?");
+ string password = "123";
+ if (password == "1234") {
+ print("it worked!");
+ return 0;
+ } else {
+ if(password == "123") {
+ print("the else worked!");
+ return 1;
+ } else {
+ print("booboo");
+ }
+ }
+}
diff --git a/ex-cond-simple1.ox b/ex-cond-simple1.ox
@@ -0,0 +1,8 @@
+void main() {
+ int a = 1;
+ if (a == 1) {
+ print("yes is expected");
+ } else {
+ print("no");
+ }
+}
diff --git a/ex-cond-simple2.ox b/ex-cond-simple2.ox
@@ -0,0 +1,10 @@
+// more conditional test, else case should be taken
+
+void main() {
+ int a = 1;
+ if (a == 2) {
+ print("no");
+ } else {
+ print("yes");
+ }
+}
diff --git a/ex1.ox b/ex1.ox
@@ -1,6 +1,6 @@
// Hello world and comment
-void main(int param1) {
- print("hello world\n");
+void main(int var) {
+ print("hello world");
//print(param1);
}
diff --git a/ex3.ox b/ex3.ox
@@ -1,15 +0,0 @@
-// conditional to be handled
-
-void main() {
- print("did it work?");
- string password = "123";
- if (password == "1234") {
- print("it worked!");
- } else {
- if(password == "123") {
- print("the else worked!");
- } else {
- print("booboo");
- }
- }
-}
diff --git a/ex4.ox b/ex4.ox
@@ -1,7 +0,0 @@
-void main() {
- if (a == true) {
- print("yes is expected");
- } else {
- print("no");
- }
-}
diff --git a/ex5.ox b/ex5.ox
@@ -1,9 +0,0 @@
-// more conditional test, else case should be taken
-
-void main() {
- if (a == false) {
- print("yes");
- } else {
- print("no");
- }
-}
diff --git a/ex8.ox b/ex8.ox
@@ -2,7 +2,7 @@
void main() {
int a = 10;
- if(true == true) {
+ if(1 == 1) {
if(a == 11) {
print("this is wrong");
} else {
diff --git a/makefile b/makefile
@@ -27,6 +27,11 @@ debug:
default:
cc ${STD} -g -Wall -Wextra -Wno-unused-parameter -Wno-unused-function -fsanitize=address,undefined -o ${BIN} ${SRC} ${LIB} # -Wpedantic -Wshadow -Wconversion
+fast:
+ cc ${STD} -O3 -ffast-math -DNDEBUG -march=native -mtune=native -flto -fomit-frame-pointer -fno-plt -fno-semantic-interposition -pipe \
+ -fno-trapping-math -Wl,-O3 ${LDFLAGS} -o ${BIN} ${SRC} ${LIB}
+ strip ${BIN}
+
clean:
rm -rf ${BIN} ${BIN}.* err.log
@@ -36,7 +41,7 @@ release: clean
check: clean
cc ${STD} -g -Wall -Wextra -fsanitize=address -fsanitize=undefined -o ${BIN} ${SRC} ${LIB}
-test: clean default
+test: clean fast
@for f in ex*.ox; do \
./${BIN} --quiet $$f > /dev/null 2>err.log || { echo "FAIL: $$f"; cat err.log; exit 1; }; \
echo $$f; \
diff --git a/src/gen.h b/src/gen.h
@@ -16,7 +16,6 @@ typedef struct {
// gcc_jit_type *type_kind; need type too?
Scope* scope;
const char* src;
- bool block_terminated;
} Gen;
Gen gen_init(Scope*, const char*, Node*, bool);
diff --git a/src/gen/gen.c b/src/gen/gen.c
@@ -299,28 +299,23 @@ add_symbol(Gen* gen, Symbol* sym)
gen->scope->symbols[gen->scope->len++] = sym;
}
-static void
-end_jump_if_needed(Gen* gen, gcc_jit_location* loc, gcc_jit_block* target)
-{
- if (!gen->block_terminated && gen->curr_block) {
- gcc_jit_block_end_with_jump(gen->curr_block, loc, target);
- gen->block_terminated = true;
- }
-}
-
-static void build_block(Gen* gen, Node* body);
+static bool build_block(Gen* gen, Node* body);
static int block_counter = 0;
-static void
+static bool
build_statement(Gen* gen, Node* node)
{
+ gcc_jit_location* loc = loc_from_node(gen, node);
switch (node->type) {
case NODE_BLOCK:
break;
- case NODE_RETURN:
- break; // TODO return from function probably only handled at the end of the gen
+ case NODE_RETURN: {
+ gcc_jit_rvalue* rv = handle_expr(gen, node->data.ret.expr);
+ gcc_jit_block_end_with_return(gen->curr_block, loc, rv);
+ gen->curr_block = NULL; // important
+ return true; // we end the block here
+ }
case NODE_VAR_DECL: {
- gcc_jit_location* loc = loc_from_node(gen, node);
const char* var_name = span_str(gen->src, node->data.var_decl.name, (char[IDENTSZ]) { 0 });
gcc_jit_type* declared_type = ox_type_to_c_type(gen, node->data.var_decl.type);
@@ -348,7 +343,6 @@ build_statement(Gen* gen, Node* node)
break;
}
case NODE_VAR_ASSIGN: {
- gcc_jit_location* loc = loc_from_node(gen, node);
gcc_jit_rvalue* rvalue = handle_expr(gen, node->data.var_assign.rhs);
// find the var_decl (d.lvalue) from the symbols table's symbol.
for (size_t i = 0; i < gen->scope->len; i++) {
@@ -372,8 +366,6 @@ build_statement(Gen* gen, Node* node)
break;
}
case NODE_IF: {
- gcc_jit_location* loc = loc_from_node(gen, node);
-
// build the condition
OpType op = node->data.if_statement.cond->data.binary_expr.op;
@@ -398,7 +390,6 @@ build_statement(Gen* gen, Node* node)
gcc_jit_rvalue* lhs_val = handle_expr(gen, lhs);
gcc_jit_rvalue* rhs_val = handle_expr(gen, rhs);
-
gcc_jit_rvalue* cond = gcc_jit_context_new_comparison(gen->ctx, loc, cmp, lhs_val, rhs_val);
// create the BLOCKS
@@ -411,47 +402,62 @@ build_statement(Gen* gen, Node* node)
snprintf(label_end, 64, "if.end%d", block_counter);
// blocks
- gcc_jit_block* then_block = gcc_jit_function_new_block(gen->curr_func, label_then);
- gcc_jit_block* merge_block = gcc_jit_function_new_block(gen->curr_func, label_else);
- gcc_jit_block* else_block = else_body ? gcc_jit_function_new_block(gen->curr_func, label_else) : NULL;
-
- // rig the jumps
-
- gcc_jit_block_end_with_conditional(gen->curr_block, loc, cond, then_block, else_body ? else_block : merge_block);
+ gcc_jit_block* then_bb = gcc_jit_function_new_block(gen->curr_func, label_then);
+ gcc_jit_block* else_bb = else_body ? gcc_jit_function_new_block(gen->curr_func, label_else) : NULL;
+ gcc_jit_block* merge_bb = NULL;
+
+ if (!else_bb) {
+ // no else: need merge now for the false edge
+ merge_bb = gcc_jit_function_new_block(gen->curr_func, label_end);
+ gcc_jit_block_end_with_conditional(gen->curr_block, loc, cond, then_bb, merge_bb);
+ } else {
+ // with else: branch to then/else; decide on merge later
+ gcc_jit_block_end_with_conditional(gen->curr_block, loc, cond, then_bb, else_bb);
+ }
- // build THEN
+ // THEN
+ gen->curr_block = then_bb;
+ bool then_ended = build_block(gen, then_body);
+ gcc_jit_block* then_open = gen->curr_block; // last open block in THEN (may differ from then_bb)
+
+ // ELSE
+ bool else_ended = false;
+ gcc_jit_block* else_open = NULL;
+ if (else_bb) {
+ gen->curr_block = else_bb;
+ else_ended = build_block(gen, else_body);
+ else_open = gen->curr_block; // last open block in ELSE
+ }
- gen->curr_block = then_block;
- gen->block_terminated = false;
- build_block(gen, then_body);
- end_jump_if_needed(gen, loc, merge_block);
+ // If both branches ended, no merge needed, we notify we have ended as well
+ if (else_bb && then_ended && else_ended) return true;
- // build ELSE block (optional)
- if (else_block != NULL) {
- gen->curr_block = else_block;
- gen->block_terminated = false;
- build_block(gen, else_body);
- end_jump_if_needed(gen, loc, merge_block);
- }
+ // Ensure we have a merge if any branch continues.
+ if (!merge_bb) merge_bb = gcc_jit_function_new_block(gen->curr_func, label_end);
- // continue after if, note that the original block is terminated.
- gen->curr_block = merge_block;
- gen->block_terminated = false;
+ if (!then_ended) gcc_jit_block_end_with_jump(then_open, loc, merge_bb);
+ if (else_bb && !else_ended) gcc_jit_block_end_with_jump(else_open, loc, merge_bb);
- break;
+ gen->curr_block = merge_bb;
+ return false;
}
default:
printf("build_statement unhandled, %s\n", node_type_str(node->type));
break;
}
+ return false;
}
-static void
+// build_block: returns true if block ended with a terminator
+static bool
build_block(Gen* gen, Node* body)
{
for (size_t i = 0; i < body->data.block.len; i++) {
- build_statement(gen, body->data.block.stmts[i]);
+ if (gen->curr_block == NULL) return true;
+ bool ended = build_statement(gen, body->data.block.stmts[i]);
+ if (ended) return true;
}
+ return false;
}
static void
diff --git a/src/parser/parser.c b/src/parser/parser.c
@@ -165,7 +165,7 @@ parse_equality(Parser* par)
Node* rhs = parse_relational(par);
node = make_binary_node(OP_INEQUALITY, node, rhs);
} else {
- perror("unhandled parse_equality token");
+ // do not error out for other things like `=`, `&`, etc. let it pass.
break;
}
}