kit

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

commit f1e91a7c2257e38b8244f99c4066cabea0336507
parent 50f2be4ee7f358e1fa5abd6b3808d6a4c4742cd6
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Mon,  1 Jun 2026 13:04:25 -0700

frontend: replace the cg_public_compat.h macro shim with direct pcg_* calls

The C parser drove codegen through a family of cg_*(g, ...) forwarding
macros in cg_public_compat.h -- a compatibility shim that mimicked an
older, richer CG-handle API on top of today's leaner cfree_cg_*. Every
macro ignored its `g` argument (always p->cg) and forwarded to the real
pcg_* adapter, so the layer bought nothing but indirection and a
misleading "compat" name.

- Promote the 13 macros that expanded inline (emit guard + type-stack
  mirroring) to real pcg_* functions in cg_adapter.c: set_loc, func_end,
  dup, swap, drop, va_start/end/copy, label_new/place, jump,
  branch_true/false.
- Rewrite all ~530 call sites: cg_X(p->cg, ...) -> pcg_X(p, ...).
- Rename cg_public_compat.h -> cg_adapter.h to match its companion
  cg_adapter.c; delete the 44 forwarding macros and the unused CGScope
  typedef.
- Drop a vestigial cg_public_compat.h include from decl.c (it only used
  <cfree/cg.h> symbols).
- Update doc/FRONTENDS.md and doc/INTERFACES.md to the new name.

No behavior change: each promoted function is byte-for-byte equivalent to
the macro it replaced. test-parse 3784/0/0, test-toy 1338/0/24,
smoke-x64 green; debug (-Werror + ASan/UBSan) and release builds clean.

Diffstat:
Mdoc/FRONTENDS.md | 15++++++---------
Mdoc/INTERFACES.md | 2+-
Mlang/c/decl/decl.c | 2--
Mlang/c/parse/cg_adapter.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alang/c/parse/cg_adapter.h | 334+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dlang/c/parse/cg_public_compat.h | 399-------------------------------------------------------------------------------
Mlang/c/parse/parse.c | 68++++++++++++++++++++++++++++++++++----------------------------------
Mlang/c/parse/parse.h | 2+-
Mlang/c/parse/parse_expr.c | 720++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mlang/c/parse/parse_init.c | 84++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mlang/c/parse/parse_stmt.c | 158++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mlang/c/parse/parse_type.c | 10+++++-----
12 files changed, 926 insertions(+), 932 deletions(-)

