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