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 }