diff --git a/doc/FRONTENDS.md b/doc/FRONTENDS.md @@ -195,16 +195,15 @@ side holds the static types and lvalue bookkeeping needed to drive the next op correctly (signedness for division/compare/shift, pointer-element size for arithmetic, bit-field metadata for loads/stores, and so on). -### The cg_public_compat.h coupling point +### The cg_adapter.h coupling point -`lang/c/parse/cg_adapter.c` and its header `cg_public_compat.h` are the real +`lang/c/parse/cg_adapter.c` and its header `cg_adapter.h` are the real parser <-> codegen seam, and the most load-bearing design decision in the C -frontend. The header defines a family of `pcg_*` helpers and a set of -`cg_*` macros that look like thin wrappers over the public `cfree_cg_*` API but -do two extra jobs on every call: +frontend. The header declares a family of `pcg_*` helpers that look like thin +wrappers over the public `cfree_cg_*` API but do two extra jobs on every call: - **They keep the parser's typed value stack in lockstep with the CG stack.** - `cg_dup`/`cg_swap`/`cg_drop` mirror the structural op onto the type stack; + `pcg_dup`/`pcg_swap`/`pcg_drop` mirror the structural op onto the type stack; `pcg_push_int` / `pcg_load` / `pcg_binop` / `pcg_convert` push, retag, or pop type-stack entries alongside emitting the CG op. The parser never calls `cfree_cg_*` for stack-affecting ops directly — it goes through `pcg_*` so @@ -221,9 +220,7 @@ do two extra jobs on every call: a pointer. The implication: **the C frontend's lowering strategy is encoded in this -shim, not in the public CG contract.** The compatibility-header name reflects -its history — it preserves the call shapes of an older richer CG surface on -top of today's leaner one — but in practice it is where C-specific decisions +adapter, not in the public CG contract.** It is where C-specific decisions (lvalue-as-effective-address, lazy load/store/addr, the typed shadow stack) are concentrated. A change to how C lowers indirection lands here, not in the backends. (`pcg_emit_enabled` also lets the parser run constant-folding / diff --git a/doc/INTERFACES.md b/doc/INTERFACES.md @@ -297,7 +297,7 @@ them — plus the two documented internal exceptions noted in the boundary map. | wasm (`lang/wasm/`) | `cfree_wasm_frontend_vtable` (`wasm.h`) | reaches `wasm/wasm.h` (shared module model) | **Frontend-tier notes:** -- `lang/c/parse/cg_public_compat.h` is a compatibility shim that wraps `cg.h` +- `lang/c/parse/cg_adapter.h` is the C parser's codegen adapter: it wraps `cg.h` with C-semantic sugar (lvalue auxiliaries, the type stack, `pcg_*` helpers). It is the real coupling point between the C parser and codegen, and it is worth understanding when working in either: it carries the C frontend's own policy on diff --git a/lang/c/decl/decl.c b/lang/c/decl/decl.c @@ -18,8 +18,6 @@ #include <string.h> -#include "parse/cg_public_compat.h" - struct DeclTable { Compiler* c; Pool* pool; diff --git a/lang/c/parse/cg_adapter.c b/lang/c/parse/cg_adapter.c @@ -141,6 +141,24 @@ void pcg_rot3_type(Parser* p) { } } +/* Structural CG ops that must keep the parser's typed shadow stack in lockstep + * with the CG stack: each emits the CG op (when codegen is enabled) and mirrors + * the same structural effect onto the type stack. */ +void pcg_dup(Parser* p) { + if (pcg_emit_enabled(p)) cfree_cg_dup(p->cg); + pcg_dup_type(p); +} + +void pcg_swap(Parser* p) { + if (pcg_emit_enabled(p)) cfree_cg_swap(p->cg); + pcg_swap_type(p); +} + +void pcg_drop(Parser* p) { + if (pcg_emit_enabled(p)) cfree_cg_drop(p->cg); + pcg_drop_type(p); +} + PcgLvAux* pcg_top_lv_aux(Parser* p) { return p->cg_type_sp ? &p->cg_lv_aux[p->cg_type_sp - 1u] : NULL; } @@ -396,6 +414,14 @@ void pcg_func_begin(Parser* p, const CGFuncDesc* fd) { } } +void pcg_func_end(Parser* p) { + if (pcg_emit_enabled(p)) cfree_cg_func_end(p->cg); +} + +void pcg_set_loc(Parser* p, SrcLoc loc) { + if (pcg_emit_enabled(p)) cfree_cg_set_loc(p->cg, loc); +} + void pcg_push_int(Parser* p, i64 v, const Type* ty) { if (pcg_emit_enabled(p)) { cfree_cg_push_int(p->cg, (uint64_t)v, pcg_tid(p, ty)); @@ -554,6 +580,32 @@ void pcg_computed_goto(Parser* p, const CGLabel* targets, u32 ntargets) { pcg_drop_type(p); } +/* ---- Control flow ---- + * + * Labels are pure bookkeeping handles, so pcg_label_new always mints one (it + * has no codegen side effect to suppress). The placement / jump / branch ops + * gate on emit; the conditional branches also pop the tested value off the + * type stack to mirror the CG-side consume. */ +CGLabel pcg_label_new(Parser* p) { return cfree_cg_label_new(p->cg); } + +void pcg_label_place(Parser* p, CGLabel l) { + if (pcg_emit_enabled(p)) cfree_cg_label_place(p->cg, l); +} + +void pcg_jump(Parser* p, CGLabel l) { + if (pcg_emit_enabled(p)) cfree_cg_jump(p->cg, l); +} + +void pcg_branch_true(Parser* p, CGLabel l) { + if (pcg_emit_enabled(p)) cfree_cg_branch_true(p->cg, l); + pcg_drop_type(p); +} + +void pcg_branch_false(Parser* p, CGLabel l) { + if (pcg_emit_enabled(p)) cfree_cg_branch_false(p->cg, l); + pcg_drop_type(p); +} + /* Store [lv, rv] -> [rv]. The expression-value of an assignment is the * assigned rvalue, so the store sequence must leave a copy of rv on TOS. */ void pcg_store(Parser* p) { @@ -1004,6 +1056,18 @@ void pcg_va_arg(Parser* p, const Type* ty) { pcg_push_type(p, ty); } +void pcg_va_start(Parser* p) { + if (pcg_emit_enabled(p)) cfree_cg_vararg_start(p->cg); +} + +void pcg_va_end(Parser* p) { + if (pcg_emit_enabled(p)) cfree_cg_vararg_end(p->cg); +} + +void pcg_va_copy(Parser* p) { + if (pcg_emit_enabled(p)) cfree_cg_vararg_copy(p->cg); +} + void pcg_atomic_load(Parser* p, MemOrder ord) { const Type* pty = pcg_top_type(p); const Type* ty = (pty && pty->kind == TY_PTR) ? pty->ptr.pointee : pty; diff --git a/lang/c/parse/cg_adapter.h b/lang/c/parse/cg_adapter.h @@ -0,0 +1,334 @@ +#ifndef CFREE_PARSE_CG_ADAPTER_H +#define CFREE_PARSE_CG_ADAPTER_H + +/* cg_adapter.h — the C parser <-> codegen seam. + * + * Declares the `pcg_*` helpers (implemented in cg_adapter.c) plus the + * C-frontend types they operate on. Every `pcg_*` call keeps the parser's + * typed shadow stack (cg_type_stack / cg_value_flags / cg_lv_aux in struct + * Parser) in lockstep with the public CG stack and folds C lvalue chains into + * single effective-address memops; the parser never calls stack-affecting + * `cfree_cg_*` ops directly. See doc/FRONTENDS.md for the design. */ + +#include <cfree/cg.h> + +#include "c_support.h" +#include "type/type.h" + +typedef CfreeCg CG; +typedef CfreeCgLabel CGLabel; +typedef CfreeCgLocal FrameSlot; + +#define FRAME_SLOT_NONE CFREE_CG_LOCAL_NONE +#define OBJ_GROUP_NONE 0u + +/* Lvalue auxiliary state, carried parallel to cg_type_stack / cg_value_flags. + * + * The C parser tracks one logical "C-language value" per stack slot. When that + * slot is a C-language lvalue (PCG_VALUE_LVALUE), the aux below records the + * pending effective-address modifiers and bit-field metadata that the next + * load / store / addr will fold onto the CG memop. + * + * Lvalue chains (`s.f`, `a[i].g`, etc.) accumulate into this aux instead of + * emitting per-step CG ops: there is no CG-level `field` / `index` / + * `addr_offset` op anymore. Field offsets bump `offset`; subscripts set + * `scale` and leave the evaluated index value on the CG stack just above the + * lvalue base. Bit-field selections fill `bit_*`. The aux is consumed by the + * very next pcg_load / pcg_store / pcg_addr that crosses the slot. + * + * `base_kind` records what the CG-stack base under this lvalue actually is — + * either an OPK_LOCAL produced by push_local (PCG_LV_BASE_LOCAL) or a + * pointer rvalue from push_symbol_addr, push_local_addr, dereference, or + * pointer arithmetic (PCG_LV_BASE_POINTER_RV). Stream A's CG-side memops + * accept either shape uniformly; pcg_addr uses the distinction to decide + * whether to emit cfree_cg_addr or treat the base as already-a-pointer. */ +typedef enum PcgLvBaseKind { + PCG_LV_BASE_LOCAL = 0, + PCG_LV_BASE_POINTER_RV = 1, +} PcgLvBaseKind; + +typedef struct PcgLvAux { + i64 offset; + u32 scale; + u16 bit_offset; + u16 bit_width; + u32 storage_size; + u8 bit_signed; + u8 base_kind; /* PcgLvBaseKind */ + u8 is_subobject; /* lvalue is a member/element of a larger CG object */ + u8 pad[5]; +} PcgLvAux; + +typedef enum BinOp { + BO_IADD, + BO_ISUB, + BO_IMUL, + BO_SDIV, + BO_UDIV, + BO_SREM, + BO_UREM, + BO_FADD, + BO_FSUB, + BO_FMUL, + BO_FDIV, + BO_AND, + BO_OR, + BO_XOR, + BO_SHL, + BO_SHR_S, + BO_SHR_U, +} BinOp; + +typedef enum UnOp { + UO_NEG, + UO_NOT, + UO_BNOT, +} UnOp; + +typedef enum CmpOp { + CMP_EQ, + CMP_NE, + CMP_LT_S, + CMP_LE_S, + CMP_GT_S, + CMP_GE_S, + CMP_LT_U, + CMP_LE_U, + CMP_GT_U, + CMP_GE_U, + CMP_LT_F, + CMP_LE_F, + CMP_GT_F, + CMP_GE_F, +} CmpOp; + +typedef enum AtomicOp { + AO_XCHG, + AO_ADD, + AO_SUB, + AO_AND, + AO_OR, + AO_XOR, + AO_NAND, +} AtomicOp; + +typedef enum MemOrder { + MO_RELAXED, + MO_CONSUME, + MO_ACQUIRE, + MO_RELEASE, + MO_ACQ_REL, + MO_SEQ_CST, +} MemOrder; + +typedef enum IntrinKind { + INTRIN_NONE = 0, + INTRIN_POPCOUNT, + INTRIN_CTZ, + INTRIN_CLZ, + INTRIN_BSWAP16, + INTRIN_BSWAP32, + INTRIN_BSWAP64, + INTRIN_MEMCPY, + INTRIN_MEMMOVE, + INTRIN_MEMSET, + INTRIN_PREFETCH, + INTRIN_ASSUME_ALIGNED, + INTRIN_EXPECT, + INTRIN_UNREACHABLE, + INTRIN_TRAP, + INTRIN_SETJMP, + INTRIN_LONGJMP, + INTRIN_SADD_OVERFLOW, + INTRIN_UADD_OVERFLOW, + INTRIN_SSUB_OVERFLOW, + INTRIN_USUB_OVERFLOW, + INTRIN_SMUL_OVERFLOW, + INTRIN_UMUL_OVERFLOW, +} IntrinKind; + +typedef enum AsmDir { ASM_IN, ASM_OUT, ASM_INOUT } AsmDir; + +typedef struct AsmConstraint { + const char* str; + Sym name; + const Type* type; + u8 dir; + u8 pad[3]; +} AsmConstraint; + +typedef enum FrameSlotKind { + FS_LOCAL, + FS_PARAM, + FS_SPILL, + FS_SRET, + FS_ALLOCA, +} FrameSlotKind; + +typedef enum FrameSlotFlag { + FSF_NONE = 0, + FSF_ADDR_TAKEN = 1u << 0, + FSF_VOLATILE = 1u << 1, +} FrameSlotFlag; + +typedef struct FrameSlotDesc { + const Type* type; + Sym name; + SrcLoc loc; + u32 size; + u32 align; + u8 kind; + u8 pad; + u16 flags; +} FrameSlotDesc; + +typedef struct CGParamDesc { + u32 index; + Sym name; + const Type* type; + FrameSlot slot; + const void* abi; + const void* incoming; + u32 nincoming; + SrcLoc loc; +} CGParamDesc; + +typedef enum CGFuncDescFlag { + CGFD_NONE = 0, + CGFD_NORETURN = 1u << 0, +} CGFuncDescFlag; + +typedef struct CGFuncDesc { + ObjSymId sym; + ObjSecId text_section_id; + u32 group_id; + const Type* fn_type; + const void* abi; + const CGParamDesc* params; + u32 nparams; + SrcLoc loc; + u32 flags; + CfreeCgInlinePolicy inline_policy; +} CGFuncDesc; + +typedef struct Parser Parser; + +CfreeCgTypeId pcg_tid(Parser*, const Type*); +CfreeCgMemAccess pcg_mem(Parser*, const Type*); +const Type* pcg_top_type(Parser*); +const Type* pcg_top2_type(Parser*); +void pcg_retag_top(Parser*, const Type*); +void pcg_push_type(Parser*, const Type*); +void pcg_drop_type(Parser*); +void pcg_dup_type(Parser*); +void pcg_swap_type(Parser*); +/* Structural CG ops that also mirror onto the typed shadow stack. */ +void pcg_dup(Parser*); +void pcg_swap(Parser*); +void pcg_drop(Parser*); +int pcg_top_is_bitfield(Parser*); +void pcg_set_top_bitfield(Parser*); +int pcg_top_is_register(Parser*); +void pcg_set_top_register(Parser*); +int pcg_top_is_lvalue(Parser*); +int pcg_top_is_modifiable_lvalue(Parser*); +int pcg_top_is_null_ptr_const(Parser*); +void pcg_set_top_lvalue(Parser*); +void pcg_rot3_type(Parser*); +int pcg_emit_enabled(Parser*); +void pcg_codegen_suppress_push(Parser*); +void pcg_codegen_suppress_pop(Parser*); + +CfreeCgIntBinOp pcg_int_binop(BinOp); +CfreeCgFpBinOp pcg_fp_binop(BinOp); +CfreeCgIntCmpOp pcg_int_cmp(CmpOp); +CfreeCgFpCmpOp pcg_fp_cmp(CmpOp); +CfreeCgAtomicOp pcg_atomic_op(AtomicOp); +CfreeCgMemOrder pcg_mem_order(MemOrder); +int pcg_type_is_fp(const Type*); +int pcg_type_is_signed(const Type*); + +FrameSlot pcg_local(Parser*, const FrameSlotDesc*); +FrameSlot pcg_param_slot(Parser*, u32, const FrameSlotDesc*); +void pcg_param(Parser*, const CGParamDesc*); +void pcg_func_begin(Parser*, const CGFuncDesc*); +void pcg_func_end(Parser*); +void pcg_set_loc(Parser*, SrcLoc); +void pcg_push_int(Parser*, i64, const Type*); +void pcg_push_float(Parser*, double, const Type*); +void pcg_push_local_typed(Parser*, FrameSlot, const Type*); +void pcg_push_global(Parser*, ObjSymId, const Type*); +void pcg_load(Parser*); +void pcg_addr(Parser*); +void pcg_push_label_addr(Parser*, CGLabel); +void pcg_computed_goto(Parser*, const CGLabel*, u32); +CGLabel pcg_label_new(Parser*); +void pcg_label_place(Parser*, CGLabel); +void pcg_jump(Parser*, CGLabel); +void pcg_branch_true(Parser*, CGLabel); +void pcg_branch_false(Parser*, CGLabel); +void pcg_store(Parser*); +void pcg_deref(Parser*, const Type*); + +/* ---- Lvalue auxiliary access ---- + * + * pcg_top_lv_aux returns a mutable pointer to TOS's lvalue aux, used by + * parse_postfix and the initializer / compound-assignment paths to fold + * field offsets and bit-field metadata inline. Returns NULL if the parser + * stack is empty; behavior on a non-lvalue TOS is the caller's responsibility + * (parse_postfix has already validated lvalueness before calling). */ +PcgLvAux* pcg_top_lv_aux(Parser*); +PcgLvAux* pcg_lv_aux_at(Parser*, u32 depth); + +/* ---- Lvalue chain helpers ---- + * + * Each maps directly to the canonical encodings in doc/INDIRECT.md without + * emitting any intermediate field / index / addr_offset CG op. Field offsets + * and array scales are accumulated on the TOS lvalue's aux; the next + * pcg_load / pcg_store / pcg_addr consumes them. */ + +/* Fold `s.f` (or any path-resolved field selection) into the TOS lvalue. + * byte_offset is the cumulative offset within the record; ty is the field + * type; bf_* are bit-field metadata (bf_width == 0 for non-bitfields). The + * caller is responsible for verifying TOS is an lvalue of a record type. */ +void pcg_lv_member(Parser*, i64 byte_offset, const Type* field_ty, + u16 bf_offset, u16 bf_width, u32 bf_storage_size); + +/* Attach `[index]` to the TOS lvalue. PRECONDITION: the index value has just + * been pushed onto the CG stack (and parser stack) above the lvalue base; + * the parser stack therefore has [base_lv, index] at depth [1, 0]. This call + * records `scale = elem_size` on the base's aux, drops the index parser + * slot (leaving the index value on the CG stack for the eventual memop), + * and retags the surviving slot as elem_ty (lvalue). */ +void pcg_lv_subscript(Parser*, u32 elem_size, const Type* elem_ty); + +/* Decay an array lvalue at TOS into a pointer-to-element rvalue. Emits + * cfree_cg_addr (or a no-op for pointer-rvalue bases) and folds any pending + * EA modifiers into the resulting pointer via ptr arithmetic. After return, + * TOS is a pointer rvalue of type `*arr_ty->elem`. */ +void pcg_decay_array(Parser*, const Type* arr_ty); + +void pcg_binop(Parser*, BinOp); +void pcg_unop(Parser*, UnOp); +void pcg_cmp(Parser*, CmpOp); +void pcg_convert(Parser*, const Type*); +void pcg_inc_dec(Parser*, BinOp, int); +void pcg_call(Parser*, u32, const Type*); +void pcg_call_symbol(Parser*, CfreeCgSym, u32, const Type*); +void pcg_ret(Parser*, int); +void pcg_alloca(Parser*); +void pcg_va_arg(Parser*, const Type*); +void pcg_va_start(Parser*); +void pcg_va_end(Parser*); +void pcg_va_copy(Parser*); +void pcg_atomic_load(Parser*, MemOrder); +void pcg_atomic_store(Parser*, MemOrder); +void pcg_atomic_rmw(Parser*, AtomicOp, MemOrder); +void pcg_atomic_cas(Parser*, MemOrder, MemOrder); +void pcg_fence(Parser*, MemOrder); +void pcg_intrinsic_unary_to_int(Parser*, IntrinKind); +void pcg_intrinsic_void(Parser*, IntrinKind); +void pcg_inline_asm(Parser*, const char*, const AsmConstraint*, u32, + const AsmConstraint*, u32, const Sym*, u32); + +#endif diff --git a/lang/c/parse/cg_public_compat.h b/lang/c/parse/cg_public_compat.h @@ -1,399 +0,0 @@ -#ifndef CFREE_PARSE_CG_PUBLIC_COMPAT_H -#define CFREE_PARSE_CG_PUBLIC_COMPAT_H - -#include <cfree/cg.h> - -#include "c_support.h" -#include "type/type.h" - -typedef CfreeCg CG; -typedef CfreeCgLabel CGLabel; -typedef CfreeCgScope CGScope; -typedef CfreeCgLocal FrameSlot; - -#define FRAME_SLOT_NONE CFREE_CG_LOCAL_NONE -#define OBJ_GROUP_NONE 0u - -/* Lvalue auxiliary state, carried parallel to cg_type_stack / cg_value_flags. - * - * The C parser tracks one logical "C-language value" per stack slot. When that - * slot is a C-language lvalue (PCG_VALUE_LVALUE), the aux below records the - * pending effective-address modifiers and bit-field metadata that the next - * load / store / addr will fold onto the CG memop. - * - * Lvalue chains (`s.f`, `a[i].g`, etc.) accumulate into this aux instead of - * emitting per-step CG ops: there is no CG-level `field` / `index` / - * `addr_offset` op anymore. Field offsets bump `offset`; subscripts set - * `scale` and leave the evaluated index value on the CG stack just above the - * lvalue base. Bit-field selections fill `bit_*`. The aux is consumed by the - * very next pcg_load / pcg_store / pcg_addr that crosses the slot. - * - * `base_kind` records what the CG-stack base under this lvalue actually is — - * either an OPK_LOCAL produced by push_local (PCG_LV_BASE_LOCAL) or a - * pointer rvalue from push_symbol_addr, push_local_addr, dereference, or - * pointer arithmetic (PCG_LV_BASE_POINTER_RV). Stream A's CG-side memops - * accept either shape uniformly; pcg_addr uses the distinction to decide - * whether to emit cfree_cg_addr or treat the base as already-a-pointer. */ -typedef enum PcgLvBaseKind { - PCG_LV_BASE_LOCAL = 0, - PCG_LV_BASE_POINTER_RV = 1, -} PcgLvBaseKind; - -typedef struct PcgLvAux { - i64 offset; - u32 scale; - u16 bit_offset; - u16 bit_width; - u32 storage_size; - u8 bit_signed; - u8 base_kind; /* PcgLvBaseKind */ - u8 is_subobject; /* lvalue is a member/element of a larger CG object */ - u8 pad[5]; -} PcgLvAux; - -typedef enum BinOp { - BO_IADD, - BO_ISUB, - BO_IMUL, - BO_SDIV, - BO_UDIV, - BO_SREM, - BO_UREM, - BO_FADD, - BO_FSUB, - BO_FMUL, - BO_FDIV, - BO_AND, - BO_OR, - BO_XOR, - BO_SHL, - BO_SHR_S, - BO_SHR_U, -} BinOp; - -typedef enum UnOp { - UO_NEG, - UO_NOT, - UO_BNOT, -} UnOp; - -typedef enum CmpOp { - CMP_EQ, - CMP_NE, - CMP_LT_S, - CMP_LE_S, - CMP_GT_S, - CMP_GE_S, - CMP_LT_U, - CMP_LE_U, - CMP_GT_U, - CMP_GE_U, - CMP_LT_F, - CMP_LE_F, - CMP_GT_F, - CMP_GE_F, -} CmpOp; - -typedef enum AtomicOp { - AO_XCHG, - AO_ADD, - AO_SUB, - AO_AND, - AO_OR, - AO_XOR, - AO_NAND, -} AtomicOp; - -typedef enum MemOrder { - MO_RELAXED, - MO_CONSUME, - MO_ACQUIRE, - MO_RELEASE, - MO_ACQ_REL, - MO_SEQ_CST, -} MemOrder; - -typedef enum IntrinKind { - INTRIN_NONE = 0, - INTRIN_POPCOUNT, - INTRIN_CTZ, - INTRIN_CLZ, - INTRIN_BSWAP16, - INTRIN_BSWAP32, - INTRIN_BSWAP64, - INTRIN_MEMCPY, - INTRIN_MEMMOVE, - INTRIN_MEMSET, - INTRIN_PREFETCH, - INTRIN_ASSUME_ALIGNED, - INTRIN_EXPECT, - INTRIN_UNREACHABLE, - INTRIN_TRAP, - INTRIN_SETJMP, - INTRIN_LONGJMP, - INTRIN_SADD_OVERFLOW, - INTRIN_UADD_OVERFLOW, - INTRIN_SSUB_OVERFLOW, - INTRIN_USUB_OVERFLOW, - INTRIN_SMUL_OVERFLOW, - INTRIN_UMUL_OVERFLOW, -} IntrinKind; - -typedef enum AsmDir { ASM_IN, ASM_OUT, ASM_INOUT } AsmDir; - -typedef struct AsmConstraint { - const char* str; - Sym name; - const Type* type; - u8 dir; - u8 pad[3]; -} AsmConstraint; - -typedef enum FrameSlotKind { - FS_LOCAL, - FS_PARAM, - FS_SPILL, - FS_SRET, - FS_ALLOCA, -} FrameSlotKind; - -typedef enum FrameSlotFlag { - FSF_NONE = 0, - FSF_ADDR_TAKEN = 1u << 0, - FSF_VOLATILE = 1u << 1, -} FrameSlotFlag; - -typedef struct FrameSlotDesc { - const Type* type; - Sym name; - SrcLoc loc; - u32 size; - u32 align; - u8 kind; - u8 pad; - u16 flags; -} FrameSlotDesc; - -typedef struct CGParamDesc { - u32 index; - Sym name; - const Type* type; - FrameSlot slot; - const void* abi; - const void* incoming; - u32 nincoming; - SrcLoc loc; -} CGParamDesc; - -typedef enum CGFuncDescFlag { - CGFD_NONE = 0, - CGFD_NORETURN = 1u << 0, -} CGFuncDescFlag; - -typedef struct CGFuncDesc { - ObjSymId sym; - ObjSecId text_section_id; - u32 group_id; - const Type* fn_type; - const void* abi; - const CGParamDesc* params; - u32 nparams; - SrcLoc loc; - u32 flags; - CfreeCgInlinePolicy inline_policy; -} CGFuncDesc; - -typedef struct Parser Parser; - -CfreeCgTypeId pcg_tid(Parser*, const Type*); -CfreeCgMemAccess pcg_mem(Parser*, const Type*); -const Type* pcg_top_type(Parser*); -const Type* pcg_top2_type(Parser*); -void pcg_retag_top(Parser*, const Type*); -void pcg_push_type(Parser*, const Type*); -void pcg_drop_type(Parser*); -void pcg_dup_type(Parser*); -void pcg_swap_type(Parser*); -int pcg_top_is_bitfield(Parser*); -void pcg_set_top_bitfield(Parser*); -int pcg_top_is_register(Parser*); -void pcg_set_top_register(Parser*); -int pcg_top_is_lvalue(Parser*); -int pcg_top_is_modifiable_lvalue(Parser*); -int pcg_top_is_null_ptr_const(Parser*); -void pcg_set_top_lvalue(Parser*); -void pcg_rot3_type(Parser*); -int pcg_emit_enabled(Parser*); -void pcg_codegen_suppress_push(Parser*); -void pcg_codegen_suppress_pop(Parser*); - -CfreeCgIntBinOp pcg_int_binop(BinOp); -CfreeCgFpBinOp pcg_fp_binop(BinOp); -CfreeCgIntCmpOp pcg_int_cmp(CmpOp); -CfreeCgFpCmpOp pcg_fp_cmp(CmpOp); -CfreeCgAtomicOp pcg_atomic_op(AtomicOp); -CfreeCgMemOrder pcg_mem_order(MemOrder); -int pcg_type_is_fp(const Type*); -int pcg_type_is_signed(const Type*); - -FrameSlot pcg_local(Parser*, const FrameSlotDesc*); -FrameSlot pcg_param_slot(Parser*, u32, const FrameSlotDesc*); -void pcg_param(Parser*, const CGParamDesc*); -void pcg_func_begin(Parser*, const CGFuncDesc*); -void pcg_push_int(Parser*, i64, const Type*); -void pcg_push_float(Parser*, double, const Type*); -void pcg_push_local_typed(Parser*, FrameSlot, const Type*); -void pcg_push_global(Parser*, ObjSymId, const Type*); -void pcg_load(Parser*); -void pcg_addr(Parser*); -void pcg_push_label_addr(Parser*, CGLabel); -void pcg_computed_goto(Parser*, const CGLabel*, u32); -void pcg_store(Parser*); -void pcg_deref(Parser*, const Type*); - -/* ---- Lvalue auxiliary access ---- - * - * pcg_top_lv_aux returns a mutable pointer to TOS's lvalue aux, used by - * parse_postfix and the initializer / compound-assignment paths to fold - * field offsets and bit-field metadata inline. Returns NULL if the parser - * stack is empty; behavior on a non-lvalue TOS is the caller's responsibility - * (parse_postfix has already validated lvalueness before calling). */ -PcgLvAux* pcg_top_lv_aux(Parser*); -PcgLvAux* pcg_lv_aux_at(Parser*, u32 depth); - -/* ---- Lvalue chain helpers ---- - * - * Each maps directly to the canonical encodings in doc/INDIRECT.md without - * emitting any intermediate field / index / addr_offset CG op. Field offsets - * and array scales are accumulated on the TOS lvalue's aux; the next - * pcg_load / pcg_store / pcg_addr consumes them. */ - -/* Fold `s.f` (or any path-resolved field selection) into the TOS lvalue. - * byte_offset is the cumulative offset within the record; ty is the field - * type; bf_* are bit-field metadata (bf_width == 0 for non-bitfields). The - * caller is responsible for verifying TOS is an lvalue of a record type. */ -void pcg_lv_member(Parser*, i64 byte_offset, const Type* field_ty, - u16 bf_offset, u16 bf_width, u32 bf_storage_size); - -/* Attach `[index]` to the TOS lvalue. PRECONDITION: the index value has just - * been pushed onto the CG stack (and parser stack) above the lvalue base; - * the parser stack therefore has [base_lv, index] at depth [1, 0]. This call - * records `scale = elem_size` on the base's aux, drops the index parser - * slot (leaving the index value on the CG stack for the eventual memop), - * and retags the surviving slot as elem_ty (lvalue). */ -void pcg_lv_subscript(Parser*, u32 elem_size, const Type* elem_ty); - -/* Decay an array lvalue at TOS into a pointer-to-element rvalue. Emits - * cfree_cg_addr (or a no-op for pointer-rvalue bases) and folds any pending - * EA modifiers into the resulting pointer via ptr arithmetic. After return, - * TOS is a pointer rvalue of type `*arr_ty->elem`. */ -void pcg_decay_array(Parser*, const Type* arr_ty); - -void pcg_binop(Parser*, BinOp); -void pcg_unop(Parser*, UnOp); -void pcg_cmp(Parser*, CmpOp); -void pcg_convert(Parser*, const Type*); -void pcg_inc_dec(Parser*, BinOp, int); -void pcg_call(Parser*, u32, const Type*); -void pcg_call_symbol(Parser*, CfreeCgSym, u32, const Type*); -void pcg_ret(Parser*, int); -void pcg_alloca(Parser*); -void pcg_va_arg(Parser*, const Type*); -void pcg_atomic_load(Parser*, MemOrder); -void pcg_atomic_store(Parser*, MemOrder); -void pcg_atomic_rmw(Parser*, AtomicOp, MemOrder); -void pcg_atomic_cas(Parser*, MemOrder, MemOrder); -void pcg_fence(Parser*, MemOrder); -void pcg_intrinsic_unary_to_int(Parser*, IntrinKind); -void pcg_intrinsic_void(Parser*, IntrinKind); -void pcg_inline_asm(Parser*, const char*, const AsmConstraint*, u32, - const AsmConstraint*, u32, const Sym*, u32); - -#define cg_set_loc(g, loc) \ - do { \ - if (pcg_emit_enabled(p)) cfree_cg_set_loc((g), (loc)); \ - } while (0) -#define cg_local(g, fsd) pcg_local(p, (fsd)) -#define cg_param(g, pd) pcg_param(p, (pd)) -#define cg_func_begin(g, fd) pcg_func_begin(p, (fd)) -#define cg_func_end(g) \ - do { \ - if (pcg_emit_enabled(p)) cfree_cg_func_end((g)); \ - } while (0) -#define cg_push_int(g, v, ty) pcg_push_int(p, (v), (ty)) -#define cg_push_float(g, v, ty) pcg_push_float(p, (v), (ty)) -#define cg_push_local_typed(g, s, ty) pcg_push_local_typed(p, (s), (ty)) -#define cg_push_global(g, sym, ty) pcg_push_global(p, (sym), (ty)) -#define cg_load(g) pcg_load(p) -#define cg_addr(g) pcg_addr(p) -#define cg_dup(g) \ - do { \ - if (pcg_emit_enabled(p)) cfree_cg_dup((g)); \ - pcg_dup_type(p); \ - } while (0) -#define cg_swap(g) \ - do { \ - if (pcg_emit_enabled(p)) cfree_cg_swap((g)); \ - pcg_swap_type(p); \ - } while (0) -#define cg_drop(g) \ - do { \ - if (pcg_emit_enabled(p)) cfree_cg_drop((g)); \ - pcg_drop_type(p); \ - } while (0) -#define cg_store(g) pcg_store(p) -#define cg_deref(g, ty) pcg_deref(p, (ty)) -#define cg_top_type(g) pcg_top_type(p) -#define cg_top2_type(g) pcg_top2_type(p) -#define cg_retag_top(g, ty) pcg_retag_top(p, (ty)) -#define cg_binop(g, op) pcg_binop(p, (op)) -#define cg_unop(g, op) pcg_unop(p, (op)) -#define cg_cmp(g, op) pcg_cmp(p, (op)) -#define cg_convert(g, ty) pcg_convert(p, (ty)) -#define cg_inc_dec(g, op, post) pcg_inc_dec(p, (op), (post)) -#define cg_call(g, nargs, fn_type) pcg_call(p, (nargs), (fn_type)) -#define cg_ret(g, has_value) pcg_ret(p, (has_value)) -#define cg_alloca(g) pcg_alloca(p) -#define cg_va_start_(g) \ - do { \ - if (pcg_emit_enabled(p)) cfree_cg_vararg_start((g)); \ - } while (0) -#define cg_va_end_(g) \ - do { \ - if (pcg_emit_enabled(p)) cfree_cg_vararg_end((g)); \ - } while (0) -#define cg_va_copy_(g) \ - do { \ - if (pcg_emit_enabled(p)) cfree_cg_vararg_copy((g)); \ - } while (0) -#define cg_va_arg_(g, ty) pcg_va_arg(p, (ty)) -#define cg_atomic_load(g, ord) pcg_atomic_load(p, (ord)) -#define cg_atomic_store(g, ord) pcg_atomic_store(p, (ord)) -#define cg_atomic_rmw(g, op, ord) pcg_atomic_rmw(p, (op), (ord)) -#define cg_atomic_cas(g, succ, fail) pcg_atomic_cas(p, (succ), (fail)) -#define cg_fence(g, ord) pcg_fence(p, (ord)) -#define cg_intrinsic_unary_to_int(g, k) pcg_intrinsic_unary_to_int(p, (k)) -#define cg_intrinsic_void(g, k) pcg_intrinsic_void(p, (k)) -#define cg_label_new(g) cfree_cg_label_new((g)) -#define cg_label_place(g, l) \ - do { \ - if (pcg_emit_enabled(p)) cfree_cg_label_place((g), (l)); \ - } while (0) -#define cg_jump(g, l) \ - do { \ - if (pcg_emit_enabled(p)) cfree_cg_jump((g), (l)); \ - } while (0) -#define cg_branch_true(g, l) \ - do { \ - if (pcg_emit_enabled(p)) cfree_cg_branch_true((g), (l)); \ - pcg_drop_type(p); \ - } while (0) -#define cg_branch_false(g, l) \ - do { \ - if (pcg_emit_enabled(p)) cfree_cg_branch_false((g), (l)); \ - pcg_drop_type(p); \ - } while (0) -#define cg_inline_asm(g, tmpl, outs, nout, ins, nin, clob, nclob) \ - pcg_inline_asm(p, (tmpl), (outs), (nout), (ins), (nin), (clob), (nclob)) - -#endif diff --git a/lang/c/parse/parse.c b/lang/c/parse/parse.c @@ -451,7 +451,7 @@ FrameSlot make_local_aligned(Parser* p, Sym name, const Type* type, SrcLoc loc, fsd.align = (align_override > nat) ? align_override : nat; fsd.kind = FS_LOCAL; fsd.flags = FSF_NONE; - s = cg_local(p->cg, &fsd); + s = pcg_local(p, &fsd); reject_same_scope_redefinition(p, name, SEK_LOCAL, type); e = scope_define(p, name, SEK_LOCAL, type); e->v.slot = s; @@ -470,15 +470,15 @@ static FrameSlot make_vla_size_slot(Parser* p) { fsd.size = c_abi_sizeof(p->abi, fsd.type); fsd.align = c_abi_alignof(p->abi, fsd.type); fsd.kind = FS_LOCAL; - return cg_local(p->cg, &fsd); + return pcg_local(p, &fsd); } static void store_top_to_size_slot(Parser* p, FrameSlot slot) { - cg_push_local_typed(p->cg, slot, ty_size_t(p)); - cg_swap(p->cg); + pcg_push_local_typed(p, slot, ty_size_t(p)); + pcg_swap(p); coerce_top_to_lvalue(p); - cg_store(p->cg); - cg_drop(p->cg); + pcg_store(p); + pcg_drop(p); } static void reset_vla_pending(Parser* p) { @@ -523,20 +523,20 @@ static int build_vla_size(Parser* p, const Type* ty, u32* count_idx, if (count_dynamic || elem_dynamic) { FrameSlot byte_slot = make_vla_size_slot(p); - cg_set_loc(p->cg, loc); + pcg_set_loc(p, loc); if (count_dynamic) { - cg_push_local_typed(p->cg, count_slot, ty_size_t(p)); - cg_load(p->cg); + pcg_push_local_typed(p, count_slot, ty_size_t(p)); + pcg_load(p); } else { - cg_push_int(p->cg, (i64)ty->arr.count, ty_size_t(p)); + pcg_push_int(p, (i64)ty->arr.count, ty_size_t(p)); } if (elem_dynamic) { - cg_push_local_typed(p->cg, elem_slot, ty_size_t(p)); - cg_load(p->cg); + pcg_push_local_typed(p, elem_slot, ty_size_t(p)); + pcg_load(p); } else { - cg_push_int(p->cg, (i64)elem_static_size, ty_size_t(p)); + pcg_push_int(p, (i64)elem_static_size, ty_size_t(p)); } - cg_binop(p->cg, BO_IMUL); + pcg_binop(p, BO_IMUL); store_top_to_size_slot(p, byte_slot); *bounds = add_vla_bound(p, *bounds, ty, byte_slot, count_slot); *out_slot = byte_slot; @@ -849,14 +849,14 @@ static void parse_init_declarator(Parser* p, const DeclSpecs* specs) { bounds = specs->vla_bounds; } ptr_slot = make_local(p, name, ptr_ty, loc); - cg_set_loc(p->cg, loc); - cg_push_local_typed(p->cg, byte_slot, ty_size_t(p)); - cg_load(p->cg); - cg_alloca(p->cg); - cg_push_local_typed(p->cg, ptr_slot, ptr_ty); - cg_swap(p->cg); - cg_store(p->cg); - cg_drop(p->cg); + pcg_set_loc(p, loc); + pcg_push_local_typed(p, byte_slot, ty_size_t(p)); + pcg_load(p); + pcg_alloca(p); + pcg_push_local_typed(p, ptr_slot, ptr_ty); + pcg_swap(p); + pcg_store(p); + pcg_drop(p); sym_entry = scope_lookup(p, name); if (sym_entry && sym_entry->kind == SEK_LOCAL) { sym_entry->vla_byte_slot = byte_slot; @@ -880,7 +880,7 @@ static void parse_init_declarator(Parser* p, const DeclSpecs* specs) { SymEntry* e = scope_lookup_current(p, name); if (e && e->kind == SEK_LOCAL) e->storage = DS_REGISTER; } - cg_set_loc(p->cg, loc); + pcg_set_loc(p, loc); init_at(p, s, var_ty, 0, var_ty); return; } @@ -890,7 +890,7 @@ static void parse_init_declarator(Parser* p, const DeclSpecs* specs) { if (e && e->kind == SEK_LOCAL) e->storage = DS_REGISTER; } if (accept_punct(p, '=')) { - cg_set_loc(p->cg, loc); + pcg_set_loc(p, loc); if ((var_ty->kind == TY_STRUCT || var_ty->kind == TY_UNION) && !is_punct(&p->cur, '{')) { parse_assign_expr(p); @@ -899,19 +899,19 @@ static void parse_init_declarator(Parser* p, const DeclSpecs* specs) { var_ty->kind == TY_UNION) { init_at(p, s, var_ty, 0, var_ty); } else { - cg_push_local_typed(p->cg, s, var_ty); + pcg_push_local_typed(p, s, var_ty); parse_assign_expr(p); to_rvalue(p); { - const Type* rhs = cg_top_type(p->cg); + const Type* rhs = pcg_top_type(p); CSemCheck chk = c_sem_check_assignment(p->pool, var_ty, rhs, C_SEM_ASSIGN_INIT); if (!chk.ok) perr(p, "%.*s", CFREE_SLICE_ARG(cfree_slice_cstr(chk.message))); } coerce_top_to_lvalue(p); - cg_store(p->cg); - cg_drop(p->cg); + pcg_store(p); + pcg_drop(p); } } } @@ -1169,8 +1169,8 @@ static void parse_function_body(Parser* p, ObjSymId fsym, const Type* fn_ty, p->goto_labels = NULL; p->cur_switch = NULL; p->computed_goto_emitted = 0; - cg_set_loc(p->cg, fname_loc); - cg_func_begin(p->cg, &fd); + pcg_set_loc(p, fname_loc); + pcg_func_begin(p, &fd); for (u16 i = 0; i < nparams; ++i) { FrameSlotDesc fsd; @@ -1199,10 +1199,10 @@ static void parse_function_body(Parser* p, ObjSymId fsym, const Type* fn_ty, parse_compound_stmt(p); if (fn_ty->fn.ret && fn_ty->fn.ret->kind != TY_VOID && fn_ty->fn.ret->kind != TY_STRUCT && fn_ty->fn.ret->kind != TY_UNION) { - cg_push_int(p->cg, 0, fn_ty->fn.ret); - cg_ret(p->cg, 1); + pcg_push_int(p, 0, fn_ty->fn.ret); + pcg_ret(p, 1); } else { - cg_ret(p->cg, 0); + pcg_ret(p, 0); } for (GotoLabel* gl = p->goto_labels; gl; gl = gl->next) { if (!gl->placed) { @@ -1212,7 +1212,7 @@ static void parse_function_body(Parser* p, ObjSymId fsym, const Type* fn_ty, p->goto_labels = saved_goto_labels; p->cur_switch = saved_switch; p->computed_goto_emitted = saved_computed_goto; - cg_func_end(p->cg); + pcg_func_end(p); scope_pop(p); } diff --git a/lang/c/parse/parse.h b/lang/c/parse/parse.h @@ -2,7 +2,7 @@ #define CFREE_LANG_C_PARSE_H #include "decl/decl.h" -#include "parse/cg_public_compat.h" +#include "parse/cg_adapter.h" #include "pp/pp.h" /* C11 frontend. Reads preprocessed tokens, records C declarations, and drives diff --git a/lang/c/parse/parse_expr.c b/lang/c/parse/parse_expr.c @@ -942,11 +942,11 @@ static CConstInt cexpr_unary(Parser* p, SrcLoc loc) { } parse_unary(p); { - const Type* ty = cg_top_type(p->cg); + const Type* ty = pcg_top_type(p); if (pcg_top_is_bitfield(p)) perr(p, "sizeof bit-field"); require_sizeof_type(p, ty); i64 sz = (i64)c_abi_sizeof(p->abi, ty); - cg_drop(p->cg); + pcg_drop(p); return cint_make_u64(p, ty_size_t(p), (u64)sz); } } @@ -964,9 +964,9 @@ static CConstInt cexpr_unary(Parser* p, SrcLoc loc) { } parse_unary(p); { - const Type* ty = cg_top_type(p->cg); + const Type* ty = pcg_top_type(p); i64 al = (i64)c_abi_alignof(p->abi, ty); - cg_drop(p->cg); + pcg_drop(p); return cint_make_u64(p, ty_size_t(p), (u64)al); } } @@ -1059,7 +1059,7 @@ static FrameSlot vla_size_slot_for_type(VLABound* bounds, const Type* ty) { } void to_rvalue(Parser* p) { - const Type* t = cg_top_type(p->cg); + const Type* t = pcg_top_type(p); int is_lvalue = pcg_top_is_lvalue(p); if (t) { if (t->kind == TY_ARRAY) { @@ -1067,7 +1067,7 @@ void to_rvalue(Parser* p) { return; } if (t->kind == TY_FUNC) { - cg_addr(p->cg); + pcg_addr(p); return; } if (t->kind == TY_STRUCT || t->kind == TY_UNION) { @@ -1085,7 +1085,7 @@ void to_rvalue(Parser* p) { return; } } - if (is_lvalue) cg_load(p->cg); + if (is_lvalue) pcg_load(p); } /* ============================================================ @@ -1093,27 +1093,27 @@ void to_rvalue(Parser* p) { * ============================================================ */ void coerce_top_to_lvalue(Parser* p) { - const Type* src = cg_top_type(p->cg); - const Type* dst = cg_top2_type(p->cg); + const Type* src = pcg_top_type(p); + const Type* dst = pcg_top2_type(p); if (!src || !dst || src == dst) return; if (type_is_arith(src) && type_is_arith(dst)) { - cg_convert(p->cg, dst); + pcg_convert(p, dst); } else if (type_is_arith(src) && type_is_ptr(dst)) { - cg_convert(p->cg, dst); + pcg_convert(p, dst); } else if (type_is_ptr(src) && type_is_ptr(dst)) { - cg_convert(p->cg, dst); + pcg_convert(p, dst); } } void coerce_top_to_type(Parser* p, const Type* dst) { - const Type* src = cg_top_type(p->cg); + const Type* src = pcg_top_type(p); if (!src || !dst || src == dst) return; if (type_is_arith(src) && type_is_arith(dst)) { - cg_convert(p->cg, dst); + pcg_convert(p, dst); } else if (type_is_arith(src) && type_is_ptr(dst)) { - cg_convert(p->cg, dst); + pcg_convert(p, dst); } else if (type_is_ptr(src) && type_is_ptr(dst)) { - cg_convert(p->cg, dst); + pcg_convert(p, dst); } } @@ -1243,7 +1243,7 @@ static int parse_builtin_mem_call(Parser* p, Sym name, SrcLoc loc) { sym = pcg_emit_enabled(p) ? builtin_libcall_sym(p, libname, fn_ty) : CFREE_CG_SYM_NONE; - cg_set_loc(p->cg, loc); + pcg_set_loc(p, loc); pcg_call_symbol(p, sym, 3, fn_ty); return 1; } @@ -1278,9 +1278,9 @@ static int parse_builtin_clear_cache_call(Parser* p, Sym name, SrcLoc loc) { case CFREE_ARCH_WASM: case CFREE_ARCH_X86_32: case CFREE_ARCH_X86_64: - cg_drop(p->cg); - cg_drop(p->cg); - cg_push_int(p->cg, 0, ty_int(p)); + pcg_drop(p); + pcg_drop(p); + pcg_push_int(p, 0, ty_int(p)); return 1; default: break; @@ -1291,9 +1291,9 @@ static int parse_builtin_clear_cache_call(Parser* p, Sym name, SrcLoc loc) { fn_ty = type_func(p->pool, void_ty, params, 2, 0); sym = pcg_emit_enabled(p) ? builtin_libcall_sym(p, "__clear_cache", fn_ty) : CFREE_CG_SYM_NONE; - cg_set_loc(p->cg, loc); + pcg_set_loc(p, loc); pcg_call_symbol(p, sym, 2, fn_ty); - cg_push_int(p->cg, 0, ty_int(p)); + pcg_push_int(p, 0, ty_int(p)); return 1; } @@ -1303,7 +1303,7 @@ static MemOrder parse_atomic_mem_order(Parser* p) { } parse_assign_expr(p); to_rvalue(p); - cg_drop(p->cg); + pcg_drop(p); return MO_SEQ_CST; } @@ -1438,7 +1438,7 @@ static FrameSlot builtin_tmp_slot(Parser* p, const Type* ty) { fsd.size = c_abi_sizeof(p->abi, ty); fsd.align = c_abi_alignof(p->abi, ty); fsd.kind = FS_LOCAL; - return cg_local(p->cg, &fsd); + return pcg_local(p, &fsd); } static int parse_builtin_overflow_call(Parser* p, Sym name, SrcLoc loc) { @@ -1466,7 +1466,7 @@ static int parse_builtin_overflow_call(Parser* p, Sym name, SrcLoc loc) { expect_punct(p, ',', "',' in overflow builtin"); parse_assign_expr(p); to_rvalue(p); - ptr_ty = cg_top_type(p->cg); + ptr_ty = pcg_top_type(p); if (!ptr_ty || ptr_ty->kind != TY_PTR) { perr(p, "overflow builtin result argument must be a pointer"); } @@ -1477,12 +1477,12 @@ static int parse_builtin_overflow_call(Parser* p, Sym name, SrcLoc loc) { expect_punct(p, ')', "')' after overflow builtin"); ptr_slot = builtin_tmp_slot(p, ptr_ty); - cg_push_local_typed(p->cg, ptr_slot, ptr_ty); - cg_swap(p->cg); - cg_store(p->cg); - cg_drop(p->cg); + pcg_push_local_typed(p, ptr_slot, ptr_ty); + pcg_swap(p); + pcg_store(p); + pcg_drop(p); - cg_set_loc(p->cg, loc); + pcg_set_loc(p, loc); if (pcg_emit_enabled(p)) { cfree_cg_intrinsic(p->cg, info.intrin, 2, pcg_tid(p, op_ty)); } @@ -1492,20 +1492,20 @@ static int parse_builtin_overflow_call(Parser* p, Sym name, SrcLoc loc) { pcg_push_type(p, bool_ty); ov_slot = builtin_tmp_slot(p, bool_ty); - cg_push_local_typed(p->cg, ov_slot, bool_ty); - cg_swap(p->cg); - cg_store(p->cg); - cg_drop(p->cg); - - cg_push_local_typed(p->cg, ptr_slot, ptr_ty); - cg_load(p->cg); - cg_deref(p->cg, out_ty); - cg_swap(p->cg); - cg_store(p->cg); - cg_drop(p->cg); - - cg_push_local_typed(p->cg, ov_slot, bool_ty); - cg_load(p->cg); + pcg_push_local_typed(p, ov_slot, bool_ty); + pcg_swap(p); + pcg_store(p); + pcg_drop(p); + + pcg_push_local_typed(p, ptr_slot, ptr_ty); + pcg_load(p); + pcg_deref(p, out_ty); + pcg_swap(p); + pcg_store(p); + pcg_drop(p); + + pcg_push_local_typed(p, ov_slot, bool_ty); + pcg_load(p); return 1; } @@ -1517,15 +1517,15 @@ static int parse_builtin_isnan_call(Parser* p, Sym name, SrcLoc loc) { expect_punct(p, '(', "'(' after __builtin_isnan"); parse_assign_expr(p); to_rvalue(p); - arg_ty = cg_top_type(p->cg); + arg_ty = pcg_top_type(p); if (!type_is_fp(arg_ty)) { perr(p, "__builtin_isnan argument must have floating type"); } expect_punct(p, ')', "')' after __builtin_isnan"); - cg_set_loc(p->cg, loc); - cg_dup(p->cg); - cg_cmp(p->cg, CMP_NE); + pcg_set_loc(p, loc); + pcg_dup(p); + pcg_cmp(p, CMP_NE); return 1; } @@ -1553,8 +1553,8 @@ static int parse_builtin_inf_call(Parser* p, Sym name, SrcLoc loc) { advance(p); /* IDENT */ expect_punct(p, '(', "'(' after floating builtin"); expect_punct(p, ')', "')' after floating builtin"); - cg_set_loc(p->cg, loc); - cg_push_float(p->cg, __builtin_inf(), ty); + pcg_set_loc(p, loc); + pcg_push_float(p, __builtin_inf(), ty); return 1; } @@ -1573,45 +1573,45 @@ static int parse_builtin_fabs_call(Parser* p, Sym name, SrcLoc loc) { expect_punct(p, '(', "'(' after __builtin_fabs"); parse_assign_expr(p); to_rvalue(p); - if (!type_is_fp(cg_top_type(p->cg))) { + if (!type_is_fp(pcg_top_type(p))) { perr(p, "__builtin_fabs argument must have floating type"); } coerce_top_to_type(p, ty); expect_punct(p, ')', "')' after __builtin_fabs"); slot = builtin_tmp_slot(p, ty); - cg_push_local_typed(p->cg, slot, ty); - cg_swap(p->cg); - cg_store(p->cg); - cg_drop(p->cg); - - cg_set_loc(p->cg, loc); - cg_push_local_typed(p->cg, slot, ty); - cg_load(p->cg); - cg_push_float(p->cg, 0.0, ty); - cg_cmp(p->cg, CMP_LT_F); - L_nonneg = cg_label_new(p->cg); - cg_branch_false(p->cg, L_nonneg); - cg_push_local_typed(p->cg, slot, ty); - cg_push_local_typed(p->cg, slot, ty); - cg_load(p->cg); - cg_unop(p->cg, UO_NEG); - cg_store(p->cg); - cg_drop(p->cg); - cg_label_place(p->cg, L_nonneg); - cg_push_local_typed(p->cg, slot, ty); - cg_load(p->cg); - cg_push_float(p->cg, 0.0, ty); - cg_cmp(p->cg, CMP_EQ); - L_nonzero = cg_label_new(p->cg); - cg_branch_false(p->cg, L_nonzero); - cg_push_local_typed(p->cg, slot, ty); - cg_push_float(p->cg, 0.0, ty); - cg_store(p->cg); - cg_drop(p->cg); - cg_label_place(p->cg, L_nonzero); - cg_push_local_typed(p->cg, slot, ty); - cg_load(p->cg); + pcg_push_local_typed(p, slot, ty); + pcg_swap(p); + pcg_store(p); + pcg_drop(p); + + pcg_set_loc(p, loc); + pcg_push_local_typed(p, slot, ty); + pcg_load(p); + pcg_push_float(p, 0.0, ty); + pcg_cmp(p, CMP_LT_F); + L_nonneg = pcg_label_new(p); + pcg_branch_false(p, L_nonneg); + pcg_push_local_typed(p, slot, ty); + pcg_push_local_typed(p, slot, ty); + pcg_load(p); + pcg_unop(p, UO_NEG); + pcg_store(p); + pcg_drop(p); + pcg_label_place(p, L_nonneg); + pcg_push_local_typed(p, slot, ty); + pcg_load(p); + pcg_push_float(p, 0.0, ty); + pcg_cmp(p, CMP_EQ); + L_nonzero = pcg_label_new(p); + pcg_branch_false(p, L_nonzero); + pcg_push_local_typed(p, slot, ty); + pcg_push_float(p, 0.0, ty); + pcg_store(p); + pcg_drop(p); + pcg_label_place(p, L_nonzero); + pcg_push_local_typed(p, slot, ty); + pcg_load(p); return 1; } @@ -1649,7 +1649,7 @@ static int parse_builtin_abs_call(Parser* p, Sym name, SrcLoc loc) { fn_ty = type_func(p->pool, int_ty, params, 1, 0); sym = pcg_emit_enabled(p) ? builtin_libcall_sym(p, libname, fn_ty) : CFREE_CG_SYM_NONE; - cg_set_loc(p->cg, loc); + pcg_set_loc(p, loc); pcg_call_symbol(p, sym, 1, fn_ty); return 1; } @@ -1695,7 +1695,7 @@ static int try_parse_builtin_call(Parser* p) { u32 off = 0; (void)offsetof_designator(p, root, &off); expect_punct(p, ')', "')' after __builtin_offsetof"); - cg_push_int(p->cg, (i64)off, ty_size_t(p)); + pcg_push_int(p, (i64)off, ty_size_t(p)); return 1; } @@ -1704,7 +1704,7 @@ static int try_parse_builtin_call(Parser* p) { to_rvalue(p); expect_punct(p, ',', "',' in __builtin_expect"); parse_assign_expr(p); - cg_drop(p->cg); + pcg_drop(p); expect_punct(p, ')', "')' after __builtin_expect"); return 1; } @@ -1713,8 +1713,8 @@ static int try_parse_builtin_call(Parser* p) { parse_assign_expr(p); to_rvalue(p); expect_punct(p, ')', "')' after __builtin_alloca"); - cg_set_loc(p->cg, loc); - cg_alloca(p->cg); + pcg_set_loc(p, loc); + pcg_alloca(p); return 1; } @@ -1722,8 +1722,8 @@ static int try_parse_builtin_call(Parser* p) { parse_assign_expr(p); to_rvalue(p); expect_punct(p, ')', "')' after __builtin_ctz"); - cg_set_loc(p->cg, loc); - cg_intrinsic_unary_to_int(p->cg, INTRIN_CTZ); + pcg_set_loc(p, loc); + pcg_intrinsic_unary_to_int(p, INTRIN_CTZ); return 1; } @@ -1731,71 +1731,71 @@ static int try_parse_builtin_call(Parser* p) { parse_assign_expr(p); to_rvalue(p); expect_punct(p, ')', "')' after __builtin_clz"); - cg_set_loc(p->cg, loc); + pcg_set_loc(p, loc); /* The operand carries its own type, which drives the sf bit on * aarch64 / REX.W on x64 / sf on rv64. Whether the caller used the * `l` / `ll` suffix only changes the C-level type the user wrote; * cfree picks the instruction width from the value type. */ - cg_intrinsic_unary_to_int(p->cg, INTRIN_CLZ); + pcg_intrinsic_unary_to_int(p, INTRIN_CLZ); return 1; } if (name == p->sym_b_trap || name == p->sym_b_unreachable) { expect_punct(p, ')', "')' after __builtin_trap/unreachable"); - cg_set_loc(p->cg, loc); - cg_intrinsic_void(p->cg, + pcg_set_loc(p, loc); + pcg_intrinsic_void(p, name == p->sym_b_trap ? INTRIN_TRAP : INTRIN_UNREACHABLE); /* Both are noreturn at the C level. Push a dummy `int 0` so callers * that consume an expression value (e.g. ternary, comma) don't see * an empty stack — the dead value will be folded out. */ - cg_push_int(p->cg, 0, ty_int(p)); + pcg_push_int(p, 0, ty_int(p)); return 1; } if (name == p->sym_b_va_start) { parse_assign_expr(p); - cg_addr(p->cg); + pcg_addr(p); expect_punct(p, ',', "',' in __builtin_va_start"); parse_assign_expr(p); - cg_drop(p->cg); + pcg_drop(p); expect_punct(p, ')', "')' after __builtin_va_start"); - cg_set_loc(p->cg, loc); - cg_va_start_(p->cg); - cg_push_int(p->cg, 0, ty_int(p)); + pcg_set_loc(p, loc); + pcg_va_start(p); + pcg_push_int(p, 0, ty_int(p)); return 1; } if (name == p->sym_b_va_end) { parse_assign_expr(p); - cg_addr(p->cg); + pcg_addr(p); expect_punct(p, ')', "')' after __builtin_va_end"); - cg_set_loc(p->cg, loc); - cg_va_end_(p->cg); - cg_push_int(p->cg, 0, ty_int(p)); + pcg_set_loc(p, loc); + pcg_va_end(p); + pcg_push_int(p, 0, ty_int(p)); return 1; } if (name == p->sym_b_va_copy) { parse_assign_expr(p); - cg_addr(p->cg); + pcg_addr(p); expect_punct(p, ',', "',' in __builtin_va_copy"); parse_assign_expr(p); - cg_addr(p->cg); + pcg_addr(p); expect_punct(p, ')', "')' after __builtin_va_copy"); - cg_set_loc(p->cg, loc); - cg_va_copy_(p->cg); - cg_push_int(p->cg, 0, ty_int(p)); + pcg_set_loc(p, loc); + pcg_va_copy(p); + pcg_push_int(p, 0, ty_int(p)); return 1; } if (name == p->sym_b_va_arg) { parse_assign_expr(p); - cg_addr(p->cg); + pcg_addr(p); expect_punct(p, ',', "',' in __builtin_va_arg"); const Type* ty = parse_type_name(p); expect_punct(p, ')', "')' after __builtin_va_arg"); - cg_set_loc(p->cg, loc); - cg_va_arg_(p->cg, ty); + pcg_set_loc(p, loc); + pcg_va_arg(p, ty); return 1; } @@ -1805,8 +1805,8 @@ static int try_parse_builtin_call(Parser* p) { expect_punct(p, ',', "',' in __atomic_load_n"); MemOrder ord = parse_atomic_mem_order(p); expect_punct(p, ')', "')' after __atomic_load_n"); - cg_set_loc(p->cg, loc); - cg_atomic_load(p->cg, ord); + pcg_set_loc(p, loc); + pcg_atomic_load(p, ord); return 1; } @@ -1814,7 +1814,7 @@ static int try_parse_builtin_call(Parser* p) { parse_assign_expr(p); to_rvalue(p); const Type* val_ty = - atomic_pointee_type(p, cg_top_type(p->cg), "__atomic_store_n"); + atomic_pointee_type(p, pcg_top_type(p), "__atomic_store_n"); expect_punct(p, ',', "',' in __atomic_store_n"); parse_assign_expr(p); to_rvalue(p); @@ -1822,18 +1822,18 @@ static int try_parse_builtin_call(Parser* p) { expect_punct(p, ',', "',' in __atomic_store_n"); MemOrder ord = parse_atomic_mem_order(p); expect_punct(p, ')', "')' after __atomic_store_n"); - cg_set_loc(p->cg, loc); - cg_atomic_store(p->cg, ord); - cg_push_int(p->cg, 0, ty_int(p)); + pcg_set_loc(p, loc); + pcg_atomic_store(p, ord); + pcg_push_int(p, 0, ty_int(p)); return 1; } if (name == p->sym_a_thread_fence || name == p->sym_a_signal_fence) { MemOrder ord = parse_atomic_mem_order(p); expect_punct(p, ')', "')' after atomic fence"); - cg_set_loc(p->cg, loc); - cg_fence(p->cg, ord); - cg_push_int(p->cg, 0, ty_int(p)); + pcg_set_loc(p, loc); + pcg_fence(p, ord); + pcg_push_int(p, 0, ty_int(p)); return 1; } @@ -1842,22 +1842,22 @@ static int try_parse_builtin_call(Parser* p) { expect_punct(p, ',', "',' in atomic lock-free builtin"); parse_assign_expr(p); to_rvalue(p); - cg_drop(p->cg); + pcg_drop(p); expect_punct(p, ')', "')' after atomic lock-free builtin"); - cg_push_int(p->cg, atomic_lock_free_for_const_size(p, size), ty_int(p)); + pcg_push_int(p, atomic_lock_free_for_const_size(p, size), ty_int(p)); return 1; } if (name == p->sym_a_cas_n) { parse_assign_expr(p); to_rvalue(p); /* ptr */ - const Type* obj_ty = atomic_pointee_type(p, cg_top_type(p->cg), + const Type* obj_ty = atomic_pointee_type(p, pcg_top_type(p), "__atomic_compare_exchange_n"); expect_punct(p, ',', "',' in __atomic_compare_exchange_n"); parse_assign_expr(p); to_rvalue(p); /* &expected */ - const Type* eptr_ty = cg_top_type(p->cg); + const Type* eptr_ty = pcg_top_type(p); if (!eptr_ty || eptr_ty->kind != TY_PTR) { perr(p, "__atomic_compare_exchange_n: arg 2 must be a pointer"); } @@ -1872,16 +1872,16 @@ static int try_parse_builtin_call(Parser* p) { fsd.size = 8; fsd.align = 8; fsd.kind = FS_LOCAL; - FrameSlot eslot = cg_local(p->cg, &fsd); - cg_push_local_typed(p->cg, eslot, eptr_ty); - cg_swap(p->cg); - cg_store(p->cg); - cg_drop(p->cg); + FrameSlot eslot = pcg_local(p, &fsd); + pcg_push_local_typed(p, eslot, eptr_ty); + pcg_swap(p); + pcg_store(p); + pcg_drop(p); - cg_push_local_typed(p->cg, eslot, eptr_ty); - cg_load(p->cg); - cg_deref(p->cg, val_ty); - cg_load(p->cg); + pcg_push_local_typed(p, eslot, eptr_ty); + pcg_load(p); + pcg_deref(p, val_ty); + pcg_load(p); expect_punct(p, ',', "',' in __atomic_compare_exchange_n"); parse_assign_expr(p); @@ -1896,21 +1896,21 @@ static int try_parse_builtin_call(Parser* p) { MemOrder fail = parse_atomic_mem_order(p); expect_punct(p, ')', "')' after __atomic_compare_exchange_n"); - cg_set_loc(p->cg, loc); - cg_atomic_cas(p->cg, succ, fail); + pcg_set_loc(p, loc); + pcg_atomic_cas(p, succ, fail); - const Type* ok_ty = cg_top_type(p->cg); + const Type* ok_ty = pcg_top_type(p); FrameSlotDesc okd; memset(&okd, 0, sizeof okd); okd.type = ok_ty; okd.size = 4; okd.align = 4; okd.kind = FS_LOCAL; - FrameSlot okslot = cg_local(p->cg, &okd); - cg_push_local_typed(p->cg, okslot, ok_ty); - cg_swap(p->cg); - cg_store(p->cg); - cg_drop(p->cg); + FrameSlot okslot = pcg_local(p, &okd); + pcg_push_local_typed(p, okslot, ok_ty); + pcg_swap(p); + pcg_store(p); + pcg_drop(p); FrameSlotDesc pd; memset(&pd, 0, sizeof pd); @@ -1918,27 +1918,27 @@ static int try_parse_builtin_call(Parser* p) { pd.size = c_abi_sizeof(p->abi, val_ty); pd.align = c_abi_alignof(p->abi, val_ty); pd.kind = FS_LOCAL; - FrameSlot pslot = cg_local(p->cg, &pd); - cg_push_local_typed(p->cg, pslot, val_ty); - cg_swap(p->cg); - cg_store(p->cg); - cg_drop(p->cg); - - cg_push_local_typed(p->cg, okslot, ok_ty); - cg_load(p->cg); - CGLabel L_done = cg_label_new(p->cg); - cg_branch_true(p->cg, L_done); - cg_push_local_typed(p->cg, eslot, eptr_ty); - cg_load(p->cg); - cg_deref(p->cg, val_ty); - cg_push_local_typed(p->cg, pslot, val_ty); - cg_load(p->cg); - cg_store(p->cg); - cg_drop(p->cg); - cg_label_place(p->cg, L_done); - - cg_push_local_typed(p->cg, okslot, ok_ty); - cg_load(p->cg); + FrameSlot pslot = pcg_local(p, &pd); + pcg_push_local_typed(p, pslot, val_ty); + pcg_swap(p); + pcg_store(p); + pcg_drop(p); + + pcg_push_local_typed(p, okslot, ok_ty); + pcg_load(p); + CGLabel L_done = pcg_label_new(p); + pcg_branch_true(p, L_done); + pcg_push_local_typed(p, eslot, eptr_ty); + pcg_load(p); + pcg_deref(p, val_ty); + pcg_push_local_typed(p, pslot, val_ty); + pcg_load(p); + pcg_store(p); + pcg_drop(p); + pcg_label_place(p, L_done); + + pcg_push_local_typed(p, okslot, ok_ty); + pcg_load(p); return 1; } @@ -1964,7 +1964,7 @@ static int try_parse_builtin_call(Parser* p) { parse_assign_expr(p); to_rvalue(p); const Type* val_ty = - atomic_pointee_type(p, cg_top_type(p->cg), "__atomic read-modify-write"); + atomic_pointee_type(p, pcg_top_type(p), "__atomic read-modify-write"); expect_punct(p, ',', "',' in atomic builtin"); parse_assign_expr(p); to_rvalue(p); @@ -1972,8 +1972,8 @@ static int try_parse_builtin_call(Parser* p) { expect_punct(p, ',', "',' in atomic builtin"); MemOrder ord = parse_atomic_mem_order(p); expect_punct(p, ')', "')' after atomic builtin"); - cg_set_loc(p->cg, loc); - cg_atomic_rmw(p->cg, op, ord); + pcg_set_loc(p, loc); + pcg_atomic_rmw(p, op, ord); return 1; } @@ -1987,14 +1987,14 @@ static void parse_primary(Parser* p) { i64 v = parse_int_literal(p, &t); const Type* lty = int_literal_type(p, &t); advance(p); - cg_push_int(p->cg, v, lty); + pcg_push_int(p, v, lty); return; } if (t.kind == TOK_FLT) { double v = parse_float_literal(p, &t); const Type* lty = float_literal_type(p, &t); advance(p); - cg_push_float(p->cg, v, lty); + pcg_push_float(p, v, lty); return; } if (is_punct(&t, '(')) { @@ -2044,7 +2044,7 @@ static void parse_primary(Parser* p) { advance(p); const Type* char_ty = type_prim(p->pool, TY_CHAR); const Type* arr_ty = type_array(p->pool, char_ty, (u32)(nlen + 1u), 0); - cg_push_global(p->cg, sym, arr_ty); + pcg_push_global(p, sym, arr_ty); return; } e = scope_lookup(p, t.v.ident); @@ -2058,7 +2058,7 @@ static void parse_primary(Parser* p) { advance(p); switch (e->kind) { case SEK_LOCAL: - cg_push_local_typed(p->cg, e->v.slot, e->type); + pcg_push_local_typed(p, e->v.slot, e->type); if (e->storage == DS_REGISTER) pcg_set_top_register(p); if (e->vla_byte_slot != FRAME_SLOT_NONE) { p->last_pushed_vla_slot = e->vla_byte_slot; @@ -2069,10 +2069,10 @@ static void parse_primary(Parser* p) { return; case SEK_GLOBAL: case SEK_FUNC: - cg_push_global(p->cg, e->v.sym, e->type); + pcg_push_global(p, e->v.sym, e->type); return; case SEK_ENUM_CST: - cg_push_int(p->cg, e->v.enum_value, e->type); + pcg_push_int(p, e->v.enum_value, e->type); return; case SEK_TYPEDEF: default: @@ -2083,7 +2083,7 @@ static void parse_primary(Parser* p) { i64 v = decode_char_literal(p, &t); const Type* lty = char_literal_type(p, &t); advance(p); - cg_push_int(p->cg, v, lty); + pcg_push_int(p, v, lty); return; } if (t.kind == TOK_STR) { @@ -2098,7 +2098,7 @@ static void parse_primary(Parser* p) { { const Type* arr_ty = type_array(p->pool, elem_ty, elem_size ? (u32)(n / elem_size) : 0, 0); - cg_push_global(p->cg, sym, arr_ty); + pcg_push_global(p, sym, arr_ty); } return; } @@ -2192,10 +2192,10 @@ static void parse_postfix(Parser* p) { if (!pcg_top_is_modifiable_lvalue(p)) { perr(p, "increment/decrement requires modifiable lvalue"); } - if (!c_type_is_scalar(cg_top_type(p->cg))) { + if (!c_type_is_scalar(pcg_top_type(p))) { perr(p, "increment/decrement requires scalar operand"); } - cg_inc_dec(p->cg, BO_IADD, /*post=*/1); + pcg_inc_dec(p, BO_IADD, /*post=*/1); continue; } if (is_punct(&t, P_DEC)) { @@ -2203,21 +2203,21 @@ static void parse_postfix(Parser* p) { if (!pcg_top_is_modifiable_lvalue(p)) { perr(p, "increment/decrement requires modifiable lvalue"); } - if (!c_type_is_scalar(cg_top_type(p->cg))) { + if (!c_type_is_scalar(pcg_top_type(p))) { perr(p, "increment/decrement requires scalar operand"); } - cg_inc_dec(p->cg, BO_ISUB, /*post=*/1); + pcg_inc_dec(p, BO_ISUB, /*post=*/1); continue; } if (is_punct(&t, '(')) { - const Type* top = cg_top_type(p->cg); + const Type* top = pcg_top_type(p); const Type* fn_type; if (top && top->kind == TY_FUNC) { fn_type = top; } else if (top && top->kind == TY_PTR && top->ptr.pointee && top->ptr.pointee->kind == TY_FUNC) { fn_type = top->ptr.pointee; - if (pcg_top_is_lvalue(p)) cg_load(p->cg); + if (pcg_top_is_lvalue(p)) pcg_load(p); } else { perr(p, "called object is not a function"); } @@ -2231,7 +2231,7 @@ static void parse_postfix(Parser* p) { to_rvalue(p); if (param_ty) { CSemCheck chk = c_sem_check_assignment( - p->pool, param_ty, cg_top_type(p->cg), C_SEM_ASSIGN_EXPR); + p->pool, param_ty, pcg_top_type(p), C_SEM_ASSIGN_EXPR); if (!chk.ok) perr(p, "%.*s", CFREE_SLICE_ARG(cfree_slice_cstr(chk.message))); coerce_top_to_type(p, param_ty); @@ -2247,23 +2247,23 @@ static void parse_postfix(Parser* p) { if (fn_type->fn.variadic && nargs < fn_type->fn.nparams) { perr(p, "too few arguments to variadic function"); } - cg_call(p->cg, nargs, fn_type); + pcg_call(p, nargs, fn_type); if (fn_type->fn.ret && fn_type->fn.ret->kind == TY_VOID) { - cg_push_int(p->cg, 0, ty_int(p)); + pcg_push_int(p, 0, ty_int(p)); } continue; } if (is_punct(&t, '[')) { - const Type* lt0 = cg_top_type(p->cg); + const Type* lt0 = pcg_top_type(p); advance(p); /* '[' */ if (lt0 && lt0->kind == TY_ARRAY) { decay_array_to_pointer(p, lt0); } else if (lt0 && lt0->kind == TY_PTR) { - if (pcg_top_is_lvalue(p)) cg_load(p->cg); + if (pcg_top_is_lvalue(p)) pcg_load(p); } parse_expr(p); { - const Type* it0 = cg_top_type(p->cg); + const Type* it0 = pcg_top_type(p); if (it0 && it0->kind == TY_ARRAY) { decay_array_to_pointer(p, it0); } else { @@ -2272,13 +2272,13 @@ static void parse_postfix(Parser* p) { } expect_punct(p, ']', "']' after subscript"); { - const Type* lt = cg_top2_type(p->cg); - const Type* it = cg_top_type(p->cg); + const Type* lt = pcg_top2_type(p); + const Type* it = pcg_top_type(p); const Type* elem; if (lt && lt->kind == TY_PTR && type_is_int(it)) { elem = lt->ptr.pointee; } else if (it && it->kind == TY_PTR && type_is_int(lt)) { - cg_swap(p->cg); + pcg_swap(p); elem = it->ptr.pointee; } else { perr(p, "invalid subscript: needs one pointer and one integer"); @@ -2288,11 +2288,11 @@ static void parse_postfix(Parser* p) { { FrameSlot elem_vla_slot = vla_size_slot_for_type(vla_bounds, elem); if (elem_vla_slot != FRAME_SLOT_NONE) { - cg_push_local_typed(p->cg, elem_vla_slot, ty_size_t(p)); - cg_load(p->cg); - cg_binop(p->cg, BO_IMUL); - cg_binop(p->cg, BO_IADD); - cg_deref(p->cg, elem); + pcg_push_local_typed(p, elem_vla_slot, ty_size_t(p)); + pcg_load(p); + pcg_binop(p, BO_IMUL); + pcg_binop(p, BO_IADD); + pcg_deref(p, elem); p->last_pushed_vla_slot = elem_vla_slot; p->last_pushed_vla_bounds = vla_bounds; } else { @@ -2304,7 +2304,7 @@ static void parse_postfix(Parser* p) { continue; } if (is_punct(&t, '.')) { - const Type* lt = cg_top_type(p->cg); + const Type* lt = pcg_top_type(p); Sym mname; const Type* mty = NULL; const Field* mf = NULL; @@ -2336,7 +2336,7 @@ static void parse_postfix(Parser* p) { u32 depth = 0; advance(p); /* `->` */ to_rvalue(p); - lt0 = cg_top_type(p->cg); + lt0 = pcg_top_type(p); if (!lt0 || lt0->kind != TY_PTR) { perr(p, "'->' requires a pointer operand"); } @@ -2351,7 +2351,7 @@ static void parse_postfix(Parser* p) { advance(p); if (!find_record_member_path(p, rec_ty, mname, &mty, path, &depth, &mf)) perr(p, "no such member"); - cg_deref(p->cg, rec_ty); + pcg_deref(p, rec_ty); cg_record_member_path(p, mty, path, depth, mf); continue; } @@ -2382,32 +2382,32 @@ void parse_unary(Parser* p) { fsd.align = c_abi_alignof(p->abi, lit_ty); fsd.kind = FS_LOCAL; fsd.flags = FSF_NONE; - slot = cg_local(p->cg, &fsd); + slot = pcg_local(p, &fsd); if (lit_ty && (lit_ty->kind == TY_ARRAY || lit_ty->kind == TY_STRUCT || lit_ty->kind == TY_UNION)) { init_at(p, slot, lit_ty, 0, lit_ty); } else { init_at(p, slot, lit_ty, 0, lit_ty); } - cg_push_local_typed(p->cg, slot, lit_ty); + pcg_push_local_typed(p, slot, lit_ty); return; } parse_unary(p); to_rvalue(p); - src = cg_top_type(p->cg); + src = pcg_top_type(p); if (dst && dst->kind == TY_VOID) { - cg_drop(p->cg); - cg_push_int(p->cg, 0, ty_int(p)); + pcg_drop(p); + pcg_push_int(p, 0, ty_int(p)); return; } if (!c_type_is_scalar(dst) || !c_type_is_scalar(src)) { perr(p, "cast requires scalar type"); } if (src && src->kind == TY_PTR && dst->kind == TY_PTR) { - cg_convert(p->cg, dst); + pcg_convert(p, dst); return; } - cg_convert(p->cg, dst); + pcg_convert(p, dst); return; } } @@ -2415,34 +2415,34 @@ void parse_unary(Parser* p) { advance(p); parse_unary(p); to_rvalue(p); - require_arith(p, cg_top_type(p->cg), "unary '+'"); + require_arith(p, pcg_top_type(p), "unary '+'"); return; } if (is_punct(&t, '-')) { advance(p); parse_unary(p); to_rvalue(p); - require_arith(p, cg_top_type(p->cg), "unary '-'"); - cg_unop(p->cg, UO_NEG); + require_arith(p, pcg_top_type(p), "unary '-'"); + pcg_unop(p, UO_NEG); return; } if (is_punct(&t, '!')) { advance(p); parse_unary(p); to_rvalue(p); - require_scalar(p, cg_top_type(p->cg), "unary '!'"); - cg_push_int(p->cg, 0, ty_int(p)); - cg_cmp(p->cg, CMP_EQ); + require_scalar(p, pcg_top_type(p), "unary '!'"); + pcg_push_int(p, 0, ty_int(p)); + pcg_cmp(p, CMP_EQ); return; } if (is_punct(&t, '~')) { advance(p); parse_unary(p); to_rvalue(p); - if (!type_is_int(cg_top_type(p->cg))) { + if (!type_is_int(pcg_top_type(p))) { perr(p, "unary '~' requires integer operand"); } - cg_unop(p->cg, UO_BNOT); + pcg_unop(p, UO_BNOT); return; } if (is_punct(&t, P_AND)) { @@ -2463,13 +2463,13 @@ void parse_unary(Parser* p) { advance(p); parse_unary(p); if (!pcg_top_is_lvalue(p) && - !(cg_top_type(p->cg) && cg_top_type(p->cg)->kind == TY_FUNC)) { + !(pcg_top_type(p) && pcg_top_type(p)->kind == TY_FUNC)) { perr(p, "address-of requires lvalue operand"); } if (pcg_top_is_bitfield(p)) perr(p, "cannot take address of bit-field"); if (pcg_top_is_register(p)) perr(p, "cannot take address of register object"); - cg_addr(p->cg); + pcg_addr(p); return; } if (is_punct(&t, '*')) { @@ -2478,7 +2478,7 @@ void parse_unary(Parser* p) { advance(p); parse_unary(p); to_rvalue(p); - pty = cg_top_type(p->cg); + pty = pcg_top_type(p); if (!pty || pty->kind != TY_PTR) { perr(p, "indirection requires pointer operand"); } @@ -2486,7 +2486,7 @@ void parse_unary(Parser* p) { if (pointee && pointee->kind == TY_VOID) { perr(p, "dereferencing pointer to incomplete type"); } - cg_deref(p->cg, pointee); + pcg_deref(p, pointee); return; } if (is_punct(&t, P_INC) || is_punct(&t, P_DEC)) { @@ -2496,10 +2496,10 @@ void parse_unary(Parser* p) { if (!pcg_top_is_modifiable_lvalue(p)) { perr(p, "increment/decrement requires modifiable lvalue"); } - if (!c_type_is_scalar(cg_top_type(p->cg))) { + if (!c_type_is_scalar(pcg_top_type(p))) { perr(p, "increment/decrement requires scalar operand"); } - cg_inc_dec(p->cg, bop, /*post=*/0); + pcg_inc_dec(p, bop, /*post=*/0); return; } if (is_kw(p, &t, KW_SIZEOF)) { @@ -2516,28 +2516,28 @@ void parse_unary(Parser* p) { p->last_pushed_vla_slot = FRAME_SLOT_NONE; pcg_codegen_suppress_push(p); parse_unary(p); - ty = cg_top_type(p->cg); + ty = pcg_top_type(p); vla_slot = p->last_pushed_vla_slot; if (pcg_top_is_bitfield(p)) perr(p, "sizeof bit-field"); - cg_drop(p->cg); + pcg_drop(p); pcg_codegen_suppress_pop(p); } } else { p->last_pushed_vla_slot = FRAME_SLOT_NONE; pcg_codegen_suppress_push(p); parse_unary(p); - ty = cg_top_type(p->cg); + ty = pcg_top_type(p); vla_slot = p->last_pushed_vla_slot; if (pcg_top_is_bitfield(p)) perr(p, "sizeof bit-field"); - cg_drop(p->cg); + pcg_drop(p); pcg_codegen_suppress_pop(p); } if (vla_slot != FRAME_SLOT_NONE) { - cg_push_local_typed(p->cg, vla_slot, ty_size_t(p)); - cg_load(p->cg); + pcg_push_local_typed(p, vla_slot, ty_size_t(p)); + pcg_load(p); } else { require_sizeof_type(p, ty); - cg_push_int(p->cg, (i64)c_abi_sizeof(p->abi, ty), ty_size_t(p)); + pcg_push_int(p, (i64)c_abi_sizeof(p->abi, ty), ty_size_t(p)); } return; } @@ -2547,8 +2547,8 @@ void parse_unary(Parser* p) { pcg_codegen_suppress_push(p); parse_assign_expr(p); to_rvalue(p); - const Type* ctl_ty = cg_top_type(p->cg); - cg_drop(p->cg); + const Type* ctl_ty = pcg_top_type(p); + pcg_drop(p); pcg_codegen_suppress_pop(p); expect_punct(p, ',', "','"); int emitted = 0; @@ -2706,11 +2706,11 @@ void parse_unary(Parser* p) { ty = parse_type_name(p); } else { parse_unary(p); - ty = cg_top_type(p->cg); - cg_drop(p->cg); + ty = pcg_top_type(p); + pcg_drop(p); } expect_punct(p, ')', "')'"); - cg_push_int(p->cg, (i64)c_abi_alignof(p->abi, ty), ty_size_t(p)); + pcg_push_int(p, (i64)c_abi_alignof(p->abi, ty), ty_size_t(p)); return; } parse_postfix(p); @@ -2737,10 +2737,10 @@ static const Type* common_fp_type(Parser* p, const Type* a, const Type* b) { } static void emit_fp_binop(Parser* p, BinOp bop, const Type* common) { - if (cg_top_type(p->cg) != common) cg_convert(p->cg, common); - cg_swap(p->cg); - if (cg_top_type(p->cg) != common) cg_convert(p->cg, common); - cg_swap(p->cg); + if (pcg_top_type(p) != common) pcg_convert(p, common); + pcg_swap(p); + if (pcg_top_type(p) != common) pcg_convert(p, common); + pcg_swap(p); BinOp fop; switch (bop) { case BO_IADD: @@ -2759,22 +2759,22 @@ static void emit_fp_binop(Parser* p, BinOp bop, const Type* common) { perr(p, "operator does not apply to floating types"); return; } - cg_binop(p->cg, fop); + pcg_binop(p, fop); } static void coerce_fp_cmp_operands(Parser* p, const Type* common) { - if (cg_top_type(p->cg) != common) cg_convert(p->cg, common); - cg_swap(p->cg); - if (cg_top_type(p->cg) != common) cg_convert(p->cg, common); - cg_swap(p->cg); + if (pcg_top_type(p) != common) pcg_convert(p, common); + pcg_swap(p); + if (pcg_top_type(p) != common) pcg_convert(p, common); + pcg_swap(p); } static void coerce_arith_operands(Parser* p, const Type* common) { if (!common) return; - if (cg_top_type(p->cg) != common) cg_convert(p->cg, common); - cg_swap(p->cg); - if (cg_top_type(p->cg) != common) cg_convert(p->cg, common); - cg_swap(p->cg); + if (pcg_top_type(p) != common) pcg_convert(p, common); + pcg_swap(p); + if (pcg_top_type(p) != common) pcg_convert(p, common); + pcg_swap(p); } static CmpOp unsigned_rel_cmp(CmpOp cop) { @@ -2822,8 +2822,8 @@ static void parse_mul(Parser* p) { to_rvalue(p); parse_unary(p); to_rvalue(p); - const Type* lt = cg_top2_type(p->cg); - const Type* rt = cg_top_type(p->cg); + const Type* lt = pcg_top2_type(p); + const Type* rt = pcg_top_type(p); const Type* common = common_fp_type(p, lt, rt); if (bop == BO_SREM) { if (!type_is_int(lt) || !type_is_int(rt)) @@ -2836,7 +2836,7 @@ static void parse_mul(Parser* p) { } else { const Type* icommon = cint_common_type(p, lt, rt); coerce_arith_operands(p, icommon); - cg_binop(p->cg, int_div_rem_binop(bop, icommon)); + pcg_binop(p, int_div_rem_binop(bop, icommon)); } } } @@ -2845,14 +2845,14 @@ static void scale_pointer_index(Parser* p, u32 elem_size) { const Type* idx_ty = c_abi_ptrdiff_type(p->abi, p->pool); coerce_top_to_type(p, idx_ty); if (elem_size != 1) { - cg_push_int(p->cg, (i64)elem_size, idx_ty); - cg_binop(p->cg, BO_IMUL); + pcg_push_int(p, (i64)elem_size, idx_ty); + pcg_binop(p, BO_IMUL); } } static void emit_add_or_sub(Parser* p, BinOp bop) { - const Type* lt = cg_top2_type(p->cg); - const Type* rt = cg_top_type(p->cg); + const Type* lt = pcg_top2_type(p); + const Type* rt = pcg_top_type(p); int l_is_ptr = lt && lt->kind == TY_PTR; int r_is_ptr = rt && rt->kind == TY_PTR; if (bop == BO_IADD) { @@ -2864,16 +2864,16 @@ static void emit_add_or_sub(Parser* p, BinOp bop) { perr(p, "pointer arithmetic on void pointer"); u32 esz = c_abi_sizeof(p->abi, lt->ptr.pointee); scale_pointer_index(p, esz); - cg_binop(p->cg, BO_IADD); + pcg_binop(p, BO_IADD); return; } if (r_is_ptr && type_is_int(lt)) { if (rt->ptr.pointee && rt->ptr.pointee->kind == TY_VOID) perr(p, "pointer arithmetic on void pointer"); - cg_swap(p->cg); + pcg_swap(p); u32 esz = c_abi_sizeof(p->abi, rt->ptr.pointee); scale_pointer_index(p, esz); - cg_binop(p->cg, BO_IADD); + pcg_binop(p, BO_IADD); return; } } else { /* BO_ISUB */ @@ -2882,7 +2882,7 @@ static void emit_add_or_sub(Parser* p, BinOp bop) { perr(p, "pointer arithmetic on void pointer"); u32 esz = c_abi_sizeof(p->abi, lt->ptr.pointee); scale_pointer_index(p, esz); - cg_binop(p->cg, BO_ISUB); + pcg_binop(p, BO_ISUB); return; } if (l_is_ptr && r_is_ptr) { @@ -2890,12 +2890,12 @@ static void emit_add_or_sub(Parser* p, BinOp bop) { perr(p, "subtraction of incompatible pointer types"); } u32 esz = c_abi_sizeof(p->abi, lt->ptr.pointee); - cg_binop(p->cg, BO_ISUB); + pcg_binop(p, BO_ISUB); if (esz != 1) { - cg_push_int(p->cg, (i64)esz, ty_size_t(p)); - cg_binop(p->cg, BO_SDIV); + pcg_push_int(p, (i64)esz, ty_size_t(p)); + pcg_binop(p, BO_SDIV); } - cg_convert(p->cg, c_abi_ptrdiff_type(p->abi, p->pool)); + pcg_convert(p, c_abi_ptrdiff_type(p->abi, p->pool)); return; } } @@ -2912,7 +2912,7 @@ static void emit_add_or_sub(Parser* p, BinOp bop) { } common = cint_common_type(p, lt, rt); coerce_arith_operands(p, common); - cg_binop(p->cg, bop); + pcg_binop(p, bop); } static void parse_add(Parser* p) { @@ -2950,25 +2950,25 @@ static void parse_shift(Parser* p) { advance(p); to_rvalue(p); { - const Type* lt = cg_top_type(p->cg); + const Type* lt = pcg_top_type(p); const Type* lp = cint_promote_type(p, lt); if (!type_is_int(lt)) perr(p, "shift operator requires integer operands"); - if (cg_top_type(p->cg) != lp) cg_convert(p->cg, lp); + if (pcg_top_type(p) != lp) pcg_convert(p, lp); if (bop == BO_SHR_S && !c_abi_type_info(p->abi, lp).signed_) bop = BO_SHR_U; } parse_add(p); to_rvalue(p); { - const Type* rt = cg_top_type(p->cg); + const Type* rt = pcg_top_type(p); const Type* rp = cint_promote_type(p, rt); if (!type_is_int(rt)) perr(p, "shift operator requires integer operands"); - if (cg_top_type(p->cg) != rp) cg_convert(p->cg, rp); + if (pcg_top_type(p) != rp) pcg_convert(p, rp); } - if (!type_is_int(cg_top2_type(p->cg)) || !type_is_int(cg_top_type(p->cg))) { + if (!type_is_int(pcg_top2_type(p)) || !type_is_int(pcg_top_type(p))) { perr(p, "shift operator requires integer operands"); } - cg_binop(p->cg, bop); + pcg_binop(p, bop); } } @@ -2993,8 +2993,8 @@ static void parse_rel(Parser* p) { parse_shift(p); to_rvalue(p); { - const Type* lt = cg_top2_type(p->cg); - const Type* rt = cg_top_type(p->cg); + const Type* lt = pcg_top2_type(p); + const Type* rt = pcg_top_type(p); const Type* common = common_fp_type(p, lt, rt); if (lt && lt->kind == TY_PTR && rt && rt->kind == TY_PTR) { if (!pointer_pointees_compatible(p, lt, rt)) { @@ -3029,7 +3029,7 @@ static void parse_rel(Parser* p) { if (!cint_signed(p, common)) cop = unsigned_rel_cmp(cop); } } - cg_cmp(p->cg, cop); + pcg_cmp(p, cop); } } @@ -3045,14 +3045,14 @@ static void parse_eq(Parser* p) { } else { break; } - int lhs_null = null_pointer_constant(p, cg_top_type(p->cg)); + int lhs_null = null_pointer_constant(p, pcg_top_type(p)); advance(p); to_rvalue(p); parse_rel(p); to_rvalue(p); { - const Type* lt = cg_top2_type(p->cg); - const Type* rt = cg_top_type(p->cg); + const Type* lt = pcg_top2_type(p); + const Type* rt = pcg_top_type(p); const Type* common = common_fp_type(p, lt, rt); int lnull = lhs_null; int rnull = null_pointer_constant(p, rt); @@ -3073,7 +3073,7 @@ static void parse_eq(Parser* p) { coerce_arith_operands(p, common); } } - cg_cmp(p->cg, cop); + pcg_cmp(p, cop); } } @@ -3084,12 +3084,12 @@ static void parse_band(Parser* p) { to_rvalue(p); parse_eq(p); to_rvalue(p); - if (!type_is_int(cg_top2_type(p->cg)) || !type_is_int(cg_top_type(p->cg))) { + if (!type_is_int(pcg_top2_type(p)) || !type_is_int(pcg_top_type(p))) { perr(p, "bitwise operator requires integer operands"); } coerce_arith_operands( - p, cint_common_type(p, cg_top2_type(p->cg), cg_top_type(p->cg))); - cg_binop(p->cg, BO_AND); + p, cint_common_type(p, pcg_top2_type(p), pcg_top_type(p))); + pcg_binop(p, BO_AND); } } @@ -3100,12 +3100,12 @@ static void parse_bxor(Parser* p) { to_rvalue(p); parse_band(p); to_rvalue(p); - if (!type_is_int(cg_top2_type(p->cg)) || !type_is_int(cg_top_type(p->cg))) { + if (!type_is_int(pcg_top2_type(p)) || !type_is_int(pcg_top_type(p))) { perr(p, "bitwise operator requires integer operands"); } coerce_arith_operands( - p, cint_common_type(p, cg_top2_type(p->cg), cg_top_type(p->cg))); - cg_binop(p->cg, BO_XOR); + p, cint_common_type(p, pcg_top2_type(p), pcg_top_type(p))); + pcg_binop(p, BO_XOR); } } @@ -3116,12 +3116,12 @@ static void parse_bor(Parser* p) { to_rvalue(p); parse_bxor(p); to_rvalue(p); - if (!type_is_int(cg_top2_type(p->cg)) || !type_is_int(cg_top_type(p->cg))) { + if (!type_is_int(pcg_top2_type(p)) || !type_is_int(pcg_top_type(p))) { perr(p, "bitwise operator requires integer operands"); } coerce_arith_operands( - p, cint_common_type(p, cg_top2_type(p->cg), cg_top_type(p->cg))); - cg_binop(p->cg, BO_OR); + p, cint_common_type(p, pcg_top2_type(p), pcg_top_type(p))); + pcg_binop(p, BO_OR); } } @@ -3141,21 +3141,21 @@ static FrameSlot ll_tmp_slot(Parser* p, const Type* ty) { fsd.align = c_abi_alignof(p->abi, ty); fsd.kind = FS_LOCAL; fsd.flags = FSF_NONE; - return cg_local(p->cg, &fsd); + return pcg_local(p, &fsd); } static void ll_store_const(Parser* p, FrameSlot tmp, const Type* ty, i64 v) { - cg_push_local_typed(p->cg, tmp, ty); - cg_push_int(p->cg, v, ty); - cg_store(p->cg); - cg_drop(p->cg); + pcg_push_local_typed(p, tmp, ty); + pcg_push_int(p, v, ty); + pcg_store(p); + pcg_drop(p); } static void parse_land(Parser* p) { parse_bor(p); while (is_punct(&p->cur, P_AND)) { - CGLabel L_false = cg_label_new(p->cg); - CGLabel L_end = cg_label_new(p->cg); + CGLabel L_false = pcg_label_new(p); + CGLabel L_end = pcg_label_new(p); const Type* result_ty = ty_int(p); FrameSlot tmp = ll_tmp_slot(p, result_ty); int lhs_known; @@ -3163,43 +3163,43 @@ static void parse_land(Parser* p) { int rhs_truth = 0; advance(p); to_rvalue(p); - require_scalar(p, cg_top_type(p->cg), "logical '&&'"); + require_scalar(p, pcg_top_type(p), "logical '&&'"); lhs_known = cg_top_const_truth(p, &lhs_truth); if (lhs_known && !lhs_truth) { - cg_drop(p->cg); + pcg_drop(p); pcg_codegen_suppress_push(p); parse_bor(p); to_rvalue(p); - require_scalar(p, cg_top_type(p->cg), "logical '&&'"); - cg_drop(p->cg); + require_scalar(p, pcg_top_type(p), "logical '&&'"); + pcg_drop(p); pcg_codegen_suppress_pop(p); - cg_push_int(p->cg, 0, result_ty); + pcg_push_int(p, 0, result_ty); continue; } - cg_branch_false(p->cg, L_false); + pcg_branch_false(p, L_false); parse_bor(p); to_rvalue(p); - require_scalar(p, cg_top_type(p->cg), "logical '&&'"); + require_scalar(p, pcg_top_type(p), "logical '&&'"); if (lhs_known && lhs_truth && cg_top_const_truth(p, &rhs_truth)) { - cg_drop(p->cg); - cg_push_int(p->cg, rhs_truth ? 1 : 0, result_ty); + pcg_drop(p); + pcg_push_int(p, rhs_truth ? 1 : 0, result_ty); continue; } - cg_branch_false(p->cg, L_false); + pcg_branch_false(p, L_false); ll_store_const(p, tmp, result_ty, 1); - cg_jump(p->cg, L_end); - cg_label_place(p->cg, L_false); + pcg_jump(p, L_end); + pcg_label_place(p, L_false); ll_store_const(p, tmp, result_ty, 0); - cg_label_place(p->cg, L_end); - cg_push_local_typed(p->cg, tmp, result_ty); + pcg_label_place(p, L_end); + pcg_push_local_typed(p, tmp, result_ty); } } static void parse_lor(Parser* p) { parse_land(p); while (is_punct(&p->cur, P_OR)) { - CGLabel L_true = cg_label_new(p->cg); - CGLabel L_end = cg_label_new(p->cg); + CGLabel L_true = pcg_label_new(p); + CGLabel L_end = pcg_label_new(p); const Type* result_ty = ty_int(p); FrameSlot tmp = ll_tmp_slot(p, result_ty); int lhs_known; @@ -3207,35 +3207,35 @@ static void parse_lor(Parser* p) { int rhs_truth = 0; advance(p); to_rvalue(p); - require_scalar(p, cg_top_type(p->cg), "logical '||'"); + require_scalar(p, pcg_top_type(p), "logical '||'"); lhs_known = cg_top_const_truth(p, &lhs_truth); if (lhs_known && lhs_truth) { - cg_drop(p->cg); + pcg_drop(p); pcg_codegen_suppress_push(p); parse_land(p); to_rvalue(p); - require_scalar(p, cg_top_type(p->cg), "logical '||'"); - cg_drop(p->cg); + require_scalar(p, pcg_top_type(p), "logical '||'"); + pcg_drop(p); pcg_codegen_suppress_pop(p); - cg_push_int(p->cg, 1, result_ty); + pcg_push_int(p, 1, result_ty); continue; } - cg_branch_true(p->cg, L_true); + pcg_branch_true(p, L_true); parse_land(p); to_rvalue(p); - require_scalar(p, cg_top_type(p->cg), "logical '||'"); + require_scalar(p, pcg_top_type(p), "logical '||'"); if (lhs_known && !lhs_truth && cg_top_const_truth(p, &rhs_truth)) { - cg_drop(p->cg); - cg_push_int(p->cg, rhs_truth ? 1 : 0, result_ty); + pcg_drop(p); + pcg_push_int(p, rhs_truth ? 1 : 0, result_ty); continue; } - cg_branch_true(p->cg, L_true); + pcg_branch_true(p, L_true); ll_store_const(p, tmp, result_ty, 0); - cg_jump(p->cg, L_end); - cg_label_place(p->cg, L_true); + pcg_jump(p, L_end); + pcg_label_place(p, L_true); ll_store_const(p, tmp, result_ty, 1); - cg_label_place(p->cg, L_end); - cg_push_local_typed(p->cg, tmp, result_ty); + pcg_label_place(p, L_end); + pcg_push_local_typed(p, tmp, result_ty); } } @@ -3244,8 +3244,8 @@ static const Type* common_fp_type(Parser* p, const Type* a, const Type* b); static void parse_ternary(Parser* p) { parse_lor(p); if (!is_punct(&p->cur, '?')) return; - CGLabel L_else = cg_label_new(p->cg); - CGLabel L_end = cg_label_new(p->cg); + CGLabel L_else = pcg_label_new(p); + CGLabel L_end = pcg_label_new(p); const Type* result_ty = ty_int(p); int then_null = 0; FrameSlot tmp; @@ -3253,16 +3253,16 @@ static void parse_ternary(Parser* p) { const Type* then_store_ty; advance(p); /* '?' */ to_rvalue(p); - require_scalar(p, cg_top_type(p->cg), "conditional operator"); - cg_branch_false(p->cg, L_else); + require_scalar(p, pcg_top_type(p), "conditional operator"); + pcg_branch_false(p, L_else); parse_expr(p); to_rvalue(p); - result_ty = cg_top_type(p->cg); + result_ty = pcg_top_type(p); then_null = null_pointer_constant(p, result_ty); if (!result_ty) result_ty = ty_int(p); if (type_is_int(result_ty)) { result_ty = type_promoted(p->pool, result_ty); - if (cg_top_type(p->cg) != result_ty) cg_convert(p->cg, result_ty); + if (pcg_top_type(p) != result_ty) pcg_convert(p, result_ty); } then_store_ty = then_null ? type_ptr(p->pool, type_prim(p->pool, TY_VOID)) : result_ty; @@ -3272,18 +3272,18 @@ static void parse_ternary(Parser* p) { fsd.align = c_abi_alignof(p->abi, then_store_ty); fsd.kind = FS_LOCAL; fsd.flags = FSF_NONE; - tmp = cg_local(p->cg, &fsd); - if (cg_top_type(p->cg) != then_store_ty) cg_convert(p->cg, then_store_ty); - cg_push_local_typed(p->cg, tmp, then_store_ty); - cg_swap(p->cg); - cg_store(p->cg); - cg_drop(p->cg); - cg_jump(p->cg, L_end); - cg_label_place(p->cg, L_else); + tmp = pcg_local(p, &fsd); + if (pcg_top_type(p) != then_store_ty) pcg_convert(p, then_store_ty); + pcg_push_local_typed(p, tmp, then_store_ty); + pcg_swap(p); + pcg_store(p); + pcg_drop(p); + pcg_jump(p, L_end); + pcg_label_place(p, L_else); expect_punct(p, ':', "':' in ternary"); parse_assign_expr(p); to_rvalue(p); - const Type* else_ty = cg_top_type(p->cg); + const Type* else_ty = pcg_top_type(p); const Type* common = common_fp_type(p, result_ty, else_ty); const Type* ptr_result = conditional_pointer_type( p, result_ty, then_null, else_ty, null_pointer_constant(p, else_ty)); @@ -3297,14 +3297,14 @@ static void parse_ternary(Parser* p) { } else if (!type_compatible(result_ty, else_ty)) { perr(p, "conditional operator type mismatch"); } - if (cg_top_type(p->cg) != result_ty) { - cg_convert(p->cg, result_ty); + if (pcg_top_type(p) != result_ty) { + pcg_convert(p, result_ty); } - cg_push_local_typed(p->cg, tmp, result_ty); - cg_swap(p->cg); - cg_store(p->cg); - cg_drop(p->cg); - cg_label_place(p->cg, L_end); + pcg_push_local_typed(p, tmp, result_ty); + pcg_swap(p); + pcg_store(p); + pcg_drop(p); + pcg_label_place(p, L_end); if (common && common != result_ty) { FrameSlotDesc cfsd; FrameSlot ctmp; @@ -3314,18 +3314,18 @@ static void parse_ternary(Parser* p) { cfsd.align = c_abi_alignof(p->abi, common); cfsd.kind = FS_LOCAL; cfsd.flags = FSF_NONE; - ctmp = cg_local(p->cg, &cfsd); - cg_push_local_typed(p->cg, tmp, result_ty); - cg_load(p->cg); - cg_convert(p->cg, common); - cg_push_local_typed(p->cg, ctmp, common); - cg_swap(p->cg); - cg_store(p->cg); - cg_drop(p->cg); - cg_push_local_typed(p->cg, ctmp, common); + ctmp = pcg_local(p, &cfsd); + pcg_push_local_typed(p, tmp, result_ty); + pcg_load(p); + pcg_convert(p, common); + pcg_push_local_typed(p, ctmp, common); + pcg_swap(p); + pcg_store(p); + pcg_drop(p); + pcg_push_local_typed(p, ctmp, common); return; } - cg_push_local_typed(p->cg, tmp, result_ty); + pcg_push_local_typed(p, tmp, result_ty); } void parse_assign_expr(Parser* p) { @@ -3373,7 +3373,7 @@ void parse_assign_expr(Parser* p) { perr(p, "assignment requires modifiable lvalue"); } advance(p); - const Type* lhs = cg_top_type(p->cg); + const Type* lhs = pcg_top_type(p); if (compound == BO_SHR_S && !c_abi_type_info(p->abi, lhs).signed_) compound = BO_SHR_U; { @@ -3398,14 +3398,14 @@ void parse_assign_expr(Parser* p) { parse_assign_expr(p); to_rvalue(p); { - const Type* rhs = cg_top_type(p->cg); + const Type* rhs = pcg_top_type(p); CSemCheck chk = c_sem_check_assignment(p->pool, lhs, rhs, C_SEM_ASSIGN_EXPR); if (!chk.ok) perr(p, "%.*s", CFREE_SLICE_ARG(cfree_slice_cstr(chk.message))); } coerce_top_to_lvalue(p); - cg_store(p->cg); + pcg_store(p); return; } { @@ -3418,11 +3418,11 @@ void parse_assign_expr(Parser* p) { } pcg_dup_type(p); } - cg_load(p->cg); + pcg_load(p); parse_assign_expr(p); to_rvalue(p); { - const Type* rhs = cg_top_type(p->cg); + const Type* rhs = pcg_top_type(p); int op = '+'; switch (compound) { case BO_IADD: @@ -3469,8 +3469,8 @@ void parse_assign_expr(Parser* p) { if (compound == BO_IADD || compound == BO_ISUB) { emit_add_or_sub(p, compound); } else { - const Type* lt = cg_top2_type(p->cg); - const Type* rt = cg_top_type(p->cg); + const Type* lt = pcg_top2_type(p); + const Type* rt = pcg_top_type(p); const Type* common = common_fp_type(p, lt, rt); if (common) { if (compound == BO_SREM) @@ -3479,19 +3479,19 @@ void parse_assign_expr(Parser* p) { } else { const Type* icommon = cint_common_type(p, lt, rt); coerce_arith_operands(p, icommon); - cg_binop(p->cg, int_div_rem_binop(compound, icommon)); + pcg_binop(p, int_div_rem_binop(compound, icommon)); } } coerce_top_to_type(p, lhs); if (p->cg_type_sp >= 2) p->cg_type_stack[p->cg_type_sp - 2u] = lhs; - cg_store(p->cg); + pcg_store(p); } void parse_expr(Parser* p) { parse_assign_expr(p); while (is_punct(&p->cur, ',')) { advance(p); - cg_drop(p->cg); + pcg_drop(p); parse_assign_expr(p); } } diff --git a/lang/c/parse/parse_init.c b/lang/c/parse/parse_init.c @@ -146,7 +146,7 @@ static int try_init_aggregate_from_expr(Parser* p, FrameSlot slot, save_sp = p->cg_type_sp; pcg_codegen_suppress_push(p); parse_assign_expr(p); - expr_ty = cg_top_type(p->cg); + expr_ty = pcg_top_type(p); compatible = type_compatible(type_unqual(p->pool, ty), type_unqual(p->pool, expr_ty)); p->cg_type_sp = save_sp; @@ -157,7 +157,7 @@ static int try_init_aggregate_from_expr(Parser* p, FrameSlot slot, parse_assign_expr(p); if (!type_compatible(type_unqual(p->pool, ty), - type_unqual(p->pool, cg_top_type(p->cg)))) { + type_unqual(p->pool, pcg_top_type(p)))) { perr(p, "incompatible aggregate initializer"); } emit_struct_copy_into_slot(p, slot, arr_ty, offset, ty); @@ -168,7 +168,7 @@ static int try_init_aggregate_from_expr(Parser* p, FrameSlot slot, * local `slot` (whose type is `arr_ty`), with element type `elem_ty`. */ void push_subobject_lv(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset, const Type* elem_ty) { - cg_push_local_typed(p->cg, slot, arr_ty); + pcg_push_local_typed(p, slot, arr_ty); /* Fold the byte offset onto the local lvalue's aux; the next * load/store/addr will bake it into the memop's ea.offset. The result is an * lvalue of elem_ty backed by the frame slot. */ @@ -210,16 +210,16 @@ static void emit_copy_leaf(Parser* p, FrameSlot dst_slot, FrameSlot src_ptr_slot, const Type* src_ptr_ty, u32 src_off, const Type* leaf_ty) { push_subobject_lv(p, dst_slot, dst_arr_ty, dst_off, leaf_ty); - cg_push_local_typed(p->cg, src_ptr_slot, src_ptr_ty); - cg_load(p->cg); + pcg_push_local_typed(p, src_ptr_slot, src_ptr_ty); + pcg_load(p); /* TOS is now a pointer rvalue (the loaded source pointer). Retag as a * C-language lvalue with POINTER_RV base, then fold the source byte offset - * onto its aux. The next cg_load consumes the EA into the memop. */ + * onto its aux. The next pcg_load consumes the EA into the memop. */ pcg_deref(p, leaf_ty); pcg_lv_member(p, (i64)src_off, leaf_ty, 0, 0, 0); - cg_load(p->cg); - cg_store(p->cg); - cg_drop(p->cg); + pcg_load(p); + pcg_store(p); + pcg_drop(p); } /* Walk a (possibly nested) aggregate, emitting a leaf load+store for each @@ -270,18 +270,18 @@ void emit_struct_copy_into_slot(Parser* p, FrameSlot dst_slot, const Type* ptr_ty = type_ptr(p->pool, ty); FrameSlotDesc fsd; FrameSlot src_ptr_slot; - cg_addr(p->cg); + pcg_addr(p); memset(&fsd, 0, sizeof fsd); fsd.type = ptr_ty; fsd.size = c_abi_sizeof(p->abi, ptr_ty); fsd.align = c_abi_alignof(p->abi, ptr_ty); fsd.kind = FS_LOCAL; fsd.flags = FSF_NONE; - src_ptr_slot = cg_local(p->cg, &fsd); - cg_push_local_typed(p->cg, src_ptr_slot, ptr_ty); - cg_swap(p->cg); - cg_store(p->cg); - cg_drop(p->cg); + src_ptr_slot = pcg_local(p, &fsd); + pcg_push_local_typed(p, src_ptr_slot, ptr_ty); + pcg_swap(p); + pcg_store(p); + pcg_drop(p); emit_walk_copy(p, dst_slot, dst_arr_ty, dst_off, src_ptr_slot, ptr_ty, 0, ty); } @@ -302,9 +302,9 @@ static void zero_init_at(Parser* p, FrameSlot slot, const Type* arr_ty, if (f->flags & FIELD_ZERO_WIDTH) continue; if (f->flags & FIELD_BITFIELD) { push_record_field_lv(p, slot, arr_ty, offset, ty, i); - cg_push_int(p->cg, 0, f->type); - cg_store(p->cg); - cg_drop(p->cg); + pcg_push_int(p, 0, f->type); + pcg_store(p); + pcg_drop(p); continue; } { @@ -325,9 +325,9 @@ static void zero_init_at(Parser* p, FrameSlot slot, const Type* arr_ty, return; } push_subobject_lv(p, slot, arr_ty, offset, ty); - cg_push_int(p->cg, 0, ty); - cg_store(p->cg); - cg_drop(p->cg); + pcg_push_int(p, 0, ty); + pcg_store(p); + pcg_drop(p); } static void init_field_at(Parser* p, FrameSlot slot, const Type* arr_ty, @@ -340,15 +340,15 @@ static void init_field_at(Parser* p, FrameSlot slot, const Type* arr_ty, parse_assign_expr(p); to_rvalue(p); { - const Type* rhs = cg_top_type(p->cg); + const Type* rhs = pcg_top_type(p); CSemCheck chk = c_sem_check_assignment(p->pool, f->type, rhs, C_SEM_ASSIGN_INIT); if (!chk.ok) perr(p, "%.*s", CFREE_SLICE_ARG(cfree_slice_cstr(chk.message))); } coerce_top_to_lvalue(p); - cg_store(p->cg); - cg_drop(p->cg); + pcg_store(p); + pcg_drop(p); return; } init_at(p, slot, arr_ty, rec_offset + L->fields[field_index].offset, f->type); @@ -367,17 +367,17 @@ static void init_string_at(Parser* p, FrameSlot slot, const Type* arr_ty, if (copy > count) copy = count; for (i = 0; i < copy; ++i) { push_subobject_lv(p, slot, arr_ty, offset + (u32)i * elem_size, elem_ty); - cg_push_int(p->cg, + pcg_push_int(p, (i64)decode_lit_unit_le(bytes + i * elem_size, elem_size), elem_ty); - cg_store(p->cg); - cg_drop(p->cg); + pcg_store(p); + pcg_drop(p); } for (; i < count; ++i) { push_subobject_lv(p, slot, arr_ty, offset + (u32)i * elem_size, elem_ty); - cg_push_int(p->cg, 0, elem_ty); - cg_store(p->cg); - cg_drop(p->cg); + pcg_push_int(p, 0, elem_ty); + pcg_store(p); + pcg_drop(p); } cfree_compiler_context(p->c)->heap->free(cfree_compiler_context(p->c)->heap, bytes, 0); @@ -534,9 +534,9 @@ static u32 init_struct_fields(Parser* p, FrameSlot slot, const Type* arr_ty, if (zf->flags & FIELD_BITFIELD) { if (!(zf->flags & FIELD_ZERO_WIDTH)) { push_record_field_lv(p, slot, arr_ty, offset, ty, zero_lo); - cg_push_int(p->cg, 0, zf->type); - cg_store(p->cg); - cg_drop(p->cg); + pcg_push_int(p, 0, zf->type); + pcg_store(p); + pcg_drop(p); } } else { u32 zoff = offset + L->fields[zero_lo].offset; @@ -588,9 +588,9 @@ static u32 init_struct_fields(Parser* p, FrameSlot slot, const Type* arr_ty, if (f->flags & FIELD_BITFIELD) { if (!(f->flags & FIELD_ZERO_WIDTH)) { push_record_field_lv(p, slot, arr_ty, offset, ty, j); - cg_push_int(p->cg, 0, f->type); - cg_store(p->cg); - cg_drop(p->cg); + pcg_push_int(p, 0, f->type); + pcg_store(p); + pcg_drop(p); } } else { u32 foff = offset + L->fields[j].offset; @@ -632,9 +632,9 @@ static void init_aggregate_remainder(Parser* p, FrameSlot slot, if (f->flags & FIELD_BITFIELD) { if (!(f->flags & FIELD_ZERO_WIDTH)) { push_record_field_lv(p, slot, arr_ty, offset, ty, i); - cg_push_int(p->cg, 0, f->type); - cg_store(p->cg); - cg_drop(p->cg); + pcg_push_int(p, 0, f->type); + pcg_store(p); + pcg_drop(p); } } else { const Type* fty = init_field_type_at(ty, i); @@ -765,14 +765,14 @@ void init_at(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset, parse_assign_expr(p); to_rvalue(p); { - const Type* rhs = cg_top_type(p->cg); + const Type* rhs = pcg_top_type(p); CSemCheck chk = c_sem_check_assignment(p->pool, ty, rhs, C_SEM_ASSIGN_INIT); if (!chk.ok) perr(p, "%.*s", CFREE_SLICE_ARG(cfree_slice_cstr(chk.message))); } coerce_top_to_lvalue(p); - cg_store(p->cg); - cg_drop(p->cg); + pcg_store(p); + pcg_drop(p); if (had_brace) { accept_punct(p, ','); expect_punct(p, '}', "'}' after scalar initializer"); diff --git a/lang/c/parse/parse_stmt.c b/lang/c/parse/parse_stmt.c @@ -40,13 +40,13 @@ static void parse_if_stmt(Parser* p) { expect_punct(p, '(', "'('"); parse_expr(p); to_rvalue(p); - if (!c_type_is_scalar(cg_top_type(p->cg))) { + if (!c_type_is_scalar(pcg_top_type(p))) { perr(p, "if condition requires scalar type"); } cond_known = cfree_cg_top_const_int(p->cg, &cond); expect_punct(p, ')', "')'"); if (cond_known) { - cg_drop(p->cg); + pcg_drop(p); if (cond) { parse_stmt(p); if (accept_kw_stmt(p, KW_ELSE)) parse_stmt_suppressed(p); @@ -78,7 +78,7 @@ static void parse_while_stmt(Parser* p) { /* Drive the structured-CF API so the C-source target can lower this to * `for (;;) { … break; … continue; }` instead of goto soup. The labels * the scope mints are reused as cur_break/cur_continue, so parse_break - * /parse_continue/etc. keep using their existing raw `cg_jump` calls — + * /parse_continue/etc. keep using their existing raw `pcg_jump` calls — * the C target recognizes the labels as the innermost scope's * boundaries and emits the structured keywords on its own. */ CfreeCgScope scope = cfree_cg_scope_begin(p->cg, CFREE_CG_TYPE_NONE); @@ -89,24 +89,24 @@ static void parse_while_stmt(Parser* p) { expect_punct(p, '(', "'('"); parse_expr(p); to_rvalue(p); - if (!c_type_is_scalar(cg_top_type(p->cg))) { + if (!c_type_is_scalar(pcg_top_type(p))) { perr(p, "while condition requires scalar type"); } expect_punct(p, ')', "')'"); - cg_branch_false(p->cg, L_end); + pcg_branch_false(p, L_end); p->cur_break = L_end; p->cur_continue = L_top; parse_stmt(p); p->cur_break = saved_break; p->cur_continue = saved_continue; - cg_jump(p->cg, L_top); + pcg_jump(p, L_top); cfree_cg_scope_end(p->cg, scope); } static void parse_for_stmt(Parser* p) { - CGLabel L_top = cg_label_new(p->cg); - CGLabel L_step = cg_label_new(p->cg); - CGLabel L_end = cg_label_new(p->cg); + CGLabel L_top = pcg_label_new(p); + CGLabel L_step = pcg_label_new(p); + CGLabel L_end = pcg_label_new(p); CGLabel saved_break = p->cur_break; CGLabel saved_continue = p->cur_continue; @@ -120,33 +120,33 @@ static void parse_for_stmt(Parser* p) { parse_local_decl(p, &specs); } else { parse_expr(p); - cg_drop(p->cg); + pcg_drop(p); expect_punct(p, ';', "';'"); } } - cg_label_place(p->cg, L_top); + pcg_label_place(p, L_top); if (!is_punct(&p->cur, ';')) { parse_expr(p); to_rvalue(p); - if (!c_type_is_scalar(cg_top_type(p->cg))) { + if (!c_type_is_scalar(pcg_top_type(p))) { perr(p, "for condition requires scalar type"); } - cg_branch_false(p->cg, L_end); + pcg_branch_false(p, L_end); } expect_punct(p, ';', "';'"); { - CGLabel L_body = cg_label_new(p->cg); - cg_jump(p->cg, L_body); - cg_label_place(p->cg, L_step); + CGLabel L_body = pcg_label_new(p); + pcg_jump(p, L_body); + pcg_label_place(p, L_step); if (!is_punct(&p->cur, ')')) { parse_expr(p); - cg_drop(p->cg); + pcg_drop(p); } - cg_jump(p->cg, L_top); + pcg_jump(p, L_top); expect_punct(p, ')', "')'"); - cg_label_place(p->cg, L_body); + pcg_label_place(p, L_body); p->cur_break = L_end; p->cur_continue = L_step; @@ -154,8 +154,8 @@ static void parse_for_stmt(Parser* p) { p->cur_break = saved_break; p->cur_continue = saved_continue; - cg_jump(p->cg, L_step); - cg_label_place(p->cg, L_end); + pcg_jump(p, L_step); + pcg_label_place(p, L_end); } scope_pop(p); } @@ -165,7 +165,7 @@ static void parse_return_stmt(Parser* p) { if (p->cur_func_ret && p->cur_func_ret->kind != TY_VOID) { perr(p, "return with no value in non-void function"); } - cg_ret(p->cg, 0); + pcg_ret(p, 0); return; } if (p->cur_func_ret && p->cur_func_ret->kind == TY_VOID) { @@ -174,7 +174,7 @@ static void parse_return_stmt(Parser* p) { parse_expr(p); to_rvalue(p); { - const Type* rhs = cg_top_type(p->cg); + const Type* rhs = pcg_top_type(p); CSemCheck chk = c_sem_check_assignment(p->pool, p->cur_func_ret, rhs, C_SEM_ASSIGN_RETURN); if (!chk.ok) @@ -182,51 +182,51 @@ static void parse_return_stmt(Parser* p) { } /* Convert the value to the function return type, as `return` performs the * equivalent of assignment to an object of the return type (§6.8.6.4). - * cg_ret expects the value already in the return type; without this a + * pcg_ret expects the value already in the return type; without this a * narrower value (e.g. a _Bool call result returned from an int function) * would be reloaded at the wider return width and read adjacent bytes. */ coerce_top_to_type(p, p->cur_func_ret); expect_punct(p, ';', "';' after return value"); - cg_ret(p->cg, 1); + pcg_ret(p, 1); } static void parse_break_stmt(Parser* p) { if (p->cur_break == 0) perr(p, "'break' outside of loop or switch"); - cg_jump(p->cg, p->cur_break); + pcg_jump(p, p->cur_break); expect_punct(p, ';', "';' after break"); } static void parse_continue_stmt(Parser* p) { if (p->cur_continue == 0) perr(p, "'continue' outside of loop"); - cg_jump(p->cg, p->cur_continue); + pcg_jump(p, p->cur_continue); expect_punct(p, ';', "';' after continue"); } static void parse_do_stmt(Parser* p) { - CGLabel L_top = cg_label_new(p->cg); - CGLabel L_cond = cg_label_new(p->cg); - CGLabel L_end = cg_label_new(p->cg); + CGLabel L_top = pcg_label_new(p); + CGLabel L_cond = pcg_label_new(p); + CGLabel L_end = pcg_label_new(p); CGLabel saved_break = p->cur_break; CGLabel saved_continue = p->cur_continue; - cg_label_place(p->cg, L_top); + pcg_label_place(p, L_top); p->cur_break = L_end; p->cur_continue = L_cond; parse_stmt(p); p->cur_break = saved_break; p->cur_continue = saved_continue; - cg_label_place(p->cg, L_cond); + pcg_label_place(p, L_cond); if (!is_kw(p, &p->cur, KW_WHILE)) perr(p, "expected 'while' after do-body"); advance(p); /* while */ expect_punct(p, '(', "'('"); parse_expr(p); to_rvalue(p); - if (!c_type_is_scalar(cg_top_type(p->cg))) { + if (!c_type_is_scalar(pcg_top_type(p))) { perr(p, "do-while condition requires scalar type"); } expect_punct(p, ')', "')' after do-while condition"); expect_punct(p, ';', "';' after do-while"); - cg_branch_true(p->cg, L_top); - cg_label_place(p->cg, L_end); + pcg_branch_true(p, L_top); + pcg_label_place(p, L_end); } GotoLabel* label_get_or_create(Parser* p, Sym name, SrcLoc loc) { @@ -238,7 +238,7 @@ GotoLabel* label_get_or_create(Parser* p, Sym name, SrcLoc loc) { if (!gl) perr(p, "out of memory in label_get_or_create"); memset(gl, 0, sizeof *gl); gl->name = name; - gl->label = cg_label_new(p->cg); + gl->label = pcg_label_new(p); gl->placed = 0; gl->first_use = loc; gl->min_forward_vla_mark = p->vla_mark; @@ -273,7 +273,7 @@ static void parse_computed_goto(Parser* p) { advance(p); /* '*' */ parse_expr(p); to_rvalue(p); - if (!type_is_ptr(cg_top_type(p->cg))) { + if (!type_is_ptr(pcg_top_type(p))) { perr(p, "computed goto requires a pointer operand"); } expect_punct(p, ';', "';' after computed goto"); @@ -317,7 +317,7 @@ static void parse_goto_stmt(Parser* p) { } else if (p->vla_mark < gl->min_forward_vla_mark) { gl->min_forward_vla_mark = p->vla_mark; } - cg_jump(p->cg, gl->label); + pcg_jump(p, gl->label); } static void parse_label_stmt(Parser* p) { @@ -333,7 +333,7 @@ static void parse_label_stmt(Parser* p) { } gl->placed = 1; gl->label_vla_mark = p->vla_mark; - cg_label_place(p->cg, gl->label); + pcg_label_place(p, gl->label); parse_stmt(p); } @@ -348,8 +348,8 @@ static void parse_case_stmt(Parser* p) { if (ce->value == v) perr(p, "duplicate case value"); } expect_punct(p, ':', "':' after case constant"); - L = cg_label_new(p->cg); - cg_label_place(p->cg, L); + L = pcg_label_new(p); + pcg_label_place(p, L); ce = arena_new(p->pool->arena, CaseEntry); if (!ce) perr(p, "out of memory in parse_case_stmt"); ce->value = v; @@ -364,8 +364,8 @@ static void parse_default_stmt(Parser* p) { if (!p->cur_switch) perr(p, "'default' label not in switch statement"); expect_punct(p, ':', "':' after default"); if (p->cur_switch->default_label != 0) perr(p, "duplicate 'default' label"); - L = cg_label_new(p->cg); - cg_label_place(p->cg, L); + L = pcg_label_new(p); + pcg_label_place(p, L); p->cur_switch->default_label = L; parse_stmt(p); } @@ -380,7 +380,7 @@ static void parse_switch_stmt(Parser* p) { * emit a real `switch (sel) { case V: goto L_V; …; default: goto * L_def; }`. */ CfreeCgScope scope = cfree_cg_scope_begin(p->cg, CFREE_CG_TYPE_NONE); - CGLabel L_dispatch = cg_label_new(p->cg); + CGLabel L_dispatch = pcg_label_new(p); CGLabel L_end = cfree_cg_scope_break_label(p->cg, scope); CGLabel saved_break = p->cur_break; SwitchCtx ctx; @@ -394,7 +394,7 @@ static void parse_switch_stmt(Parser* p) { expect_punct(p, '(', "'('"); parse_expr(p); to_rvalue(p); - vty = cg_top_type(p->cg); + vty = pcg_top_type(p); if (!vty) vty = type_prim(p->pool, TY_INT); if (!type_is_int(vty)) perr(p, "switch expression requires integer type"); /* C99 6.8.4.2: the integer promotions are performed on the controlling @@ -408,7 +408,7 @@ static void parse_switch_stmt(Parser* p) { else prom = type_promoted(p->pool, prom); if (prom && prom != vty) { - cg_convert(p->cg, prom); + pcg_convert(p, prom); vty = prom; } } @@ -420,16 +420,16 @@ static void parse_switch_stmt(Parser* p) { fsd.size = c_abi_sizeof(p->abi, vty); fsd.align = c_abi_alignof(p->abi, vty); fsd.kind = FS_LOCAL; - ctx.value_slot = cg_local(p->cg, &fsd); + ctx.value_slot = pcg_local(p, &fsd); ctx.value_type = vty; ctx.parent = saved_switch; - cg_push_local_typed(p->cg, ctx.value_slot, vty); - cg_swap(p->cg); - cg_store(p->cg); - cg_drop(p->cg); + pcg_push_local_typed(p, ctx.value_slot, vty); + pcg_swap(p); + pcg_store(p); + pcg_drop(p); - cg_jump(p->cg, L_dispatch); + pcg_jump(p, L_dispatch); p->cur_switch = &ctx; p->cur_break = L_end; @@ -437,9 +437,9 @@ static void parse_switch_stmt(Parser* p) { p->cur_break = saved_break; p->cur_switch = saved_switch; - cg_jump(p->cg, L_end); + pcg_jump(p, L_end); - cg_label_place(p->cg, L_dispatch); + pcg_label_place(p, L_dispatch); /* Reverse cases into source order; CaseEntry list grows at the head * during parsing so iteration here is LIFO without the flip. */ prev = NULL; @@ -470,8 +470,8 @@ static void parse_switch_stmt(Parser* p) { i++; } } - cg_push_local_typed(p->cg, ctx.value_slot, vty); - cg_load(p->cg); + pcg_push_local_typed(p, ctx.value_slot, vty); + pcg_load(p); { CfreeCgSwitch sw; memset(&sw, 0, sizeof sw); @@ -604,22 +604,22 @@ static void parse_asm_stmt(Parser* p) { c.dir = ASM_OUT; expect_punct(p, '(', "'(' before asm output lvalue"); parse_assign_expr(p); - val_ty = cg_top_type(p->cg); + val_ty = pcg_top_type(p); if (!val_ty) perr(p, "asm output: cannot determine lvalue type"); c.type = val_ty; - cg_addr(p->cg); - ptr_ty = cg_top_type(p->cg); + pcg_addr(p); + ptr_ty = pcg_top_type(p); if (!ptr_ty) perr(p, "asm output: cannot take address"); memset(&fsd, 0, sizeof fsd); fsd.type = ptr_ty; fsd.size = 8; fsd.align = 8; fsd.kind = FS_LOCAL; - slot = cg_local(p->cg, &fsd); - cg_push_local_typed(p->cg, slot, ptr_ty); - cg_swap(p->cg); - cg_store(p->cg); - cg_drop(p->cg); + slot = pcg_local(p, &fsd); + pcg_push_local_typed(p, slot, ptr_ty); + pcg_swap(p); + pcg_store(p); + pcg_drop(p); lv.addr_slot = slot; lv.ptr_ty = ptr_ty; lv.val_ty = val_ty; @@ -657,7 +657,7 @@ static void parse_asm_stmt(Parser* p) { expect_punct(p, '(', "'(' before asm input expression"); parse_assign_expr(p); to_rvalue(p); - c.type = cg_top_type(p->cg); + c.type = pcg_top_type(p); expect_punct(p, ')', "')' after asm input expression"); if (nin == cap_in) { u32 nc = cap_in * 2; @@ -738,10 +738,10 @@ static void parse_asm_stmt(Parser* p) { "matching-digit syntax"); } AsmOutLValue* lv = &out_lvs[i]; - cg_push_local_typed(p->cg, lv->addr_slot, lv->ptr_ty); - cg_load(p->cg); - cg_deref(p->cg, lv->val_ty); - cg_load(p->cg); + pcg_push_local_typed(p, lv->addr_slot, lv->ptr_ty); + pcg_load(p); + pcg_deref(p, lv->val_ty); + pcg_load(p); AsmConstraint mc; memset(&mc, 0, sizeof mc); mc.str = k_match_strs[i]; @@ -751,19 +751,19 @@ static void parse_asm_stmt(Parser* p) { } } - cg_set_loc(p->cg, loc); - cg_inline_asm(p->cg, tmpl, outs, nout, ins, nin, clobbers, nclob); + pcg_set_loc(p, loc); + pcg_inline_asm(p, tmpl, outs, nout, ins, nin, clobbers, nclob); if (nout > 0) { u32 i; for (i = nout; i-- > 0;) { AsmOutLValue* lv = &out_lvs[i]; - cg_push_local_typed(p->cg, lv->addr_slot, lv->ptr_ty); - cg_load(p->cg); - cg_deref(p->cg, lv->val_ty); - cg_swap(p->cg); - cg_store(p->cg); - cg_drop(p->cg); + pcg_push_local_typed(p, lv->addr_slot, lv->ptr_ty); + pcg_load(p); + pcg_deref(p, lv->val_ty); + pcg_swap(p); + pcg_store(p); + pcg_drop(p); } } } @@ -796,7 +796,7 @@ void parse_compound_stmt(Parser* p) { } void parse_stmt(Parser* p) { - cg_set_loc(p->cg, tok_loc_stmt(&p->cur)); + pcg_set_loc(p, tok_loc_stmt(&p->cur)); if (p->cur.kind == TOK_IDENT && ident_kw_stmt(p, p->cur.v.ident) == KW_NONE) { Tok n = peek1(p); if (is_punct(&n, ':')) { @@ -874,6 +874,6 @@ void parse_stmt(Parser* p) { } /* Expression statement. */ parse_expr(p); - cg_drop(p->cg); + pcg_drop(p); expect_punct(p, ';', "';' after expression"); } diff --git a/lang/c/parse/parse_type.c b/lang/c/parse/parse_type.c @@ -1388,14 +1388,14 @@ int parse_decl_suffix(Parser* p, DeclSuffix* out) { fsd.size = c_abi_sizeof(p->abi, fsd.type); fsd.align = c_abi_alignof(p->abi, fsd.type); fsd.kind = FS_LOCAL; - out->vla_count_slot = cg_local(p->cg, &fsd); + out->vla_count_slot = pcg_local(p, &fsd); parse_assign_expr(p); to_rvalue(p); - cg_push_local_typed(p->cg, out->vla_count_slot, fsd.type); - cg_swap(p->cg); + pcg_push_local_typed(p, out->vla_count_slot, fsd.type); + pcg_swap(p); coerce_top_to_lvalue(p); - cg_store(p->cg); - cg_drop(p->cg); + pcg_store(p); + pcg_drop(p); p->vla_pending = 1; ++p->vla_mark; p->vla_pending_count_slot = out->vla_count_slot;