kit

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

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:
Msrc/arch/aa64/asm.c | 22+++++++++++-----------
Msrc/arch/aa64/native.c | 194++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/arch/mc.c | 92+++++++++++++++++++++++++++++--------------------------------------------------
Msrc/arch/mc.h | 91+++++++++++++++++++++++++++++++++++++-------------------------------------------
Msrc/arch/riscv/asm.c | 20++++++++++----------
Msrc/arch/riscv/native.c | 100++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/arch/x64/asm.c | 54+++++++++++++++++++++++++++---------------------------
Msrc/arch/x64/emit.c | 70+++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/arch/x64/native.c | 290++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/asm/asm.c | 26+++++++++++++-------------
Msrc/cg/native_direct_target.c | 2+-
Msrc/opt/pass_native_emit.c | 4++--
Mtest/debug/cfi_unit.c | 14+++++++-------
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);