fix(gen,renum): 指针操作符目标写入落盘 + REnum tag 三侧口径统一,修 kind() CastError

- AssignGenMixin: 补 UnaryOp(Deref) 赋值目标分支(*p = v / *&x = *&y),非 Deref 的 &x/-x/~x fail-fast;*p += v 真正实现;Tuple/List 目标合并

- CallGenDispatch: kind() 改四级 REnum 判据(变体表 / struct __tag / pointee 带 __tag / X.field 声明类型反推);修正 build_load 第一参数误传指针类型 rk_tag_p(生成 load i32*, i32* 使返回值 Ty 为 i32*,导致 CallGenLib.vp:355 vk_a: int = val.Ty.kind() 报指针隐式转整数的 CastError),rk_load 分支同步改 rk_ty.Pointee

- CallGenCtor / MatchGenMixin: __tag 读/写/比统一取字段声明类型 FieldEntry.Ty

- Test/FieldReadTest: 字段读取探针
This commit is contained in:
TermiNexus committed 2026-09-27 00:19:44 +08:00
1 parent bcf66edebe
commit f0309e4904
6 files changed
+323 -35

No files matched your search

+75 -3
View File
@@ -1534,9 +1534,47 @@ novirtual class AssignGenMixin:
llvmlite.build_store(builder, result, elem_ptr, vol_sa)
return 0
# UnaryOp 目标: *p += v —— 解引用增强赋值。
# 目标节点是 UnaryOp(Deref)(SetStoreContext 不改 UnaryOp 的 ctx),
# 与 `*p = v` 同一形态;流程同 Subscript 分支:
# 操作数求值取指针 → load 当前值 → 二元运算 → store 回同址。
if tk == ast.ASTKind.UnaryOp:
uo_ag: ast.UnaryOp* = ast.UnaryOp*(target)
if uo_ag is None or uo_ag.operand is None:
self.Gen.TypeGenErr.fatal_error(target, "增量赋值目标单目运算缺少操作数", "TypeError")
if uo_ag.op != ast.OpKind.Deref:
self.Gen.TypeGenErr.fatal_error(target,
"增量赋值目标只支持单目 '*' 解引用(&x / -x / ~x 不是合法左值)", "SyntaxError")
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
mod: llvmlite.LLVMModule* = trans.Module
ptr_ag: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, uo_ag.operand, None, 0, trans)
if ptr_ag is None or ptr_ag.Ty is None \
or self.Gen.ExprGenBase.is_ptr_type(ptr_ag.Ty) == 0:
self.Gen.TypeGenErr.fatal_error(target,
"增量赋值 '*' 的操作数必须是指针类型(类型推断退化)", "TypeError")
ty_ag: llvmlite.LLVMType* = ptr_ag.Ty.Pointee
if ty_ag is None:
self.Gen.TypeGenErr.fatal_error(target,
"解引用增量赋值的目标类型缺失(pointee 为空)", "TypeError")
old_ag: llvmlite.Value* = llvmlite.build_load(builder, ty_ag, ptr_ag, 0)
if old_ag is None:
self.Gen.TypeGenErr.fatal_error(target, "无法加载解引用当前值", "TypeError")
rhs_ag: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, aug.value, None, 0, trans)
if rhs_ag is None:
self.Gen.TypeGenErr.fatal_error(target, "rhs 翻译失败", "TypeError")
res_ag: llvmlite.Value* = self._apply_aug_op(pool, builder, aug.op, old_ag, rhs_ag, node, trans, target)
if res_ag is None:
self.Gen.TypeGenErr.fatal_error(target, f"解引用二元运算失败 op={aug.op}", "TypeError")
res_ag = self.Gen.ExprGenBase.coerce_to_type(builder, res_ag, ty_ag, node, trans)
if res_ag is None:
self.Gen.TypeGenErr.fatal_error(target, "类型对齐失败", "TypeError")
llvmlite.build_store(builder, res_ag, ptr_ag, 0)
return 0
if tk != ast.ASTKind.Name:
# fail-fast: 不支持的 AugAssign 目标类型
self.Gen.TypeGenErr.fatal_error(target, "AugAssign 目标类型不支持,仅支持 Name/Attribute/Subscript", "TypeError")
self.Gen.TypeGenErr.fatal_error(target, "AugAssign 目标类型不支持,仅支持 Name/Attribute/Subscript/*解引用", "TypeError")
nm: ast.Name* = ast.Name*(target)
if nm is None or nm.id is None:
@@ -2700,10 +2738,13 @@ novirtual class AssignGenMixin:
tk: int = target.kind()
# Tuple 赋值: a, b = f() 多返回值解包
# Tuple/List 赋值: a, b = f() / [a, b] = f() 多返回值解包
# rhs_val 是匿名 struct 值(函数返回 tuple[T1,T2] 打包)→ alloca +
# store + GEP 逐字段 load → store 到各 Name 目标。
if tk == ast.ASTKind.Tuple:
# ast.List 与 ast.Tuple 字段表逐字相同(Nodes.py:119-120 均为
# ('elts','ctx')),故按 Tuple 视图统一取 elts;此前只认 Tuple ⇒
# `[a, b] = f()` 落入无分支区被静默丢弃(不落盘、不报错)。
if tk == ast.ASTKind.Tuple or tk == ast.ASTKind.List:
tgt_tup: ast.Tuple* = ast.Tuple*(target)
tgt_elts: list[ast.AST*]* = tgt_tup.elts
# 守卫:rhs 不是 struct(tuple 打包)时跳过本 target
@@ -2887,6 +2928,37 @@ novirtual class AssignGenMixin:
self.Gen.TypeGenErr.fatal_error(target, "subscript ptr is None")
continue
# UnaryOp 目标: *p = val —— 解引用写入(与读侧同一节点形态)。
# 解析链:语句级 Assign 走 vast_c.c ParseSimpleStmt 的
# ParseExprList + SetStoreContext;`*p` 由 ParseFactor 产出
# UnaryOp(Deref)(与 `*p` 读侧完全同形),而 SetStoreContext 只改
# Attribute/Subscript/Name/Tuple/List/Starred 的 ctx,**不改 UnaryOp**
# ⇒ 赋值目标就是 ctx=Load 的 UnaryOp(Deref)。
# 此前目标分派(Tuple/Subscript/Attribute/Name)无 UnaryOp 分支且无兜底
# ⇒ 该语句被整条静默丢弃(既不落盘也不报错):memhub 的块头
# `(order<<1)|1`、空闲链 next、canary 三处写入全不发射 ⇒ 块头恒为 0
# (free 被拒)、free_lists 链读到未初始化 0xBE、池单调漏满 ⇒ 1 GiB OOM。
# `&x`/`-x` 作目标不是合法左值,故除 Deref 外一律 fail-fast。
if tk == ast.ASTKind.UnaryOp:
uo_w: ast.UnaryOp* = ast.UnaryOp*(target)
if uo_w is None or uo_w.operand is None:
self.Gen.TypeGenErr.fatal_error(target, "赋值目标单目运算缺少操作数", "TypeError")
if uo_w.op != ast.OpKind.Deref:
self.Gen.TypeGenErr.fatal_error(target,
"赋值目标只支持单目 '*' 解引用(&x / -x / ~x 不是合法左值)", "SyntaxError")
ptr_w: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, uo_w.operand, None, 0, trans)
if ptr_w is None or ptr_w.Ty is None \
or self.Gen.ExprGenBase.is_ptr_type(ptr_w.Ty) == 0:
self.Gen.TypeGenErr.fatal_error(target,
"单目 '*' 赋值的操作数必须是指针类型(类型推断退化)", "TypeError")
pointee_w: llvmlite.LLVMType* = ptr_w.Ty.Pointee
if pointee_w is None:
self.Gen.TypeGenErr.fatal_error(target,
"解引用写入的目标类型缺失(pointee 为空)", "TypeError")
sv_w: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, pointee_w, node, trans)
llvmlite.build_store(builder, sv_w, ptr_w)
continue
# Attribute 赋值: obj.field = val
if tk == ast.ASTKind.Attribute:
# property setter 拦截: obj.attr = v 且 attr 是 @x.setter 方法时,