backend

Unnamed repository; edit this file 'description' to name the repository.
git clone https://git.deepztream.com/backend
Log | Files | Refs

ir_backend.c (6030B)


      1 typedef struct {
      2   void *loc;
      3   void *end;
      4 } Temp_allocator;
      5 
      6 Temp_allocator temp_allocator = {0};
      7 
      8 void *
      9 temp_alloc(size_t size)
     10 {
     11   if (!temp_allocator.loc) {
     12     size_t allocator_size = 1024*1024;
     13     temp_allocator.loc = malloc(allocator_size);
     14     temp_allocator.end = temp_allocator.loc + allocator_size;
     15     temp_allocator.loc = (void *)((intptr_t)(temp_allocator.loc + 0xF) & ~0xFul);
     16   }
     17   void *result = temp_allocator.loc;
     18   temp_allocator.loc += (size + 0xF) & ~0xFul;
     19   if (temp_allocator.loc >= temp_allocator.end) {
     20     fprintf(stderr, "Error: Temp allocator out of memory\n");
     21     exit(1);
     22   }
     23   return result;
     24 }
     25 
     26 const char *
     27 ir_arg_to_cstr(Ir_arg arg)
     28 {
     29   int len;
     30   char *str;
     31   if (arg.type == ARG_INT_LITERAL) {
     32     len = snprintf(NULL, 0, "%li", arg.i64) + 1;
     33     str = temp_alloc(len);
     34     snprintf(str, len, "%li", arg.i64);
     35   } else if (arg.type == ARG_TEMP_STORAGE) {
     36     len = snprintf(NULL, 0, "%%%li", arg.temp_id) + 1;
     37     str = temp_alloc(len);
     38     snprintf(str, len, "%%%li", arg.temp_id);
     39   } else if (arg.type == ARG_ADDRESS) {
     40     len = snprintf(NULL, 0, "0x%p", arg.addr) + 1;
     41     str = temp_alloc(len);
     42     snprintf(str, len, "0x%p", arg.addr);
     43   } else if (arg.type == ARG_CSTRING_LITERAL) {
     44     len = strlen(arg.cstr);
     45     str = temp_alloc(len + 3);
     46     memcpy(str + 1, arg.cstr, len);
     47     str[0] = '"';
     48     str[len + 1] = '"';
     49     str[len + 2] = '\0';
     50   } else {
     51     assert(0 && "Invalid arg");
     52   }
     53   return str;
     54 }
     55 
     56 const char *
     57 ir_binop_to_cstr(enum Ir_binop binop)
     58 {
     59   const char *str;
     60   switch (binop) {
     61     case OP_ADD: str = "+";  break;
     62     case OP_SUB: str = "-";  break;
     63     case OP_MUL: str = "*";  break;
     64     case OP_DIV: str = "/";  break;
     65     case OP_LT:  str = "<";  break;
     66     case OP_GT:  str = ">";  break;
     67     case OP_EQ:  str = "=="; break;
     68     case OP_LEQ: str = "<="; break;
     69     case OP_GEQ: str = "=>"; break;
     70     default: assert(0 && "Unknown binop");
     71   }
     72   return str;
     73 }
     74 
     75 const char *
     76 ir_type_to_cstr(enum Ir_type type)
     77 {
     78   const char *str;
     79   switch (type) {
     80     case TYPE_VOID: str = "void"; break;
     81     case TYPE_I8:   str = "i8";   break;
     82     case TYPE_U8:   str = "u8";   break;
     83     case TYPE_I16:  str = "i16";  break;
     84     case TYPE_U16:  str = "u16";  break;
     85     case TYPE_I32:  str = "i32";  break;
     86     case TYPE_U32:  str = "u32";  break;
     87     case TYPE_I64:  str = "i64";  break;
     88     case TYPE_U64:  str = "u64";  break;
     89     case TYPE_PTR:  str = "ptr";  break;
     90     case TYPE_F32:  str = "f32";  break;
     91     case TYPE_F64:  str = "f64";  break;
     92     default: assert(0 && "Unknown type");
     93   }
     94   return str;
     95 }
     96 
     97 bool
     98 ir_compile_body(Ir_list irs, string_builder *sb)
     99 {
    100   size_t i, j;
    101   Ir ir;
    102   Temp_allocator saved_allocator;
    103   for (i = 0; i < irs.count; i++) {
    104     saved_allocator = temp_allocator;
    105     ir = irs.items[i];
    106     assert(ir.result.type == ARG_TEMP_STORAGE || ir.result.type == ARG_NONE);
    107     sb_append_cstr(sb, "  ");
    108     switch (ir.type) {
    109       case IR_LOAD:
    110         assert(ir.result.type != ARG_NONE);
    111         sb_printf(sb, "  %s = load(%s)", ir_arg_to_cstr(ir.result), ir_arg_to_cstr(ir.load.loc));
    112         break;
    113       case IR_STORE:
    114         assert(ir.result.type == ARG_NONE);
    115         sb_printf(sb, "  store(%s, %s)", ir_arg_to_cstr(ir.store.loc), ir_arg_to_cstr(ir.store.data));
    116         break;
    117       case IR_ASSIGN:
    118         assert(ir.result.type != ARG_NONE);
    119         sb_printf(sb, "  %s = %s", ir_arg_to_cstr(ir.result), ir_arg_to_cstr(ir.assign));
    120         break;
    121       case IR_BINOP:
    122         assert(ir.result.type != ARG_NONE);
    123         sb_printf(sb, "  %s = %s %s %s", ir_arg_to_cstr(ir.result), ir_arg_to_cstr(ir.binop.left), ir_binop_to_cstr(ir.binop.op), ir_arg_to_cstr(ir.binop.right));
    124         break;
    125       case IR_CALL:
    126         assert(ir.result.type != ARG_NONE);
    127         if (ir.call.indirect.type != ARG_NONE) {
    128           sb_printf(sb, "  %s = call %s (", ir_arg_to_cstr(ir.result), ir_arg_to_cstr(ir.call.indirect));
    129         } else {
    130           sb_printf(sb, "  %s = call %.*s (", ir_arg_to_cstr(ir.result), ir.call.name.count, ir.call.name.data);
    131         }
    132         for (j = 0; j < ir.call.args.count; j++) {
    133           if (j) {
    134             sb_append_cstr(sb, ", ");
    135           }
    136           sb_append_cstr(sb, ir_arg_to_cstr(ir.call.args.items[j]));
    137         }
    138         sb_append_char(sb, ')');
    139         break;
    140       case IR_RETURN:
    141         assert(ir.result.type == ARG_NONE);
    142         sb_printf(sb, "  return %s", ir_arg_to_cstr(ir.ret));
    143         break;
    144       case IR_LABEL:
    145         assert(ir.result.type == ARG_NONE);
    146         sb_printf(sb, "#%.*s:", ir.label.count, ir.label.data);
    147         break;
    148       case IR_JUMP:
    149         assert(ir.result.type == ARG_NONE);
    150         sb_printf(sb, "  jump #%.*s", ir.jump.label.count, ir.jump.label.data);
    151         break;
    152       case IR_JUMP_IF_NOT:
    153         assert(ir.result.type == ARG_NONE);
    154         sb_printf(sb, "  jump_if_not %s #%.*s", ir_arg_to_cstr(ir.jump.cond), ir.jump.label.count, ir.jump.label.data);
    155         break;
    156       default:
    157         fprintf(stderr, "Error: Unknown IR %lu\n", i);
    158         temp_allocator = saved_allocator;
    159         return false;
    160     }
    161     sb_append_char(sb, '\n');
    162     temp_allocator = saved_allocator;
    163   }
    164   return true;
    165 }
    166 
    167 bool
    168 ir_compile(Ir_program prog, string_builder *sb)
    169 {
    170   size_t i, j;
    171   Ir_function function;
    172   Temp_allocator saved_allocator;
    173   for (i = 0; i < prog.functions.count; i++) {
    174     saved_allocator = temp_allocator;
    175     if (i) {
    176       sb_append_char(sb, '\n');
    177     }
    178     function = prog.functions.items[i];
    179     sb_printf(sb, "$%.*s(", function.name.count, function.name.data);
    180     for (j = 0; j < function.argument_types.count; j++) {
    181       if (j) {
    182         sb_append_cstr(sb, ", ");
    183       }
    184       sb_append_cstr(sb, ir_type_to_cstr(function.argument_types.items[j]));
    185     }
    186     sb_printf(sb, ") -> %s {\n", ir_type_to_cstr(function.return_type));
    187     if (!ir_compile_body(function.body, sb)) {
    188       temp_allocator = saved_allocator;
    189       return false;
    190     }
    191     sb_append_cstr(sb, "}\n");
    192     temp_allocator = saved_allocator;
    193   }
    194   return true;
    195 }