kit

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

commit a2f6367d5228992098a5ed2c3883ec113d623ab9
parent 917ffe99af9830110b9e682f3cfe21690f17ea58
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Mon,  1 Jun 2026 19:29:08 -0700

cg: consume public CfreeCgAtomicOp/CfreeCgMemOrder directly (Track 2, atomics slice)

Delete the internal AtomicOp and MemOrder enums (identical 1:1 to the public
CfreeCgAtomicOp/CfreeCgMemOrder) and api_map_atomic_op/api_map_mem_order. Both
the semantic CgTarget and the physical NativeTarget atomic hooks
(atomic_load/store/rmw/cas/fence), the recorded + opt IR aux structs, and every
backend + the interpreter now carry the public enums straight through. The C
frontend keeps its own private copy (separate Principle-1 issue). Value-
preserving; no behavior change. toy 1344/0, cg-api 173/0, smoke x64+rv64 green.

Diffstat:
Msrc/arch/aa64/native.c | 54+++++++++++++++++++++++++++---------------------------
Msrc/arch/c_target/c_emit.c | 56++++++++++++++++++++++++++++----------------------------
Msrc/arch/c_target/c_emit.h | 12++++++------
Msrc/arch/c_target/ir_emit.c | 2+-
Msrc/arch/check_target.c | 12++++++------
Msrc/arch/native_target.h | 12++++++------
Msrc/arch/rv64/native.c | 42+++++++++++++++++++++---------------------
Msrc/arch/wasm/emit.c | 36++++++++++++++++++------------------
Msrc/arch/wasm/internal.h | 2+-
Msrc/arch/wasm/ir_emit.c | 14+++++++-------
Msrc/arch/x64/native.c | 30+++++++++++++++---------------
Msrc/cg/atomic.c | 12++++++------
Msrc/cg/cgtarget.h | 43++++++++++++++-----------------------------
Msrc/cg/internal.h | 2--
Msrc/cg/ir.h | 6+++---
Msrc/cg/ir_recorder.c | 12++++++------
Msrc/cg/native_direct_target.c | 12++++++------
Msrc/cg/value.c | 37-------------------------------------
Msrc/interp/engine.c | 16++++++++--------
Msrc/interp/interp.h | 2+-
Msrc/opt/ir.h | 10+++++-----
Msrc/opt/pass_native_emit.c | 4++--
22 files changed, 187 insertions(+), 241 deletions(-)

