commit 499b2ff90e63d0b9214b4dc23eb32667ab412165
parent 61c13e81caf86e7a92f5bbd3eb7819ec4a565566
Author: citbl <citbl@citbl.org>
Date: Mon, 27 Oct 2025 21:33:04 +1000
janky as for loop initial impl
Diffstat:
3 files changed, 139 insertions(+), 49 deletions(-)
diff --git a/.zed/debug.json b/.zed/debug.json
@@ -11,7 +11,7 @@
"cwd": "$ZED_WORKTREE_ROOT"
},
"program": "$ZED_WORKTREE_ROOT/oxc",
- "args": ["$ZED_WORKTREE_ROOT/ex-subscript-simple.ox"],
+ "args": ["$ZED_WORKTREE_ROOT/ex-for-simple1.ox"],
"request": "launch",
"adapter": "CodeLLDB"
}
diff --git a/ex-for-simple1.ox b/ex-for-simple1.ox
@@ -1,6 +1,6 @@
void main() {
int i = 0;
- for(i = 0; i < 5; i = i + 1) {
+ for(i = 0; i < 5; i++) {
print("bozo!");
}
}
diff --git a/src/gen/gen.c b/src/gen/gen.c
@@ -157,6 +157,123 @@ handle_ident_call(Gen* gen, Node* node)
return gcc_jit_lvalue_as_rvalue(sym->d.lvalue);
}
+static gcc_jit_rvalue* handle_expr(Gen*, Node*);
+
+static inline int
+is_intlike(gcc_jit_context* ctx, gcc_jit_type* t)
+{
+ return t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_INT)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_SHORT)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_SHORT)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_LONG)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_LONG)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_LONG_LONG)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_LONG_LONG)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT64_T)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT32_T)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_CHAR)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_CHAR);
+}
+
+static inline int
+is_floatlike(gcc_jit_context* ctx, gcc_jit_type* t)
+{
+ return t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_FLOAT)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_DOUBLE)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_LONG_DOUBLE);
+}
+
+static inline int
+is_cstr(gcc_jit_context* ctx, gcc_jit_type* t)
+{
+ return t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_CONST_CHAR_PTR);
+}
+
+static gcc_jit_rvalue*
+handle_binary_expr(Gen* gen, Node* node)
+{
+ OpType op = node->data.binary_expr.op;
+ Node* lhs = node->data.binary_expr.lhs;
+ Node* rhs = node->data.binary_expr.rhs;
+
+ gcc_jit_context* ctx = gen->ctx;
+ gcc_jit_location* loc = loc_from_node(gen, node);
+ switch (op) {
+ case OP_LT: {
+ gcc_jit_rvalue* L = handle_expr(gen, lhs);
+ gcc_jit_rvalue* R = handle_expr(gen, rhs);
+ gcc_jit_type* Lt = gcc_jit_rvalue_get_type(L);
+ gcc_jit_type* Rt = gcc_jit_rvalue_get_type(R);
+
+ // floats: cast both to double
+ if (is_floatlike(ctx, Lt) || is_floatlike(ctx, Rt)) {
+ gcc_jit_type* T = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_DOUBLE);
+ L = gcc_jit_context_new_cast(ctx, loc, L, T);
+ R = gcc_jit_context_new_cast(ctx, loc, R, T);
+ return gcc_jit_context_new_comparison(
+ ctx, loc, GCC_JIT_COMPARISON_LT, L, R);
+ }
+
+ // integers: cast both to signed/unsigned long long (cheap, predictable)
+ if (is_intlike(ctx, Lt) && is_intlike(ctx, Rt)) {
+ int any_unsigned
+ = (Lt == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_CHAR))
+ || (Lt
+ == gcc_jit_context_get_type(
+ ctx, GCC_JIT_TYPE_UNSIGNED_SHORT))
+ || (Lt == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_INT))
+ || (Lt == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_LONG))
+ || (Lt
+ == gcc_jit_context_get_type(
+ ctx, GCC_JIT_TYPE_UNSIGNED_LONG_LONG))
+ || (Rt == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_CHAR))
+ || (Rt
+ == gcc_jit_context_get_type(
+ ctx, GCC_JIT_TYPE_UNSIGNED_SHORT))
+ || (Rt == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_INT))
+ || (Rt == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_LONG))
+ || (Rt
+ == gcc_jit_context_get_type(
+ ctx, GCC_JIT_TYPE_UNSIGNED_LONG_LONG));
+
+ gcc_jit_type* T = gcc_jit_context_get_type(ctx,
+ any_unsigned ? GCC_JIT_TYPE_UNSIGNED_LONG_LONG
+ : GCC_JIT_TYPE_LONG_LONG);
+
+ L = gcc_jit_context_new_cast(ctx, loc, L, T);
+ R = gcc_jit_context_new_cast(ctx, loc, R, T);
+ return gcc_jit_context_new_comparison(
+ ctx, loc, GCC_JIT_COMPARISON_LT, L, R);
+ }
+
+ // pointers: either reject or compare addresses (UB in C for unrelated objs).
+ if (
+#ifdef GCC_JIT_HAVE_gcc_jit_type_is_pointer
+ gcc_jit_type_is_pointer(Lt) && gcc_jit_type_is_pointer(Rt)
+#else
+ 0
+#endif
+ ) {
+ gcc_jit_type* T
+ = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
+ L = gcc_jit_context_new_cast(ctx, loc, L, T);
+ R = gcc_jit_context_new_cast(ctx, loc, R, T);
+ return gcc_jit_context_new_comparison(
+ ctx, loc, GCC_JIT_COMPARISON_LT, L, R);
+ }
+
+ // unsupported types (e.g., strings or structs)
+ printf("handle_binary_expr OP_LT: unsupported operand types\n");
+ return NULL;
+ }
+ default:
+ printf("handle_binary_expr unhandled OpType %d (can be ignored in var assignment (for now))\n", op);
+ return NULL;
+ break;
+ }
+}
+
static gcc_jit_rvalue*
handle_unary_expr(Gen* gen, Node* node)
{
@@ -198,8 +315,6 @@ handle_unary_expr(Gen* gen, Node* node)
return NULL;
}
-static gcc_jit_rvalue* handle_expr(Gen*, Node*);
-
static gcc_jit_rvalue*
emit_literal_string(Gen* gen, Node* node)
{
@@ -233,28 +348,7 @@ build_program(Gen* gen, Node* node)
gen_next(gen, node->data.program.decl[i]);
}
}
-static inline int
-is_intlike(gcc_jit_context* ctx, gcc_jit_type* t)
-{
- return t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT)
- || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_INT)
- || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_SHORT)
- || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_SHORT)
- || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_LONG)
- || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_LONG)
- || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_LONG_LONG)
- || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_LONG_LONG)
- || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT64_T)
- || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT32_T)
- || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_CHAR)
- || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_CHAR);
-}
-static inline int
-is_cstr(gcc_jit_context* ctx, gcc_jit_type* t)
-{
- return t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_CONST_CHAR_PTR);
-}
static gcc_jit_rvalue*
lower_builtin_print(Gen* gen, Node* node)
{
@@ -277,11 +371,13 @@ lower_builtin_print(Gen* gen, Node* node)
// print a integer
else if (is_intlike(gen->ctx, t)) {
// cast to int for a clean %d
- gcc_jit_type* t_int = gcc_jit_context_get_type(gen->ctx, GCC_JIT_TYPE_INT64_T);
+ gcc_jit_type* t_int
+ = gcc_jit_context_get_type(gen->ctx, GCC_JIT_TYPE_INT64_T);
gcc_jit_rvalue* fmt = gcc_jit_context_new_string_literal(gen->ctx, "%d\n");
- gcc_jit_rvalue* ival = arg;//(t == t_int)
- //? arg
- //: gcc_jit_context_new_cast(gen->ctx, NULL, arg, t_int);
+ gcc_jit_rvalue* ival = arg; //(t == t_int)
+ //? arg
+ //: gcc_jit_context_new_cast(gen->ctx,
+ //: NULL, arg, t_int);
gcc_jit_rvalue* args[] = { fmt, ival };
return gcc_jit_context_new_call(gen->ctx, loc, gen->printf_fn, 2, args);
}
@@ -300,8 +396,8 @@ lower_builtin_print(Gen* gen, Node* node)
// break;
// default:
- // printf("lower_builtin_print: unhandled type passed %s\n", type_of_args);
- // break;
+ // printf("lower_builtin_print: unhandled type passed %s\n",
+ // type_of_args); break;
// }
}
@@ -420,6 +516,9 @@ handle_expr(Gen* gen, Node* node)
case NODE_UNARY_EXPR: // ++ etc.
return handle_unary_expr(gen, node);
break;
+ case NODE_BINARY_EXPR:
+ return handle_binary_expr(gen, node);
+ break;
// case NODE_IDENT: {
// return NULL; // fixme
@@ -474,14 +573,6 @@ static int block_counter = 0, loop_counter = 0;
static bool
build_for_statement(Gen* gen, Node* node)
{
- /*
- entry → (init) → [head: cond?] ──T──> (body) ──continue──> (step) ──┐
- └──F───────────────────> (end) → next
- ^
- └── back to
- [head]
- */
-
gcc_jit_location* loc = loc_from_node(gen, node);
Node* init = node->data.for_statement.init;
@@ -538,7 +629,7 @@ build_for_statement(Gen* gen, Node* node)
gen->curr_block = step_block;
if (step) { build_statement(gen, step); }
- gcc_jit_block_end_with_jump(step_block, loc, end_block);
+ gcc_jit_block_end_with_jump(step_block, loc, cond_block);
// resume after loop
@@ -549,12 +640,6 @@ build_for_statement(Gen* gen, Node* node)
static bool
build_if_statement(Gen* gen, Node* node)
{
- /*
- pre → [cond?] ──T──> (then) ─────┐
- └──F──> (else) ─────┐ │
- (merge) → next
- */
-
gcc_jit_location* loc = loc_from_node(gen, node);
// build the condition
@@ -732,10 +817,15 @@ build_statement(Gen* gen, Node* node)
break;
}
case NODE_BINARY_EXPR: {
- printf("TODO NODE_BINARY_EXPR\nTODO NODE_BINARY_EXPR\nTODO "
- "NODE_BINARY_EXPR\nTODO\n");
+ printf("TODO NODE_BINARY_EXPR\n \
+ TODO NODE_BINARY_EXPR\nTODO \
+ NODE_BINARY_EXPR\nTODO\n");
+ }
+ case NODE_UNARY_EXPR: {
+ gcc_jit_rvalue* rv = handle_unary_expr(gen, node);
+ if (rv) gcc_jit_block_add_eval(gen->curr_block, loc_from_node(gen, node), rv);
+ break;
}
-
case NODE_EXPR_STATEMENT: {
gcc_jit_rvalue* rv = handle_expr(gen, node->data.expr_statement.expr);
if (rv) gcc_jit_block_add_eval(gen->curr_block, loc_from_node(gen, node), rv);