kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

ir_emit.c (9920B)


      1 #include "arch/c_target/ir_emit.h"
      2 
      3 #include <string.h>
      4 
      5 typedef struct CIrEmitter {
      6   CTarget* target;
      7   CGScope* scope_map;
      8   u32 scope_map_n;
      9 } CIrEmitter;
     10 
     11 static CGScope ir_scope_lookup(CIrEmitter* e, CGScope recorded, SrcLoc loc) {
     12   if ((u32)recorded >= e->scope_map_n || !e->scope_map[recorded]) {
     13     compiler_panic(e->target->c, loc,
     14                    "C target IR emit: unknown recorded scope %u",
     15                    (unsigned)recorded);
     16   }
     17   return e->scope_map[recorded];
     18 }
     19 
     20 static void ir_scope_bind(CIrEmitter* e, CGScope recorded, CGScope emitted,
     21                           SrcLoc loc) {
     22   if ((u32)recorded >= e->scope_map_n) {
     23     compiler_panic(e->target->c, loc,
     24                    "C target IR emit: recorded scope %u out of range",
     25                    (unsigned)recorded);
     26   }
     27   e->scope_map[recorded] = emitted;
     28 }
     29 
     30 static void ir_emit_param_bind(CIrEmitter* e, const CgIrParam* p) {
     31   c_emit_param_bind(e->target, p->local, p->desc.type, p->desc.index);
     32 }
     33 
     34 static void ir_declare_locals(CIrEmitter* e, const CgIrFunc* f) {
     35   for (u32 i = 0; i < f->nlocals; ++i) {
     36     const CgIrLocal* l = &f->locals[i];
     37     c_ensure_local(e->target, l->id, l->desc.type);
     38   }
     39   for (u32 i = 0; i < f->nparams; ++i) ir_emit_param_bind(e, &f->params[i]);
     40 }
     41 
     42 static void ir_emit_switch(CIrEmitter* e, const CgIrInst* in) {
     43   const CgIrSwitchAux* aux = (const CgIrSwitchAux*)in->extra.aux;
     44   CGSwitchDesc d;
     45   memset(&d, 0, sizeof d);
     46   d.selector = in->opnds[0];
     47   d.selector_type = aux->selector_type;
     48   d.default_label = aux->default_label;
     49   d.cases = aux->cases;
     50   d.ncases = aux->ncases;
     51   d.hint = aux->hint;
     52   d.opt_level = aux->opt_level;
     53   c_emit_switch_(e->target, &d);
     54 }
     55 
     56 static void ir_emit_inst(CIrEmitter* e, const CgIrInst* in) {
     57   CTarget* t = e->target;
     58   c_emit_set_loc(t, in->loc);
     59   switch ((CgIrOp)in->op) {
     60     case CG_IR_NOP:
     61       return;
     62     case CG_IR_LABEL:
     63       c_emit_label_place(t, (Label)in->extra.imm);
     64       return;
     65     case CG_IR_LOAD_IMM:
     66       c_emit_load_imm(t, in->opnds[0], in->extra.imm);
     67       return;
     68     case CG_IR_LOAD_CONST:
     69       c_emit_load_const(t, in->opnds[0], in->extra.cbytes);
     70       return;
     71     case CG_IR_COPY:
     72       c_emit_copy(t, in->opnds[0], in->opnds[1]);
     73       return;
     74     case CG_IR_LOAD:
     75       c_emit_load(t, in->opnds[0], in->opnds[1], in->extra.mem);
     76       return;
     77     case CG_IR_STORE:
     78       c_emit_store(t, in->opnds[0], in->opnds[1], in->extra.mem);
     79       return;
     80     case CG_IR_ADDR_OF:
     81       c_emit_addr_of(t, in->opnds[0], in->opnds[1]);
     82       return;
     83     case CG_IR_TLS_ADDR_OF: {
     84       const CgIrTlsAux* aux = (const CgIrTlsAux*)in->extra.aux;
     85       c_emit_tls_addr_of(t, in->opnds[0], aux->sym, aux->addend);
     86       return;
     87     }
     88     case CG_IR_AGG_COPY: {
     89       const CgIrAggAux* aux = (const CgIrAggAux*)in->extra.aux;
     90       c_emit_copy_bytes(t, in->opnds[0], in->opnds[1], aux->access);
     91       return;
     92     }
     93     case CG_IR_AGG_SET: {
     94       const CgIrAggAux* aux = (const CgIrAggAux*)in->extra.aux;
     95       c_emit_set_bytes(t, in->opnds[0], in->opnds[1], aux->access);
     96       return;
     97     }
     98     case CG_IR_BITFIELD_LOAD: {
     99       const CgIrBitFieldAux* aux = (const CgIrBitFieldAux*)in->extra.aux;
    100       c_emit_bitfield_load(t, in->opnds[0], in->opnds[1], aux->access);
    101       return;
    102     }
    103     case CG_IR_BITFIELD_STORE: {
    104       const CgIrBitFieldAux* aux = (const CgIrBitFieldAux*)in->extra.aux;
    105       c_emit_bitfield_store(t, in->opnds[0], in->opnds[1], aux->access);
    106       return;
    107     }
    108     case CG_IR_BINOP:
    109       c_emit_binop(t, (BinOp)in->extra.imm, in->opnds[0], in->opnds[1],
    110                    in->opnds[2]);
    111       return;
    112     case CG_IR_UNOP:
    113       c_emit_unop(t, (UnOp)in->extra.imm, in->opnds[0], in->opnds[1]);
    114       return;
    115     case CG_IR_CMP:
    116       c_emit_cmp(t, (CmpOp)in->extra.imm, in->opnds[0], in->opnds[1],
    117                  in->opnds[2]);
    118       return;
    119     case CG_IR_CONVERT:
    120       c_emit_convert(t, (ConvKind)in->extra.imm, in->opnds[0], in->opnds[1]);
    121       return;
    122     case CG_IR_CALL: {
    123       const CgIrCallAux* aux = (const CgIrCallAux*)in->extra.aux;
    124       c_emit_call(t, &aux->desc);
    125       return;
    126     }
    127     case CG_IR_RET: {
    128       const CgIrRetAux* aux = (const CgIrRetAux*)in->extra.aux;
    129       c_emit_ret(t, aux->present ? aux->value : CG_LOCAL_NONE);
    130       return;
    131     }
    132     case CG_IR_UNREACHABLE:
    133       c_emit_unreachable(t);
    134       return;
    135     case CG_IR_BR:
    136       c_emit_jump(t, (Label)in->extra.imm);
    137       return;
    138     case CG_IR_CMP_BRANCH: {
    139       const CgIrCmpBranchAux* aux = (const CgIrCmpBranchAux*)in->extra.aux;
    140       c_emit_cmp_branch(t, aux->op, in->opnds[0], in->opnds[1], aux->target);
    141       return;
    142     }
    143     case CG_IR_SWITCH:
    144       ir_emit_switch(e, in);
    145       return;
    146     case CG_IR_INDIRECT_BRANCH: {
    147       const CgIrIndirectAux* aux = (const CgIrIndirectAux*)in->extra.aux;
    148       c_emit_indirect_branch(t, in->opnds[0], aux->targets, aux->ntargets);
    149       return;
    150     }
    151     case CG_IR_LOAD_LABEL_ADDR:
    152       c_emit_load_label_addr(t, in->opnds[0], (Label)in->extra.imm);
    153       return;
    154     case CG_IR_LOCAL_STATIC_DATA_BEGIN: {
    155       const CgIrLocalStaticBeginAux* aux =
    156           (const CgIrLocalStaticBeginAux*)in->extra.aux;
    157       (void)c_emit_local_static_data_begin(t, &aux->desc);
    158       return;
    159     }
    160     case CG_IR_LOCAL_STATIC_DATA_WRITE: {
    161       const CgIrLocalStaticWriteAux* aux =
    162           (const CgIrLocalStaticWriteAux*)in->extra.aux;
    163       c_emit_local_static_data_write(t, aux->has_data ? aux->data : NULL,
    164                                      aux->len);
    165       return;
    166     }
    167     case CG_IR_LOCAL_STATIC_DATA_LABEL_ADDR: {
    168       const CgIrLocalStaticLabelAux* aux =
    169           (const CgIrLocalStaticLabelAux*)in->extra.aux;
    170       c_emit_local_static_data_label_addr(t, aux->target, aux->addend,
    171                                           aux->width, aux->address_space);
    172       return;
    173     }
    174     case CG_IR_LOCAL_STATIC_DATA_END:
    175       c_emit_local_static_data_end(t);
    176       return;
    177     case CG_IR_SCOPE_BEGIN: {
    178       const CgIrScopeAux* aux = (const CgIrScopeAux*)in->extra.aux;
    179       CGScope emitted = c_emit_scope_begin(t, &aux->desc);
    180       ir_scope_bind(e, aux->scope, emitted, in->loc);
    181       return;
    182     }
    183     case CG_IR_SCOPE_END:
    184       c_emit_scope_end(t, ir_scope_lookup(e, (CGScope)in->extra.imm, in->loc));
    185       return;
    186     case CG_IR_BREAK_TO:
    187       c_emit_break_to(t, ir_scope_lookup(e, (CGScope)in->extra.imm, in->loc));
    188       return;
    189     case CG_IR_CONTINUE_TO:
    190       c_emit_continue_to(t,
    191                          ir_scope_lookup(e, (CGScope)in->extra.imm, in->loc));
    192       return;
    193     case CG_IR_ALLOCA:
    194       c_emit_alloca(t, in->opnds[0], in->opnds[1], (u32)in->extra.imm);
    195       return;
    196     case CG_IR_VA_START:
    197       c_emit_va_start(t, in->opnds[0]);
    198       return;
    199     case CG_IR_VA_ARG:
    200       c_emit_va_arg(t, in->opnds[0], in->opnds[1], (KitCgTypeId)in->extra.imm);
    201       return;
    202     case CG_IR_VA_END:
    203       c_emit_va_end(t, in->opnds[0]);
    204       return;
    205     case CG_IR_VA_COPY:
    206       c_emit_va_copy(t, in->opnds[0], in->opnds[1]);
    207       return;
    208     case CG_IR_ATOMIC_LOAD: {
    209       const CgIrAtomicAux* aux = (const CgIrAtomicAux*)in->extra.aux;
    210       c_emit_atomic_load(t, in->opnds[0], in->opnds[1], aux->mem, aux->order);
    211       return;
    212     }
    213     case CG_IR_ATOMIC_STORE: {
    214       const CgIrAtomicAux* aux = (const CgIrAtomicAux*)in->extra.aux;
    215       c_emit_atomic_store(t, in->opnds[0], in->opnds[1], aux->mem, aux->order);
    216       return;
    217     }
    218     case CG_IR_ATOMIC_RMW: {
    219       const CgIrAtomicAux* aux = (const CgIrAtomicAux*)in->extra.aux;
    220       c_emit_atomic_rmw(t, aux->op, in->opnds[0], in->opnds[1], in->opnds[2],
    221                         aux->mem, aux->order);
    222       return;
    223     }
    224     case CG_IR_ATOMIC_CAS: {
    225       const CgIrAtomicAux* aux = (const CgIrAtomicAux*)in->extra.aux;
    226       c_emit_atomic_cas(t, in->opnds[0], in->opnds[1], in->opnds[2],
    227                         in->opnds[3], in->opnds[4], aux->mem, aux->order,
    228                         aux->failure);
    229       return;
    230     }
    231     case CG_IR_FENCE:
    232       c_emit_fence(t, (KitCgMemOrder)in->extra.imm);
    233       return;
    234     case CG_IR_INTRINSIC: {
    235       const CgIrIntrinsicAux* aux = (const CgIrIntrinsicAux*)in->extra.aux;
    236       c_emit_intrinsic(t, aux->kind, aux->dsts, aux->ndst, aux->args,
    237                        aux->narg);
    238       return;
    239     }
    240     case CG_IR_ASM_BLOCK: {
    241       const CgIrAsmAux* aux = (const CgIrAsmAux*)in->extra.aux;
    242       c_emit_asm_block(t, aux->tmpl, aux->outs, aux->nout, aux->out_ops,
    243                        aux->ins, aux->nin, aux->in_ops, aux->clobbers,
    244                        aux->nclob);
    245       return;
    246     }
    247   }
    248   compiler_panic(t->c, in->loc, "C target IR emit: unknown op %u",
    249                  (unsigned)in->op);
    250 }
    251 
    252 static void ir_emit_func(CTarget* t, const CgIrFunc* f) {
    253   CIrEmitter e;
    254   Heap* h = t->c->ctx->heap;
    255   memset(&e, 0, sizeof e);
    256   e.target = t;
    257   e.scope_map_n = f->nscopes + 1u;
    258   if (e.scope_map_n) {
    259     e.scope_map = (CGScope*)h->alloc(h, sizeof(CGScope) * e.scope_map_n,
    260                                      _Alignof(CGScope));
    261     if (!e.scope_map) {
    262       compiler_panic(t->c, f->desc.loc, "C target IR emit: out of memory");
    263     }
    264     memset(e.scope_map, 0, sizeof(CGScope) * e.scope_map_n);
    265   }
    266 
    267   c_emit_func_begin(t, &f->desc);
    268   ir_declare_locals(&e, f);
    269   for (u32 i = 0; i < f->ninsts; ++i) ir_emit_inst(&e, &f->insts[i]);
    270   c_emit_func_end(t);
    271 
    272   if (e.scope_map) h->free(h, e.scope_map, sizeof(CGScope) * e.scope_map_n);
    273 }
    274 
    275 void c_emit_ir_module(CTarget* t, const CgIrModule* module) {
    276   if (!t || !module) return;
    277   for (u32 i = 0; i < module->naliases; ++i) {
    278     const CgIrAlias* a = &module->aliases[i];
    279     c_emit_alias(t, a->alias_sym, a->target_sym, a->type);
    280   }
    281   for (u32 i = 0; i < module->nfile_scope_asms; ++i) {
    282     const CgIrFileScopeAsm* a = &module->file_scope_asms[i];
    283     c_emit_file_scope_asm(t, a->src, a->len);
    284   }
    285   for (u32 i = 0; i < module->nfuncs; ++i) {
    286     ir_emit_func(t, module->funcs[i]);
    287   }
    288 }