diff --git a/src/arch/aa64/native.c b/src/arch/aa64/native.c @@ -2950,13 +2950,13 @@ static void aa_bitfield_store(NativeTarget* t, NativeAddr addr, NativeLoc src, static void aa_trap(NativeTarget* t); -static int aa_order_acquire(MemOrder order) { - return order == MO_CONSUME || order == MO_ACQUIRE || order == MO_ACQ_REL || - order == MO_SEQ_CST; +static int aa_order_acquire(CfreeCgMemOrder order) { + return order == CFREE_CG_MO_CONSUME || order == CFREE_CG_MO_ACQUIRE || order == CFREE_CG_MO_ACQ_REL || + order == CFREE_CG_MO_SEQ_CST; } -static int aa_order_release(MemOrder order) { - return order == MO_RELEASE || order == MO_ACQ_REL || order == MO_SEQ_CST; +static int aa_order_release(CfreeCgMemOrder order) { + return order == CFREE_CG_MO_RELEASE || order == CFREE_CG_MO_ACQ_REL || order == CFREE_CG_MO_SEQ_CST; } static NativeLoc aa_i64_reg_loc(u32 reg) { @@ -3008,31 +3008,31 @@ static void aa_saved_tmp_restore(AANativeTarget* a, u32 reg) { } static void aa_atomic_load(NativeTarget* t, NativeLoc dst, NativeAddr addr, - MemAccess mem, MemOrder order) { + MemAccess mem, CfreeCgMemOrder order) { u32 base = AA_TMP0; u32 sz = size_idx(mem.size ? mem.size : type_size32(t, dst.type)); aa_atomic_addr_reg(t, addr, base); aa_emit32(t->mc, aa_order_acquire(order) ? aa_ldar(sz, loc_reg(dst), base) : aa_ldr_uimm(sz, loc_reg(dst), base, 0)); - if (order == MO_SEQ_CST) aa_emit32(t->mc, aa64_dmb(AA64_BARRIER_OPT_ISH)); + if (order == CFREE_CG_MO_SEQ_CST) aa_emit32(t->mc, aa64_dmb(AA64_BARRIER_OPT_ISH)); } static void aa_atomic_store(NativeTarget* t, NativeAddr addr, NativeLoc src, - MemAccess mem, MemOrder order) { + MemAccess mem, CfreeCgMemOrder order) { u32 base = AA_TMP0; u32 sz = size_idx(mem.size ? mem.size : type_size32(t, src.type)); - if (order == MO_SEQ_CST) aa_emit32(t->mc, aa64_dmb(AA64_BARRIER_OPT_ISH)); + if (order == CFREE_CG_MO_SEQ_CST) aa_emit32(t->mc, aa64_dmb(AA64_BARRIER_OPT_ISH)); aa_atomic_addr_reg(t, addr, base); aa_emit32(t->mc, aa_order_release(order) ? aa_stlr(sz, loc_reg(src), base) : aa_str_uimm(sz, loc_reg(src), base, 0)); - if (order == MO_SEQ_CST) aa_emit32(t->mc, aa64_dmb(AA64_BARRIER_OPT_ISH)); + if (order == CFREE_CG_MO_SEQ_CST) aa_emit32(t->mc, aa64_dmb(AA64_BARRIER_OPT_ISH)); } -static void aa_atomic_rmw(NativeTarget* t, AtomicOp op, NativeLoc dst, +static void aa_atomic_rmw(NativeTarget* t, CfreeCgAtomicOp op, NativeLoc dst, NativeAddr addr, NativeLoc val, MemAccess mem, - MemOrder order) { + CfreeCgMemOrder order) { AANativeTarget* a = aa_of(t); u32 base = AA_TMP0; u32 next_reg = AA_TMP1; @@ -3040,32 +3040,32 @@ static void aa_atomic_rmw(NativeTarget* t, AtomicOp op, NativeLoc dst, NativeLoc next = aa_tmp_loc(dst.type, next_reg); MCLabel retry = t->mc->label_new(t->mc); u32 sz = size_idx(mem.size ? mem.size : type_size32(t, dst.type)); - if (order == MO_SEQ_CST) aa_emit32(t->mc, aa64_dmb(AA64_BARRIER_OPT_ISH)); + if (order == CFREE_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); aa_emit32(t->mc, aa_order_acquire(order) ? aa_ldaxr(sz, loc_reg(dst), base) : aa_ldxr(sz, loc_reg(dst), base)); switch (op) { - case AO_XCHG: + case CFREE_CG_ATOMIC_XCHG: aa_move(t, next, val); break; - case AO_ADD: + case CFREE_CG_ATOMIC_ADD: aa_binop(t, BO_IADD, next, dst, val); break; - case AO_SUB: + case CFREE_CG_ATOMIC_SUB: aa_binop(t, BO_ISUB, next, dst, val); break; - case AO_AND: + case CFREE_CG_ATOMIC_AND: aa_binop(t, BO_AND, next, dst, val); break; - case AO_OR: + case CFREE_CG_ATOMIC_OR: aa_binop(t, BO_OR, next, dst, val); break; - case AO_XOR: + case CFREE_CG_ATOMIC_XOR: aa_binop(t, BO_XOR, next, dst, val); break; - case AO_NAND: + case CFREE_CG_ATOMIC_NAND: aa_binop(t, BO_AND, next, dst, val); aa_unop(t, UO_BNOT, next, next); break; @@ -3078,13 +3078,13 @@ static void aa_atomic_rmw(NativeTarget* t, AtomicOp op, NativeLoc dst, aa_emit32(t->mc, aa64_cbnz_imm(0, status, 0)); t->mc->emit_label_ref(t->mc, retry, R_AARCH64_CONDBR19, 4, 0); aa_saved_tmp_restore(a, status); - if (order == MO_SEQ_CST) aa_emit32(t->mc, aa64_dmb(AA64_BARRIER_OPT_ISH)); + if (order == CFREE_CG_MO_SEQ_CST) aa_emit32(t->mc, aa64_dmb(AA64_BARRIER_OPT_ISH)); } static void aa_atomic_cas(NativeTarget* t, NativeLoc prior, NativeLoc ok, NativeAddr addr, NativeLoc expected, - NativeLoc desired, MemAccess mem, MemOrder success, - MemOrder failure) { + NativeLoc desired, MemAccess mem, CfreeCgMemOrder success, + CfreeCgMemOrder failure) { u32 base = AA_TMP0; u32 status = AA_TMP1; u32 sz = size_idx(mem.size ? mem.size : type_size32(t, prior.type)); @@ -3094,7 +3094,7 @@ static void aa_atomic_cas(NativeTarget* t, NativeLoc prior, NativeLoc ok, MCLabel retry = t->mc->label_new(t->mc); MCLabel fail = t->mc->label_new(t->mc); MCLabel done = t->mc->label_new(t->mc); - if (success == MO_SEQ_CST || failure == MO_SEQ_CST) + if (success == CFREE_CG_MO_SEQ_CST || failure == CFREE_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); @@ -3113,12 +3113,12 @@ static void aa_atomic_cas(NativeTarget* t, NativeLoc prior, NativeLoc ok, 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); - if (success == MO_SEQ_CST || failure == MO_SEQ_CST) + if (success == CFREE_CG_MO_SEQ_CST || failure == CFREE_CG_MO_SEQ_CST) aa_emit32(t->mc, aa64_dmb(AA64_BARRIER_OPT_ISH)); } -static void aa_fence(NativeTarget* t, MemOrder order) { - if (order != MO_RELAXED) aa_emit32(t->mc, aa64_dmb(AA64_BARRIER_OPT_ISH)); +static void aa_fence(NativeTarget* t, CfreeCgMemOrder order) { + if (order != CFREE_CG_MO_RELAXED) aa_emit32(t->mc, aa64_dmb(AA64_BARRIER_OPT_ISH)); } static void aa_intrinsic(NativeTarget* t, IntrinKind kind, diff --git a/src/arch/c_target/c_emit.c b/src/arch/c_target/c_emit.c @@ -3245,39 +3245,39 @@ void c_emit_load_const(CTarget* t, Operand dst, ConstBytes cb) { * * Lowered to gcc/clang's `__atomic_*` generic builtins. The host compiler * picks the inline sequence vs. libcall and applies the requested memory - * order. cfree's MemOrder enum aligns 1-1 with the `__ATOMIC_*` constants. */ + * order. cfree's CfreeCgMemOrder enum aligns 1-1 with the `__ATOMIC_*` constants. */ -static const char* c_memorder_token(MemOrder o) { +static const char* c_memorder_token(CfreeCgMemOrder o) { switch (o) { - case MO_RELAXED: + case CFREE_CG_MO_RELAXED: return "__ATOMIC_RELAXED"; - case MO_CONSUME: + case CFREE_CG_MO_CONSUME: return "__ATOMIC_CONSUME"; - case MO_ACQUIRE: + case CFREE_CG_MO_ACQUIRE: return "__ATOMIC_ACQUIRE"; - case MO_RELEASE: + case CFREE_CG_MO_RELEASE: return "__ATOMIC_RELEASE"; - case MO_ACQ_REL: + case CFREE_CG_MO_ACQ_REL: return "__ATOMIC_ACQ_REL"; - case MO_SEQ_CST: + case CFREE_CG_MO_SEQ_CST: return "__ATOMIC_SEQ_CST"; } return "__ATOMIC_SEQ_CST"; } void c_emit_atomic_load(CTarget* t, Operand dst, Operand addr, MemAccess m, - MemOrder o); + CfreeCgMemOrder o); void c_emit_atomic_store(CTarget* t, Operand addr, Operand src, MemAccess m, - MemOrder o); -void c_emit_atomic_rmw(CTarget* t, AtomicOp op, Operand dst, Operand addr, - Operand val, MemAccess m, MemOrder o); + CfreeCgMemOrder o); +void c_emit_atomic_rmw(CTarget* t, CfreeCgAtomicOp op, Operand dst, Operand addr, + Operand val, MemAccess m, CfreeCgMemOrder o); void c_emit_atomic_cas(CTarget* t, Operand prior, Operand ok, Operand addr, Operand expected, Operand desired, MemAccess m, - MemOrder so, MemOrder fo); -void c_emit_fence(CTarget* t, MemOrder o); + CfreeCgMemOrder so, CfreeCgMemOrder fo); +void c_emit_fence(CTarget* t, CfreeCgMemOrder o); void c_emit_atomic_load(CTarget* t, Operand dst, Operand addr, MemAccess m, - MemOrder o) { + CfreeCgMemOrder o) { (void)m; c_assert_no_index(t, addr, "atomic_load"); c_ensure_local(t, dst.v.local, dst.type); @@ -3294,7 +3294,7 @@ void c_emit_atomic_load(CTarget* t, Operand dst, Operand addr, MemAccess m, } void c_emit_atomic_store(CTarget* t, Operand addr, Operand src, MemAccess m, - MemOrder o) { + CfreeCgMemOrder o) { (void)m; c_assert_no_index(t, addr, "atomic_store"); cbuf_puts(&t->body, " __atomic_store_n(("); @@ -3308,28 +3308,28 @@ void c_emit_atomic_store(CTarget* t, Operand addr, Operand src, MemAccess m, cbuf_puts(&t->body, ");\n"); } -static const char* c_atomic_op_builtin(AtomicOp op) { +static const char* c_atomic_op_builtin(CfreeCgAtomicOp op) { switch (op) { - case AO_XCHG: + case CFREE_CG_ATOMIC_XCHG: return "__atomic_exchange_n"; - case AO_ADD: + case CFREE_CG_ATOMIC_ADD: return "__atomic_fetch_add"; - case AO_SUB: + case CFREE_CG_ATOMIC_SUB: return "__atomic_fetch_sub"; - case AO_AND: + case CFREE_CG_ATOMIC_AND: return "__atomic_fetch_and"; - case AO_OR: + case CFREE_CG_ATOMIC_OR: return "__atomic_fetch_or"; - case AO_XOR: + case CFREE_CG_ATOMIC_XOR: return "__atomic_fetch_xor"; - case AO_NAND: + case CFREE_CG_ATOMIC_NAND: return "__atomic_fetch_nand"; } return NULL; } -void c_emit_atomic_rmw(CTarget* t, AtomicOp op, Operand dst, Operand addr, - Operand val, MemAccess m, MemOrder o) { +void c_emit_atomic_rmw(CTarget* t, CfreeCgAtomicOp op, Operand dst, Operand addr, + Operand val, MemAccess m, CfreeCgMemOrder o) { (void)m; SrcLoc loc = t->cur_fn ? t->cur_fn->loc : (SrcLoc){0, 0, 0}; c_assert_no_index(t, addr, "atomic_rmw"); @@ -3355,7 +3355,7 @@ void c_emit_atomic_rmw(CTarget* t, AtomicOp op, Operand dst, Operand addr, void c_emit_atomic_cas(CTarget* t, Operand prior, Operand ok, Operand addr, Operand expected, Operand desired, MemAccess m, - MemOrder so, MemOrder fo) { + CfreeCgMemOrder so, CfreeCgMemOrder fo) { (void)m; c_assert_no_index(t, addr, "atomic_cas"); /* gcc's __atomic_compare_exchange_n needs a real lvalue holding the @@ -3397,7 +3397,7 @@ void c_emit_atomic_cas(CTarget* t, Operand prior, Operand ok, Operand addr, cbuf_puts(&t->body, "; }\n"); } -void c_emit_fence(CTarget* t, MemOrder o) { +void c_emit_fence(CTarget* t, CfreeCgMemOrder o) { cbuf_puts(&t->body, " __atomic_thread_fence("); cbuf_puts(&t->body, c_memorder_token(o)); cbuf_puts(&t->body, ");\n"); diff --git a/src/arch/c_target/c_emit.h b/src/arch/c_target/c_emit.h @@ -246,12 +246,12 @@ void c_emit_asm_block(CTarget*, const char*, const AsmConstraint*, u32, void c_emit_bitfield_load(CTarget*, Operand, Operand, BitFieldAccess); void c_emit_bitfield_store(CTarget*, Operand, Operand, BitFieldAccess); void c_emit_tls_addr_of(CTarget*, Operand, ObjSymId, i64); -void c_emit_atomic_load(CTarget*, Operand, Operand, MemAccess, MemOrder); -void c_emit_atomic_store(CTarget*, Operand, Operand, MemAccess, MemOrder); -void c_emit_atomic_rmw(CTarget*, AtomicOp, Operand, Operand, Operand, MemAccess, - MemOrder); +void c_emit_atomic_load(CTarget*, Operand, Operand, MemAccess, CfreeCgMemOrder); +void c_emit_atomic_store(CTarget*, Operand, Operand, MemAccess, CfreeCgMemOrder); +void c_emit_atomic_rmw(CTarget*, CfreeCgAtomicOp, Operand, Operand, Operand, MemAccess, + CfreeCgMemOrder); void c_emit_atomic_cas(CTarget*, Operand, Operand, Operand, Operand, Operand, - MemAccess, MemOrder, MemOrder); -void c_emit_fence(CTarget*, MemOrder); + MemAccess, CfreeCgMemOrder, CfreeCgMemOrder); +void c_emit_fence(CTarget*, CfreeCgMemOrder); #endif diff --git a/src/arch/c_target/ir_emit.c b/src/arch/c_target/ir_emit.c @@ -227,7 +227,7 @@ static void ir_emit_inst(CIrEmitter* e, const CgIrInst* in) { return; } case CG_IR_FENCE: - c_emit_fence(t, (MemOrder)in->extra.imm); + c_emit_fence(t, (CfreeCgMemOrder)in->extra.imm); return; case CG_IR_INTRINSIC: { const CgIrIntrinsicAux* aux = (const CgIrIntrinsicAux*)in->extra.aux; diff --git a/src/arch/check_target.c b/src/arch/check_target.c @@ -292,7 +292,7 @@ static void check_asm_block(CgTarget* t, const char* tmpl, } static void check_atomic_load(CgTarget* t, Operand dst, Operand addr, - MemAccess m, MemOrder order) { + MemAccess m, CfreeCgMemOrder order) { (void)t; (void)dst; (void)addr; @@ -301,7 +301,7 @@ static void check_atomic_load(CgTarget* t, Operand dst, Operand addr, } static void check_atomic_store(CgTarget* t, Operand addr, Operand src, - MemAccess m, MemOrder order) { + MemAccess m, CfreeCgMemOrder order) { (void)t; (void)addr; (void)src; @@ -309,9 +309,9 @@ static void check_atomic_store(CgTarget* t, Operand addr, Operand src, (void)order; } -static void check_atomic_rmw(CgTarget* t, AtomicOp op, Operand dst, +static void check_atomic_rmw(CgTarget* t, CfreeCgAtomicOp op, Operand dst, Operand addr, Operand val, MemAccess m, - MemOrder order) { + CfreeCgMemOrder order) { (void)t; (void)op; (void)dst; @@ -323,7 +323,7 @@ static void check_atomic_rmw(CgTarget* t, AtomicOp op, Operand dst, static void check_atomic_cas(CgTarget* t, Operand prior, Operand ok, Operand addr, Operand expected, Operand desired, - MemAccess m, MemOrder success, MemOrder failure) { + MemAccess m, CfreeCgMemOrder success, CfreeCgMemOrder failure) { (void)t; (void)prior; (void)ok; @@ -335,7 +335,7 @@ static void check_atomic_cas(CgTarget* t, Operand prior, Operand ok, (void)failure; } -static void check_fence(CgTarget* t, MemOrder order) { +static void check_fence(CgTarget* t, CfreeCgMemOrder order) { (void)t; (void)order; } diff --git a/src/arch/native_target.h b/src/arch/native_target.h @@ -460,15 +460,15 @@ struct NativeTarget { void (*ret)(NativeTarget*); void (*atomic_load)(NativeTarget*, NativeLoc dst, NativeAddr addr, MemAccess, - MemOrder); + CfreeCgMemOrder); void (*atomic_store)(NativeTarget*, NativeAddr addr, NativeLoc src, MemAccess, - MemOrder); - void (*atomic_rmw)(NativeTarget*, AtomicOp, NativeLoc dst, NativeAddr addr, - NativeLoc val, MemAccess, MemOrder); + CfreeCgMemOrder); + void (*atomic_rmw)(NativeTarget*, CfreeCgAtomicOp, NativeLoc dst, NativeAddr addr, + NativeLoc val, MemAccess, CfreeCgMemOrder); void (*atomic_cas)(NativeTarget*, NativeLoc prior, NativeLoc ok, NativeAddr addr, NativeLoc expected, NativeLoc desired, - MemAccess, MemOrder success, MemOrder failure); - void (*fence)(NativeTarget*, MemOrder); + MemAccess, CfreeCgMemOrder success, CfreeCgMemOrder failure); + void (*fence)(NativeTarget*, CfreeCgMemOrder); /* Variadic support. The optimizer passes the va_list pointer opaquely as a * NativeLoc (a register or memory location holding the address of the * va_list object); va_arg additionally receives the argument type and a diff --git a/src/arch/rv64/native.c b/src/arch/rv64/native.c @@ -2338,12 +2338,12 @@ static void rv_bitfield_store(NativeTarget* t, NativeAddr ra, NativeLoc src, rv64_emit32(mc, rv_or(RV_TMP2, RV_TMP2, RV_TMP0)); rv64_emit32(mc, enc_int_store(storage_bytes, RV_TMP2, base, off)); } -static int rv_order_acquire(MemOrder o) { - return o == MO_CONSUME || o == MO_ACQUIRE || o == MO_ACQ_REL || - o == MO_SEQ_CST; +static int rv_order_acquire(CfreeCgMemOrder o) { + return o == CFREE_CG_MO_CONSUME || o == CFREE_CG_MO_ACQUIRE || o == CFREE_CG_MO_ACQ_REL || + o == CFREE_CG_MO_SEQ_CST; } -static int rv_order_release(MemOrder o) { - return o == MO_RELEASE || o == MO_ACQ_REL || o == MO_SEQ_CST; +static int rv_order_release(CfreeCgMemOrder o) { + return o == CFREE_CG_MO_RELEASE || o == CFREE_CG_MO_ACQ_REL || o == CFREE_CG_MO_SEQ_CST; } /* Materialize the atomic operand address into RV_TMP0 (a bare pointer, since @@ -2356,12 +2356,12 @@ static u32 rv_atomic_addr_reg(RvNativeTarget* a, NativeAddr addr) { } static void rv_atomic_load(NativeTarget* t, NativeLoc dst, NativeAddr addr, - MemAccess mem, MemOrder mo) { + MemAccess mem, CfreeCgMemOrder mo) { RvNativeTarget* a = rv_of(t); MCEmitter* mc = t->mc; u32 sf = (mem.size ? mem.size : rv_type_size(t, dst.type)) == 8u ? 1u : 0u; u32 base = rv_atomic_addr_reg(a, addr); - if (mo == MO_SEQ_CST) rv64_emit32(mc, rv_fence_rw_rw()); + if (mo == CFREE_CG_MO_SEQ_CST) rv64_emit32(mc, rv_fence_rw_rw()); if (rv_order_acquire(mo)) { /* lr.w/d as an ordered load (aq=1). */ rv64_emit32(mc, sf ? rv_lr_d(loc_reg(dst), base, 1, 0) @@ -2373,7 +2373,7 @@ static void rv_atomic_load(NativeTarget* t, NativeLoc dst, NativeAddr addr, } static void rv_atomic_store(NativeTarget* t, NativeAddr addr, NativeLoc src, - MemAccess mem, MemOrder mo) { + MemAccess mem, CfreeCgMemOrder mo) { RvNativeTarget* a = rv_of(t); MCEmitter* mc = t->mc; u32 sz = mem.size ? mem.size : rv_type_size(t, src.type); @@ -2381,12 +2381,12 @@ static void rv_atomic_store(NativeTarget* t, NativeAddr addr, NativeLoc src, u32 base = rv_atomic_addr_reg(a, addr); if (rv_order_release(mo)) rv64_emit32(mc, rv_fence_rw_rw()); rv64_emit32(mc, enc_int_store(sz, loc_reg(src), base, 0)); - if (mo == MO_SEQ_CST) rv64_emit32(mc, rv_fence_rw_rw()); + if (mo == CFREE_CG_MO_SEQ_CST) rv64_emit32(mc, rv_fence_rw_rw()); } -static void rv_atomic_rmw(NativeTarget* t, AtomicOp op, NativeLoc dst, +static void rv_atomic_rmw(NativeTarget* t, CfreeCgAtomicOp op, NativeLoc dst, NativeAddr addr, NativeLoc val, MemAccess mem, - MemOrder mo) { + CfreeCgMemOrder mo) { RvNativeTarget* a = rv_of(t); MCEmitter* mc = t->mc; u32 sf = (mem.size ? mem.size : rv_type_size(t, dst.type)) == 8u ? 1u : 0u; @@ -2401,25 +2401,25 @@ static void rv_atomic_rmw(NativeTarget* t, AtomicOp op, NativeLoc dst, 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 AO_XCHG: + case CFREE_CG_ATOMIC_XCHG: rv64_emit32(mc, rv_addi(RV_TMP3, vreg, 0)); break; - case AO_ADD: + case CFREE_CG_ATOMIC_ADD: rv64_emit32(mc, sf ? rv_add(RV_TMP3, rd, vreg) : rv_addw(RV_TMP3, rd, vreg)); break; - case AO_SUB: + case CFREE_CG_ATOMIC_SUB: rv64_emit32(mc, sf ? rv_sub(RV_TMP3, rd, vreg) : rv_subw(RV_TMP3, rd, vreg)); break; - case AO_AND: + case CFREE_CG_ATOMIC_AND: rv64_emit32(mc, rv_and(RV_TMP3, rd, vreg)); break; - case AO_OR: + case CFREE_CG_ATOMIC_OR: rv64_emit32(mc, rv_or(RV_TMP3, rd, vreg)); break; - case AO_XOR: + case CFREE_CG_ATOMIC_XOR: rv64_emit32(mc, rv_xor(RV_TMP3, rd, vreg)); break; - case AO_NAND: + case CFREE_CG_ATOMIC_NAND: rv64_emit32(mc, rv_and(RV_TMP3, rd, vreg)); rv64_emit32(mc, rv_xori(RV_TMP3, RV_TMP3, -1)); break; @@ -2434,7 +2434,7 @@ static void rv_atomic_rmw(NativeTarget* t, AtomicOp op, NativeLoc dst, static void rv_atomic_cas(NativeTarget* t, NativeLoc prior, NativeLoc ok, NativeAddr addr, NativeLoc expected, NativeLoc desired, - MemAccess mem, MemOrder success, MemOrder failure) { + MemAccess mem, CfreeCgMemOrder success, CfreeCgMemOrder failure) { RvNativeTarget* a = rv_of(t); MCEmitter* mc = t->mc; u32 sf = (mem.size ? mem.size : rv_type_size(t, prior.type)) == 8u ? 1u : 0u; @@ -2468,8 +2468,8 @@ static void rv_atomic_cas(NativeTarget* t, NativeLoc prior, NativeLoc ok, mc->label_place(mc, done); } -static void rv_fence(NativeTarget* t, MemOrder mo) { - if (mo == MO_RELAXED) return; +static void rv_fence(NativeTarget* t, CfreeCgMemOrder mo) { + if (mo == CFREE_CG_MO_RELAXED) return; rv64_emit32(t->mc, rv_fence_rw_rw()); } /* ---- variadics (LP64D ABI_VA_LIST_POINTER) ---- diff --git a/src/arch/wasm/emit.c b/src/arch/wasm/emit.c @@ -1442,7 +1442,7 @@ void wasm_set_bytes(CGTarget* tg, Operand dst, Operand byte, } /* Atomic ops. CG forces `addr` to a REG and accepts reg-or-imm for value - * operands. Wasm only models seq_cst; the MemOrder argument is captured but + * operands. Wasm only models seq_cst; the CfreeCgMemOrder argument is captured but * not encoded — every emitted atomic op is sequentially consistent. The * caller-provided MemAccess carries the type and natural alignment we need * for the memarg width. */ @@ -1454,7 +1454,7 @@ static void atomic_require_addr_reg(WTarget* t, Operand addr, } void wasm_atomic_load(CGTarget* tg, Operand dst, Operand addr, MemAccess mem, - MemOrder mo) { + CfreeCgMemOrder mo) { WTarget* t = (WTarget*)tg; (void)mo; if (t->dead) return; @@ -1471,7 +1471,7 @@ void wasm_atomic_load(CGTarget* tg, Operand dst, Operand addr, MemAccess mem, } void wasm_atomic_store(CGTarget* tg, Operand addr, Operand src, MemAccess mem, - MemOrder mo) { + CfreeCgMemOrder mo) { WTarget* t = (WTarget*)tg; (void)mo; if (t->dead) return; @@ -1487,8 +1487,8 @@ void wasm_atomic_store(CGTarget* tg, Operand addr, Operand src, MemAccess mem, w->type = mem.type ? mem.type : src.type; } -void wasm_atomic_rmw(CGTarget* tg, AtomicOp op, Operand dst, Operand addr, - Operand val, MemAccess mem, MemOrder mo) { +void wasm_atomic_rmw(CGTarget* tg, CfreeCgAtomicOp op, Operand dst, Operand addr, + Operand val, MemAccess mem, CfreeCgMemOrder mo) { WTarget* t = (WTarget*)tg; (void)mo; if (t->dead) return; @@ -1496,7 +1496,7 @@ void wasm_atomic_rmw(CGTarget* tg, AtomicOp op, Operand dst, Operand addr, atomic_require_addr_reg(t, addr, "atomic_rmw"); if (val.kind != OPK_REG && val.kind != OPK_IMM) wfail(t, "wasm: atomic_rmw value must be REG or IMM"); - /* AO_NAND has no native wasm-threads opcode; the linearizer expands it into + /* CFREE_CG_ATOMIC_NAND has no native wasm-threads opcode; the linearizer expands it into * an atomic cmpxchg retry loop (see WIR_ATOMIC_RMW). */ ensure_shared_memory(t); WIR* w = wir_push(t); @@ -1512,7 +1512,7 @@ void wasm_atomic_rmw(CGTarget* tg, AtomicOp op, Operand dst, Operand addr, void wasm_atomic_cas(CGTarget* tg, Operand prior, Operand ok, Operand addr, Operand expected, Operand desired, MemAccess mem, - MemOrder success, MemOrder failure) { + CfreeCgMemOrder success, CfreeCgMemOrder failure) { WTarget* t = (WTarget*)tg; (void)success; (void)failure; @@ -1545,7 +1545,7 @@ void wasm_atomic_cas(CGTarget* tg, Operand prior, Operand ok, Operand addr, w->type2 = ok.type; } -void wasm_fence(CGTarget* tg, MemOrder mo) { +void wasm_fence(CGTarget* tg, CfreeCgMemOrder mo) { WTarget* t = (WTarget*)tg; (void)mo; if (t->dead) return; @@ -2191,7 +2191,7 @@ static WasmInsnKind atomic_store_kind_for(WTarget* t, CfreeCgTypeId ty, wfail(t, "wasm: atomic store i32 size %u not supported", size); } -static WasmInsnKind atomic_rmw_kind_for(WTarget* t, AtomicOp op, +static WasmInsnKind atomic_rmw_kind_for(WTarget* t, CfreeCgAtomicOp op, CfreeCgTypeId ty, MemAccess ma) { WasmValType vt = type_valtype(t, ty); u32 size = ma.size ? ma.size : (u32)abi_cg_sizeof(t->c->abi, ty); @@ -2208,20 +2208,20 @@ static WasmInsnKind atomic_rmw_kind_for(WTarget* t, AtomicOp op, size); } switch (op) { - case AO_ADD: + case CFREE_CG_ATOMIC_ADD: return is64 ? WASM_INSN_I64_ATOMIC_RMW_ADD : WASM_INSN_I32_ATOMIC_RMW_ADD; - case AO_SUB: + case CFREE_CG_ATOMIC_SUB: return is64 ? WASM_INSN_I64_ATOMIC_RMW_SUB : WASM_INSN_I32_ATOMIC_RMW_SUB; - case AO_AND: + case CFREE_CG_ATOMIC_AND: return is64 ? WASM_INSN_I64_ATOMIC_RMW_AND : WASM_INSN_I32_ATOMIC_RMW_AND; - case AO_OR: + case CFREE_CG_ATOMIC_OR: return is64 ? WASM_INSN_I64_ATOMIC_RMW_OR : WASM_INSN_I32_ATOMIC_RMW_OR; - case AO_XOR: + case CFREE_CG_ATOMIC_XOR: return is64 ? WASM_INSN_I64_ATOMIC_RMW_XOR : WASM_INSN_I32_ATOMIC_RMW_XOR; - case AO_XCHG: + case CFREE_CG_ATOMIC_XCHG: return is64 ? WASM_INSN_I64_ATOMIC_RMW_XCHG : WASM_INSN_I32_ATOMIC_RMW_XCHG; - case AO_NAND: + case CFREE_CG_ATOMIC_NAND: wfail(t, "wasm target: atomic NAND has no native wasm-threads opcode"); } wfail(t, "wasm: unsupported atomic RMW op %d", (int)op); @@ -3671,7 +3671,7 @@ static void linearize_range(WTarget* t, LoweringState* L, u32 start, u32 end) { break; } case WIR_ATOMIC_RMW: { - if ((AtomicOp)w->cgop == AO_NAND) { + if ((CfreeCgAtomicOp)w->cgop == CFREE_CG_ATOMIC_NAND) { /* wasm-threads has no atomic.rmw.nand. Expand to a cmpxchg retry * loop computing desired = ~(old & val): * loop @@ -3716,7 +3716,7 @@ static void linearize_range(WTarget* t, LoweringState* L, u32 start, u32 end) { break; } WasmInsnKind k = - atomic_rmw_kind_for(t, (AtomicOp)w->cgop, w->type, w->mem); + atomic_rmw_kind_for(t, (CfreeCgAtomicOp)w->cgop, w->type, w->mem); u32 width = wasm_mem_width((uint8_t)k); emit_push_operand_reg(t, w->a); emit_push_operand(t, w->imm_kind_b, w->imm_b, w->b, w->type); diff --git a/src/arch/wasm/internal.h b/src/arch/wasm/internal.h @@ -80,7 +80,7 @@ typedef enum WIROp { WIR_SET_BYTES, /* memset-like byte set */ WIR_ATOMIC_LOAD, /* dst = atomic.load(addr_reg), mem holds access info */ WIR_ATOMIC_STORE, /* atomic.store(addr_reg, src) */ - WIR_ATOMIC_RMW, /* dst = atomic.rmw_<op>(addr_reg, val); cgop = AtomicOp */ + WIR_ATOMIC_RMW, /* dst = atomic.rmw_<op>(addr_reg, val); cgop = CfreeCgAtomicOp */ WIR_ATOMIC_CAS, /* dst = prior; dst2 = ok (i32 0/1); a=addr_reg, b/imm_kind_b=expected, op_c/imm_kind_c=desired */ WIR_FENCE, /* atomic.fence (memory order ignored, wasm has seq_cst) */ diff --git a/src/arch/wasm/ir_emit.c b/src/arch/wasm/ir_emit.c @@ -46,13 +46,13 @@ void wasm_va_start(CGTarget*, Operand); void wasm_va_arg(CGTarget*, Operand, Operand, CfreeCgTypeId); void wasm_va_end(CGTarget*, Operand); void wasm_va_copy(CGTarget*, Operand, Operand); -void wasm_atomic_load(CGTarget*, Operand, Operand, MemAccess, MemOrder); -void wasm_atomic_store(CGTarget*, Operand, Operand, MemAccess, MemOrder); -void wasm_atomic_rmw(CGTarget*, AtomicOp, Operand, Operand, Operand, MemAccess, - MemOrder); +void wasm_atomic_load(CGTarget*, Operand, Operand, MemAccess, CfreeCgMemOrder); +void wasm_atomic_store(CGTarget*, Operand, Operand, MemAccess, CfreeCgMemOrder); +void wasm_atomic_rmw(CGTarget*, CfreeCgAtomicOp, Operand, Operand, Operand, MemAccess, + CfreeCgMemOrder); void wasm_atomic_cas(CGTarget*, Operand, Operand, Operand, Operand, Operand, - MemAccess, MemOrder, MemOrder); -void wasm_fence(CGTarget*, MemOrder); + MemAccess, CfreeCgMemOrder, CfreeCgMemOrder); +void wasm_fence(CGTarget*, CfreeCgMemOrder); void wasm_intrinsic(CGTarget*, IntrinKind, Operand*, u32, const Operand*, u32); void wasm_asm_block(CGTarget*, const char*, const AsmConstraint*, u32, Operand*, const AsmConstraint*, u32, const Operand*, const Sym*, u32); @@ -765,7 +765,7 @@ static void wasm_ir_emit_inst(WasmIrEmitter* e, const CgIrFunc* f, return; } case CG_IR_FENCE: - wasm_fence(t, (MemOrder)in->extra.imm); + wasm_fence(t, (CfreeCgMemOrder)in->extra.imm); return; case CG_IR_INTRINSIC: { const CgIrIntrinsicAux* aux = (const CgIrIntrinsicAux*)in->extra.aux; diff --git a/src/arch/x64/native.c b/src/arch/x64/native.c @@ -2822,7 +2822,7 @@ static u32 x64_atomic_base(X64NativeTarget* a, NativeAddr addr) { } static void x64_atomic_load(NativeTarget* t, NativeLoc dst, NativeAddr addr, - MemAccess mem, MemOrder mo) { + MemAccess mem, CfreeCgMemOrder mo) { X64NativeTarget* a = x64_of(t); u32 sz = mem.size ? mem.size : x64_type_size(t, dst.type); u32 base; @@ -2832,14 +2832,14 @@ static void x64_atomic_load(NativeTarget* t, NativeLoc dst, NativeAddr addr, } static void x64_atomic_store(NativeTarget* t, NativeAddr addr, NativeLoc src, - MemAccess mem, MemOrder mo) { + MemAccess mem, CfreeCgMemOrder mo) { X64NativeTarget* a = x64_of(t); MCEmitter* mc = t->mc; u32 sz = mem.size ? mem.size : x64_type_size(t, src.type); int w = sz == 8u ? 1 : 0; u32 base = x64_atomic_base(a, addr); u32 sr = loc_reg(src); - if (mo == MO_SEQ_CST) { + if (mo == CFREE_CG_MO_SEQ_CST) { /* xchg [mem], r11 implicitly fences. Stage src in rax (r11 holds base). */ if (sr != X64_RAX) emit_mov_rr(mc, w, X64_RAX, sr); emit_lock_prefix(mc); @@ -2854,9 +2854,9 @@ static void x64_atomic_store(NativeTarget* t, NativeAddr addr, NativeLoc src, emit_mov_store(mc, sz, sr, base, 0); } -static void x64_atomic_rmw(NativeTarget* t, AtomicOp op, NativeLoc dst, +static void x64_atomic_rmw(NativeTarget* t, CfreeCgAtomicOp op, NativeLoc dst, NativeAddr addr, NativeLoc val, MemAccess mem, - MemOrder mo) { + CfreeCgMemOrder mo) { X64NativeTarget* a = x64_of(t); MCEmitter* mc = t->mc; u32 sz = mem.size ? mem.size : x64_type_size(t, dst.type); @@ -2874,8 +2874,8 @@ static void x64_atomic_rmw(NativeTarget* t, AtomicOp op, NativeLoc dst, } /* val staged in rdx (rax/rcx used by the cmpxchg loop). */ emit_mov_rr(mc, w, X64_RDX, vr); - if (op == AO_ADD || op == AO_SUB) { - if (op == AO_SUB) emit_f7_rm(mc, w, X64_F7_SUB_NEG, X64_RDX); + if (op == CFREE_CG_ATOMIC_ADD || op == CFREE_CG_ATOMIC_SUB) { + if (op == CFREE_CG_ATOMIC_SUB) emit_f7_rm(mc, w, X64_F7_SUB_NEG, X64_RDX); emit_lock_prefix(mc); emit_rex(mc, w, X64_RDX, 0, base); { @@ -2886,7 +2886,7 @@ static void x64_atomic_rmw(NativeTarget* t, AtomicOp op, NativeLoc dst, if (dr != X64_RDX) emit_mov_rr(mc, w, dr, X64_RDX); return; } - if (op == AO_XCHG) { + if (op == CFREE_CG_ATOMIC_XCHG) { emit_lock_prefix(mc); emit_rex(mc, w, X64_RDX, 0, base); { @@ -2904,10 +2904,10 @@ static void x64_atomic_rmw(NativeTarget* t, AtomicOp op, NativeLoc dst, mc->label_place(mc, retry); emit_mov_rr(mc, w, X64_RCX, X64_RAX); switch (op) { - case AO_AND: emit_alu_rr(mc, w, X64_OPC_ALU_AND, X64_RCX, X64_RDX); break; - case AO_OR: emit_alu_rr(mc, w, X64_OPC_ALU_OR, X64_RCX, X64_RDX); break; - case AO_XOR: emit_alu_rr(mc, w, X64_OPC_ALU_XOR, X64_RCX, X64_RDX); break; - case AO_NAND: + case CFREE_CG_ATOMIC_AND: emit_alu_rr(mc, w, X64_OPC_ALU_AND, X64_RCX, X64_RDX); break; + case CFREE_CG_ATOMIC_OR: emit_alu_rr(mc, w, X64_OPC_ALU_OR, X64_RCX, X64_RDX); break; + case CFREE_CG_ATOMIC_XOR: emit_alu_rr(mc, w, X64_OPC_ALU_XOR, X64_RCX, X64_RDX); break; + case CFREE_CG_ATOMIC_NAND: emit_alu_rr(mc, w, X64_OPC_ALU_AND, X64_RCX, X64_RDX); emit_f7_rm(mc, w, X64_F7_SUB_NOT, X64_RCX); break; @@ -2927,7 +2927,7 @@ static void x64_atomic_rmw(NativeTarget* t, AtomicOp op, NativeLoc dst, static void x64_atomic_cas(NativeTarget* t, NativeLoc prior, NativeLoc ok, NativeAddr addr, NativeLoc expected, NativeLoc desired, - MemAccess mem, MemOrder success, MemOrder failure) { + MemAccess mem, CfreeCgMemOrder success, CfreeCgMemOrder failure) { X64NativeTarget* a = x64_of(t); MCEmitter* mc = t->mc; u32 sz = mem.size ? mem.size : x64_type_size(t, prior.type); @@ -2976,8 +2976,8 @@ static void x64_atomic_cas(NativeTarget* t, NativeLoc prior, NativeLoc ok, if (rprior != X64_RAX) emit_mov_rr(mc, w, rprior, X64_RAX); } -static void x64_fence(NativeTarget* t, MemOrder mo) { - if (mo == MO_SEQ_CST) emit_mfence(t->mc); +static void x64_fence(NativeTarget* t, CfreeCgMemOrder mo) { + if (mo == CFREE_CG_MO_SEQ_CST) emit_mfence(t->mc); } /* ============================ variadics ============================ diff --git a/src/cg/atomic.c b/src/cg/atomic.c @@ -51,7 +51,7 @@ void cfree_cg_atomic_load(CfreeCg* g, CfreeCgMemAccess access, rr = api_alloc_temp_local(g, val_ty); dst = api_op_local(rr, val_ty); g->target->atomic_load(g->target, dst, addr, api_mem_for_atomic(g, val_ty), - api_map_mem_order(order)); + order); api_release(g, &ptr); api_push(g, api_make_sv(dst, val_ty)); } @@ -73,7 +73,7 @@ void cfree_cg_atomic_store(CfreeCg* g, CfreeCgMemAccess access, addr = api_force_local(g, &ptr, pty); src = api_sv_op_is_local_or_imm(&val) ? val.op : api_force_local(g, &val, val_ty); g->target->atomic_store(g->target, addr, src, api_mem_for_atomic(g, val_ty), - api_map_mem_order(order)); + order); api_release(g, &val); api_release(g, &ptr); } @@ -97,9 +97,9 @@ void cfree_cg_atomic_rmw(CfreeCg* g, CfreeCgMemAccess access, vop = api_sv_op_is_local_or_imm(&val) ? val.op : api_force_local(g, &val, val_ty); rr = api_alloc_temp_local(g, val_ty); dst = api_op_local(rr, val_ty); - g->target->atomic_rmw(g->target, api_map_atomic_op(op), dst, addr, vop, + g->target->atomic_rmw(g->target, op, dst, addr, vop, api_mem_for_atomic(g, val_ty), - api_map_mem_order(order)); + order); api_release(g, &val); api_release(g, &ptr); api_push(g, api_make_sv(dst, val_ty)); @@ -140,7 +140,7 @@ void cfree_cg_atomic_cmpxchg(CfreeCg* g, CfreeCgMemAccess access, ok = api_op_local(kr, bool_ty); g->target->atomic_cas(g->target, prior, ok, addr, exp_op, des_op, api_mem_for_atomic(g, val_ty), - api_map_mem_order(success), api_map_mem_order(failure)); + success, failure); api_release(g, &desired); api_release(g, &expected); api_release(g, &ptr); @@ -151,7 +151,7 @@ void cfree_cg_atomic_cmpxchg(CfreeCg* g, CfreeCgMemAccess access, void cfree_cg_atomic_fence(CfreeCg* g, CfreeCgMemOrder order) { if (!g) return; api_local_const_memory_boundary(g); - g->target->fence(g->target, api_map_mem_order(order)); + g->target->fence(g->target, order); } /* ============================================================ diff --git a/src/cg/cgtarget.h b/src/cg/cgtarget.h @@ -92,28 +92,12 @@ typedef enum ConvKind { CV_BITCAST, } ConvKind; -typedef enum AtomicOp { - AO_XCHG, - AO_ADD, - AO_SUB, - AO_AND, - AO_OR, - AO_XOR, - AO_NAND, -} AtomicOp; - -/* Memory orders. Which orders are legal depends on the atomic op: load excludes - * release/acq_rel; store excludes acquire/consume/acq_rel; CAS failure order is - * one of relaxed/consume/acquire/seq_cst and no stronger than success. See the - * Atomics edge-case rules in doc/IR.md (mirrored by cfree_cg_atomic_is_legal). */ -typedef enum MemOrder { - MO_RELAXED, - MO_CONSUME, - MO_ACQUIRE, - MO_RELEASE, - MO_ACQ_REL, - MO_SEQ_CST, -} MemOrder; +/* Atomic op kinds (CfreeCgAtomicOp) and memory orders (CfreeCgMemOrder) come + * straight from the public API. Which orders are legal depends on the atomic + * op: load excludes release/acq_rel; store excludes acquire/consume/acq_rel; + * CAS failure order is one of relaxed/consume/acquire/seq_cst and no stronger + * than success. See the Atomics edge-case rules in doc/IR.md (mirrored by + * cfree_cg_atomic_is_legal). */ /* Compiler-intrinsic kinds dispatched through CgTarget.intrinsic and carried * on IR_INTRINSIC via IRIntrinAux.kind. The set is bounded: a backend @@ -639,16 +623,17 @@ struct CgTarget { /* ---- atomics ---- */ void (*atomic_load)(CgTarget*, Operand dst /*LOCAL*/, Operand addr, MemAccess, - MemOrder); + CfreeCgMemOrder); void (*atomic_store)(CgTarget*, Operand addr, Operand src, MemAccess, - MemOrder); - void (*atomic_rmw)(CgTarget*, AtomicOp, Operand dst /*LOCAL: prior value*/, - Operand addr, Operand val, MemAccess, MemOrder); + CfreeCgMemOrder); + void (*atomic_rmw)(CgTarget*, CfreeCgAtomicOp, + Operand dst /*LOCAL: prior value*/, Operand addr, + Operand val, MemAccess, CfreeCgMemOrder); void (*atomic_cas)(CgTarget*, Operand prior /*LOCAL*/, Operand ok /*LOCAL, i1*/, Operand addr, Operand expected, - Operand desired, MemAccess, MemOrder success, - MemOrder failure); - void (*fence)(CgTarget*, MemOrder); + Operand desired, MemAccess, CfreeCgMemOrder success, + CfreeCgMemOrder failure); + void (*fence)(CgTarget*, CfreeCgMemOrder); /* ---- compiler intrinsics ---- * Typed dispatch for builtins whose lowering is backend-relevant diff --git a/src/cg/internal.h b/src/cg/internal.h @@ -428,8 +428,6 @@ UnOp api_map_int_unop(CfreeCgIntUnOp op); CmpOp api_map_int_cmp(CfreeCgIntCmpOp op); CmpOp api_map_fp_cmp(CfreeCgFpCmpOp op); CmpOp api_invert_cmp(CmpOp op); -AtomicOp api_map_atomic_op(CfreeCgAtomicOp op); -MemOrder api_map_mem_order(CfreeCgMemOrder order); u32 api_int_like_width(Compiler* c, CfreeCgTypeId id); int api_type_is_bool(Compiler* c, CfreeCgTypeId id); u64 api_width_mask(u32 width); diff --git a/src/cg/ir.h b/src/cg/ir.h @@ -153,9 +153,9 @@ typedef struct CgIrScopeAux { typedef struct CgIrAtomicAux { MemAccess mem; - MemOrder order; - AtomicOp op; - MemOrder failure; + CfreeCgMemOrder order; + CfreeCgAtomicOp op; + CfreeCgMemOrder failure; } CgIrAtomicAux; typedef struct CgIrAsmAux { diff --git a/src/cg/ir_recorder.c b/src/cg/ir_recorder.c @@ -461,7 +461,7 @@ static void rec_va_copy(CgTarget* t, Operand dst_ap_addr, Operand src_ap_addr) { } static void rec_atomic_load(CgTarget* t, Operand dst, Operand addr, - MemAccess mem, MemOrder order) { + MemAccess mem, CfreeCgMemOrder order) { CgIrRecorder* r = rec_of(t); CgIrInst* in = emit(r, CG_IR_ATOMIC_LOAD); CgIrAtomicAux* aux = AUX_NEW(r, CgIrAtomicAux); @@ -473,7 +473,7 @@ static void rec_atomic_load(CgTarget* t, Operand dst, Operand addr, } static void rec_atomic_store(CgTarget* t, Operand addr, Operand src, - MemAccess mem, MemOrder order) { + MemAccess mem, CfreeCgMemOrder order) { CgIrRecorder* r = rec_of(t); CgIrInst* in = emit(r, CG_IR_ATOMIC_STORE); CgIrAtomicAux* aux = AUX_NEW(r, CgIrAtomicAux); @@ -484,8 +484,8 @@ static void rec_atomic_store(CgTarget* t, Operand addr, Operand src, in->extra.aux = aux; } -static void rec_atomic_rmw(CgTarget* t, AtomicOp op, Operand dst, Operand addr, - Operand val, MemAccess mem, MemOrder order) { +static void rec_atomic_rmw(CgTarget* t, CfreeCgAtomicOp op, Operand dst, Operand addr, + Operand val, MemAccess mem, CfreeCgMemOrder order) { CgIrRecorder* r = rec_of(t); CgIrInst* in = emit(r, CG_IR_ATOMIC_RMW); CgIrAtomicAux* aux = AUX_NEW(r, CgIrAtomicAux); @@ -499,7 +499,7 @@ static void rec_atomic_rmw(CgTarget* t, AtomicOp op, Operand dst, Operand addr, static void rec_atomic_cas(CgTarget* t, Operand prior, Operand ok, Operand addr, Operand expected, Operand desired, MemAccess mem, - MemOrder success, MemOrder failure) { + CfreeCgMemOrder success, CfreeCgMemOrder failure) { CgIrRecorder* r = rec_of(t); CgIrInst* in = emit(r, CG_IR_ATOMIC_CAS); CgIrAtomicAux* aux = AUX_NEW(r, CgIrAtomicAux); @@ -511,7 +511,7 @@ static void rec_atomic_cas(CgTarget* t, Operand prior, Operand ok, Operand addr, in->extra.aux = aux; } -static void rec_fence(CgTarget* t, MemOrder order) { +static void rec_fence(CgTarget* t, CfreeCgMemOrder order) { CgIrInst* in = emit(rec_of(t), CG_IR_FENCE); in->extra.imm = (i64)order; } diff --git a/src/cg/native_direct_target.c b/src/cg/native_direct_target.c @@ -1580,7 +1580,7 @@ static void nd_va_copy(CgTarget* t, Operand dst_ap_addr, Operand src_ap_addr) { } static void nd_atomic_load(CgTarget* t, Operand dst, Operand addr, - MemAccess mem, MemOrder order) { + MemAccess mem, CfreeCgMemOrder order) { NativeDirectTarget* d = nd_of(t); NdAddrTemps temps; nd_flush_all(d); @@ -1596,7 +1596,7 @@ static void nd_atomic_load(CgTarget* t, Operand dst, Operand addr, } static void nd_atomic_store(CgTarget* t, Operand addr, Operand src, - MemAccess mem, MemOrder order) { + MemAccess mem, CfreeCgMemOrder order) { NativeDirectTarget* d = nd_of(t); NdAddrTemps temps; nd_flush_all(d); @@ -1610,8 +1610,8 @@ static void nd_atomic_store(CgTarget* t, Operand addr, Operand src, nd_addr_temps_release(d, &temps); } -static void nd_atomic_rmw(CgTarget* t, AtomicOp op, Operand dst, Operand addr, - Operand val, MemAccess mem, MemOrder order) { +static void nd_atomic_rmw(CgTarget* t, CfreeCgAtomicOp op, Operand dst, Operand addr, + Operand val, MemAccess mem, CfreeCgMemOrder order) { NativeDirectTarget* d = nd_of(t); NdAddrTemps temps; nd_flush_all(d); @@ -1630,7 +1630,7 @@ static void nd_atomic_rmw(CgTarget* t, AtomicOp op, Operand dst, Operand addr, static void nd_atomic_cas(CgTarget* t, Operand prior, Operand ok, Operand addr, Operand expected, Operand desired, MemAccess mem, - MemOrder success, MemOrder failure) { + CfreeCgMemOrder success, CfreeCgMemOrder failure) { NativeDirectTarget* d = nd_of(t); NdAddrTemps temps; nd_flush_all(d); @@ -1654,7 +1654,7 @@ static void nd_atomic_cas(CgTarget* t, Operand prior, Operand ok, Operand addr, nd_addr_temps_release(d, &temps); } -static void nd_fence(CgTarget* t, MemOrder order) { +static void nd_fence(CgTarget* t, CfreeCgMemOrder order) { NativeDirectTarget* d = nd_of(t); nd_flush_all(d); ND_REQUIRE_NATIVE(d, fence, "target does not emit fences"); diff --git a/src/cg/value.c b/src/cg/value.c @@ -701,43 +701,6 @@ CmpOp api_invert_cmp(CmpOp op) { return CMP_EQ; } -AtomicOp api_map_atomic_op(CfreeCgAtomicOp op) { - switch (op) { - case CFREE_CG_ATOMIC_XCHG: - return AO_XCHG; - case CFREE_CG_ATOMIC_ADD: - return AO_ADD; - case CFREE_CG_ATOMIC_SUB: - return AO_SUB; - case CFREE_CG_ATOMIC_AND: - return AO_AND; - case CFREE_CG_ATOMIC_OR: - return AO_OR; - case CFREE_CG_ATOMIC_XOR: - return AO_XOR; - case CFREE_CG_ATOMIC_NAND: - return AO_NAND; - } - return AO_XCHG; -} - -MemOrder api_map_mem_order(CfreeCgMemOrder order) { - switch (order) { - case CFREE_CG_MO_RELAXED: - return MO_RELAXED; - case CFREE_CG_MO_CONSUME: - return MO_CONSUME; - case CFREE_CG_MO_ACQUIRE: - return MO_ACQUIRE; - case CFREE_CG_MO_RELEASE: - return MO_RELEASE; - case CFREE_CG_MO_ACQ_REL: - return MO_ACQ_REL; - case CFREE_CG_MO_SEQ_CST: - return MO_SEQ_CST; - } - return MO_RELAXED; -} /* ---- immediate integer folding ---- */ diff --git a/src/interp/engine.c b/src/interp/engine.c @@ -416,14 +416,14 @@ static u64 do_convert(InterpStack* st, InterpInsn* in, u64 v) { } static u64 do_rmw(u32 op, u64 old, u64 val, u32 w) { - switch ((AtomicOp)op) { - case AO_XCHG: return mask_w(val, w); - case AO_ADD: return mask_w(old + val, w); - case AO_SUB: return mask_w(old - val, w); - case AO_AND: return mask_w(old & val, w); - case AO_OR: return mask_w(old | val, w); - case AO_XOR: return mask_w(old ^ val, w); - case AO_NAND: return mask_w(~(old & val), w); + switch ((CfreeCgAtomicOp)op) { + case CFREE_CG_ATOMIC_XCHG: return mask_w(val, w); + case CFREE_CG_ATOMIC_ADD: return mask_w(old + val, w); + case CFREE_CG_ATOMIC_SUB: return mask_w(old - val, w); + case CFREE_CG_ATOMIC_AND: return mask_w(old & val, w); + case CFREE_CG_ATOMIC_OR: return mask_w(old | val, w); + case CFREE_CG_ATOMIC_XOR: return mask_w(old ^ val, w); + case CFREE_CG_ATOMIC_NAND: return mask_w(~(old & val), w); default: return old; } } diff --git a/src/interp/interp.h b/src/interp/interp.h @@ -73,7 +73,7 @@ typedef struct InterpInsn { void* handler; /* reserved: &&label for direct threading */ const Inst* inst; /* source instruction (arena-resident, c->tu lifetime) */ u32 op; /* InterpOp */ - u32 sub; /* sub-op tag: BinOp/UnOp/CmpOp/ConvKind/AtomicOp/MemOrder */ + u32 sub; /* sub-op tag: BinOp/UnOp/CmpOp/ConvKind/CfreeCgAtomicOp/CfreeCgMemOrder */ u32 dst; /* dest PReg id (cache of opnds[0].v.reg); 0 if none */ u32 t0; /* resolved pc of succ[0] / switch-table index / src reg */ u32 t1; /* resolved pc of succ[1] */ diff --git a/src/opt/ir.h b/src/opt/ir.h @@ -311,7 +311,7 @@ typedef enum IROp { IR_ATOMIC_STORE, /* opnds = [addr, src]; extra.aux = IRAtomicAux */ IR_ATOMIC_RMW, /* opnds = [dst, addr, val]; extra.aux */ IR_ATOMIC_CAS, /* defs = [prior, ok] OPK_REG ids; extra.aux = IRCasAux */ - IR_FENCE, /* extra.imm = MemOrder */ + IR_FENCE, /* extra.imm = CfreeCgMemOrder */ /* Inline asm. extra.aux = IRAsmAux. */ IR_ASM_BLOCK, @@ -415,14 +415,14 @@ typedef struct IRScopeAux { typedef struct IRAtomicAux { MemAccess mem; - MemOrder mo; - u8 op; /* AtomicOp; valid for IR_ATOMIC_RMW */ + CfreeCgMemOrder mo; + u8 op; /* CfreeCgAtomicOp; valid for IR_ATOMIC_RMW */ } IRAtomicAux; typedef struct IRCasAux { MemAccess mem; - MemOrder success; - MemOrder failure; + CfreeCgMemOrder success; + CfreeCgMemOrder failure; } IRCasAux; typedef struct IRAsmAux { diff --git a/src/opt/pass_native_emit.c b/src/opt/pass_native_emit.c @@ -1111,7 +1111,7 @@ static void emit_inst(NativeEmitCtx* e, u32 block, u32 order_index, Inst* in, dst = scratch_loc(e, in->opnds[0].type, class_for_type(e, in->opnds[0].type), src.v.reg, REG_NONE, in->loc); - e->target->atomic_rmw(e->target, (AtomicOp)aux->op, dst, addr, src, + e->target->atomic_rmw(e->target, (CfreeCgAtomicOp)aux->op, dst, addr, src, aux->mem, aux->mo); if (in->opnds[0].kind != OPK_REG) write_loc(e, loc_from_operand(e, &in->opnds[0], in->loc), dst, aux->mem, @@ -1217,7 +1217,7 @@ static void emit_inst(NativeEmitCtx* e, u32 block, u32 order_index, Inst* in, case IR_CONTINUE_TO: emit_panic(e, in->loc, "operation is not wired to NativeTarget yet"); case IR_FENCE: - e->target->fence(e->target, (MemOrder)in->extra.imm); + e->target->fence(e->target, (CfreeCgMemOrder)in->extra.imm); return; case IR_INTRINSIC: { IRIntrinAux* aux = (IRIntrinAux*)in->extra.aux;