commit a6426a10c2e6ee9f983cedd3ac1ff386a91d7430
parent ab3b7e641d72f9d11e6be706098f0e12abd26967
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Wed, 27 May 2026 11:50:11 -0700
c/cg: emit FP add/sub for ++/-- on floating operands
pcg_inc_dec always lowered ++/-- via push_int + int_binop, so an
increment of a floating lvalue (e.g. mandelbrot's `++x`/`++y` loop
counters) emitted BO_IADD into an FP register, which the aarch64
backend cannot encode ("unsupported floating binary op"). Branch on the
operand type like pcg_binop does: floating operands step by 1.0 via an
FP add/sub, pointers by pointee size, everything else by 1. Factor the
shared step emission into pcg_emit_inc_step for the pre/post branches.
Diffstat:
1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/lang/c/parse/cg_adapter.c b/lang/c/parse/cg_adapter.c
@@ -844,6 +844,23 @@ void pcg_convert(Parser* p, const Type* dst) {
pcg_retag_top(p, dst);
}
+/* Emit "value <op> step" for an inc/dec, picking the float or integer binop
+ * based on the operand type. Floating operands step by 1.0 via an FP add/sub;
+ * pointers step by the pointee size and everything else by 1. */
+static void pcg_emit_inc_step(Parser* p, const Type* ty, BinOp op,
+ CfreeCgIntBinOp cg_op, const Type* step_ty,
+ u32 step) {
+ if (pcg_type_is_fp(ty)) {
+ BinOp fop = (op == BO_ISUB) ? BO_FSUB : BO_FADD;
+ cfree_cg_push_float(p->cg, 1.0, pcg_tid(p, ty));
+ cfree_cg_fp_binop(p->cg, pcg_fp_binop(fop), CFREE_CG_FP_NONE);
+ } else {
+ i64 amount = (ty && ty->kind == TY_PTR) ? (i64)step : 1;
+ cfree_cg_push_int(p->cg, amount, pcg_tid(p, step_ty));
+ cfree_cg_int_binop(p->cg, cg_op, 0);
+ }
+}
+
void pcg_inc_dec(Parser* p, BinOp op, int post) {
const Type* ty = pcg_top_type(p);
if (!pcg_emit_enabled(p)) {
@@ -899,23 +916,15 @@ void pcg_inc_dec(Parser* p, BinOp op, int post) {
cfree_cg_swap(p->cg);
cfree_cg_store(p->cg, r_access,
zero_ea); /* ..., lv-base[, idx], old */
- if (ty && ty->kind == TY_PTR) {
- cfree_cg_push_int(p->cg, step, pcg_tid(p, step_ty));
- } else {
- cfree_cg_push_int(p->cg, 1, pcg_tid(p, step_ty));
- }
- cfree_cg_int_binop(p->cg, cg_op, 0); /* ..., lv-base[, idx], new */
+ pcg_emit_inc_step(p, ty, op, cg_op, step_ty,
+ step); /* ..., lv-base[, idx], new */
cfree_cg_store(p->cg, access, ea); /* [] */
cfree_cg_push_local(p->cg, tmp);
cfree_cg_load(p->cg, r_access, zero_ea); /* [old] */
} else {
/* Compute new, stash new, store, then re-load new as result. */
- if (ty && ty->kind == TY_PTR) {
- cfree_cg_push_int(p->cg, step, pcg_tid(p, step_ty));
- } else {
- cfree_cg_push_int(p->cg, 1, pcg_tid(p, step_ty));
- }
- cfree_cg_int_binop(p->cg, cg_op, 0); /* ..., lv-base[, idx], new */
+ pcg_emit_inc_step(p, ty, op, cg_op, step_ty,
+ step); /* ..., lv-base[, idx], new */
cfree_cg_dup(p->cg); /* ..., lv-base[, idx], new, new */
cfree_cg_push_local(p->cg, tmp);
cfree_cg_swap(p->cg);