ir_recorder.c (23716B)
1 #include "cg/ir_recorder.h" 2 3 #include <string.h> 4 5 struct CgIrRecorder { 6 CgTarget base; 7 u32 magic; 8 CgIrModule* module; 9 CgIrFunc* cur; 10 SrcLoc loc; 11 void (*func_recorded)(void*, CgIrFunc*); 12 void (*finalize_recorded)(void*, const CgIrModule*); 13 void (*destroy_user)(void*); 14 int (*local_static_data_begin)(void*, const CGLocalStaticDataDesc*); 15 const char* (*data_label_addr_unsupported_msg)(void*); 16 const char* (*tail_call_unrealizable_reason)(void*, const CGFuncDesc*, 17 const CGCallDesc*); 18 int (*asm_is_reg_constraint)(void*, const char*); 19 void* user; 20 }; 21 22 #define CG_IR_RECORDER_MAGIC 0x43524952u 23 24 static CgIrRecorder* rec_of(CgTarget* t) { return (CgIrRecorder*)t; } 25 26 static void rec_panic(CgIrRecorder* r, const char* what) { 27 compiler_panic(r->base.c, r->loc, "cg ir recorder: %s", what); 28 } 29 30 static CgIrFunc* require_func(CgIrRecorder* r) { 31 if (!r->cur) rec_panic(r, "operation outside function"); 32 return r->cur; 33 } 34 35 static void* aux_alloc(CgIrRecorder* r, size_t size, size_t align) { 36 void* p = arena_zalloc(require_func(r)->arena, size, align); 37 if (!p) rec_panic(r, "out of memory"); 38 return p; 39 } 40 41 #define AUX_NEW(r, T) ((T*)aux_alloc((r), sizeof(T), _Alignof(T))) 42 43 static CgIrInst* emit(CgIrRecorder* r, CgIrOp op) { 44 return cg_ir_emit(require_func(r), op, r->loc); 45 } 46 47 static void note_global_ref(CgIrRecorder* r, Operand op) { 48 if (op.kind == OPK_GLOBAL) 49 cg_ir_symset_add(r->base.c, &require_func(r)->global_refs, op.v.global.sym); 50 } 51 52 static void note_global_refs(CgIrRecorder* r, const Operand* ops, u32 n) { 53 if (!ops) return; 54 for (u32 i = 0; i < n; ++i) note_global_ref(r, ops[i]); 55 } 56 57 static void set_ops(CgIrRecorder* r, CgIrInst* in, const Operand* ops, u32 n) { 58 in->opnds = cg_ir_dup_operands(require_func(r)->arena, ops, n); 59 in->nopnds = n; 60 note_global_refs(r, ops, n); 61 } 62 63 static void rec_func_begin(CgTarget* t, const CGFuncDesc* desc) { 64 CgIrRecorder* r = rec_of(t); 65 if (r->cur) rec_panic(r, "nested function begin"); 66 r->cur = cg_ir_func_new(t->c, desc); 67 if (!r->cur) rec_panic(r, "out of memory"); 68 cg_ir_module_add_func(r->module, r->cur); 69 r->loc = desc ? desc->loc : (SrcLoc){0, 0, 0}; 70 } 71 72 static void rec_func_end(CgTarget* t) { 73 CgIrRecorder* r = rec_of(t); 74 CgIrFunc* f = require_func(r); 75 f->complete = 1; 76 if (r->func_recorded) r->func_recorded(r->user, f); 77 r->cur = NULL; 78 } 79 80 static void rec_alias(CgTarget* t, ObjSymId alias_sym, ObjSymId target_sym, 81 KitCgTypeId type) { 82 CgIrRecorder* r = rec_of(t); 83 cg_ir_module_add_alias(r->module, alias_sym, target_sym, type); 84 } 85 86 static CGLocal rec_local(CgTarget* t, const CGLocalDesc* desc) { 87 CgIrRecorder* r = rec_of(t); 88 return cg_ir_func_add_local(require_func(r), desc, 0, 0); 89 } 90 91 static void rec_local_addr(CgTarget* t, Operand dst, const CGLocalDesc* desc, 92 CGLocal local) { 93 CgIrRecorder* r = rec_of(t); 94 CgIrInst* in = emit(r, CG_IR_ADDR_OF); 95 Operand ops[2]; 96 (void)desc; 97 cg_ir_func_mark_local_address_taken(require_func(r), local); 98 memset(ops, 0, sizeof ops); 99 ops[0] = dst; 100 ops[1].kind = OPK_LOCAL; 101 ops[1].type = desc ? desc->type : dst.type; 102 ops[1].v.local = local; 103 set_ops(r, in, ops, 2); 104 } 105 106 static CGLocal rec_param(CgTarget* t, const CGParamDesc* desc) { 107 CgIrRecorder* r = rec_of(t); 108 CgIrFunc* f = require_func(r); 109 CGLocalDesc ld; 110 CGLocal local; 111 memset(&ld, 0, sizeof ld); 112 ld.type = desc->type; 113 ld.name = desc->name; 114 ld.loc = desc->loc; 115 ld.size = desc->size; 116 ld.align = desc->align; 117 ld.flags = desc->flags; 118 local = cg_ir_func_add_local(f, &ld, 1, desc->index); 119 cg_ir_func_add_param(f, local, desc); 120 return local; 121 } 122 123 static Label rec_label_new(CgTarget* t) { 124 return cg_ir_func_add_label(require_func(rec_of(t))); 125 } 126 127 static void rec_label_place(CgTarget* t, Label label) { 128 CgIrRecorder* r = rec_of(t); 129 CgIrInst* in = emit(r, CG_IR_LABEL); 130 in->extra.imm = (i64)label; 131 cg_ir_func_note_label_place(require_func(r), label, r->loc); 132 } 133 134 static void rec_jump(CgTarget* t, Label label) { 135 CgIrInst* in = emit(rec_of(t), CG_IR_BR); 136 in->extra.imm = (i64)label; 137 } 138 139 static void rec_cmp_branch(CgTarget* t, CmpOp op, Operand a, Operand b, 140 Label label) { 141 CgIrRecorder* r = rec_of(t); 142 CgIrInst* in = emit(r, CG_IR_CMP_BRANCH); 143 CgIrCmpBranchAux* aux = AUX_NEW(r, CgIrCmpBranchAux); 144 Operand ops[2] = {a, b}; 145 aux->op = op; 146 aux->target = label; 147 set_ops(r, in, ops, 2); 148 in->extra.aux = aux; 149 } 150 151 static void rec_switch(CgTarget* t, const CGSwitchDesc* desc) { 152 CgIrRecorder* r = rec_of(t); 153 CgIrInst* in = emit(r, CG_IR_SWITCH); 154 CgIrSwitchAux* aux = AUX_NEW(r, CgIrSwitchAux); 155 Operand op = desc->selector; 156 aux->selector_type = desc->selector_type; 157 aux->default_label = desc->default_label; 158 aux->cases = 159 cg_ir_dup_switch_cases(require_func(r)->arena, desc->cases, desc->ncases); 160 aux->ncases = desc->ncases; 161 aux->hint = desc->hint; 162 aux->opt_level = desc->opt_level; 163 set_ops(r, in, &op, 1); 164 in->extra.aux = aux; 165 } 166 167 static void rec_indirect_branch(CgTarget* t, Operand addr, 168 const Label* valid_targets, u32 ntargets) { 169 CgIrRecorder* r = rec_of(t); 170 CgIrInst* in = emit(r, CG_IR_INDIRECT_BRANCH); 171 CgIrIndirectAux* aux = AUX_NEW(r, CgIrIndirectAux); 172 aux->targets = 173 cg_ir_dup_labels(require_func(r)->arena, valid_targets, ntargets); 174 aux->ntargets = ntargets; 175 set_ops(r, in, &addr, 1); 176 in->extra.aux = aux; 177 } 178 179 static void rec_load_label_addr(CgTarget* t, Operand dst, Label label) { 180 CgIrInst* in = emit(rec_of(t), CG_IR_LOAD_LABEL_ADDR); 181 set_ops(rec_of(t), in, &dst, 1); 182 in->extra.imm = (i64)label; 183 } 184 185 static int rec_local_static_data_begin(CgTarget* t, 186 const CGLocalStaticDataDesc* desc) { 187 CgIrRecorder* r = rec_of(t); 188 if (r->local_static_data_begin && 189 !r->local_static_data_begin(r->user, desc)) { 190 return 0; 191 } 192 CgIrInst* in = emit(r, CG_IR_LOCAL_STATIC_DATA_BEGIN); 193 CgIrLocalStaticBeginAux* aux = AUX_NEW(r, CgIrLocalStaticBeginAux); 194 aux->desc = *desc; 195 in->extra.aux = aux; 196 return 1; 197 } 198 199 static void rec_local_static_data_write(CgTarget* t, const u8* data, u64 len) { 200 CgIrRecorder* r = rec_of(t); 201 CgIrFunc* f = require_func(r); 202 CgIrInst* in = emit(r, CG_IR_LOCAL_STATIC_DATA_WRITE); 203 CgIrLocalStaticWriteAux* aux = AUX_NEW(r, CgIrLocalStaticWriteAux); 204 aux->len = len; 205 if (data && len) { 206 if (len > UINT32_MAX) rec_panic(r, "local static data chunk too large"); 207 aux->data = arena_array(f->arena, u8, (u32)len); 208 memcpy(aux->data, data, (size_t)len); 209 aux->has_data = 1; 210 } 211 in->extra.aux = aux; 212 } 213 214 static void rec_local_static_data_label_addr(CgTarget* t, Label target, 215 i64 addend, u32 width, 216 u32 address_space) { 217 CgIrRecorder* r = rec_of(t); 218 CgIrInst* in = emit(r, CG_IR_LOCAL_STATIC_DATA_LABEL_ADDR); 219 CgIrLocalStaticLabelAux* aux = AUX_NEW(r, CgIrLocalStaticLabelAux); 220 aux->target = target; 221 aux->addend = addend; 222 aux->width = width; 223 aux->address_space = address_space; 224 in->extra.aux = aux; 225 } 226 227 static void rec_local_static_data_end(CgTarget* t) { 228 (void)emit(rec_of(t), CG_IR_LOCAL_STATIC_DATA_END); 229 } 230 231 static const char* rec_data_label_addr_unsupported_msg(CgTarget* t) { 232 CgIrRecorder* r = rec_of(t); 233 if (r->data_label_addr_unsupported_msg) 234 return r->data_label_addr_unsupported_msg(r->user); 235 return "IR recorder supports function-local label address data"; 236 } 237 238 /* A target that cannot resolve code-label addresses in static data (it set 239 * data_label_addr_unsupported_msg) likewise cannot build a label-address jump 240 * table; report that so kit_cg_switch routes table plans through switch_. */ 241 static int rec_supports_label_table(CgTarget* t) { 242 CgIrRecorder* r = rec_of(t); 243 return r->data_label_addr_unsupported_msg ? 0 : 1; 244 } 245 246 static CGScope rec_scope_begin(CgTarget* t, const CGScopeDesc* desc) { 247 CgIrRecorder* r = rec_of(t); 248 CgIrInst* in = emit(r, CG_IR_SCOPE_BEGIN); 249 CgIrScopeAux* aux = AUX_NEW(r, CgIrScopeAux); 250 CGScope scope = cg_ir_func_add_scope(require_func(r), desc); 251 aux->scope = scope; 252 aux->desc = *desc; 253 in->extra.aux = aux; 254 return scope; 255 } 256 257 static void rec_scope_id_op(CgTarget* t, CgIrOp op, CGScope scope) { 258 CgIrInst* in = emit(rec_of(t), op); 259 in->extra.imm = (i64)scope; 260 } 261 262 static void rec_scope_end(CgTarget* t, CGScope scope) { 263 rec_scope_id_op(t, CG_IR_SCOPE_END, scope); 264 } 265 266 static void rec_break_to(CgTarget* t, CGScope scope) { 267 rec_scope_id_op(t, CG_IR_BREAK_TO, scope); 268 } 269 270 static void rec_continue_to(CgTarget* t, CGScope scope) { 271 rec_scope_id_op(t, CG_IR_CONTINUE_TO, scope); 272 } 273 274 static void rec_load_imm(CgTarget* t, Operand dst, i64 imm) { 275 CgIrInst* in = emit(rec_of(t), CG_IR_LOAD_IMM); 276 set_ops(rec_of(t), in, &dst, 1); 277 in->extra.imm = imm; 278 } 279 280 static void rec_load_const(CgTarget* t, Operand dst, ConstBytes cbytes) { 281 CgIrRecorder* r = rec_of(t); 282 CgIrInst* in = emit(r, CG_IR_LOAD_CONST); 283 set_ops(r, in, &dst, 1); 284 in->extra.cbytes = cg_ir_dup_const_bytes(require_func(r)->arena, cbytes); 285 } 286 287 static void rec_copy(CgTarget* t, Operand dst, Operand src) { 288 CgIrInst* in = emit(rec_of(t), CG_IR_COPY); 289 Operand ops[2] = {dst, src}; 290 set_ops(rec_of(t), in, ops, 2); 291 } 292 293 /* Bit-fields ride the generic load/store (mem.bf_width != 0); this impl 294 * translates them to the dedicated CG_IR_BITFIELD_LOAD/STORE opcodes. */ 295 static void rec_bitfield_load(CgTarget* t, Operand dst, Operand record_addr, 296 BitFieldAccess access); 297 static void rec_bitfield_store(CgTarget* t, Operand record_addr, Operand src, 298 BitFieldAccess access); 299 300 static void rec_load(CgTarget* t, Operand dst, Operand addr, MemAccess mem) { 301 CgIrInst* in; 302 if (mem.bf_width != 0) { 303 rec_bitfield_load(t, dst, addr, bf_from_mem(mem)); 304 return; 305 } 306 in = emit(rec_of(t), CG_IR_LOAD); 307 Operand ops[2] = {dst, addr}; 308 set_ops(rec_of(t), in, ops, 2); 309 in->extra.mem = mem; 310 } 311 312 static void rec_store(CgTarget* t, Operand addr, Operand src, MemAccess mem) { 313 CgIrInst* in; 314 if (mem.bf_width != 0) { 315 rec_bitfield_store(t, addr, src, bf_from_mem(mem)); 316 return; 317 } 318 in = emit(rec_of(t), CG_IR_STORE); 319 Operand ops[2] = {addr, src}; 320 set_ops(rec_of(t), in, ops, 2); 321 in->extra.mem = mem; 322 } 323 324 static void rec_addr_of(CgTarget* t, Operand dst, Operand lv) { 325 CgIrInst* in = emit(rec_of(t), CG_IR_ADDR_OF); 326 Operand ops[2] = {dst, lv}; 327 set_ops(rec_of(t), in, ops, 2); 328 if (lv.kind == OPK_LOCAL) 329 cg_ir_func_mark_local_address_taken(require_func(rec_of(t)), lv.v.local); 330 } 331 332 static void rec_tls_addr_of(CgTarget* t, Operand dst, ObjSymId sym, 333 i64 addend) { 334 CgIrRecorder* r = rec_of(t); 335 CgIrInst* in = emit(r, CG_IR_TLS_ADDR_OF); 336 CgIrTlsAux* aux = AUX_NEW(r, CgIrTlsAux); 337 aux->sym = sym; 338 aux->addend = addend; 339 set_ops(r, in, &dst, 1); 340 cg_ir_symset_add(r->base.c, &require_func(r)->global_refs, sym); 341 in->extra.aux = aux; 342 } 343 344 static void rec_copy_bytes(CgTarget* t, Operand dst_addr, Operand src_addr, 345 AggregateAccess access) { 346 CgIrRecorder* r = rec_of(t); 347 CgIrInst* in = emit(r, CG_IR_AGG_COPY); 348 CgIrAggAux* aux = AUX_NEW(r, CgIrAggAux); 349 Operand ops[2] = {dst_addr, src_addr}; 350 aux->access = access; 351 set_ops(r, in, ops, 2); 352 in->extra.aux = aux; 353 } 354 355 static void rec_set_bytes(CgTarget* t, Operand dst_addr, Operand byte_value, 356 AggregateAccess access) { 357 CgIrRecorder* r = rec_of(t); 358 CgIrInst* in = emit(r, CG_IR_AGG_SET); 359 CgIrAggAux* aux = AUX_NEW(r, CgIrAggAux); 360 Operand ops[2] = {dst_addr, byte_value}; 361 aux->access = access; 362 set_ops(r, in, ops, 2); 363 in->extra.aux = aux; 364 } 365 366 static void rec_bitfield_load(CgTarget* t, Operand dst, Operand record_addr, 367 BitFieldAccess access) { 368 CgIrRecorder* r = rec_of(t); 369 CgIrInst* in = emit(r, CG_IR_BITFIELD_LOAD); 370 CgIrBitFieldAux* aux = AUX_NEW(r, CgIrBitFieldAux); 371 Operand ops[2] = {dst, record_addr}; 372 aux->access = access; 373 set_ops(r, in, ops, 2); 374 in->extra.aux = aux; 375 } 376 377 static void rec_bitfield_store(CgTarget* t, Operand record_addr, Operand src, 378 BitFieldAccess access) { 379 CgIrRecorder* r = rec_of(t); 380 CgIrInst* in = emit(r, CG_IR_BITFIELD_STORE); 381 CgIrBitFieldAux* aux = AUX_NEW(r, CgIrBitFieldAux); 382 Operand ops[2] = {record_addr, src}; 383 aux->access = access; 384 set_ops(r, in, ops, 2); 385 in->extra.aux = aux; 386 } 387 388 static void rec_binop(CgTarget* t, BinOp op, Operand dst, Operand a, 389 Operand b) { 390 CgIrInst* in = emit(rec_of(t), CG_IR_BINOP); 391 Operand ops[3] = {dst, a, b}; 392 set_ops(rec_of(t), in, ops, 3); 393 in->extra.imm = (i64)op; 394 } 395 396 static void rec_unop(CgTarget* t, UnOp op, Operand dst, Operand a) { 397 CgIrInst* in = emit(rec_of(t), CG_IR_UNOP); 398 Operand ops[2] = {dst, a}; 399 set_ops(rec_of(t), in, ops, 2); 400 in->extra.imm = (i64)op; 401 } 402 403 static void rec_cmp(CgTarget* t, CmpOp op, Operand dst, Operand a, Operand b) { 404 CgIrInst* in = emit(rec_of(t), CG_IR_CMP); 405 Operand ops[3] = {dst, a, b}; 406 set_ops(rec_of(t), in, ops, 3); 407 in->extra.imm = (i64)op; 408 } 409 410 static void rec_convert(CgTarget* t, ConvKind op, Operand dst, Operand src) { 411 CgIrInst* in = emit(rec_of(t), CG_IR_CONVERT); 412 Operand ops[2] = {dst, src}; 413 set_ops(rec_of(t), in, ops, 2); 414 in->extra.imm = (i64)op; 415 } 416 417 static void rec_call(CgTarget* t, const CGCallDesc* desc) { 418 CgIrRecorder* r = rec_of(t); 419 CgIrInst* in = emit(r, CG_IR_CALL); 420 CgIrCallAux* aux = AUX_NEW(r, CgIrCallAux); 421 aux->desc = cg_ir_dup_call_desc(require_func(r)->arena, desc); 422 note_global_ref(r, desc->callee); 423 if (desc->callee.kind == OPK_GLOBAL && desc->callee.v.global.addend == 0) { 424 cg_ir_symset_add(r->base.c, &require_func(r)->call_refs, 425 desc->callee.v.global.sym); 426 } 427 in->extra.aux = aux; 428 } 429 430 static const char* rec_tail_call_unrealizable_reason(CgTarget* t, 431 const CGCallDesc* desc) { 432 CgIrRecorder* r = rec_of(t); 433 if (r->tail_call_unrealizable_reason) { 434 CgIrFunc* f = require_func(r); 435 return r->tail_call_unrealizable_reason(r->user, &f->desc, desc); 436 } 437 return NULL; 438 } 439 440 static void rec_ret(CgTarget* t, CGLocal value) { 441 CgIrRecorder* r = rec_of(t); 442 CgIrInst* in = emit(r, CG_IR_RET); 443 CgIrRetAux* aux = AUX_NEW(r, CgIrRetAux); 444 aux->value = value; 445 aux->present = value != CG_LOCAL_NONE; 446 in->extra.aux = aux; 447 } 448 449 static void rec_unreachable(CgTarget* t) { 450 (void)emit(rec_of(t), CG_IR_UNREACHABLE); 451 } 452 453 static void rec_alloca(CgTarget* t, Operand dst, Operand size, u32 align) { 454 CgIrInst* in = emit(rec_of(t), CG_IR_ALLOCA); 455 Operand ops[2] = {dst, size}; 456 set_ops(rec_of(t), in, ops, 2); 457 in->extra.imm = (i64)align; 458 } 459 460 static void rec_va_start(CgTarget* t, Operand ap_addr) { 461 CgIrInst* in = emit(rec_of(t), CG_IR_VA_START); 462 set_ops(rec_of(t), in, &ap_addr, 1); 463 } 464 465 static void rec_va_arg(CgTarget* t, Operand dst, Operand ap_addr, 466 KitCgTypeId type) { 467 CgIrInst* in = emit(rec_of(t), CG_IR_VA_ARG); 468 Operand ops[2] = {dst, ap_addr}; 469 set_ops(rec_of(t), in, ops, 2); 470 in->extra.imm = (i64)type; 471 } 472 473 static void rec_va_end(CgTarget* t, Operand ap_addr) { 474 CgIrInst* in = emit(rec_of(t), CG_IR_VA_END); 475 set_ops(rec_of(t), in, &ap_addr, 1); 476 } 477 478 static void rec_va_copy(CgTarget* t, Operand dst_ap_addr, Operand src_ap_addr) { 479 CgIrInst* in = emit(rec_of(t), CG_IR_VA_COPY); 480 Operand ops[2] = {dst_ap_addr, src_ap_addr}; 481 set_ops(rec_of(t), in, ops, 2); 482 } 483 484 static void rec_atomic_load(CgTarget* t, Operand dst, Operand addr, 485 MemAccess mem, KitCgMemOrder order) { 486 CgIrRecorder* r = rec_of(t); 487 CgIrInst* in = emit(r, CG_IR_ATOMIC_LOAD); 488 CgIrAtomicAux* aux = AUX_NEW(r, CgIrAtomicAux); 489 Operand ops[2] = {dst, addr}; 490 aux->mem = mem; 491 aux->order = order; 492 set_ops(r, in, ops, 2); 493 in->extra.aux = aux; 494 } 495 496 static void rec_atomic_store(CgTarget* t, Operand addr, Operand src, 497 MemAccess mem, KitCgMemOrder order) { 498 CgIrRecorder* r = rec_of(t); 499 CgIrInst* in = emit(r, CG_IR_ATOMIC_STORE); 500 CgIrAtomicAux* aux = AUX_NEW(r, CgIrAtomicAux); 501 Operand ops[2] = {addr, src}; 502 aux->mem = mem; 503 aux->order = order; 504 set_ops(r, in, ops, 2); 505 in->extra.aux = aux; 506 } 507 508 static void rec_atomic_rmw(CgTarget* t, KitCgAtomicOp op, Operand dst, 509 Operand addr, Operand val, MemAccess mem, 510 KitCgMemOrder order) { 511 CgIrRecorder* r = rec_of(t); 512 CgIrInst* in = emit(r, CG_IR_ATOMIC_RMW); 513 CgIrAtomicAux* aux = AUX_NEW(r, CgIrAtomicAux); 514 Operand ops[3] = {dst, addr, val}; 515 aux->mem = mem; 516 aux->order = order; 517 aux->op = op; 518 set_ops(r, in, ops, 3); 519 in->extra.aux = aux; 520 } 521 522 static void rec_atomic_cas(CgTarget* t, Operand prior, Operand ok, Operand addr, 523 Operand expected, Operand desired, MemAccess mem, 524 KitCgMemOrder success, KitCgMemOrder failure) { 525 CgIrRecorder* r = rec_of(t); 526 CgIrInst* in = emit(r, CG_IR_ATOMIC_CAS); 527 CgIrAtomicAux* aux = AUX_NEW(r, CgIrAtomicAux); 528 Operand ops[5] = {prior, ok, addr, expected, desired}; 529 aux->mem = mem; 530 aux->order = success; 531 aux->failure = failure; 532 set_ops(r, in, ops, 5); 533 in->extra.aux = aux; 534 } 535 536 static void rec_fence(CgTarget* t, KitCgMemOrder order) { 537 CgIrInst* in = emit(rec_of(t), CG_IR_FENCE); 538 in->extra.imm = (i64)order; 539 } 540 541 static void rec_intrinsic(CgTarget* t, IntrinKind kind, Operand* dsts, u32 ndst, 542 const Operand* args, u32 narg) { 543 CgIrRecorder* r = rec_of(t); 544 CgIrInst* in = emit(r, CG_IR_INTRINSIC); 545 CgIrIntrinsicAux* aux = AUX_NEW(r, CgIrIntrinsicAux); 546 aux->kind = kind; 547 aux->dsts = cg_ir_dup_operands(require_func(r)->arena, dsts, ndst); 548 aux->args = cg_ir_dup_operands(require_func(r)->arena, args, narg); 549 aux->ndst = ndst; 550 aux->narg = narg; 551 note_global_refs(r, dsts, ndst); 552 note_global_refs(r, args, narg); 553 in->extra.aux = aux; 554 } 555 556 static int rec_asm_is_reg_constraint(CgTarget* t, const char* constraint) { 557 CgIrRecorder* r = rec_of(t); 558 if (!r->asm_is_reg_constraint) return 0; 559 return r->asm_is_reg_constraint(r->user, constraint); 560 } 561 562 static void rec_asm_block(CgTarget* t, const char* tmpl, 563 const AsmConstraint* outs, u32 nout, Operand* out_ops, 564 const AsmConstraint* ins, u32 nin, 565 const Operand* in_ops, const Sym* clobbers, u32 nclob, 566 u32 clobber_abi_sets) { 567 CgIrRecorder* r = rec_of(t); 568 CgIrFunc* f = require_func(r); 569 CgIrInst* in = emit(r, CG_IR_ASM_BLOCK); 570 CgIrAsmAux* aux = AUX_NEW(r, CgIrAsmAux); 571 aux->tmpl = cg_ir_dup_cstr(f->arena, tmpl); 572 aux->outs = cg_ir_dup_asm_constraints(f->arena, outs, nout); 573 aux->out_ops = cg_ir_dup_operands(f->arena, out_ops, nout); 574 aux->ins = cg_ir_dup_asm_constraints(f->arena, ins, nin); 575 aux->in_ops = cg_ir_dup_operands(f->arena, in_ops, nin); 576 note_global_refs(r, out_ops, nout); 577 note_global_refs(r, in_ops, nin); 578 if (nclob) { 579 aux->clobbers = arena_array(f->arena, Sym, nclob); 580 memcpy(aux->clobbers, clobbers, sizeof(*aux->clobbers) * nclob); 581 } 582 aux->nout = nout; 583 aux->nin = nin; 584 aux->nclob = nclob; 585 aux->clobber_abi_sets = clobber_abi_sets; 586 in->extra.aux = aux; 587 } 588 589 static void rec_file_scope_asm(CgTarget* t, const char* src, size_t len) { 590 CgIrRecorder* r = rec_of(t); 591 cg_ir_module_add_file_scope_asm(r->module, src, len); 592 } 593 594 static void rec_set_loc(CgTarget* t, SrcLoc loc) { rec_of(t)->loc = loc; } 595 596 static void rec_finalize(CgTarget* t) { 597 CgIrRecorder* r = rec_of(t); 598 if (r->cur) rec_panic(r, "finalize with open function"); 599 if (r->finalize_recorded) r->finalize_recorded(r->user, r->module); 600 } 601 602 static void rec_destroy(CgTarget* t) { 603 CgIrRecorder* r = rec_of(t); 604 if (r->destroy_user) r->destroy_user(r->user); 605 cg_ir_module_refsets_fini(r->module); 606 } 607 608 CgTarget* cg_ir_recorder_new(Compiler* c, ObjBuilder* obj, 609 const CgIrRecorderConfig* cfg) { 610 CgIrRecorder* r; 611 if (!c) return NULL; 612 r = arena_znew(c->tu, CgIrRecorder); 613 if (!r) return NULL; 614 r->base.c = c; 615 r->base.obj = obj; 616 r->magic = CG_IR_RECORDER_MAGIC; 617 r->module = cg_ir_module_new(c); 618 if (!r->module) return NULL; 619 if (cfg) { 620 r->func_recorded = cfg->func_recorded; 621 r->finalize_recorded = cfg->finalize; 622 r->destroy_user = cfg->destroy; 623 r->local_static_data_begin = cfg->local_static_data_begin; 624 r->data_label_addr_unsupported_msg = cfg->data_label_addr_unsupported_msg; 625 r->tail_call_unrealizable_reason = cfg->tail_call_unrealizable_reason; 626 r->asm_is_reg_constraint = cfg->asm_is_reg_constraint; 627 r->user = cfg->user; 628 } 629 630 r->base.func_begin = rec_func_begin; 631 r->base.func_end = rec_func_end; 632 r->base.alias = rec_alias; 633 r->base.local = rec_local; 634 r->base.local_addr = rec_local_addr; 635 r->base.param = rec_param; 636 r->base.label_new = rec_label_new; 637 r->base.label_place = rec_label_place; 638 r->base.jump = rec_jump; 639 r->base.cmp_branch = rec_cmp_branch; 640 r->base.switch_ = rec_switch; 641 r->base.supports_label_table = rec_supports_label_table; 642 r->base.indirect_branch = rec_indirect_branch; 643 r->base.load_label_addr = rec_load_label_addr; 644 r->base.local_static_data_begin = rec_local_static_data_begin; 645 r->base.local_static_data_write = rec_local_static_data_write; 646 r->base.local_static_data_label_addr = rec_local_static_data_label_addr; 647 r->base.local_static_data_end = rec_local_static_data_end; 648 r->base.data_label_addr_unsupported_msg = rec_data_label_addr_unsupported_msg; 649 r->base.scope_begin = rec_scope_begin; 650 r->base.scope_end = rec_scope_end; 651 r->base.break_to = rec_break_to; 652 r->base.continue_to = rec_continue_to; 653 r->base.load_imm = rec_load_imm; 654 r->base.load_const = rec_load_const; 655 r->base.copy = rec_copy; 656 r->base.load = rec_load; 657 r->base.store = rec_store; 658 r->base.addr_of = rec_addr_of; 659 r->base.tls_addr_of = rec_tls_addr_of; 660 r->base.copy_bytes = rec_copy_bytes; 661 r->base.set_bytes = rec_set_bytes; 662 r->base.binop = rec_binop; 663 r->base.unop = rec_unop; 664 r->base.cmp = rec_cmp; 665 r->base.convert = rec_convert; 666 r->base.call = rec_call; 667 r->base.tail_call_unrealizable_reason = rec_tail_call_unrealizable_reason; 668 r->base.ret = rec_ret; 669 r->base.unreachable = rec_unreachable; 670 r->base.alloca_ = rec_alloca; 671 r->base.va_start_ = rec_va_start; 672 r->base.va_arg_ = rec_va_arg; 673 r->base.va_end_ = rec_va_end; 674 r->base.va_copy_ = rec_va_copy; 675 r->base.atomic_load = rec_atomic_load; 676 r->base.atomic_store = rec_atomic_store; 677 r->base.atomic_rmw = rec_atomic_rmw; 678 r->base.atomic_cas = rec_atomic_cas; 679 r->base.fence = rec_fence; 680 r->base.intrinsic = rec_intrinsic; 681 r->base.asm_is_reg_constraint = rec_asm_is_reg_constraint; 682 r->base.asm_block = rec_asm_block; 683 r->base.file_scope_asm = rec_file_scope_asm; 684 r->base.set_loc = rec_set_loc; 685 r->base.finalize = rec_finalize; 686 r->base.destroy = rec_destroy; 687 return &r->base; 688 } 689 690 CgIrRecorder* cg_ir_recorder_from_target(CgTarget* t) { 691 CgIrRecorder* r = t ? rec_of(t) : NULL; 692 return r && r->magic == CG_IR_RECORDER_MAGIC ? r : NULL; 693 } 694 695 void* cg_ir_recorder_user(const CgIrRecorder* r) { return r ? r->user : NULL; } 696 697 const CgIrModule* cg_ir_recorder_module(const CgTarget* t) { 698 const CgIrRecorder* r = (const CgIrRecorder*)t; 699 return r && r->magic == CG_IR_RECORDER_MAGIC ? r->module : NULL; 700 } 701 702 CgIrFunc* cg_ir_recorder_current_func(const CgTarget* t) { 703 const CgIrRecorder* r = (const CgIrRecorder*)t; 704 return r && r->magic == CG_IR_RECORDER_MAGIC ? r->cur : NULL; 705 }