gen.c (43481B)
1 #include "../gen.h" 2 #include "../parser.h" 3 #include "../utils.h" 4 #include "../typer.h" 5 6 #include <stdint.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 #include <assert.h> 11 #include <sys/param.h> 12 13 static gcc_jit_type* type_boolean; 14 static gcc_jit_type* type_int; 15 static gcc_jit_type* type_i8; 16 static gcc_jit_type* type_i16; 17 static gcc_jit_type* type_i32; 18 static gcc_jit_type* type_i64; 19 static gcc_jit_type* type_i128; 20 static gcc_jit_type* type_u8; 21 static gcc_jit_type* type_u16; 22 static gcc_jit_type* type_u32; 23 static gcc_jit_type* type_u64; 24 static gcc_jit_type* type_u128; 25 static gcc_jit_type* type_f32; 26 static gcc_jit_type* type_f64; 27 static gcc_jit_type* type_f128; 28 static gcc_jit_type* type_uint; 29 static gcc_jit_type* type_void; 30 static gcc_jit_type* type_cstr; 31 static gcc_jit_type* type_char; 32 static gcc_jit_type* type_voidp; 33 34 static const char* type_func = "function"; 35 static const char* type_var = "variable"; 36 37 #define MAXARGS 16 38 39 static gcc_jit_location* 40 loc_from_node(Gen* gen, Node* node) 41 { 42 if (node->filename == NULL) return NULL; 43 return gcc_jit_context_new_location(gen->ctx, node->filename, node->line, node->col); 44 } 45 46 static void 47 push_loop(Gen* gen, gcc_jit_block* brk, gcc_jit_block* cont) 48 { 49 LoopContext* lctx = (LoopContext*)malloc(sizeof(LoopContext)); 50 if (lctx == NULL) { panic("push_loop: could not alloc"); } 51 lctx->break_target = brk; 52 lctx->continue_target = cont; 53 lctx->prev = gen->loop; 54 gen->loop = lctx; 55 } 56 57 static void 58 pop_loop(Gen* gen) 59 { 60 LoopContext* lctx = gen->loop; 61 gen->loop = lctx->prev; 62 free(lctx); 63 } 64 65 static inline gcc_jit_block* 66 current_break(Gen* gen) 67 { 68 return gen->loop ? gen->loop->break_target : NULL; 69 } 70 71 static inline gcc_jit_block* 72 current_continue(Gen* gen) 73 { 74 return gen->loop ? gen->loop->continue_target : NULL; 75 } 76 77 __attribute__((unused)) static const char* 78 get_english_type(gcc_jit_type* T) 79 { 80 return gcc_jit_object_get_debug_string(gcc_jit_type_as_object(T)); 81 } 82 83 Gen 84 gen_init(Scope* scope, const char* src, Node* node, bool quiet) 85 { 86 if (scope == NULL || src == NULL) { panic("gen_init: no Scope or AST provided"); } 87 88 gcc_jit_context* ctx; 89 90 ctx = gcc_jit_context_acquire(); 91 92 if (!ctx) { panic("could not acquire gcc jit context"); } 93 94 // needs loc* to work 95 // gcc_jit_context_set_bool_option(ctx, GCC_JIT_BOOL_OPTION_DEBUGINFO, 96 // 1); high level 97 98 gcc_jit_context_set_bool_option(ctx, GCC_JIT_BOOL_OPTION_DEBUGINFO, 1); 99 100 if (quiet == false) { gcc_jit_context_set_bool_option(ctx, GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 1); } 101 102 // gcc_jit_context_set_bool_option(ctx, 103 // GCC_JIT_BOOL_OPTION_DUMP_SUMMARY, 1); 104 105 gcc_jit_context_set_str_option(ctx, GCC_JIT_STR_OPTION_PROGNAME, "ox"); 106 // keep FP 107 gcc_jit_context_add_driver_option(ctx, "-fno-omit-frame-pointer"); 108 109 gcc_jit_context_set_int_option(ctx, 110 GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 111 /*0-3 for O3*/ 0); 112 113 type_boolean = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_BOOL); 114 115 type_int = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT64_T); 116 type_i8 = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT8_T); 117 type_i16 = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT16_T); 118 type_i32 = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT32_T); 119 type_i64 = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT64_T); 120 type_i128 = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT128_T); 121 122 type_u8 = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UINT8_T); 123 type_u16 = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UINT16_T); 124 type_u32 = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UINT32_T); 125 type_u64 = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UINT64_T); 126 type_u128 = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UINT128_T); 127 128 type_f32 = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_FLOAT); 129 type_f64 = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_DOUBLE); 130 type_f128 = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_LONG_DOUBLE); 131 132 type_uint = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UINT64_T); 133 type_char = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_CHAR); 134 type_void = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_VOID); 135 type_cstr = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_CONST_CHAR_PTR); 136 type_voidp = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_VOID_PTR); 137 /* gcc_jit_type_dyncast_function_ptr_type; */ 138 139 gcc_jit_location* loc = gcc_jit_context_new_location(ctx, node->filename, 0, 0); 140 141 gcc_jit_param* pm_puts[] = { gcc_jit_context_new_param(ctx, loc, type_cstr, "s") }; 142 gcc_jit_function* fn_puts = gcc_jit_context_new_function(ctx, loc, GCC_JIT_FUNCTION_IMPORTED, type_int, "puts", 1, pm_puts, 0); 143 144 gcc_jit_param* pm_printf[] = { gcc_jit_context_new_param(ctx, loc, type_cstr, "fmt") }; 145 gcc_jit_function* fn_printf = gcc_jit_context_new_function(ctx, 146 loc, 147 GCC_JIT_FUNCTION_IMPORTED, 148 type_int, 149 "printf", 150 1, 151 pm_printf, 152 /*is_variadic=*/1); 153 154 return (Gen) { 155 .ctx = ctx, 156 .scope = scope, 157 .prev_func = NULL, 158 .curr_func = NULL, 159 .prev_block = NULL, 160 .curr_block = NULL, 161 .puts_fn = fn_puts, 162 .printf_fn = fn_printf, 163 .src = src, 164 }; 165 } 166 167 static void 168 push_scope(Gen* gen) 169 { 170 printf("push_scope\n"); 171 Scope* scope = calloc(1, sizeof(Scope)); 172 *scope = (Scope) { 0 }; 173 scope->symbols = (Symbol**)calloc(16, sizeof(Symbol*)); 174 if (scope->symbols == NULL) panic("push_scope: symbols: could not alloc"); 175 scope->cap = 16; 176 scope->len = 0; 177 178 scope->parent = gen->scope; 179 gen->scope = scope; 180 } 181 182 static void 183 pop_scope(Gen* gen) 184 { 185 printf("pop_scope\n"); 186 Scope* s = gen->scope; 187 gen->scope = s->parent; 188 } 189 190 static Symbol* 191 find_symbol(Gen* gen, Scope* scope, Span name) 192 { 193 const char* ident_name = span_str(gen->src, name, (char[IDENTSZ]) { 0 }); 194 // Look up the symbol in the current scope // TODO look up in parent 195 // scope with utility function and recursion 196 for (size_t i = 0; i < scope->len; i++) { 197 Symbol* sym = scope->symbols[i]; 198 const char* sym_name = span_str(gen->src, sym->name, (char[IDENTSZ]) { 0 }); 199 // printf("symbol %s\n", sym_name); 200 // printf("ident %s\n", ident_name); 201 if (strcmp(sym_name, ident_name) == 0) { 202 printf("found symbol %s\n", sym_name); 203 return sym; 204 } 205 } 206 printf("find_symbol: not found locally: %s\n", ident_name); 207 208 if (scope->parent != NULL) { 209 printf("looking up symbol %s in parent\n", ident_name); 210 return find_symbol(gen, scope->parent, name); 211 } 212 213 return NULL; 214 } 215 216 static void 217 add_symbol(Gen* gen, Symbol* sym) 218 { 219 if (gen->scope->len == gen->scope->cap) { 220 gen->scope->cap *= 2; 221 gen->scope->symbols = (Symbol**)realloc(gen->scope->symbols, sizeof(Symbol*) * gen->scope->cap); 222 } 223 224 gen->scope->symbols[gen->scope->len++] = sym; 225 226 printf("add_symbol: we now have %zu symbols: ", gen->scope->len); 227 for (size_t i = 0; i < gen->scope->len; i++) { 228 Symbol* symy = gen->scope->symbols[i]; 229 const char* name = span_str(gen->src, symy->name, (char[IDENTSZ]) { 0 }); 230 printf("%s, ", name); 231 } 232 printf("\n"); 233 } 234 235 static gcc_jit_rvalue* 236 handle_ident_call(Gen* gen, Node* node) 237 { 238 // Look up the symbol in the current scope // TODO look up in parent 239 // scope with utility function and recursion 240 Symbol* sym = find_symbol(gen, gen->scope, node->data.ident.name); 241 242 if (sym == NULL) { 243 panic_at(node, 244 "handle_ident_call: undefined variable: %s\n", 245 span_str(gen->src, node->data.ident.name, (char[IDENTSZ]) { 0 })); 246 } 247 return gcc_jit_lvalue_as_rvalue(sym->d.lvalue); 248 } 249 250 static gcc_jit_rvalue* handle_expr(Gen*, Node*); 251 252 static inline int 253 is_intlike(gcc_jit_context* ctx, gcc_jit_type* t) // TODO support all new types 254 { 255 return t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT) || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_INT) 256 || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_SHORT) 257 || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_SHORT) 258 || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_LONG) 259 || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_LONG) 260 || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_LONG_LONG) 261 || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_LONG_LONG) 262 || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT64_T) || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT32_T) 263 || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_CHAR) 264 || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_CHAR); 265 } 266 267 static inline int 268 is_floatlike(gcc_jit_context* ctx, gcc_jit_type* t) 269 { 270 return t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_FLOAT) || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_DOUBLE) 271 || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_LONG_DOUBLE); 272 } 273 274 static inline int 275 is_cstr(gcc_jit_context* ctx, gcc_jit_type* t) 276 { 277 return t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_CONST_CHAR_PTR); 278 } 279 280 // > < >= <= + - / * % 281 static gcc_jit_rvalue* 282 handle_bin_expr(Gen* gen, Node* node, int gcc_jit_op, bool cmp) 283 { 284 Node* lhs = node->data.binary_expr.lhs; 285 Node* rhs = node->data.binary_expr.rhs; 286 gcc_jit_context* ctx = gen->ctx; 287 gcc_jit_location* loc = loc_from_node(gen, node); 288 289 gcc_jit_rvalue* L = handle_expr(gen, lhs); 290 gcc_jit_rvalue* R = handle_expr(gen, rhs); 291 gcc_jit_type* Lt = gcc_jit_rvalue_get_type(L); 292 gcc_jit_type* Rt = gcc_jit_rvalue_get_type(R); 293 gcc_jit_rvalue* result = NULL; 294 295 // floats: cast both to double 296 if (is_floatlike(ctx, Lt) || is_floatlike(ctx, Rt)) { 297 gcc_jit_type* T = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_DOUBLE); 298 L = gcc_jit_context_new_cast(ctx, loc, L, T); 299 R = gcc_jit_context_new_cast(ctx, loc, R, T); 300 result = cmp ? gcc_jit_context_new_comparison(ctx, loc, gcc_jit_op, L, R) 301 : gcc_jit_context_new_binary_op(ctx, loc, gcc_jit_op, T, L, R); 302 ; 303 } 304 305 // integers: cast both to signed/unsigned long long (cheap, predictable) 306 if (is_intlike(ctx, Lt) && is_intlike(ctx, Rt)) { 307 int any_unsigned = (Lt == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_CHAR)) 308 || (Lt == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_SHORT)) 309 || (Lt == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_INT)) 310 || (Lt == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_LONG)) 311 || (Lt == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_LONG_LONG)) 312 || (Rt == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_CHAR)) 313 || (Rt == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_SHORT)) 314 || (Rt == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_INT)) 315 || (Rt == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_LONG)) 316 || (Rt == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_LONG_LONG)); 317 318 gcc_jit_type* T = gcc_jit_context_get_type(ctx, any_unsigned ? GCC_JIT_TYPE_UINT64_T : GCC_JIT_TYPE_INT64_T); 319 320 L = gcc_jit_context_new_cast(ctx, loc, L, T); 321 R = gcc_jit_context_new_cast(ctx, loc, R, T); 322 result = cmp ? gcc_jit_context_new_comparison(ctx, loc, gcc_jit_op, L, R) 323 : gcc_jit_context_new_binary_op(ctx, loc, gcc_jit_op, T, L, R); 324 } 325 326 // pointers: either reject or compare addresses (UB in C for unrelated objs). 327 if ( 328 #ifdef GCC_JIT_HAVE_gcc_jit_type_is_pointer 329 gcc_jit_type_is_pointer(Lt) && gcc_jit_type_is_pointer(Rt) 330 #else 331 0 332 #endif 333 ) { 334 gcc_jit_type* T = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_LONG_LONG); 335 L = gcc_jit_context_new_cast(ctx, loc, L, T); 336 R = gcc_jit_context_new_cast(ctx, loc, R, T); 337 result = cmp ? gcc_jit_context_new_comparison(ctx, loc, gcc_jit_op, L, R) 338 : gcc_jit_context_new_binary_op(ctx, loc, gcc_jit_op, T, L, R); 339 } 340 341 return result; 342 } 343 344 static gcc_jit_rvalue* 345 handle_binary_expr(Gen* gen, Node* node) 346 { 347 int gcc_jit_op = -1; 348 OpType op = node->data.binary_expr.op; 349 350 switch (op) { 351 case OP_PLUS: 352 gcc_jit_op = GCC_JIT_BINARY_OP_PLUS; 353 return handle_bin_expr(gen, node, gcc_jit_op, false); 354 break; 355 case OP_MINUS: 356 gcc_jit_op = GCC_JIT_BINARY_OP_MINUS; 357 return handle_bin_expr(gen, node, gcc_jit_op, false); 358 break; 359 case OP_MUL: 360 gcc_jit_op = GCC_JIT_BINARY_OP_MULT; 361 return handle_bin_expr(gen, node, gcc_jit_op, false); 362 break; 363 case OP_DIV: 364 gcc_jit_op = GCC_JIT_BINARY_OP_DIVIDE; 365 return handle_bin_expr(gen, node, gcc_jit_op, false); 366 break; 367 case OP_MOD: 368 gcc_jit_op = GCC_JIT_BINARY_OP_MODULO; 369 return handle_bin_expr(gen, node, gcc_jit_op, false); 370 break; 371 case OP_LT: 372 gcc_jit_op = GCC_JIT_COMPARISON_LT; 373 break; 374 case OP_GT: 375 gcc_jit_op = GCC_JIT_COMPARISON_GT; 376 break; 377 case OP_GT_EQ: 378 gcc_jit_op = GCC_JIT_COMPARISON_GE; 379 break; 380 case OP_LT_EQ: 381 gcc_jit_op = GCC_JIT_COMPARISON_LE; 382 break; 383 default: 384 printf("handle_binary_expr unhandled OpType %d (can be ignored in var assignment " 385 "(for now))\n", 386 op); 387 return NULL; 388 break; 389 } 390 391 if (gcc_jit_op < 0) { 392 // unsupported types (e.g., strings or structs) 393 printf("handle_binary_expr OP_LT: unsupported operand types\n"); 394 return NULL; 395 } 396 397 return handle_bin_expr(gen, node, gcc_jit_op, true); 398 } 399 400 static gcc_jit_rvalue* 401 handle_unary_expr(Gen* gen, Node* node) 402 { 403 gcc_jit_context* ctx = gen->ctx; 404 gcc_jit_block* bb = gen->curr_block; 405 406 Node* opnd = node->data.unary_expr.operand; 407 Symbol* sym = find_symbol(gen, gen->scope, opnd->data.ident.name); 408 if (sym == NULL) { 409 panic_at(node, 410 "handle_unary_expr: undefined variable: %s\n", 411 span_str(gen->src, opnd->data.ident.name, (char[IDENTSZ]) { 0 })); 412 } 413 414 gcc_jit_lvalue* lv = sym->d.lvalue; 415 if (lv == NULL) { 416 printf("handle_unary_expr: no lvalue\n"); 417 return NULL; 418 } 419 gcc_jit_rvalue* orig = gcc_jit_lvalue_as_rvalue(lv); 420 gcc_jit_type* ty = gcc_jit_rvalue_get_type(orig); 421 gcc_jit_rvalue* one = gcc_jit_context_one(ctx, ty); 422 423 gcc_jit_rvalue* inc = gcc_jit_context_new_binary_op(ctx, NULL, GCC_JIT_BINARY_OP_PLUS, ty, orig, one); 424 switch (node->data.unary_expr.op) { 425 case OPER_POSTINC: { // i++ 426 427 if (!sym->is_variadic) { 428 panic_at(node, 429 "OPER_POSTINC: cannot change non variadic variable %s\n", 430 span_str(gen->src, opnd->data.ident_type.name, (char[IDENTSZ]) { 0 })); 431 } else if (sym->is_comp_time) { 432 panic_at(node, 433 "OPER_POSTINC: cannot change comp time constant %s\n", 434 span_str(gen->src, opnd->data.ident_type.name, (char[IDENTSZ]) { 0 })); 435 } 436 gcc_jit_block_add_assignment(bb, NULL, lv, inc); 437 return orig; // return value before incr as ++ is postfix 438 439 break; 440 } 441 default: 442 printf("handle_unary_expr, unhandled op %d\n", node->data.unary_expr.op); 443 return NULL; 444 break; 445 } 446 return NULL; 447 } 448 449 static gcc_jit_rvalue* 450 emit_literal_bool(Gen* gen, Node* node) 451 { 452 int v = node->data.boolean.value ? 1 : 0; 453 return gcc_jit_context_new_rvalue_from_int(gen->ctx, type_boolean, v); 454 } 455 456 static gcc_jit_rvalue* 457 emit_literal_string(Gen* gen, Node* node) 458 { 459 size_t len = node->data.string.value.end - node->data.string.value.start; 460 char* str = calloc(len + 1, sizeof(char)); 461 if (str == NULL) panic_at(node, "emit_literal_string: could not alloc"); 462 memcpy(str, gen->src + node->data.string.value.start, len); 463 str[len] = '\0'; 464 return gcc_jit_context_new_string_literal(gen->ctx, str); 465 } 466 467 static gcc_jit_rvalue* 468 emit_literal_int(Gen* gen, Node* node) 469 { 470 return gcc_jit_context_new_rvalue_from_int(gen->ctx, type_int, (int)node->data.number.value); 471 } 472 473 static gcc_jit_rvalue* 474 emit_literal_float(Gen* gen, Node* node) 475 { 476 return gcc_jit_context_new_rvalue_from_double(gen->ctx, type_f32, node->data.number.value); 477 } 478 479 static void 480 build_program(Gen* gen, Node* node) 481 { 482 size_t cnt = node->data.program.len; 483 for (size_t i = 0; i < cnt; i++) { 484 gen_next(gen, node->data.program.decl[i]); 485 } 486 } 487 488 static gcc_jit_rvalue* 489 lower_builtin_print(Gen* gen, Node* node) 490 { 491 printf("lower_builtin_print\n"); 492 493 size_t argc = node->data.call_expr.len; 494 495 // for (size_t i = 0; i < argc; i++) { 496 // Node* arg = node->data.call_expr.args[i]; 497 // } 498 499 // 1-arg, treat as puts(arg) 500 if (argc == 1) { 501 gcc_jit_rvalue* arg = handle_expr(gen, node->data.call_expr.args[0]); 502 gcc_jit_type* t = gcc_jit_rvalue_get_type(arg); 503 gcc_jit_location* loc = loc_from_node(gen, node->data.call_expr.args[0]); 504 // print a string 505 if (is_cstr(gen->ctx, t)) { 506 gcc_jit_rvalue* args[] = { arg }; 507 return gcc_jit_context_new_call(gen->ctx, loc, gen->puts_fn, 1, args); 508 } 509 // print an integer or bool 510 else if (is_intlike(gen->ctx, t) || t == type_boolean) { 511 // cast to int for a clean %d 512 // gcc_jit_type* t_int 513 // = gcc_jit_context_get_type(gen->ctx, GCC_JIT_TYPE_INT64_T); 514 gcc_jit_rvalue* fmt = gcc_jit_context_new_string_literal(gen->ctx, "%d\n"); 515 gcc_jit_rvalue* ival = arg; 516 gcc_jit_rvalue* args[] = { fmt, ival }; 517 return gcc_jit_context_new_call(gen->ctx, loc, gen->printf_fn, 2, args); 518 } 519 // cast common cases to const char* 520 // if (gcc_jit_rvalue_get_type(arg) != type_cstr) arg = 521 // gcc_jit_context_new_cast(gen->ctx, loc_from_node(gen, node), 522 // arg, type_cstr); 523 524 // gcc_jit_rvalue* args[] = { arg }; 525 // return gcc_jit_context_new_call( 526 // gen->ctx, loc_from_node(gen, node), gen->puts_fn, 1, args); 527 528 // gcc_jit_type* type_of_args = gcc_jit_rvalue_get_type(arg); 529 // switch (type_of_args) { 530 // case GCC_JIT_TYPE_CONST_CHAR_PTR: 531 532 // break; 533 // default: 534 // printf("lower_builtin_print: unhandled type passed %s\n", 535 // type_of_args); break; 536 // } 537 } 538 539 return NULL; 540 541 // softpanic("we don't currently handle formatted strings to print"); 542 543 // n>=1, treat as printf(fmt, ...) // Part of TODO about args as list 544 // and not 545 // 546 // through each args, form the ("formatted %s string %d etc.", str, 547 // intv) for clib's printf 548 549 // TODO we're talking about formatting here, which we plan on doing as a 550 // string interpolation, something along the lines of {{variable}} 551 // without defining its type would involve lookup split of the string 552 // and then formatting 553 554 // we need to discuss and decide what we'd do when the user inevitably 555 // would print out a ref to a struct. Do we say [[struct]] or do we have 556 // some automatic unwrap and display of struct data... probably, yes. 557 558 gcc_jit_rvalue** args = (gcc_jit_rvalue**)calloc(MAXARGS, sizeof(gcc_jit_rvalue*)); 559 560 if (argc > MAXARGS) { 561 panic_at(node, 562 "we do not currently support more than 16 args to a " 563 "print call"); 564 } 565 566 for (size_t i = 0; i < argc; i++) { 567 gcc_jit_rvalue* arg = handle_expr(gen, node->data.call_expr.args[i]); 568 if (i == 0) { 569 if (gcc_jit_rvalue_get_type(arg) != type_cstr) { 570 // note this is probably not going to work as 571 // limited cast supported and string isn't one 572 // of them 573 arg = gcc_jit_context_new_cast(gen->ctx, loc_from_node(gen, node), arg, type_cstr); 574 } 575 } else { 576 // 577 // simple widening for common scalar types 578 // 579 gcc_jit_type* ty = gcc_jit_rvalue_get_type(arg); 580 if (ty == type_int) { 581 arg = gcc_jit_context_new_cast(gen->ctx, loc_from_node(gen, node), arg, type_cstr); 582 } else if (ty == type_f32) { // TODO print() for other types 583 // variadics already promote float→double; 584 // double is 585 } else if (ty == type_cstr) { 586 // leave as const char* 587 } else if (ty == type_boolean) { 588 arg = gcc_jit_context_new_cast(gen->ctx, loc_from_node(gen, node), arg, type_cstr); 589 } else { 590 // fallback: pass pointer as void* 591 arg = gcc_jit_context_new_cast(gen->ctx, 592 loc_from_node(gen, node), 593 arg, 594 gcc_jit_context_get_type(gen->ctx, GCC_JIT_TYPE_VOID_PTR)); 595 } 596 } 597 // TODO auto grow 598 args[i] = arg; 599 } 600 return gcc_jit_context_new_call(gen->ctx, NULL, gen->printf_fn, argc, args); 601 return NULL; 602 } 603 604 static gcc_jit_function* 605 lookup_function(Gen* gen, Scope* scope, const char* func_name) 606 { 607 for (size_t i = 0; i < scope->len; i++) { 608 Symbol* sym = scope->symbols[i]; 609 610 if (sym->ctype == type_voidp) { 611 const char* name = span_str(gen->src, sym->name, (char[IDENTSZ]) { 0 }); 612 if (strcmp(name, func_name) == 0) { 613 return sym->d.funcvalue; // 614 } 615 } 616 } 617 618 printf("lookup_function: not found locally: %s\n", func_name); 619 620 if (scope->parent != NULL) { 621 printf("looking up function %s in parent\n", func_name); 622 return lookup_function(gen, scope->parent, func_name); 623 } 624 625 return NULL; 626 } 627 628 static gcc_jit_rvalue* 629 handle_func_call(Gen* gen, Node* node) 630 { 631 Node* fcallee = node->data.call_expr.callee; 632 const char* func_name = span_str(gen->src, fcallee->data.ident.name, (char[IDENTSZ]) { 0 }); 633 634 // short circuit to print 635 if (strcmp(func_name, "print") == 0) return lower_builtin_print(gen, node); 636 637 gcc_jit_function* callee = lookup_function(gen, gen->scope, func_name); 638 gcc_jit_location* loc = loc_from_node(gen, node); 639 640 // args handling 641 size_t argc = node->data.call_expr.len; 642 643 // alloc args 644 gcc_jit_rvalue** args = NULL; 645 646 if (argc > 0) { 647 args = calloc(argc, sizeof *args); // or alloca, or a fixed upper bound 648 for (size_t i = 0; i < argc; ++i) { 649 args[i] = handle_expr(gen, node->data.call_expr.args[i]); 650 } 651 } 652 653 for (size_t i = 0; i < argc; i++) { 654 args[i] = handle_expr(gen, node->data.call_expr.args[i]); 655 } 656 657 /* 658 When generating the identifier expression message in the AST: 659 Lookup env["message"] -> you get a gcc_jit_param* or gcc_jit_lvalue*. 660 Use gcc_jit_param_as_rvalue / gcc_jit_lvalue_as_rvalue. 661 662 gcc_jit_rvalue *msg = gcc_jit_param_as_rvalue(callee_param); 663 664 gcc_jit_rvalue *args[1] = { msg }; 665 gcc_jit_block_add_eval( 666 b, loc, 667 gcc_jit_context_new_call(ctx, loc, print_fn, 1, args)); 668 */ 669 670 // gcc_jit_rvalue *msg = gcc_jit_param_as_rvalue(callee_param); 671 // gcc_jit_rvalue *args[1] = { msg }; 672 assert(callee != NULL && "callee not found"); 673 return gcc_jit_context_new_call(gen->ctx, loc, callee, argc, args); 674 675 // TODO consider 676 /* 677 // calling bob() directly 678 void emit_direct_call(gcc_jit_context *ctxt, SymbolId bob, gcc_jit_function *caller) { 679 GccObj *cal = ensure_func(ctxt, bob); 680 gcc_jit_block *b = gcc_jit_function_new_block(caller, "call_bob"); 681 gcc_jit_rvalue *args[] = {}; 682 gcc_jit_block_add_eval(b, NULL, gcc_jit_context_new_call(ctxt, cal->func, 0, args)); 683 gcc_jit_block_end_with_void_return(b, NULL); 684 } 685 */ 686 687 // return gcc_jit_context_new_call(gen->ctx, NULL, callee, 0, NULL); 688 689 // TODO handle return values 690 // almost unrelated could be useful to deal with return values: 691 // gcc_jit_rvalue* rv = handle_func_call(gen, node); 692 // if (rv) { gcc_jit_block_add_eval(gen->curr_block, loc_from_node(gen, node), rv); } 693 // return false; 694 return NULL; 695 } 696 697 static gcc_jit_rvalue* 698 handle_expr(Gen* gen, Node* node) 699 { 700 switch (node->type) { 701 case NODE_INT_LITERAL: 702 return emit_literal_int(gen, node); 703 break; 704 case NODE_FLOAT_LITERAL: 705 return emit_literal_float(gen, node); 706 break; 707 case NODE_STRING_LITERAL: 708 return emit_literal_string(gen, node); 709 break; 710 case NODE_BOOL_LITERAL: 711 return emit_literal_bool(gen, node); 712 case NODE_CALL_EXPR: 713 return handle_func_call(gen, node); 714 break; 715 case NODE_IDENT: 716 return handle_ident_call(gen, node); 717 break; 718 case NODE_UNARY_EXPR: // ++ etc. 719 return handle_unary_expr(gen, node); 720 break; 721 case NODE_BINARY_EXPR: 722 return handle_binary_expr(gen, node); 723 break; 724 725 // case NODE_IDENT: { 726 // return NULL; // fixme 727 // break; 728 // } 729 default: 730 printf("handle_expr unhandled, %s\n", node_type_str(node->type)); 731 } 732 return NULL; 733 } 734 735 static gcc_jit_type* 736 ox_type_to_c_type(Gen* gen, Node* node) 737 { 738 if (node == NULL) return type_void; 739 740 const char* type_name = span_str(gen->src, node->data.ident.name, (char[IDENTSZ]) { 0 }); 741 742 if (strcmp(type_name, "int") == 0) { 743 return type_int; 744 745 } else if (strcmp(type_name, "i8") == 0) { 746 return type_i8; 747 } else if (strcmp(type_name, "i16") == 0) { 748 return type_i16; 749 } else if (strcmp(type_name, "i32") == 0) { 750 return type_i32; 751 } else if (strcmp(type_name, "i64") == 0) { 752 return type_i64; 753 } else if (strcmp(type_name, "i128") == 0) { 754 return type_i128; 755 756 } else if (strcmp(type_name, "u8") == 0) { 757 return type_u8; 758 } else if (strcmp(type_name, "u16") == 0) { 759 return type_u16; 760 } else if (strcmp(type_name, "u32") == 0) { 761 return type_u32; 762 } else if (strcmp(type_name, "u64") == 0) { 763 return type_u64; 764 } else if (strcmp(type_name, "u128") == 0) { 765 return type_u128; 766 767 } else if (strcmp(type_name, "f32") == 0) { 768 return type_f32; 769 } else if (strcmp(type_name, "f64") == 0) { 770 return type_f64; 771 } else if (strcmp(type_name, "f128") == 0) { 772 return type_f128; 773 774 } else if (strcmp(type_name, "str") == 0) { 775 return type_cstr; 776 } else if (strcmp(type_name, "float") == 0) { 777 return type_f32; 778 } else if (strcmp(type_name, "double") == 0) { 779 return type_f64; 780 } else if (strcmp(type_name, "longdouble") == 0) { 781 return type_f128; 782 } else if (strcmp(type_name, "uint") == 0) { 783 return type_uint; 784 } else if (strcmp(type_name, "void") == 0) { 785 return type_void; 786 } else { 787 panic_at(node, "unhandled type in gen %s", type_name); 788 } 789 return NULL; 790 } 791 792 static void 793 print_symbols_here(Gen* gen) 794 { 795 for (size_t i = 0; i < gen->scope->len; i++) { 796 Symbol* sym = gen->scope->symbols[i]; 797 const char* name = span_str(gen->src, sym->name, (char[IDENTSZ]) { 0 }); 798 printf("[%zu/%zu] symbol: %s (%s)\n", i + 1, gen->scope->len, name, sym->english_type); 799 } 800 } 801 802 static bool build_block(Gen*, Node*); 803 static bool build_statement(Gen*, Node*); 804 805 static gcc_jit_rvalue* build_bool_value(Gen*, Node*); 806 807 static int block_counter = 0, loop_counter = 0, while_counter = 0; 808 809 static bool 810 build_while_statement(Gen* gen, Node* node) 811 { 812 gcc_jit_location* loc = loc_from_node(gen, node); 813 814 Node* cond = node->data.while_statement.cond; 815 Node* body = node->data.while_statement.body; 816 817 while_counter++; 818 char label_cond[64], label_body[64], label_end[64]; 819 snprintf(label_cond, sizeof label_cond, "while.cond%d", while_counter); 820 snprintf(label_body, sizeof label_body, "while.body%d", while_counter); 821 snprintf(label_end, sizeof label_end, "while.end%d", while_counter); 822 823 gcc_jit_block* cond_block = gcc_jit_function_new_block(gen->curr_func, label_cond); 824 gcc_jit_block* body_block = gcc_jit_function_new_block(gen->curr_func, label_body); 825 gcc_jit_block* end_block = gcc_jit_function_new_block(gen->curr_func, label_end); 826 827 /* jump from current block into the loop */ 828 gcc_jit_block_end_with_jump(gen->curr_block, loc, cond_block); 829 830 gen->curr_block = cond_block; 831 gcc_jit_rvalue* cnd = NULL; 832 833 if (cond != NULL) { 834 cnd = build_bool_value(gen, cond); 835 gcc_jit_block_end_with_conditional(cond_block, loc, cnd, body_block, end_block); 836 } else { 837 /* while (1) */ 838 gcc_jit_block_end_with_jump(cond_block, loc, body_block); 839 } 840 841 gcc_jit_block* continue_target = cond != NULL ? cond_block : body_block; 842 push_loop(gen, /*break to*/ end_block, /*continue to*/ continue_target); 843 844 gen->curr_block = body_block; 845 bool body_ended = build_block(gen, body); 846 if (!body_ended) { gcc_jit_block_end_with_jump(gen->curr_block, loc, continue_target); } 847 848 pop_loop(gen); 849 850 /* resume after loop */ 851 gen->curr_block = end_block; 852 return false; 853 } 854 855 static bool 856 build_for_statement(Gen* gen, Node* node) 857 { 858 gcc_jit_location* loc = loc_from_node(gen, node); 859 860 Node* init = node->data.for_statement.init; 861 Node* cond = node->data.for_statement.cond; 862 Node* step = node->data.for_statement.increment; 863 Node* body = node->data.for_statement.body; 864 865 loop_counter++; 866 867 char label_cond[64], label_body[64], label_step[64], label_end[64]; 868 snprintf(label_cond, 64, "for.cond%d", loop_counter); 869 snprintf(label_body, 64, "for.body%d", loop_counter); 870 snprintf(label_step, 64, "for.step%d", loop_counter); 871 snprintf(label_end, 64, "for.end%d", loop_counter); 872 873 gcc_jit_block* cond_block = gcc_jit_function_new_block(gen->curr_func, label_cond); 874 gcc_jit_block* body_block = gcc_jit_function_new_block(gen->curr_func, label_body); 875 gcc_jit_block* step_block = gcc_jit_function_new_block(gen->curr_func, label_step); 876 gcc_jit_block* end_block = gcc_jit_function_new_block(gen->curr_func, label_end); 877 878 // gcc_jit_block* saved_break = gen->loop->break_target; 879 // gcc_jit_block* saved_cont = gen->loop->continue_target; 880 // gen->loop->break_target = end_block; 881 // gen->loop->continue_target = step_block; 882 883 // header, e.g. for(int = 0 <- 884 if (init) { build_statement(gen, init); } 885 886 // jump to cond e.g. ; i < 5 <- 887 gcc_jit_block_end_with_jump(gen->curr_block, loc, cond_block); 888 889 // cond: evaluate 890 gen->curr_block = cond_block; 891 gcc_jit_rvalue* cnd = NULL; 892 893 if (cond != NULL) { 894 cnd = build_bool_value(gen, cond); 895 gcc_jit_block_end_with_conditional(cond_block, loc, cnd, body_block, end_block); 896 } else { 897 gcc_jit_block_end_with_jump(cond_block, loc, body_block); // presume for(;;) 898 } 899 900 push_loop(gen, /*break to*/ end_block, /*continue to*/ step_block); 901 902 // build for body 903 904 gen->curr_block = body_block; 905 bool for_body_ended = build_block(gen, body); 906 if (!for_body_ended) { gcc_jit_block_end_with_jump(gen->curr_block, loc, step_block); } 907 908 pop_loop(gen); 909 910 // step incr etc. 911 912 gen->curr_block = step_block; 913 if (step) { build_statement(gen, step); } 914 gcc_jit_block_end_with_jump(step_block, loc, cond != NULL ? cond_block : body_block); 915 916 // resume after loop 917 918 gen->curr_block = end_block; 919 return false; 920 } 921 922 static bool 923 build_if_statement(Gen* gen, Node* node) 924 { 925 gcc_jit_location* loc = loc_from_node(gen, node); 926 // build the condition 927 928 OpType op = node->data.if_statement.cond->data.binary_expr.op; 929 Node* lhs = node->data.if_statement.cond->data.binary_expr.lhs; 930 Node* rhs = node->data.if_statement.cond->data.binary_expr.rhs; 931 932 Node* then_body = node->data.if_statement.then_body; 933 Node* else_body = node->data.if_statement.else_body; 934 935 enum gcc_jit_comparison cmp; 936 switch (op) { 937 case OP_EQUALITY: 938 cmp = GCC_JIT_COMPARISON_EQ; 939 break; 940 case OP_INEQUALITY: 941 cmp = GCC_JIT_COMPARISON_NE; 942 break; 943 case OP_GT: 944 cmp = GCC_JIT_COMPARISON_GT; 945 break; 946 case OP_GT_EQ: 947 cmp = GCC_JIT_COMPARISON_GE; 948 break; 949 case OP_LT_EQ: 950 cmp = GCC_JIT_COMPARISON_LE; 951 break; 952 case OP_LT: 953 cmp = GCC_JIT_COMPARISON_LT; 954 break; 955 default: 956 printf("/!\\ build_statement NODE_IF unhandled, %d\n", op); 957 cmp = GCC_JIT_COMPARISON_NE; 958 } 959 960 gcc_jit_rvalue* lhs_val = handle_expr(gen, lhs); 961 gcc_jit_rvalue* rhs_val = handle_expr(gen, rhs); 962 963 gcc_jit_rvalue* cond = gcc_jit_context_new_comparison(gen->ctx, loc, cmp, lhs_val, rhs_val); 964 965 // create the BLOCKS 966 967 // labels 968 block_counter++; 969 char label_then[64], label_else[64], label_end[64]; 970 snprintf(label_then, 64, "if.then%d", block_counter); 971 snprintf(label_else, 64, "if.else%d", block_counter); 972 snprintf(label_end, 64, "if.end%d", block_counter); 973 974 // blocks 975 gcc_jit_block* then_bb = gcc_jit_function_new_block(gen->curr_func, label_then); 976 gcc_jit_block* else_bb = else_body ? gcc_jit_function_new_block(gen->curr_func, label_else) : NULL; 977 gcc_jit_block* merge_bb = NULL; 978 979 if (!else_bb) { 980 // no else: need merge now for the false edge 981 merge_bb = gcc_jit_function_new_block(gen->curr_func, label_end); 982 gcc_jit_block_end_with_conditional(gen->curr_block, loc, cond, then_bb, merge_bb); 983 } else { 984 // with else: branch to then/else; decide on merge later 985 gcc_jit_block_end_with_conditional(gen->curr_block, loc, cond, then_bb, else_bb); 986 } 987 988 // THEN 989 gen->curr_block = then_bb; 990 bool then_ended = build_block(gen, then_body); 991 gcc_jit_block* then_open = gen->curr_block; // last open block in THEN 992 // (may differ from then_bb) 993 994 // ELSE 995 bool else_ended = false; 996 gcc_jit_block* else_open = NULL; 997 if (else_bb) { 998 gen->curr_block = else_bb; 999 else_ended = build_block(gen, else_body); 1000 else_open = gen->curr_block; // last open block in ELSE 1001 } 1002 1003 // If both branches ended, no merge needed, we notify we have ended as 1004 // well 1005 if (else_bb && then_ended && else_ended) return true; 1006 1007 // Ensure we have a merge if any branch continues. 1008 if (!merge_bb) merge_bb = gcc_jit_function_new_block(gen->curr_func, label_end); 1009 1010 if (!then_ended) gcc_jit_block_end_with_jump(then_open, loc, merge_bb); 1011 if (else_bb && !else_ended) gcc_jit_block_end_with_jump(else_open, loc, merge_bb); 1012 1013 gen->curr_block = merge_bb; 1014 return false; 1015 } 1016 1017 static bool 1018 build_var_decl_statement(Gen* gen, Node* node) 1019 { 1020 gcc_jit_location* loc = loc_from_node(gen, node); 1021 const char* var_name = span_str(gen->src, node->data.var_decl.name, (char[IDENTSZ]) { 0 }); 1022 gcc_jit_type* declared_type = ox_type_to_c_type(gen, node->data.var_decl.type); 1023 1024 gcc_jit_lvalue* var_decl = NULL; 1025 1026 gcc_jit_rvalue* rvalue = NULL; 1027 Node* init = node->data.var_decl.init; 1028 if (init != NULL) { rvalue = handle_expr(gen, init); } 1029 1030 if (gen->curr_func == NULL && gen->curr_block == NULL) { 1031 // global var 1032 var_decl = gcc_jit_context_new_global(gen->ctx, loc, GCC_JIT_GLOBAL_INTERNAL, declared_type, strdup(var_name)); 1033 if (rvalue) gcc_jit_global_set_initializer_rvalue(var_decl, rvalue); 1034 } else { 1035 // local var 1036 var_decl = gcc_jit_function_new_local(gen->curr_func, loc, declared_type, strdup(var_name)); 1037 if (rvalue) gcc_jit_block_add_assignment(gen->curr_block, loc, var_decl, rvalue); 1038 } 1039 1040 // this is not an error, there is just no initial value 1041 // if (node->data.var_decl.init == NULL) { panic("could not instanciate gcc jit new local"); } 1042 1043 printf("adding 1 symbol: %s\n", var_name); 1044 1045 Symbol* sym = (Symbol*)calloc(1, sizeof(Symbol)); 1046 sym->name = node->data.var_decl.name; 1047 sym->decl = node; 1048 sym->ctype = declared_type; 1049 sym->d.lvalue = var_decl; 1050 sym->english_type = type_var; 1051 sym->is_variadic = node->data.var_decl.type->data.ident_type.is_variadic; 1052 sym->is_comp_time = node->data.var_decl.type->data.ident_type.is_comp_time; 1053 add_symbol(gen, sym); // add var_decl symbol 1054 return false; 1055 } 1056 1057 static void build_func_decl(Gen*, Node*); 1058 1059 static bool 1060 build_statement(Gen* gen, Node* node) 1061 { 1062 gcc_jit_location* loc = loc_from_node(gen, node); 1063 switch (node->type) { 1064 case NODE_RETURN: { 1065 Node* return_expr = node->data.ret.expr; 1066 if (return_expr) { 1067 gcc_jit_rvalue* ret_rval = handle_expr(gen, return_expr); 1068 gcc_jit_type* expect_type = gcc_jit_function_get_return_type(gen->curr_func); 1069 gcc_jit_type* ret_type = gcc_jit_rvalue_get_type(ret_rval); 1070 types_match_or_panic(node, expect_type, ret_type); 1071 gcc_jit_block_end_with_return(gen->curr_block, loc, ret_rval); 1072 } else { 1073 gcc_jit_block_end_with_void_return(gen->curr_block, loc); 1074 } 1075 gen->curr_block = NULL; // important 1076 return true; // we end the block here 1077 } 1078 case NODE_BREAK: { 1079 gcc_jit_block* t = current_break(gen); 1080 if (!t) return true; // break outside the loop 1081 gcc_jit_block_end_with_jump(gen->curr_block, loc, t); 1082 gen->curr_block = NULL; 1083 return true; 1084 } 1085 case NODE_CONTINUE: { 1086 gcc_jit_block* t = current_continue(gen); 1087 if (!t) return true; // continue outside of a loop 1088 gcc_jit_block_end_with_jump(gen->curr_block, loc, t); 1089 gen->curr_block = NULL; 1090 return true; 1091 } 1092 case NODE_VAR_DECL: { 1093 return build_var_decl_statement(gen, node); 1094 } 1095 case NODE_VAR_ASSIGN: { 1096 gcc_jit_rvalue* rvalue = handle_expr(gen, node->data.var_assign.rhs); 1097 // find the var_decl (d.lvalue) from the symbols table's symbol. 1098 for (size_t i = 0; i < gen->scope->len; i++) { 1099 Symbol* sym = gen->scope->symbols[i]; 1100 if (span_ident_same(sym->name, node->data.var_assign.lhs->data.ident.name, gen->src)) { 1101 // we found the symbol we are assigning to 1102 // TODO check for variadic and comp_time 1103 if (!sym->is_variadic) { 1104 const char* name = span_str(gen->src, sym->name, (char[IDENTSZ]) { 0 }); 1105 panic_at(node, "symbol %s is not variadic, cannot mutate.", name); 1106 } 1107 if (sym->is_comp_time) { 1108 const char* name = span_str(gen->src, sym->name, (char[IDENTSZ]) { 0 }); 1109 panic_at(node, "symbol %s is comp time, cannot mutate.", name); 1110 } 1111 1112 gcc_jit_lvalue* lvalue = sym->d.lvalue; 1113 1114 // check the type of lvalue matches the rvalue 1115 gcc_jit_type* ltype = sym->ctype; 1116 gcc_jit_type* rtype = gcc_jit_rvalue_get_type(rvalue); 1117 if (rtype != ltype) { 1118 panic_at(node, 1119 "right hand side of assigment " 1120 "doesn't match the " 1121 "type of the left hand side: %s <-- %s", 1122 get_english_type(ltype), 1123 get_english_type(rtype)); 1124 } 1125 if (lvalue) gcc_jit_block_add_assignment(gen->curr_block, loc, lvalue, rvalue); 1126 } 1127 } 1128 break; 1129 } 1130 case NODE_BINARY_EXPR: { 1131 Symbol* sym = find_symbol(gen, gen->scope, node->data.binary_expr.lhs->data.ident.name); 1132 if (!sym) 1133 panic_at(node, 1134 "NODE_BINARY_EXPR: Undefined symbol: %s\n", 1135 span_str(gen->src, node->data.ident.name, (char[IDENTSZ]) { 0 })); 1136 1137 gcc_jit_lvalue* lv = sym->d.lvalue; 1138 gcc_jit_rvalue* rhs = handle_expr(gen, node->data.binary_expr.rhs); 1139 gcc_jit_rvalue* lhs = handle_expr(gen, node->data.binary_expr.lhs); 1140 gcc_jit_rvalue* temp = gcc_jit_lvalue_as_rvalue(lv); 1141 gcc_jit_type* lvtype = gcc_jit_rvalue_get_type(temp); 1142 gcc_jit_rvalue* sum 1143 = gcc_jit_context_new_binary_op(gen->ctx, loc_from_node(gen, node), GCC_JIT_BINARY_OP_PLUS, lvtype, lhs, rhs); 1144 1145 gcc_jit_block_add_assignment(gen->curr_block, loc_from_node(gen, node), lv, sum); 1146 } 1147 case NODE_UNARY_EXPR: { 1148 gcc_jit_rvalue* rv = handle_unary_expr(gen, node); 1149 if (rv) gcc_jit_block_add_eval(gen->curr_block, loc_from_node(gen, node), rv); 1150 break; 1151 } 1152 case NODE_EXPR_STATEMENT: { 1153 gcc_jit_rvalue* rv = handle_expr(gen, node->data.expr_statement.expr); 1154 if (rv) gcc_jit_block_add_eval(gen->curr_block, loc_from_node(gen, node), rv); 1155 break; 1156 } 1157 case NODE_IF: 1158 return build_if_statement(gen, node); 1159 case NODE_FOR: 1160 return build_for_statement(gen, node); 1161 case NODE_WHILE: 1162 return build_while_statement(gen, node); 1163 case NODE_FUNCTION_DECL: 1164 // "closure" 1165 build_func_decl(gen, node); 1166 return false; 1167 case NODE_BLOCK: 1168 build_block(gen, node); 1169 default: 1170 printf("--- WARNING: build_statement unhandled, %s\n", node_type_str(node->type)); 1171 break; 1172 } 1173 return false; 1174 } 1175 1176 static gcc_jit_rvalue* 1177 build_bool_value(Gen* gen, Node* node) 1178 { 1179 gcc_jit_location* loc = loc_from_node(gen, node); 1180 1181 switch (node->type) { 1182 case NODE_BOOL_LITERAL: 1183 /* true/false literal */ 1184 return gcc_jit_context_new_rvalue_from_int(gen->ctx, type_boolean, node->data.boolean.value ? 1 : 0); 1185 break; 1186 case NODE_INT_LITERAL: { 1187 /* while (1) style – C truthiness */ 1188 gcc_jit_rvalue* iv = emit_literal_int(gen, node); 1189 return gcc_jit_context_new_cast(gen->ctx, loc, iv, type_boolean); 1190 } 1191 case NODE_STRING_LITERAL: { 1192 /* while("word") should also be truthy if the pointer is non null */ 1193 gcc_jit_rvalue* v = emit_literal_string(gen, node); 1194 gcc_jit_type* ty = gcc_jit_rvalue_get_type(v); 1195 gcc_jit_rvalue* nullv = gcc_jit_context_null(gen->ctx, ty); 1196 return gcc_jit_context_new_comparison(gen->ctx, loc, GCC_JIT_COMPARISON_NE, v, nullv); 1197 } 1198 case NODE_BINARY_EXPR: { 1199 gcc_jit_rvalue* lvalue = handle_expr(gen, node->data.binary_expr.lhs); 1200 gcc_jit_rvalue* rvalue = handle_expr(gen, node->data.binary_expr.rhs); 1201 enum gcc_jit_comparison op; 1202 switch (node->data.binary_expr.op) { 1203 case OP_LT: 1204 op = GCC_JIT_COMPARISON_LT; 1205 break; 1206 case OP_GT: 1207 op = GCC_JIT_COMPARISON_GT; 1208 break; 1209 case OP_LT_EQ: 1210 op = GCC_JIT_COMPARISON_LE; 1211 break; 1212 case OP_GT_EQ: 1213 op = GCC_JIT_COMPARISON_GE; 1214 break; 1215 default: 1216 printf("build_bool_rvalue nodebinary op unhandled, " 1217 "%s\n", 1218 node_type_str(node->type)); 1219 return NULL; 1220 } 1221 return gcc_jit_context_new_comparison(gen->ctx, loc, op, lvalue, rvalue); 1222 break; 1223 } 1224 default: 1225 printf("/!\\ build_bool_rvalue unhandled, %s\n", node_type_str(node->type)); 1226 break; 1227 } 1228 1229 return NULL; 1230 } 1231 1232 // build_block: returns true if block ended with a terminator 1233 static bool 1234 build_block(Gen* gen, Node* body) 1235 { 1236 // TODO if there is no block ({ ... }), we presume there is only 1 statement. 1237 // This might not always be valid, func declaration do require a block {}, but there might be cases... 1238 // FIXME: a symbol declared in a child block is accessible in the parent or in a sibling block... 1239 if (body->data.block.len == 0) { return build_statement(gen, body); } 1240 1241 for (size_t i = 0; i < body->data.block.len; i++) { 1242 if (gen->curr_block == NULL) return true; 1243 bool ended = build_statement(gen, body->data.block.stmts[i]); 1244 if (ended) return true; 1245 } 1246 return false; 1247 } 1248 1249 static void 1250 build_func_decl(Gen* gen, Node* node) 1251 { 1252 const char* func_name = span_str(gen->src, node->data.function_decl.name, (char[IDENTSZ]) { 0 }); 1253 1254 Node* return_type = node->data.function_decl.return_type; 1255 gcc_jit_type* ret_type = ox_type_to_c_type(gen, return_type); 1256 gcc_jit_location* loc = loc_from_node(gen, node); 1257 1258 size_t argc = node->data.function_decl.p_len; 1259 1260 gcc_jit_param** params = calloc(argc, sizeof(gcc_jit_param*)); 1261 1262 // 1) Create ONE gcc_jit_param per AST param 1263 for (size_t i = 0; i < argc; i++) { 1264 Node* pnode = node->data.function_decl.params[i]; 1265 const char* pname = span_str(gen->src, pnode->data.param.name, (char[IDENTSZ]) { 0 }); 1266 1267 gcc_jit_type* declared_type = ox_type_to_c_type(gen, pnode->data.param.type); 1268 1269 gcc_jit_param* p = gcc_jit_context_new_param(gen->ctx, loc, declared_type, strdup(pname)); 1270 1271 params[i] = p; 1272 } 1273 1274 // 2) Create the function with those params 1275 gcc_jit_function* func = gcc_jit_context_new_function(gen->ctx, 1276 loc, 1277 GCC_JIT_FUNCTION_EXPORTED, 1278 ret_type, 1279 strdup(func_name), 1280 argc, 1281 params, // <-- these are now owned by 'func' 1282 0); 1283 1284 gcc_jit_block* block = gcc_jit_function_new_block(func, "entry"); 1285 1286 gcc_jit_function* prev_func = gen->curr_func; 1287 gcc_jit_block* prev_block = gen->curr_block; 1288 gen->curr_func = func; 1289 gen->curr_block = block; 1290 1291 // 3) Add the function symbol to the current (enclosing) scope 1292 Symbol* sym = (Symbol*)calloc(1, sizeof(Symbol)); 1293 sym->name = node->data.function_decl.name; 1294 sym->decl = node; 1295 sym->ctype = type_voidp; // whatever you use for function type metadata 1296 sym->d.funcvalue = func; 1297 sym->english_type = type_func; 1298 add_symbol(gen, sym); // add function symbol -- to the 'parent scope', before we push_scope 1299 1300 // ENTER FUNCTION SCOPE 1301 push_scope(gen); 1302 1303 // 4) Add parameter symbols to the FUNCTION scope, reusing the same gcc_jit_param* 1304 for (size_t i = 0; i < argc; i++) { 1305 Node* pnode = node->data.function_decl.params[i]; 1306 1307 gcc_jit_param* p = params[i]; // <-- reuse, DO NOT new_param again 1308 1309 gcc_jit_type* declared_type = ox_type_to_c_type(gen, pnode->data.param.type); 1310 1311 Symbol* ps = (Symbol*)calloc(1, sizeof(Symbol)); 1312 ps->name = pnode->data.param.name; // param identifier span 1313 ps->decl = pnode; 1314 ps->ctype = declared_type; 1315 ps->d.param = p; // <-- this is associated with 'func' 1316 ps->english_type = type_var; // or type_param if you distinguish 1317 add_symbol(gen, ps); // add param symbol 1318 } 1319 1320 print_symbols_here(gen); 1321 1322 build_block(gen, node->data.function_decl.body); 1323 1324 if (gen->curr_block == NULL) { 1325 // no open block: all paths already terminated, don't add an implicit return 1326 } else if (ret_type == type_int) { 1327 gcc_jit_rvalue* ret_value = gcc_jit_context_new_rvalue_from_int(gen->ctx, type_int, 0); 1328 gcc_jit_block_end_with_return(gen->curr_block, loc, ret_value); 1329 } else if (ret_type == type_void) { 1330 gcc_jit_block_end_with_void_return(gen->curr_block, loc); 1331 } else { 1332 printf("build_func_decl unhandled return type in func: %s - " 1333 "defaulting to void\n", 1334 func_name); 1335 gcc_jit_block_end_with_void_return(gen->curr_block, loc); 1336 } 1337 1338 // LEAVE FUNCTION SCOPE 1339 pop_scope(gen); 1340 1341 gen->curr_func = prev_func; 1342 gen->curr_block = prev_block; 1343 } 1344 1345 void 1346 gen_next(Gen* gen, Node* node) 1347 { 1348 // printf("gen_next, %s\n", node_type_str(node->type)); 1349 1350 switch (node->type) { 1351 case NODE_PROGRAM: 1352 build_program(gen, node); 1353 break; 1354 case NODE_FUNCTION_DECL: 1355 build_func_decl(gen, node); 1356 break; 1357 case NODE_STRING_LITERAL: 1358 emit_literal_string(gen, node); 1359 break; 1360 case NODE_INT_LITERAL: 1361 emit_literal_int(gen, node); 1362 break; 1363 case NODE_FLOAT_LITERAL: 1364 emit_literal_float(gen, node); 1365 break; 1366 case NODE_VAR_DECL: 1367 build_statement(gen, node); 1368 break; 1369 default: 1370 printf("gen: unhandled, %s\n", node_type_str(node->type)); 1371 } 1372 }