commit cb0a4c2eaa613a365372d11eeaf259f237a92435
parent 3f68896d566b03a54d6e2ef0887f8c6c38a8fce0
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Sat, 13 Jun 2026 01:18:03 -0700
perf(mc): devirtualize MCEmitter — direct calls, drop the fake vtable (F2)
MCEmitter has exactly one implementation (mc.c serves every arch; arch-specific
behavior enters only via ArchImpl), so its 16 per-instance function pointers
were pure indirection across ~386 call sites with zero polymorphism. Replace
them with extern mc_* functions called directly by the arch backends, and drop
the pointers from the struct. The always-true CFI-slot guards (the slots were
set unconditionally in mc_new) become unconditional calls.
Deliberately NOT static inline: inlining the hot emit_bytes/pos into the
per-arch leaf emitters bloats them enough to disrupt the inliner's own cascade
(measured a net +21M instructions on sqlite -c); a direct call to an
out-of-line body removes the indirect call + fn-ptr load without that effect.
NativeTarget stays a real per-arch vtable (aa64/x64/rv64) — only the
monomorphic MCEmitter layer is devirtualized.
Measured in isolation (sqlite3.c, best-of-7, byte-identical objects): -c
2153.0M -> 2151.8M (-1.2M); -fsyntax-only flat (MCEmitter unused there).
Cumulative D6+F1+F2: 2160.7M -> 2151.8M (-8.9M, -0.41%).
Gate: perf_identity_gate.sh 60/60 byte-identical (measured on a clean F1+F2
build, isolated from unrelated in-tree WIP).
Diffstat:
13 files changed, 474 insertions(+), 505 deletions(-)
diff --git a/src/arch/aa64/asm.c b/src/arch/aa64/asm.c
@@ -535,7 +535,7 @@ static void emit32(AsmDriver* d, u32 word) {
buf[1] = (u8)((word >> 8) & 0xff);
buf[2] = (u8)((word >> 16) & 0xff);
buf[3] = (u8)((word >> 24) & 0xff);
- mc->emit_bytes(mc, buf, 4);
+ mc_emit_bytes(mc, buf, 4);
}
static int parse_cond_from_ident(AsmDriver* d, Sym ident, u32* out) {
@@ -898,7 +898,7 @@ static void p_addsub(AsmDriver* d, int is_sub, int set_flags) {
.Rd = rd.num});
emit32(d, word);
MCEmitter* mc = asm_driver_mc(d);
- mc->emit_reloc_at(mc, asm_driver_cur_section(d), mc->pos(mc) - 4,
+ mc_emit_reloc_at(mc, asm_driver_cur_section(d), mc_pos(mc) - 4,
R_AARCH64_ADD_ABS_LO12_NC, sym, off, 1, 0);
return;
}
@@ -1238,10 +1238,10 @@ static void emit_branch_imm(AsmDriver* d, u32 op_bl, ObjSymId target,
* either the symbol or the constant displacement. */
u32 word = aa64_brimm_pack((AA64BrImm){.op = op_bl, .imm26 = 0});
emit32(d, word);
- u32 ofs = mc->pos(mc) - 4;
+ u32 ofs = mc_pos(mc) - 4;
RelocKind k = op_bl ? R_AARCH64_CALL26 : R_AARCH64_JUMP26;
if (target != OBJ_SYM_NONE) {
- mc->emit_reloc_at(mc, asm_driver_cur_section(d), ofs, k, target, addend, 1,
+ mc_emit_reloc_at(mc, asm_driver_cur_section(d), ofs, k, target, addend, 1,
0);
} else {
/* Pure constant displacement is rare in real .s; reject it now.
@@ -1272,8 +1272,8 @@ static void p_b_cond(AsmDriver* d, u32 cond) {
u32 word = aa64_brcond_pack((AA64BrCond){.imm19 = 0, .cond = cond});
emit32(d, word);
MCEmitter* mc = asm_driver_mc(d);
- u32 ofs = mc->pos(mc) - 4;
- mc->emit_reloc_at(mc, asm_driver_cur_section(d), ofs, R_AARCH64_CONDBR19, sym,
+ u32 ofs = mc_pos(mc) - 4;
+ mc_emit_reloc_at(mc, asm_driver_cur_section(d), ofs, R_AARCH64_CONDBR19, sym,
off, 1, 0);
}
@@ -1289,8 +1289,8 @@ static void p_cbz(AsmDriver* d, u32 op) {
aa64_cb_pack((AA64CB){.sf = rt.is64, .op = op, .imm19 = 0, .Rt = rt.num});
emit32(d, word);
MCEmitter* mc = asm_driver_mc(d);
- u32 ofs = mc->pos(mc) - 4;
- mc->emit_reloc_at(mc, asm_driver_cur_section(d), ofs, R_AARCH64_CONDBR19, sym,
+ u32 ofs = mc_pos(mc) - 4;
+ mc_emit_reloc_at(mc, asm_driver_cur_section(d), ofs, R_AARCH64_CONDBR19, sym,
off, 1, 0);
}
@@ -1458,7 +1458,7 @@ static void p_ldst_core(AsmDriver* d, int is_load, int fixed_size,
? R_AARCH64_LD64_GOT_LO12_NC
: aa64_ldst_lo12_reloc(d, size);
MCEmitter* mc = asm_driver_mc(d);
- mc->emit_reloc_at(mc, asm_driver_cur_section(d), mc->pos(mc) - 4, k,
+ mc_emit_reloc_at(mc, asm_driver_cur_section(d), mc_pos(mc) - 4, k,
m.reloc_sym, m.reloc_off, 1, 0);
return;
}
@@ -1638,11 +1638,11 @@ static void p_adr(AsmDriver* d, int is_adrp) {
.Rd = rd.num};
emit32(d, aa64_pcrel_adr_pack(f));
MCEmitter* mc = asm_driver_mc(d);
- u32 ofs = mc->pos(mc) - 4;
+ u32 ofs = mc_pos(mc) - 4;
RelocKind k = !is_adrp ? R_AARCH64_ADR_PREL_LO21
: mod == AA64_RELMOD_GOT ? R_AARCH64_ADR_GOT_PAGE
: R_AARCH64_ADR_PREL_PG_HI21;
- mc->emit_reloc_at(mc, asm_driver_cur_section(d), ofs, k, sym, off, 1, 0);
+ mc_emit_reloc_at(mc, asm_driver_cur_section(d), ofs, k, sym, off, 1, 0);
}
/* ---- atomics / exclusive ----
diff --git a/src/arch/aa64/native.c b/src/arch/aa64/native.c
@@ -333,10 +333,10 @@ static void aa_emit32(MCEmitter* mc, u32 word) {
* skip it on the common no-debug compile (one fewer lookup per instruction). */
if (mc->debug) {
u32 ofs = obj_pos(mc->obj, mc->section_id);
- mc->emit_bytes(mc, b, sizeof b);
+ mc_emit_bytes(mc, b, sizeof b);
debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
} else {
- mc->emit_bytes(mc, b, sizeof b);
+ mc_emit_bytes(mc, b, sizeof b);
}
}
@@ -794,14 +794,14 @@ static void aa_emit_mem(AANativeTarget* a, int load, NativeLoc reg,
addr.index_kind == NATIVE_ADDR_INDEX_NONE) {
i64 addend = addr.base.global.addend + (i64)addr.offset;
u32 scratch = (!load && rt == AA_TMP0) ? AA_TMP1 : AA_TMP0;
- u32 pos = mc->pos(mc);
+ u32 pos = mc_pos(mc);
if (aa_use_got_for_sym(&a->base, addr.base.global.sym)) {
aa_emit32(mc, aa64_adrp(scratch, 0, 0));
- mc->emit_reloc_at(mc, mc->section_id, pos, R_AARCH64_ADR_GOT_PAGE,
+ mc_emit_reloc_at(mc, mc->section_id, pos, R_AARCH64_ADR_GOT_PAGE,
addr.base.global.sym, 0, 0, 0);
- pos = mc->pos(mc);
+ pos = mc_pos(mc);
aa_emit32(mc, aa_ldr_uimm(3, scratch, scratch, 0));
- mc->emit_reloc_at(mc, mc->section_id, pos, R_AARCH64_LD64_GOT_LO12_NC,
+ mc_emit_reloc_at(mc, mc->section_id, pos, R_AARCH64_LD64_GOT_LO12_NC,
addr.base.global.sym, 0, 0, 0);
if (addend) aa_emit_add_i64(a, scratch, scratch, addend);
aa_emit32(mc, load
@@ -810,13 +810,13 @@ static void aa_emit_mem(AANativeTarget* a, int load, NativeLoc reg,
return;
}
aa_emit32(mc, aa64_adrp(scratch, 0, 0));
- mc->emit_reloc_at(mc, mc->section_id, pos, R_AARCH64_ADR_PREL_PG_HI21,
+ mc_emit_reloc_at(mc, mc->section_id, pos, R_AARCH64_ADR_PREL_PG_HI21,
addr.base.global.sym, addend, 0, 0);
- pos = mc->pos(mc);
+ pos = mc_pos(mc);
aa_emit32(mc,
load ? aa_ldr_uimm_v(sz, native_loc_is_fp(reg), rt, scratch, 0)
: aa_str_uimm_v(sz, native_loc_is_fp(reg), rt, scratch, 0));
- mc->emit_reloc_at(mc, mc->section_id, pos, aa_ldst_reloc_for_size(sz),
+ mc_emit_reloc_at(mc, mc->section_id, pos, aa_ldst_reloc_for_size(sz),
addr.base.global.sym, addend, 0, 0);
return;
}
@@ -1143,14 +1143,14 @@ static void aa_func_begin_common(NativeTarget* t, const CGFuncDesc* fd) {
? vai.gp_reg_count * vai.gp_slot_size
: 0u;
}
- mc->set_section(mc, fd->text_section_id);
- mc->emit_align(mc, 4, 0);
- a->func_start = mc->pos(mc);
+ mc_set_section(mc, fd->text_section_id);
+ mc_emit_align(mc, 4, 0);
+ a->func_start = mc_pos(mc);
mc_begin_function(mc, fd->sym, fd->text_section_id, a->func_start);
- if (mc->cfi_startproc) mc->cfi_startproc(mc);
- a->prologue_pos = mc->pos(mc);
+ mc_cfi_startproc(mc);
+ a->prologue_pos = mc_pos(mc);
a->minimal_prologue_words = 0;
- a->epilogue_label = mc->label_new(mc);
+ a->epilogue_label = mc_label_new(mc);
}
/* Single-pass (NativeDirectTarget) entry point: the frame is not known up
@@ -1175,18 +1175,18 @@ static void aa_func_begin(NativeTarget* t, const CGFuncDesc* fd) {
* aa_func_end. The region starts here; record it for the patch and CFI. */
region = abi_stack_probe_interval(a->base.c->abi) ? AA_NDT_SUB_WORDS
: AA_NDT_SUB_WORDS_NOPROBE;
- a->prologue_pos = mc->pos(mc);
+ a->prologue_pos = mc_pos(mc);
a->prologue_region_words = region;
{
u8 nops[AA_NDT_SUB_WORDS * 4u];
for (u32 i = 0; i < region; ++i) wr_u32_le(nops + i * 4u, 0xd503201fu);
if (mc->debug) {
u32 ofs = obj_pos(mc->obj, mc->section_id);
- mc->emit_bytes(mc, nops, region * 4u);
+ mc_emit_bytes(mc, nops, region * 4u);
for (u32 i = 0; i < region; ++i)
debug_emit_row(mc->debug, mc->section_id, ofs + i * 4u, mc->loc);
} else {
- mc->emit_bytes(mc, nops, region * 4u);
+ mc_emit_bytes(mc, nops, region * 4u);
}
}
aa_emit_entry_saves(a);
@@ -1650,7 +1650,7 @@ static void aa_func_end(NativeTarget* t) {
a->frame.known_frame
? a->minimal_prologue_words
: (AA_NDT_FIXED_ENTRY_WORDS + a->prologue_region_words);
- mc->label_place(mc, a->epilogue_label);
+ mc_label_place(mc, a->epilogue_label);
aa_emit_callee_restores(a);
aa_emit_restore_frame(a, &L);
aa_emit32(mc, aa64_ret(AA_LR));
@@ -1663,29 +1663,29 @@ static void aa_func_end(NativeTarget* t) {
aa_patch_prologue(a, &L);
aa_apply_patches(a, &L);
}
- if (mc->cfi_set_next_pc_offset && mc->cfi_def_cfa && mc->cfi_offset) {
+ {
i32 cfa = aa_cfa_off(a);
- mc->cfi_set_next_pc_offset(mc, prologue_advance_words * 4u);
+ mc_cfi_set_next_pc_offset(mc, prologue_advance_words * 4u);
/* CFA = caller's sp, an fp-relative offset that depends on the layout:
* fp+16 (top-record) or fp+frame_size (bottom-record). saved fp/lr live at
* [fp]/[fp+8] in both, hence at CFA-cfa / CFA-cfa+8. */
- mc->cfi_def_cfa(mc, AA_FP, cfa);
- mc->cfi_offset(mc, AA_FP, aa_fp_off_saved_fp() - cfa);
- mc->cfi_offset(mc, AA_LR, aa_fp_off_saved_lr() - cfa);
+ mc_cfi_def_cfa(mc, AA_FP, cfa);
+ mc_cfi_offset(mc, AA_FP, aa_fp_off_saved_fp() - cfa);
+ mc_cfi_offset(mc, AA_LR, aa_fp_off_saved_lr() - cfa);
}
obj_symbol_define(t->obj, a->func->sym, a->func->text_section_id,
- a->func_start, mc->pos(mc) - a->func_start);
+ a->func_start, mc_pos(mc) - a->func_start);
if (a->func->atomize) {
obj_atom_define(t->obj, a->func->text_section_id, a->func_start,
- mc->pos(mc) - a->func_start, a->func->sym, 0);
+ mc_pos(mc) - a->func_start, a->func->sym, 0);
}
/* Hand the function's PC range to the Debug producer so its line program
* (and DW_AT_low_pc/high_pc) cover this function — emit_section_line skips
* functions without a recorded range. */
if (mc->debug)
debug_func_pc_range(mc->debug, a->func->text_section_id, a->func_start,
- mc->pos(mc));
- if (mc->cfi_endproc) mc->cfi_endproc(mc);
+ mc_pos(mc));
+ mc_cfi_endproc(mc);
mc_end_function(mc);
a->func = NULL;
}
@@ -1853,15 +1853,15 @@ static void aa_reload(NativeTarget* t, NativeLoc dst, NativeFrameSlot slot,
aa_emit_mem(aa_of(t), 1, dst, addr, mem);
}
-static MCLabel aa_label_new(NativeTarget* t) { return t->mc->label_new(t->mc); }
+static MCLabel aa_label_new(NativeTarget* t) { return mc_label_new(t->mc); }
static void aa_label_place(NativeTarget* t, MCLabel label) {
- t->mc->label_place(t->mc, label);
+ mc_label_place(t->mc, label);
}
static void aa_jump(NativeTarget* t, MCLabel label) {
aa_emit32(t->mc, aa64_b(0));
- t->mc->emit_label_ref(t->mc, label, R_AARCH64_JUMP26, 4, 0);
+ mc_emit_label_ref(t->mc, label, R_AARCH64_JUMP26, 4, 0);
}
static void aa_cmp_branch(NativeTarget* t, CmpOp op, NativeLoc lhs,
@@ -1872,21 +1872,21 @@ static void aa_cmp_branch(NativeTarget* t, CmpOp op, NativeLoc lhs,
if (op == CMP_ONE_F) {
/* ordered & !=: branch if a<b (MI) or a>b (GT). */
aa_emit32(t->mc, aa64_brcond_pack((AA64BrCond){.cond = 0x4u})); /* MI */
- t->mc->emit_label_ref(t->mc, label, R_AARCH64_CONDBR19, 4, 0);
+ mc_emit_label_ref(t->mc, label, R_AARCH64_CONDBR19, 4, 0);
aa_emit32(t->mc, aa64_brcond_pack((AA64BrCond){.cond = 0xcu})); /* GT */
- t->mc->emit_label_ref(t->mc, label, R_AARCH64_CONDBR19, 4, 0);
+ mc_emit_label_ref(t->mc, label, R_AARCH64_CONDBR19, 4, 0);
return;
}
if (op == CMP_UEQ_F) {
/* unordered | ==: branch if a==b (EQ) or unordered (VS). */
aa_emit32(t->mc, aa64_brcond_pack((AA64BrCond){.cond = 0x0u})); /* EQ */
- t->mc->emit_label_ref(t->mc, label, R_AARCH64_CONDBR19, 4, 0);
+ mc_emit_label_ref(t->mc, label, R_AARCH64_CONDBR19, 4, 0);
aa_emit32(t->mc, aa64_brcond_pack((AA64BrCond){.cond = 0x6u})); /* VS */
- t->mc->emit_label_ref(t->mc, label, R_AARCH64_CONDBR19, 4, 0);
+ mc_emit_label_ref(t->mc, label, R_AARCH64_CONDBR19, 4, 0);
return;
}
aa_emit32(t->mc, aa64_brcond_pack((AA64BrCond){.cond = cmp_cond(op)}));
- t->mc->emit_label_ref(t->mc, label, R_AARCH64_CONDBR19, 4, 0);
+ mc_emit_label_ref(t->mc, label, R_AARCH64_CONDBR19, 4, 0);
}
static void aa_indirect_branch(NativeTarget* t, NativeLoc addr,
@@ -1905,13 +1905,13 @@ static void aa_load_label_addr(NativeTarget* t, NativeLoc dst, MCLabel target) {
MCEmitter* mc = t->mc;
u32 rd = loc_reg(dst);
ObjSymId sym = mc_label_symbol(mc, target);
- u32 pos = mc->pos(mc);
+ u32 pos = mc_pos(mc);
aa_emit32(mc, aa64_adrp(rd, 0, 0));
- mc->emit_reloc_at(mc, mc->section_id, pos, R_AARCH64_ADR_PREL_PG_HI21, sym, 0,
+ mc_emit_reloc_at(mc, mc->section_id, pos, R_AARCH64_ADR_PREL_PG_HI21, sym, 0,
0, 0);
- pos = mc->pos(mc);
+ pos = mc_pos(mc);
aa_emit32(mc, aa64_add_imm(1, rd, rd, 0, 0));
- mc->emit_reloc_at(mc, mc->section_id, pos, R_AARCH64_ADD_ABS_LO12_NC, sym, 0,
+ mc_emit_reloc_at(mc, mc->section_id, pos, R_AARCH64_ADD_ABS_LO12_NC, sym, 0,
0, 0);
}
@@ -2001,15 +2001,15 @@ static void aa_load_addr(NativeTarget* t, NativeLoc dst, NativeAddr addr) {
return;
case NATIVE_ADDR_BASE_GLOBAL: {
i64 addend = addr.base.global.addend + (i64)addr.offset;
- u32 pos = t->mc->pos(t->mc);
+ u32 pos = mc_pos(t->mc);
if (aa_use_got_for_sym(t, addr.base.global.sym)) {
aa_emit32(t->mc, aa64_adrp(rd, 0, 0));
- t->mc->emit_reloc_at(t->mc, t->mc->section_id, pos,
+ mc_emit_reloc_at(t->mc, t->mc->section_id, pos,
R_AARCH64_ADR_GOT_PAGE, addr.base.global.sym, 0, 0,
0);
- pos = t->mc->pos(t->mc);
+ pos = mc_pos(t->mc);
aa_emit32(t->mc, aa_ldr_uimm(3, rd, rd, 0));
- t->mc->emit_reloc_at(t->mc, t->mc->section_id, pos,
+ mc_emit_reloc_at(t->mc, t->mc->section_id, pos,
R_AARCH64_LD64_GOT_LO12_NC, addr.base.global.sym,
0, 0, 0);
if (addend) aa_emit_add_i64(a, rd, rd, addend);
@@ -2017,12 +2017,12 @@ static void aa_load_addr(NativeTarget* t, NativeLoc dst, NativeAddr addr) {
return;
}
aa_emit32(t->mc, aa64_adrp(rd, 0, 0));
- t->mc->emit_reloc_at(t->mc, t->mc->section_id, pos,
+ mc_emit_reloc_at(t->mc, t->mc->section_id, pos,
R_AARCH64_ADR_PREL_PG_HI21, addr.base.global.sym,
addend, 0, 0);
- pos = t->mc->pos(t->mc);
+ pos = mc_pos(t->mc);
aa_emit32(t->mc, aa64_add_imm(1, rd, rd, 0, 0));
- t->mc->emit_reloc_at(t->mc, t->mc->section_id, pos,
+ mc_emit_reloc_at(t->mc, t->mc->section_id, pos,
R_AARCH64_ADD_ABS_LO12_NC, addr.base.global.sym,
addend, 0, 0);
aa_apply_index(a, rd, &addr);
@@ -2070,25 +2070,25 @@ static void aa_tls_addr_of_win(NativeTarget* t, NativeLoc dst, ObjSymId sym,
/* (1) rd = TEB.ThreadLocalStoragePointer. */
aa_emit32(mc, aa_ldr_uimm(3, rd, AA_WIN_TEB_REG, AA_WIN_TEB_TLS_PTR_OFF));
/* (2)+(3) x16 = &_tls_index via ADRP + ADD. */
- pos = mc->pos(mc);
+ pos = mc_pos(mc);
aa_emit32(mc, aa64_adrp(AA_TMP0, 0, 0));
- mc->emit_reloc_at(mc, sec, pos, R_AARCH64_ADR_PREL_PG_HI21, idx_sym, 0, 0, 0);
- pos = mc->pos(mc);
+ mc_emit_reloc_at(mc, sec, pos, R_AARCH64_ADR_PREL_PG_HI21, idx_sym, 0, 0, 0);
+ pos = mc_pos(mc);
aa_emit32(mc, aa64_add_imm(1, AA_TMP0, AA_TMP0, 0, 0));
- mc->emit_reloc_at(mc, sec, pos, R_AARCH64_ADD_ABS_LO12_NC, idx_sym, 0, 0, 0);
+ mc_emit_reloc_at(mc, sec, pos, R_AARCH64_ADD_ABS_LO12_NC, idx_sym, 0, 0, 0);
/* (4) w16 = _tls_index (the loaded value). */
aa_emit32(mc, aa_ldr_uimm(2, AA_TMP0, AA_TMP0, 0));
/* (5) rd = TLS array slot for this module: ldr rd, [rd, x16, lsl #3]. */
aa_emit32(mc, aa_ldst_regoff_v(3, 0, 1, rd, rd, AA_TMP0, 1));
/* (6) rd += :secrel_hi12:sym (ADD with sh=1; linker patches imm12). */
- pos = mc->pos(mc);
+ pos = mc_pos(mc);
aa_emit32(mc, aa64_add_imm(1, rd, rd, 0, 1));
- mc->emit_reloc_at(mc, sec, pos, R_COFF_AARCH64_SECREL_HIGH12A, sym, addend, 1,
+ mc_emit_reloc_at(mc, sec, pos, R_COFF_AARCH64_SECREL_HIGH12A, sym, addend, 1,
0);
/* (7) rd += :secrel_lo12:sym (ADD with sh=0). */
- pos = mc->pos(mc);
+ pos = mc_pos(mc);
aa_emit32(mc, aa64_add_imm(1, rd, rd, 0, 0));
- mc->emit_reloc_at(mc, sec, pos, R_COFF_AARCH64_SECREL_LOW12A, sym, addend, 1,
+ mc_emit_reloc_at(mc, sec, pos, R_COFF_AARCH64_SECREL_LOW12A, sym, addend, 1,
0);
}
@@ -2100,12 +2100,12 @@ static void aa_tls_addr_of(NativeTarget* t, NativeLoc dst, ObjSymId sym,
u32 pos;
if (obj_format_tls_via_descriptor(t->c)) {
aa_emit32(mc, aa64_adrp(0, 0, 0));
- pos = mc->pos(mc) - 4u;
- mc->emit_reloc_at(mc, mc->section_id, pos, R_AARCH64_TLVP_LOAD_PAGE21, sym,
+ pos = mc_pos(mc) - 4u;
+ mc_emit_reloc_at(mc, mc->section_id, pos, R_AARCH64_TLVP_LOAD_PAGE21, sym,
0, 0, 0);
aa_emit32(mc, aa_ldr_uimm(3, 0, 0, 0));
- pos = mc->pos(mc) - 4u;
- mc->emit_reloc_at(mc, mc->section_id, pos, R_AARCH64_TLVP_LOAD_PAGEOFF12,
+ pos = mc_pos(mc) - 4u;
+ mc_emit_reloc_at(mc, mc->section_id, pos, R_AARCH64_TLVP_LOAD_PAGEOFF12,
sym, 0, 0, 0);
aa_emit32(mc, aa_ldr_uimm(3, AA_TMP0, 0, 0));
aa_emit32(mc, aa64_blr(AA_TMP0));
@@ -2121,13 +2121,13 @@ static void aa_tls_addr_of(NativeTarget* t, NativeLoc dst, ObjSymId sym,
aa_panic(a, "unsupported TLS object format");
}
aa_emit32(mc, aa_mrs_tpidr_el0(rd));
- pos = mc->pos(mc);
+ pos = mc_pos(mc);
aa_emit32(mc, aa64_add_imm(1, rd, rd, 0, 1));
- mc->emit_reloc_at(mc, mc->section_id, pos, R_AARCH64_TLSLE_ADD_TPREL_HI12,
+ mc_emit_reloc_at(mc, mc->section_id, pos, R_AARCH64_TLSLE_ADD_TPREL_HI12,
sym, addend, 0, 0);
- pos = mc->pos(mc);
+ pos = mc_pos(mc);
aa_emit32(mc, aa64_add_imm(1, rd, rd, 0, 0));
- mc->emit_reloc_at(mc, mc->section_id, pos, R_AARCH64_TLSLE_ADD_TPREL_LO12_NC,
+ mc_emit_reloc_at(mc, mc->section_id, pos, R_AARCH64_TLSLE_ADD_TPREL_LO12_NC,
sym, addend, 0, 0);
}
@@ -2562,7 +2562,7 @@ static void aa_alloca(NativeTarget* t, NativeLoc dst, NativeLoc size,
} else {
AAPatch* p = aa_patch_alloc(a);
p->kind = AA_PATCH_ALLOCA;
- p->pos = t->mc->pos(t->mc);
+ p->pos = mc_pos(t->mc);
p->u.dst_reg = loc_reg(dst);
a->nalloca++;
aa_emit32(t->mc, aa64_add_imm(1, loc_reg(dst), AA_SP, 0, 0));
@@ -3081,9 +3081,9 @@ static void aa_emit_tail_site(NativeTarget* t, NativeLoc callee) {
if (callee.kind == NATIVE_LOC_REG) {
aa_emit32(t->mc, aa64_br(loc_reg(callee)));
} else if (callee.kind == NATIVE_LOC_GLOBAL) {
- u32 pos = t->mc->pos(t->mc);
+ u32 pos = mc_pos(t->mc);
aa_emit32(t->mc, aa64_b(0));
- t->mc->emit_reloc_at(t->mc, t->mc->section_id, pos, R_AARCH64_JUMP26,
+ mc_emit_reloc_at(t->mc, t->mc->section_id, pos, R_AARCH64_JUMP26,
callee.v.global.sym, callee.v.global.addend, 0, 0);
} else {
aa_panic(a, "unsupported tail target");
@@ -3094,11 +3094,11 @@ static void aa_emit_tail_site(NativeTarget* t, NativeLoc callee) {
* restores and frame restore depend on the not-yet-final frame layout. */
AAPatch* p = aa_patch_alloc(a);
p->kind = AA_PATCH_TAIL;
- p->pos = t->mc->pos(t->mc);
+ p->pos = mc_pos(t->mc);
p->u.callee = callee;
for (u32 i = 0; i < AA_TAIL_WORDS; ++i) aa_emit32(t->mc, 0xd503201fu);
if (callee.kind == NATIVE_LOC_GLOBAL) {
- t->mc->emit_reloc_at(t->mc, t->mc->section_id,
+ mc_emit_reloc_at(t->mc, t->mc->section_id,
p->pos + (AA_TAIL_WORDS - 1u) * 4u, R_AARCH64_JUMP26,
callee.v.global.sym, callee.v.global.addend, 0, 0);
}
@@ -3115,7 +3115,7 @@ static void aa_emit_call(NativeTarget* t, const NativeCallPlan* plan) {
}
if (plan->callee.kind == NATIVE_LOC_GLOBAL) {
aa_emit32(t->mc, aa64_bl(0));
- t->mc->emit_reloc_at(t->mc, t->mc->section_id, t->mc->pos(t->mc) - 4u,
+ mc_emit_reloc_at(t->mc, t->mc->section_id, mc_pos(t->mc) - 4u,
R_AARCH64_CALL26, plan->callee.v.global.sym,
plan->callee.v.global.addend, 0, 0);
return;
@@ -3361,13 +3361,13 @@ static void aa_atomic_rmw(NativeTarget* t, KitCgAtomicOp op, NativeLoc dst,
u32 next_reg = AA_TMP1;
u32 status = aa_saved_tmp_pick(loc_reg(dst), loc_reg(val), base);
NativeLoc next = aa_tmp_loc(dst.type, next_reg);
- MCLabel retry = t->mc->label_new(t->mc);
+ MCLabel retry = mc_label_new(t->mc);
u32 sz = size_idx(mem.size ? mem.size : type_size32(t, dst.type));
if (order == KIT_CG_MO_SEQ_CST)
aa_emit32(t->mc, aa64_dmb(AA64_BARRIER_OPT_ISH));
aa_saved_tmp_spill(a, status);
aa_atomic_addr_reg(t, addr, base);
- t->mc->label_place(t->mc, retry);
+ mc_label_place(t->mc, retry);
aa_emit32(t->mc, aa_order_acquire(order) ? aa_ldaxr(sz, loc_reg(dst), base)
: aa_ldxr(sz, loc_reg(dst), base));
switch (op) {
@@ -3400,7 +3400,7 @@ static void aa_atomic_rmw(NativeTarget* t, KitCgAtomicOp op, NativeLoc dst,
? aa_stlxr(sz, status, next_reg, base)
: aa_stxr(sz, status, next_reg, base));
aa_emit32(t->mc, aa64_cbnz_imm(0, status, 0));
- t->mc->emit_label_ref(t->mc, retry, R_AARCH64_CONDBR19, 4, 0);
+ mc_emit_label_ref(t->mc, retry, R_AARCH64_CONDBR19, 4, 0);
aa_saved_tmp_restore(a, status);
if (order == KIT_CG_MO_SEQ_CST)
aa_emit32(t->mc, aa64_dmb(AA64_BARRIER_OPT_ISH));
@@ -3416,28 +3416,28 @@ static void aa_atomic_cas(NativeTarget* t, NativeLoc prior, NativeLoc ok,
u32 sf = sz == 3u;
int acquire = aa_order_acquire(success) || aa_order_acquire(failure);
int release = aa_order_release(success);
- MCLabel retry = t->mc->label_new(t->mc);
- MCLabel fail = t->mc->label_new(t->mc);
- MCLabel done = t->mc->label_new(t->mc);
+ MCLabel retry = mc_label_new(t->mc);
+ MCLabel fail = mc_label_new(t->mc);
+ MCLabel done = mc_label_new(t->mc);
if (success == KIT_CG_MO_SEQ_CST || failure == KIT_CG_MO_SEQ_CST)
aa_emit32(t->mc, aa64_dmb(AA64_BARRIER_OPT_ISH));
aa_atomic_addr_reg(t, addr, base);
- t->mc->label_place(t->mc, retry);
+ mc_label_place(t->mc, retry);
aa_emit32(t->mc, acquire ? aa_ldaxr(sz, loc_reg(prior), base)
: aa_ldxr(sz, loc_reg(prior), base));
aa_emit32(t->mc, aa_subs_reg(sf, AA64_ZR, loc_reg(prior), loc_reg(expected)));
aa_emit32(t->mc, aa64_brcond_pack((AA64BrCond){.cond = cmp_cond(CMP_NE)}));
- t->mc->emit_label_ref(t->mc, fail, R_AARCH64_CONDBR19, 4, 0);
+ mc_emit_label_ref(t->mc, fail, R_AARCH64_CONDBR19, 4, 0);
aa_emit32(t->mc, release ? aa_stlxr(sz, status, loc_reg(desired), base)
: aa_stxr(sz, status, loc_reg(desired), base));
aa_emit32(t->mc, aa64_cbnz_imm(0, status, 0));
- t->mc->emit_label_ref(t->mc, retry, R_AARCH64_CONDBR19, 4, 0);
+ mc_emit_label_ref(t->mc, retry, R_AARCH64_CONDBR19, 4, 0);
aa_emit_load_imm(t->mc, loc_is_64(t, ok), loc_reg(ok), 1);
aa_jump(t, done);
- t->mc->label_place(t->mc, fail);
+ mc_label_place(t->mc, fail);
aa_emit32(t->mc, aa64_clrex(AA64_BARRIER_OPT_SY));
aa_emit_load_imm(t->mc, loc_is_64(t, ok), loc_reg(ok), 0);
- t->mc->label_place(t->mc, done);
+ mc_label_place(t->mc, done);
if (success == KIT_CG_MO_SEQ_CST || failure == KIT_CG_MO_SEQ_CST)
aa_emit32(t->mc, aa64_dmb(AA64_BARRIER_OPT_ISH));
}
@@ -3509,20 +3509,20 @@ static void aa_intrinsic(NativeTarget* t, IntrinKind kind,
u32 sf = loc_is_64(t, args[0]);
u32 rd = loc_reg(dsts[0]);
u32 rn = loc_reg(args[0]);
- MCLabel loop = t->mc->label_new(t->mc);
- MCLabel done = t->mc->label_new(t->mc);
+ MCLabel loop = mc_label_new(t->mc);
+ MCLabel done = mc_label_new(t->mc);
aa_emit_load_imm(t->mc, sf, rd, 0);
aa_emit32(t->mc, aa64_mov_reg(sf, AA_TMP0, rn));
- t->mc->label_place(t->mc, loop);
+ mc_label_place(t->mc, loop);
aa_emit32(t->mc, aa64_cbz(sf, AA_TMP0, 0));
- t->mc->emit_label_ref(t->mc, done, R_AARCH64_CONDBR19, 4, 0);
+ mc_emit_label_ref(t->mc, done, R_AARCH64_CONDBR19, 4, 0);
aa_emit_load_imm(t->mc, sf, AA_TMP1, 1);
aa_emit32(t->mc, aa64_and(sf, AA_TMP1, AA_TMP0, AA_TMP1));
aa_emit32(t->mc, aa64_add(sf, rd, rd, AA_TMP1));
aa_emit_load_imm(t->mc, sf, AA_TMP1, 1);
aa_emit32(t->mc, aa64_lsrv(sf, AA_TMP0, AA_TMP0, AA_TMP1));
aa_jump(t, loop);
- t->mc->label_place(t->mc, done);
+ mc_label_place(t->mc, done);
return;
}
break;
@@ -3626,8 +3626,8 @@ static void aa_intrinsic(NativeTarget* t, IntrinKind kind,
}
break;
case INTRIN_MEMMOVE: {
- MCLabel forward = t->mc->label_new(t->mc);
- MCLabel done = t->mc->label_new(t->mc);
+ MCLabel forward = mc_label_new(t->mc);
+ MCLabel done = mc_label_new(t->mc);
if (narg != 3u || args[0].kind != NATIVE_LOC_REG ||
args[1].kind != NATIVE_LOC_REG || args[2].kind != NATIVE_LOC_IMM)
aa_panic(aa_of(t), "unsupported memory intrinsic operands");
@@ -3642,12 +3642,12 @@ static void aa_intrinsic(NativeTarget* t, IntrinKind kind,
aa_emit32(t->mc, aa_subs_reg(1, AA64_ZR, args[0].v.reg, args[1].v.reg));
aa_emit32(t->mc,
aa64_brcond_pack((AA64BrCond){.cond = cmp_cond(CMP_LT_U)}));
- t->mc->emit_label_ref(t->mc, forward, R_AARCH64_CONDBR19, 4, 0);
+ mc_emit_label_ref(t->mc, forward, R_AARCH64_CONDBR19, 4, 0);
aa_copy_bytes_dir(t, dst_addr, src_addr, access, 1);
aa_jump(t, done);
- t->mc->label_place(t->mc, forward);
+ mc_label_place(t->mc, forward);
aa_copy_bytes_dir(t, dst_addr, src_addr, access, 0);
- t->mc->label_place(t->mc, done);
+ mc_label_place(t->mc, done);
return;
}
case INTRIN_EXPECT:
@@ -3775,7 +3775,7 @@ static int aa_machine_op_clobbers(NativeTarget* t, const NativeMachineOp* op,
static void aa_set_loc(NativeTarget* t, SrcLoc loc) {
AANativeTarget* a = aa_of(t);
a->loc = loc;
- if (t->mc && t->mc->set_loc) t->mc->set_loc(t->mc, loc);
+ if (t->mc) mc_set_loc(t->mc, loc);
}
static void aa_bind_native_param(NativeTarget* t, const CGParamDesc* p,
@@ -4428,13 +4428,13 @@ static void aa_va_arg_core(AANativeTarget* a, NativeLoc dst, NativeAddr ap,
u32 offs_field = is_fp ? vai.vr_offs_offset : vai.gr_offs_offset;
u32 top_field = is_fp ? vai.vr_top_offset : vai.gr_top_offset;
u32 slot_size = is_fp ? vai.fp_slot_size : vai.gp_slot_size;
- MCLabel stack_label = t->mc->label_new(t->mc);
- MCLabel done_label = t->mc->label_new(t->mc);
+ MCLabel stack_label = mc_label_new(t->mc);
+ MCLabel done_label = mc_label_new(t->mc);
aa_emit_mem(a, 1, off, aa_reg_addr(i32_ty, base, (i32)offs_field), i32_mem);
aa_emit32(t->mc, aa64_subs_imm12(0, AA64_ZR, AA_TMP1, 0, 0));
aa_emit32(t->mc,
aa64_brcond_pack((AA64BrCond){.cond = cmp_cond(CMP_GE_S)}));
- t->mc->emit_label_ref(t->mc, stack_label, R_AARCH64_CONDBR19, 4, 0);
+ mc_emit_label_ref(t->mc, stack_label, R_AARCH64_CONDBR19, 4, 0);
aa_emit_mem(a, 1, cur, aa_reg_addr(cur.type, base, (i32)top_field),
ptr_mem);
aa_emit32(t->mc, aa_sbfm(1, AA_TMP1, AA_TMP1, 0, 31));
@@ -4443,15 +4443,15 @@ static void aa_va_arg_core(AANativeTarget* a, NativeLoc dst, NativeAddr ap,
aa_emit_add_imm(a, AA_TMP1, AA_TMP1, (i32)slot_size);
aa_emit_mem(a, 0, off, aa_reg_addr(i32_ty, base, (i32)offs_field), i32_mem);
aa_emit32(t->mc, aa64_b(0));
- t->mc->emit_label_ref(t->mc, done_label, R_AARCH64_JUMP26, 4, 0);
- t->mc->label_place(t->mc, stack_label);
+ mc_emit_label_ref(t->mc, done_label, R_AARCH64_JUMP26, 4, 0);
+ mc_label_place(t->mc, stack_label);
aa_emit_mem(a, 1, cur, aa_reg_addr(cur.type, base, (i32)vai.stack_offset),
ptr_mem);
aa_emit_mem(a, 1, val, aa_reg_addr(type, AA_TMP0, 0), val_mem);
aa_emit_add_imm(a, AA_TMP0, AA_TMP0, 8);
aa_emit_mem(a, 0, cur, aa_reg_addr(cur.type, base, (i32)vai.stack_offset),
ptr_mem);
- t->mc->label_place(t->mc, done_label);
+ mc_label_place(t->mc, done_label);
return;
}
compiler_panic(t->c, a->func ? a->func->loc : (SrcLoc){0, 0, 0},
diff --git a/src/arch/mc.c b/src/arch/mc.c
@@ -73,7 +73,7 @@ typedef struct MCLabelInfo {
* references that must survive a re-encoding assembler: switch jump-table
* entries (.quad <sym>) and `&&label` address-takes (a PC-relative reloc
* against <sym>). OBJ_SYM_NONE until first requested via mc_label_symbol;
- * defined at the label's offset in m_label_place (forward-ref safe). */
+ * defined at the label's offset in mc_label_place (forward-ref safe). */
ObjSymId block_sym;
} MCLabelInfo;
@@ -144,7 +144,7 @@ static void labels_grow(MCImpl* mc, u32 want) {
while (ncap < want) ncap *= 2;
MCLabelInfo* nbuf = arena_array(mc->arena, MCLabelInfo, ncap);
if (mc->labels) memcpy(nbuf, mc->labels, sizeof(MCLabelInfo) * mc->nlabels);
- /* The grown tail is left uninitialized: m_label_new fully assigns every
+ /* The grown tail is left uninitialized: mc_label_new fully assigns every
* field of the one slot it hands out before any consumer indexes it, and
* nothing ever reads labels[i] for i >= nlabels (every access guards on
* id < nlabels and rejects MC_LABEL_NONE). */
@@ -175,7 +175,7 @@ static void emit_label_data_reloc_now(MCImpl* mc, MCLabel label,
bytes[i] = (u8)((u64)addend >> shift);
}
obj_patch(mc->base.obj, r->data_sec, r->data_offset, bytes, r->width);
- mc->base.emit_reloc_at(&mc->base, r->data_sec, r->data_offset, r->kind, sym,
+ mc_emit_reloc_at(&mc->base, r->data_sec, r->data_offset, r->kind, sym,
addend, /*explicit_addend=*/1, /*pair=*/0);
}
@@ -208,7 +208,7 @@ static void apply_fixup(MCImpl* mc, const MCFixup* fx, u32 target_offset) {
* be able to recompute: switch jump-table entries and `&&label` address-takes
* relocate against it instead of baking a fixed offset. Created undefined if
* the label is not yet placed (a forward reference) and defined in
- * m_label_place; defined immediately otherwise. The name is per-object-unique
+ * mc_label_place; defined immediately otherwise. The name is per-object-unique
* (MCLabel ids are monotonic within a TU). */
ObjSymId mc_label_symbol(MCEmitter* m, MCLabel id) {
MCImpl* mc = impl_of(m);
@@ -232,9 +232,23 @@ ObjSymId mc_label_symbol(MCEmitter* m, MCLabel id) {
return li->block_sym;
}
-/* ---- vtable methods ---- */
+/* ---- emission ops (called directly by the arch backends) ---- */
-static void m_set_section(MCEmitter* m, u32 section_id) {
+void mc_emit_bytes(MCEmitter* m, const u8* data, size_t n) {
+ /* Fast path: append straight to the cached section buffer (inlined
+ * buf_write). cur_bytes is NULL for NOBITS/.bss/none, where obj_write does
+ * the bss_size accounting instead. */
+ if (m->cur_bytes)
+ buf_write(m->cur_bytes, data, n);
+ else
+ obj_write(m->obj, m->section_id, data, n);
+}
+
+u32 mc_pos(MCEmitter* m) { return obj_pos(m->obj, m->section_id); }
+
+void mc_set_loc(MCEmitter* m, SrcLoc loc) { m->loc = loc; }
+
+void mc_set_section(MCEmitter* m, u32 section_id) {
m->section_id = section_id;
/* Cache the active section's byte buffer so the hot emit path avoids the
* per-instruction Sections_at deref + nobits branch. NULL for NOBITS/.bss
@@ -242,9 +256,7 @@ static void m_set_section(MCEmitter* m, u32 section_id) {
m->cur_bytes = obj_section_bytes(m->obj, section_id);
}
-static u32 m_pos(MCEmitter* m) { return obj_pos(m->obj, m->section_id); }
-
-static MCLabel m_label_new(MCEmitter* m) {
+MCLabel mc_label_new(MCEmitter* m) {
MCImpl* mc = impl_of(m);
if (mc->nlabels == 0) {
labels_grow(mc, 1);
@@ -262,7 +274,7 @@ static MCLabel m_label_new(MCEmitter* m) {
return (MCLabel)id;
}
-static void m_label_place(MCEmitter* m, MCLabel id) {
+void mc_label_place(MCEmitter* m, MCLabel id) {
MCImpl* mc = impl_of(m);
if (id == MC_LABEL_NONE || id >= mc->nlabels) {
compiler_panic(m->c, mc->base.loc, "MCEmitter: bad label %u", (unsigned)id);
@@ -295,17 +307,7 @@ static void m_label_place(MCEmitter* m, MCLabel id) {
li->pending_data = NULL;
}
-static void m_emit_bytes(MCEmitter* m, const u8* data, size_t n) {
- /* Fast path: append straight to the cached section buffer (inlined
- * buf_write). cur_bytes is NULL for NOBITS/.bss/none, where obj_write does
- * the bss_size accounting instead. */
- if (m->cur_bytes)
- buf_write(m->cur_bytes, data, n);
- else
- obj_write(m->obj, m->section_id, data, n);
-}
-
-static void m_emit_fill(MCEmitter* m, size_t n, u8 byte) {
+void mc_emit_fill(MCEmitter* m, size_t n, u8 byte) {
u8 buf[64];
memset(buf, byte, sizeof buf);
while (n > 0) {
@@ -315,27 +317,27 @@ static void m_emit_fill(MCEmitter* m, size_t n, u8 byte) {
}
}
-static void m_emit_align(MCEmitter* m, u32 align, u8 fill) {
+void mc_emit_align(MCEmitter* m, u32 align, u8 fill) {
if (align <= 1) return;
u32 cur = obj_pos(m->obj, m->section_id);
u32 misalign = cur & (align - 1);
if (misalign == 0) return;
- m_emit_fill(m, align - misalign, fill);
+ mc_emit_fill(m, align - misalign, fill);
}
-static void m_emit_reloc(MCEmitter* m, RelocKind k, ObjSymId sym, i64 addend) {
+void mc_emit_reloc(MCEmitter* m, RelocKind k, ObjSymId sym, i64 addend) {
obj_reloc(m->obj, m->section_id, obj_pos(m->obj, m->section_id), k, sym,
addend);
}
-static void m_emit_reloc_at(MCEmitter* m, u32 section_id, u32 offset,
+void mc_emit_reloc_at(MCEmitter* m, u32 section_id, u32 offset,
RelocKind k, ObjSymId sym, i64 addend,
int explicit_addend, int pair) {
obj_reloc_ex(m->obj, section_id, offset, k, sym, addend, explicit_addend,
pair);
}
-static void m_emit_label_ref(MCEmitter* m, MCLabel id, RelocKind kind,
+void mc_emit_label_ref(MCEmitter* m, MCLabel id, RelocKind kind,
u32 width, i64 addend) {
MCImpl* mc = impl_of(m);
if (id == MC_LABEL_NONE || id >= mc->nlabels) {
@@ -358,7 +360,7 @@ static void m_emit_label_ref(MCEmitter* m, MCLabel id, RelocKind kind,
}
}
-static void m_emit_label_data_reloc(MCEmitter* m, u32 data_sec, u32 data_offset,
+void mc_emit_label_data_reloc(MCEmitter* m, u32 data_sec, u32 data_offset,
MCLabel id, RelocKind kind, u32 width,
i64 extra_addend) {
MCImpl* mc = impl_of(m);
@@ -390,7 +392,6 @@ static void m_emit_label_data_reloc(MCEmitter* m, u32 data_sec, u32 data_offset,
}
}
-static void m_set_loc(MCEmitter* m, SrcLoc loc) { m->loc = loc; }
/* CFI: buffered for .eh_frame emission. Backend calls cfi_startproc to
* open a per-function FDE record, then cfi_def_cfa / cfi_offset / ...
@@ -444,7 +445,7 @@ static void fde_push(MCImpl* mc, u8 kind, u32 reg, i32 imm) {
d->imm = imm;
}
-static void m_cfi_startproc(MCEmitter* m) {
+void mc_cfi_startproc(MCEmitter* m) {
MCImpl* mc = impl_of(m);
Heap* heap = m->c->ctx->heap;
if (mc->cur_fde >= 0) {
@@ -480,7 +481,7 @@ static void m_cfi_startproc(MCEmitter* m) {
}
}
-static void m_cfi_endproc(MCEmitter* m) {
+void mc_cfi_endproc(MCEmitter* m) {
MCImpl* mc = impl_of(m);
CfiFde* fde;
if (mc->cur_fde < 0) return;
@@ -491,24 +492,22 @@ static void m_cfi_endproc(MCEmitter* m) {
0; /* the sticky prologue-PC override ends with the FDE */
}
-static void m_cfi_def_cfa(MCEmitter* m, u32 r, i32 o) {
+void mc_cfi_def_cfa(MCEmitter* m, u32 r, i32 o) {
MCImpl* mc = impl_of(m);
if (mc->cur_fde < 0) return;
fde_push(mc, CFI_OP_DEF_CFA, r, o);
}
-static void m_cfi_offset(MCEmitter* m, u32 r, i32 o) {
+void mc_cfi_offset(MCEmitter* m, u32 r, i32 o) {
MCImpl* mc = impl_of(m);
if (mc->cur_fde < 0) return;
fde_push(mc, CFI_OP_OFFSET, r, o);
}
-static void m_cfi_set_next_pc_offset(MCEmitter* m, u32 pc_offset) {
+void mc_cfi_set_next_pc_offset(MCEmitter* m, u32 pc_offset) {
MCImpl* mc = impl_of(m);
mc->has_pc_override = 1;
mc->pc_override = pc_offset;
}
-static void m_destroy(MCEmitter* m) { (void)m; /* arena-backed */ }
-
/* ---- construction ---- */
static void mc_cleanup(void* arg) { mc_free((MCEmitter*)arg); }
@@ -525,29 +524,6 @@ MCEmitter* mc_new(Compiler* c, ObjBuilder* o) {
base->cur_func_section = 0;
base->cur_func_start = 0;
- base->set_section = m_set_section;
- base->pos = m_pos;
-
- base->label_new = m_label_new;
- base->label_place = m_label_place;
-
- base->emit_bytes = m_emit_bytes;
- base->emit_fill = m_emit_fill;
- base->emit_align = m_emit_align;
- base->emit_reloc = m_emit_reloc;
- base->emit_reloc_at = m_emit_reloc_at;
- base->emit_label_ref = m_emit_label_ref;
- base->emit_label_data_reloc = m_emit_label_data_reloc;
- base->set_loc = m_set_loc;
-
- base->cfi_startproc = m_cfi_startproc;
- base->cfi_endproc = m_cfi_endproc;
- base->cfi_def_cfa = m_cfi_def_cfa;
- base->cfi_offset = m_cfi_offset;
- base->cfi_set_next_pc_offset = m_cfi_set_next_pc_offset;
-
- base->destroy = m_destroy;
-
mc->arena = c->tu;
mc->labels = NULL;
mc->nlabels = 0;
diff --git a/src/arch/mc.h b/src/arch/mc.h
@@ -79,61 +79,54 @@ struct MCEmitter {
ObjSymId cur_func_sym;
u32 cur_func_section;
u32 cur_func_start;
-
- void (*set_section)(MCEmitter*, u32 section_id);
- u32 (*pos)(MCEmitter*);
-
- MCLabel (*label_new)(MCEmitter*);
- void (*label_place)(MCEmitter*, MCLabel);
-
- void (*emit_bytes)(MCEmitter*, const u8*, size_t);
- void (*emit_fill)(MCEmitter*, size_t n, u8 byte);
- void (*emit_align)(MCEmitter*, u32 align, u8 fill);
- void (*emit_reloc)(MCEmitter*, RelocKind, ObjSymId, i64 addend);
- void (*emit_reloc_at)(MCEmitter*, u32 section_id, u32 offset, RelocKind,
- ObjSymId, i64 addend, int explicit_addend, int pair);
- void (*emit_label_ref)(MCEmitter*, MCLabel, RelocKind, u32 width, i64 addend);
-
- /* Emit a relocation at (data_sec, data_offset) that resolves at link
- * time to the runtime address of `label` (an intra-function code label).
- *
- * The relocation is generated against the currently active function
- * symbol (cur_func_sym) with addend = (label_offset_in_section -
- * cur_func_start) + extra_addend. If `label` is already placed, the
- * reloc is emitted immediately; otherwise it is queued and emitted at
- * label_place time. Callers must have an active function (set by
- * backend func_begin); panics otherwise. */
- void (*emit_label_data_reloc)(MCEmitter*, u32 data_sec, u32 data_offset,
- MCLabel label, RelocKind kind, u32 width,
- i64 extra_addend);
- void (*set_loc)(MCEmitter*, SrcLoc);
-
- /* ---- CFI / unwind ----
- * Buffered per-function and emitted into .debug_frame / .eh_frame by Debug
- * at TU finalize. CFI directives are byte-position-bound — they describe
- * the register-save state starting at the current pos() in the current
- * section — so they live on MCEmitter (the only common point that already
- * tracks (section_id, offset)). If the CG was constructed with Debug=NULL,
- * records are discarded. Register numbering is the per-arch DWARF reg
- * number; offsets are byte deltas from the CFA. */
- void (*cfi_startproc)(MCEmitter*);
- void (*cfi_endproc)(MCEmitter*);
- void (*cfi_def_cfa)(MCEmitter*, u32 reg, i32 ofs);
- void (*cfi_offset)(MCEmitter*, u32 reg, i32 ofs);
- /* Override the PC offset used by the *next* cfi_* directive (one-shot).
- * Backends that patch the prologue in func_end (so the live pc has
- * moved past the prologue) call this with the post-prologue offset
- * (relative to cfi_startproc's recorded func_start) before emitting
- * the frame-state directives. */
- void (*cfi_set_next_pc_offset)(MCEmitter*, u32 pc_offset);
-
- void (*destroy)(MCEmitter*);
};
+/* MCEmitter has exactly one implementation (this file), so its operations are
+ * plain extern functions, not a per-instance vtable: the arch backends call
+ * these mc_* functions directly. (They are deliberately NOT `static inline`:
+ * inlining the hot emit_bytes/pos into the per-arch leaf emitters bloats them
+ * enough to break the inliner's own cascade — measured a net +21M instructions
+ * on sqlite -c — so a direct call to an out-of-line body is the win, removing
+ * the indirect call + fn-ptr load without disturbing leaf inlining.) */
+
/* Construct the right target/emitter pair for c->target. */
MCEmitter* mc_new(Compiler*, ObjBuilder*);
void mc_free(MCEmitter*);
+/* Append machine-code bytes to the active section (the hot emit path). */
+void mc_emit_bytes(MCEmitter*, const u8* data, size_t n);
+/* Current byte offset within the active section. */
+u32 mc_pos(MCEmitter*);
+/* Stamp the pending source location read by the per-arch emit choke point. */
+void mc_set_loc(MCEmitter*, SrcLoc);
+
+void mc_set_section(MCEmitter*, u32 section_id);
+MCLabel mc_label_new(MCEmitter*);
+void mc_label_place(MCEmitter*, MCLabel);
+void mc_emit_fill(MCEmitter*, size_t n, u8 byte);
+void mc_emit_align(MCEmitter*, u32 align, u8 fill);
+void mc_emit_reloc(MCEmitter*, RelocKind, ObjSymId, i64 addend);
+void mc_emit_reloc_at(MCEmitter*, u32 section_id, u32 offset, RelocKind, ObjSymId,
+ i64 addend, int explicit_addend, int pair);
+void mc_emit_label_ref(MCEmitter*, MCLabel, RelocKind, u32 width, i64 addend);
+/* Emit a relocation at (data_sec, data_offset) that resolves at link time to
+ * the runtime address of `label` (an intra-function code label). Generated
+ * against the active function symbol; emitted immediately if `label` is placed,
+ * else queued and emitted at label_place. Requires an active function. */
+void mc_emit_label_data_reloc(MCEmitter*, u32 data_sec, u32 data_offset,
+ MCLabel label, RelocKind kind, u32 width,
+ i64 extra_addend);
+/* ---- CFI / unwind ---- buffered per-function, emitted into .eh_frame at TU
+ * finalize; byte-position-bound so they live on MCEmitter. Discarded when the
+ * CG was constructed with Debug=NULL. */
+void mc_cfi_startproc(MCEmitter*);
+void mc_cfi_endproc(MCEmitter*);
+void mc_cfi_def_cfa(MCEmitter*, u32 reg, i32 ofs);
+void mc_cfi_offset(MCEmitter*, u32 reg, i32 ofs);
+/* Override the PC offset used by the *next* cfi_* directive (sticky until
+ * cfi_endproc) — for backends that emit the CFI batch in func_end. */
+void mc_cfi_set_next_pc_offset(MCEmitter*, u32 pc_offset);
+
/* Lazily mint (and return) a per-label SB_LOCAL symbol defined at `label`'s
* placement. Backends use this to reference a code location relocatably —
* `&&label` address-takes emit a PC-relative reloc against it instead of baking
diff --git a/src/arch/riscv/asm.c b/src/arch/riscv/asm.c
@@ -205,7 +205,7 @@ static int rv_emit_imm_mod_reloc(AsmDriver* d, RvModPos pos) {
RelocKind k;
if (!rv_parse_mod_reloc(d, pos, &sym, &off, &k)) return 0;
MCEmitter* mc = asm_driver_mc(d);
- mc->emit_reloc_at(mc, mc->section_id, mc->pos(mc), k, sym, off, 0, 0);
+ mc_emit_reloc_at(mc, mc->section_id, mc_pos(mc), k, sym, off, 0, 0);
return 1;
}
@@ -243,7 +243,7 @@ static void rv_emit_mem_mod_reloc(AsmDriver* d, const Rv64Mem* m,
? (is_store ? R_RV_PCREL_LO12_S : R_RV_PCREL_LO12_I)
: (is_store ? R_RV_LO12_S : R_RV_LO12_I);
MCEmitter* mc = asm_driver_mc(d);
- mc->emit_reloc_at(mc, mc->section_id, mc->pos(mc), k, m->sym, m->off, 0, 0);
+ mc_emit_reloc_at(mc, mc->section_id, mc_pos(mc), k, m->sym, m->off, 0, 0);
}
/* Fence pred/succ parser — accepts a string like "rw" / "iorw" / "0" /
@@ -443,7 +443,7 @@ static i32 rv_reloc_target(AsmDriver* d, RelocKind kind) {
asm_driver_parse_sym_expr(d, &sym, &off);
if (sym != OBJ_SYM_NONE) {
MCEmitter* mc = asm_driver_mc(d);
- mc->emit_reloc_at(mc, mc->section_id, mc->pos(mc), kind, sym, off, 0, 0);
+ mc_emit_reloc_at(mc, mc->section_id, mc_pos(mc), kind, sym, off, 0, 0);
return 0;
}
return (i32)off;
@@ -885,7 +885,7 @@ static u32 assemble_one(AsmDriver* d, const Rv64InsnDesc* desc) {
* expands to an LUI/ADDI(W)/SLLI chain (no relocations). Each 32-bit
* word goes out through rv64_emit32 — the same path assemble_one's
* single-word result uses — and relocations are attached via
- * mc->emit_reloc_at at the appropriate word offset. */
+ * mc_emit_reloc_at at the appropriate word offset. */
/* 12-bit signed immediate range check for li short-circuit. */
static bool rv_fits_i12(i64 v) { return v >= -2048 && v <= 2047; }
@@ -905,9 +905,9 @@ static ObjSymId rv_emit_pcrel_hi(AsmDriver* d, u32 rd, ObjSymId sym,
ObjBuilder* obj = asm_driver_ob(d);
Compiler* c = asm_driver_compiler(d);
u32 sec = mc->section_id;
- u32 ap = mc->pos(mc);
+ u32 ap = mc_pos(mc);
rv64_emit32(mc, rv_auipc(rd, 0));
- mc->emit_reloc_at(mc, sec, ap, R_RV_PCREL_HI20, sym, addend, 0, 0);
+ mc_emit_reloc_at(mc, sec, ap, R_RV_PCREL_HI20, sym, addend, 0, 0);
Sym an = pool_intern_slice(c->global, SLICE_LIT(".LpcrelHi"));
return obj_symbol(obj, an, SB_LOCAL, SK_OBJ, sec, (u64)ap, 0);
}
@@ -924,10 +924,10 @@ static void rv_emit_call_pseudo(AsmDriver* d, u32 link, u32 rd) {
if (sym == OBJ_SYM_NONE)
asm_driver_panic(d, "rv64 asm: call/tail target must be a symbol");
u32 sec = mc->section_id;
- u32 ap = mc->pos(mc);
+ u32 ap = mc_pos(mc);
rv64_emit32(mc, rv_auipc(link, 0));
rv64_emit32(mc, rv_jalr(rd, link, 0));
- mc->emit_reloc_at(mc, sec, ap, R_RV_CALL, sym, off, 0, 0);
+ mc_emit_reloc_at(mc, sec, ap, R_RV_CALL, sym, off, 0, 0);
}
/* la/lla rd, sym: AUIPC rd,%pcrel_hi(sym) + ADDI rd,rd,%pcrel_lo(anchor).
@@ -943,9 +943,9 @@ static void rv_emit_la_pseudo(AsmDriver* d) {
asm_driver_panic(d, "rv64 asm: la/lla target must be a symbol");
ObjSymId anchor = rv_emit_pcrel_hi(d, rd, sym, off);
u32 sec = mc->section_id;
- u32 lp = mc->pos(mc);
+ u32 lp = mc_pos(mc);
rv64_emit32(mc, rv_addi(rd, rd, 0));
- mc->emit_reloc_at(mc, sec, lp, R_RV_PCREL_LO12_I, anchor, 0, 0, 0);
+ mc_emit_reloc_at(mc, sec, lp, R_RV_PCREL_LO12_I, anchor, 0, 0, 0);
}
/* LUI immediate that sign-extends to a negative 32-bit value: bit 19 of
diff --git a/src/arch/riscv/native.c b/src/arch/riscv/native.c
@@ -82,7 +82,7 @@ void rv64_emit32(MCEmitter* mc, u32 word) {
u8 b[4];
u32 ofs = obj_pos(mc->obj, mc->section_id);
wr_u32_le(b, word);
- mc->emit_bytes(mc, b, sizeof b);
+ mc_emit_bytes(mc, b, sizeof b);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
@@ -91,7 +91,7 @@ void rv64_emit16(MCEmitter* mc, u32 halfword) {
u32 ofs = obj_pos(mc->obj, mc->section_id);
b[0] = (u8)(halfword & 0xff);
b[1] = (u8)((halfword >> 8) & 0xff);
- mc->emit_bytes(mc, b, sizeof b);
+ mc_emit_bytes(mc, b, sizeof b);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
@@ -685,15 +685,15 @@ static void rv_emit_pcrel_anchor(NativeTarget* t, u32 dst, ObjSymId target_sym,
RelocKind hi20, u32 follow_insn) {
MCEmitter* mc = t->mc;
u32 sec = mc->section_id;
- u32 ap = mc->pos(mc);
+ u32 ap = mc_pos(mc);
rv64_emit32(mc, rv_auipc(dst, 0));
- mc->emit_reloc_at(mc, sec, ap, hi20, target_sym, 0, 0, 0);
+ mc_emit_reloc_at(mc, sec, ap, hi20, target_sym, 0, 0, 0);
{
Sym an = pool_intern_slice(t->c->global, SLICE_LIT(".LpcrelHi"));
ObjSymId anchor = obj_symbol(t->obj, an, SB_LOCAL, SK_OBJ, sec, (u64)ap, 0);
- u32 lp = mc->pos(mc);
+ u32 lp = mc_pos(mc);
rv64_emit32(mc, follow_insn);
- mc->emit_reloc_at(mc, sec, lp, R_RV_PCREL_LO12_I, anchor, 0, 0, 0);
+ mc_emit_reloc_at(mc, sec, lp, R_RV_PCREL_LO12_I, anchor, 0, 0, 0);
}
}
@@ -1360,13 +1360,13 @@ static void rv_reload(NativeTarget* t, NativeLoc dst, NativeFrameSlot slot,
/* ============================ control flow ============================ */
-static MCLabel rv_label_new(NativeTarget* t) { return t->mc->label_new(t->mc); }
+static MCLabel rv_label_new(NativeTarget* t) { return mc_label_new(t->mc); }
static void rv_label_place(NativeTarget* t, MCLabel l) {
- t->mc->label_place(t->mc, l);
+ mc_label_place(t->mc, l);
}
static void rv_jump(NativeTarget* t, MCLabel l) {
rv64_emit32(t->mc, rv_jal(RV_ZERO, 0));
- t->mc->emit_label_ref(t->mc, l, R_RV_JAL, 4, 0);
+ mc_emit_label_ref(t->mc, l, R_RV_JAL, 4, 0);
}
static void rv_cmp_branch(NativeTarget* t, CmpOp op, NativeLoc aop,
@@ -1503,12 +1503,12 @@ static void rv_func_begin_common(NativeTarget* t, const CGFuncDesc* fd) {
a->minimal_prologue_words = 0;
a->slim_prologue = 0;
- mc->set_section(mc, fd->text_section_id);
- mc->emit_align(mc, 4, 0);
- a->func_start = mc->pos(mc);
+ mc_set_section(mc, fd->text_section_id);
+ mc_emit_align(mc, 4, 0);
+ a->func_start = mc_pos(mc);
mc_begin_function(mc, fd->sym, fd->text_section_id, a->func_start);
- if (mc->cfi_startproc) mc->cfi_startproc(mc);
- a->epilogue_label = mc->label_new(mc);
+ mc_cfi_startproc(mc);
+ a->epilogue_label = mc_label_new(mc);
}
/* sret: reserve a hidden slot for the incoming destination pointer (a0). */
@@ -1759,7 +1759,7 @@ static void rv_func_begin(NativeTarget* t, const CGFuncDesc* fd) {
* it for the patch and CFI. RISC-V has no stack probe, so the region is just
* the worst-case far `sub`. */
region = RV_NDT_SUB_WORDS;
- a->prologue_pos = mc->pos(mc);
+ a->prologue_pos = mc_pos(mc);
/* The live fixed entry is exactly RV_NDT_FIXED_ENTRY_WORDS words; the CFI
* advance in rv_func_end relies on prologue_pos sitting just past it. */
if (a->prologue_pos - a->func_start != RV_NDT_FIXED_ENTRY_WORDS * 4u)
@@ -1787,7 +1787,7 @@ static void rv_func_end(NativeTarget* t) {
a->fp_pair_off = fp_pair_off;
/* epilogue */
- mc->label_place(mc, a->epilogue_label);
+ mc_label_place(mc, a->epilogue_label);
if (a->slim_prologue) {
/* Frameless leaf: no callee-saves, no s0/ra to reload, sp untouched. */
rv64_emit32(mc, rv_jalr(RV_ZERO, RV_RA, 0));
@@ -1844,13 +1844,13 @@ static void rv_func_end(NativeTarget* t) {
}
/* CFI: CFA = s0 + (frame_size - fp_pair_off) */
- if (mc->cfi_set_next_pc_offset && mc->cfi_def_cfa && mc->cfi_offset) {
+ {
if (a->slim_prologue) {
/* Frameless leaf: CFA = sp (unchanged from entry) and the return address
* stays live in ra (the CIE default), so no saved-register rules. The
* state holds from the first instruction (offset 0). */
- mc->cfi_set_next_pc_offset(mc, 0);
- mc->cfi_def_cfa(mc, RV_SP, 0);
+ mc_cfi_set_next_pc_offset(mc, 0);
+ mc_cfi_def_cfa(mc, RV_SP, 0);
} else {
i32 cfa = (i32)frame_size - (i32)fp_pair_off;
/* CFI advance to the post-prologue PC. known-frame: prologue_pos +
@@ -1863,27 +1863,27 @@ static void rv_func_end(NativeTarget* t) {
? a->minimal_prologue_words * 4u
: a->prologue_region_words * 4u);
u32 k;
- mc->cfi_set_next_pc_offset(mc, post - a->func_start);
- mc->cfi_def_cfa(mc, RV_S0, cfa);
- mc->cfi_offset(mc, RV_S0, -cfa);
+ mc_cfi_set_next_pc_offset(mc, post - a->func_start);
+ mc_cfi_def_cfa(mc, RV_S0, cfa);
+ mc_cfi_offset(mc, RV_S0, -cfa);
/* ra is saved at the saved-pair stride above s0 (ptr_bytes). */
- mc->cfi_offset(mc, RV_RA, -cfa + (i32)a->variant->ptr_bytes);
+ mc_cfi_offset(mc, RV_RA, -cfa + (i32)a->variant->ptr_bytes);
for (k = 0; k < n_int; ++k)
- mc->cfi_offset(mc, int_regs[k], rv_save_off(a, n_int, k) - cfa);
+ mc_cfi_offset(mc, int_regs[k], rv_save_off(a, n_int, k) - cfa);
for (k = 0; k < n_fp; ++k)
- mc->cfi_offset(mc, 32u + fp_regs[k],
+ mc_cfi_offset(mc, 32u + fp_regs[k],
rv_save_off(a, n_int, n_int + k) - cfa);
}
}
- end = mc->pos(mc);
+ end = mc_pos(mc);
obj_symbol_define(obj, a->func->sym, sec, (u64)a->func_start,
(u64)(end - a->func_start));
if (a->func->atomize)
obj_atom_define(obj, sec, a->func_start, end - a->func_start, a->func->sym,
0);
if (mc->debug) debug_func_pc_range(mc->debug, sec, a->func_start, end);
- if (mc->cfi_endproc) mc->cfi_endproc(mc);
+ mc_cfi_endproc(mc);
mc_end_function(mc);
a->func = NULL;
}
@@ -1982,7 +1982,7 @@ static void rv_func_begin_known_frame(NativeTarget* t, const CGFuncDesc* fd,
fp_pair_off = rv_fp_pair_off(a, frame_size);
a->frame_size_final = frame_size;
a->fp_pair_off = fp_pair_off;
- a->prologue_pos = mc->pos(mc);
+ a->prologue_pos = mc_pos(mc);
/* Leaf no-frame tier (aa64 slim_prologue equivalent): a leaf with no
* callee-saves, no body slots, no outgoing args, no sret/variadic and
* register-only params never reads s0 (no frame slots / stack args) nor
@@ -2545,10 +2545,10 @@ static void rv_emit_tail_site(NativeTarget* t, NativeLoc callee) {
rv64_emit32(mc, rv_addi(RV_SP, RV_S0, cfa));
rv64_emit32(mc, rv_ld_ptr(v, RV_S0, RV_S0, 0));
if (callee.kind == NATIVE_LOC_GLOBAL) {
- u32 pos = mc->pos(mc);
+ u32 pos = mc_pos(mc);
rv64_emit32(mc, rv_auipc(RV_TMP0, 0));
rv64_emit32(mc, rv_jalr(RV_ZERO, RV_TMP0, 0));
- mc->emit_reloc_at(mc, mc->section_id, pos, R_RV_CALL, callee.v.global.sym,
+ mc_emit_reloc_at(mc, mc->section_id, pos, R_RV_CALL, callee.v.global.sym,
callee.v.global.addend, 0, 0);
} else if (indirect) {
rv64_emit32(mc, rv_jalr(RV_ZERO, RV_TMP1, 0));
@@ -2565,10 +2565,10 @@ static void rv_emit_call(NativeTarget* t, const NativeCallPlan* plan) {
return;
}
if (plan->callee.kind == NATIVE_LOC_GLOBAL) {
- u32 pos = mc->pos(mc);
+ u32 pos = mc_pos(mc);
rv64_emit32(mc, rv_auipc(RV_RA, 0));
rv64_emit32(mc, rv_jalr(RV_RA, RV_RA, 0));
- mc->emit_reloc_at(mc, sec, pos, R_RV_CALL, plan->callee.v.global.sym,
+ mc_emit_reloc_at(mc, sec, pos, R_RV_CALL, plan->callee.v.global.sym,
plan->callee.v.global.addend, 0, 0);
return;
}
@@ -2669,7 +2669,7 @@ static void rv_alloca(NativeTarget* t, NativeLoc dst, NativeLoc size,
a->patches_cap = cap;
}
a->patches[a->npatches].kind = RV_PATCH_ALLOCA;
- a->patches[a->npatches].pos = mc->pos(mc);
+ a->patches[a->npatches].pos = mc_pos(mc);
a->patches[a->npatches].dst_reg = rd;
a->npatches++;
a->nalloca++;
@@ -2693,14 +2693,14 @@ static void rv_tls_addr_of(NativeTarget* t, NativeLoc dst, ObjSymId sym,
* rather than a working binary. */
/* lui t0, %tprel_hi(sym); add t0, tp, t0; addi dst, t0, %tprel_lo(sym). */
{
- u32 hp = mc->pos(mc);
+ u32 hp = mc_pos(mc);
rv64_emit32(mc, rv_lui(RV_TMP0, 0));
- mc->emit_reloc_at(mc, sec, hp, R_RV_TPREL_HI20, sym, addend, 0, 0);
+ mc_emit_reloc_at(mc, sec, hp, R_RV_TPREL_HI20, sym, addend, 0, 0);
rv64_emit32(mc, rv_add(RV_TMP0, RV_TP, RV_TMP0));
{
- u32 lp = mc->pos(mc);
+ u32 lp = mc_pos(mc);
rv64_emit32(mc, rv_addi(rd, RV_TMP0, 0));
- mc->emit_reloc_at(mc, sec, lp, R_RV_TPREL_LO12_I, sym, addend, 0, 0);
+ mc_emit_reloc_at(mc, sec, lp, R_RV_TPREL_LO12_I, sym, addend, 0, 0);
}
}
}
@@ -2829,10 +2829,10 @@ static void rv_atomic_rmw(NativeTarget* t, KitCgAtomicOp op, NativeLoc dst,
u32 rd = loc_reg(dst);
u32 aq = (u32)rv_order_acquire(mo);
u32 rl = (u32)rv_order_release(mo);
- MCLabel retry = mc->label_new(mc);
+ MCLabel retry = mc_label_new(mc);
/* LR/SC loop: dst = *base; new = dst op val; sc new; retry on failure.
* RV_TMP1 carries the SC status, RV_TMP3 the computed new value. */
- mc->label_place(mc, retry);
+ mc_label_place(mc, retry);
rv64_emit32(mc, sf ? rv_lr_d(rd, base, aq, 0) : rv_lr_w(rd, base, aq, 0));
switch (op) {
case KIT_CG_ATOMIC_XCHG:
@@ -2865,7 +2865,7 @@ static void rv_atomic_rmw(NativeTarget* t, KitCgAtomicOp op, NativeLoc dst,
rv64_emit32(mc, sf ? rv_sc_d(RV_TMP1, base, RV_TMP3, 0, rl)
: rv_sc_w(RV_TMP1, base, RV_TMP3, 0, rl));
rv64_emit32(mc, rv_bne(RV_TMP1, RV_ZERO, 0));
- mc->emit_label_ref(mc, retry, R_RV_BRANCH, 4, 0);
+ mc_emit_label_ref(mc, retry, R_RV_BRANCH, 4, 0);
}
static void rv_atomic_cas(NativeTarget* t, NativeLoc prior, NativeLoc ok,
@@ -2883,28 +2883,28 @@ static void rv_atomic_cas(NativeTarget* t, NativeLoc prior, NativeLoc ok,
u32 rok = loc_reg(ok);
u32 aq = (u32)rv_order_acquire(success);
u32 rl = (u32)rv_order_release(success);
- MCLabel retry = mc->label_new(mc);
- MCLabel fail = mc->label_new(mc);
- MCLabel done = mc->label_new(mc);
+ MCLabel retry = mc_label_new(mc);
+ MCLabel fail = mc_label_new(mc);
+ MCLabel done = mc_label_new(mc);
(void)failure;
- mc->label_place(mc, retry);
+ mc_label_place(mc, retry);
rv64_emit32(mc,
sf ? rv_lr_d(rprior, base, aq, 0) : rv_lr_w(rprior, base, aq, 0));
/* if (prior != expected) -> fail */
rv64_emit32(mc, rv_bne(rprior, rexp, 0));
- mc->emit_label_ref(mc, fail, R_RV_BRANCH, 4, 0);
+ mc_emit_label_ref(mc, fail, R_RV_BRANCH, 4, 0);
/* sc.w/d status, desired, (base); retry on failure. */
rv64_emit32(mc, sf ? rv_sc_d(RV_TMP1, base, rdes, 0, rl)
: rv_sc_w(RV_TMP1, base, rdes, 0, rl));
rv64_emit32(mc, rv_bne(RV_TMP1, RV_ZERO, 0));
- mc->emit_label_ref(mc, retry, R_RV_BRANCH, 4, 0);
+ mc_emit_label_ref(mc, retry, R_RV_BRANCH, 4, 0);
/* ok = 1; jump done. */
rv_emit_load_imm(a->variant, mc, 0, rok, 1);
rv64_emit32(mc, rv_jal(RV_ZERO, 0));
- mc->emit_label_ref(mc, done, R_RV_JAL, 4, 0);
- mc->label_place(mc, fail);
+ mc_emit_label_ref(mc, done, R_RV_JAL, 4, 0);
+ mc_label_place(mc, fail);
rv_emit_load_imm(a->variant, mc, 0, rok, 0);
- mc->label_place(mc, done);
+ mc_label_place(mc, done);
}
static void rv_fence(NativeTarget* t, KitCgMemOrder mo) {
@@ -3996,7 +3996,7 @@ static void rv_asm_block_native(NativeTarget* t, const char* tmpl,
static void rv_trap(NativeTarget* t) { rv64_emit32(t->mc, rv_ebreak()); }
static void rv_set_loc(NativeTarget* t, SrcLoc loc) {
rv_of(t)->loc = loc;
- if (t->mc->set_loc) t->mc->set_loc(t->mc, loc);
+ mc_set_loc(t->mc, loc);
}
/* ============================ construction ============================ */
diff --git a/src/arch/x64/asm.c b/src/arch/x64/asm.c
@@ -314,8 +314,8 @@ static X64AsmOperand parse_operand(AsmDriver* d) {
static void x64_emit_mem_reloc(AsmDriver* d, MCEmitter* mc,
const X64AsmOperand* m, u32 trailing) {
if (!m->has_reloc) return;
- u32 disp_pos = mc->pos(mc) - 4u - trailing;
- mc->emit_reloc_at(mc, asm_driver_cur_section(d), disp_pos, m->reloc_kind,
+ u32 disp_pos = mc_pos(mc) - 4u - trailing;
+ mc_emit_reloc_at(mc, asm_driver_cur_section(d), disp_pos, m->reloc_kind,
m->reloc_sym, m->reloc_off - 4 - (i64)trailing, 1, 0);
}
@@ -361,7 +361,7 @@ static void emit_reg_mem_operand(AsmDriver* d, MCEmitter* mc, u32 size, u8 opc,
n += x64_pack_rex_mem_operand(buf + n, size == 8u, dst, src);
buf[n++] = opc;
n += x64_pack_mem_operand(buf + n, dst, src);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
x64_emit_mem_reloc(d, mc, &src, 0);
}
@@ -388,7 +388,7 @@ static void emit_reg_store_operand(AsmDriver* d, MCEmitter* mc, u32 size,
n += x64_pack_rex_mem_operand(buf + n, size == 8u, src, dst);
buf[n++] = opc;
n += x64_pack_mem_operand(buf + n, src, dst);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
x64_emit_mem_reloc(d, mc, &dst, 0);
}
@@ -435,7 +435,7 @@ static void emit_rm_imm_store_operand(AsmDriver* d, MCEmitter* mc, u32 size,
n += x64_put_u32le(buf + n, (u32)(i32)imm);
trailing = 4u;
}
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
x64_emit_mem_reloc(d, mc, &dst, trailing);
}
@@ -446,15 +446,15 @@ static void expect_comma(AsmDriver* d) {
static void emit_indirect_branch(MCEmitter* mc, u32 sub, u32 reg) {
u8 op = 0xff;
emit_rex(mc, 0, 0, 0, reg);
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
{
u8 mr = modrm(3u, sub, reg);
- mc->emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &mr, 1);
}
}
static void emit_packed(MCEmitter* mc, const u8* bytes, u32 n) {
- mc->emit_bytes(mc, bytes, n);
+ mc_emit_bytes(mc, bytes, n);
}
static int byte_reg_needs_rex(const X64AsmOperand* op) {
@@ -479,10 +479,10 @@ static __attribute__((unused)) void emit_movb_rr_operand(AsmDriver* d,
emit_rex_force(mc, 0, src.reg, 0, dst.reg);
else
emit_rex(mc, 0, src.reg, 0, dst.reg);
- mc->emit_bytes(mc, &ob, 1);
+ mc_emit_bytes(mc, &ob, 1);
{
u8 mr = modrm(3u, src.reg, dst.reg);
- mc->emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &mr, 1);
}
}
@@ -494,8 +494,8 @@ static __attribute__((unused)) void emit_movb_store_operand(AsmDriver* d,
u8 ob = 0x88;
if (dst.no_base || dst.base >= 8u)
asm_driver_panic(d, "x64 asm: high-byte register cannot use REX");
- if (dst.seg) mc->emit_bytes(mc, &dst.seg, 1);
- mc->emit_bytes(mc, &ob, 1);
+ if (dst.seg) mc_emit_bytes(mc, &dst.seg, 1);
+ mc_emit_bytes(mc, &ob, 1);
emit_mem_operand(mc, src.reg, dst.base, dst.disp);
return;
}
@@ -815,7 +815,7 @@ static void parse_nullary(X64ParseCtx* p) {
if (p->desc->rex_w_req == X64_W_REQ_1) buf[n++] = X64_REX_BASE | X64_REX_W;
for (u32 i = 0; i < p->desc->opc_len; ++i) buf[n++] = p->desc->opc[i];
if (p->desc->opc_len >= 1u) {
- p->mc->emit_bytes(p->mc, buf, n);
+ mc_emit_bytes(p->mc, buf, n);
return;
}
asm_driver_panic(p->d, "x64 asm: nullary form not implemented");
@@ -886,7 +886,7 @@ static void parse_alu_rr(X64ParseCtx* p) {
u8 op = p->desc->opc[0];
if (p->width == 2u) {
u8 pfx = X64_OPSIZE_PFX;
- p->mc->emit_bytes(p->mc, &pfx, 1);
+ mc_emit_bytes(p->mc, &pfx, 1);
}
if (op == 0x89u) {
/* MOV r/m, r — phase-1 keeps the existing helper. */
@@ -974,7 +974,7 @@ static void parse_mov_rm_load(X64ParseCtx* p) {
if (src.kind == X64_ASM_OP_REG && dst.kind == X64_ASM_OP_REG) {
if (p->width == 2u) {
u8 pfx = X64_OPSIZE_PFX;
- p->mc->emit_bytes(p->mc, &pfx, 1);
+ mc_emit_bytes(p->mc, &pfx, 1);
}
emit_mov_rr(p->mc, width_to_w(p->width), dst.reg, src.reg);
return;
@@ -1036,10 +1036,10 @@ static void parse_cmovcc(X64ParseCtx* p) {
u8 op[2] = {0x0f, (u8)(0x40u | (p->cc & 0xfu))};
if (p->width == 2u) {
u8 pfx = X64_OPSIZE_PFX;
- p->mc->emit_bytes(p->mc, &pfx, 1);
+ mc_emit_bytes(p->mc, &pfx, 1);
}
emit_rex(p->mc, width_to_w(p->width), dst.reg, 0, src.reg);
- p->mc->emit_bytes(p->mc, op, 2);
+ mc_emit_bytes(p->mc, op, 2);
emit_rm_reg(p->mc, dst.reg, src.reg);
}
}
@@ -1052,7 +1052,7 @@ static void parse_push_pop(X64ParseCtx* p) {
asm_driver_panic(p->d, "x64 asm: push/pop register");
emit_rex(p->mc, 0, 0, 0, op.reg);
ob = (u8)(base | (op.reg & 7u));
- p->mc->emit_bytes(p->mc, &ob, 1);
+ mc_emit_bytes(p->mc, &ob, 1);
}
static void parse_movzx_movsx(X64ParseCtx* p) {
@@ -1187,13 +1187,13 @@ static void parse_rel32_branch(X64ParseCtx* p) {
u32 disp_pos;
if (p->desc->fmt == X64_FMT_JCC_REL32) {
u8 op[2] = {0x0f, (u8)(0x80u | (p->cc & 0xfu))};
- p->mc->emit_bytes(p->mc, op, 2);
+ mc_emit_bytes(p->mc, op, 2);
} else {
u8 op = (p->desc->fmt == X64_FMT_CALL_REL32) ? X64_OPC_CALL_REL32
: X64_OPC_JMP_REL32;
- p->mc->emit_bytes(p->mc, &op, 1);
+ mc_emit_bytes(p->mc, &op, 1);
}
- disp_pos = p->mc->pos(p->mc);
+ disp_pos = mc_pos(p->mc);
emit_u32le(p->mc, 0);
asm_driver_parse_sym_expr(p->d, &sym, &off);
if (sym == OBJ_SYM_NONE)
@@ -1204,7 +1204,7 @@ static void parse_rel32_branch(X64ParseCtx* p) {
RelocKind k = x64_parse_reloc_suffix(p->d, dflt);
if (k != R_X64_PLT32 && k != R_PC32)
asm_driver_panic(p->d, "x64 asm: only @PLT is valid on a branch target");
- p->mc->emit_reloc_at(p->mc, asm_driver_cur_section(p->d), disp_pos, k, sym,
+ mc_emit_reloc_at(p->mc, asm_driver_cur_section(p->d), disp_pos, k, sym,
off - 4, 1, 0);
}
@@ -1213,7 +1213,7 @@ static void parse_setcc(X64ParseCtx* p) {
if (dst.kind == X64_ASM_OP_REG) {
if (dst.high8) {
u8 op[2] = {0x0f, (u8)(0x90u | (p->cc & 0xfu))};
- p->mc->emit_bytes(p->mc, op, 2);
+ mc_emit_bytes(p->mc, op, 2);
emit_rm_reg(p->mc, 0, dst.reg);
} else {
emit_setcc(p->mc, p->cc, dst.reg);
@@ -1301,7 +1301,7 @@ static void parse_bswap(X64ParseCtx* p) {
emit_rex(p->mc, width_to_w(p->width), 0, 0, reg.reg);
op[0] = 0x0f;
op[1] = (u8)(0xc8u | (reg.reg & 7u));
- p->mc->emit_bytes(p->mc, op, 2);
+ mc_emit_bytes(p->mc, op, 2);
}
static void parse_bs_popcnt(X64ParseCtx* p) {
@@ -1343,7 +1343,7 @@ static void parse_atomic(X64ParseCtx* p) {
static void parse_nop_multi(X64ParseCtx* p) {
u8 nop6[6] = {X64_NOP6_BYTE0, X64_NOP6_BYTE1, X64_NOP6_BYTE2,
X64_NOP6_BYTE3, X64_NOP6_BYTE4, X64_NOP6_BYTE5};
- p->mc->emit_bytes(p->mc, nop6, sizeof nop6);
+ mc_emit_bytes(p->mc, nop6, sizeof nop6);
}
static void parse_and_emit_for_format(X64ParseCtx* p) {
@@ -1453,7 +1453,7 @@ static void x64_arch_asm_insn(ArchAsm* base, AsmDriver* d, Sym mnemonic) {
if (n == 4 && memcmp(p, "lock", 4) == 0) {
AsmTok next;
u8 pfx = 0xf0;
- mc->emit_bytes(mc, &pfx, 1);
+ mc_emit_bytes(mc, &pfx, 1);
next = asm_driver_next(d);
if (next.kind != ASM_TOK_IDENT)
asm_driver_panic(d, "x64 asm: lock requires an instruction");
@@ -1501,7 +1501,7 @@ static void x64_arch_asm_insn(ArchAsm* base, AsmDriver* d, Sym mnemonic) {
}
if (w == 2u) {
u8 pfx = X64_OPSIZE_PFX;
- mc->emit_bytes(mc, &pfx, 1);
+ mc_emit_bytes(mc, &pfx, 1);
}
emit_mov_rr(mc, width_to_w(w), dst.reg, src.reg);
return;
diff --git a/src/arch/x64/emit.c b/src/arch/x64/emit.c
@@ -64,7 +64,7 @@ const X64ABIRegs* x64_abi_for_os(KitOSKind os) {
* instruction-start. */
void emit1(MCEmitter* mc, u8 b) {
u32 ofs = obj_pos(mc->obj, mc->section_id);
- mc->emit_bytes(mc, &b, 1);
+ mc_emit_bytes(mc, &b, 1);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
void emit_u32le(MCEmitter* mc, u32 v) {
@@ -73,7 +73,7 @@ void emit_u32le(MCEmitter* mc, u32 v) {
b[1] = (u8)(v >> 8);
b[2] = (u8)(v >> 16);
b[3] = (u8)(v >> 24);
- mc->emit_bytes(mc, b, 4);
+ mc_emit_bytes(mc, b, 4);
}
static u8 make_rex(int w, u32 reg, u32 index, u32 rm) {
u8 r = 0;
@@ -85,14 +85,14 @@ static u8 make_rex(int w, u32 reg, u32 index, u32 rm) {
}
void emit_rex(MCEmitter* mc, int w, u32 reg, u32 index, u32 rm) {
u8 r = make_rex(w, reg, index, rm);
- if (r) mc->emit_bytes(mc, &r, 1);
+ if (r) mc_emit_bytes(mc, &r, 1);
}
/* Force REX (even REX=0x40) — required for byte-reg encodings that
* promote SIL/DIL/etc. */
void emit_rex_force(MCEmitter* mc, int w, u32 reg, u32 index, u32 rm) {
u8 r = (u8)(X64_REX_BASE | (w ? X64_REX_W : 0) | ((reg & 8) ? X64_REX_R : 0) |
((index & 8) ? X64_REX_X : 0) | ((rm & 8) ? X64_REX_B : 0));
- mc->emit_bytes(mc, &r, 1);
+ mc_emit_bytes(mc, &r, 1);
}
u8 modrm(u32 mod, u32 reg, u32 rm) {
@@ -113,23 +113,23 @@ void emit_mem_operand(MCEmitter* mc, u32 reg, u32 base, i32 disp) {
if ((base & 7u) == 4u) {
/* SIB byte required: index=4 (none), base=base. */
u8 mr = modrm(m, reg, 4u);
- mc->emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &mr, 1);
u8 s = sib(0, 4u, base);
- mc->emit_bytes(mc, &s, 1);
+ mc_emit_bytes(mc, &s, 1);
} else {
u8 mr = modrm(m, reg, base);
- mc->emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &mr, 1);
}
if (m == 1u) {
u8 d = (u8)(i8)disp;
- mc->emit_bytes(mc, &d, 1);
+ mc_emit_bytes(mc, &d, 1);
} else if (m == 2u) {
emit_u32le(mc, (u32)disp);
}
}
void emit_rm_reg(MCEmitter* mc, u32 reg, u32 rm) {
u8 mr = modrm(3u, reg, rm);
- mc->emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &mr, 1);
}
/* ---- specific instruction emitters ---- */
@@ -140,7 +140,7 @@ void emit_mov_rr(MCEmitter* mc, int w, u32 dst, u32 src) {
u8 buf[16];
u32 n = x64_alu_rr_pack(
(X64AluRR){.w = w, .op = X64_OPC_MOV_RM_R, .dst = dst, .src = src}, buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
@@ -181,7 +181,7 @@ void emit_mov_load(MCEmitter* mc, u32 size, int signed_ext, u32 dst, u32 base,
.disp = disp},
buf);
}
- if (n) mc->emit_bytes(mc, buf, n);
+ if (n) mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
@@ -222,7 +222,7 @@ void emit_mov_store(MCEmitter* mc, u32 size, u32 src, u32 base, i32 disp) {
.disp = disp},
buf);
}
- if (n) mc->emit_bytes(mc, buf, n);
+ if (n) mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
@@ -233,7 +233,7 @@ void emit_lea(MCEmitter* mc, u32 dst, u32 base, i32 disp) {
(X64MovRMLoad){
.w = 1, .opc0 = X64_OPC_LEA, .dst = dst, .base = base, .disp = disp},
buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
@@ -258,7 +258,7 @@ static void emit_mem_idx_op(MCEmitter* mc, u8 prefix, int w, int force_rex,
buf[n++] = opc0;
}
n += x64_pack_mem_sib(buf + n, reg, base, index, log2_scale, disp);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
}
/* mov reg, [base + index<<log2_scale + disp]; size 1/2/4/8. */
@@ -319,7 +319,7 @@ void x64_emit_load_imm(MCEmitter* mc, int is64, u32 dst, i64 imm) {
u8 buf[16];
u32 n =
x64_mov_ri_pack((X64MovRI){.is64 = is64, .dst = dst, .imm = imm}, buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
@@ -330,7 +330,7 @@ void emit_alu_rr(MCEmitter* mc, int w, u8 op, u32 dst, u32 src) {
u8 buf[16];
u32 n = x64_alu_rr_pack((X64AluRR){.w = w, .op = op, .dst = dst, .src = src},
buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
@@ -338,7 +338,7 @@ void emit_imul_rr(MCEmitter* mc, int w, u32 dst, u32 src) {
u32 ofs = obj_pos(mc->obj, mc->section_id);
u8 buf[16];
u32 n = x64_imul_rr_pack((X64ImulRR){.w = w, .dst = dst, .src = src}, buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
@@ -346,7 +346,7 @@ void emit_f7_rm(MCEmitter* mc, int w, u32 sub, u32 reg) {
u32 ofs = obj_pos(mc->obj, mc->section_id);
u8 buf[16];
u32 n = x64_f7_rm_pack((X64F7RM){.w = w, .sub = sub, .reg = reg}, buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
@@ -354,7 +354,7 @@ void emit_shift_cl(MCEmitter* mc, int w, u32 sub, u32 reg) {
u32 ofs = obj_pos(mc->obj, mc->section_id);
u8 buf[16];
u32 n = x64_shift_cl_pack((X64ShiftCL){.w = w, .sub = sub, .reg = reg}, buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
@@ -364,14 +364,14 @@ void emit_shift_imm(MCEmitter* mc, int w, u32 sub, u32 reg, u8 imm) {
u8 buf[16];
u32 n = x64_shift_imm_pack(
(X64ShiftImm){.w = w, .sub = sub, .reg = reg, .imm = imm}, buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
void emit_cqo_or_cdq(MCEmitter* mc, int w) {
u8 buf[16];
u32 n = x64_nullary_pack((X64Nullary){.w = w, .opc0 = X64_OPC_CDQ_CQO}, buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
}
void emit_xor_self(MCEmitter* mc, int w, u32 r) {
@@ -385,7 +385,7 @@ void emit_cmp_imm8(MCEmitter* mc, int w, u32 reg, i8 imm) {
u32 n = x64_alu_imm8_pack(
(X64AluRmImm8){.w = w, .sub = X64_ALU_SUB_CMP, .reg = reg, .imm = imm},
buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
@@ -396,7 +396,7 @@ void emit_alu_imm8(MCEmitter* mc, int w, u32 sub, u32 reg, i8 imm) {
u8 buf[16];
u32 n = x64_alu_imm8_pack(
(X64AluRmImm8){.w = w, .sub = sub, .reg = reg, .imm = imm}, buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
@@ -406,7 +406,7 @@ void emit_alu_imm32(MCEmitter* mc, int w, u32 sub, u32 reg, i32 imm) {
u8 buf[16];
u32 n = x64_alu_imm32_pack(
(X64AluRmImm32){.w = w, .sub = sub, .reg = reg, .imm = imm}, buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
@@ -420,7 +420,7 @@ void emit_imul_imm8(MCEmitter* mc, int w, u32 dst, u32 src, i8 imm) {
u32 n = x64_imul_rri_pack(
(X64ImulRRI){.w = w, .imm32 = 0, .dst = dst, .src = src, .imm = imm},
buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
void emit_imul_imm32(MCEmitter* mc, int w, u32 dst, u32 src, i32 imm) {
@@ -429,7 +429,7 @@ void emit_imul_imm32(MCEmitter* mc, int w, u32 dst, u32 src, i32 imm) {
u32 n = x64_imul_rri_pack(
(X64ImulRRI){.w = w, .imm32 = 1, .dst = dst, .src = src, .imm = imm},
buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
@@ -452,7 +452,7 @@ void emit_setcc(MCEmitter* mc, u32 cc, u32 reg) {
u32 ofs = obj_pos(mc->obj, mc->section_id);
u8 buf[16];
u32 n = x64_setcc_pack((X64Setcc){.cc = cc, .reg = reg}, buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
@@ -465,7 +465,7 @@ void emit_movzx_r32_r8(MCEmitter* mc, u32 dst, u32 src) {
.dst = dst,
.src = src},
buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
@@ -505,17 +505,17 @@ void emit_extend_rr(MCEmitter* mc, int w, int signed_ext, u32 src_size, u32 dst,
* destination holds the value. */
if (dst != src) emit_mov_rr(mc, w, dst, src);
}
- if (n) mc->emit_bytes(mc, buf, n);
+ if (n) mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
void emit_ret(MCEmitter* mc) {
u8 op = X64_OPC_RET;
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
}
void emit_leave(MCEmitter* mc) {
u8 op = X64_OPC_LEAVE;
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
}
/* ---- SSE scalar FP encoders ---- */
@@ -526,7 +526,7 @@ void emit_sse_rr(MCEmitter* mc, u8 prefix, u8 opcode, u32 dst, u32 src) {
(X64SseRR){
.prefix = prefix, .opcode = opcode, .w = 0, .dst = dst, .src = src},
buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
void emit_sse_load(MCEmitter* mc, u8 prefix, u8 opcode, u32 dst, u32 base,
@@ -539,7 +539,7 @@ void emit_sse_load(MCEmitter* mc, u8 prefix, u8 opcode, u32 dst, u32 base,
.base = base,
.disp = disp},
buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
void emit_sse_store(MCEmitter* mc, u8 prefix, u8 opcode, u32 src, u32 base,
@@ -552,7 +552,7 @@ void emit_sse_store(MCEmitter* mc, u8 prefix, u8 opcode, u32 src, u32 base,
.base = base,
.disp = disp},
buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
void emit_sse_load_idx(MCEmitter* mc, u8 prefix, u8 opcode, u32 dst, u32 base,
@@ -585,6 +585,6 @@ void emit_sse_rr_w(MCEmitter* mc, u8 prefix, u8 opcode, int w, u32 dst,
(X64SseRR){
.prefix = prefix, .opcode = opcode, .w = w, .dst = dst, .src = src},
buf);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
if (mc->debug) debug_emit_row(mc->debug, mc->section_id, ofs, mc->loc);
}
diff --git a/src/arch/x64/native.c b/src/arch/x64/native.c
@@ -521,25 +521,25 @@ static void x64_emit_global_lea(NativeTarget* t, u32 dst_reg, ObjSymId sym,
u32 disp_pos;
emit_rex(mc, 1, dst_reg, 0, 0);
op = X64_OPC_MOV_R_RM;
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
{
u8 mr = modrm(0u, dst_reg & 7u, 5u); /* [rip + disp32] */
- mc->emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &mr, 1);
}
- disp_pos = mc->pos(mc);
+ disp_pos = mc_pos(mc);
emit_u32le(mc, 0);
- mc->emit_reloc_at(mc, sec, disp_pos, R_X64_REX_GOTPCRELX, sym, -4, 1, 0);
+ mc_emit_reloc_at(mc, sec, disp_pos, R_X64_REX_GOTPCRELX, sym, -4, 1, 0);
if (addend) {
i32 a = (i32)addend;
emit_rex(mc, 1, 0, 0, dst_reg);
if (imm_fits_i8(a)) {
u8 buf[3] = {X64_OPC_ALU_IMM8, modrm(3u, X64_ALU_SUB_ADD, dst_reg & 7u),
(u8)a};
- mc->emit_bytes(mc, buf, 3);
+ mc_emit_bytes(mc, buf, 3);
} else {
u8 buf[2] = {X64_OPC_ALU_IMM32,
modrm(3u, X64_ALU_SUB_ADD, dst_reg & 7u)};
- mc->emit_bytes(mc, buf, 2);
+ mc_emit_bytes(mc, buf, 2);
emit_u32le(mc, (u32)a);
}
}
@@ -549,14 +549,14 @@ static void x64_emit_global_lea(NativeTarget* t, u32 dst_reg, ObjSymId sym,
u8 op = X64_OPC_LEA;
u32 disp_pos;
emit_rex(mc, 1, dst_reg, 0, 0);
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
{
u8 mr = modrm(0u, dst_reg & 7u, 5u); /* [rip + disp32] */
- mc->emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &mr, 1);
}
- disp_pos = mc->pos(mc);
+ disp_pos = mc_pos(mc);
emit_u32le(mc, 0);
- mc->emit_reloc_at(mc, sec, disp_pos, x64_pcrel_reloc_for_sym(t, sym), sym,
+ mc_emit_reloc_at(mc, sec, disp_pos, x64_pcrel_reloc_for_sym(t, sym), sym,
addend - 4, 1, 0);
}
}
@@ -636,32 +636,32 @@ static void x64_emit_mem(X64NativeTarget* a, int is_load, NativeLoc reg,
u32 disp_pos;
if (fp) {
u8 prefix = sse_scalar_prefix(sz);
- mc->emit_bytes(mc, &prefix, 1);
+ mc_emit_bytes(mc, &prefix, 1);
emit_rex(mc, 0, r, 0, 0);
{
u8 op2[2] = {X64_OPC_TWOBYTE, (u8)(is_load ? 0x10u : 0x11u)};
- mc->emit_bytes(mc, op2, 2);
+ mc_emit_bytes(mc, op2, 2);
}
} else if (sz == 8 || sz == 4) {
emit_rex(mc, sz == 8, r, 0, 0);
{
u8 op = is_load ? X64_OPC_MOV_R_RM : X64_OPC_MOV_RM_R;
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
}
} else if (sz == 2) {
if (is_load) {
emit_rex(mc, 0, r, 0, 0);
{
u8 op2[2] = {X64_OPC_TWOBYTE, X64_OPC_MOVZX_W};
- mc->emit_bytes(mc, op2, 2);
+ mc_emit_bytes(mc, op2, 2);
}
} else {
u8 p = X64_OPSIZE_PFX;
- mc->emit_bytes(mc, &p, 1);
+ mc_emit_bytes(mc, &p, 1);
emit_rex(mc, 0, r, 0, 0);
{
u8 op = X64_OPC_MOV_RM_R;
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
}
}
} else { /* size 1 */
@@ -669,23 +669,23 @@ static void x64_emit_mem(X64NativeTarget* a, int is_load, NativeLoc reg,
emit_rex(mc, 0, r, 0, 0);
{
u8 op2[2] = {X64_OPC_TWOBYTE, X64_OPC_MOVZX_B};
- mc->emit_bytes(mc, op2, 2);
+ mc_emit_bytes(mc, op2, 2);
}
} else {
emit_rex_force(mc, 0, r, 0, 0);
{
u8 op = X64_OPC_MOV_RM_R8;
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
}
}
}
{
u8 mr = modrm(0u, r & 7u, 5u);
- mc->emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &mr, 1);
}
- disp_pos = mc->pos(mc);
+ disp_pos = mc_pos(mc);
emit_u32le(mc, 0);
- mc->emit_reloc_at(mc, sec, disp_pos, x64_pcrel_reloc_for_sym(t, sym), sym,
+ mc_emit_reloc_at(mc, sec, disp_pos, x64_pcrel_reloc_for_sym(t, sym), sym,
ad - 4, 1, 0);
return;
}
@@ -775,7 +775,7 @@ static void x64_load_addr(NativeTarget* t, NativeLoc dst, NativeAddr addr) {
n += x64_pack_rex(buf + n, 1, rd, idx, base);
buf[n++] = X64_OPC_LEA;
n += x64_pack_mem_sib(buf + n, rd, base, idx, scale, off);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
}
}
@@ -813,7 +813,7 @@ static u32 x64_addr_to_base_reg(X64NativeTarget* a, NativeAddr addr,
n += x64_pack_rex(buf + n, 1, scratch, idx, base);
buf[n++] = X64_OPC_LEA;
n += x64_pack_mem_sib(buf + n, scratch, base, idx, scale, off);
- mc->emit_bytes(mc, buf, n);
+ mc_emit_bytes(mc, buf, n);
}
return scratch;
}
@@ -1371,13 +1371,13 @@ static void x64_convert(NativeTarget* t, ConvKind k, NativeLoc dst,
int w_src = x64_is_64(t, src.type) ? 1 : 0;
u8 prefix = sse_scalar_prefix(native_type_size(t, dst.type));
if (k == CV_ITOF_U && w_src == 1) {
- MCLabel L_high = mc->label_new(mc);
- MCLabel L_done = mc->label_new(mc);
+ MCLabel L_high = mc_label_new(mc);
+ MCLabel L_done = mc_label_new(mc);
emit_test_self(mc, 1, rs);
emit_jcc_rel32(mc, X64_CC_S, L_high);
emit_sse_rr_w(mc, prefix, 0x2A, 1, rd, rs);
emit_jmp_rel32(mc, L_done);
- mc->label_place(mc, L_high);
+ mc_label_place(mc, L_high);
emit_mov_rr(mc, 1, X64_R11, rs);
emit_mov_rr(mc, 1, X64_RAX, rs);
emit_alu_imm8(mc, 1, X64_ALU_SUB_AND, X64_RAX, 1);
@@ -1385,7 +1385,7 @@ static void x64_convert(NativeTarget* t, ConvKind k, NativeLoc dst,
emit_alu_rr(mc, 1, X64_OPC_ALU_OR, X64_R11, X64_RAX);
emit_sse_rr_w(mc, prefix, 0x2A, 1, rd, X64_R11);
emit_sse_rr(mc, prefix, 0x58, rd, rd);
- mc->label_place(mc, L_done);
+ mc_label_place(mc, L_done);
return;
}
if (k == CV_ITOF_U) {
@@ -1404,8 +1404,8 @@ static void x64_convert(NativeTarget* t, ConvKind k, NativeLoc dst,
* (with the destination widened to 64 for u32) is exact. */
if (k == CV_FTOI_U && w_dst == 1) {
int dbl = native_type_size(t, src.type) == 8u;
- MCLabel L_small = mc->label_new(mc);
- MCLabel L_done = mc->label_new(mc);
+ MCLabel L_small = mc_label_new(mc);
+ MCLabel L_done = mc_label_new(mc);
/* limit = 2^63 in fp scratch. */
x64_emit_load_imm(
mc, 1, X64_R11,
@@ -1419,9 +1419,9 @@ static void x64_convert(NativeTarget* t, ConvKind k, NativeLoc dst,
x64_emit_load_imm(mc, 1, X64_R11, (i64)0x8000000000000000ull);
emit_alu_rr(mc, 1, X64_OPC_ALU_XOR, rd, X64_R11);
emit_jmp_rel32(mc, L_done);
- mc->label_place(mc, L_small);
+ mc_label_place(mc, L_small);
emit_sse_rr_w(mc, prefix, 0x2C, 1, rd, rs);
- mc->label_place(mc, L_done);
+ mc_label_place(mc, L_done);
return;
}
if (k == CV_FTOI_U) w_dst = 1; /* widen u32 result */
@@ -1473,22 +1473,22 @@ static void x64_reload(NativeTarget* t, NativeLoc dst, NativeFrameSlot slot,
static void emit_jmp_rel32(MCEmitter* mc, MCLabel l) {
u8 op = X64_OPC_JMP_REL32;
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
emit_u32le(mc, 0);
- mc->emit_label_ref(mc, l, R_PC32, 4, -4);
+ mc_emit_label_ref(mc, l, R_PC32, 4, -4);
}
static void emit_jcc_rel32(MCEmitter* mc, u32 cc, MCLabel l) {
u8 op[2] = {X64_OPC_TWOBYTE, (u8)(X64_OPC_JCC_BASE | (cc & 0xfu))};
- mc->emit_bytes(mc, op, 2);
+ mc_emit_bytes(mc, op, 2);
emit_u32le(mc, 0);
- mc->emit_label_ref(mc, l, R_PC32, 4, -4);
+ mc_emit_label_ref(mc, l, R_PC32, 4, -4);
}
static MCLabel x64_label_new(NativeTarget* t) {
- return t->mc->label_new(t->mc);
+ return mc_label_new(t->mc);
}
static void x64_label_place(NativeTarget* t, MCLabel l) {
- t->mc->label_place(t->mc, l);
+ mc_label_place(t->mc, l);
}
static void x64_jump(NativeTarget* t, MCLabel l) { emit_jmp_rel32(t->mc, l); }
@@ -1516,11 +1516,11 @@ static void x64_cmp_branch(NativeTarget* t, CmpOp op, NativeLoc aop,
static void x64_emit_indirect_rm(MCEmitter* mc, u32 r, u32 digit) {
if (r & 8u) {
u8 rex = X64_REX_BASE | X64_REX_B;
- mc->emit_bytes(mc, &rex, 1);
+ mc_emit_bytes(mc, &rex, 1);
}
{
u8 buf[2] = {X64_OP_JMP_RM64, modrm(3u, digit, r & 7u)};
- mc->emit_bytes(mc, buf, 2);
+ mc_emit_bytes(mc, buf, 2);
}
}
@@ -1546,15 +1546,15 @@ static void x64_load_label_addr(NativeTarget* t, NativeLoc dst, MCLabel l) {
emit_rex(mc, 1, rd, 0, 0);
{
u8 op = X64_OPC_LEA;
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
}
{
u8 mr = modrm(0u, rd & 7u, 5u); /* [rip + disp32] */
- mc->emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &mr, 1);
}
- disp_pos = mc->pos(mc);
+ disp_pos = mc_pos(mc);
emit_u32le(mc, 0);
- mc->emit_reloc_at(mc, mc->section_id, disp_pos, R_PC32, sym, -4, 1, 0);
+ mc_emit_reloc_at(mc, mc->section_id, disp_pos, R_PC32, sym, -4, 1, 0);
}
/* ============================ frame / lifecycle ============================
@@ -1773,12 +1773,12 @@ static void x64_func_begin_common(NativeTarget* t, const CGFuncDesc* fd) {
a->prologue_nbytes = a->abi->shadow_space ? X64_NDT_PROLOGUE_BYTES_WIN64
: X64_NDT_PROLOGUE_BYTES;
- mc->set_section(mc, fd->text_section_id);
- mc->emit_align(mc, 16, X64_NOP1);
- a->func_start = mc->pos(mc);
+ mc_set_section(mc, fd->text_section_id);
+ mc_emit_align(mc, 16, X64_NOP1);
+ a->func_start = mc_pos(mc);
mc_begin_function(mc, fd->sym, fd->text_section_id, a->func_start);
- if (mc->cfi_startproc) mc->cfi_startproc(mc);
- a->epilogue_label = mc->label_new(mc);
+ mc_cfi_startproc(mc);
+ a->epilogue_label = mc_label_new(mc);
}
/* Reserve the sret-pointer slot and (SysV) the 176-byte variadic reg-save
@@ -1834,7 +1834,7 @@ static void x64_func_begin(NativeTarget* t, const CGFuncDesc* fd) {
MCEmitter* mc = t->mc;
u32 i;
x64_func_begin_common(t, fd);
- a->prologue_pos = mc->pos(mc);
+ a->prologue_pos = mc_pos(mc);
for (i = 0; i < a->prologue_nbytes; ++i) emit1(mc, X64_NOP1);
x64_reserve_entry_saves(a);
x64_emit_variadic_reg_saves(a);
@@ -1962,14 +1962,14 @@ static void x64_func_begin_known_frame(NativeTarget* t, const CGFuncDesc* fd,
a->redzone_leaf = !a->slim_frame && a->abi->shadow_space == 0 && frame &&
frame->is_leaf && !frame->has_asm && !a->frame.has_alloca &&
a->frame.max_outgoing == 0 && frame_size <= 128u;
- a->prologue_pos = mc->pos(mc);
+ a->prologue_pos = mc_pos(mc);
nbytes = x64_build_prologue(a, buf, sizeof buf, frame_size, cs_int, n_int,
cs_fp, n_fp, a->slim_frame || a->redzone_leaf,
&chkstk_disp_pos);
- mc->emit_bytes(mc, buf, nbytes);
+ mc_emit_bytes(mc, buf, nbytes);
if (chkstk_disp_pos != (u32)-1) {
ObjSymId chk = x64_chkstk_sym(t);
- mc->emit_reloc_at(mc, mc->section_id, a->prologue_pos + chkstk_disp_pos,
+ mc_emit_reloc_at(mc, mc->section_id, a->prologue_pos + chkstk_disp_pos,
R_X64_PLT32, chk, -4, 1, 0);
}
a->prologue_nbytes = nbytes; /* exact length: used for the CFI post offset */
@@ -1991,7 +1991,7 @@ static void x64_func_end(NativeTarget* t) {
a->frame_size_final = frame_size;
/* Epilogue. */
- mc->label_place(mc, a->epilogue_label);
+ mc_label_place(mc, a->epilogue_label);
x64_emit_callee_restores(a);
emit_leave(mc);
emit_ret(mc);
@@ -2011,7 +2011,7 @@ static void x64_func_end(NativeTarget* t) {
obj_patch(obj, sec, a->prologue_pos, buf, a->prologue_nbytes);
if (chkstk_disp_pos != (u32)-1) {
ObjSymId chk = x64_chkstk_sym(t);
- mc->emit_reloc_at(mc, sec, a->prologue_pos + chkstk_disp_pos, R_X64_PLT32,
+ mc_emit_reloc_at(mc, sec, a->prologue_pos + chkstk_disp_pos, R_X64_PLT32,
chk, -4, 1, 0);
}
}
@@ -2028,34 +2028,34 @@ static void x64_func_end(NativeTarget* t) {
}
/* CFI: after the prologue, CFA = rbp + 16; rbp at cfa-16, ra at cfa-8. */
- if (mc->cfi_set_next_pc_offset && mc->cfi_def_cfa && mc->cfi_offset) {
+ {
/* Body starts past the prologue. prologue_nbytes is the reserved NOP-region
* size on the single-pass path and the exact prologue length on the
* known-frame path (set in x64_func_begin_known_frame). */
u32 post = a->prologue_pos + a->prologue_nbytes;
u32 k;
- mc->cfi_set_next_pc_offset(mc, post - a->func_start);
+ mc_cfi_set_next_pc_offset(mc, post - a->func_start);
/* CFI register operands are DWARF numbers, which differ from the x86-64
* hardware encoding for rbp/rsp/rsi/rdi/rcx/rdx (e.g. rbp is HW 5 but
* DWARF 6). Map every hardware GPR through x64_dwarf_from_hw_gpr; rip's
* DWARF number (16) is already correct. */
- mc->cfi_def_cfa(mc, x64_dwarf_from_hw_gpr(X64_RBP), 16);
- mc->cfi_offset(mc, x64_dwarf_from_hw_gpr(X64_RBP), -16);
- mc->cfi_offset(mc, 16u /* rip */, -8);
+ mc_cfi_def_cfa(mc, x64_dwarf_from_hw_gpr(X64_RBP), 16);
+ mc_cfi_offset(mc, x64_dwarf_from_hw_gpr(X64_RBP), -16);
+ mc_cfi_offset(mc, 16u /* rip */, -8);
for (k = 0; k < n_int; ++k) {
i32 off = x64_cs_int_off(xmm_base, n_fp, k);
- mc->cfi_offset(mc, x64_dwarf_from_hw_gpr(cs_int[k]), off);
+ mc_cfi_offset(mc, x64_dwarf_from_hw_gpr(cs_int[k]), off);
}
}
- end = mc->pos(mc);
+ end = mc_pos(mc);
obj_symbol_define(obj, a->func->sym, sec, (u64)a->func_start,
(u64)(end - a->func_start));
if (a->func->atomize)
obj_atom_define(obj, sec, a->func_start, end - a->func_start, a->func->sym,
0);
if (mc->debug) debug_func_pc_range(mc->debug, sec, a->func_start, end);
- if (mc->cfi_endproc) mc->cfi_endproc(mc);
+ mc_cfi_endproc(mc);
mc_end_function(mc);
a->func = NULL;
}
@@ -2705,10 +2705,10 @@ static void x64_emit_tail_site(NativeTarget* t, NativeLoc callee) {
if (callee.kind == NATIVE_LOC_GLOBAL) {
u8 op = X64_OPC_JMP_REL32;
u32 disp_pos;
- mc->emit_bytes(mc, &op, 1);
- disp_pos = mc->pos(mc);
+ mc_emit_bytes(mc, &op, 1);
+ disp_pos = mc_pos(mc);
emit_u32le(mc, 0);
- mc->emit_reloc_at(mc, sec, disp_pos, R_X64_PLT32, callee.v.global.sym,
+ mc_emit_reloc_at(mc, sec, disp_pos, R_X64_PLT32, callee.v.global.sym,
callee.v.global.addend - 4, 1, 0);
} else if (callee.kind == NATIVE_LOC_REG) {
/* indirect callee was staged in r11 by plan_call */
@@ -2729,10 +2729,10 @@ static void x64_emit_call(NativeTarget* t, const NativeCallPlan* plan) {
if (plan->callee.kind == NATIVE_LOC_GLOBAL) {
u8 op = X64_OPC_CALL_REL32;
u32 disp_pos;
- mc->emit_bytes(mc, &op, 1);
- disp_pos = mc->pos(mc);
+ mc_emit_bytes(mc, &op, 1);
+ disp_pos = mc_pos(mc);
emit_u32le(mc, 0);
- mc->emit_reloc_at(mc, sec, disp_pos, R_X64_PLT32, plan->callee.v.global.sym,
+ mc_emit_reloc_at(mc, sec, disp_pos, R_X64_PLT32, plan->callee.v.global.sym,
plan->callee.v.global.addend - 4, 1, 0);
return;
}
@@ -2835,7 +2835,7 @@ static void x64_alloca(NativeTarget* t, NativeLoc dst, NativeLoc size,
emit_rex(mc, 1, 0, 0, X64_RSP);
{
u8 buf[2] = {X64_OPC_ALU_IMM32, modrm(3u, X64_ALU_SUB_SUB, X64_RSP)};
- mc->emit_bytes(mc, buf, 2);
+ mc_emit_bytes(mc, buf, 2);
}
emit_u32le(mc, (u32)aligned);
} else {
@@ -2844,7 +2844,7 @@ static void x64_alloca(NativeTarget* t, NativeLoc dst, NativeLoc size,
emit_rex(mc, 1, 0, 0, X64_RAX);
{
u8 buf[3] = {X64_OPC_ALU_IMM8, modrm(3u, X64_ALU_SUB_AND, X64_RAX), 0xF0};
- mc->emit_bytes(mc, buf, 3);
+ mc_emit_bytes(mc, buf, 3);
}
emit_alu_rr(mc, 1, X64_OPC_ALU_SUB, X64_RSP, X64_RAX);
}
@@ -2860,18 +2860,18 @@ static void x64_alloca(NativeTarget* t, NativeLoc dst, NativeLoc size,
emit_rex(mc, 1, rd, 0, X64_RSP);
{
u8 op = X64_OPC_LEA;
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
}
{
u8 mr = modrm(2u, rd & 7u, 4u);
- mc->emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &mr, 1);
}
{
u8 s = sib(0u, 4u, X64_RSP);
- mc->emit_bytes(mc, &s, 1);
+ mc_emit_bytes(mc, &s, 1);
}
a->patches[a->npatches].kind = X64_PATCH_ALLOCA;
- a->patches[a->npatches].pos = mc->pos(mc);
+ a->patches[a->npatches].pos = mc_pos(mc);
a->npatches++;
a->nalloca++;
emit_u32le(mc, 0); /* placeholder disp32 */
@@ -2889,19 +2889,19 @@ static void x64_tls_addr_of_win64(NativeTarget* t, NativeLoc dst, ObjSymId sym,
/* (1) mov rd, gs:[0x58]. */
{
u8 gs = 0x65;
- mc->emit_bytes(mc, &gs, 1);
+ mc_emit_bytes(mc, &gs, 1);
emit_rex(mc, 1, rd, 0, 0);
{
u8 op = X64_OPC_MOV_R_RM;
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
}
{
u8 mr = modrm(0u, rd & 7u, 4u);
- mc->emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &mr, 1);
}
{
u8 s = sib(0u, 4u, 5u);
- mc->emit_bytes(mc, &s, 1);
+ mc_emit_bytes(mc, &s, 1);
}
emit_u32le(mc, 0x58u);
}
@@ -2915,35 +2915,35 @@ static void x64_tls_addr_of_win64(NativeTarget* t, NativeLoc dst, ObjSymId sym,
idx_sym =
obj_symbol(t->obj, idx_name, SB_GLOBAL, SK_UNDEF, OBJ_SEC_NONE, 0, 0);
rex_r = X64_REX_BASE | X64_REX_R;
- mc->emit_bytes(mc, &rex_r, 1);
+ mc_emit_bytes(mc, &rex_r, 1);
op = X64_OPC_MOV_R_RM;
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
mr = modrm(0u, 3u, 5u); /* r11&7, rip-rel */
- mc->emit_bytes(mc, &mr, 1);
- disp_pos = mc->pos(mc);
+ mc_emit_bytes(mc, &mr, 1);
+ disp_pos = mc_pos(mc);
emit_u32le(mc, 0);
- mc->emit_reloc_at(mc, sec, disp_pos, R_PC32, idx_sym, -4, 1, 0);
+ mc_emit_reloc_at(mc, sec, disp_pos, R_PC32, idx_sym, -4, 1, 0);
}
/* (3) mov rd, [rd + r11*8]. */
{
u8 rex = X64_REX_BASE | X64_REX_W | X64_REX_X;
u8 op;
if (rd & 8u) rex |= X64_REX_R | X64_REX_B;
- mc->emit_bytes(mc, &rex, 1);
+ mc_emit_bytes(mc, &rex, 1);
op = X64_OPC_MOV_R_RM;
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
if ((rd & 7u) == 5u) {
u8 mr = modrm(1u, rd & 7u, 4u);
u8 s = sib(3u, 3u, rd & 7u);
u8 zero = 0;
- mc->emit_bytes(mc, &mr, 1);
- mc->emit_bytes(mc, &s, 1);
- mc->emit_bytes(mc, &zero, 1);
+ mc_emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &s, 1);
+ mc_emit_bytes(mc, &zero, 1);
} else {
u8 mr = modrm(0u, rd & 7u, 4u);
u8 s = sib(3u, 3u, rd & 7u);
- mc->emit_bytes(mc, &mr, 1);
- mc->emit_bytes(mc, &s, 1);
+ mc_emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &s, 1);
}
}
/* (4) lea rd, [rd + sym@SECREL]. */
@@ -2952,21 +2952,21 @@ static void x64_tls_addr_of_win64(NativeTarget* t, NativeLoc dst, ObjSymId sym,
u8 op;
u32 disp_pos;
if (rd & 8u) rex |= X64_REX_R | X64_REX_B;
- mc->emit_bytes(mc, &rex, 1);
+ mc_emit_bytes(mc, &rex, 1);
op = X64_OPC_LEA;
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
if ((rd & 7u) == 4u) {
u8 mr = modrm(2u, rd & 7u, 4u);
u8 s = sib(0u, 4u, rd & 7u);
- mc->emit_bytes(mc, &mr, 1);
- mc->emit_bytes(mc, &s, 1);
+ mc_emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &s, 1);
} else {
u8 mr = modrm(2u, rd & 7u, rd & 7u);
- mc->emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &mr, 1);
}
- disp_pos = mc->pos(mc);
+ disp_pos = mc_pos(mc);
emit_u32le(mc, 0);
- mc->emit_reloc_at(mc, sec, disp_pos, R_COFF_SECREL, sym, addend, 1, 0);
+ mc_emit_reloc_at(mc, sec, disp_pos, R_COFF_SECREL, sym, addend, 1, 0);
}
}
@@ -2989,19 +2989,19 @@ static void x64_tls_addr_of_macho(NativeTarget* t, NativeLoc dst, ObjSymId sym,
emit_rex(mc, 1, X64_RDI, 0, 0);
{
u8 op = X64_OPC_MOV_R_RM;
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
}
{
u8 mr = modrm(0u, X64_RDI & 7u, 5u); /* [rip + disp32] */
- mc->emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &mr, 1);
}
- disp_pos = mc->pos(mc);
+ disp_pos = mc_pos(mc);
emit_u32le(mc, 0);
- mc->emit_reloc_at(mc, sec, disp_pos, R_X64_TLV, sym, -4, 1, 0);
+ mc_emit_reloc_at(mc, sec, disp_pos, R_X64_TLV, sym, -4, 1, 0);
/* callq *(%rdi) (FF /2, mem [rdi]) -> %rax = &storage. */
{
u8 call[2] = {0xFFu, modrm(0u, 2u, X64_RDI & 7u)};
- mc->emit_bytes(mc, call, 2);
+ mc_emit_bytes(mc, call, 2);
}
/* %rax += addend (byte offset into the variable). */
if (addend) {
@@ -3011,11 +3011,11 @@ static void x64_tls_addr_of_macho(NativeTarget* t, NativeLoc dst, ObjSymId sym,
if (imm_fits_i8(a)) {
u8 buf[3] = {X64_OPC_ALU_IMM8, modrm(3u, X64_ALU_SUB_ADD, X64_RAX & 7u),
(u8)a};
- mc->emit_bytes(mc, buf, 3);
+ mc_emit_bytes(mc, buf, 3);
} else {
u8 buf[2] = {X64_OPC_ALU_IMM32,
modrm(3u, X64_ALU_SUB_ADD, X64_RAX & 7u)};
- mc->emit_bytes(mc, buf, 2);
+ mc_emit_bytes(mc, buf, 2);
emit_u32le(mc, (u32)a);
}
} else {
@@ -3045,19 +3045,19 @@ static void x64_tls_addr_of(NativeTarget* t, NativeLoc dst, ObjSymId sym,
/* mov rd, fs:[0]. */
{
u8 fs = 0x64;
- mc->emit_bytes(mc, &fs, 1);
+ mc_emit_bytes(mc, &fs, 1);
emit_rex(mc, 1, rd, 0, 0);
{
u8 op = X64_OPC_MOV_R_RM;
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
}
{
u8 mr = modrm(0u, rd & 7u, 4u);
- mc->emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &mr, 1);
}
{
u8 s = sib(0u, 4u, 5u);
- mc->emit_bytes(mc, &s, 1);
+ mc_emit_bytes(mc, &s, 1);
}
emit_u32le(mc, 0);
}
@@ -3065,31 +3065,31 @@ static void x64_tls_addr_of(NativeTarget* t, NativeLoc dst, ObjSymId sym,
emit_rex(mc, 1, rd, 0, rd);
{
u8 op = X64_OPC_LEA;
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
}
if ((rd & 7u) == 4u) {
u8 mr = modrm(2u, rd & 7u, 4u);
u8 s = sib(0u, 4u, rd & 7u);
- mc->emit_bytes(mc, &mr, 1);
- mc->emit_bytes(mc, &s, 1);
+ mc_emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &s, 1);
} else {
u8 mr = modrm(2u, rd & 7u, rd & 7u);
- mc->emit_bytes(mc, &mr, 1);
+ mc_emit_bytes(mc, &mr, 1);
}
- disp_pos = mc->pos(mc);
+ disp_pos = mc_pos(mc);
emit_u32le(mc, 0);
- mc->emit_reloc_at(mc, sec, disp_pos, R_X64_TPOFF32, sym, addend, 0, 0);
+ mc_emit_reloc_at(mc, sec, disp_pos, R_X64_TPOFF32, sym, addend, 0, 0);
}
/* ============================ atomics ============================ */
static void emit_lock_prefix(MCEmitter* mc) {
u8 b = 0xF0;
- mc->emit_bytes(mc, &b, 1);
+ mc_emit_bytes(mc, &b, 1);
}
static void emit_mfence(MCEmitter* mc) {
u8 b[3] = {0x0F, 0xAE, 0xF0};
- mc->emit_bytes(mc, b, 3);
+ mc_emit_bytes(mc, b, 3);
}
/* Resolve an atomic addr to a bare base register (r11) + disp 0. */
@@ -3122,7 +3122,7 @@ static void x64_atomic_store(NativeTarget* t, NativeAddr addr, NativeLoc src,
emit_rex(mc, w, X64_RAX, 0, base);
{
u8 op = 0x87; /* xchg r/m, r */
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
}
emit_mem_operand(mc, X64_RAX, base, 0);
return;
@@ -3157,7 +3157,7 @@ static void x64_atomic_rmw(NativeTarget* t, KitCgAtomicOp op, NativeLoc dst,
emit_rex(mc, w, X64_RDX, 0, base);
{
u8 op2[2] = {X64_OPC_TWOBYTE, 0xC1}; /* xadd */
- mc->emit_bytes(mc, op2, 2);
+ mc_emit_bytes(mc, op2, 2);
}
emit_mem_operand(mc, X64_RDX, base, 0);
if (dr != X64_RDX) emit_mov_rr(mc, w, dr, X64_RDX);
@@ -3168,7 +3168,7 @@ static void x64_atomic_rmw(NativeTarget* t, KitCgAtomicOp op, NativeLoc dst,
emit_rex(mc, w, X64_RDX, 0, base);
{
u8 op2 = 0x87; /* xchg */
- mc->emit_bytes(mc, &op2, 1);
+ mc_emit_bytes(mc, &op2, 1);
}
emit_mem_operand(mc, X64_RDX, base, 0);
if (dr != X64_RDX) emit_mov_rr(mc, w, dr, X64_RDX);
@@ -3176,9 +3176,9 @@ static void x64_atomic_rmw(NativeTarget* t, KitCgAtomicOp op, NativeLoc dst,
}
/* AND/OR/XOR/NAND: cmpxchg retry loop. rax=prior, rcx=new, rdx=val. */
{
- MCLabel retry = mc->label_new(mc);
+ MCLabel retry = mc_label_new(mc);
emit_mov_load(mc, sz, 0, X64_RAX, base, 0);
- mc->label_place(mc, retry);
+ mc_label_place(mc, retry);
emit_mov_rr(mc, w, X64_RCX, X64_RAX);
switch (op) {
case KIT_CG_ATOMIC_AND:
@@ -3201,7 +3201,7 @@ static void x64_atomic_rmw(NativeTarget* t, KitCgAtomicOp op, NativeLoc dst,
emit_rex(mc, w, X64_RCX, 0, base);
{
u8 op2[2] = {X64_OPC_TWOBYTE, 0xB1}; /* cmpxchg */
- mc->emit_bytes(mc, op2, 2);
+ mc_emit_bytes(mc, op2, 2);
}
emit_mem_operand(mc, X64_RCX, base, 0);
emit_jcc_rel32(mc, X64_CC_NE, retry);
@@ -3240,7 +3240,7 @@ static void x64_atomic_cas(NativeTarget* t, NativeLoc prior, NativeLoc ok,
emit_rex(mc, w, X64_RCX, 0, X64_RAX);
{
u8 xchg[2] = {0x87, modrm(3u, X64_RCX, X64_RAX)};
- mc->emit_bytes(mc, xchg, 2);
+ mc_emit_bytes(mc, xchg, 2);
}
} else if (rdes == X64_RAX) {
/* desired sits in rax; move it to rcx before rax is overwritten. */
@@ -3254,7 +3254,7 @@ static void x64_atomic_cas(NativeTarget* t, NativeLoc prior, NativeLoc ok,
emit_rex(mc, w, X64_RCX, 0, base);
{
u8 op2[2] = {X64_OPC_TWOBYTE, 0xB1}; /* cmpxchg [base], rcx */
- mc->emit_bytes(mc, op2, 2);
+ mc_emit_bytes(mc, op2, 2);
}
emit_mem_operand(mc, X64_RCX, base, 0);
emit_setcc(mc, X64_CC_E, rok);
@@ -3294,17 +3294,17 @@ static void x64_add_mem_imm(MCEmitter* mc, int w, u32 base, i32 disp, i8 imm) {
u8 op = X64_OPC_ALU_IMM8;
u8 b;
emit_rex(mc, w, 0, 0, base);
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
emit_mem_operand(mc, X64_ALU_SUB_ADD, base, disp); /* modrm.reg = /0 (ADD) */
b = (u8)imm;
- mc->emit_bytes(mc, &b, 1);
+ mc_emit_bytes(mc, &b, 1);
}
/* add r64, [base+disp] (0x03 /r). */
static void x64_add_reg_mem(MCEmitter* mc, u32 dst, u32 base, i32 disp) {
u8 op = 0x03;
emit_rex(mc, 1, dst, 0, base);
- mc->emit_bytes(mc, &op, 1);
+ mc_emit_bytes(mc, &op, 1);
emit_mem_operand(mc, dst, base, disp);
}
@@ -3369,8 +3369,8 @@ static void x64_va_arg_core(X64NativeTarget* a, NativeLoc dst, NativeAddr ap,
u32 offs_field = is_fp ? 4u : 0u;
u32 max_offs = is_fp ? 176u : 48u;
i8 stride = is_fp ? 16 : 8;
- MCLabel L_stack = mc->label_new(mc);
- MCLabel L_done = mc->label_new(mc);
+ MCLabel L_stack = mc_label_new(mc);
+ MCLabel L_done = mc_label_new(mc);
/* gp32 = ap[offs]; cmp gp32, max; jae L_stack. Use the imm8 form when the
* threshold fits (gp_offset max 48) so the encoding is canonical and the
* `cc -S | as` round-trip reproduces it; fp_offset max 176 needs imm32. */
@@ -3390,14 +3390,14 @@ static void x64_va_arg_core(X64NativeTarget* a, NativeLoc dst, NativeAddr ap,
emit_mov_load(mc, sz, 0, dr, gp, 0);
emit_jmp_rel32(mc, L_done);
/* stack path: gp = ap[8] (overflow area); load; ap[8] += 8. */
- mc->label_place(mc, L_stack);
+ mc_label_place(mc, L_stack);
emit_mov_load(mc, 8, 0, gp, ap_base, 8);
if (is_fp)
emit_sse_load(mc, sse_scalar_prefix(sz), 0x10, dr, gp, 0);
else
emit_mov_load(mc, sz, 0, dr, gp, 0);
x64_add_mem_imm(mc, 1, ap_base, 8, 8);
- mc->label_place(mc, L_done);
+ mc_label_place(mc, L_done);
}
}
@@ -3448,11 +3448,11 @@ static void x64_va_copy_native(NativeTarget* t, NativeLoc dst, NativeLoc src) {
static void emit_popcnt(MCEmitter* mc, int w, u32 dst, u32 src) {
u8 p = 0xF3;
- mc->emit_bytes(mc, &p, 1);
+ mc_emit_bytes(mc, &p, 1);
emit_rex(mc, w, dst, 0, src);
{
u8 op[2] = {X64_OPC_TWOBYTE, 0xB8};
- mc->emit_bytes(mc, op, 2);
+ mc_emit_bytes(mc, op, 2);
}
emit_rm_reg(mc, dst, src);
}
@@ -3460,7 +3460,7 @@ static void emit_bs(MCEmitter* mc, int w, u8 opcode2, u32 dst, u32 src) {
emit_rex(mc, w, dst, 0, src);
{
u8 op[2] = {X64_OPC_TWOBYTE, opcode2};
- mc->emit_bytes(mc, op, 2);
+ mc_emit_bytes(mc, op, 2);
}
emit_rm_reg(mc, dst, src);
}
@@ -3468,26 +3468,26 @@ static void emit_bswap(MCEmitter* mc, int w, u32 reg) {
emit_rex(mc, w, 0, 0, reg);
{
u8 op[2] = {X64_OPC_TWOBYTE, (u8)(0xC8 + (reg & 7u))};
- mc->emit_bytes(mc, op, 2);
+ mc_emit_bytes(mc, op, 2);
}
}
static void emit_rol16_imm8(MCEmitter* mc, u32 reg, u8 imm) {
u8 p = X64_OPSIZE_PFX;
- mc->emit_bytes(mc, &p, 1);
+ mc_emit_bytes(mc, &p, 1);
emit_rex(mc, 0, 0, 0, reg);
{
u8 buf[3] = {X64_OPC_SHIFT_IMM, modrm(3u, 0u, reg & 7u), imm};
- mc->emit_bytes(mc, buf, 3);
+ mc_emit_bytes(mc, buf, 3);
}
}
static void emit_ud2(MCEmitter* mc) {
u8 b[2] = {0x0F, 0x0B};
- mc->emit_bytes(mc, b, 2);
+ mc_emit_bytes(mc, b, 2);
}
static void emit_syscall(MCEmitter* mc) {
u8 b[2] = {0x0F, 0x05};
- mc->emit_bytes(mc, b, 2);
+ mc_emit_bytes(mc, b, 2);
}
static void x64_intrinsic(NativeTarget* t, IntrinKind kind,
@@ -3654,28 +3654,28 @@ static void x64_intrinsic(NativeTarget* t, IntrinKind kind,
}
case INTRIN_CPU_NOP: {
u8 b = 0x90; /* NOP */
- mc->emit_bytes(mc, &b, 1);
+ mc_emit_bytes(mc, &b, 1);
return;
}
case INTRIN_CPU_YIELD: {
u8 b[2] = {0xF3, 0x90}; /* PAUSE */
- mc->emit_bytes(mc, b, 2);
+ mc_emit_bytes(mc, b, 2);
return;
}
case INTRIN_DMB:
case INTRIN_DSB: {
u8 b[3] = {0x0F, 0xAE, 0xF0}; /* MFENCE: full-system memory barrier */
- mc->emit_bytes(mc, b, 3);
+ mc_emit_bytes(mc, b, 3);
return;
}
case INTRIN_IRQ_DISABLE: {
u8 b = 0xFA; /* CLI (privileged) */
- mc->emit_bytes(mc, &b, 1);
+ mc_emit_bytes(mc, &b, 1);
return;
}
case INTRIN_IRQ_ENABLE: {
u8 b = 0xFB; /* STI (privileged) */
- mc->emit_bytes(mc, &b, 1);
+ mc_emit_bytes(mc, &b, 1);
return;
}
case INTRIN_FRAME_ADDRESS:
@@ -4183,7 +4183,7 @@ static void x64_asm_block_native(NativeTarget* t, const char* tmpl,
static void x64_trap(NativeTarget* t) { emit_ud2(t->mc); }
static void x64_set_loc(NativeTarget* t, SrcLoc loc) {
x64_of(t)->loc = loc;
- if (t->mc->set_loc) t->mc->set_loc(t->mc, loc);
+ mc_set_loc(t->mc, loc);
}
/* Physical registers each x86-64 instruction's encoding clobbers as a side
diff --git a/src/asm/asm.c b/src/asm/asm.c
@@ -167,7 +167,7 @@ static void set_section(AsmDriver* d, Sym name, SecKind kind, u16 flags,
u32 align) {
ObjSecId id = ensure_section(d, name, kind, flags, align);
d->cur_sec = id;
- d->mc->set_section(d->mc, id);
+ mc_set_section(d->mc, id);
}
/* ---- symbol management ---- */
@@ -474,7 +474,7 @@ ObjSecId asm_driver_cur_section(AsmDriver* d) {
if (!d->n_text) d->n_text = pool_intern_slice(d->pool, SLICE_LIT(".text"));
d->cur_sec =
ensure_section(d, d->n_text, SEC_TEXT, (u16)(SF_ALLOC | SF_EXEC), 4);
- d->mc->set_section(d->mc, d->cur_sec);
+ mc_set_section(d->mc, d->cur_sec);
}
return d->cur_sec;
}
@@ -656,7 +656,7 @@ static void emit_le(AsmDriver* d, u64 v, u32 width) {
u8 buf[8];
for (u32 i = 0; i < width; ++i) buf[i] = (u8)(v >> (8 * i));
(void)asm_driver_cur_section(d);
- d->mc->emit_bytes(d->mc, buf, width);
+ mc_emit_bytes(d->mc, buf, width);
}
static void emit_int_directive(AsmDriver* d, u32 width) {
@@ -680,7 +680,7 @@ static void emit_int_directive(AsmDriver* d, u32 width) {
else
d_panicf(d, "asm: symbolic .byte/.hword not supported");
(void)asm_driver_cur_section(d);
- u32 ofs = d->mc->pos(d->mc);
+ u32 ofs = mc_pos(d->mc);
/* Write the addend into the data field, not zero. Mach-O relocations
* carry the addend implicitly in the relocated field (REL form); writing
* zero loses it (every `.quad sym+N` would resolve to sym+0 — a switch
@@ -688,7 +688,7 @@ static void emit_int_directive(AsmDriver* d, u32 width) {
* the same way. On ELF (RELA) the linker overwrites the field with S+A,
* so the pre-written value is harmless there. */
emit_le(d, (u64)e.value, width);
- d->mc->emit_reloc_at(d->mc, d->cur_sec, ofs, k, e.sym, e.value, 1, 0);
+ mc_emit_reloc_at(d->mc, d->cur_sec, ofs, k, e.sym, e.value, 1, 0);
} else {
emit_le(d, (u64)e.value, width);
}
@@ -962,7 +962,7 @@ static void do_directive(AsmDriver* d, Sym name) {
ObjSecId sid = ensure_section_ex(d, sname, kind, sem, flags, 1);
if (entsize) obj_section_set_entsize(d->ob, sid, entsize);
d->cur_sec = sid;
- d->mc->set_section(d->mc, sid);
+ mc_set_section(d->mc, sid);
}
return;
}
@@ -1053,7 +1053,7 @@ static void do_directive(AsmDriver* d, Sym name) {
(void)d_next(d);
const ObjSym* os = obj_symbol_get(d->ob, id);
if (os && os->section_id == d->cur_sec)
- sz = (i64)d->mc->pos(d->mc) - (i64)os->value;
+ sz = (i64)mc_pos(d->mc) - (i64)os->value;
}
}
} else {
@@ -1116,7 +1116,7 @@ static void do_directive(AsmDriver* d, Sym name) {
size_t cap = 0;
decode_string(d, t.spelling, &buf, &n, &cap);
(void)asm_driver_cur_section(d);
- d->mc->emit_bytes(d->mc, buf, n);
+ mc_emit_bytes(d->mc, buf, n);
if (term) emit_le(d, 0, 1);
d->heap->free(d->heap, buf, cap);
if (!asm_driver_eat_comma(d)) break;
@@ -1131,7 +1131,7 @@ static void do_directive(AsmDriver* d, Sym name) {
if (asm_driver_eat_comma(d)) fill = asm_driver_parse_const(d);
if (n > 0) {
(void)asm_driver_cur_section(d);
- d->mc->emit_fill(d->mc, (size_t)n, (u8)fill);
+ mc_emit_fill(d->mc, (size_t)n, (u8)fill);
}
d_skip_to_eol(d);
return;
@@ -1153,7 +1153,7 @@ static void do_directive(AsmDriver* d, Sym name) {
if (asm_driver_eat_comma(d)) fill = asm_driver_parse_const(d);
if (a <= 0 || (a & (a - 1))) d_panicf(d, "asm: .align: not a power of 2");
(void)asm_driver_cur_section(d);
- d->mc->emit_align(d->mc, (u32)a, (u8)fill);
+ mc_emit_align(d->mc, (u32)a, (u8)fill);
d_skip_to_eol(d);
return;
}
@@ -1163,7 +1163,7 @@ static void do_directive(AsmDriver* d, Sym name) {
if (asm_driver_eat_comma(d)) fill = asm_driver_parse_const(d);
if (lg < 0 || lg > 16) d_panicf(d, "asm: .p2align: out of range");
(void)asm_driver_cur_section(d);
- d->mc->emit_align(d->mc, 1u << (u32)lg, (u8)fill);
+ mc_emit_align(d->mc, 1u << (u32)lg, (u8)fill);
d_skip_to_eol(d);
return;
}
@@ -1234,7 +1234,7 @@ static void do_directive(AsmDriver* d, Sym name) {
buf[n++] = b;
} while (uv);
}
- d->mc->emit_bytes(d->mc, buf, n);
+ mc_emit_bytes(d->mc, buf, n);
if (!asm_driver_eat_comma(d)) break;
}
d_skip_to_eol(d);
@@ -1339,7 +1339,7 @@ static void process_label(AsmDriver* d, Sym name) {
const ObjSym* os = obj_symbol_get(d->ob, id);
if (os && os->section_id != OBJ_SEC_NONE)
d_panicf(d, "asm: symbol defined twice");
- obj_symbol_define(d->ob, id, d->cur_sec, (u64)d->mc->pos(d->mc), 0);
+ obj_symbol_define(d->ob, id, d->cur_sec, (u64)mc_pos(d->mc), 0);
/* Promote SK_UNDEF (forward ref via reloc) to SK_NOTYPE so it's a
* real defined symbol; explicit `.type SYM, @function` will refine. */
if (os && os->kind == SK_UNDEF) sym_mut(d, id)->kind = (u16)SK_NOTYPE;
diff --git a/src/cg/native_direct_target.c b/src/cg/native_direct_target.c
@@ -1248,7 +1248,7 @@ static void nd_local_static_data_label_addr(CgTarget* t, Label target,
memset(zero, 0, sizeof zero);
off = d->local_static_base + d->local_static_size;
obj_write(t->obj, d->local_static_sec, zero, width);
- d->native->mc->emit_label_data_reloc(d->native->mc, d->local_static_sec, off,
+ mc_emit_label_data_reloc(d->native->mc, d->local_static_sec, off,
nd_mc_label(d, target), kind, width,
addend);
d->local_static_size += width;
diff --git a/src/opt/pass_native_emit.c b/src/opt/pass_native_emit.c
@@ -113,7 +113,7 @@ static void emit_local_static_label_addr(NativeEmitCtx* e, MCLabel target,
memset(zero, 0, sizeof zero);
off = e->local_static_base + e->local_static_size;
obj_write(e->target->obj, e->local_static_sec, zero, width);
- e->target->mc->emit_label_data_reloc(e->target->mc, e->local_static_sec, off,
+ mc_emit_label_data_reloc(e->target->mc, e->local_static_sec, off,
target, kind, width, addend);
e->local_static_size += width;
}
@@ -745,7 +745,7 @@ static void emit_ret(NativeEmitCtx* e, Inst* in, const CGFuncDesc* fd) {
for (u32 i = 0; i < nrets; ++i)
write_loc(e, rets[i].dst, rets[i].src, rets[i].mem, in->loc);
/* Skip the trailing branch-to-epilogue when this IR_RET is the very last
- * inst emitted: func_end will place the epilogue label at mc->pos right
+ * inst emitted: func_end will place the epilogue label at mc_pos right
* after this, so the branch would jump to the next 4 bytes. The actual
* `ret` instruction lives in func_end's restore-frame sequence and is
* unaffected. */
diff --git a/test/debug/cfi_unit.c b/test/debug/cfi_unit.c
@@ -123,9 +123,9 @@ static void check_arch(const CfiExpect* ex) {
kit_compiler_free(c);
return;
}
- mc->set_section(mc, text_sec);
+ mc_set_section(mc, text_sec);
mc_begin_function(mc, fsym, text_sec, 0);
- mc->cfi_startproc(mc);
+ mc_cfi_startproc(mc);
/* Write the (placeholder) function body bytes AFTER cfi_startproc so
* the FDE range captured by cfi_endproc reflects the body size. */
{
@@ -135,12 +135,12 @@ static void check_arch(const CfiExpect* ex) {
/* Anchor the directives at pc_offset=0 so the test can predict offsets
* deterministically (we wrote the bytes before opening the FDE, so
* cur_pos > func_start). */
- mc->cfi_set_next_pc_offset(mc, 0);
- mc->cfi_def_cfa(mc, ex->cfa_reg_after_setup, ex->cfa_off_after_setup);
+ mc_cfi_set_next_pc_offset(mc, 0);
+ mc_cfi_def_cfa(mc, ex->cfa_reg_after_setup, ex->cfa_off_after_setup);
/* Save the return-address register at CFA-8. */
- mc->cfi_set_next_pc_offset(mc, 0);
- mc->cfi_offset(mc, ex->expected_return_reg, -8);
- mc->cfi_endproc(mc);
+ mc_cfi_set_next_pc_offset(mc, 0);
+ mc_cfi_offset(mc, ex->expected_return_reg, -8);
+ mc_cfi_endproc(mc);
mc_end_function(mc);
mc_emit_eh_frame(mc);