commit dce052f5cd1a9b361a65cb2e7573b35c0f6fd85f
parent 54fdf61dc669598af59c54ec278002f1686ea817
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Tue, 2 Jun 2026 02:49:38 -0700
cg: strict PLACE/VALUE addressing, remove the load/store EA rider (Track 7)
Cut the public CfreeCg addressing surface over to a clean, strict PLACE/VALUE
discipline. Every stack entry is exactly one kind and each op declares the kinds
it consumes/produces, panicking on a mismatch — CG never infers a value's kind
or inserts an implicit dereference.
- load/store consume a PLACE; the CfreeCgEffAddr rider is gone.
- deref(offset): VALUE(ptr) -> PLACE *(ptr+offset) [folds offset]
- field(i): PLACE(record) -> PLACE(field) by layout, preserving any
index/scale a preceding elem left [folds offset]
- elem(offset): VALUE(ptr)+index -> PLACE, scale=sizeof(T) [folds scale+offset]
- addr: PLACE -> VALUE(ptr)
The place ops fold the constant offset and scale into one
OPK_INDIRECT[base + index*scale + offset] (base/index dynamic, scale/offset
folded), so the backend still emits a single addressing-mode memop. cg.h
documents the kinds and per-op contracts.
All frontends (C/toy/wasm), the emulator, and the cg-api tests are conformed to
build explicit places (addr/deref/elem/field) at every memory site. The C
frontend keeps scalar-local reads as direct push_local PLACEs so small accessors
stay inlinable.
Green: toy 1344/0/26, cg-api 173+168, opt (incl tiny-inline), smoke x64/rv64,
libc musl 18 + glibc 9, isa/link/elf/debug/dwarf/ar/lib-deps; `make bootstrap`
reproduces byte-identical at -O0 AND -O1. Remaining Track 7 refinements
(explicit ApiSValue kind tag, aggregate-VALUE panics, wide16-as-value,
bitfields-as-PLACE-subkind, -O0 clean-memop pass for the C frontend) are tracked
in doc/plan/CODEGEN.md.
Diffstat:
16 files changed, 1104 insertions(+), 1415 deletions(-)
diff --git a/doc/CODEGEN.md b/doc/CODEGEN.md
@@ -55,14 +55,24 @@ once and shared.
## The public CfreeCg API and value stack
-`include/cfree/cg.h` is a 132-call stack machine. A frontend pushes typed
-values (locals, lvalues, immediates, constants), names types, and issues
-operations that pop operands and push results — `cfree_cg_func_begin`,
-`cfree_cg_load`/`cfree_cg_store`, `cfree_cg_fp_binop`, `cfree_cg_call`,
-`cfree_cg_branch_true`, `cfree_cg_block_begin`, and so on. This API is the
-insulation layer: it is source-stable across all the internal changes below it,
-so the C parser's `cg_adapter`, the toy frontend, and the wasm-language frontend
-do not change when a backend does. See [FRONTENDS.md](FRONTENDS.md).
+`include/cfree/cg.h` is a stack machine. A frontend pushes typed values, names
+types, and issues operations that pop operands and push results —
+`cfree_cg_func_begin`, `cfree_cg_load`/`cfree_cg_store`, `cfree_cg_fp_binop`,
+`cfree_cg_call`, `cfree_cg_branch_true`, `cfree_cg_block_begin`, and so on. This
+API is the insulation layer: it is source-stable across all the internal changes
+below it. See [FRONTENDS.md](FRONTENDS.md).
+
+Every stack entry is exactly one of two **kinds**, and each op declares the
+kinds it consumes and produces: a **PLACE** (an addressable, typed location — a
+local's storage, a global, or a computed `[base + index*scale + offset]`) or a
+**VALUE** (a scalar rvalue: integer, float, pointer, or 128-bit scalar).
+Addressing is built explicitly — `push_local`→PLACE, `addr` PLACE→VALUE(ptr),
+`deref` VALUE(ptr)→PLACE, `field i` PLACE(record)→PLACE, `elem` VALUE(ptr)+index
+→PLACE — and the op *panics* on a kind mismatch; CG never infers the kind or
+inserts an implicit dereference. `load`/`store` take a PLACE and no
+effective-address rider; the place ops fold the constant offset (deref/field)
+and scale (elem) into one `OPK_INDIRECT`, so the backend still gets a single
+addressing-mode memop. Aggregates are always a PLACE.
The implementation lives in `src/cg/`, split by op family rather than one
monolith: `value.c` (stack discipline, lvalue/rvalue conversion, operand
diff --git a/doc/plan/CODEGEN.md b/doc/plan/CODEGEN.md
@@ -54,6 +54,7 @@ Between them sits the translation layer (`src/cg/value.c`, `arith.c`, `memory.c`
| `917ffe9` | **2 (AsmDir)** | Deleted internal `AsmDir` + `api_map_asm_dir`; `AsmConstraint.dir` and backends use public `CfreeCgAsmDir`. |
| `a2f6367` | **2 (Atomic/Order)** | Deleted internal `AtomicOp`/`MemOrder` + `api_map_atomic_op`/`api_map_mem_order`; **both** the semantic `CgTarget` and physical `NativeTarget` atomic hooks, the recorder+opt IR aux, and the interpreter now carry public `CfreeCgAtomicOp`/`CfreeCgMemOrder`. |
| `d03eb4c` | **6.2** | Isolated the `-O0` semantic peephole into `src/cg/fold.{c,h}`: integer constant folding, the `SV_CMP` delayed-compare lifecycle, the (gated-off) `SV_ARITH` delayed-arith lifecycle, and const-local store-to-load forwarding with its invalidation boundaries. `fold.h` is the documented contract, re-exported via `internal.h`; `value.c` keeps stack discipline, `api_lvalue_addr`, and the enum-mapping helpers. Pure relocation, no behavior change. `doc/CODEGEN.md` updated. |
+| `c338c74`+`8e17cb9` | **7 (core)** | Strict PLACE/VALUE addressing. Removed `CfreeCgEffAddr` from `load`/`store` (they consume a PLACE); added `deref(offset)` (VALUE ptr→PLACE), renamed `index`→`elem` (VALUE ptr + index→PLACE, scale=sizeof(T)), kept `field(i)`/`addr`. Each op **panics on kind mismatch** — no place/value inference. The place ops fold the constant offset (deref/field) and scale (elem→`log2_scale`) into one `OPK_INDIRECT[base + index*scale + offset]`, so the backend still gets a single addressing-mode memop (base/index dynamic, scale/offset folded). All three frontends + emu + cg-api tests conformed (explicit `deref`/decay/`field`). `cg.h` documents the kinds + per-op contracts. Green: toy 1344/0, cg-api, opt (incl tiny-inline), smoke, libc, isa/link/elf, and `make bootstrap` reproduces byte-identical at -O0 AND -O1. |
So **Tracks 1a/1d, 5, 3a, 6.2 are done; Track 2 is 2/3 done** (the 3 identical enums); **Track 4**
has FP_REM removed.
@@ -241,7 +242,31 @@ The semantic layer is also a `-O0` peephole optimizer — a **kept feature** (Pr
---
-## Track 7 — Strict place/value discipline (the centerpiece, UNTOUCHED)
+## Track 7 — Strict place/value discipline (the centerpiece)
+
+**Status: core LANDED** (`c338c74`+`8e17cb9`). The public addressing surface is the strict
+`push_local`/`addr`/`deref`/`field`/`elem`/`load`/`store` set; the `CfreeCgEffAddr` rider is
+gone; every op panics on a place/value kind mismatch (no inference at the boundary); and the
+place ops fold the constant offset/scale into one `OPK_INDIRECT[base + index*scale + offset]`
+for clean memops. All frontends + emu + cg-api tests conform; `make bootstrap` reproduces at
+-O0 AND -O1.
+
+**Remaining refinements (follow-ups):**
+- The *internal* `api_is_lvalue_sv` is still the place predicate (a heuristic on `ApiSValue`).
+ The boundary is strict, but replacing the internal heuristic with an explicit `ApiSValue`
+ kind tag (Model B's "every stack entry is exactly one kind") is not yet done.
+- Aggregate **VALUE**s aren't yet hard-forbidden inside the stack (aggregates are PLACEs in
+ practice, but there's no panic on an aggregate-typed value).
+- **wide16** (i128/f128) is still special-cased as aggregate-like in `memory.c`/`call.c`/
+ `wide.c` rather than flowing as a VALUE.
+- **Bitfields** still ride on `CfreeCgMemAccess`/`CfreeCgField` (Track 3b: make them a PLACE
+ subkind on the strict `load`/`store`).
+- **-O0 mem-op quality**: the C frontend reaches non-trivial places via
+ `pcg_materialize_lv_to_ptr` (int arithmetic) + `deref`; it could instead emit
+ `deref(offset)`/`elem` directly so -O0 also gets the folded addressing mode (-O1's
+ addr-fold already recovers it; decision #8 makes this non-blocking).
+
+### Original design notes (for the remaining refinements)
**Decided:** Model B (explicit place/value kinds); wide-16 scalars are *values*. (Track 3c —
the `scale` vs `log2_scale` rider mismatch — is subsumed here: the `CfreeCgEffAddr` rider is
diff --git a/include/cfree/cg.h b/include/cfree/cg.h
@@ -266,19 +266,6 @@ typedef struct CfreeCgMemAccess {
int bit_signed;
} CfreeCgMemAccess;
-/* Effective address rider on the memops: encodes
- * base + index * scale + offset directly on the load/store.
- *
- * scale == 0 indicates "no index"; the memop consumes only [base].
- * scale > 0 indicates an indexed access; the memop consumes [base, index]
- * and multiplies index by scale raw bytes (frontends pass element size
- * explicitly — not log2). offset is a signed byte displacement folded into
- * the addressing mode where the target permits. */
-typedef struct CfreeCgEffAddr {
- int64_t offset;
- uint32_t scale;
-} CfreeCgEffAddr;
-
/* ============================================================
* Declarations and Symbols
* ============================================================ */
@@ -561,8 +548,33 @@ CFREE_API void cfree_cg_computed_goto(CfreeCg*,
CFREE_API void cfree_cg_unreachable(CfreeCg*);
/* ============================================================
- * Value Stack and Lvalues
- * ============================================================ */
+ * Value stack: PLACES and VALUES
+ * ============================================================
+ *
+ * Every stack entry is exactly one of two kinds, and each op below declares the
+ * kinds it consumes and produces. The op enforces this: handing an op the wrong
+ * kind is a usage error and panics. CG never *infers* the kind of a stack entry
+ * or silently inserts a dereference — addressing is always built explicitly.
+ *
+ * PLACE — an addressable, typed location of an object (a local's storage, a
+ * global, or a computed `[base + index*scale + offset]`). Produced by
+ * push_local / deref / field / elem; consumed by load / store / addr.
+ *
+ * VALUE — a scalar rvalue: an integer, float, pointer, or 128-bit scalar.
+ * Produced by push_int/float/null, push_symbol_addr, push_local_addr,
+ * addr, and load; consumed by the arithmetic / call / branch ops.
+ *
+ * Aggregates (records, arrays) are ALWAYS a PLACE — there is no aggregate VALUE.
+ * Copying an aggregate is an explicit store/memcpy between places.
+ *
+ * The four building blocks of addressing:
+ * - push_local l : — -> PLACE (the local's storage)
+ * - addr : PLACE -> VALUE(ptr) (address of the place)
+ * - deref : VALUE(ptr) -> PLACE (the place the ptr names)
+ * - field i : PLACE(record)-> PLACE(field) (sub-object, by layout)
+ * - elem : VALUE(ptr),index VALUE -> PLACE (element of an array/ptr)
+ * From these, `*p` is `deref`, `p->f` is `deref; field`, `s.f` is `field`,
+ * `a[i]` is `addr; <decay to *elem>; elem`, and `&x` is `addr`. */
CFREE_API void cfree_cg_dup(CfreeCg*);
CFREE_API void cfree_cg_dup2(CfreeCg*); /* duplicates the top two slots */
@@ -571,57 +583,71 @@ CFREE_API void cfree_cg_drop(CfreeCg*);
CFREE_API void cfree_cg_rot3(CfreeCg*); /* [..., a, b, c] -> [..., b, c, a] */
/* Returns nonzero when the current top-of-stack value is a compile-time known
- * integer-like immediate. The value is not popped. */
+ * integer-like immediate VALUE. The value is not popped. */
CFREE_API int cfree_cg_top_const_int(CfreeCg*, int64_t* out_value);
+/* Push a scalar VALUE. */
CFREE_API void cfree_cg_push_int(CfreeCg*, uint64_t value, CfreeCgTypeId type);
CFREE_API void cfree_cg_push_float(CfreeCg*, double value, CfreeCgTypeId type);
CFREE_API void cfree_cg_push_null(CfreeCg*, CfreeCgTypeId ptr_type);
+/* Push the PLACE that is the local's storage. Stack: [] -> [place]. */
CFREE_API void cfree_cg_push_local(CfreeCg*, CfreeCgLocal local);
+/* Push the local's address as a pointer VALUE (sugar for push_local; addr).
+ * Stack: [] -> [ptr]. */
CFREE_API void cfree_cg_push_local_addr(CfreeCg*, CfreeCgLocal local);
/* Anonymous immutable data. Returns a local readonly object symbol; callers
- * can materialize its address with push_symbol_addr. pointee_type describes
- * the logical value at that address, enabling const_data + indirect + load to
- * materialize arbitrary-width constants. */
+ * can materialize its address (a VALUE) with push_symbol_addr. pointee_type
+ * describes the logical value at that address, enabling const_data +
+ * push_symbol_addr + deref + load to materialize arbitrary-width constants. */
CFREE_API CfreeCgSym cfree_cg_const_data(CfreeCg*, const uint8_t* data,
size_t len, uint32_t align,
CfreeCgTypeId pointee_type);
-/* Pushes &sym + addend as a pointer rvalue. For TLS objects this means the
- * address of the current thread's instance; the target chooses LE/IE/GD/TLVP
- * or equivalent lowering from the symbol attrs and output mode. */
+/* Push &sym + addend as a pointer VALUE. For TLS objects this means the address
+ * of the current thread's instance; the target chooses LE/IE/GD/TLVP or
+ * equivalent lowering from the symbol attrs and output mode. Stack: [] -> [ptr].
+ */
CFREE_API void cfree_cg_push_symbol_addr(CfreeCg*, CfreeCgSym sym,
int64_t addend);
-/* Projects an lvalue TOS back to a pointer rvalue (e.g. for `&x`, passing to
- * a call, escape). */
+/* PLACE -> VALUE(ptr): the address of the place (e.g. `&x`, or to pass/escape).
+ * Stack: [place] -> [ptr]. Errors if TOS is not a PLACE. */
CFREE_API void cfree_cg_addr(CfreeCg*);
-/* Project through array/pointer and record fields. These leave an lvalue on
- * the stack, so callers can load from or store to the selected slot. */
-CFREE_API void cfree_cg_index(CfreeCg*, uint64_t offset);
+/* VALUE(ptr) -> PLACE: the explicit pointer->place transition. The produced
+ * place is `*(ptr + offset bytes)`; `offset` is a byte displacement folded into
+ * the addressing mode (0 for a plain `*p`). Stack: [ptr] -> [place]. Errors if
+ * TOS is not a pointer VALUE — a PLACE must be turned into a pointer with `addr`
+ * first; the op never guesses. */
+CFREE_API void cfree_cg_deref(CfreeCg*, int64_t offset);
+
+/* PLACE(record) -> PLACE(field): project a record place to one of its fields by
+ * index; the byte offset and field type come from the record's layout (CG owns
+ * layout). Stack: [place] -> [place]. Errors if TOS is not a record PLACE — for
+ * `p->f` the frontend does `deref; field`, not `field` on a pointer. */
CFREE_API void cfree_cg_field(CfreeCg*, uint32_t field_index);
-/* Single load/store ops with an effective-address rider.
- *
- * `base` is either an lvalue (push_local) or a pointer-typed value. When
- * `ea.scale == 0` the memop consumes only [base]; when `ea.scale > 0` it
- * also pops an integer-typed `index` (with signedness inherited from its
- * producer). Field offsets ride in `ea.offset`; array scales ride in
- * `ea.scale` as raw bytes.
+/* (VALUE(ptr to T), index VALUE) -> PLACE(T): the element at `*(base +
+ * index*sizeof(T) + offset)`. The index is scaled by sizeof(T) (the pointer's
+ * pointee) and the constant `offset` byte displacement is folded in, so the
+ * place is a single `[base + index*scale + offset]` addressing mode (base and
+ * index dynamic; scale and offset constant). The base is a pointer VALUE; an
+ * array is decayed to a pointer (`addr` + cast to *T) by the frontend first.
+ * Stack: [base, index] -> [place]. Errors if the base is not a pointer VALUE. */
+CFREE_API void cfree_cg_elem(CfreeCg*, int64_t offset);
+
+/* Load a VALUE from a PLACE / store a VALUE into a PLACE. The PLACE carries all
+ * addressing (built via push_local / deref / field / elem); the memop takes no
+ * effective-address rider. Bit-field metadata rides in `access`. Both error if
+ * the addressed operand is not a PLACE — a pointer VALUE must be `deref`'d
+ * first.
*
* Stack effects:
- * scale == 0:
- * load: [base] -> [value]
- * store: [base, value] -> []
- * scale > 0:
- * load: [base, index] -> [value]
- * store: [base, index, value] -> [] */
-CFREE_API void cfree_cg_load(CfreeCg*, CfreeCgMemAccess access,
- CfreeCgEffAddr ea);
-CFREE_API void cfree_cg_store(CfreeCg*, CfreeCgMemAccess access,
- CfreeCgEffAddr ea);
+ * load: [place] -> [value]
+ * store: [place, value] -> [] */
+CFREE_API void cfree_cg_load(CfreeCg*, CfreeCgMemAccess access);
+CFREE_API void cfree_cg_store(CfreeCg*, CfreeCgMemAccess access);
/* ============================================================
* ABI variadic argument access
@@ -1161,18 +1187,16 @@ static inline void cfree_cg_musttail_call_symbol(CfreeCg* cg, CfreeCgSym sym,
/* Read the scalar value of a local. Stack: [] -> [value]. */
static inline void cfree_cg_local_read(CfreeCg* cg, CfreeCgLocal local,
CfreeCgMemAccess access) {
- CfreeCgEffAddr ea = {0, 0};
cfree_cg_push_local(cg, local);
- cfree_cg_load(cg, access, ea);
+ cfree_cg_load(cg, access);
}
/* Write the scalar value on TOS into a local. Stack: [value] -> []. */
static inline void cfree_cg_local_write(CfreeCg* cg, CfreeCgLocal local,
CfreeCgMemAccess access) {
- CfreeCgEffAddr ea = {0, 0};
cfree_cg_push_local(cg, local); /* [value, lv] */
cfree_cg_swap(cg); /* [lv, value] */
- cfree_cg_store(cg, access, ea);
+ cfree_cg_store(cg, access);
}
/* Increment/decrement an lvalue in place. Stack: [lv] -> [result].
@@ -1181,23 +1205,22 @@ static inline void cfree_cg_local_write(CfreeCg* cg, CfreeCgLocal local,
* of the lvalue. */
static inline void cfree_cg_inc_dec(CfreeCg* cg, CfreeCgIntBinOp op, int post,
CfreeCgTypeId ty, CfreeCgMemAccess access) {
- CfreeCgEffAddr ea = {0, 0};
- cfree_cg_dup(cg); /* [lv, lv] */
- cfree_cg_load(cg, access, ea); /* [lv, old] */
+ cfree_cg_dup(cg); /* [lv, lv] */
+ cfree_cg_load(cg, access); /* [lv, old] */
if (post) {
- cfree_cg_dup(cg); /* [lv, old, old] */
- cfree_cg_push_int(cg, 1, ty); /* [lv, old, old, 1] */
- cfree_cg_int_binop(cg, op, 0); /* [lv, old, new] */
- cfree_cg_rot3(cg); /* [old, new, lv] */
- cfree_cg_swap(cg); /* [old, lv, new] */
- cfree_cg_store(cg, access, ea); /* [old] */
+ cfree_cg_dup(cg); /* [lv, old, old] */
+ cfree_cg_push_int(cg, 1, ty); /* [lv, old, old, 1] */
+ cfree_cg_int_binop(cg, op, 0); /* [lv, old, new] */
+ cfree_cg_rot3(cg); /* [old, new, lv] */
+ cfree_cg_swap(cg); /* [old, lv, new] */
+ cfree_cg_store(cg, access); /* [old] */
} else {
- cfree_cg_push_int(cg, 1, ty); /* [lv, old, 1] */
- cfree_cg_int_binop(cg, op, 0); /* [lv, new] */
- cfree_cg_dup(cg); /* [lv, new, new] */
- cfree_cg_rot3(cg); /* [new, new, lv] */
- cfree_cg_swap(cg); /* [new, lv, new] */
- cfree_cg_store(cg, access, ea); /* [new] */
+ cfree_cg_push_int(cg, 1, ty); /* [lv, old, 1] */
+ cfree_cg_int_binop(cg, op, 0); /* [lv, new] */
+ cfree_cg_dup(cg); /* [lv, new, new] */
+ cfree_cg_rot3(cg); /* [new, new, lv] */
+ cfree_cg_swap(cg); /* [new, lv, new] */
+ cfree_cg_store(cg, access); /* [new] */
}
}
diff --git a/lang/c/parse/cg_adapter.c b/lang/c/parse/cg_adapter.c
@@ -437,24 +437,35 @@ void pcg_push_float(Parser* p, double v, const Type* ty) {
pcg_push_type(p, ty);
}
-/* Fill `access` (CfreeCgMemAccess) and `ea` (CfreeCgEffAddr) for a memop
- * against the TOS lvalue. The lvalue's pending EA on aux is consumed: caller
- * is expected to follow with the matching cfree_cg_load / cfree_cg_store. */
-static void pcg_consume_ea_for_top(Parser* p, const Type* access_ty,
- CfreeCgMemAccess* access,
- CfreeCgEffAddr* ea) {
- PcgLvAux* lv = pcg_top_lv_aux(p);
- *access = pcg_mem(p, access_ty);
+/* Fill `access` (CfreeCgMemAccess) for a memop against an lvalue carrying the
+ * given aux. Bit-field metadata rides in the access; addressing is no longer a
+ * rider — it is built explicitly with deref/elem/field before the load/store. */
+static CfreeCgMemAccess pcg_access_for(Parser* p, const Type* access_ty,
+ const PcgLvAux* lv) {
+ CfreeCgMemAccess access = pcg_mem(p, access_ty);
if (lv && lv->bit_width) {
- access->bit_offset = lv->bit_offset;
- access->bit_width = lv->bit_width;
- access->storage_size = lv->storage_size;
- access->bit_signed = lv->bit_signed;
+ access.bit_offset = lv->bit_offset;
+ access.bit_width = lv->bit_width;
+ access.storage_size = lv->storage_size;
+ access.bit_signed = lv->bit_signed;
}
- ea->offset = lv ? lv->offset : 0;
- ea->scale = lv ? lv->scale : 0u;
+ return access;
}
+/* A trivially-addressable lvalue: a bare local slot with no pending field
+ * offset, array scale, or bit-field. Its PLACE is already on the CG stack
+ * (push_local), so a load/store can consume it directly without first
+ * materializing an address. */
+static int pcg_lv_is_trivial_local(const PcgLvAux* lv) {
+ return lv && lv->base_kind == PCG_LV_BASE_LOCAL && lv->offset == 0 &&
+ lv->scale == 0 && lv->bit_width == 0;
+}
+
+/* Materialize the TOS lvalue (folding its pending field offset / array scale
+ * into the address) as a single pointer rvalue. Defined below; the memops use
+ * it to build an explicit place before load/store. */
+static void pcg_materialize_lv_to_ptr(Parser* p, const Type* result_ptr_ty);
+
void pcg_push_local_typed(Parser* p, FrameSlot s, const Type* ty) {
if (pcg_emit_enabled(p)) cfree_cg_push_local(p->cg, s);
pcg_push_type(p, ty);
@@ -481,12 +492,20 @@ void pcg_load(Parser* p) {
const Type* ty = pcg_top_type(p);
int was_lvalue = pcg_top_is_lvalue(p);
if (pcg_emit_enabled(p)) {
- CfreeCgMemAccess access;
- CfreeCgEffAddr ea;
- pcg_consume_ea_for_top(p, ty, &access, &ea);
- cfree_cg_load(p->cg, access, ea);
+ PcgLvAux* lv = pcg_top_lv_aux(p);
+ CfreeCgMemAccess access = pcg_access_for(p, ty, lv);
+ /* Build the PLACE the strict load requires. A trivial local already has its
+ * PLACE on the CG stack (push_local) and loads directly; anything else is
+ * reduced to a single pointer (materialize, or a pointer-rvalue base) and
+ * then deref'd to a place. */
+ if (!was_lvalue || !pcg_lv_is_trivial_local(lv)) {
+ if (was_lvalue) pcg_materialize_lv_to_ptr(p, type_ptr(p->pool, ty));
+ cfree_cg_deref(p->cg, 0);
+ }
+ cfree_cg_load(p->cg, access);
}
if (was_lvalue && p->cg_type_sp) {
+ p->cg_type_stack[p->cg_type_sp - 1u] = ty;
p->cg_value_flags[p->cg_type_sp - 1u] = 0;
pcg_aux_clear(&p->cg_lv_aux[p->cg_type_sp - 1u]);
}
@@ -613,84 +632,54 @@ void pcg_store(Parser* p) {
const Type* rv_ty = pcg_top_type(p);
const Type* mem_ty = lv_ty;
int emit = pcg_emit_enabled(p);
+ /* The aux to consume lives on the lvalue slot at parser depth 1. */
+ PcgLvAux* lv = pcg_lv_aux_at(p, 1);
CfreeCgMemAccess access;
- CfreeCgEffAddr ea;
- PcgLvAux* lv;
if (rv_ty && type_is_ptr(rv_ty) && (!lv_ty || !type_is_ptr(lv_ty))) {
mem_ty = rv_ty;
}
- /* The aux to consume lives on the lvalue slot at parser depth 1. */
- lv = pcg_lv_aux_at(p, 1);
- access = pcg_mem(p, mem_ty ? mem_ty : rv_ty);
- if (lv && lv->bit_width) {
- access.bit_offset = lv->bit_offset;
- access.bit_width = lv->bit_width;
- access.storage_size = lv->storage_size;
- access.bit_signed = lv->bit_signed;
- }
- ea.offset = lv ? lv->offset : 0;
- ea.scale = lv ? lv->scale : 0u;
- if (ea.scale == 0 &&
- !(rv_ty && (rv_ty->kind == TY_INT128 || rv_ty->kind == TY_UINT128 ||
- rv_ty->kind == TY_LDOUBLE))) {
- if (emit) {
+ access = pcg_access_for(p, mem_ty ? mem_ty : rv_ty, lv);
+ if (emit) {
+ int wide = rv_ty && (rv_ty->kind == TY_INT128 ||
+ rv_ty->kind == TY_UINT128 || rv_ty->kind == TY_LDOUBLE);
+ if (pcg_lv_is_trivial_local(lv) && !wide) {
+ /* The destination place is already on the CG stack. Keep a copy of rv as
+ * the assignment's value. Stack: [place, value]. */
cfree_cg_dup(p->cg);
cfree_cg_rot3(p->cg);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, access, ea);
- }
- } else if (ea.scale == 0) {
- /* Simple lvalue: stash rv so the actual destination store does not have
- * to keep a duplicate expression result live under register pressure. */
- FrameSlotDesc fsd;
- FrameSlot tmp;
- memset(&fsd, 0, sizeof fsd);
- fsd.type = rv_ty;
- fsd.size = c_abi_sizeof(p->abi, rv_ty);
- fsd.align = c_abi_alignof(p->abi, rv_ty);
- fsd.kind = FS_LOCAL;
- tmp = pcg_local(p, &fsd);
- if (emit) {
- CfreeCgMemAccess rv_access = pcg_mem(p, rv_ty);
- CfreeCgEffAddr zero_ea;
- zero_ea.offset = 0;
- zero_ea.scale = 0;
- /* [base, rv] */
- cfree_cg_push_local(p->cg, tmp); /* [base, rv, tmp] */
- cfree_cg_swap(p->cg); /* [base, tmp, rv] */
- cfree_cg_store(p->cg, rv_access, zero_ea); /* [base] */
- cfree_cg_push_local(p->cg, tmp);
- cfree_cg_load(p->cg, rv_access, zero_ea); /* [base, rv] */
- cfree_cg_store(p->cg, access, ea); /* [] */
- cfree_cg_push_local(p->cg, tmp);
- cfree_cg_load(p->cg, rv_access, zero_ea); /* [rv] */
- }
- } else {
- /* Indexed lvalue: CG stack on entry is [base, idx, rv]. Stash rv into a
- * compiler-temp local so we can reorder cleanly, then re-load after the
- * store. */
- FrameSlotDesc fsd;
- FrameSlot tmp;
- memset(&fsd, 0, sizeof fsd);
- fsd.type = rv_ty;
- fsd.size = c_abi_sizeof(p->abi, rv_ty);
- fsd.align = c_abi_alignof(p->abi, rv_ty);
- fsd.kind = FS_LOCAL;
- tmp = pcg_local(p, &fsd);
- if (emit) {
+ cfree_cg_store(p->cg, access);
+ } else {
+ /* Stash rv into a temp so the destination place can be built from the
+ * base — folding any field offset / array scale into an explicit pointer
+ * — then reload rv to store it and to leave it as the expression value. */
+ FrameSlotDesc fsd;
+ FrameSlot tmp;
CfreeCgMemAccess rv_access = pcg_mem(p, rv_ty);
- CfreeCgEffAddr zero_ea;
- zero_ea.offset = 0;
- zero_ea.scale = 0;
- /* [base, idx, rv] */
- cfree_cg_push_local(p->cg, tmp); /* [base, idx, rv, tmp] */
- cfree_cg_swap(p->cg); /* [base, idx, tmp, rv] */
- cfree_cg_store(p->cg, rv_access, zero_ea); /* [base, idx] */
+ int trivial = pcg_lv_is_trivial_local(lv);
+ memset(&fsd, 0, sizeof fsd);
+ fsd.type = rv_ty;
+ fsd.size = c_abi_sizeof(p->abi, rv_ty);
+ fsd.align = c_abi_alignof(p->abi, rv_ty);
+ fsd.kind = FS_LOCAL;
+ tmp = pcg_local(p, &fsd);
+ cfree_cg_push_local(p->cg, tmp); /* [base.., value, &tmp] */
+ cfree_cg_swap(p->cg); /* [base.., &tmp, value] */
+ cfree_cg_store(p->cg, rv_access); /* [base..] (stash rv) */
+ if (!trivial) {
+ /* Materialize operates on the parser-TOS lvalue; drop the rv type slot
+ * so the lvalue is on top and matches the CG [base..]. The pointer is
+ * deref'd to the PLACE the strict store requires. */
+ pcg_drop_type(p);
+ pcg_materialize_lv_to_ptr(p, type_ptr(p->pool, lv_ty)); /* [dst_ptr] */
+ cfree_cg_deref(p->cg, 0); /* [dst_place] */
+ pcg_push_type(p, rv_ty);
+ }
cfree_cg_push_local(p->cg, tmp);
- cfree_cg_load(p->cg, rv_access, zero_ea); /* [base, idx, rv] */
- cfree_cg_store(p->cg, access, ea); /* [] */
+ cfree_cg_load(p->cg, rv_access); /* [dst, value] */
+ cfree_cg_store(p->cg, access); /* [] */
cfree_cg_push_local(p->cg, tmp);
- cfree_cg_load(p->cg, rv_access, zero_ea); /* [rv] */
+ cfree_cg_load(p->cg, rv_access); /* [value] */
}
}
pcg_drop_type(p);
@@ -938,12 +927,9 @@ void pcg_inc_dec(Parser* p, BinOp op, int post) {
{
CfreeCgIntBinOp cg_op = pcg_int_binop(op);
PcgLvAux* lv = pcg_top_lv_aux(p);
- int indexed = lv && lv->scale != 0;
- CfreeCgMemAccess access;
- CfreeCgEffAddr ea;
+ CfreeCgMemAccess access = pcg_access_for(p, ty, lv);
const Type* step_ty = ty;
u32 step = 1;
- pcg_consume_ea_for_top(p, ty, &access, &ea);
if (ty && ty->kind == TY_PTR) {
const Type* pointee = ty->ptr.pointee;
if (pointee && pointee->kind == TY_VOID)
@@ -951,57 +937,51 @@ void pcg_inc_dec(Parser* p, BinOp op, int post) {
step = c_abi_sizeof(p->abi, pointee);
step_ty = c_abi_ptrdiff_type(p->abi, p->pool);
}
- /* Allocate a temp to stash the previous (post=1) or new (post=0) value
- * for the expression-value. Both indexed and simple paths use the same
- * stash so the resulting sequence is uniform. */
+ /* Materialize the lvalue to a single destination pointer so its address can
+ * be duplicated for the read-modify-write. */
+ pcg_materialize_lv_to_ptr(p, type_ptr(p->pool, ty));
{
FrameSlotDesc fsd;
FrameSlot tmp;
const Type* result_ty = ty;
+ CfreeCgMemAccess r_access = pcg_mem(p, result_ty);
memset(&fsd, 0, sizeof fsd);
fsd.type = result_ty;
fsd.size = c_abi_sizeof(p->abi, result_ty);
fsd.align = c_abi_alignof(p->abi, result_ty);
fsd.kind = FS_LOCAL;
tmp = pcg_local(p, &fsd);
- {
- CfreeCgMemAccess r_access = pcg_mem(p, result_ty);
- CfreeCgEffAddr zero_ea = {0, 0};
- /* Duplicate the lvalue base (+ index if indexed) so we can load the
- * old value AND store the new value through the same address. */
- if (indexed) {
- cfree_cg_dup2(p->cg);
- } else {
- cfree_cg_dup(p->cg);
- }
- cfree_cg_load(p->cg, access, ea); /* ..., lv-base[, idx], old */
- if (post) {
- /* Stash old, compute new, store, then re-load old as result. */
- cfree_cg_dup(p->cg); /* ..., lv-base[, idx], old, old */
- cfree_cg_push_local(p->cg, tmp);
- cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, r_access,
- zero_ea); /* ..., lv-base[, idx], old */
- pcg_emit_inc_step(p, ty, op, cg_op, step_ty,
- step); /* ..., lv-base[, idx], new */
- cfree_cg_store(p->cg, access, ea); /* [] */
- cfree_cg_push_local(p->cg, tmp);
- cfree_cg_load(p->cg, r_access, zero_ea); /* [old] */
- } else {
- /* Compute new, stash new, store, then re-load new as result. */
- pcg_emit_inc_step(p, ty, op, cg_op, step_ty,
- step); /* ..., lv-base[, idx], new */
- cfree_cg_dup(p->cg); /* ..., lv-base[, idx], new, new */
- cfree_cg_push_local(p->cg, tmp);
- cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, r_access,
- zero_ea); /* ..., lv-base[, idx], new */
- cfree_cg_store(p->cg, access, ea); /* [] */
- cfree_cg_push_local(p->cg, tmp);
- cfree_cg_load(p->cg, r_access, zero_ea); /* [new] */
- }
- (void)step;
+ cfree_cg_dup(p->cg); /* [ptr, ptr] */
+ cfree_cg_deref(p->cg, 0); /* [ptr, place] */
+ cfree_cg_load(p->cg, access); /* [ptr, old] */
+ if (post) {
+ /* Stash old, compute new, store, then re-load old as result. */
+ cfree_cg_dup(p->cg); /* [ptr, old, old] */
+ cfree_cg_push_local(p->cg, tmp);
+ cfree_cg_swap(p->cg);
+ cfree_cg_store(p->cg, r_access); /* [ptr, old] */
+ pcg_emit_inc_step(p, ty, op, cg_op, step_ty, step); /* [ptr, new] */
+ cfree_cg_swap(p->cg); /* [new, ptr] */
+ cfree_cg_deref(p->cg, 0); /* [new, place] */
+ cfree_cg_swap(p->cg); /* [place, new] */
+ cfree_cg_store(p->cg, access); /* [] */
+ cfree_cg_push_local(p->cg, tmp);
+ cfree_cg_load(p->cg, r_access); /* [old] */
+ } else {
+ /* Compute new, stash new, store, then re-load new as result. */
+ pcg_emit_inc_step(p, ty, op, cg_op, step_ty, step); /* [ptr, new] */
+ cfree_cg_dup(p->cg); /* [ptr, new, new] */
+ cfree_cg_push_local(p->cg, tmp);
+ cfree_cg_swap(p->cg);
+ cfree_cg_store(p->cg, r_access); /* [ptr, new] */
+ cfree_cg_swap(p->cg); /* [new, ptr] */
+ cfree_cg_deref(p->cg, 0); /* [new, place] */
+ cfree_cg_swap(p->cg); /* [place, new] */
+ cfree_cg_store(p->cg, access); /* [] */
+ cfree_cg_push_local(p->cg, tmp);
+ cfree_cg_load(p->cg, r_access); /* [new] */
}
+ (void)step;
}
}
/* Parser stack: drop the lvalue slot, push the result rvalue type. */
diff --git a/lang/toy/asm.c b/lang/toy/asm.c
@@ -187,6 +187,9 @@ static int toy_parse_asm_input_operand(ToyParser* p,
toy_error(p, p->cur.loc, "unknown asm memory operand");
return 0;
}
+ /* The "m" operand wants a memory PLACE; toy_emit_var_lvalue leaves the
+ * variable's address as a pointer VALUE, so deref it back to a place. */
+ cfree_cg_deref(p->cg, 0);
} else {
operand->type = toy_parse_expr(p);
}
@@ -480,11 +483,13 @@ int toy_parse_typed_asm_tail(ToyParser* p, CfreeCgTypeId result_ty,
&foff) != 0)
goto done;
cfree_cg_push_local(p->cg, rec_slot);
+ cfree_cg_addr(p->cg);
+ cfree_cg_deref(p->cg, (int64_t)foff);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, field.type),
- (CfreeCgEffAddr){(int64_t)foff, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, field.type));
}
- cfree_cg_push_local(p->cg, rec_slot);
+ /* Record result lives as a pointer VALUE (its address) on the stack. */
+ cfree_cg_push_local_addr(p->cg, rec_slot);
}
ok = 1;
diff --git a/lang/toy/builtins.c b/lang/toy/builtins.c
@@ -27,20 +27,20 @@ static void toy_store_top_to_local(ToyParser* p, CfreeCgLocal local,
CfreeCgTypeId ty) {
cfree_cg_push_local(p->cg, local);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, ty));
}
static void toy_store_const_to_local(ToyParser* p, CfreeCgLocal local,
CfreeCgTypeId ty, uint64_t value) {
cfree_cg_push_local(p->cg, local);
cfree_cg_push_int(p->cg, value, ty);
- cfree_cg_store(p->cg, toy_mem_access(p, ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, ty));
}
static void toy_push_loaded_local(ToyParser* p, CfreeCgLocal local,
CfreeCgTypeId ty) {
cfree_cg_push_local(p->cg, local);
- cfree_cg_load(p->cg, toy_mem_access(p, ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(p->cg, toy_mem_access(p, ty));
}
static void toy_emit_dynamic_memory_loop(ToyParser* p, CfreeCgLocal dst_local,
@@ -64,22 +64,25 @@ static void toy_emit_dynamic_memory_loop(ToyParser* p, CfreeCgLocal dst_local,
toy_push_loaded_local(p, dst_local, u8_ptr_ty);
toy_push_loaded_local(p, index_local, p->int_type);
- /* The destination memop carries scale = sizeof(u8) = 1; it pops
- * [dst_ptr, index] and then [value]. */
+ /* Build the destination element place from [dst_ptr, index]; the element
+ * scale = sizeof(u8) = 1 is derived from the base type. The store then
+ * consumes [dst_place, value]. */
+ cfree_cg_elem(p->cg, 0);
if (is_memset) {
cfree_cg_push_int(p->cg, set_value, u8_ty);
} else {
toy_push_loaded_local(p, src_local, u8_ptr_ty);
toy_push_loaded_local(p, index_local, p->int_type);
- cfree_cg_load(p->cg, toy_mem_access(p, u8_ty), (CfreeCgEffAddr){0, 1});
+ cfree_cg_elem(p->cg, 0);
+ cfree_cg_load(p->cg, toy_mem_access(p, u8_ty));
}
- cfree_cg_store(p->cg, toy_mem_access(p, u8_ty), (CfreeCgEffAddr){0, 1});
+ cfree_cg_store(p->cg, toy_mem_access(p, u8_ty));
cfree_cg_push_local(p->cg, index_local);
toy_push_loaded_local(p, index_local, p->int_type);
cfree_cg_push_int(p->cg, 1, p->int_type);
cfree_cg_int_binop(p->cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_store(p->cg, toy_mem_access(p, p->int_type), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, p->int_type));
cfree_cg_jump(p->cg, loop_label);
cfree_cg_label_place(p->cg, end_label);
@@ -565,17 +568,17 @@ CfreeCgTypeId toy_parse_builtin_call(ToyParser* p, CfreeSym name,
dst_slot = cfree_cg_local(p->cg, dst_ty, toy_slot_attrs(0));
cfree_cg_push_local(p->cg, src_slot);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, src_ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, src_ty));
cfree_cg_push_local(p->cg, dst_slot);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, dst_ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, dst_ty));
cfree_cg_push_local(p->cg, dst_slot);
- cfree_cg_load(p->cg, toy_mem_access(p, dst_ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(p->cg, toy_mem_access(p, dst_ty));
cfree_cg_push_int(p->cg, clear_mask, dst_ty);
cfree_cg_int_binop(p->cg, CFREE_CG_INT_AND, 0);
cfree_cg_push_local(p->cg, src_slot);
- cfree_cg_load(p->cg, toy_mem_access(p, src_ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(p->cg, toy_mem_access(p, src_ty));
cfree_cg_push_int(p->cg, src_mask, src_ty);
cfree_cg_int_binop(p->cg, CFREE_CG_INT_AND, 0);
if (lo > 0) {
@@ -998,15 +1001,19 @@ CfreeCgTypeId toy_parse_generic_builtin(ToyParser* p, CfreeSym name,
cfree_cg_type_record_field(p->c, rec_ty, 0, NULL, &f0_off);
cfree_cg_type_record_field(p->c, rec_ty, 1, NULL, &f1_off);
cfree_cg_push_local(p->cg, rec_slot);
+ cfree_cg_addr(p->cg);
+ cfree_cg_deref(p->cg, (int64_t)f1_off);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, fields[1].type),
- (CfreeCgEffAddr){(int64_t)f1_off, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, fields[1].type));
cfree_cg_push_local(p->cg, rec_slot);
+ cfree_cg_addr(p->cg);
+ cfree_cg_deref(p->cg, (int64_t)f0_off);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, fields[0].type),
- (CfreeCgEffAddr){(int64_t)f0_off, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, fields[0].type));
}
- cfree_cg_push_local(p->cg, rec_slot);
+ /* Record result lives as a pointer VALUE (its address) on the stack, the
+ * shape record field-access / record-copy consume downstream. */
+ cfree_cg_push_local_addr(p->cg, rec_slot);
return rec_ty;
}
@@ -1327,15 +1334,18 @@ CfreeCgTypeId toy_parse_atomic_generic_builtin(ToyParser* p, CfreeSym name,
cfree_cg_type_record_field(p->c, rec_ty, 0, NULL, &f0_off);
cfree_cg_type_record_field(p->c, rec_ty, 1, NULL, &f1_off);
cfree_cg_push_local(p->cg, rec_slot);
+ cfree_cg_addr(p->cg);
+ cfree_cg_deref(p->cg, (int64_t)f1_off);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, fields[1].type),
- (CfreeCgEffAddr){(int64_t)f1_off, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, fields[1].type));
cfree_cg_push_local(p->cg, rec_slot);
+ cfree_cg_addr(p->cg);
+ cfree_cg_deref(p->cg, (int64_t)f0_off);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, fields[0].type),
- (CfreeCgEffAddr){(int64_t)f0_off, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, fields[0].type));
}
- cfree_cg_push_local(p->cg, rec_slot);
+ /* Record result lives as a pointer VALUE (its address) on the stack. */
+ cfree_cg_push_local_addr(p->cg, rec_slot);
return rec_ty;
}
diff --git a/lang/toy/expr.c b/lang/toy/expr.c
@@ -39,9 +39,20 @@ static int toy_reject_tail_call_operand(ToyParser* p) {
CfreeCgTypeId toy_push_named_rvalue(ToyParser* p, CfreeSym name) {
ToyVar* v = toy_find_var(p, name);
if (v) {
- toy_push_var_lvalue(p, v);
- if (cfree_cg_type_kind(p->c, v->type) != CFREE_CG_TYPE_RECORD)
- cfree_cg_load(p->cg, toy_mem_access(p, v->type), (CfreeCgEffAddr){0, 0});
+ if (cfree_cg_type_kind(p->c, v->type) == CFREE_CG_TYPE_RECORD) {
+ /* Record: leave the address (pointer VALUE) for the caller's copy. */
+ toy_push_var_lvalue(p, v);
+ } else if (v->is_static) {
+ /* Static scalar: its address is a pointer; deref to a place, then load. */
+ cfree_cg_push_symbol_addr(p->cg, v->static_sym, 0);
+ cfree_cg_deref(p->cg, 0);
+ cfree_cg_load(p->cg, toy_mem_access(p, v->type));
+ } else {
+ /* Local scalar: the local's PLACE loads directly (no address round-trip,
+ * which keeps small accessors inlinable). */
+ cfree_cg_push_local(p->cg, v->local);
+ cfree_cg_load(p->cg, toy_mem_access(p, v->type));
+ }
p->last_type = v->toy_type;
return v->type;
}
@@ -49,9 +60,10 @@ CfreeCgTypeId toy_push_named_rvalue(ToyParser* p, CfreeSym name) {
ToyGlobal* g = toy_find_global(p, name);
if (g) {
cfree_cg_push_symbol_addr(p->cg, toy_global_cur_sym(p, g), 0);
- if (cfree_cg_type_kind(p->c, g->type) != CFREE_CG_TYPE_RECORD)
- cfree_cg_load(p->cg, toy_mem_access(p, g->type),
- (CfreeCgEffAddr){0, 0});
+ if (cfree_cg_type_kind(p->c, g->type) != CFREE_CG_TYPE_RECORD) {
+ cfree_cg_deref(p->cg, 0);
+ cfree_cg_load(p->cg, toy_mem_access(p, g->type));
+ }
p->last_type = g->toy_type;
return g->type;
}
@@ -494,7 +506,7 @@ static void toy_store_tos_to_local(ToyParser* p, CfreeCgLocal local,
CfreeCgTypeId ty) {
cfree_cg_push_local(p->cg, local);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, ty));
}
/* Consumes [slice_base, idx] where slice_base is a pointer to the slice
@@ -518,10 +530,10 @@ CfreeCgTypeId toy_emit_slice_index_lvalue(ToyParser* p, CfreeCgTypeId slice_ty,
* and compute element pointer. */
idx_slot = cfree_cg_local(p->cg, p->int_type, toy_slot_attrs(0));
toy_store_tos_to_local(p, idx_slot, p->int_type);
- cfree_cg_load(p->cg, toy_mem_access(p, ptr_field.type),
- (CfreeCgEffAddr){(int64_t)ptr_field_off, 0});
+ cfree_cg_deref(p->cg, (int64_t)ptr_field_off);
+ cfree_cg_load(p->cg, toy_mem_access(p, ptr_field.type));
cfree_cg_push_local(p->cg, idx_slot);
- cfree_cg_load(p->cg, toy_mem_access(p, p->int_type), (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(p->cg, toy_mem_access(p, p->int_type));
toy_addr_index(p, cfree_cg_type_size(p->c, elem_ty),
cfree_cg_type_ptr(p->c, elem_ty, 0));
if (elem_toy_out) *elem_toy_out = elem_toy;
@@ -585,8 +597,8 @@ CfreeCgTypeId toy_emit_slice_value(ToyParser* p, CfreeCgTypeId base_ty,
/* TOS = [base] (slice lvalue/pointer or array lvalue/pointer). */
if (toy_type_is_slice(p, base_toy_type)) {
/* Replace slice base with its data pointer (a pointer-rvalue). */
- cfree_cg_load(p->cg, toy_mem_access(p, ptr_field.type),
- (CfreeCgEffAddr){(int64_t)ptr_off, 0});
+ cfree_cg_deref(p->cg, (int64_t)ptr_off);
+ cfree_cg_load(p->cg, toy_mem_access(p, ptr_field.type));
} else {
/* Array base: TOS is a pointer-rvalue (callers always project
* to a pointer for array/slice bases now). Bitcast to *elem. */
@@ -595,30 +607,32 @@ CfreeCgTypeId toy_emit_slice_value(ToyParser* p, CfreeCgTypeId base_ty,
/* Compute (base + start * sizeof(elem)) as a pointer to the slice's
* first element. */
cfree_cg_push_local(p->cg, start_slot);
- cfree_cg_load(p->cg, toy_mem_access(p, p->int_type),
- (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(p->cg, toy_mem_access(p, p->int_type));
toy_addr_index(p, cfree_cg_type_size(p->c, elem_ty),
cfree_cg_type_ptr(p->c, elem_ty, 0));
/* Store the data pointer into result_slot.ptr. */
cfree_cg_push_local(p->cg, result_slot);
+ cfree_cg_addr(p->cg);
+ cfree_cg_deref(p->cg, (int64_t)ptr_off);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, ptr_field.type),
- (CfreeCgEffAddr){(int64_t)ptr_off, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, ptr_field.type));
/* len = end - start; store into result_slot.len. */
cfree_cg_push_local(p->cg, result_slot);
+ cfree_cg_addr(p->cg);
+ cfree_cg_deref(p->cg, (int64_t)len_off);
cfree_cg_push_local(p->cg, end_slot);
- cfree_cg_load(p->cg, toy_mem_access(p, p->int_type),
- (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(p->cg, toy_mem_access(p, p->int_type));
cfree_cg_push_local(p->cg, start_slot);
- cfree_cg_load(p->cg, toy_mem_access(p, p->int_type),
- (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(p->cg, toy_mem_access(p, p->int_type));
cfree_cg_int_binop(p->cg, CFREE_CG_INT_SUB, 0);
- cfree_cg_store(p->cg, toy_mem_access(p, p->int_type),
- (CfreeCgEffAddr){(int64_t)len_off, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, p->int_type));
}
- cfree_cg_push_local(p->cg, result_slot);
+ /* Hand back the slice record as a pointer VALUE (its address), matching the
+ * "records/slices are pointer VALUEs" shape the downstream record-copy and
+ * slice-index paths consume. */
+ cfree_cg_push_local_addr(p->cg, result_slot);
if (slice_toy_out) *slice_toy_out = slice_toy;
p->last_type = slice_toy;
return slice_ty;
@@ -740,6 +754,10 @@ static CfreeCgTypeId toy_parse_expr_primary(ToyParser* p) {
attrs.inline_policy = fn->func_attrs.inline_policy;
cfree_cg_call_symbol(p->cg, toy_fn_cur_sym(p, fn), (uint32_t)nargs, attrs);
}
+ /* An aggregate return is a PLACE; project it to a pointer VALUE so it
+ * matches the records-are-pointers invariant used downstream. */
+ if (cfree_cg_type_kind(p->c, fn->ret) == CFREE_CG_TYPE_RECORD)
+ cfree_cg_addr(p->cg);
p->last_type = fn->toy_ret;
return fn->ret;
}
@@ -766,6 +784,9 @@ static CfreeCgTypeId toy_parse_expr_primary(ToyParser* p) {
&nargs))
return CFREE_CG_TYPE_NONE;
cfree_cg_call_default(p->cg, (uint32_t)nargs, fn_ty);
+ if (cfree_cg_type_kind(p->c, toy_cg_func_ret(p, fn_ty)) ==
+ CFREE_CG_TYPE_RECORD)
+ cfree_cg_addr(p->cg);
p->last_type =
source_fn_type
? source_fn_type->ret
@@ -850,8 +871,9 @@ static CfreeCgTypeId toy_parse_expr_postfix(ToyParser* p) {
}
ty = cfree_cg_type_ptr_pointee(p->c, ty);
toy_ty = toy_type_pointee(p, toy_ty);
- /* TOS is a pointer-rvalue; memop accepts it as base directly. */
- cfree_cg_load(p->cg, toy_mem_access(p, ty), (CfreeCgEffAddr){0, 0});
+ /* TOS is a pointer VALUE; deref it to a PLACE, then load. */
+ cfree_cg_deref(p->cg, 0);
+ cfree_cg_load(p->cg, toy_mem_access(p, ty));
p->last_type = toy_ty != TOY_TYPE_NONE ? toy_ty : toy_type_from_cg(p, ty);
continue;
}
@@ -899,12 +921,20 @@ static CfreeCgTypeId toy_parse_expr_postfix(ToyParser* p) {
toy_ty = source_pointee;
}
} else if (cfree_cg_type_kind(p->c, ty) == CFREE_CG_TYPE_ARRAY) {
- ty = cfree_cg_type_array_elem(p->c, ty);
+ /* TOS = [ptr-to-array, idx]. Decay the base to *elem so cfree_cg_elem
+ * scales by the element size, not the whole array. */
+ CfreeCgTypeId elem_ty = cfree_cg_type_array_elem(p->c, ty);
+ cfree_cg_swap(p->cg);
+ cfree_cg_bitcast(p->cg, cfree_cg_type_ptr(p->c, elem_ty, 0));
+ cfree_cg_swap(p->cg);
+ ty = elem_ty;
toy_ty = toy_type_array_elem(p, toy_ty);
} else if (toy_type_is_slice(p, toy_ty)) {
ty = toy_emit_slice_index_lvalue(p, ty, toy_ty, &toy_ty);
if (ty == CFREE_CG_TYPE_NONE) return CFREE_CG_TYPE_NONE;
- cfree_cg_load(p->cg, toy_mem_access(p, ty), (CfreeCgEffAddr){0, 0});
+ /* toy_emit_slice_index_lvalue returns an element pointer VALUE. */
+ cfree_cg_deref(p->cg, 0);
+ cfree_cg_load(p->cg, toy_mem_access(p, ty));
p->last_type =
toy_ty != TOY_TYPE_NONE ? toy_ty : toy_type_from_cg(p, ty);
continue;
@@ -912,10 +942,9 @@ static CfreeCgTypeId toy_parse_expr_postfix(ToyParser* p) {
toy_error(p, p->cur.loc, "cannot index non-array/non-pointer");
return CFREE_CG_TYPE_NONE;
}
- /* TOS = [base, idx]; load with element-size scale. */
- cfree_cg_load(
- p->cg, toy_mem_access(p, ty),
- (CfreeCgEffAddr){0, (uint32_t)cfree_cg_type_size(p->c, ty)});
+ /* TOS = [base, idx]; elem yields the element PLACE, then load. */
+ cfree_cg_elem(p->cg, 0);
+ cfree_cg_load(p->cg, toy_mem_access(p, ty));
p->last_type = toy_ty != TOY_TYPE_NONE ? toy_ty : toy_type_from_cg(p, ty);
continue;
}
@@ -955,8 +984,8 @@ static CfreeCgTypeId toy_parse_expr_postfix(ToyParser* p) {
if (named && field_index < named->nfields)
field_toy_type = named->fields[field_index].toy_type;
ty = found_field.type;
- cfree_cg_load(p->cg, toy_mem_access(p, ty),
- (CfreeCgEffAddr){(int64_t)found_off, 0});
+ cfree_cg_deref(p->cg, (int64_t)found_off);
+ cfree_cg_load(p->cg, toy_mem_access(p, ty));
if (field_toy_type != TOY_TYPE_NONE) {
CfreeCgTypeId resolved = toy_type_resolved_cg(p, field_toy_type);
p->last_type = field_toy_type;
@@ -1001,8 +1030,8 @@ static CfreeCgTypeId toy_parse_expr_postfix(ToyParser* p) {
return CFREE_CG_TYPE_NONE;
}
ty = found_field.type;
- cfree_cg_load(p->cg, toy_mem_access(p, ty),
- (CfreeCgEffAddr){(int64_t)found_off, 0});
+ cfree_cg_deref(p->cg, (int64_t)found_off);
+ cfree_cg_load(p->cg, toy_mem_access(p, ty));
if (field_toy_type != TOY_TYPE_NONE) {
CfreeCgTypeId resolved = toy_type_resolved_cg(p, field_toy_type);
p->last_type = field_toy_type;
@@ -1129,13 +1158,13 @@ static CfreeCgTypeId toy_parse_expr_unary(ToyParser* p) {
cfree_cg_local(p->cg, p->int_type, toy_slot_attrs(0));
cfree_cg_push_local(p->cg, idx_slot);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, p->int_type),
- (CfreeCgEffAddr){0, 0});
- cfree_cg_load(p->cg, toy_mem_access(p, ty),
- (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, p->int_type));
+ /* TOS is the chain pointer VALUE (**T); deref to a PLACE and
+ * load the inner pointer it addresses. */
+ cfree_cg_deref(p->cg, 0);
+ cfree_cg_load(p->cg, toy_mem_access(p, ty));
cfree_cg_push_local(p->cg, idx_slot);
- cfree_cg_load(p->cg, toy_mem_access(p, p->int_type),
- (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(p->cg, toy_mem_access(p, p->int_type));
}
if (cfree_cg_type_kind(p->c, pointee) == CFREE_CG_TYPE_ARRAY) {
CfreeCgTypeId elem_ty = cfree_cg_type_array_elem(p->c, pointee);
@@ -1171,8 +1200,9 @@ static CfreeCgTypeId toy_parse_expr_unary(ToyParser* p) {
toy_error(p, p->cur.loc, "cannot dereference non-pointer");
return CFREE_CG_TYPE_NONE;
}
- /* TOS = **T; load to TOS = *T. */
- cfree_cg_load(p->cg, toy_mem_access(p, ty), (CfreeCgEffAddr){0, 0});
+ /* TOS = **T (pointer VALUE); deref to PLACE and load to TOS = *T. */
+ cfree_cg_deref(p->cg, 0);
+ cfree_cg_load(p->cg, toy_mem_access(p, ty));
ty = cfree_cg_type_ptr_pointee(p->c, ty);
ty_toy = toy_type_pointee(p, ty_toy);
continue;
@@ -1185,8 +1215,9 @@ static CfreeCgTypeId toy_parse_expr_unary(ToyParser* p) {
if (cfree_cg_type_kind(p->c, ty) == CFREE_CG_TYPE_PTR &&
cfree_cg_type_kind(p->c, cfree_cg_type_ptr_pointee(p->c, ty)) ==
CFREE_CG_TYPE_RECORD) {
- /* TOS = **Rec; load to *Rec. */
- cfree_cg_load(p->cg, toy_mem_access(p, ty), (CfreeCgEffAddr){0, 0});
+ /* TOS = **Rec (pointer VALUE); deref to PLACE and load to *Rec. */
+ cfree_cg_deref(p->cg, 0);
+ cfree_cg_load(p->cg, toy_mem_access(p, ty));
ty = cfree_cg_type_ptr_pointee(p->c, ty);
ty_toy = toy_type_pointee(p, ty_toy);
}
@@ -1559,15 +1590,15 @@ static CfreeCgTypeId toy_parse_expr_and(ToyParser* p) {
cfree_cg_branch_false(p->cg, false_label);
cfree_cg_push_local(p->cg, result_slot);
cfree_cg_push_int(p->cg, 1, bool_ty);
- cfree_cg_store(p->cg, toy_mem_access(p, bool_ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, bool_ty));
cfree_cg_jump(p->cg, end_label);
cfree_cg_label_place(p->cg, false_label);
cfree_cg_push_local(p->cg, result_slot);
cfree_cg_push_int(p->cg, 0, bool_ty);
- cfree_cg_store(p->cg, toy_mem_access(p, bool_ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, bool_ty));
cfree_cg_label_place(p->cg, end_label);
cfree_cg_push_local(p->cg, result_slot);
- cfree_cg_load(p->cg, toy_mem_access(p, bool_ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(p->cg, toy_mem_access(p, bool_ty));
ty = bool_ty;
toy_note_cg_result_type(p, ty);
}
@@ -1598,15 +1629,15 @@ static CfreeCgTypeId toy_parse_expr_or(ToyParser* p) {
cfree_cg_branch_true(p->cg, true_label);
cfree_cg_push_local(p->cg, result_slot);
cfree_cg_push_int(p->cg, 0, bool_ty);
- cfree_cg_store(p->cg, toy_mem_access(p, bool_ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, bool_ty));
cfree_cg_jump(p->cg, end_label);
cfree_cg_label_place(p->cg, true_label);
cfree_cg_push_local(p->cg, result_slot);
cfree_cg_push_int(p->cg, 1, bool_ty);
- cfree_cg_store(p->cg, toy_mem_access(p, bool_ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, bool_ty));
cfree_cg_label_place(p->cg, end_label);
cfree_cg_push_local(p->cg, result_slot);
- cfree_cg_load(p->cg, toy_mem_access(p, bool_ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(p->cg, toy_mem_access(p, bool_ty));
ty = bool_ty;
toy_note_cg_result_type(p, ty);
}
diff --git a/lang/toy/parser.c b/lang/toy/parser.c
@@ -32,11 +32,15 @@ int toy_parse_block(ToyParser* p) {
return 1;
}
-/* Pushes [base, index] onto the value stack as the EA-shaped pair consumed
- * by an indexed memop. Callers supply the element size in the store's EA. */
+/* Pushes [base_ptr, index] for cfree_cg_elem: the array local is decayed to a
+ * pointer to its element type (its address, bitcast to *elem), then the index
+ * value is pushed on top. The following cfree_cg_elem(0) yields the element
+ * PLACE. */
static void toy_push_local_indexed(ToyParser* p, CfreeCgLocal slot,
- uint64_t index) {
+ CfreeCgTypeId elem_ty, uint64_t index) {
cfree_cg_push_local(p->cg, slot);
+ cfree_cg_addr(p->cg);
+ cfree_cg_bitcast(p->cg, cfree_cg_type_ptr(p->c, elem_ty, 0));
cfree_cg_push_int(p->cg, index, p->int_type);
}
@@ -99,12 +103,13 @@ static int toy_copy_record_lvalue_to_local(ToyParser* p, CfreeCgTypeId src_ty,
uint64_t offset = 0;
if (cfree_cg_type_record_field(p->c, dst_ty, i, &field, &offset)) return 0;
cfree_cg_dup(p->cg);
- cfree_cg_load(p->cg, toy_mem_access(p, field.type),
- (CfreeCgEffAddr){(int64_t)offset, 0});
+ cfree_cg_deref(p->cg, (int64_t)offset);
+ cfree_cg_load(p->cg, toy_mem_access(p, field.type));
cfree_cg_push_local(p->cg, dst_slot);
+ cfree_cg_addr(p->cg);
+ cfree_cg_deref(p->cg, (int64_t)offset);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, field.type),
- (CfreeCgEffAddr){(int64_t)offset, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, field.type));
}
cfree_cg_drop(p->cg);
return 1;
@@ -126,16 +131,16 @@ static int toy_copy_record_lvalue_to_var(ToyParser* p, CfreeCgTypeId src_ty,
uint64_t offset = 0;
if (cfree_cg_type_record_field(p->c, dst_ty, i, &field, &offset)) return 0;
cfree_cg_dup(p->cg);
- cfree_cg_load(p->cg, toy_mem_access(p, field.type),
- (CfreeCgEffAddr){(int64_t)offset, 0});
+ cfree_cg_deref(p->cg, (int64_t)offset);
+ cfree_cg_load(p->cg, toy_mem_access(p, field.type));
if (dst_var) {
toy_push_var_lvalue(p, dst_var);
} else {
cfree_cg_push_symbol_addr(p->cg, toy_global_cur_sym(p, dst_global), 0);
}
+ cfree_cg_deref(p->cg, (int64_t)offset);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, field.type),
- (CfreeCgEffAddr){(int64_t)offset, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, field.type));
}
cfree_cg_drop(p->cg);
return 1;
@@ -159,7 +164,8 @@ static int toy_parse_array_initializer(ToyParser* p, CfreeCgLocal slot,
toy_error(p, p->cur.loc, "too many array elements");
return 0;
}
- toy_push_local_indexed(p, slot, index);
+ toy_push_local_indexed(p, slot, elem_ty, index);
+ cfree_cg_elem(p->cg, 0);
expr_ty = toy_parse_expr(p);
if (expr_ty == CFREE_CG_TYPE_NONE) return 0;
if (!toy_check_source_value(p, elem_ty, elem_toy_type, expr_ty,
@@ -167,9 +173,7 @@ static int toy_parse_array_initializer(ToyParser* p, CfreeCgLocal slot,
return 0;
}
if (expr_ty != elem_ty) cfree_cg_bitcast(p->cg, elem_ty);
- cfree_cg_store(
- p->cg, toy_mem_access(p, elem_ty),
- (CfreeCgEffAddr){0, (uint32_t)cfree_cg_type_size(p->c, elem_ty)});
+ cfree_cg_store(p->cg, toy_mem_access(p, elem_ty));
index++;
if (!toy_parser_match(p, TOK_COMMA)) break;
}
@@ -178,11 +182,10 @@ static int toy_parse_array_initializer(ToyParser* p, CfreeCgLocal slot,
return 0;
}
while (index < count) {
- toy_push_local_indexed(p, slot, index);
+ toy_push_local_indexed(p, slot, elem_ty, index);
+ cfree_cg_elem(p->cg, 0);
cfree_cg_push_int(p->cg, 0, elem_ty);
- cfree_cg_store(
- p->cg, toy_mem_access(p, elem_ty),
- (CfreeCgEffAddr){0, (uint32_t)cfree_cg_type_size(p->c, elem_ty)});
+ cfree_cg_store(p->cg, toy_mem_access(p, elem_ty));
index++;
}
return 1;
@@ -207,9 +210,10 @@ static int toy_parse_record_initializer(ToyParser* p, CfreeCgLocal slot,
if (cfree_cg_type_record_field(p->c, record_ty, i, &field, &foff) != 0)
return 0;
cfree_cg_push_local(p->cg, slot);
+ cfree_cg_addr(p->cg);
+ cfree_cg_deref(p->cg, (int64_t)foff);
cfree_cg_push_int(p->cg, 0, field.type);
- cfree_cg_store(p->cg, toy_mem_access(p, field.type),
- (CfreeCgEffAddr){(int64_t)foff, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, field.type));
}
if (positional) {
@@ -226,6 +230,8 @@ static int toy_parse_record_initializer(ToyParser* p, CfreeCgLocal slot,
&foff) != 0)
return 0;
cfree_cg_push_local(p->cg, slot);
+ cfree_cg_addr(p->cg);
+ cfree_cg_deref(p->cg, (int64_t)foff);
expr_ty = toy_parse_expr(p);
if (expr_ty == CFREE_CG_TYPE_NONE) return 0;
{
@@ -239,8 +245,7 @@ static int toy_parse_record_initializer(ToyParser* p, CfreeCgLocal slot,
}
}
if (expr_ty != field.type) cfree_cg_bitcast(p->cg, field.type);
- cfree_cg_store(p->cg, toy_mem_access(p, field.type),
- (CfreeCgEffAddr){(int64_t)foff, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, field.type));
field_index++;
if (!toy_parser_match(p, TOK_COMMA)) break;
}
@@ -276,6 +281,8 @@ static int toy_parse_record_initializer(ToyParser* p, CfreeCgLocal slot,
0)
return 0;
cfree_cg_push_local(p->cg, slot);
+ cfree_cg_addr(p->cg);
+ cfree_cg_deref(p->cg, (int64_t)foff);
expr_ty = toy_parse_expr(p);
if (expr_ty == CFREE_CG_TYPE_NONE) return 0;
{
@@ -288,8 +295,7 @@ static int toy_parse_record_initializer(ToyParser* p, CfreeCgLocal slot,
}
}
if (expr_ty != field.type) cfree_cg_bitcast(p->cg, field.type);
- cfree_cg_store(p->cg, toy_mem_access(p, field.type),
- (CfreeCgEffAddr){(int64_t)foff, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, field.type));
if (!toy_parser_match(p, TOK_COMMA)) break;
}
if (!toy_parser_expect(p, TOK_RBRACE)) {
@@ -370,7 +376,7 @@ static int toy_parse_value_block_body_to_local(ToyParser* p, CfreeCgLocal slot,
if (arm_ty != result_ty) cfree_cg_bitcast(p->cg, result_ty);
cfree_cg_push_local(p->cg, slot);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, result_ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, result_ty));
if (!toy_parser_expect(p, TOK_RBRACE)) {
toy_error(p, p->cur.loc, "expected '}' after value block");
p->nvars = saved_nvars;
@@ -456,7 +462,7 @@ static int toy_parse_switch_initializer(ToyParser* p, CfreeCgLocal slot,
selector_slot = cfree_cg_local(p->cg, selector_ty, toy_slot_attrs(0));
cfree_cg_push_local(p->cg, selector_slot);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, selector_ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, selector_ty));
end_label = cfree_cg_label_new(p->cg);
dispatch_label = cfree_cg_label_new(p->cg);
/* Skip the arm bodies on entry; come back through the dispatch label. */
@@ -539,7 +545,7 @@ static int toy_parse_switch_initializer(ToyParser* p, CfreeCgLocal slot,
}
cfree_cg_label_place(p->cg, dispatch_label);
cfree_cg_push_local(p->cg, selector_slot);
- cfree_cg_load(p->cg, toy_mem_access(p, selector_ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(p->cg, toy_mem_access(p, selector_ty));
if (saw_default) {
sw.default_label = default_arm_label;
} else {
@@ -648,7 +654,7 @@ static int toy_parse_while_initializer_named(ToyParser* p, CfreeCgLocal slot,
p->nscopes--;
cfree_cg_push_local(p->cg, slot);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, result_ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, result_ty));
return 1;
}
@@ -836,7 +842,7 @@ static int toy_parse_let_stmt(ToyParser* p) {
if (!toy_add_local_typed(p, name, ty, toy_ty, slot, is_var)) return 0;
cfree_cg_push_local(p->cg, slot);
cfree_cg_push_int(p->cg, (uint64_t)value, ty);
- cfree_cg_store(p->cg, toy_mem_access(p, ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, ty));
if (!toy_parser_expect(p, TOK_SEMI)) {
toy_error(p, p->cur.loc, "expected ';' after let");
return 0;
@@ -954,7 +960,7 @@ static int toy_parse_let_stmt(ToyParser* p) {
} else {
cfree_cg_push_local(p->cg, slot);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, ty));
}
}
if (!toy_parser_expect(p, TOK_SEMI)) {
@@ -1059,7 +1065,7 @@ static int toy_parse_switch_stmt_named(ToyParser* p, CfreeSym label_name) {
selector_slot = cfree_cg_local(p->cg, selector_ty, toy_slot_attrs(0));
cfree_cg_push_local(p->cg, selector_slot);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, selector_ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, selector_ty));
end_label = cfree_cg_label_new(p->cg);
dispatch_label = cfree_cg_label_new(p->cg);
if (!toy_parser_reserve(p, (void**)&p->scopes, &p->cap_scopes,
@@ -1124,7 +1130,7 @@ static int toy_parse_switch_stmt_named(ToyParser* p, CfreeSym label_name) {
}
cfree_cg_label_place(p->cg, dispatch_label);
cfree_cg_push_local(p->cg, selector_slot);
- cfree_cg_load(p->cg, toy_mem_access(p, selector_ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(p->cg, toy_mem_access(p, selector_ty));
sw.selector_type = selector_ty;
sw.default_label =
default_arm_label != CFREE_CG_LABEL_NONE ? default_arm_label : end_label;
@@ -1427,8 +1433,7 @@ static int toy_parse_return_stmt(ToyParser* p) {
}
}
cfree_cg_push_local(p->cg, slot);
- cfree_cg_load(p->cg, toy_mem_access(p, p->cur_fn_ret),
- (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(p->cg, toy_mem_access(p, p->cur_fn_ret));
cfree_cg_ret(p->cg);
if (!toy_parser_expect(p, TOK_SEMI)) {
toy_error(p, p->cur.loc, "expected ';' after return");
@@ -1579,13 +1584,13 @@ static int toy_parse_stmt(ToyParser* p) {
cfree_cg_local(p->cg, p->int_type, toy_slot_attrs(0));
cfree_cg_push_local(p->cg, idx_slot);
cfree_cg_swap(p->cg);
- cfree_cg_store(p->cg, toy_mem_access(p, p->int_type),
- (CfreeCgEffAddr){0, 0});
- cfree_cg_load(p->cg, toy_mem_access(p, lhs_ty),
- (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, p->int_type));
+ /* TOS is the chain pointer VALUE (**T); deref to a PLACE and
+ * load the inner pointer it addresses. */
+ cfree_cg_deref(p->cg, 0);
+ cfree_cg_load(p->cg, toy_mem_access(p, lhs_ty));
cfree_cg_push_local(p->cg, idx_slot);
- cfree_cg_load(p->cg, toy_mem_access(p, p->int_type),
- (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(p->cg, toy_mem_access(p, p->int_type));
}
if (cfree_cg_type_kind(p->c, pointee) == CFREE_CG_TYPE_ARRAY) {
CfreeCgTypeId elem_ty = cfree_cg_type_array_elem(p->c, pointee);
@@ -1621,8 +1626,9 @@ static int toy_parse_stmt(ToyParser* p) {
toy_error(p, p->cur.loc, "cannot dereference non-pointer");
return 0;
}
- /* TOS = `**T`; load to TOS = `*T`. */
- cfree_cg_load(p->cg, toy_mem_access(p, lhs_ty), (CfreeCgEffAddr){0, 0});
+ /* TOS = `**T` (pointer VALUE); deref to PLACE and load to `*T`. */
+ cfree_cg_deref(p->cg, 0);
+ cfree_cg_load(p->cg, toy_mem_access(p, lhs_ty));
lhs_ty = cfree_cg_type_ptr_pointee(p->c, lhs_ty);
lhs_toy_type = toy_type_pointee(p, lhs_toy_type);
continue;
@@ -1635,9 +1641,10 @@ static int toy_parse_stmt(ToyParser* p) {
if (cfree_cg_type_kind(p->c, lhs_ty) == CFREE_CG_TYPE_PTR &&
cfree_cg_type_kind(p->c, cfree_cg_type_ptr_pointee(p->c, lhs_ty)) ==
CFREE_CG_TYPE_RECORD) {
- /* `p.field`: load the pointer value to address the record. */
- cfree_cg_load(p->cg, toy_mem_access(p, lhs_ty),
- (CfreeCgEffAddr){0, 0});
+ /* `p.field`: deref to PLACE and load the pointer value that
+ * addresses the record. */
+ cfree_cg_deref(p->cg, 0);
+ cfree_cg_load(p->cg, toy_mem_access(p, lhs_ty));
lhs_ty = cfree_cg_type_ptr_pointee(p->c, lhs_ty);
lhs_toy_type = toy_type_pointee(p, lhs_toy_type);
}
@@ -1700,6 +1707,9 @@ static int toy_parse_stmt(ToyParser* p) {
toy_error(p, p->cur.loc, "cannot assign to slice metadata");
return 0;
}
+ /* The address chain leaves a pointer VALUE (`*lhs_ty`) on the stack; turn
+ * it into a PLACE before pushing the rhs so store sees [place, value]. */
+ cfree_cg_deref(p->cg, 0);
{
CfreeCgTypeId expr_ty = toy_parse_expr(p);
ToyTypeId expr_toy_type = p->last_type;
@@ -1714,7 +1724,7 @@ static int toy_parse_stmt(ToyParser* p) {
toy_error(p, p->cur.loc, "type mismatch in assignment");
return 0;
}
- cfree_cg_store(p->cg, toy_mem_access(p, lhs_ty), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, lhs_ty));
}
if (!toy_parser_expect(p, TOK_SEMI)) {
toy_error(p, p->cur.loc, "expected ';' after assignment");
@@ -1751,10 +1761,10 @@ static int toy_parse_stmt(ToyParser* p) {
return 1;
}
toy_push_var_lvalue(p, v);
+ cfree_cg_deref(p->cg, 0); /* pointer VALUE -> PLACE for store */
cfree_cg_swap(p->cg);
if (expr_ty != v->type) cfree_cg_bitcast(p->cg, v->type);
- cfree_cg_store(p->cg, toy_mem_access(p, v->type),
- (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, v->type));
} else {
ToyGlobal* g = toy_find_global(p, name);
if (!g) {
@@ -1779,10 +1789,10 @@ static int toy_parse_stmt(ToyParser* p) {
return 1;
}
cfree_cg_push_symbol_addr(p->cg, toy_global_cur_sym(p, g), 0);
+ cfree_cg_deref(p->cg, 0); /* pointer VALUE -> PLACE for store */
cfree_cg_swap(p->cg);
if (expr_ty != g->type) cfree_cg_bitcast(p->cg, g->type);
- cfree_cg_store(p->cg, toy_mem_access(p, g->type),
- (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(p->cg, toy_mem_access(p, g->type));
}
}
if (!toy_parser_expect(p, TOK_SEMI)) {
diff --git a/lang/toy/symbols.c b/lang/toy/symbols.c
@@ -165,14 +165,18 @@ ToyScope* toy_find_innermost_loop_scope(ToyParser* p) {
return NULL;
}
-/* Pushes a base operand suitable for the canonical memops: for a frame-local
- * this is the lvalue; for a static-local this is the symbol address (the
- * memop accepts both shapes as `base`). */
+/* Pushes the variable's address as a pointer VALUE for the chained-memop
+ * paths: a frame-local yields `push_local_addr`, a static-local yields its
+ * symbol address. Callers turn the pointer into a PLACE with `cfree_cg_deref`
+ * (offset 0 for the whole object) before a load/store, and compose field /
+ * index selectors on the pointer with the address-chain helpers. This keeps a
+ * single uniform shape (pointer VALUE) regardless of storage class, matching
+ * the `push_symbol_addr` shape used for globals. */
void toy_push_var_lvalue(ToyParser* p, const ToyVar* v) {
if (v->is_static)
cfree_cg_push_symbol_addr(p->cg, v->static_sym, 0);
else
- cfree_cg_push_local(p->cg, v->local);
+ cfree_cg_push_local_addr(p->cg, v->local);
}
void toy_push_var_addr(ToyParser* p, const ToyVar* v) {
diff --git a/lang/wasm/cg.c b/lang/wasm/cg.c
@@ -35,15 +35,6 @@ static CfreeCgMemAccess wasm_cg_mem_type(CfreeCgTypeId ty) {
return mem;
}
-/* Convenience: zero effective-address (no offset, no index). Used for
- * load/store on a base TOS that already represents the exact address. */
-static CfreeCgEffAddr wasm_cg_ea0(void) {
- CfreeCgEffAddr ea;
- ea.offset = 0;
- ea.scale = 0;
- return ea;
-}
-
static void wasm_cg_push_zero(CfreeCompiler* c, CfreeCg* cg,
CfreeCgBuiltinTypes b, WasmValType vt) {
CfreeCgTypeId ty = wasm_cg_type(c, b, vt);
@@ -502,14 +493,16 @@ static void wasm_cg_build_runtime(CfreeCompiler* c, CfreeCgBuiltinTypes b,
* Stack: [] -> [void*]. Callers fold a struct offset into the memop's EA. */
static void wasm_cg_push_instance_ptr(CfreeCg* cg, const WasmCgRuntime* rt,
CfreeCgLocal instance_local) {
- CfreeCgEffAddr ea = {0, 0};
cfree_cg_push_local(cg, instance_local);
- cfree_cg_load(cg, wasm_cg_mem_type(rt->instance_ptr_ty), ea);
+ cfree_cg_load(cg, wasm_cg_mem_type(rt->instance_ptr_ty));
}
+/* Push the instance as a record PLACE (the pointee of the instance pointer).
+ * Stack: [] -> [place]. Callers project struct fields off it with field/elem. */
static void wasm_cg_push_instance_lvalue(CfreeCg* cg, const WasmCgRuntime* rt,
CfreeCgLocal instance_local) {
wasm_cg_push_instance_ptr(cg, rt, instance_local);
+ cfree_cg_deref(cg, 0);
}
/* Add a constant byte offset to the pointer rvalue on TOS, retyping to
@@ -532,11 +525,9 @@ static void wasm_cg_ptr_add_offset(CfreeCg* cg, CfreeCgBuiltinTypes b,
static void wasm_cg_push_memory_data_ptr(CfreeCg* cg, const WasmCgRuntime* rt,
CfreeCgLocal instance_local,
uint32_t memidx) {
- CfreeCgEffAddr ea;
- ea.offset = (int64_t)(rt->memory_offset[memidx] + rt->memory_data_offset);
- ea.scale = 0;
wasm_cg_push_instance_ptr(cg, rt, instance_local);
- cfree_cg_load(cg, wasm_cg_mem_type(rt->i8_ptr_ty), ea);
+ cfree_cg_deref(cg, (int64_t)(rt->memory_offset[memidx] + rt->memory_data_offset));
+ cfree_cg_load(cg, wasm_cg_mem_type(rt->i8_ptr_ty));
}
static void wasm_cg_push_memory_pages_lvalue(CfreeCg* cg,
@@ -552,12 +543,11 @@ static void wasm_cg_push_memory_pages_lvalue(CfreeCg* cg,
static void wasm_cg_push_import_func_ptr(CfreeCg* cg, const WasmCgRuntime* rt,
CfreeCgLocal instance_local,
uint32_t func_index) {
- CfreeCgEffAddr ea;
- ea.offset =
- (int64_t)(rt->func_import_offset[func_index] + rt->func_import_fn_offset);
- ea.scale = 0;
wasm_cg_push_instance_ptr(cg, rt, instance_local);
- cfree_cg_load(cg, wasm_cg_mem_type(rt->void_ptr_ty), ea);
+ cfree_cg_deref(
+ cg,
+ (int64_t)(rt->func_import_offset[func_index] + rt->func_import_fn_offset));
+ cfree_cg_load(cg, wasm_cg_mem_type(rt->void_ptr_ty));
}
/* Push a pointer rvalue to instance->globals[global_index]'s value cell,
@@ -572,12 +562,10 @@ static void wasm_cg_push_global_value_ptr(CfreeCompiler* c, CfreeCg* cg,
CfreeCgTypeId ptr_ty = cfree_cg_type_ptr(
c, wasm_cg_type(c, b, m->globals[global_index].type), 0);
if (m->globals[global_index].is_import) {
- CfreeCgEffAddr ea;
- ea.offset = (int64_t)(rt->global_offset[global_index] +
- rt->global_import_addr_offset);
- ea.scale = 0;
wasm_cg_push_instance_ptr(cg, rt, instance_local);
- cfree_cg_load(cg, wasm_cg_mem_type(rt->void_ptr_ty), ea);
+ cfree_cg_deref(cg, (int64_t)(rt->global_offset[global_index] +
+ rt->global_import_addr_offset));
+ cfree_cg_load(cg, wasm_cg_mem_type(rt->void_ptr_ty));
cfree_cg_dup(cg);
cfree_cg_push_null(cg, rt->void_ptr_ty);
cfree_cg_int_cmp(cg, CFREE_CG_INT_NE);
@@ -609,10 +597,10 @@ static void wasm_cg_push_table_entry_lvalue(CfreeCg* cg,
CfreeCgMemAccess index_mem) {
wasm_cg_push_table_lvalue(cg, rt, instance_local, table_index);
cfree_cg_field(cg, rt->table_entries_ptr_field);
- cfree_cg_load(cg, wasm_cg_mem_type(rt->table_entry_ptr_ty), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem_type(rt->table_entry_ptr_ty));
cfree_cg_push_local(cg, index_local);
- cfree_cg_load(cg, index_mem, wasm_cg_ea0());
- cfree_cg_index(cg, 0);
+ cfree_cg_load(cg, index_mem);
+ cfree_cg_elem(cg, 0);
}
/* Push a pointer rvalue to instance->tables[table_index].entries[index_local].
@@ -624,19 +612,17 @@ static void wasm_cg_push_table_entry_ptr(CfreeCg* cg, CfreeCgBuiltinTypes b,
uint32_t table_index,
CfreeCgLocal index_local,
CfreeCgMemAccess index_mem) {
- CfreeCgEffAddr ea;
- CfreeCgEffAddr ea_idx = {0, 0};
CfreeCgTypeId i64_ty = b.id[CFREE_CG_BUILTIN_I64];
/* Load entries pointer from instance->tables[i].entries. */
- ea.offset =
- (int64_t)(rt->table_offset[table_index] + rt->table_entries_ptr_offset);
- ea.scale = 0;
wasm_cg_push_instance_ptr(cg, rt, instance_local);
- cfree_cg_load(cg, wasm_cg_mem_type(rt->table_entry_ptr_ty), ea);
+ cfree_cg_deref(
+ cg,
+ (int64_t)(rt->table_offset[table_index] + rt->table_entries_ptr_offset));
+ cfree_cg_load(cg, wasm_cg_mem_type(rt->table_entry_ptr_ty));
/* Compute entries + index * sizeof(entry) into a pointer rvalue. */
cfree_cg_ptr_to_int(cg, i64_ty);
cfree_cg_push_local(cg, index_local);
- cfree_cg_load(cg, index_mem, ea_idx);
+ cfree_cg_load(cg, index_mem);
cfree_cg_zext(cg, i64_ty);
cfree_cg_push_int(cg, rt->table_entry_size, i64_ty);
cfree_cg_int_binop(cg, CFREE_CG_INT_MUL, 0);
@@ -675,7 +661,6 @@ static void wasm_cg_memory_check(CfreeCompiler* c, CfreeCg* cg,
uint32_t width = wasm_mem_width(in->kind);
uint64_t end = in->offset64 + width;
CfreeCgLabel ok = cfree_cg_label_new(cg);
- CfreeCgEffAddr pages_ea;
uint32_t max_pages = (uint32_t)(m->memories[in->memidx].has_max
? m->memories[in->memidx].max_pages
: m->memories[in->memidx].min_pages);
@@ -685,11 +670,10 @@ static void wasm_cg_memory_check(CfreeCompiler* c, CfreeCg* cg,
}
(void)c;
cfree_cg_dup(cg);
- pages_ea.offset =
- (int64_t)(rt->memory_offset[in->memidx] + rt->memory_pages_offset);
- pages_ea.scale = 0;
wasm_cg_push_instance_ptr(cg, rt, instance_local);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64), pages_ea);
+ cfree_cg_deref(
+ cg, (int64_t)(rt->memory_offset[in->memidx] + rt->memory_pages_offset));
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
cfree_cg_push_int(cg, 65536u, b.id[CFREE_CG_BUILTIN_I64]);
cfree_cg_int_binop(cg, CFREE_CG_INT_MUL, 0);
cfree_cg_push_int(cg, end, b.id[CFREE_CG_BUILTIN_I64]);
@@ -739,24 +723,24 @@ static void wasm_cg_rotate(CfreeCompiler* c, CfreeCg* cg, CfreeCgBuiltinTypes b,
lhs = cfree_cg_local(cg, ty, attrs);
cfree_cg_push_local(cg, rhs);
cfree_cg_swap(cg);
- cfree_cg_store(cg, mem, wasm_cg_ea0());
+ cfree_cg_store(cg, mem);
cfree_cg_push_local(cg, lhs);
cfree_cg_swap(cg);
- cfree_cg_store(cg, mem, wasm_cg_ea0());
+ cfree_cg_store(cg, mem);
cfree_cg_push_local(cg, lhs);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
+ cfree_cg_load(cg, mem);
cfree_cg_push_local(cg, rhs);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
+ cfree_cg_load(cg, mem);
cfree_cg_push_int(cg, mask, ty);
cfree_cg_int_binop(cg, CFREE_CG_INT_AND, 0);
cfree_cg_int_binop(cg, right ? CFREE_CG_INT_LSHR : CFREE_CG_INT_SHL, 0);
cfree_cg_push_local(cg, lhs);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
+ cfree_cg_load(cg, mem);
cfree_cg_push_int(cg, 0, ty);
cfree_cg_push_local(cg, rhs);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
+ cfree_cg_load(cg, mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_SUB, 0);
cfree_cg_push_int(cg, mask, ty);
cfree_cg_int_binop(cg, CFREE_CG_INT_AND, 0);
@@ -779,12 +763,12 @@ static void wasm_cg_checked_divrem(CfreeCompiler* c, CfreeCg* cg,
lhs = cfree_cg_local(cg, ty, attrs);
cfree_cg_push_local(cg, rhs);
cfree_cg_swap(cg);
- cfree_cg_store(cg, mem, wasm_cg_ea0());
+ cfree_cg_store(cg, mem);
cfree_cg_push_local(cg, lhs);
cfree_cg_swap(cg);
- cfree_cg_store(cg, mem, wasm_cg_ea0());
+ cfree_cg_store(cg, mem);
cfree_cg_push_local(cg, rhs);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
+ cfree_cg_load(cg, mem);
cfree_cg_push_int(cg, 0, ty);
cfree_cg_int_cmp(cg, CFREE_CG_INT_NE);
cfree_cg_branch_true(cg, ok);
@@ -795,12 +779,12 @@ static void wasm_cg_checked_divrem(CfreeCompiler* c, CfreeCg* cg,
uint64_t min_val = vt == WASM_VAL_I32 ? UINT64_C(0x80000000)
: UINT64_C(0x8000000000000000);
cfree_cg_push_local(cg, lhs);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
+ cfree_cg_load(cg, mem);
cfree_cg_push_int(cg, min_val, ty);
cfree_cg_int_cmp(cg, CFREE_CG_INT_NE);
cfree_cg_branch_true(cg, no_overflow);
cfree_cg_push_local(cg, rhs);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
+ cfree_cg_load(cg, mem);
cfree_cg_push_int(cg, UINT64_MAX, ty);
cfree_cg_int_cmp(cg, CFREE_CG_INT_NE);
cfree_cg_branch_true(cg, no_overflow);
@@ -808,9 +792,9 @@ static void wasm_cg_checked_divrem(CfreeCompiler* c, CfreeCg* cg,
cfree_cg_label_place(cg, no_overflow);
}
cfree_cg_push_local(cg, lhs);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
+ cfree_cg_load(cg, mem);
cfree_cg_push_local(cg, rhs);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
+ cfree_cg_load(cg, mem);
cfree_cg_int_binop(cg, op, 0);
}
@@ -840,25 +824,25 @@ static void wasm_cg_checked_trunc(CfreeCompiler* c, CfreeCg* cg,
abs_bits = cfree_cg_local(cg, bit_ty, attrs);
cfree_cg_push_local(cg, value);
cfree_cg_swap(cg);
- cfree_cg_store(cg, src_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, src_mem);
cfree_cg_push_local(cg, bits);
cfree_cg_push_local(cg, value);
- cfree_cg_load(cg, src_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, src_mem);
cfree_cg_bitcast(cg, bit_ty);
- cfree_cg_store(cg, bit_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, bit_mem);
cfree_cg_push_local(cg, abs_bits);
cfree_cg_push_local(cg, bits);
- cfree_cg_load(cg, bit_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, bit_mem);
cfree_cg_push_int(cg, abs_mask, bit_ty);
cfree_cg_int_binop(cg, CFREE_CG_INT_AND, 0);
- cfree_cg_store(cg, bit_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, bit_mem);
{
CfreeCgLabel finite = cfree_cg_label_new(cg);
cfree_cg_push_local(cg, abs_bits);
- cfree_cg_load(cg, bit_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, bit_mem);
cfree_cg_push_int(cg, inf_bits, bit_ty);
cfree_cg_int_cmp(cg, CFREE_CG_INT_LE_U);
cfree_cg_branch_true(cg, finite);
@@ -883,12 +867,12 @@ static void wasm_cg_checked_trunc(CfreeCompiler* c, CfreeCg* cg,
if (is_unsigned) {
CfreeCgLabel nonnegative = cfree_cg_label_new(cg);
cfree_cg_push_local(cg, abs_bits);
- cfree_cg_load(cg, bit_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, bit_mem);
cfree_cg_push_int(cg, 0, bit_ty);
cfree_cg_int_cmp(cg, CFREE_CG_INT_EQ);
cfree_cg_branch_true(cg, nonnegative);
cfree_cg_push_local(cg, bits);
- cfree_cg_load(cg, bit_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, bit_mem);
cfree_cg_push_int(cg, sign_mask, bit_ty);
cfree_cg_int_cmp(cg, CFREE_CG_INT_LT_U);
cfree_cg_branch_true(cg, nonnegative);
@@ -898,7 +882,7 @@ static void wasm_cg_checked_trunc(CfreeCompiler* c, CfreeCg* cg,
{
CfreeCgLabel in_range = cfree_cg_label_new(cg);
cfree_cg_push_local(cg, abs_bits);
- cfree_cg_load(cg, bit_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, bit_mem);
cfree_cg_push_int(cg, limit_bits, bit_ty);
cfree_cg_int_cmp(cg, CFREE_CG_INT_LT_U);
cfree_cg_branch_true(cg, in_range);
@@ -909,19 +893,19 @@ static void wasm_cg_checked_trunc(CfreeCompiler* c, CfreeCg* cg,
CfreeCgLabel negative = cfree_cg_label_new(cg);
CfreeCgLabel in_range = cfree_cg_label_new(cg);
cfree_cg_push_local(cg, bits);
- cfree_cg_load(cg, bit_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, bit_mem);
cfree_cg_push_int(cg, sign_mask, bit_ty);
cfree_cg_int_cmp(cg, CFREE_CG_INT_GE_U);
cfree_cg_branch_true(cg, negative);
cfree_cg_push_local(cg, abs_bits);
- cfree_cg_load(cg, bit_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, bit_mem);
cfree_cg_push_int(cg, limit_bits, bit_ty);
cfree_cg_int_cmp(cg, CFREE_CG_INT_LT_U);
cfree_cg_branch_true(cg, in_range);
wasm_cg_trap_invalid_conversion(cg, rt);
cfree_cg_label_place(cg, negative);
cfree_cg_push_local(cg, abs_bits);
- cfree_cg_load(cg, bit_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, bit_mem);
cfree_cg_push_int(cg, limit_bits, bit_ty);
cfree_cg_int_cmp(cg, CFREE_CG_INT_LE_U);
cfree_cg_branch_true(cg, in_range);
@@ -930,7 +914,7 @@ static void wasm_cg_checked_trunc(CfreeCompiler* c, CfreeCg* cg,
}
cfree_cg_push_local(cg, value);
- cfree_cg_load(cg, src_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, src_mem);
if (is_unsigned)
cfree_cg_float_to_uint(cg, dst_ty, CFREE_CG_ROUND_TOWARD_ZERO);
else
@@ -1010,30 +994,30 @@ static void wasm_cg_call_func(CfreeCompiler* c, CfreeCg* cg,
cfree_cg_local(cg, wasm_cg_type(c, b, f->params[param]), attrs);
cfree_cg_push_local(cg, args[param]);
cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, f->params[param]), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, f->params[param]));
}
if (f->is_import) {
CfreeCgLabel ok = cfree_cg_label_new(cg);
callee = cfree_cg_local(cg, rt->void_ptr_ty, attrs);
cfree_cg_push_local(cg, callee);
wasm_cg_push_import_func_ptr(cg, rt, instance_local, func_index);
- cfree_cg_store(cg, wasm_cg_mem_type(rt->void_ptr_ty), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem_type(rt->void_ptr_ty));
cfree_cg_push_local(cg, callee);
- cfree_cg_load(cg, wasm_cg_mem_type(rt->void_ptr_ty), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem_type(rt->void_ptr_ty));
cfree_cg_push_null(cg, rt->void_ptr_ty);
cfree_cg_int_cmp(cg, CFREE_CG_INT_NE);
cfree_cg_branch_true(cg, ok);
wasm_cg_trap_table(cg, rt);
cfree_cg_label_place(cg, ok);
cfree_cg_push_local(cg, callee);
- cfree_cg_load(cg, wasm_cg_mem_type(rt->void_ptr_ty), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem_type(rt->void_ptr_ty));
cfree_cg_bitcast(cg, cfree_cg_type_ptr(c, func_type, 0));
}
cfree_cg_push_local(cg, instance_local);
- cfree_cg_load(cg, wasm_cg_mem_type(rt->instance_ptr_ty), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem_type(rt->instance_ptr_ty));
for (uint32_t p = 0; p < f->nparams; ++p) {
cfree_cg_push_local(cg, args[p]);
- cfree_cg_load(cg, wasm_cg_mem(c, b, f->params[p]), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem(c, b, f->params[p]));
}
if (f->is_import)
cfree_cg_call(
@@ -1276,20 +1260,20 @@ static void wasm_cg_bulk_bounds_check(CfreeCg* cg, CfreeCgBuiltinTypes b,
* overflow. First check size >= addr. */
CfreeCgLabel addr_ok = cfree_cg_label_new(cg);
cfree_cg_push_local(cg, size_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, addr_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_cmp(cg, CFREE_CG_INT_GE_U);
cfree_cg_branch_true(cg, addr_ok);
wasm_cg_trap_bounds(cg, rt);
cfree_cg_label_place(cg, addr_ok);
cfree_cg_push_local(cg, size_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, addr_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_SUB, 0);
cfree_cg_push_local(cg, n_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_cmp(cg, CFREE_CG_INT_GE_U);
cfree_cg_branch_true(cg, ok);
wasm_cg_trap_bounds(cg, rt);
@@ -1324,7 +1308,7 @@ static void wasm_cg_emit_byte_copy_loop(CfreeCg* cg, CfreeCgBuiltinTypes b,
(void)ptr_mem;
/* If n == 0, nothing to do. */
cfree_cg_push_local(cg, n_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_int(cg, 0, b.id[CFREE_CG_BUILTIN_I64]);
cfree_cg_int_cmp(cg, CFREE_CG_INT_EQ);
cfree_cg_branch_true(cg, done);
@@ -1335,101 +1319,99 @@ static void wasm_cg_emit_byte_copy_loop(CfreeCg* cg, CfreeCgBuiltinTypes b,
* ? backward : forward. */
cfree_cg_push_local(cg, dir);
cfree_cg_push_local(cg, dst_base_local);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
cfree_cg_push_local(cg, src_base_local);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
cfree_cg_int_cmp(cg, CFREE_CG_INT_EQ);
- cfree_cg_store(cg, wasm_cg_mem_type(b.id[CFREE_CG_BUILTIN_I32]),
- wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem_type(b.id[CFREE_CG_BUILTIN_I32]));
cfree_cg_push_local(cg, dir);
- cfree_cg_load(cg, wasm_cg_mem_type(b.id[CFREE_CG_BUILTIN_I32]),
- wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem_type(b.id[CFREE_CG_BUILTIN_I32]));
cfree_cg_branch_false(cg, forward);
cfree_cg_push_local(cg, dst_addr_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, src_addr_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_cmp(cg, CFREE_CG_INT_GT_U);
cfree_cg_branch_false(cg, forward);
/* Backward loop: idx = n - 1, while idx >= 0 then idx-- (stop at 0). */
cfree_cg_push_local(cg, idx);
cfree_cg_push_local(cg, n_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
+ cfree_cg_store(cg, i64_mem);
{
CfreeCgLabel back_loop = cfree_cg_label_new(cg);
cfree_cg_label_place(cg, back_loop);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_int(cg, 0, b.id[CFREE_CG_BUILTIN_I64]);
cfree_cg_int_cmp(cg, CFREE_CG_INT_EQ);
cfree_cg_branch_true(cg, done);
/* idx-- */
cfree_cg_push_local(cg, idx);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_int(cg, 1, b.id[CFREE_CG_BUILTIN_I64]);
cfree_cg_int_binop(cg, CFREE_CG_INT_SUB, 0);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
/* dst_base[dst_addr + idx] = src_base[src_addr + idx] */
cfree_cg_push_local(cg, dst_base_local);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
cfree_cg_push_local(cg, dst_addr_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_index(cg, 0);
+ cfree_cg_elem(cg, 0);
cfree_cg_push_local(cg, src_base_local);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
cfree_cg_push_local(cg, src_addr_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_index(cg, 0);
- cfree_cg_load(cg, i8_mem, wasm_cg_ea0());
- cfree_cg_store(cg, i8_mem, wasm_cg_ea0());
+ cfree_cg_elem(cg, 0);
+ cfree_cg_load(cg, i8_mem);
+ cfree_cg_store(cg, i8_mem);
cfree_cg_jump(cg, back_loop);
}
cfree_cg_label_place(cg, forward);
/* Forward loop: idx = 0; while idx < n then dst[idx]=src[idx]; idx++. */
cfree_cg_push_local(cg, idx);
cfree_cg_push_int(cg, 0, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_jump(cg, after_dir);
cfree_cg_label_place(cg, after_dir);
cfree_cg_label_place(cg, loop_start);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, n_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_cmp(cg, CFREE_CG_INT_GE_U);
cfree_cg_branch_true(cg, done);
cfree_cg_push_local(cg, dst_base_local);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
cfree_cg_push_local(cg, dst_addr_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_index(cg, 0);
+ cfree_cg_elem(cg, 0);
cfree_cg_push_local(cg, src_base_local);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
cfree_cg_push_local(cg, src_addr_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_index(cg, 0);
- cfree_cg_load(cg, i8_mem, wasm_cg_ea0());
- cfree_cg_store(cg, i8_mem, wasm_cg_ea0());
+ cfree_cg_elem(cg, 0);
+ cfree_cg_load(cg, i8_mem);
+ cfree_cg_store(cg, i8_mem);
cfree_cg_push_local(cg, idx);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_int(cg, 1, b.id[CFREE_CG_BUILTIN_I64]);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_jump(cg, loop_start);
cfree_cg_label_place(cg, done);
}
@@ -1455,32 +1437,32 @@ static void wasm_cg_emit_byte_fill_loop(CfreeCg* cg, CfreeCgBuiltinTypes b,
idx = cfree_cg_local(cg, b.id[CFREE_CG_BUILTIN_I64], attrs);
cfree_cg_push_local(cg, idx);
cfree_cg_push_int(cg, 0, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_label_place(cg, loop_start);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, n_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_cmp(cg, CFREE_CG_INT_GE_U);
cfree_cg_branch_true(cg, done);
cfree_cg_push_local(cg, dst_base_local);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
cfree_cg_push_local(cg, dst_addr_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_index(cg, 0);
+ cfree_cg_elem(cg, 0);
cfree_cg_push_local(cg, val_local);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_trunc(cg, b.id[CFREE_CG_BUILTIN_I8]);
- cfree_cg_store(cg, i8_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i8_mem);
cfree_cg_push_local(cg, idx);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_int(cg, 1, b.id[CFREE_CG_BUILTIN_I64]);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_jump(cg, loop_start);
cfree_cg_label_place(cg, done);
}
@@ -1506,145 +1488,145 @@ static void wasm_cg_emit_table_copy_loop(
idx = cfree_cg_local(cg, b.id[CFREE_CG_BUILTIN_I64], attrs);
dir = cfree_cg_local(cg, b.id[CFREE_CG_BUILTIN_I32], attrs);
cfree_cg_push_local(cg, n_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_int(cg, 0, b.id[CFREE_CG_BUILTIN_I64]);
cfree_cg_int_cmp(cg, CFREE_CG_INT_EQ);
cfree_cg_branch_true(cg, done);
/* dir = (dst_base == src_base) ? (dst_idx > src_idx) : 0 */
cfree_cg_push_local(cg, dir);
cfree_cg_push_local(cg, dst_base_local);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
cfree_cg_push_local(cg, src_base_local);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
cfree_cg_int_cmp(cg, CFREE_CG_INT_EQ);
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i32_mem);
cfree_cg_push_local(cg, dir);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_branch_false(cg, forward);
cfree_cg_push_local(cg, dst_idx_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, src_idx_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_cmp(cg, CFREE_CG_INT_GT_U);
cfree_cg_branch_false(cg, forward);
{
CfreeCgLabel back_loop = cfree_cg_label_new(cg);
cfree_cg_push_local(cg, idx);
cfree_cg_push_local(cg, n_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
+ cfree_cg_store(cg, i64_mem);
cfree_cg_label_place(cg, back_loop);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_int(cg, 0, b.id[CFREE_CG_BUILTIN_I64]);
cfree_cg_int_cmp(cg, CFREE_CG_INT_EQ);
cfree_cg_branch_true(cg, done);
cfree_cg_push_local(cg, idx);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_int(cg, 1, b.id[CFREE_CG_BUILTIN_I64]);
cfree_cg_int_binop(cg, CFREE_CG_INT_SUB, 0);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
/* copy fn and typeidx fields */
cfree_cg_push_local(cg, dst_base_local);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
cfree_cg_push_local(cg, dst_idx_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_index(cg, 0);
+ cfree_cg_elem(cg, 0);
cfree_cg_field(cg, rt->table_entry_fn_field);
cfree_cg_push_local(cg, src_base_local);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
cfree_cg_push_local(cg, src_idx_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_index(cg, 0);
+ cfree_cg_elem(cg, 0);
cfree_cg_field(cg, rt->table_entry_fn_field);
- cfree_cg_load(cg, fn_mem, wasm_cg_ea0());
- cfree_cg_store(cg, fn_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, fn_mem);
+ cfree_cg_store(cg, fn_mem);
cfree_cg_push_local(cg, dst_base_local);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
cfree_cg_push_local(cg, dst_idx_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_index(cg, 0);
+ cfree_cg_elem(cg, 0);
cfree_cg_field(cg, rt->table_entry_typeidx_field);
cfree_cg_push_local(cg, src_base_local);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
cfree_cg_push_local(cg, src_idx_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_index(cg, 0);
+ cfree_cg_elem(cg, 0);
cfree_cg_field(cg, rt->table_entry_typeidx_field);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
+ cfree_cg_store(cg, i32_mem);
cfree_cg_jump(cg, back_loop);
}
cfree_cg_label_place(cg, forward);
cfree_cg_push_local(cg, idx);
cfree_cg_push_int(cg, 0, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_label_place(cg, loop_start);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, n_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_cmp(cg, CFREE_CG_INT_GE_U);
cfree_cg_branch_true(cg, done);
cfree_cg_push_local(cg, dst_base_local);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
cfree_cg_push_local(cg, dst_idx_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_index(cg, 0);
+ cfree_cg_elem(cg, 0);
cfree_cg_field(cg, rt->table_entry_fn_field);
cfree_cg_push_local(cg, src_base_local);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
cfree_cg_push_local(cg, src_idx_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_index(cg, 0);
+ cfree_cg_elem(cg, 0);
cfree_cg_field(cg, rt->table_entry_fn_field);
- cfree_cg_load(cg, fn_mem, wasm_cg_ea0());
- cfree_cg_store(cg, fn_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, fn_mem);
+ cfree_cg_store(cg, fn_mem);
cfree_cg_push_local(cg, dst_base_local);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
cfree_cg_push_local(cg, dst_idx_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_index(cg, 0);
+ cfree_cg_elem(cg, 0);
cfree_cg_field(cg, rt->table_entry_typeidx_field);
cfree_cg_push_local(cg, src_base_local);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
cfree_cg_push_local(cg, src_idx_local);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_index(cg, 0);
+ cfree_cg_elem(cg, 0);
cfree_cg_field(cg, rt->table_entry_typeidx_field);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
+ cfree_cg_store(cg, i32_mem);
cfree_cg_push_local(cg, idx);
cfree_cg_push_local(cg, idx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_int(cg, 1, b.id[CFREE_CG_BUILTIN_I64]);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_jump(cg, loop_start);
cfree_cg_label_place(cg, done);
}
@@ -1786,20 +1768,21 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
const WasmMemory* mem = &m->memories[i];
uint64_t max_pages = mem->has_max ? mem->max_pages : mem->min_pages;
uint32_t flags = (mem->shared ? 1u : 0u) | (mem->is64 ? 2u : 0u);
- CfreeCgEffAddr ea;
- ea.scale = 0;
- ea.offset = (int64_t)(rt.memory_offset[i] + rt.memory_pages_offset);
wasm_cg_push_instance_ptr(cg, &rt, instance_local);
+ cfree_cg_deref(cg,
+ (int64_t)(rt.memory_offset[i] + rt.memory_pages_offset));
cfree_cg_push_int(cg, mem->min_pages, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64), ea);
- ea.offset = (int64_t)(rt.memory_offset[i] + rt.memory_max_pages_offset);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
wasm_cg_push_instance_ptr(cg, &rt, instance_local);
+ cfree_cg_deref(
+ cg, (int64_t)(rt.memory_offset[i] + rt.memory_max_pages_offset));
cfree_cg_push_int(cg, max_pages, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64), ea);
- ea.offset = (int64_t)(rt.memory_offset[i] + rt.memory_flags_offset);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
wasm_cg_push_instance_ptr(cg, &rt, instance_local);
+ cfree_cg_deref(cg,
+ (int64_t)(rt.memory_offset[i] + rt.memory_flags_offset));
cfree_cg_push_int(cg, flags, b.id[CFREE_CG_BUILTIN_I32]);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32), ea);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
/* For each active data segment targeting this memory, memcpy its
* bytes into the linear memory at the segment's offset. Passive
* segments are not initialized here — they're consumed by an
@@ -1838,53 +1821,51 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
} else {
cfree_cg_push_null(cg, rt.i8_ptr_ty);
}
- cfree_cg_store(cg, wasm_cg_mem_type(rt.i8_ptr_ty), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem_type(rt.i8_ptr_ty));
wasm_cg_push_passive_data_lvalue(cg, &rt, instance_local, di);
cfree_cg_field(cg, rt.passive_data_len_field);
cfree_cg_push_int(cg, (d->mode == WASM_SEG_PASSIVE) ? d->nbytes : 0u,
b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
}
for (i = 0; i < m->nfuncs; ++i) {
- CfreeCgEffAddr ea;
- ea.scale = 0;
- ea.offset =
- (int64_t)(rt.func_ref_entry_offset[i] + rt.table_entry_fn_offset);
wasm_cg_push_instance_ptr(cg, &rt, instance_local);
+ cfree_cg_deref(
+ cg,
+ (int64_t)(rt.func_ref_entry_offset[i] + rt.table_entry_fn_offset));
if (m->funcs[i].is_import) {
wasm_cg_push_import_func_ptr(cg, &rt, instance_local, i);
} else {
cfree_cg_push_symbol_addr(cg, syms[i], 0);
cfree_cg_bitcast(cg, rt.void_ptr_ty);
}
- cfree_cg_store(cg, wasm_cg_mem_type(rt.void_ptr_ty), ea);
- ea.offset = (int64_t)(rt.func_ref_entry_offset[i] +
- rt.table_entry_typeidx_offset);
+ cfree_cg_store(cg, wasm_cg_mem_type(rt.void_ptr_ty));
wasm_cg_push_instance_ptr(cg, &rt, instance_local);
+ cfree_cg_deref(cg, (int64_t)(rt.func_ref_entry_offset[i] +
+ rt.table_entry_typeidx_offset));
cfree_cg_push_int(cg, m->funcs[i].typeidx, b.id[CFREE_CG_BUILTIN_I32]);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32), ea);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
}
for (i = 0; i < m->ntables; ++i) {
const WasmTable* t = &m->tables[i];
uint32_t max = t->has_max ? t->max : t->min;
- CfreeCgEffAddr ea;
- ea.scale = 0;
/* tables[i].entries = &instance->table_entries_arr[i][0]. The address
* of the entries array is instance + table_entries_offset[i]. */
- ea.offset = (int64_t)(rt.table_offset[i] + rt.table_entries_ptr_offset);
wasm_cg_push_instance_ptr(cg, &rt, instance_local);
+ cfree_cg_deref(
+ cg, (int64_t)(rt.table_offset[i] + rt.table_entries_ptr_offset));
wasm_cg_push_instance_ptr(cg, &rt, instance_local);
wasm_cg_ptr_add_offset(cg, b, rt.table_entries_offset[i],
rt.table_entry_ptr_ty);
- cfree_cg_store(cg, wasm_cg_mem_type(rt.table_entry_ptr_ty), ea);
- ea.offset = (int64_t)(rt.table_offset[i] + rt.table_len_offset);
+ cfree_cg_store(cg, wasm_cg_mem_type(rt.table_entry_ptr_ty));
wasm_cg_push_instance_ptr(cg, &rt, instance_local);
+ cfree_cg_deref(cg, (int64_t)(rt.table_offset[i] + rt.table_len_offset));
cfree_cg_push_int(cg, t->min, b.id[CFREE_CG_BUILTIN_I32]);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32), ea);
- ea.offset = (int64_t)(rt.table_offset[i] + rt.table_max_offset);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
wasm_cg_push_instance_ptr(cg, &rt, instance_local);
+ cfree_cg_deref(cg, (int64_t)(rt.table_offset[i] + rt.table_max_offset));
cfree_cg_push_int(cg, max, b.id[CFREE_CG_BUILTIN_I32]);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32), ea);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
}
for (i = 0; i < m->nelems; ++i) {
const WasmElemSegment* seg = &m->elems[i];
@@ -1903,7 +1884,7 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
cfree_cg_push_int(cg, (uint32_t)(seg->offset + j),
b.id[CFREE_CG_BUILTIN_I32]);
}
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
/* Resolve the target table-entry lvalue: active segments write into
* the module's table; passive segments write into the per-segment
* inline storage array so the bytes survive instantiation for
@@ -1911,9 +1892,11 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
if (is_passive) {
wasm_cg_push_passive_elem_storage_array_lvalue(cg, &rt,
instance_local, i);
+ cfree_cg_addr(cg);
+ cfree_cg_bitcast(cg, rt.table_entry_ptr_ty);
cfree_cg_push_local(cg, slot_local);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32), wasm_cg_ea0());
- cfree_cg_index(cg, 0);
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ cfree_cg_elem(cg, 0);
} else {
wasm_cg_push_table_entry_lvalue(cg, &rt, instance_local,
seg->tableidx, slot_local,
@@ -1926,13 +1909,15 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
cfree_cg_push_symbol_addr(cg, syms[funcidx], 0);
cfree_cg_bitcast(cg, rt.void_ptr_ty);
}
- cfree_cg_store(cg, wasm_cg_mem_type(rt.void_ptr_ty), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem_type(rt.void_ptr_ty));
if (is_passive) {
wasm_cg_push_passive_elem_storage_array_lvalue(cg, &rt,
instance_local, i);
+ cfree_cg_addr(cg);
+ cfree_cg_bitcast(cg, rt.table_entry_ptr_ty);
cfree_cg_push_local(cg, slot_local);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32), wasm_cg_ea0());
- cfree_cg_index(cg, 0);
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ cfree_cg_elem(cg, 0);
} else {
wasm_cg_push_table_entry_lvalue(cg, &rt, instance_local,
seg->tableidx, slot_local,
@@ -1941,7 +1926,7 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
cfree_cg_field(cg, rt.table_entry_typeidx_field);
cfree_cg_push_int(cg, m->funcs[funcidx].typeidx,
b.id[CFREE_CG_BUILTIN_I32]);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
}
/* Initialize the passive_elem descriptor (entries pointer + length).
* Active segments get a zero-length descriptor so table.init on an
@@ -1951,33 +1936,32 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
if (is_passive && seg->nfuncs) {
wasm_cg_push_passive_elem_storage_array_lvalue(cg, &rt, instance_local,
i);
+ cfree_cg_addr(cg);
+ cfree_cg_bitcast(cg, rt.table_entry_ptr_ty);
cfree_cg_push_int(cg, 0, b.id[CFREE_CG_BUILTIN_I32]);
- cfree_cg_index(cg, 0);
+ cfree_cg_elem(cg, 0);
cfree_cg_addr(cg);
} else {
cfree_cg_push_null(cg, rt.table_entry_ptr_ty);
}
- cfree_cg_store(cg, wasm_cg_mem_type(rt.table_entry_ptr_ty),
- wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem_type(rt.table_entry_ptr_ty));
wasm_cg_push_passive_elem_lvalue(cg, &rt, instance_local, i);
cfree_cg_field(cg, rt.passive_elem_length_field);
cfree_cg_push_int(cg, is_passive ? seg->nfuncs : 0u,
b.id[CFREE_CG_BUILTIN_I32]);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
}
for (i = 0; i < m->nglobals; ++i) {
const WasmGlobal* g = &m->globals[i];
- CfreeCgEffAddr ea;
if (g->is_import) continue;
- ea.scale = 0;
- ea.offset = (int64_t)rt.global_offset[i];
wasm_cg_push_instance_ptr(cg, &rt, instance_local);
+ cfree_cg_deref(cg, (int64_t)rt.global_offset[i]);
if (g->type == WASM_VAL_F32 || g->type == WASM_VAL_F64)
cfree_cg_push_float(cg, g->init.fp, wasm_cg_type(c, b, g->type));
else
cfree_cg_push_int(cg, (uint64_t)g->init.imm,
wasm_cg_type(c, b, g->type));
- cfree_cg_store(cg, wasm_cg_mem(c, b, g->type), ea);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, g->type));
}
if (m->has_start)
wasm_cg_call_func(c, cg, b, &m->funcs[m->start_func], &rt,
@@ -2040,7 +2024,7 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
cfree_cg_local(cg, wasm_cg_type(c, b, f->locals[j]), attrs);
cfree_cg_push_local(cg, locals[f->nparams + j]);
wasm_cg_push_zero(c, cg, b, f->locals[j]);
- cfree_cg_store(cg, wasm_cg_mem(c, b, f->locals[j]), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, f->locals[j]));
}
for (j = 0; j < f->ninsns; ++j) {
WasmInsn in = f->insns[j];
@@ -2188,30 +2172,30 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
cfree_cg_push_local(cg, cond);
cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
cfree_cg_push_local(cg, rhs);
cfree_cg_swap(cg);
- cfree_cg_store(cg, mem, wasm_cg_ea0());
+ cfree_cg_store(cg, mem);
cfree_cg_push_local(cg, lhs);
cfree_cg_swap(cg);
- cfree_cg_store(cg, mem, wasm_cg_ea0());
+ cfree_cg_store(cg, mem);
cfree_cg_push_local(cg, cond);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
cfree_cg_branch_false(cg, else_label);
cfree_cg_push_local(cg, result);
cfree_cg_push_local(cg, lhs);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
- cfree_cg_store(cg, mem, wasm_cg_ea0());
+ cfree_cg_load(cg, mem);
+ cfree_cg_store(cg, mem);
cfree_cg_jump(cg, end_label);
cfree_cg_label_place(cg, else_label);
cfree_cg_push_local(cg, result);
cfree_cg_push_local(cg, rhs);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
- cfree_cg_store(cg, mem, wasm_cg_ea0());
+ cfree_cg_load(cg, mem);
+ cfree_cg_store(cg, mem);
cfree_cg_label_place(cg, end_label);
cfree_cg_push_local(cg, result);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
+ cfree_cg_load(cg, mem);
} break;
case WASM_INSN_I32_CONST:
cfree_cg_push_int(cg, (uint64_t)(uint32_t)in.imm,
@@ -2229,16 +2213,14 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
case WASM_INSN_LOCAL_GET: {
uint32_t index = (uint32_t)in.imm;
cfree_cg_push_local(cg, locals[index]);
- cfree_cg_load(cg, wasm_cg_mem(c, b, wasm_func_local_type(f, index)),
- wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem(c, b, wasm_func_local_type(f, index)));
break;
}
case WASM_INSN_LOCAL_SET: {
uint32_t index = (uint32_t)in.imm;
cfree_cg_push_local(cg, locals[index]);
cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, wasm_func_local_type(f, index)),
- wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, wasm_func_local_type(f, index)));
break;
}
case WASM_INSN_LOCAL_TEE: {
@@ -2246,8 +2228,7 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
cfree_cg_dup(cg);
cfree_cg_push_local(cg, locals[index]);
cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, wasm_func_local_type(f, index)),
- wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, wasm_func_local_type(f, index)));
break;
}
case WASM_INSN_CALL:
@@ -2294,27 +2275,24 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
cfree_cg_local(cg, wasm_cg_type(c, b, t->results[0]), attrs);
cfree_cg_push_local(cg, selector);
cfree_cg_swap(cg);
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i32_mem);
for (uint32_t p = 0; p < t->nparams; ++p) {
uint32_t param = t->nparams - 1u - p;
args[param] =
cfree_cg_local(cg, wasm_cg_type(c, b, t->params[param]), attrs);
cfree_cg_push_local(cg, args[param]);
cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, t->params[param]),
- wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, t->params[param]));
}
ok = cfree_cg_label_new(cg);
cfree_cg_push_local(cg, selector);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
{
- CfreeCgEffAddr ea_len;
- ea_len.scale = 0;
- ea_len.offset =
- (int64_t)(rt.table_offset[in.align] + rt.table_len_offset);
wasm_cg_push_instance_ptr(cg, &rt, instance_local);
- cfree_cg_load(cg, i32_mem, ea_len);
+ cfree_cg_deref(
+ cg, (int64_t)(rt.table_offset[in.align] + rt.table_len_offset));
+ cfree_cg_load(cg, i32_mem);
}
cfree_cg_int_cmp(cg, CFREE_CG_INT_LT_U);
cfree_cg_branch_true(cg, ok);
@@ -2326,14 +2304,12 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
wasm_cg_push_table_entry_ptr(cg, b, &rt, instance_local, in.align,
selector, i32_mem);
{
- CfreeCgEffAddr ea_fn;
- ea_fn.scale = 0;
- ea_fn.offset = (int64_t)rt.table_entry_fn_offset;
- cfree_cg_load(cg, wasm_cg_mem_type(rt.void_ptr_ty), ea_fn);
+ cfree_cg_deref(cg, (int64_t)rt.table_entry_fn_offset);
+ cfree_cg_load(cg, wasm_cg_mem_type(rt.void_ptr_ty));
}
- cfree_cg_store(cg, wasm_cg_mem_type(rt.void_ptr_ty), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem_type(rt.void_ptr_ty));
cfree_cg_push_local(cg, callee);
- cfree_cg_load(cg, wasm_cg_mem_type(rt.void_ptr_ty), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem_type(rt.void_ptr_ty));
cfree_cg_push_null(cg, rt.void_ptr_ty);
cfree_cg_int_cmp(cg, CFREE_CG_INT_NE);
cfree_cg_branch_true(cg, ok);
@@ -2344,10 +2320,8 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
wasm_cg_push_table_entry_ptr(cg, b, &rt, instance_local, in.align,
selector, i32_mem);
{
- CfreeCgEffAddr ea_ti;
- ea_ti.scale = 0;
- ea_ti.offset = (int64_t)rt.table_entry_typeidx_offset;
- cfree_cg_load(cg, i32_mem, ea_ti);
+ cfree_cg_deref(cg, (int64_t)rt.table_entry_typeidx_offset);
+ cfree_cg_load(cg, i32_mem);
}
cfree_cg_push_int(cg, (uint32_t)in.imm, b.id[CFREE_CG_BUILTIN_I32]);
cfree_cg_int_cmp(cg, CFREE_CG_INT_EQ);
@@ -2356,14 +2330,13 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
cfree_cg_label_place(cg, ok);
cfree_cg_push_local(cg, callee);
- cfree_cg_load(cg, wasm_cg_mem_type(rt.void_ptr_ty), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem_type(rt.void_ptr_ty));
cfree_cg_bitcast(cg, cfree_cg_type_ptr(c, indirect_func_type, 0));
cfree_cg_push_local(cg, instance_local);
- cfree_cg_load(cg, wasm_cg_mem_type(rt.instance_ptr_ty),
- wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem_type(rt.instance_ptr_ty));
for (uint32_t p = 0; p < t->nparams; ++p) {
cfree_cg_push_local(cg, args[p]);
- cfree_cg_load(cg, wasm_cg_mem(c, b, t->params[p]), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem(c, b, t->params[p]));
}
cfree_cg_call(cg, t->nparams + 1u, indirect_func_type,
(CfreeCgCallAttrs){
@@ -2376,9 +2349,9 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
} else if (t->nresults) {
cfree_cg_push_local(cg, result);
cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, t->results[0]), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, t->results[0]));
cfree_cg_push_local(cg, result);
- cfree_cg_load(cg, wasm_cg_mem(c, b, t->results[0]), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem(c, b, t->results[0]));
}
break;
}
@@ -2415,19 +2388,18 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
callee = cfree_cg_local(cg, rt.void_ptr_ty, attrs);
cfree_cg_push_local(cg, callee_ref);
cfree_cg_swap(cg);
- cfree_cg_store(cg, ref_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, ref_mem);
for (uint32_t p = 0; p < t->nparams; ++p) {
uint32_t param = t->nparams - 1u - p;
args[param] =
cfree_cg_local(cg, wasm_cg_type(c, b, t->params[param]), attrs);
cfree_cg_push_local(cg, args[param]);
cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, t->params[param]),
- wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, t->params[param]));
}
ok = cfree_cg_label_new(cg);
cfree_cg_push_local(cg, callee_ref);
- cfree_cg_load(cg, ref_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ref_mem);
cfree_cg_push_null(cg, rt.void_ptr_ty);
cfree_cg_int_cmp(cg, CFREE_CG_INT_NE);
cfree_cg_branch_true(cg, ok);
@@ -2436,13 +2408,11 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
ok = cfree_cg_label_new(cg);
cfree_cg_push_local(cg, callee_ref);
- cfree_cg_load(cg, ref_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ref_mem);
cfree_cg_bitcast(cg, rt.table_entry_ptr_ty);
{
- CfreeCgEffAddr ea_ti;
- ea_ti.scale = 0;
- ea_ti.offset = (int64_t)rt.table_entry_typeidx_offset;
- cfree_cg_load(cg, i32_mem, ea_ti);
+ cfree_cg_deref(cg, (int64_t)rt.table_entry_typeidx_offset);
+ cfree_cg_load(cg, i32_mem);
}
cfree_cg_push_int(cg, (uint32_t)in.imm, b.id[CFREE_CG_BUILTIN_I32]);
cfree_cg_int_cmp(cg, CFREE_CG_INT_EQ);
@@ -2452,15 +2422,13 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
cfree_cg_push_local(cg, callee);
cfree_cg_push_local(cg, callee_ref);
- cfree_cg_load(cg, ref_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ref_mem);
cfree_cg_bitcast(cg, rt.table_entry_ptr_ty);
{
- CfreeCgEffAddr ea_fn;
- ea_fn.scale = 0;
- ea_fn.offset = (int64_t)rt.table_entry_fn_offset;
- cfree_cg_load(cg, ref_mem, ea_fn);
+ cfree_cg_deref(cg, (int64_t)rt.table_entry_fn_offset);
+ cfree_cg_load(cg, ref_mem);
}
- cfree_cg_store(cg, ref_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, ref_mem);
ref_params[0].type = rt.instance_ptr_ty;
for (uint32_t p = 0; p < t->nparams; ++p)
@@ -2481,14 +2449,13 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
result =
cfree_cg_local(cg, wasm_cg_type(c, b, t->results[0]), attrs);
cfree_cg_push_local(cg, callee);
- cfree_cg_load(cg, ref_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ref_mem);
cfree_cg_bitcast(cg, cfree_cg_type_ptr(c, ref_func_type, 0));
cfree_cg_push_local(cg, instance_local);
- cfree_cg_load(cg, wasm_cg_mem_type(rt.instance_ptr_ty),
- wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem_type(rt.instance_ptr_ty));
for (uint32_t p = 0; p < t->nparams; ++p) {
cfree_cg_push_local(cg, args[p]);
- cfree_cg_load(cg, wasm_cg_mem(c, b, t->params[p]), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem(c, b, t->params[p]));
}
cfree_cg_call(
cg, t->nparams + 1u, ref_func_type,
@@ -2501,9 +2468,9 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
} else if (t->nresults) {
cfree_cg_push_local(cg, result);
cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, t->results[0]), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, t->results[0]));
cfree_cg_push_local(cg, result);
- cfree_cg_load(cg, wasm_cg_mem(c, b, t->results[0]), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem(c, b, t->results[0]));
}
break;
}
@@ -2511,17 +2478,17 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
uint32_t index = (uint32_t)in.imm;
wasm_cg_push_global_value_ptr(c, cg, b, &rt, instance_local, m,
index);
- cfree_cg_load(cg, wasm_cg_mem(c, b, m->globals[index].type),
- wasm_cg_ea0());
+ cfree_cg_deref(cg, 0);
+ cfree_cg_load(cg, wasm_cg_mem(c, b, m->globals[index].type));
break;
}
case WASM_INSN_GLOBAL_SET: {
uint32_t index = (uint32_t)in.imm;
wasm_cg_push_global_value_ptr(c, cg, b, &rt, instance_local, m,
index);
+ cfree_cg_deref(cg, 0);
cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, m->globals[index].type),
- wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, m->globals[index].type));
break;
}
case WASM_INSN_RETURN:
@@ -2531,12 +2498,11 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
cfree_cg_drop(cg);
break;
case WASM_INSN_MEMORY_SIZE: {
- CfreeCgEffAddr ea_pages;
- ea_pages.scale = 0;
- ea_pages.offset =
- (int64_t)(rt.memory_offset[in.memidx] + rt.memory_pages_offset);
wasm_cg_push_instance_ptr(cg, &rt, instance_local);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64), ea_pages);
+ cfree_cg_deref(
+ cg,
+ (int64_t)(rt.memory_offset[in.memidx] + rt.memory_pages_offset));
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
if (!m->memories[in.memidx].is64)
cfree_cg_trunc(cg, b.id[CFREE_CG_BUILTIN_I32]);
break;
@@ -2549,13 +2515,6 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
WasmValType page_vt =
m->memories[in.memidx].is64 ? WASM_VAL_I64 : WASM_VAL_I32;
CfreeCgTypeId page_ty = wasm_cg_type(c, b, page_vt);
- CfreeCgEffAddr ea_pages, ea_max;
- ea_pages.scale = 0;
- ea_pages.offset =
- (int64_t)(rt.memory_offset[in.memidx] + rt.memory_pages_offset);
- ea_max.scale = 0;
- ea_max.offset = (int64_t)(rt.memory_offset[in.memidx] +
- rt.memory_max_pages_offset);
memset(&attrs, 0, sizeof attrs);
attrs.flags = CFREE_CG_LOCAL_COMPILER_TEMP;
delta = cfree_cg_local(cg, page_ty, attrs);
@@ -2563,47 +2522,55 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
grow_result = cfree_cg_local(cg, page_ty, attrs);
cfree_cg_push_local(cg, delta);
cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, page_vt), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, page_vt));
cfree_cg_push_local(cg, old_pages);
wasm_cg_push_instance_ptr(cg, &rt, instance_local);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64), ea_pages);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64), wasm_cg_ea0());
+ cfree_cg_deref(
+ cg,
+ (int64_t)(rt.memory_offset[in.memidx] + rt.memory_pages_offset));
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
cfree_cg_push_local(cg, delta);
- cfree_cg_load(cg, wasm_cg_mem(c, b, page_vt), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem(c, b, page_vt));
if (!m->memories[in.memidx].is64)
cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
wasm_cg_push_instance_ptr(cg, &rt, instance_local);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64), ea_max);
+ cfree_cg_deref(cg, (int64_t)(rt.memory_offset[in.memidx] +
+ rt.memory_max_pages_offset));
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
cfree_cg_push_local(cg, old_pages);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
cfree_cg_int_binop(cg, CFREE_CG_INT_SUB, 0);
cfree_cg_int_cmp(cg, CFREE_CG_INT_LE_U);
cfree_cg_branch_false(cg, fail);
wasm_cg_push_instance_ptr(cg, &rt, instance_local);
+ cfree_cg_deref(
+ cg,
+ (int64_t)(rt.memory_offset[in.memidx] + rt.memory_pages_offset));
cfree_cg_push_local(cg, old_pages);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
cfree_cg_push_local(cg, delta);
- cfree_cg_load(cg, wasm_cg_mem(c, b, page_vt), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem(c, b, page_vt));
if (!m->memories[in.memidx].is64)
cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64), ea_pages);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
cfree_cg_push_local(cg, grow_result);
cfree_cg_push_local(cg, old_pages);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
if (!m->memories[in.memidx].is64)
cfree_cg_trunc(cg, b.id[CFREE_CG_BUILTIN_I32]);
- cfree_cg_store(cg, wasm_cg_mem(c, b, page_vt), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, page_vt));
cfree_cg_jump(cg, done);
cfree_cg_label_place(cg, fail);
cfree_cg_push_local(cg, grow_result);
cfree_cg_push_int(cg, UINT64_MAX, page_ty);
- cfree_cg_store(cg, wasm_cg_mem(c, b, page_vt), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, page_vt));
cfree_cg_label_place(cg, done);
cfree_cg_push_local(cg, grow_result);
- cfree_cg_load(cg, wasm_cg_mem(c, b, page_vt), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem(c, b, page_vt));
break;
}
case WASM_INSN_MEMORY_COPY: {
@@ -2631,34 +2598,34 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
cfree_cg_push_local(cg, n_l);
cfree_cg_swap(cg);
if (!dst_is64) cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_push_local(cg, src_addr_l);
cfree_cg_swap(cg);
if (!src_is64) cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_push_local(cg, dst_addr_l);
cfree_cg_swap(cg);
if (!dst_is64) cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
/* Cache base and size for src and dst memories. */
cfree_cg_push_local(cg, src_base_l);
wasm_cg_push_memory_data_ptr(cg, &rt, instance_local, src_memidx);
- cfree_cg_store(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, ptr_mem);
cfree_cg_push_local(cg, dst_base_l);
wasm_cg_push_memory_data_ptr(cg, &rt, instance_local, dst_memidx);
- cfree_cg_store(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, ptr_mem);
cfree_cg_push_local(cg, src_size_l);
wasm_cg_push_memory_pages_lvalue(cg, &rt, instance_local, src_memidx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_int(cg, 65536u, b.id[CFREE_CG_BUILTIN_I64]);
cfree_cg_int_binop(cg, CFREE_CG_INT_MUL, 0);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_push_local(cg, dst_size_l);
wasm_cg_push_memory_pages_lvalue(cg, &rt, instance_local, dst_memidx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_int(cg, 65536u, b.id[CFREE_CG_BUILTIN_I64]);
cfree_cg_int_binop(cg, CFREE_CG_INT_MUL, 0);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
wasm_cg_bulk_bounds_check(cg, b, &rt, src_addr_l, n_l, src_size_l);
wasm_cg_bulk_bounds_check(cg, b, &rt, dst_addr_l, n_l, dst_size_l);
wasm_cg_emit_byte_copy_loop(cg, b, &rt, dst_base_l, src_base_l,
@@ -2686,23 +2653,23 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
cfree_cg_push_local(cg, n_l);
cfree_cg_swap(cg);
if (!is64) cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_push_local(cg, val_l);
cfree_cg_swap(cg);
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i32_mem);
cfree_cg_push_local(cg, dst_addr_l);
cfree_cg_swap(cg);
if (!is64) cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_push_local(cg, dst_base_l);
wasm_cg_push_memory_data_ptr(cg, &rt, instance_local, memidx);
- cfree_cg_store(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, ptr_mem);
cfree_cg_push_local(cg, dst_size_l);
wasm_cg_push_memory_pages_lvalue(cg, &rt, instance_local, memidx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_int(cg, 65536u, b.id[CFREE_CG_BUILTIN_I64]);
cfree_cg_int_binop(cg, CFREE_CG_INT_MUL, 0);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
wasm_cg_bulk_bounds_check(cg, b, &rt, dst_addr_l, n_l, dst_size_l);
wasm_cg_emit_byte_fill_loop(cg, b, &rt, dst_base_l, dst_addr_l, val_l,
n_l);
@@ -2732,36 +2699,36 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
cfree_cg_push_local(cg, n_l);
cfree_cg_swap(cg);
cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_push_local(cg, src_addr_l);
cfree_cg_swap(cg);
cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_push_local(cg, dst_addr_l);
cfree_cg_swap(cg);
if (!is64) cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
/* src_base = inst->passive_data[dataidx].base */
cfree_cg_push_local(cg, src_base_l);
wasm_cg_push_passive_data_lvalue(cg, &rt, instance_local, dataidx);
cfree_cg_field(cg, rt.passive_data_base_field);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
- cfree_cg_store(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
+ cfree_cg_store(cg, ptr_mem);
/* src_size = inst->passive_data[dataidx].len */
cfree_cg_push_local(cg, src_size_l);
wasm_cg_push_passive_data_lvalue(cg, &rt, instance_local, dataidx);
cfree_cg_field(cg, rt.passive_data_len_field);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
+ cfree_cg_store(cg, i64_mem);
cfree_cg_push_local(cg, dst_base_l);
wasm_cg_push_memory_data_ptr(cg, &rt, instance_local, memidx);
- cfree_cg_store(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, ptr_mem);
cfree_cg_push_local(cg, dst_size_l);
wasm_cg_push_memory_pages_lvalue(cg, &rt, instance_local, memidx);
- cfree_cg_load(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i64_mem);
cfree_cg_push_int(cg, 65536u, b.id[CFREE_CG_BUILTIN_I64]);
cfree_cg_int_binop(cg, CFREE_CG_INT_MUL, 0);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
wasm_cg_bulk_bounds_check(cg, b, &rt, src_addr_l, n_l, src_size_l);
wasm_cg_bulk_bounds_check(cg, b, &rt, dst_addr_l, n_l, dst_size_l);
wasm_cg_emit_byte_copy_loop(cg, b, &rt, dst_base_l, src_base_l,
@@ -2773,7 +2740,7 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
wasm_cg_push_passive_data_lvalue(cg, &rt, instance_local, dataidx);
cfree_cg_field(cg, rt.passive_data_len_field);
cfree_cg_push_int(cg, 0, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
break;
}
case WASM_INSN_ELEM_DROP: {
@@ -2781,14 +2748,14 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
wasm_cg_push_passive_elem_lvalue(cg, &rt, instance_local, elemidx);
cfree_cg_field(cg, rt.passive_elem_length_field);
cfree_cg_push_int(cg, 0, b.id[CFREE_CG_BUILTIN_I32]);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
break;
}
case WASM_INSN_TABLE_SIZE: {
uint32_t tableidx = (uint32_t)in.imm;
wasm_cg_push_table_lvalue(cg, &rt, instance_local, tableidx);
cfree_cg_field(cg, rt.table_len_field);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
break;
}
case WASM_INSN_TABLE_GROW: {
@@ -2814,10 +2781,10 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
idx_l = cfree_cg_local(cg, b.id[CFREE_CG_BUILTIN_I32], attrs);
cfree_cg_push_local(cg, delta_l);
cfree_cg_swap(cg);
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i32_mem);
cfree_cg_push_local(cg, val_l);
cfree_cg_swap(cg);
- cfree_cg_store(cg, fn_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, fn_mem);
/* Cache *val (a CfreeWasmTableEntry) into fn/typeidx locals so the
* fill loop writes the correct pair into each new slot. */
CfreeCgLocal val_fn_l = cfree_cg_local(cg, rt.void_ptr_ty, attrs);
@@ -2825,63 +2792,65 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
cfree_cg_local(cg, b.id[CFREE_CG_BUILTIN_I32], attrs);
cfree_cg_push_local(cg, val_fn_l);
cfree_cg_push_local(cg, val_l);
- cfree_cg_load(cg, fn_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, fn_mem);
cfree_cg_bitcast(cg, cfree_cg_type_ptr(c, rt.table_entry_ty, 0));
+ cfree_cg_deref(cg, 0);
cfree_cg_field(cg, rt.table_entry_fn_field);
- cfree_cg_load(cg, fn_mem, wasm_cg_ea0());
- cfree_cg_store(cg, fn_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, fn_mem);
+ cfree_cg_store(cg, fn_mem);
cfree_cg_push_local(cg, val_typeidx_l);
cfree_cg_push_local(cg, val_l);
- cfree_cg_load(cg, fn_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, fn_mem);
cfree_cg_bitcast(cg, cfree_cg_type_ptr(c, rt.table_entry_ty, 0));
+ cfree_cg_deref(cg, 0);
cfree_cg_field(cg, rt.table_entry_typeidx_field);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
+ cfree_cg_store(cg, i32_mem);
cfree_cg_push_local(cg, old_len_l);
wasm_cg_push_table_lvalue(cg, &rt, instance_local, tableidx);
cfree_cg_field(cg, rt.table_len_field);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
+ cfree_cg_store(cg, i32_mem);
/* Check old_len + delta <= max. */
wasm_cg_push_table_lvalue(cg, &rt, instance_local, tableidx);
cfree_cg_field(cg, rt.table_max_field);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_push_local(cg, old_len_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_int_cmp(cg, CFREE_CG_INT_LT_U);
cfree_cg_branch_true(cg, fail);
/* max - old_len >= delta */
wasm_cg_push_table_lvalue(cg, &rt, instance_local, tableidx);
cfree_cg_field(cg, rt.table_max_field);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_push_local(cg, old_len_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_SUB, 0);
cfree_cg_push_local(cg, delta_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_int_cmp(cg, CFREE_CG_INT_LT_U);
cfree_cg_branch_true(cg, fail);
/* Update length first. */
wasm_cg_push_table_lvalue(cg, &rt, instance_local, tableidx);
cfree_cg_field(cg, rt.table_len_field);
cfree_cg_push_local(cg, old_len_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_push_local(cg, delta_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i32_mem);
/* Initialize new slots [old_len, old_len+delta) to val. */
cfree_cg_push_local(cg, idx_l);
cfree_cg_push_local(cg, old_len_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
+ cfree_cg_store(cg, i32_mem);
cfree_cg_label_place(cg, fill_loop);
cfree_cg_push_local(cg, idx_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_push_local(cg, old_len_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_push_local(cg, delta_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
cfree_cg_int_cmp(cg, CFREE_CG_INT_GE_U);
{
@@ -2891,36 +2860,36 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
idx_l, i32_mem);
cfree_cg_field(cg, rt.table_entry_fn_field);
cfree_cg_push_local(cg, val_fn_l);
- cfree_cg_load(cg, fn_mem, wasm_cg_ea0());
- cfree_cg_store(cg, fn_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, fn_mem);
+ cfree_cg_store(cg, fn_mem);
wasm_cg_push_table_entry_lvalue(cg, &rt, instance_local, tableidx,
idx_l, i32_mem);
cfree_cg_field(cg, rt.table_entry_typeidx_field);
cfree_cg_push_local(cg, val_typeidx_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
+ cfree_cg_store(cg, i32_mem);
cfree_cg_push_local(cg, idx_l);
cfree_cg_push_local(cg, idx_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_push_int(cg, 1, b.id[CFREE_CG_BUILTIN_I32]);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i32_mem);
cfree_cg_jump(cg, fill_loop);
cfree_cg_label_place(cg, fill_end);
}
cfree_cg_push_local(cg, result_l);
cfree_cg_push_local(cg, old_len_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
+ cfree_cg_store(cg, i32_mem);
cfree_cg_jump(cg, done);
cfree_cg_label_place(cg, fail);
cfree_cg_push_local(cg, result_l);
cfree_cg_push_int(cg, UINT32_C(0xffffffff),
b.id[CFREE_CG_BUILTIN_I32]);
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i32_mem);
cfree_cg_label_place(cg, done);
cfree_cg_push_local(cg, result_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
break;
}
case WASM_INSN_TABLE_FILL: {
@@ -2949,40 +2918,42 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
val_typeidx_l = cfree_cg_local(cg, b.id[CFREE_CG_BUILTIN_I32], attrs);
cfree_cg_push_local(cg, n_l);
cfree_cg_swap(cg);
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i32_mem);
cfree_cg_push_local(cg, val_l);
cfree_cg_swap(cg);
- cfree_cg_store(cg, fn_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, fn_mem);
cfree_cg_push_local(cg, dst_idx_l);
cfree_cg_swap(cg);
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i32_mem);
/* Cache *val into (val_fn, val_typeidx). val points at a
* CfreeWasmTableEntry which has fn (void*) at offset 0 and
* typeidx (i32) at offset sizeof(void*). */
cfree_cg_push_local(cg, val_fn_l);
cfree_cg_push_local(cg, val_l);
- cfree_cg_load(cg, fn_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, fn_mem);
cfree_cg_bitcast(cg, cfree_cg_type_ptr(c, rt.table_entry_ty, 0));
+ cfree_cg_deref(cg, 0);
cfree_cg_field(cg, rt.table_entry_fn_field);
- cfree_cg_load(cg, fn_mem, wasm_cg_ea0());
- cfree_cg_store(cg, fn_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, fn_mem);
+ cfree_cg_store(cg, fn_mem);
cfree_cg_push_local(cg, val_typeidx_l);
cfree_cg_push_local(cg, val_l);
- cfree_cg_load(cg, fn_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, fn_mem);
cfree_cg_bitcast(cg, cfree_cg_type_ptr(c, rt.table_entry_ty, 0));
+ cfree_cg_deref(cg, 0);
cfree_cg_field(cg, rt.table_entry_typeidx_field);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
+ cfree_cg_store(cg, i32_mem);
/* Bounds check: dst_idx + n <= len. */
cfree_cg_push_local(cg, len_l);
wasm_cg_push_table_lvalue(cg, &rt, instance_local, tableidx);
cfree_cg_field(cg, rt.table_len_field);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
+ cfree_cg_store(cg, i32_mem);
cfree_cg_push_local(cg, len_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_push_local(cg, dst_idx_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_int_cmp(cg, CFREE_CG_INT_GE_U);
cfree_cg_branch_true(cg, ok);
wasm_cg_trap_bounds(cg, &rt);
@@ -2990,12 +2961,12 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
{
CfreeCgLabel ok2 = cfree_cg_label_new(cg);
cfree_cg_push_local(cg, len_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_push_local(cg, dst_idx_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_SUB, 0);
cfree_cg_push_local(cg, n_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_int_cmp(cg, CFREE_CG_INT_GE_U);
cfree_cg_branch_true(cg, ok2);
wasm_cg_trap_bounds(cg, &rt);
@@ -3004,12 +2975,12 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
/* idx = 0; while idx < n: table[dst_idx+idx] = val; idx++ */
cfree_cg_push_local(cg, idx_l);
cfree_cg_push_int(cg, 0, b.id[CFREE_CG_BUILTIN_I32]);
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i32_mem);
cfree_cg_label_place(cg, loop);
cfree_cg_push_local(cg, idx_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_push_local(cg, n_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_int_cmp(cg, CFREE_CG_INT_GE_U);
cfree_cg_branch_true(cg, done);
{
@@ -3019,30 +2990,30 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
cfree_cg_local(cg, b.id[CFREE_CG_BUILTIN_I32], attrs);
cfree_cg_push_local(cg, slot_l);
cfree_cg_push_local(cg, dst_idx_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_push_local(cg, idx_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i32_mem);
wasm_cg_push_table_entry_lvalue(cg, &rt, instance_local, tableidx,
slot_l, i32_mem);
cfree_cg_field(cg, rt.table_entry_fn_field);
cfree_cg_push_local(cg, val_fn_l);
- cfree_cg_load(cg, fn_mem, wasm_cg_ea0());
- cfree_cg_store(cg, fn_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, fn_mem);
+ cfree_cg_store(cg, fn_mem);
wasm_cg_push_table_entry_lvalue(cg, &rt, instance_local, tableidx,
slot_l, i32_mem);
cfree_cg_field(cg, rt.table_entry_typeidx_field);
cfree_cg_push_local(cg, val_typeidx_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
+ cfree_cg_store(cg, i32_mem);
}
cfree_cg_push_local(cg, idx_l);
cfree_cg_push_local(cg, idx_l);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_push_int(cg, 1, b.id[CFREE_CG_BUILTIN_I32]);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i32_mem);
cfree_cg_jump(cg, loop);
cfree_cg_label_place(cg, done);
break;
@@ -3071,37 +3042,37 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
cfree_cg_push_local(cg, n_l);
cfree_cg_swap(cg);
cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_push_local(cg, src_idx_l);
cfree_cg_swap(cg);
cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_push_local(cg, dst_idx_l);
cfree_cg_swap(cg);
cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_push_local(cg, src_base_l);
wasm_cg_push_table_lvalue(cg, &rt, instance_local, src_tbl);
cfree_cg_field(cg, rt.table_entries_ptr_field);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
- cfree_cg_store(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
+ cfree_cg_store(cg, ptr_mem);
cfree_cg_push_local(cg, dst_base_l);
wasm_cg_push_table_lvalue(cg, &rt, instance_local, dst_tbl);
cfree_cg_field(cg, rt.table_entries_ptr_field);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
- cfree_cg_store(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
+ cfree_cg_store(cg, ptr_mem);
cfree_cg_push_local(cg, src_len_l);
wasm_cg_push_table_lvalue(cg, &rt, instance_local, src_tbl);
cfree_cg_field(cg, rt.table_len_field);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_push_local(cg, dst_len_l);
wasm_cg_push_table_lvalue(cg, &rt, instance_local, dst_tbl);
cfree_cg_field(cg, rt.table_len_field);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
wasm_cg_bulk_bounds_check(cg, b, &rt, src_idx_l, n_l, src_len_l);
wasm_cg_bulk_bounds_check(cg, b, &rt, dst_idx_l, n_l, dst_len_l);
wasm_cg_emit_table_copy_loop(c, cg, b, &rt, dst_base_l, src_base_l,
@@ -3132,37 +3103,37 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
cfree_cg_push_local(cg, n_l);
cfree_cg_swap(cg);
cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_push_local(cg, src_idx_l);
cfree_cg_swap(cg);
cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_push_local(cg, dst_idx_l);
cfree_cg_swap(cg);
cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_push_local(cg, src_base_l);
wasm_cg_push_passive_elem_lvalue(cg, &rt, instance_local, elemidx);
cfree_cg_field(cg, rt.passive_elem_entries_field);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
- cfree_cg_store(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
+ cfree_cg_store(cg, ptr_mem);
cfree_cg_push_local(cg, dst_base_l);
wasm_cg_push_table_lvalue(cg, &rt, instance_local, tableidx);
cfree_cg_field(cg, rt.table_entries_ptr_field);
- cfree_cg_load(cg, ptr_mem, wasm_cg_ea0());
- cfree_cg_store(cg, ptr_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, ptr_mem);
+ cfree_cg_store(cg, ptr_mem);
cfree_cg_push_local(cg, src_len_l);
wasm_cg_push_passive_elem_lvalue(cg, &rt, instance_local, elemidx);
cfree_cg_field(cg, rt.passive_elem_length_field);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
cfree_cg_push_local(cg, dst_len_l);
wasm_cg_push_table_lvalue(cg, &rt, instance_local, tableidx);
cfree_cg_field(cg, rt.table_len_field);
- cfree_cg_load(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_load(cg, i32_mem);
cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_store(cg, i64_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i64_mem);
wasm_cg_bulk_bounds_check(cg, b, &rt, src_idx_l, n_l, src_len_l);
wasm_cg_bulk_bounds_check(cg, b, &rt, dst_idx_l, n_l, dst_len_l);
wasm_cg_emit_table_copy_loop(c, cg, b, &rt, dst_base_l, src_base_l,
@@ -3227,12 +3198,12 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
value_tmp = cfree_cg_local(cg, ty, attrs);
cfree_cg_push_local(cg, value_tmp);
cfree_cg_swap(cg);
- cfree_cg_store(cg, mem, wasm_cg_ea0());
+ cfree_cg_store(cg, mem);
wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
wasm_cg_memory_addr_from_tos(cg, b, &rt, m, instance_local, in.memidx,
in.offset64);
cfree_cg_push_local(cg, value_tmp);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
+ cfree_cg_load(cg, mem);
cfree_cg_atomic_store(cg, mem, CFREE_CG_MO_SEQ_CST);
break;
}
@@ -3259,12 +3230,12 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
value_tmp = cfree_cg_local(cg, ty, attrs);
cfree_cg_push_local(cg, value_tmp);
cfree_cg_swap(cg);
- cfree_cg_store(cg, mem, wasm_cg_ea0());
+ cfree_cg_store(cg, mem);
wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
wasm_cg_memory_addr_from_tos(cg, b, &rt, m, instance_local, in.memidx,
in.offset64);
cfree_cg_push_local(cg, value_tmp);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
+ cfree_cg_load(cg, mem);
cfree_cg_atomic_rmw(cg, mem, wasm_atomic_rmw_op(in.kind),
CFREE_CG_MO_SEQ_CST);
break;
@@ -3283,17 +3254,17 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
expected_tmp = cfree_cg_local(cg, ty, attrs);
cfree_cg_push_local(cg, desired_tmp);
cfree_cg_swap(cg);
- cfree_cg_store(cg, mem, wasm_cg_ea0());
+ cfree_cg_store(cg, mem);
cfree_cg_push_local(cg, expected_tmp);
cfree_cg_swap(cg);
- cfree_cg_store(cg, mem, wasm_cg_ea0());
+ cfree_cg_store(cg, mem);
wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
wasm_cg_memory_addr_from_tos(cg, b, &rt, m, instance_local, in.memidx,
in.offset64);
cfree_cg_push_local(cg, expected_tmp);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
+ cfree_cg_load(cg, mem);
cfree_cg_push_local(cg, desired_tmp);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
+ cfree_cg_load(cg, mem);
cfree_cg_atomic_cmpxchg(cg, mem, CFREE_CG_MO_SEQ_CST,
CFREE_CG_MO_SEQ_CST, 0);
cfree_cg_drop(cg);
@@ -3316,30 +3287,30 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
result_tmp = cfree_cg_local(cg, b.id[CFREE_CG_BUILTIN_I32], attrs);
cfree_cg_push_local(cg, timeout_tmp);
cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
cfree_cg_push_local(cg, expected_tmp);
cfree_cg_swap(cg);
- cfree_cg_store(cg, mem, wasm_cg_ea0());
+ cfree_cg_store(cg, mem);
wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
wasm_cg_memory_addr_from_tos(cg, b, &rt, m, instance_local, in.memidx,
in.offset64);
cfree_cg_atomic_load(cg, mem, CFREE_CG_MO_SEQ_CST);
cfree_cg_push_local(cg, expected_tmp);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
+ cfree_cg_load(cg, mem);
cfree_cg_int_cmp(cg, CFREE_CG_INT_EQ);
cfree_cg_branch_true(cg, equal);
cfree_cg_push_local(cg, result_tmp);
cfree_cg_push_int(cg, 1, b.id[CFREE_CG_BUILTIN_I32]);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
cfree_cg_jump(cg, done);
cfree_cg_label_place(cg, equal);
(void)timeout_tmp;
cfree_cg_push_local(cg, result_tmp);
cfree_cg_push_int(cg, 2, b.id[CFREE_CG_BUILTIN_I32]);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
cfree_cg_label_place(cg, done);
cfree_cg_push_local(cg, result_tmp);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
break;
}
case WASM_INSN_MEMORY_ATOMIC_NOTIFY: {
@@ -3351,7 +3322,7 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
count_tmp = cfree_cg_local(cg, b.id[CFREE_CG_BUILTIN_I32], attrs);
cfree_cg_push_local(cg, count_tmp);
cfree_cg_swap(cg);
- cfree_cg_store(cg, i32_mem, wasm_cg_ea0());
+ cfree_cg_store(cg, i32_mem);
wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
cfree_cg_drop(cg);
cfree_cg_push_int(cg, 0, b.id[CFREE_CG_BUILTIN_I32]);
@@ -3381,7 +3352,8 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
wasm_cg_memory_addr_from_tos(cg, b, &rt, m, instance_local, in.memidx,
in.offset64);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
+ cfree_cg_deref(cg, 0);
+ cfree_cg_load(cg, mem);
if (storage != result) {
if (in.kind == WASM_INSN_I32_LOAD8_S ||
in.kind == WASM_INSN_I32_LOAD16_S ||
@@ -3421,18 +3393,19 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
addr_tmp = cfree_cg_local(cg, wasm_cg_type(c, b, addr_vt), attrs);
cfree_cg_push_local(cg, value_tmp);
cfree_cg_swap(cg);
- cfree_cg_store(cg, mem, wasm_cg_ea0());
+ cfree_cg_store(cg, mem);
wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
cfree_cg_push_local(cg, addr_tmp);
cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, addr_vt), wasm_cg_ea0());
+ cfree_cg_store(cg, wasm_cg_mem(c, b, addr_vt));
cfree_cg_push_local(cg, addr_tmp);
- cfree_cg_load(cg, wasm_cg_mem(c, b, addr_vt), wasm_cg_ea0());
+ cfree_cg_load(cg, wasm_cg_mem(c, b, addr_vt));
wasm_cg_memory_addr_from_tos(cg, b, &rt, m, instance_local, in.memidx,
in.offset64);
+ cfree_cg_deref(cg, 0);
cfree_cg_push_local(cg, value_tmp);
- cfree_cg_load(cg, mem, wasm_cg_ea0());
- cfree_cg_store(cg, mem, wasm_cg_ea0());
+ cfree_cg_load(cg, mem);
+ cfree_cg_store(cg, mem);
break;
}
case WASM_INSN_I32_ADD:
diff --git a/src/arch/rv64/emu.c b/src/arch/rv64/emu.c
@@ -153,7 +153,7 @@ static CfreeCgMemAccess rv64_emu_mem(CfreeCgTypeId type) {
static void rv64_emu_push_thread(CfreeCg* cg, CfreeCgLocal thread,
CfreeCgTypeId thread_ptr) {
cfree_cg_push_local(cg, thread);
- cfree_cg_load(cg, rv64_emu_mem(thread_ptr), (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(cg, rv64_emu_mem(thread_ptr));
}
static void rv64_emu_push_xreg(CfreeCg* cg, const Rv64EmuLiftSyms* s,
@@ -174,7 +174,7 @@ static void rv64_emu_store_xreg_from_tmp(CfreeCg* cg, const Rv64EmuLiftSyms* s,
rv64_emu_push_thread(cg, thread, s->thread_ptr);
cfree_cg_push_int(cg, reg, s->i32);
cfree_cg_push_local(cg, tmp);
- cfree_cg_load(cg, rv64_emu_mem(s->i64), (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(cg, rv64_emu_mem(s->i64));
cfree_cg_call_symbol(cg, s->set_xreg, 3, (CfreeCgCallAttrs){0});
}
@@ -184,7 +184,7 @@ static void rv64_emu_store_xreg_from_stack(CfreeCg* cg,
CfreeCgLocal tmp) {
cfree_cg_push_local(cg, tmp);
cfree_cg_swap(cg);
- cfree_cg_store(cg, rv64_emu_mem(s->i64), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(cg, rv64_emu_mem(s->i64));
if (reg == 0u) return;
rv64_emu_store_xreg_from_tmp(cg, s, thread, tmp, reg);
}
@@ -194,13 +194,13 @@ static void rv64_emu_store_local_from_stack(CfreeCg* cg,
CfreeCgLocal local) {
cfree_cg_push_local(cg, local);
cfree_cg_swap(cg);
- cfree_cg_store(cg, rv64_emu_mem(s->i64), (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(cg, rv64_emu_mem(s->i64));
}
static void rv64_emu_push_local_value(CfreeCg* cg, const Rv64EmuLiftSyms* s,
CfreeCgLocal local) {
cfree_cg_push_local(cg, local);
- cfree_cg_load(cg, rv64_emu_mem(s->i64), (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(cg, rv64_emu_mem(s->i64));
}
static void rv64_emu_push_addr(CfreeCg* cg, const Rv64EmuLiftSyms* s,
diff --git a/src/cg/control.c b/src/cg/control.c
@@ -259,19 +259,17 @@ static void cg_emit_switch_table(CfreeCg* g, const CGSwitchDesc* d,
decl.as.object.flags = CFREE_CG_OBJ_READONLY;
api_remember_sym(g, table_sym, arr_ty, decl);
- /* 6. Load table[idx]: push the table's address, swap so the index is on top,
- * then load with EA scale = pointer size. */
+ /* 6. Load table[idx]: bitcast the table pointer to a pointer-to-element so
+ * the element place carries the pointer-size scale, put the index on top,
+ * project the element place, then load it. */
cfree_cg_push_symbol_addr(g, (CfreeCgSym)table_sym, 0); /* [idx, &table] */
+ cfree_cg_bitcast(g, cg_type_ptr_to(c, void_ptr_ty)); /* &table : void** */
cfree_cg_swap(g); /* [&table, idx] */
+ cfree_cg_elem(g, 0); /* [&table[idx]] */
memset(&acc, 0, sizeof acc);
acc.type = void_ptr_ty;
acc.align = (uint32_t)c->target.ptr_align;
- {
- CfreeCgEffAddr ea;
- ea.offset = 0;
- ea.scale = (uint32_t)c->target.ptr_size;
- cfree_cg_load(g, acc, ea); /* [label_addr] */
- }
+ cfree_cg_load(g, acc); /* [label_addr] */
/* 7. Indirect branch with the full closed target set (every case +
* default), so backends doing branch-target hardening (BTI/IBT/CFG)
@@ -826,96 +824,97 @@ void cfree_cg_memset(CfreeCg* g, uint8_t val, uint64_t size,
api_release(g, &dst);
}
-void cfree_cg_index(CfreeCg* g, uint64_t offset) {
+/* log2 of a {1,2,4,8} scale, else -1. */
+static int cg_scale_to_log2(u32 scale) {
+ switch (scale) {
+ case 1:
+ return 0;
+ case 2:
+ return 1;
+ case 4:
+ return 2;
+ case 8:
+ return 3;
+ default:
+ return -1;
+ }
+}
+
+void cfree_cg_elem(CfreeCg* g, int64_t offset) {
ApiSValue idx, base;
CgTarget* T;
CfreeCgTypeId base_ty, base_ptr_ty, elem_ty, idx_ty;
const CgType* base_info;
u32 elemsz;
- int free_base_op = 0;
- Operand base_op, idx_op, result;
- CGLocal rr;
+ Operand base_op, idx_op;
+ CGLocal base_local;
if (!g) return;
- if (offset > INT64_MAX) {
- compiler_panic(g->c, g->cur_loc, "CfreeCg: index offset too large");
- return;
- }
T = g->target;
idx = api_pop(g);
base = api_pop(g);
- api_ensure_local(g, &base);
base_ty = api_sv_type(&base);
base_info = cg_type_get(g->c, base_ty);
- if (base_info && base_info->kind == CFREE_CG_TYPE_PTR) {
- elem_ty = base_info->ptr.pointee;
- base_ptr_ty = base_ty;
- } else if (base_info && base_info->kind == CFREE_CG_TYPE_ARRAY &&
- api_is_lvalue_sv(&base)) {
- elem_ty = base_info->array.elem;
- base_ptr_ty = cg_type_ptr_to(g->c, elem_ty);
- } else {
+ if (api_is_lvalue_sv(&base) || !base_info ||
+ base_info->kind != CFREE_CG_TYPE_PTR) {
compiler_panic(g->c, g->cur_loc,
- "CfreeCg: index base is not a pointer or array lvalue");
+ "CfreeCg: elem requires a pointer value base (decay an "
+ "array to a pointer first)");
return;
}
+ elem_ty = base_info->ptr.pointee;
+ base_ptr_ty = base_ty;
elemsz = (u32)abi_cg_sizeof(g->c->abi, elem_ty);
idx_ty = idx.type ? idx.type : idx.op.type;
- if (!idx_ty) idx_ty = builtin_id(CFREE_CG_BUILTIN_I32);
- if (base_info && base_info->kind == CFREE_CG_TYPE_ARRAY) {
- rr = api_alloc_temp_local(g, base_ptr_ty);
- base_op = api_op_local(rr, base_ptr_ty);
- T->addr_of(T, base_op, base.op);
- api_release(g, &base);
- free_base_op = 1;
- } else {
- base_op = api_force_local(g, &base, base_ptr_ty);
- }
+ if (!idx_ty) idx_ty = builtin_id(CFREE_CG_BUILTIN_I64);
+ base_op = api_force_local(g, &base, base_ptr_ty);
+ base_local = base_op.v.local;
idx_op = api_force_local_unless_imm(g, &idx, idx_ty);
- rr = api_alloc_temp_local(g, base_ptr_ty);
- result = api_op_local(rr, base_ptr_ty);
+
+ /* Constant index folds entirely into the displacement — no instructions, just
+ * a larger offset on the OPK_INDIRECT. */
if (idx_op.kind == OPK_IMM) {
- i64 total_offset = idx_op.v.imm * (i64)elemsz + (i64)offset;
- T->binop(T, BO_IADD, result, base_op,
- api_op_imm(total_offset, base_ptr_ty));
- } else {
- CGLocal sr = api_alloc_temp_local(g, idx_ty);
- Operand scaled = api_op_local(sr, idx_ty);
- /* Allocating `scaled` can materialize a delayed index expression into a
- * fresh virtual local under opt. Refresh idx_op so the multiply uses
- * the materialized value, not the pre-materialization source operand. */
+ i64 ofs = idx_op.v.imm * (i64)elemsz + offset;
+ Operand place;
+ if (ofs >= INT32_MIN && ofs <= INT32_MAX) {
+ place = api_op_indirect(base_local, (i32)ofs, elem_ty);
+ } else {
+ CGLocal r = api_alloc_temp_local(g, base_ptr_ty);
+ Operand ro = api_op_local(r, base_ptr_ty);
+ T->binop(T, BO_IADD, ro, api_op_local(base_local, base_ptr_ty),
+ api_op_imm(ofs, base_ptr_ty));
+ place = api_op_indirect(r, 0, elem_ty);
+ }
+ api_release(g, &base);
+ api_release(g, &idx);
+ api_push(g, api_make_lv(place, elem_ty));
+ return;
+ }
+
+ /* Dynamic index: build a scaled-index place so the backend emits one
+ * [base + index*scale] addressing mode. A power-of-two element size rides in
+ * log2_scale; any other size pre-multiplies the index once (scale 1). The
+ * index is copied into a fresh local for unambiguous ownership. */
+ {
+ int lg2 = cg_scale_to_log2(elemsz);
+ CGLocal ir = api_alloc_temp_local(g, idx_ty);
+ Operand iro = api_op_local(ir, idx_ty);
+ u8 log2_scale;
+ /* Refresh idx_op: allocating `ir` may have materialized a delayed index. */
idx_op = api_force_local_unless_imm(g, &idx, idx_ty);
if (idx.op.kind == OPK_LOCAL) idx_op = idx.op;
- T->binop(T, BO_IMUL, scaled, idx_op, api_op_imm((i64)elemsz, idx_ty));
- if (offset > 0) {
- T->binop(T, BO_IADD, scaled, scaled, api_op_imm((i64)offset, idx_ty));
- }
- /* The final IADD takes operands with the pointer's integer width. Match
- * the scaled index to the base pointer width before adding. */
- u32 idx_sz = (u32)abi_cg_sizeof(g->c->abi, idx_ty);
- u32 ptr_sz = (u32)abi_cg_sizeof(g->c->abi, base_ptr_ty);
- if (idx_sz && ptr_sz && idx_sz > ptr_sz) {
- CGLocal narrow_r = api_alloc_temp_local(g, base_ptr_ty);
- Operand narrow = api_op_local(narrow_r, base_ptr_ty);
- T->convert(T, CV_TRUNC, narrow, scaled);
- T->binop(T, BO_IADD, result, base_op, narrow);
- api_release_temp_local(g, narrow_r);
- } else if (idx_sz && ptr_sz && idx_sz < ptr_sz) {
- CGLocal wide_r = api_alloc_temp_local(g, base_ptr_ty);
- Operand wide = api_op_local(wide_r, base_ptr_ty);
- T->convert(T, CV_ZEXT, wide, scaled);
- T->binop(T, BO_IADD, result, base_op, wide);
- api_release_temp_local(g, wide_r);
+ if (lg2 >= 0) {
+ T->copy(T, iro, idx_op);
+ log2_scale = (u8)lg2;
} else {
- T->binop(T, BO_IADD, result, base_op, scaled);
+ T->binop(T, BO_IMUL, iro, idx_op, api_op_imm((i64)elemsz, idx_ty));
+ log2_scale = 0;
}
- api_release_temp_local(g, sr);
- }
- if (free_base_op) api_release_temp_local(g, base_op.v.local);
- if (!base_info || base_info->kind != CFREE_CG_TYPE_ARRAY)
api_release(g, &base);
- api_release(g, &idx);
- api_push(g,
- api_make_lv(api_op_indirect(result.v.local, 0, elem_ty), elem_ty));
+ api_release(g, &idx);
+ api_push(g, api_make_lv(api_op_indirect_indexed(base_local, ir, log2_scale,
+ (i32)offset, elem_ty),
+ elem_ty));
+ }
}
void cfree_cg_field(CfreeCg* g, uint32_t field_index) {
@@ -925,11 +924,9 @@ void cfree_cg_field(CfreeCg* g, uint32_t field_index) {
CfreeCgTypeId base_ty;
CfreeCgTypeId field_ty;
CfreeCgTypeId rec_ptr_ty;
- const CgType* base_info;
const CgType* rec_info;
const ABIRecordLayout* layout;
u32 field_offset;
- int base_is_lvalue;
Operand result;
CGLocal rr;
if (!g) return;
@@ -937,20 +934,15 @@ void cfree_cg_field(CfreeCg* g, uint32_t field_index) {
base = api_pop(g);
api_ensure_local(g, &base);
base_ty = api_sv_type(&base);
- base_is_lvalue = api_is_lvalue_sv(&base);
- if (base_is_lvalue) {
- rec_ty = base_ty;
- } else {
- base_info = cg_type_get(g->c, base_ty);
- if (!base_info || base_info->kind != CFREE_CG_TYPE_PTR) {
- compiler_panic(g->c, g->cur_loc,
- "CfreeCg: field base is not an lvalue or record pointer");
- api_release(g, &base);
- return;
- }
- rec_ty = base_info->ptr.pointee;
+ if (!api_is_lvalue_sv(&base)) {
+ compiler_panic(g->c, g->cur_loc,
+ "CfreeCg: field requires a record place; deref a pointer "
+ "first");
+ api_release(g, &base);
+ return;
}
- rec_ptr_ty = base_is_lvalue ? cg_type_ptr_to(g->c, rec_ty) : base_ty;
+ rec_ty = base_ty;
+ rec_ptr_ty = cg_type_ptr_to(g->c, rec_ty);
layout = abi_cg_record_layout(g->c->abi, rec_ty);
if (!layout || field_index >= layout->nfields) {
compiler_panic(g->c, g->cur_loc, "CfreeCg: invalid field index");
@@ -975,12 +967,6 @@ void cfree_cg_field(CfreeCg* g, uint32_t field_index) {
api_release(g, &base);
return;
}
- if (!base_is_lvalue) {
- compiler_panic(g->c, g->cur_loc,
- "CfreeCg: pointer field bit-fields are not supported");
- api_release(g, &base);
- return;
- }
base_addr = api_lvalue_addr(g, &base, rec_ptr_ty);
memset(&bf, 0, sizeof bf);
bf.field_type = field_ty;
@@ -997,29 +983,18 @@ void cfree_cg_field(CfreeCg* g, uint32_t field_index) {
api_push(g, sv);
return;
}
- if (!base_is_lvalue) {
- Operand base_op = api_force_local(g, &base, rec_ptr_ty);
- if (field_offset == 0) {
- result = base_op;
- base.res = RES_INHERENT;
- } else {
- rr = api_alloc_temp_local(g, rec_ptr_ty);
- result = api_op_local(rr, rec_ptr_ty);
- T->binop(T, BO_IADD, result, base_op,
- api_op_imm((i64)field_offset, rec_ptr_ty));
- api_release(g, &base);
- }
- api_push(
- g, api_make_lv(api_op_indirect(result.v.local, 0, field_ty), field_ty));
- } else if (base.op.kind == OPK_GLOBAL) {
+ if (base.op.kind == OPK_GLOBAL) {
result =
api_op_global(base.op.v.global.sym,
base.op.v.global.addend + (i64)field_offset, field_ty);
api_push(g, api_make_lv(result, field_ty));
} else if (base.op.kind == OPK_INDIRECT && field_offset <= (u32)INT32_MAX &&
base.op.v.ind.ofs <= INT32_MAX - (i32)field_offset) {
- result = api_op_indirect(base.op.v.ind.base,
- base.op.v.ind.ofs + (i32)field_offset, field_ty);
+ /* Fold the field offset into the displacement, preserving any index/scale
+ * a preceding `elem` left so `p[i].f` stays one [base+index*scale+off]. */
+ result = api_op_indirect_indexed(
+ base.op.v.ind.base, base.op.v.ind.index, base.op.v.ind.log2_scale,
+ base.op.v.ind.ofs + (i32)field_offset, field_ty);
api_push(g, api_make_lv(result, field_ty));
} else {
Operand base_addr;
diff --git a/src/cg/internal.h b/src/cg/internal.h
@@ -333,9 +333,10 @@ void api_push_source_local_lvalue(CfreeCg* g, CfreeCgLocal local,
void cfree_cg_push_local(CfreeCg* g, CfreeCgLocal local);
void cfree_cg_push_local_addr(CfreeCg* g, CfreeCgLocal local);
void cfree_cg_push_symbol_addr(CfreeCg* g, CfreeCgSym sym, int64_t addend);
-void cfree_cg_load(CfreeCg* g, CfreeCgMemAccess access, CfreeCgEffAddr ea);
+void cfree_cg_load(CfreeCg* g, CfreeCgMemAccess access);
void cfree_cg_addr(CfreeCg* g);
-void cfree_cg_store(CfreeCg* g, CfreeCgMemAccess access, CfreeCgEffAddr ea);
+void cfree_cg_deref(CfreeCg* g, int64_t offset);
+void cfree_cg_store(CfreeCg* g, CfreeCgMemAccess access);
void cfree_cg_dup(CfreeCg* g);
void cfree_cg_dup2(CfreeCg* g);
void cfree_cg_swap(CfreeCg* g);
diff --git a/src/cg/memory.c b/src/cg/memory.c
@@ -141,224 +141,6 @@ void cfree_cg_push_symbol_addr(CfreeCg* g, CfreeCgSym sym, int64_t addend) {
}
}
-/* ============================================================
- * Load / addr / store
- *
- * The memops dispatch on the TOS shape of `base`:
- * 1. lvalue base, no index -> fold ea.offset into the operand encoding
- * (OPK_LOCAL / OPK_GLOBAL / OPK_INDIRECT) and emit a single memop.
- * 2. lvalue base, scaled index -> take the lvalue's address, then form an
- * indexed OPK_INDIRECT and emit a single memop.
- * 3. pointer-rvalue base, no index -> for OPK_GLOBAL fold the offset into
- * the addend; otherwise use [local + offset].
- * 4. pointer-rvalue base, scaled index -> form OPK_INDIRECT against the
- * pointer local with index/scale.
- *
- * Scale normalization (ea.scale != 0):
- * {1,2,4,8} -> log2_scale 0..3 on OPK_INDIRECT.
- * otherwise -> compute index*scale into a fresh local, fold into base,
- * dispatch with index = CG_LOCAL_NONE.
- * ============================================================ */
-
-/* log2 of a {1,2,4,8} scale, else -1. */
-static int scale_to_log2(uint32_t scale) {
- switch (scale) {
- case 1:
- return 0;
- case 2:
- return 1;
- case 4:
- return 2;
- case 8:
- return 3;
- default:
- return -1;
- }
-}
-
-/* Materialize the EA into an OPK_INDIRECT operand suitable for the backend
- * load/store. `addr` may be OPK_LOCAL, OPK_GLOBAL, or OPK_INDIRECT. The
- * `offset` is folded into the operand; the indexed form is encoded directly.
- * If the index path requires arithmetic on a global/local, the address is
- * first lowered into a local via T->addr_of and then combined.
- *
- * The caller owns `index_local` (CG_LOCAL_NONE if no index). On return,
- * *out_owned_base is set to the local that the caller must free after the
- * memop completes (CG_LOCAL_NONE if no new local was allocated). The returned
- * operand's index local is freed by the caller separately when applicable;
- * this helper does not free it.
- */
-static Operand fold_ea_into_operand(CfreeCg* g, Operand addr, i64 offset,
- CGLocal index, u8 log2_scale,
- CfreeCgTypeId access_ty,
- int addr_is_pointer_value,
- CGLocal* out_owned_base) {
- CgTarget* T = g->target;
- CfreeCgTypeId base_ty = cg_type_is_ptr(g->c, addr.type)
- ? addr.type
- : cg_type_ptr_to(g->c, access_ty);
- *out_owned_base = CG_LOCAL_NONE;
-
- if (index == CG_LOCAL_NONE) {
- /* No index: fold offset into the operand directly. */
- if (addr.kind == OPK_LOCAL) {
- if (addr_is_pointer_value) {
- if (offset >= INT32_MIN && offset <= INT32_MAX) {
- return api_op_indirect(addr.v.local, (i32)offset, access_ty);
- }
- {
- CGLocal br = api_alloc_temp_local(g, base_ty);
- Operand base_reg = api_op_local(br, base_ty);
- T->binop(T, BO_IADD, base_reg, api_op_local(addr.v.local, base_ty),
- api_op_imm(offset, base_ty));
- *out_owned_base = br;
- return api_op_indirect(br, 0, access_ty);
- }
- }
- if (offset == 0) {
- (void)access_ty;
- return addr;
- }
- /* OPK_LOCAL has no displacement field; materialize the base address into
- * a local and apply the offset. */
- {
- CGLocal br = api_alloc_temp_local(g, base_ty);
- Operand base_reg = api_op_local(br, base_ty);
- T->addr_of(T, base_reg, addr);
- if (offset >= INT32_MIN && offset <= INT32_MAX) {
- *out_owned_base = br;
- return api_op_indirect(br, (i32)offset, access_ty);
- }
- T->binop(T, BO_IADD, base_reg, base_reg, api_op_imm(offset, base_ty));
- *out_owned_base = br;
- return api_op_indirect(br, 0, access_ty);
- }
- }
- if (addr.kind == OPK_GLOBAL) {
- Operand r = api_op_global(addr.v.global.sym,
- addr.v.global.addend + offset, access_ty);
- return r;
- }
- if (addr.kind == OPK_INDIRECT) {
- i64 sum = (i64)addr.v.ind.ofs + offset;
- if (sum >= INT32_MIN && sum <= INT32_MAX) {
- return api_op_indirect_indexed(addr.v.ind.base, addr.v.ind.index,
- addr.v.ind.log2_scale, (i32)sum,
- access_ty);
- }
- /* Offset too large for i32 displacement; materialize. */
- {
- CGLocal br = api_alloc_temp_local(g, base_ty);
- Operand base_reg = api_op_local(br, base_ty);
- T->copy(T, base_reg, api_op_local(addr.v.ind.base, base_ty));
- T->binop(T, BO_IADD, base_reg, base_reg, api_op_imm(offset, base_ty));
- *out_owned_base = br;
- return api_op_indirect_indexed(br, addr.v.ind.index,
- addr.v.ind.log2_scale, addr.v.ind.ofs,
- access_ty);
- }
- }
- }
-
- /* Indexed form. addr must be reduced to a base local first when it is
- * not already an OPK_INDIRECT with room for an index local. */
- if (addr.kind == OPK_INDIRECT && addr.v.ind.index == CG_LOCAL_NONE &&
- offset == 0) {
- /* Reuse existing INDIRECT base; add index and scale. The displacement
- * stays whatever the operand already had. */
- return api_op_indirect_indexed(addr.v.ind.base, index, log2_scale,
- addr.v.ind.ofs, access_ty);
- }
- if (addr.kind == OPK_INDIRECT && addr.v.ind.index == CG_LOCAL_NONE) {
- i64 sum = (i64)addr.v.ind.ofs + offset;
- if (sum >= INT32_MIN && sum <= INT32_MAX) {
- return api_op_indirect_indexed(addr.v.ind.base, index, log2_scale,
- (i32)sum, access_ty);
- }
- }
- /* Otherwise, materialize addr into a local and then build the indexed
- * operand around it. */
- {
- CGLocal br = api_alloc_temp_local(g, base_ty);
- Operand base_reg = api_op_local(br, base_ty);
- if (addr.kind == OPK_LOCAL) {
- if (addr_is_pointer_value)
- T->copy(T, base_reg, api_op_local(addr.v.local, base_ty));
- else
- T->addr_of(T, base_reg, addr);
- } else {
- T->addr_of(T, base_reg, addr);
- }
- if (offset != 0) {
- if (offset >= INT32_MIN && offset <= INT32_MAX) {
- *out_owned_base = br;
- return api_op_indirect_indexed(br, index, log2_scale, (i32)offset,
- access_ty);
- }
- T->binop(T, BO_IADD, base_reg, base_reg, api_op_imm(offset, base_ty));
- }
- *out_owned_base = br;
- return api_op_indirect_indexed(br, index, log2_scale, 0, access_ty);
- }
-}
-
-/* Pop the index operand for a scaled-index memop. Returns the index in a
- * freshly allocated local that the caller owns and must free after the
- * memop. Handles the scale-not-in-{1,2,4,8} case by computing index*scale.
- *
- * On return:
- * *out_log2 = log2_scale (0..3) if scale was normalized to one of {1,2,4,8}
- * or to 0 if we materialized the scaled value (log2=0).
- */
-static CGLocal pop_and_normalize_index(CfreeCg* g, uint32_t scale,
- u8* out_log2) {
- ApiSValue idx;
- CfreeCgTypeId idx_ty;
- int lg2;
- Operand idx_op;
- CgTarget* T = g->target;
- CGLocal sr;
- Operand scaled;
-
- idx = api_pop(g);
- idx_ty = api_sv_type(&idx);
- if (!idx_ty) idx_ty = builtin_id(CFREE_CG_BUILTIN_I64);
-
- lg2 = scale_to_log2(scale);
- if (lg2 >= 0) {
- *out_log2 = (u8)lg2;
- /* Always allocate a fresh local so the caller has unambiguous
- * ownership; copy the index value in. */
- idx_op = api_force_local_unless_imm(g, &idx, idx_ty);
- sr = api_alloc_temp_local(g, idx_ty);
- scaled = api_op_local(sr, idx_ty);
- if (idx_op.kind == OPK_IMM) {
- T->load_imm(T, scaled, idx_op.v.imm);
- } else {
- /* Re-fetch in case alloc materialized a delayed expression. */
- idx_op = api_force_local_unless_imm(g, &idx, idx_ty);
- if (idx.op.kind == OPK_LOCAL) idx_op = idx.op;
- T->copy(T, scaled, idx_op);
- }
- api_release(g, &idx);
- return sr;
- }
-
- /* Non-power-of-two scale: materialize index*scale into a fresh local. */
- idx_op = api_force_local_unless_imm(g, &idx, idx_ty);
- sr = api_alloc_temp_local(g, idx_ty);
- scaled = api_op_local(sr, idx_ty);
- if (idx_op.kind == OPK_IMM) {
- T->load_imm(T, scaled, idx_op.v.imm * (i64)scale);
- } else {
- idx_op = api_force_local_unless_imm(g, &idx, idx_ty);
- if (idx.op.kind == OPK_LOCAL) idx_op = idx.op;
- T->binop(T, BO_IMUL, scaled, idx_op, api_op_imm((i64)scale, idx_ty));
- }
- api_release(g, &idx);
- *out_log2 = 0;
- return sr;
-}
/* Build a BitFieldAccess descriptor from the CfreeCgMemAccess metadata. */
static BitFieldAccess bf_from_access(CfreeCg* g, CfreeCgMemAccess access,
@@ -387,54 +169,51 @@ static int api_sv_local_storage_is_aggregate(CfreeCg* g, const ApiSValue* sv) {
cg_type_is_aggregate(g->c, rec->type);
}
-/* Pop the base for a memop; populate `*base_addr` with an operand the backend
- * can consume (LOCAL/GLOBAL/INDIRECT for lvalue forms, or LOCAL holding a
- * pointer for rvalue forms). Returns 1 if `base` is an lvalue, 0 otherwise.
- *
- * Sets `*source_local_out` to the lvalue's source_local handle when applicable
- * (so the caller can update constant tracking). Sets `*lvalue_sv` to a copy of
- * the popped lvalue so the caller can call api_release on it after the memop;
- * for rvalue-pointer forms, `*lvalue_sv` is the popped value (used for
- * release).
- */
+/* Retype an already-addressable place operand to the access type — the way the
+ * old offset-0 EA fold did. GLOBAL/INDIRECT carry the access type into the
+ * operand; a bare LOCAL keeps its own type (the memop's MemAccess carries the
+ * access width). */
+static Operand place_operand_for_access(Operand op, CfreeCgTypeId access_ty) {
+ switch (op.kind) {
+ case OPK_GLOBAL:
+ return api_op_global(op.v.global.sym, op.v.global.addend, access_ty);
+ case OPK_INDIRECT:
+ return api_op_indirect_indexed(op.v.ind.base, op.v.ind.index,
+ op.v.ind.log2_scale, op.v.ind.ofs,
+ access_ty);
+ default:
+ return op;
+ }
+}
-void cfree_cg_load(CfreeCg* g, CfreeCgMemAccess access, CfreeCgEffAddr ea) {
+/* Load a VALUE from the PLACE on TOS. The place encodes the full address (built
+ * by push_local / deref / field / elem); there is no EA rider. Strict: the
+ * operand must be a PLACE — a pointer VALUE must be `deref`'d first. */
+void cfree_cg_load(CfreeCg* g, CfreeCgMemAccess access) {
ApiSValue base;
CgTarget* T;
CfreeCgTypeId ty;
CfreeCgTypeId access_ty;
CGLocal owned_base = CG_LOCAL_NONE;
- CGLocal owned_index = CG_LOCAL_NONE;
- u8 log2_scale = 0;
Operand mem_op;
CGLocal dst_r;
Operand dst;
- int is_lvalue;
int is_bitfield;
- int has_index;
if (!g) return;
T = g->target;
if (access.flags & CFREE_CG_MEM_VOLATILE) api_local_const_memory_boundary(g);
- has_index = (ea.scale != 0);
is_bitfield = (access.bit_width != 0);
- if (has_index) {
- /* Pop and normalize the index first; it sits between base and any
- * follow-up value (none for load). */
- owned_index = pop_and_normalize_index(g, ea.scale, &log2_scale);
- }
-
base = api_pop(g);
- is_lvalue = api_is_lvalue_sv(&base);
+ if (!api_is_lvalue_sv(&base)) {
+ compiler_panic(g->c, g->cur_loc,
+ "CfreeCg: load requires a place; deref the pointer first");
+ }
- /* Aggregate / non-EA fast paths only apply to the no-index, no-bitfield
- * case where the result is the lvalue itself (matches old behavior).
- * Scalar accesses at an offset into an aggregate lvalue are the canonical
- * field-access pattern under the EA model and fall through to the normal
- * scalar load path below. */
- if (!has_index && !is_bitfield && is_lvalue && ea.offset == 0 &&
- cg_type_is_aggregate(g->c, api_sv_type(&base))) {
+ /* Aggregate place: an aggregate-typed access returns the place itself; a
+ * scalar access reads a scalar sub-object and falls through. */
+ if (!is_bitfield && cg_type_is_aggregate(g->c, api_sv_type(&base))) {
ty = api_mem_access_type(g, access, api_sv_type(&base), "load");
if (cg_type_is_aggregate(g->c, ty)) {
u32 access_size = api_mem_type_size(g, ty, "load");
@@ -448,48 +227,26 @@ void cfree_cg_load(CfreeCg* g, CfreeCgMemAccess access, CfreeCgEffAddr ea) {
api_push(g, base);
return;
}
- /* Scalar access from aggregate lvalue: fall through. */
- }
-
- /* From here on, base must reduce to something we can address. */
- if (!is_lvalue && cg_type_is_aggregate(g->c, api_sv_type(&base))) {
- /* Pointer rvalue to aggregate without any EA -- return as-is. */
- if (!has_index && !is_bitfield && ea.offset == 0) {
- api_push(g, base);
- return;
- }
+ /* scalar access from an aggregate place: fall through */
}
ty = api_mem_access_type(g, access, api_sv_type(&base), "load");
access_ty = ty;
- if (!has_index && !is_bitfield && !is_lvalue && base.kind == SV_OPERAND &&
- base.op.kind == OPK_GLOBAL &&
- (cg_type_is_aggregate(g->c, ty) || api_is_wide16_scalar_type(g->c, ty))) {
- base.type = ty;
- base.op.type = ty;
- base.lvalue = 1;
- api_push(g, base);
- return;
- }
-
if (!is_bitfield) api_require_scalar_mem_type(g, "load", access_ty);
- /* Source-local constant load (only the plain, no-EA case is tracked). */
- if (!has_index && !is_bitfield && ea.offset == 0 && is_lvalue &&
- base.source_local != CFREE_CG_LOCAL_NONE &&
+ /* Source-local constant load. */
+ if (!is_bitfield && base.source_local != CFREE_CG_LOCAL_NONE &&
api_local_const_load(g, base.source_local, access, &dst)) {
api_release(g, &base);
api_push(g, api_make_sv(dst, dst.type));
return;
}
- /* Scalar local lvalue: plain no-EA load returns the local value directly.
- * Aggregate locals are storage; even offset-zero field accesses must go
- * through the memory path so the access type controls the dereference instead
- * of treating the whole aggregate as a scalar value. */
- if (!has_index && !is_bitfield && ea.offset == 0 && is_lvalue &&
- base.source_local != CFREE_CG_LOCAL_NONE && base.op.kind == OPK_LOCAL &&
+ /* Scalar local place: the value already lives in the local; hand it back
+ * directly without a memory access. */
+ if (!is_bitfield && base.source_local != CFREE_CG_LOCAL_NONE &&
+ base.op.kind == OPK_LOCAL &&
!api_sv_local_storage_is_aggregate(g, &base) &&
!cg_type_is_aggregate(g->c, api_sv_type(&base)) &&
!cg_type_is_aggregate(g->c, ty) &&
@@ -501,76 +258,23 @@ void cfree_cg_load(CfreeCg* g, CfreeCgMemAccess access, CfreeCgEffAddr ea) {
return;
}
- /* Wide-16 scalar lvalue load: keep the addressable storage as the value.
- * For fields at a fixed offset, fold the EA into a new lvalue operand instead
- * of asking the backend for a single 16-byte local load. */
- if (!has_index && !is_bitfield && is_lvalue &&
- api_is_wide16_scalar_type(g->c, ty)) {
- if (ea.offset == 0) {
- api_push(g, base);
- return;
- }
- if (!api_operand_can_address(&base.op)) {
- CfreeCgTypeId pty = cg_type_ptr_to(g->c, api_sv_type(&base));
- Operand addr = api_lvalue_addr(g, &base, pty);
- mem_op = fold_ea_into_operand(g, addr, ea.offset, CG_LOCAL_NONE, 0, ty, 1,
- &owned_base);
- if (owned_base == CG_LOCAL_NONE)
- owned_base = addr.v.local;
- else if (owned_base != addr.v.local)
- api_release_temp_local(g, addr.v.local);
- } else {
- mem_op = fold_ea_into_operand(g, base.op, ea.offset, CG_LOCAL_NONE, 0, ty,
- 0, &owned_base);
- }
- if (mem_op.kind == OPK_INDIRECT && owned_base == CG_LOCAL_NONE &&
- base.op.kind == OPK_INDIRECT) {
- base.res = RES_INHERENT;
- }
- api_release(g, &base);
- api_push(g, api_make_lv(mem_op, ty));
+ /* Wide-16 scalar place: keep the addressable storage as the value. */
+ if (!is_bitfield && api_is_wide16_scalar_type(g->c, ty)) {
+ api_push(g, base);
return;
}
- /* Compute the memop operand. Lvalue bases preserve named-storage operands;
- * pointer rvalues use the local holding the address. */
- if (is_lvalue) {
- if (!api_operand_can_address(&base.op)) {
- /* Source-local needs an EA: take
- * the lvalue's address first. */
- CfreeCgTypeId pty = cg_type_ptr_to(g->c, api_sv_type(&base));
- Operand addr = api_lvalue_addr(g, &base, pty);
- mem_op = fold_ea_into_operand(g, addr, ea.offset, owned_index, log2_scale,
- access_ty, 1, &owned_base);
- /* `addr` is an owned local from api_lvalue_addr. */
- if (owned_base == CG_LOCAL_NONE)
- owned_base = addr.v.local;
- else if (owned_base != addr.v.local)
- api_release_temp_local(g, addr.v.local);
- } else {
- /* The lvalue carries its own operand; fold the EA into it. */
- mem_op = fold_ea_into_operand(g, base.op, ea.offset, owned_index,
- log2_scale, access_ty, 0, &owned_base);
- }
- } else if (base.kind == SV_OPERAND && base.op.kind == OPK_GLOBAL) {
- /* Pointer-rvalue OPK_GLOBAL: fold the EA directly against the global
- * (matching the lvalue OPK_GLOBAL path) so the backend can emit a single
- * PC-relative or absolute access. */
- mem_op = fold_ea_into_operand(g, base.op, ea.offset, owned_index,
- log2_scale, access_ty, 0, &owned_base);
+ /* Resolve the place into a single backend memop operand. */
+ if (!api_operand_can_address(&base.op)) {
+ CfreeCgTypeId pty = cg_type_ptr_to(g->c, api_sv_type(&base));
+ Operand addr = api_lvalue_addr(g, &base, pty);
+ mem_op = api_op_indirect(addr.v.local, 0, access_ty);
+ owned_base = addr.v.local;
} else {
- /* Pointer rvalue: ensure the address is in a local and treat that as
- * the base. */
- CfreeCgTypeId pty = api_sv_type(&base);
- Operand ptr_op = api_force_local(g, &base, pty);
- mem_op = fold_ea_into_operand(g, ptr_op, ea.offset, owned_index, log2_scale,
- access_ty, 1, &owned_base);
+ mem_op = place_operand_for_access(base.op, access_ty);
}
- /* Mutate source-local tracking. Any EA-shaped load through a tracked local
- * (offset != 0 or has_index or non-matching access) cannot use the cached
- * scalar value: clear it. */
- if (is_lvalue && base.source_local != CFREE_CG_LOCAL_NONE) {
+ if (base.source_local != CFREE_CG_LOCAL_NONE) {
api_local_const_clear(api_local_from_handle(g, base.source_local));
}
@@ -585,33 +289,51 @@ void cfree_cg_load(CfreeCg* g, CfreeCgMemAccess access, CfreeCgEffAddr ea) {
T->load(T, dst, mem_op, api_mem_from_access(g, &mem_op, access));
}
- /* Release the base lvalue/rvalue and any owned locals. */
- if (is_lvalue) {
- /* If the original lvalue's operand was OPK_INDIRECT, its base local
- * was owned by the lvalue and is still in mem_op.v.ind.base when we did
- * not allocate a new owned_base. Free that base when no new owned_base
- * shadows it. */
- if (base.op.kind == OPK_INDIRECT && owned_base == CG_LOCAL_NONE) {
- /* mem_op uses the same base local as base.op; free it via the
- * lvalue release. */
- }
- api_release(g, &base);
- } else {
- /* For rvalue-pointer bases, the local holding the pointer was the
- * owned local of `base`; api_release will free it unless the EA folding
- * already absorbed it into mem_op. The fold_ea_into_operand path for
- * LOCAL returns either OPK_INDIRECT(addr.v.local, ofs) (no new owned_base)
- * or a freshly allocated owned_base. In either case api_release(&base)
- * frees the pointer local; that is fine because we already issued
- * the memop. */
- api_release(g, &base);
- }
+ api_release(g, &base);
if (owned_base != CG_LOCAL_NONE) api_release_temp_local(g, owned_base);
- if (owned_index != CG_LOCAL_NONE) api_release_temp_local(g, owned_index);
-
api_push(g, api_make_sv(dst, access_ty));
}
+/* VALUE(ptr) -> PLACE: the explicit pointer->place transition. The produced
+ * place is *(ptr + offset bytes). Strict on kind: the operand must be a pointer
+ * VALUE, never a PLACE — the caller turns a place into a pointer with `addr`
+ * first. */
+void cfree_cg_deref(CfreeCg* g, int64_t offset) {
+ ApiSValue v;
+ CfreeCgTypeId pty;
+ CfreeCgTypeId pointee;
+ Operand ptr;
+ if (!g) return;
+ v = api_pop(g);
+ pty = api_sv_type(&v);
+ if (api_is_lvalue_sv(&v) || !cg_type_is_ptr(g->c, pty)) {
+ compiler_panic(g->c, g->cur_loc,
+ "CfreeCg: deref requires a pointer value, not a place");
+ }
+ pointee = cg_type_pointee(g->c, pty);
+ if (!pointee) pointee = builtin_id(CFREE_CG_BUILTIN_VOID);
+ /* A symbol address derefs to a global place, preserving direct
+ * (PC-relative/absolute) addressing rather than materializing the address. */
+ if (v.kind == SV_OPERAND && v.op.kind == OPK_GLOBAL) {
+ api_push(g, api_make_lv(
+ api_op_global(v.op.v.global.sym,
+ v.op.v.global.addend + offset, pointee),
+ pointee));
+ return;
+ }
+ ptr = api_force_local(g, &v, pty);
+ if (offset >= INT32_MIN && offset <= INT32_MAX) {
+ api_push(g, api_make_lv(api_op_indirect(ptr.v.local, (i32)offset, pointee),
+ pointee));
+ } else {
+ CGLocal r = api_alloc_temp_local(g, pty);
+ Operand p2 = api_op_local(r, pty);
+ g->target->binop(g->target, BO_IADD, p2, ptr, api_op_imm(offset, pty));
+ api_push(g, api_make_lv(api_op_indirect(r, 0, pointee), pointee));
+ }
+}
+
+
void cfree_cg_addr(CfreeCg* g) {
ApiSValue v;
CfreeCgTypeId pty;
@@ -626,57 +348,42 @@ void cfree_cg_addr(CfreeCg* g) {
api_push(g, api_make_sv(dst, pty));
}
-void cfree_cg_store(CfreeCg* g, CfreeCgMemAccess access, CfreeCgEffAddr ea) {
+/* Store the VALUE on TOS into the PLACE beneath it. Stack: [place, value] -> [].
+ * The place encodes the full address; there is no EA rider. Strict: the
+ * destination must be a PLACE — a pointer VALUE must be `deref`'d first. */
+void cfree_cg_store(CfreeCg* g, CfreeCgMemAccess access) {
ApiSValue base, rv;
CgTarget* T;
CfreeCgTypeId ty;
CfreeCgTypeId access_ty;
Operand src;
CGLocal owned_base = CG_LOCAL_NONE;
- CGLocal owned_index = CG_LOCAL_NONE;
- u8 log2_scale = 0;
Operand mem_op;
int is_lvalue;
int is_bitfield;
- int has_index;
if (!g) return;
T = g->target;
if (access.flags & CFREE_CG_MEM_VOLATILE) api_local_const_memory_boundary(g);
- has_index = (ea.scale != 0);
is_bitfield = (access.bit_width != 0);
- /* Stack:
- * no index: [base, value] - pop value, then index (none), then base
- * indexed: [base, index, value] - pop value, then index, then base
- */
+ /* Stack: [base, value] - pop value, then base. */
rv = api_pop(g);
- if (has_index) {
- owned_index = pop_and_normalize_index(g, ea.scale, &log2_scale);
- }
base = api_pop(g);
is_lvalue = api_is_lvalue_sv(&base);
if (!is_lvalue) {
- /* The "destination is not an lvalue" diagnostic now only fires when the
- * popped base is neither an lvalue nor a pointer-typed rvalue. */
- if (!cg_type_is_ptr(g->c, api_sv_type(&base))) {
- compiler_panic(g->c, g->cur_loc,
- "CfreeCg: store destination is not an lvalue or pointer");
- return;
- }
+ compiler_panic(g->c, g->cur_loc,
+ "CfreeCg: store requires a place destination; deref first");
+ return;
}
ty = api_mem_access_type(g, access, api_sv_type(&base), "store");
access_ty = ty;
- /* Aggregate store (no EA): memcpy through src lvalue. Only triggers when
- * the access type itself is aggregate. Scalar stores at an offset into an
- * aggregate lvalue are field-stores under the EA model and fall through to
- * the scalar store path. */
- if (!has_index && !is_bitfield && ea.offset == 0 &&
- (cg_type_is_aggregate(g->c, ty) ||
- cg_type_is_aggregate(g->c, api_sv_type(&rv)))) {
+ /* Aggregate store: memcpy through the source place. */
+ if (!is_bitfield && (cg_type_is_aggregate(g->c, ty) ||
+ cg_type_is_aggregate(g->c, api_sv_type(&rv)))) {
CfreeCgTypeId ptr_ty;
Operand dst_addr, src_addr;
int dst_addr_owned;
@@ -712,13 +419,8 @@ void cfree_cg_store(CfreeCg* g, CfreeCgMemAccess access, CfreeCgEffAddr ea) {
api_local_const_memory_boundary(g);
}
ptr_ty = cg_type_ptr_to(g->c, ty);
- if (is_lvalue) {
- dst_addr = api_lvalue_addr(g, &base, ptr_ty);
- dst_addr_owned = 1;
- } else {
- dst_addr = api_force_local(g, &base, api_sv_type(&base));
- dst_addr_owned = 0;
- }
+ dst_addr = api_lvalue_addr(g, &base, ptr_ty);
+ dst_addr_owned = 1;
if (src_ptr_rvalue) {
src_addr = api_force_local(g, &rv, api_sv_type(&rv));
src_addr_owned = 0;
@@ -739,28 +441,8 @@ void cfree_cg_store(CfreeCg* g, CfreeCgMemAccess access, CfreeCgEffAddr ea) {
if (!is_bitfield) api_validate_memory_value(g, "store", ty, api_sv_type(&rv));
- /* Wide-16 scalar store: keep the pre-existing wide16 lowering for the plain
- * (no-EA) case. */
- if (!has_index && !is_bitfield && api_is_wide16_scalar_type(g->c, ty)) {
- /* Normalize the destination up front into a single offset-0 lvalue
- * operand so every sub-branch below addresses the right location. Two
- * cases otherwise misbehave: a pointer-rvalue base (`*p`) is the address
- * itself and must be dereferenced (not treated as storage), and a field
- * offset (a struct member) must be folded in. Both collapse to an
- * OPK_INDIRECT lvalue here. */
- if (!is_lvalue) {
- /* Pointer-rvalue base: the operand value is the destination address. */
- Operand ptr_op = api_force_local(g, &base, api_sv_type(&base));
- base =
- api_make_lv(api_op_indirect(ptr_op.v.local, (i32)ea.offset, ty), ty);
- ea.offset = 0;
- is_lvalue = 1;
- } else if (ea.offset != 0 && base.op.kind == OPK_LOCAL) {
- CfreeCgTypeId base_ptr_ty = cg_type_ptr_to(g->c, ty);
- Operand addr = api_lvalue_addr(g, &base, base_ptr_ty);
- base = api_make_lv(api_op_indirect(addr.v.local, (i32)ea.offset, ty), ty);
- ea.offset = 0;
- }
+ /* Wide-16 scalar store. */
+ if (!is_bitfield && api_is_wide16_scalar_type(g->c, ty)) {
if (base.source_local != CFREE_CG_LOCAL_NONE) {
api_local_const_clear(api_local_from_handle(g, base.source_local));
} else if (base.op.kind == OPK_INDIRECT || base.op.kind == OPK_GLOBAL ||
@@ -774,19 +456,11 @@ void cfree_cg_store(CfreeCg* g, CfreeCgMemAccess access, CfreeCgEffAddr ea) {
int dst_addr_owned = 0;
int src_addr_owned = 0;
AggregateAccess agg;
- if (is_lvalue && base.op.kind == OPK_LOCAL) {
- if (ea.offset == 0) {
- dst_addr = base.op;
- } else {
- dst_addr = fold_ea_into_operand(g, base.op, ea.offset, CG_LOCAL_NONE,
- 0, ty, 0, &owned_base);
- dst_addr_owned = owned_base != CG_LOCAL_NONE;
- }
- } else if (is_lvalue) {
+ if (base.op.kind == OPK_LOCAL) {
+ dst_addr = base.op;
+ } else {
dst_addr = api_lvalue_addr(g, &base, ptr_ty);
dst_addr_owned = 1;
- } else {
- dst_addr = api_force_local(g, &base, api_sv_type(&base));
}
if (rv.op.kind == OPK_LOCAL) {
src_addr = rv.op;
@@ -823,21 +497,15 @@ void cfree_cg_store(CfreeCg* g, CfreeCgMemAccess access, CfreeCgEffAddr ea) {
CfreeCgTypeId ptr_ty = cg_type_ptr_to(g->c, ty);
Operand dst_addr;
Operand src_addr;
- int dst_addr_owned = 0;
AggregateAccess agg;
api_store_f128_bytes(g, local, ty, bytes);
- if (is_lvalue) {
- dst_addr = api_lvalue_addr(g, &base, ptr_ty);
- dst_addr_owned = 1;
- } else {
- dst_addr = api_force_local(g, &base, api_sv_type(&base));
- }
+ dst_addr = api_lvalue_addr(g, &base, ptr_ty);
src_addr = api_lvalue_addr(g, &tmp, ptr_ty);
memset(&agg, 0, sizeof agg);
agg.size = 16;
agg.align = access.align ? access.align : 16;
T->copy_bytes(T, dst_addr, src_addr, agg);
- if (dst_addr_owned) api_release_temp_local(g, dst_addr.v.local);
+ api_release_temp_local(g, dst_addr.v.local);
api_release_temp_local(g, src_addr.v.local);
}
} else {
@@ -849,11 +517,8 @@ void cfree_cg_store(CfreeCg* g, CfreeCgMemAccess access, CfreeCgEffAddr ea) {
return;
}
- /* General EA-shaped scalar / bit-field store. Resolve the EA into a
- * single operand the backend can consume. */
-
- /* Compute the source operand first so its local lifetime doesn't
- * overlap any EA-arith we issue. */
+ /* General scalar / bit-field store. Compute the source operand first so its
+ * local lifetime doesn't overlap any addressing arith. */
api_ensure_local(g, &rv);
if (api_sv_op_is_local_or_imm(&rv)) {
src = rv.op;
@@ -861,11 +526,9 @@ void cfree_cg_store(CfreeCg* g, CfreeCgMemAccess access, CfreeCgEffAddr ea) {
src = api_force_local(g, &rv, api_sv_type(&rv));
}
- /* Scalar local-resident lvalue, plain no-EA store: just copy into the local.
- * Aggregate locals are storage; field stores into them need the normal memory
- * path so offset-zero fields still use the scalar access type. */
- if (!has_index && !is_bitfield && ea.offset == 0 && is_lvalue &&
- base.source_local != CFREE_CG_LOCAL_NONE && base.op.kind == OPK_LOCAL &&
+ /* Scalar local-resident place, plain store: copy into the local. */
+ if (!is_bitfield && base.source_local != CFREE_CG_LOCAL_NONE &&
+ base.op.kind == OPK_LOCAL &&
!api_sv_local_storage_is_aggregate(g, &base) &&
!cg_type_is_aggregate(g->c, api_sv_type(&base)) &&
!cg_type_is_aggregate(g->c, ty) &&
@@ -884,49 +547,29 @@ void cfree_cg_store(CfreeCg* g, CfreeCgMemAccess access, CfreeCgEffAddr ea) {
}
api_release(g, &base);
api_release(g, &rv);
- if (owned_index != CG_LOCAL_NONE) api_release_temp_local(g, owned_index);
return;
}
- if (is_lvalue) {
- if (!api_operand_can_address(&base.op)) {
- CfreeCgTypeId pty = cg_type_ptr_to(g->c, api_sv_type(&base));
- Operand addr = api_lvalue_addr(g, &base, pty);
- mem_op = fold_ea_into_operand(g, addr, ea.offset, owned_index, log2_scale,
- access_ty, 1, &owned_base);
- if (owned_base == CG_LOCAL_NONE)
- owned_base = addr.v.local;
- else if (owned_base != addr.v.local)
- api_release_temp_local(g, addr.v.local);
- } else {
- mem_op = fold_ea_into_operand(g, base.op, ea.offset, owned_index,
- log2_scale, access_ty, 0, &owned_base);
- }
- } else if (base.kind == SV_OPERAND && base.op.kind == OPK_GLOBAL) {
- /* Pointer-rvalue OPK_GLOBAL: fold EA directly. */
- mem_op = fold_ea_into_operand(g, base.op, ea.offset, owned_index,
- log2_scale, access_ty, 0, &owned_base);
+ /* Resolve the place into a single backend memop operand. */
+ if (!api_operand_can_address(&base.op)) {
+ CfreeCgTypeId pty = cg_type_ptr_to(g->c, api_sv_type(&base));
+ Operand addr = api_lvalue_addr(g, &base, pty);
+ mem_op = api_op_indirect(addr.v.local, 0, access_ty);
+ owned_base = addr.v.local;
} else {
- CfreeCgTypeId pty = api_sv_type(&base);
- Operand ptr_op = api_force_local(g, &base, pty);
- mem_op = fold_ea_into_operand(g, ptr_op, ea.offset, owned_index, log2_scale,
- access_ty, 1, &owned_base);
+ mem_op = place_operand_for_access(base.op, access_ty);
}
- /* Source-local tracking. Only the plain no-EA scalar-to-scalar store can
- * fold into a tracked constant; everything else clears tracking. */
- if (is_lvalue && base.source_local != CFREE_CG_LOCAL_NONE) {
- if (!has_index && !is_bitfield && ea.offset == 0 && src.kind == OPK_IMM) {
+ /* Source-local tracking: only a plain scalar-to-scalar store can fold into a
+ * tracked constant; everything else clears tracking. */
+ if (base.source_local != CFREE_CG_LOCAL_NONE) {
+ if (!is_bitfield && src.kind == OPK_IMM) {
api_local_const_store(g, base.source_local, access, src.v.imm);
} else {
api_local_const_clear(api_local_from_handle(g, base.source_local));
}
- } else if (is_lvalue &&
- (base.op.kind == OPK_INDIRECT || base.op.kind == OPK_GLOBAL ||
- (access.flags & CFREE_CG_MEM_VOLATILE))) {
- api_local_const_memory_boundary(g);
- } else if (!is_lvalue) {
- /* Store through pointer is a memory write -- be conservative. */
+ } else if (base.op.kind == OPK_INDIRECT || base.op.kind == OPK_GLOBAL ||
+ (access.flags & CFREE_CG_MEM_VOLATILE)) {
api_local_const_memory_boundary(g);
}
@@ -940,9 +583,9 @@ void cfree_cg_store(CfreeCg* g, CfreeCgMemAccess access, CfreeCgEffAddr ea) {
api_release(g, &base);
api_release(g, &rv);
if (owned_base != CG_LOCAL_NONE) api_release_temp_local(g, owned_base);
- if (owned_index != CG_LOCAL_NONE) api_release_temp_local(g, owned_index);
}
+
/* ============================================================
* Stack manipulation
* ============================================================ */
diff --git a/test/api/cg_switch_test.c b/test/api/cg_switch_test.c
@@ -144,8 +144,7 @@ static void build_switch_fn(CfreeCompiler* c, CfreeCgTypeId i32_ty,
cfree_cg_load(
cg,
(CfreeCgMemAccess){.type = sh->selector_type,
- .align = cfree_cg_type_align(c, sh->selector_type)},
- (CfreeCgEffAddr){0, 0});
+ .align = cfree_cg_type_align(c, sh->selector_type)});
memset(&sw, 0, sizeof sw);
sw.selector_type = sh->selector_type;
sw.default_label = default_lbl;
diff --git a/test/api/cg_type_test.c b/test/api/cg_type_test.c
@@ -146,13 +146,13 @@ static void exercise_cg_handles(CfreeCompiler* c, CfreeCgTypeId i32_ty,
cfree_cg_push_local(cg, local);
cfree_cg_push_local_addr(cg, param);
- /* removed: cfree_cg_indirect no longer needed */
- cfree_cg_load(cg, mem, (CfreeCgEffAddr){0, 0});
- cfree_cg_store(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_deref(cg, 0); /* pointer VALUE -> PLACE for the load */
+ cfree_cg_load(cg, mem);
+ cfree_cg_store(cg, mem);
cfree_cg_push_local_addr(cg, local);
- /* removed: cfree_cg_indirect no longer needed */
- cfree_cg_load(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_deref(cg, 0); /* pointer VALUE -> PLACE for the load */
+ cfree_cg_load(cg, mem);
cfree_cg_ret(cg);
cfree_cg_func_end(cg);
@@ -218,9 +218,9 @@ static void exercise_cg_scalar_local(CfreeCompiler* c, CfreeCgTypeId i32_ty,
cfree_cg_push_local(cg, local);
cfree_cg_push_int(cg, 40, i32_ty);
- cfree_cg_store(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(cg, mem);
cfree_cg_push_local(cg, local);
- cfree_cg_load(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(cg, mem);
cfree_cg_push_int(cg, 2, i32_ty);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
cfree_cg_ret(cg);
@@ -288,10 +288,10 @@ static void exercise_cg_late_local_addr(CfreeCompiler* c, CfreeCgTypeId i32_ty,
cfree_cg_push_local(cg, local);
cfree_cg_push_int(cg, 41, i32_ty);
- cfree_cg_store(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(cg, mem);
cfree_cg_push_local_addr(cg, local);
- /* removed: cfree_cg_indirect no longer needed */
- cfree_cg_load(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_deref(cg, 0); /* pointer VALUE -> PLACE for the load */
+ cfree_cg_load(cg, mem);
cfree_cg_push_int(cg, 1, i32_ty);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
cfree_cg_ret(cg);
@@ -549,7 +549,7 @@ static uint32_t cg_emit_delayed_chain(CfreeCompiler* c, CfreeCgTypeId i32_ty,
mem.type = i32_ty;
mem.align = cfree_cg_type_align(c, i32_ty);
cfree_cg_push_local(cg, param);
- cfree_cg_load(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(cg, mem);
cfree_cg_push_int(cg, 40, i32_ty);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
cfree_cg_push_int(cg, 2, i32_ty);
@@ -622,7 +622,7 @@ static uint32_t cg_emit_unary_chain(CfreeCompiler* c, CfreeCgTypeId i32_ty,
mem.type = i32_ty;
mem.align = cfree_cg_type_align(c, i32_ty);
cfree_cg_push_local(cg, param);
- cfree_cg_load(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(cg, mem);
cfree_cg_int_unop(cg, CFREE_CG_INT_BNOT, 0);
cfree_cg_int_unop(cg, CFREE_CG_INT_BNOT, 0);
cfree_cg_ret(cg);
@@ -689,9 +689,9 @@ static uint32_t cg_emit_local_shadow(CfreeCompiler* c, CfreeCgTypeId i32_ty,
mem.align = cfree_cg_type_align(c, i32_ty);
cfree_cg_push_local(cg, local);
cfree_cg_push_int(cg, 40, i32_ty);
- cfree_cg_store(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(cg, mem);
cfree_cg_push_local(cg, local);
- cfree_cg_load(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(cg, mem);
cfree_cg_push_int(cg, 2, i32_ty);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
cfree_cg_ret(cg);
@@ -762,7 +762,7 @@ static uint32_t cg_emit_delayed_cmp(CfreeCompiler* c, CfreeCgTypeId i32_ty,
mem.type = i32_ty;
mem.align = cfree_cg_type_align(c, i32_ty);
cfree_cg_push_local(cg, param);
- cfree_cg_load(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(cg, mem);
cfree_cg_push_int(cg, 40, i32_ty);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
cfree_cg_push_int(cg, 2, i32_ty);
@@ -842,14 +842,14 @@ static uint32_t cg_emit_delayed_store(CfreeCompiler* c, CfreeCgTypeId i32_ty,
mem.align = cfree_cg_type_align(c, i32_ty);
cfree_cg_push_local(cg, local);
cfree_cg_push_local(cg, param);
- cfree_cg_load(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(cg, mem);
cfree_cg_push_int(cg, 40, i32_ty);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
cfree_cg_push_int(cg, 2, i32_ty);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_store(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(cg, mem);
cfree_cg_push_local(cg, local);
- cfree_cg_load(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(cg, mem);
cfree_cg_ret(cg);
cfree_cg_func_end(cg);
@@ -925,12 +925,12 @@ static uint32_t cg_emit_delayed_pressure(CfreeCompiler* c, CfreeCgTypeId i32_ty,
for (uint32_t i = 0; i + 1 < NPARAMS; ++i) {
cfree_cg_push_local(cg, params[i]);
- cfree_cg_load(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(cg, mem);
cfree_cg_push_int(cg, 1, i32_ty);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
}
cfree_cg_push_local(cg, params[NPARAMS - 1]);
- cfree_cg_load(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(cg, mem);
cfree_cg_drop(cg);
for (uint32_t i = 0; i + 1 < NPARAMS; ++i) cfree_cg_drop(cg);
cfree_cg_push_int(cg, 0, i32_ty);
@@ -1009,7 +1009,7 @@ static uint32_t cg_emit_local_shadow_boundary(CfreeCompiler* c,
cfree_cg_push_local(cg, local);
cfree_cg_push_int(cg, 40, i32_ty);
- cfree_cg_store(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(cg, mem);
switch (boundary) {
case CG_SHADOW_LABEL: {
@@ -1031,20 +1031,20 @@ static uint32_t cg_emit_local_shadow_boundary(CfreeCompiler* c,
case CG_SHADOW_VOLATILE:
mem.flags = CFREE_CG_MEM_VOLATILE;
cfree_cg_push_local(cg, local);
- cfree_cg_load(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(cg, mem);
cfree_cg_drop(cg);
mem.flags = 0;
break;
case CG_SHADOW_INDIRECT_STORE:
cfree_cg_push_local_addr(cg, local);
- /* removed: cfree_cg_indirect no longer needed */
+ cfree_cg_deref(cg, 0); /* pointer VALUE -> PLACE for the store */
cfree_cg_push_int(cg, 41, i32_ty);
- cfree_cg_store(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(cg, mem);
break;
}
cfree_cg_push_local(cg, local);
- cfree_cg_load(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(cg, mem);
cfree_cg_push_int(cg, 2, i32_ty);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
cfree_cg_ret(cg);
@@ -1118,12 +1118,12 @@ static uint32_t cg_emit_local_shadow_partial_store(CfreeCompiler* c,
cfree_cg_push_local(cg, local);
cfree_cg_push_int(cg, 40, i32_ty);
- cfree_cg_store(cg, mem_i32, (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(cg, mem_i32);
cfree_cg_push_local(cg, local);
cfree_cg_push_int(cg, 7, i8_ty);
- cfree_cg_store(cg, mem_i8, (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(cg, mem_i8);
cfree_cg_push_local(cg, local);
- cfree_cg_load(cg, mem_i32, (CfreeCgEffAddr){0, 0});
+ cfree_cg_load(cg, mem_i32);
cfree_cg_push_int(cg, 2, i32_ty);
cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
cfree_cg_ret(cg);
@@ -1258,7 +1258,7 @@ static void run_bad_scalar_access_to_aggregate(void* arg) {
mem.align = cfree_cg_type_align(ctx->c, ctx->i32_ty);
cfree_cg_push_local(cg, local);
cfree_cg_push_int(cg, 42, ctx->i32_ty);
- cfree_cg_store(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(cg, mem);
}
static void run_bad_store_value_size(void* arg) {
@@ -1276,7 +1276,7 @@ static void run_bad_store_value_size(void* arg) {
mem.align = cfree_cg_type_align(ctx->c, ctx->i64_ty);
cfree_cg_push_local(cg, local);
cfree_cg_push_int(cg, 42, ctx->i32_ty);
- cfree_cg_store(cg, mem, (CfreeCgEffAddr){0, 0});
+ cfree_cg_store(cg, mem);
}
static void exercise_cg_memory_mismatch_diags(CfreeCompiler* c,