ox

The Ox programming language, compiler and tools (WIP)
Log | Files | Refs | README | LICENSE

commit 2f61c2b50ac165f96b91096ab1471b6c46effe43
parent 92e1639b07afa8e67e225e020ddb157de0637c83
Author: citbl <citbl@citbl.org>
Date:   Mon, 13 Oct 2025 21:10:06 +1000

handle ret void

Diffstat:
Msrc/gen/gen.c | 145++++++++++++++++++++++++++++++++++++++++++-------------------------------------
1 file changed, 78 insertions(+), 67 deletions(-)

diff --git a/src/gen/gen.c b/src/gen/gen.c @@ -8,27 +8,27 @@ #include <string.h> #include <sys/param.h> -static gcc_jit_type *type_int; -static gcc_jit_type *type_uint; -static gcc_jit_type *type_double; -static gcc_jit_type *type_void; -static gcc_jit_type *type_cstr; +static gcc_jit_type* type_int; +static gcc_jit_type* type_uint; +static gcc_jit_type* type_double; +static gcc_jit_type* type_void; +static gcc_jit_type* type_cstr; #define MAXARGS 16 -static gcc_jit_location * -loc_from_node(Gen *gen, Node *node) +static gcc_jit_location* +loc_from_node(Gen* gen, Node* node) { if (node->filename == NULL) return NULL; return gcc_jit_context_new_location(gen->ctx, node->filename, node->line, node->col); } Gen -gen_init(Scope *scope, const char *src, Node *node, bool quiet) +gen_init(Scope* scope, const char* src, Node* node, bool quiet) { if (scope == NULL || src == NULL) { panic("gen_init: no Scope or AST provided"); } - gcc_jit_context *ctx; + gcc_jit_context* ctx; ctx = gcc_jit_context_acquire(); @@ -37,6 +37,9 @@ gen_init(Scope *scope, const char *src, Node *node, bool quiet) // needs loc* to work // gcc_jit_context_set_bool_option(ctx, GCC_JIT_BOOL_OPTION_DEBUGINFO, 1); // high level + + 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); } // gcc_jit_context_set_bool_option(ctx, GCC_JIT_BOOL_OPTION_DUMP_SUMMARY, 1); @@ -55,13 +58,13 @@ gen_init(Scope *scope, const char *src, Node *node, bool quiet) 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); - gcc_jit_location *loc = gcc_jit_context_new_location(ctx, node->filename, 0, 0); + 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_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_param *pm_printf[] = { gcc_jit_context_new_param(ctx, loc, type_cstr, "fmt") }; - gcc_jit_function *fn_printf = gcc_jit_context_new_function(ctx, + 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, loc, GCC_JIT_FUNCTION_IMPORTED, type_int, @@ -83,16 +86,16 @@ gen_init(Scope *scope, const char *src, Node *node, bool quiet) }; } -static gcc_jit_rvalue * -handle_ident_call(Gen *gen, Node *node) +static gcc_jit_rvalue* +handle_ident_call(Gen* gen, Node* node) { // Look up the symbol in the current scope for (size_t i = 0; i < gen->scope->len; i++) { - Symbol *sym = gen->scope->symbols[i]; - const char *sym_name = span_str(gen->src, sym->name, (char[IDENTSZ]) { 0 }); + Symbol* sym = gen->scope->symbols[i]; + const char* sym_name = span_str(gen->src, sym->name, (char[IDENTSZ]) { 0 }); printf("symbol %s\n", sym_name); - const char *ident_name = span_str(gen->src, node->data.ident.name, (char[IDENTSZ]) { 0 }); + const char* ident_name = span_str(gen->src, node->data.ident.name, (char[IDENTSZ]) { 0 }); printf("ident %s\n", ident_name); printf("comparing: %s vs. %s\n", sym_name, ident_name); @@ -121,33 +124,33 @@ handle_ident_call(Gen *gen, Node *node) return NULL; } -static gcc_jit_rvalue *handle_expr(Gen *, Node *); +static gcc_jit_rvalue* handle_expr(Gen*, Node*); -static gcc_jit_rvalue * -emit_literal_string(Gen *gen, Node *node) +static gcc_jit_rvalue* +emit_literal_string(Gen* gen, Node* node) { size_t len = node->data.string.value.end - node->data.string.value.start; - char *str = calloc(len + 1, sizeof(char)); + char* str = calloc(len + 1, sizeof(char)); if (str == NULL) panic("emit_literal_string: could not alloc"); memcpy(str, gen->src + node->data.string.value.start, len); str[len] = '\0'; return gcc_jit_context_new_string_literal(gen->ctx, str); } -static gcc_jit_rvalue * -emit_literal_int(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); } -static gcc_jit_rvalue * -emit_literal_float(Gen *gen, Node *node) +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); } static void -build_program(Gen *gen, Node *node) +build_program(Gen* gen, Node* node) { size_t cnt = node->data.program.len; for (size_t i = 0; i < cnt; i++) { @@ -155,17 +158,17 @@ build_program(Gen *gen, Node *node) } } -static gcc_jit_rvalue * -lower_builtin_print(Gen *gen, Node *node) +static gcc_jit_rvalue* +lower_builtin_print(Gen* gen, Node* node) { size_t argc = node->data.call_expr.len; // 1-arg, treat as puts(arg) if (argc == 1) { - gcc_jit_rvalue *arg = handle_expr(gen, node->data.call_expr.args[0]); // TODO [0] when many + gcc_jit_rvalue* arg = handle_expr(gen, node->data.call_expr.args[0]); // TODO [0] when many // cast common cases to const char* // if (gcc_jit_rvalue_get_type(arg) != type_cstr) arg = gcc_jit_context_new_cast(gen->ctx, loc_from_node(gen, node), arg, type_cstr); - gcc_jit_rvalue *args[] = { arg }; + gcc_jit_rvalue* args[] = { arg }; return gcc_jit_context_new_call(gen->ctx, loc_from_node(gen, node), gen->puts_fn, 1, args); } @@ -183,12 +186,12 @@ lower_builtin_print(Gen *gen, Node *node) // to a struct. Do we say [[struct]] or do we have some automatic unwrap and display of // struct data... probably, yes. - gcc_jit_rvalue **args = (gcc_jit_rvalue **)calloc(MAXARGS, sizeof(gcc_jit_rvalue *)); + gcc_jit_rvalue** args = (gcc_jit_rvalue**)calloc(MAXARGS, sizeof(gcc_jit_rvalue*)); if (argc > MAXARGS) { softpanic("we do not currently support more than 16 args to a print call"); } for (size_t i = 0; i < argc; i++) { - gcc_jit_rvalue *arg = handle_expr(gen, node->data.call_expr.args[i]); + gcc_jit_rvalue* arg = handle_expr(gen, node->data.call_expr.args[i]); if (i == 0) { if (gcc_jit_rvalue_get_type(arg) != type_cstr) { // note this is probably not going to work as limited cast supported @@ -199,7 +202,7 @@ lower_builtin_print(Gen *gen, Node *node) // // simple widening for common scalar types // - gcc_jit_type *ty = gcc_jit_rvalue_get_type(arg); + 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); } else if (ty == type_double) { @@ -225,11 +228,11 @@ lower_builtin_print(Gen *gen, Node *node) // // TODO see todo below about linked list parameters... // } -static gcc_jit_rvalue * -handle_func_call(Gen *gen, Node *node) +static gcc_jit_rvalue* +handle_func_call(Gen* gen, Node* node) { - Node *fcallee = node->data.call_expr.callee; - const char *func_name = span_str(gen->src, fcallee->data.ident.name, (char[IDENTSZ]) { 0 }); + Node* fcallee = node->data.call_expr.callee; + const char* func_name = span_str(gen->src, fcallee->data.ident.name, (char[IDENTSZ]) { 0 }); if (strcmp(func_name, "print") == 0) return lower_builtin_print(gen, node); softpanic("unhandled func call named: %s", func_name); @@ -248,8 +251,8 @@ handle_func_call(Gen *gen, Node *node) // return NULL; } -static gcc_jit_rvalue * -handle_expr(Gen *gen, Node *node) +static gcc_jit_rvalue* +handle_expr(Gen* gen, Node* node) { switch (node->type) { case NODE_INT_LITERAL: @@ -277,10 +280,10 @@ handle_expr(Gen *gen, Node *node) return NULL; } -static gcc_jit_type * -ox_type_to_c_type(Gen *gen, Node *node) +static gcc_jit_type* +ox_type_to_c_type(Gen* gen, Node* node) { - const char *type_name = span_str(gen->src, node->data.ident.name, (char[IDENTSZ]) { 0 }); + const char* type_name = span_str(gen->src, node->data.ident.name, (char[IDENTSZ]) { 0 }); if (strcmp(type_name, "int") == 0) { return type_int; @@ -299,7 +302,7 @@ ox_type_to_c_type(Gen *gen, Node *node) } static void -build_statement(Gen *gen, Node *node) +build_statement(Gen* gen, Node* node) { switch (node->type) { case NODE_BLOCK: @@ -307,12 +310,12 @@ build_statement(Gen *gen, Node *node) case NODE_RETURN: break; 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); + 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); - gcc_jit_lvalue *var_decl = NULL; - gcc_jit_rvalue *rvalue = handle_expr(gen, node->data.var_decl.init); + gcc_jit_lvalue* var_decl = NULL; + gcc_jit_rvalue* rvalue = handle_expr(gen, node->data.var_decl.init); if (gen->curr_func == NULL && gen->curr_block == NULL) { var_decl = gcc_jit_context_new_global(gen->ctx, loc, GCC_JIT_GLOBAL_INTERNAL, declared_type, strdup(var_name)); @@ -326,7 +329,7 @@ build_statement(Gen *gen, Node *node) printf("adding 1 symbol: %s\n", span_str(gen->src, node->data.var_decl.name, (char[IDENTSZ]) { 0 })); - Symbol *sym = (Symbol *)calloc(1, sizeof(Symbol)); + Symbol* sym = (Symbol*)calloc(1, sizeof(Symbol)); sym->name = node->data.var_decl.name; sym->decl = node; sym->ctype = declared_type; @@ -334,13 +337,13 @@ build_statement(Gen *gen, Node *node) 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; } break; case NODE_EXPR_STATEMENT: { - gcc_jit_rvalue *rv = handle_expr(gen, node->data.expr_statement.expr); + 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); } break; default: @@ -350,7 +353,7 @@ build_statement(Gen *gen, Node *node) } static void -build_block(Gen *gen, Node *body) +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]); @@ -358,38 +361,46 @@ build_block(Gen *gen, Node *body) } static void -build_func_decl(Gen *gen, Node *node) +build_func_decl(Gen* gen, Node* node) { - gcc_jit_function *func = gcc_jit_context_new_function(gen->ctx, - loc_from_node(gen, node), + const char* func_name = span_str(gen->src, node->data.function_decl.name, (char[IDENTSZ]) { 0 }); + + auto ret_type = ox_type_to_c_type(gen, node->data.function_decl.return_type); + auto loc = loc_from_node(gen, node); + + gcc_jit_function* func = gcc_jit_context_new_function(gen->ctx, + loc, GCC_JIT_FUNCTION_EXPORTED, // declared - type_int, // ret - "main", // name + ret_type, // ret + strdup(func_name), // name 0, // num params NULL, // params 0); // is variadic - gcc_jit_block *block = gcc_jit_function_new_block(func, "entry"); + gcc_jit_block* block = gcc_jit_function_new_block(func, "entry"); - gcc_jit_function *prev_func = gen->curr_func; - gcc_jit_block *prev_block = gen->curr_block; + gcc_jit_function* prev_func = gen->curr_func; + gcc_jit_block* prev_block = gen->curr_block; gen->curr_block = block; gen->curr_func = func; build_block(gen, node->data.function_decl.body); - if (gen->curr_block) { - 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_from_node(gen, node), ret_value); - gen->curr_block = NULL; + if (gen->curr_block && ret_type == type_int) { + auto 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 { + gcc_jit_block_end_with_void_return(gen->curr_block, loc); } + gen->curr_block = NULL; + gen->curr_func = prev_func; gen->curr_block = prev_block; } void -gen_next(Gen *gen, Node *node) +gen_next(Gen* gen, Node* node) { // printf("gen_next, %s\n", node_type_str(node->type));