commit b290a67e08f796d852ed959274848ee53771ea03
parent 8a3f64aad987500d0cc2c91693af668e6801ff07
Author: citbl <citbl@citbl.org>
Date: Sat, 1 Nov 2025 16:53:45 +1000
binops
Diffstat:
5 files changed, 163 insertions(+), 119 deletions(-)
diff --git a/.clang-format b/.clang-format
@@ -19,7 +19,7 @@ AlignConsecutiveMacros: false
SortIncludes: false
IndentCaseLabels: false
-ColumnLimit: 100
+ColumnLimit: 135
PenaltyBreakBeforeFirstCallParameter: 1
AlignAfterOpenBracket: DontAlign
BinPackArguments: false
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-for-simple1.ox"],
+ "args": ["$ZED_WORKTREE_ROOT/ex-binop-simple1.ox"],
"request": "launch",
"adapter": "CodeLLDB"
}
diff --git a/ex-binop-simple1.ox b/ex-binop-simple1.ox
@@ -0,0 +1,7 @@
+void main() {
+ int i = 0;
+ i = i + 1;
+ print(i);
+ i = i + 2;
+ print(i);
+}
diff --git a/ex-for-simple2.ox b/ex-for-simple2.ox
@@ -1,6 +1,6 @@
void main() {
- int i = 0;
- for(i = 0; i < 5; i == i + 1) {
+ for(int i = 0; i < 5; i++) {
+ print(i);
print("bozo!");
}
}
diff --git a/src/gen/gen.c b/src/gen/gen.c
@@ -9,10 +9,13 @@
#include <sys/param.h>
static gcc_jit_type* type_int;
+static gcc_jit_type* type_float;
static gcc_jit_type* type_uint;
static gcc_jit_type* type_double;
+static gcc_jit_type* type_long;
static gcc_jit_type* type_void;
static gcc_jit_type* type_cstr;
+static gcc_jit_type* type_char;
static gcc_jit_type* type_voidp;
#define MAXARGS 16
@@ -55,6 +58,13 @@ current_continue(Gen* gen)
return gen->loop ? gen->loop->continue_target : NULL;
}
+static const char*
+get_english_type(gcc_jit_type* t)
+{
+ gcc_jit_object* obj = gcc_jit_type_as_object(t);
+ const char* st = gcc_jit_object_get_debug_string(obj);
+ return st;
+}
Gen
gen_init(Scope* scope, const char* src, Node* node, bool quiet)
{
@@ -72,9 +82,7 @@ gen_init(Scope* scope, const char* src, Node* node, bool quiet)
gcc_jit_context_set_bool_option(ctx, GCC_JIT_BOOL_OPTION_DEBUGINFO, 1);
- if (quiet == false) {
- gcc_jit_context_set_bool_option(ctx, GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 1);
- }
+ if (quiet == false) { gcc_jit_context_set_bool_option(ctx, GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 1); }
// gcc_jit_context_set_bool_option(ctx,
// GCC_JIT_BOOL_OPTION_DUMP_SUMMARY, 1);
@@ -88,8 +96,11 @@ gen_init(Scope* scope, const char* src, Node* node, bool quiet)
/*0-3 for O3*/ 0);
type_int = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT64_T);
+ type_float = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_BFLOAT16);
type_uint = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UINT64_T);
type_double = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_DOUBLE);
+ type_long = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_LONG_LONG);
+ type_char = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_CHAR);
type_void = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_VOID);
type_cstr = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_CONST_CHAR_PTR);
type_voidp = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_VOID_PTR);
@@ -97,8 +108,7 @@ gen_init(Scope* scope, const char* src, Node* node, bool quiet)
gcc_jit_location* loc = gcc_jit_context_new_location(ctx, node->filename, 0, 0);
gcc_jit_param* pm_puts[] = { gcc_jit_context_new_param(ctx, loc, type_cstr, "s") };
- gcc_jit_function* fn_puts = gcc_jit_context_new_function(
- ctx, loc, GCC_JIT_FUNCTION_IMPORTED, type_int, "puts", 1, pm_puts, 0);
+ gcc_jit_function* fn_puts = gcc_jit_context_new_function(ctx, loc, GCC_JIT_FUNCTION_IMPORTED, type_int, "puts", 1, pm_puts, 0);
gcc_jit_param* pm_printf[] = { gcc_jit_context_new_param(ctx, loc, type_cstr, "fmt") };
gcc_jit_function* fn_printf = gcc_jit_context_new_function(ctx,
@@ -162,16 +172,14 @@ 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)
+ 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_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);
}
@@ -179,8 +187,7 @@ is_intlike(gcc_jit_context* ctx, gcc_jit_type* t)
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)
+ 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);
}
@@ -190,83 +197,110 @@ 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)
+handle_bin_expr(Gen* gen, Node* node, int gcc_jit_op, bool cmp)
{
- 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 (
+ 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);
+ gcc_jit_rvalue* result = NULL;
+
+ // 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);
+ result = cmp ? gcc_jit_context_new_comparison(ctx, loc, gcc_jit_op, L, R)
+ : gcc_jit_context_new_binary_op(ctx, loc, gcc_jit_op, T, 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);
+ result = cmp ? gcc_jit_context_new_comparison(ctx, loc, gcc_jit_op, L, R)
+ : gcc_jit_context_new_binary_op(ctx, loc, gcc_jit_op, T, 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)
+ gcc_jit_type_is_pointer(Lt) && gcc_jit_type_is_pointer(Rt)
#else
- 0
+ 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;
+ ) {
+ 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);
+ result = cmp ? gcc_jit_context_new_comparison(ctx, loc, gcc_jit_op, L, R)
+ : gcc_jit_context_new_binary_op(ctx, loc, gcc_jit_op, T, L, R);
}
+
+ return result;
+}
+
+static gcc_jit_rvalue*
+handle_binary_expr(Gen* gen, Node* node)
+{
+ int gcc_jit_op = -1;
+ OpType op = node->data.binary_expr.op;
+
+ switch (op) {
+ case OP_PLUS:
+ gcc_jit_op = GCC_JIT_BINARY_OP_PLUS;
+ return handle_bin_expr(gen, node, gcc_jit_op, false);
+ break;
+ case OP_MINUS:
+ gcc_jit_op = GCC_JIT_BINARY_OP_MINUS;
+ return handle_bin_expr(gen, node, gcc_jit_op, false);
+ break;
+ case OP_MUL:
+ gcc_jit_op = GCC_JIT_BINARY_OP_MULT;
+ return handle_bin_expr(gen, node, gcc_jit_op, false);
+ break;
+ case OP_DIV:
+ gcc_jit_op = GCC_JIT_BINARY_OP_DIVIDE;
+ return handle_bin_expr(gen, node, gcc_jit_op, false);
+ break;
+ case OP_MOD:
+ gcc_jit_op = GCC_JIT_BINARY_OP_MODULO;
+ return handle_bin_expr(gen, node, gcc_jit_op, false);
+ break;
+ case OP_LT:
+ gcc_jit_op = GCC_JIT_COMPARISON_LT;
+ break;
+ case OP_GT:
+ gcc_jit_op = GCC_JIT_COMPARISON_GT;
+ break;
+ case OP_GT_EQ:
+ gcc_jit_op = GCC_JIT_COMPARISON_GE;
+ break;
+ case OP_LT_EQ:
+ gcc_jit_op = GCC_JIT_COMPARISON_LE;
+ break;
default:
printf("handle_binary_expr unhandled OpType %d (can be ignored in var assignment "
"(for now))\n",
@@ -274,6 +308,14 @@ handle_binary_expr(Gen* gen, Node* node)
return NULL;
break;
}
+
+ if (gcc_jit_op < 0) {
+ // unsupported types (e.g., strings or structs)
+ printf("handle_binary_expr OP_LT: unsupported operand types\n");
+ return NULL;
+ }
+
+ return handle_bin_expr(gen, node, gcc_jit_op, true);
}
static gcc_jit_rvalue*
@@ -289,14 +331,12 @@ handle_unary_expr(Gen* gen, Node* node)
span_str(gen->src, opnd->data.ident.name, (char[IDENTSZ]) { 0 }));
}
- // gcc_jit_lvalue* lv = gcc_jit_rvalue_dereference(, NULL);
gcc_jit_lvalue* lv = sym->d.lvalue;
gcc_jit_rvalue* orig = gcc_jit_lvalue_as_rvalue(sym->d.lvalue);
gcc_jit_type* ty = gcc_jit_rvalue_get_type(orig);
gcc_jit_rvalue* one = gcc_jit_context_one(ctx, ty);
- gcc_jit_rvalue* inc
- = gcc_jit_context_new_binary_op(ctx, NULL, GCC_JIT_BINARY_OP_PLUS, ty, orig, one);
+ gcc_jit_rvalue* inc = gcc_jit_context_new_binary_op(ctx, NULL, GCC_JIT_BINARY_OP_PLUS, ty, orig, one);
switch (node->data.unary_expr.op) {
case OPER_POSTINC: { // i++
gcc_jit_block_add_assignment(bb, NULL, lv, inc);
@@ -331,15 +371,13 @@ emit_literal_string(Gen* gen, Node* node)
static gcc_jit_rvalue*
emit_literal_int(Gen* gen, Node* node)
{
- return gcc_jit_context_new_rvalue_from_int(
- gen->ctx, type_int, (int)node->data.number.value);
+ return gcc_jit_context_new_rvalue_from_int(gen->ctx, type_int, (int)node->data.number.value);
}
static gcc_jit_rvalue*
emit_literal_float(Gen* gen, Node* node)
{
- return gcc_jit_context_new_rvalue_from_double(
- gen->ctx, type_double, node->data.number.value);
+ return gcc_jit_context_new_rvalue_from_double(gen->ctx, type_double, node->data.number.value);
}
static void
@@ -436,8 +474,7 @@ lower_builtin_print(Gen* gen, Node* node)
// note this is probably not going to work as
// limited cast supported and string isn't one
// of them
- arg = gcc_jit_context_new_cast(
- gen->ctx, loc_from_node(gen, node), arg, type_cstr);
+ arg = gcc_jit_context_new_cast(gen->ctx, loc_from_node(gen, node), arg, type_cstr);
}
} else {
//
@@ -445,8 +482,7 @@ lower_builtin_print(Gen* gen, Node* node)
//
gcc_jit_type* ty = gcc_jit_rvalue_get_type(arg);
if (ty == type_int) {
- arg = gcc_jit_context_new_cast(
- gen->ctx, loc_from_node(gen, node), arg, type_cstr);
+ arg = gcc_jit_context_new_cast(gen->ctx, loc_from_node(gen, node), arg, type_cstr);
} else if (ty == type_double) {
// variadics already promote float→double;
// double is
@@ -558,8 +594,7 @@ add_symbol(Gen* gen, Symbol* sym)
{
if (gen->scope->len == gen->scope->cap) {
gen->scope->cap *= 2;
- gen->scope->symbols
- = (Symbol**)realloc(gen->scope->symbols, sizeof(Symbol*) * gen->scope->cap);
+ gen->scope->symbols = (Symbol**)realloc(gen->scope->symbols, sizeof(Symbol*) * gen->scope->cap);
}
gen->scope->symbols[gen->scope->len++] = sym;
@@ -681,8 +716,7 @@ build_if_statement(Gen* gen, Node* node)
// blocks
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* else_bb = else_body ? gcc_jit_function_new_block(gen->curr_func, label_else) : NULL;
gcc_jit_block* merge_bb = NULL;
if (!else_bb) {
@@ -738,13 +772,11 @@ build_var_decl_statement(Gen* gen, Node* node)
if (gen->curr_func == NULL && gen->curr_block == NULL) {
// global var
- var_decl = gcc_jit_context_new_global(
- gen->ctx, loc, GCC_JIT_GLOBAL_INTERNAL, declared_type, strdup(var_name));
+ var_decl = gcc_jit_context_new_global(gen->ctx, loc, GCC_JIT_GLOBAL_INTERNAL, declared_type, strdup(var_name));
if (rvalue) gcc_jit_global_set_initializer_rvalue(var_decl, rvalue);
} else {
// local var
- var_decl = gcc_jit_function_new_local(
- gen->curr_func, loc, declared_type, strdup(var_name));
+ var_decl = gcc_jit_function_new_local(gen->curr_func, loc, declared_type, strdup(var_name));
if (rvalue) gcc_jit_block_add_assignment(gen->curr_block, loc, var_decl, rvalue);
}
@@ -796,32 +828,39 @@ build_statement(Gen* gen, Node* node)
// find the var_decl (d.lvalue) from the symbols table's symbol.
for (size_t i = 0; i < gen->scope->len; i++) {
Symbol* sym = gen->scope->symbols[i];
- if (span_ident_same(sym->name,
- node->data.var_assign.lhs->data.ident.name,
- gen->src)) {
+ if (span_ident_same(sym->name, node->data.var_assign.lhs->data.ident.name, gen->src)) {
// we found the symbol we are assigning to
gcc_jit_lvalue* lvalue = sym->d.lvalue;
// check the type of lvalue matches the rvalue
gcc_jit_type* ltype = sym->ctype;
gcc_jit_type* rtype = gcc_jit_rvalue_get_type(rvalue);
- if (rtype != ltype) {
- panic_at(node,
- "right hand side of assigment "
- "doesn't match the "
- "type of the left hand side");
- }
- if (lvalue)
- gcc_jit_block_add_assignment(
- gen->curr_block, loc, lvalue, rvalue);
+ // if (rtype != ltype) {
+ // panic_at(node,
+ // "right hand side of assigment "
+ // "doesn't match the "
+ // "type of the left hand side: %s, %s",
+ // get_english_type(ltype),
+ // get_english_type(rtype));
+ // }
+ if (lvalue) gcc_jit_block_add_assignment(gen->curr_block, loc, lvalue, rvalue);
}
}
break;
}
case NODE_BINARY_EXPR: {
- printf("TODO NODE_BINARY_EXPR\n \
- TODO NODE_BINARY_EXPR\nTODO \
- NODE_BINARY_EXPR\nTODO\n");
+ Symbol* sym = find_symbol(gen, node->data.binary_expr.lhs->data.ident.name);
+ if (!sym) softpanic("undefined variable: %s\n", span_str(gen->src, node->data.ident.name, (char[IDENTSZ]) { 0 }));
+
+ gcc_jit_lvalue* lv = sym->d.lvalue;
+ gcc_jit_rvalue* rhs = handle_expr(gen, node->data.binary_expr.rhs);
+ gcc_jit_rvalue* lhs = handle_expr(gen, node->data.binary_expr.lhs);
+ gcc_jit_rvalue* temp = gcc_jit_lvalue_as_rvalue(lv);
+ gcc_jit_type* lvtype = gcc_jit_rvalue_get_type(temp);
+ gcc_jit_rvalue* sum
+ = gcc_jit_context_new_binary_op(gen->ctx, loc_from_node(gen, node), GCC_JIT_BINARY_OP_PLUS, lvtype, lhs, rhs);
+
+ gcc_jit_block_add_assignment(gen->curr_block, loc_from_node(gen, node), lv, sum);
}
case NODE_UNARY_EXPR: {
gcc_jit_rvalue* rv = handle_unary_expr(gen, node);
@@ -899,8 +938,7 @@ build_block(Gen* gen, Node* body)
static void
build_func_decl(Gen* gen, Node* node)
{
- const char* func_name
- = span_str(gen->src, node->data.function_decl.name, (char[IDENTSZ]) { 0 });
+ const char* func_name = span_str(gen->src, node->data.function_decl.name, (char[IDENTSZ]) { 0 });
Node* return_type = node->data.function_decl.return_type;
gcc_jit_type* ret_type = ox_type_to_c_type(gen, return_type);
@@ -925,8 +963,7 @@ build_func_decl(Gen* gen, Node* node)
build_block(gen, node->data.function_decl.body);
if (gen->curr_block && ret_type == type_int) { // TODO handle more return types
- gcc_jit_rvalue* ret_value
- = gcc_jit_context_new_rvalue_from_int(gen->ctx, type_int, 0);
+ gcc_jit_rvalue* ret_value = gcc_jit_context_new_rvalue_from_int(gen->ctx, type_int, 0);
gcc_jit_block_end_with_return(gen->curr_block, loc, ret_value);
} else if (gen->curr_block && ret_type == type_void) {
gcc_jit_block_end_with_void_return(gen->curr_block, loc);