fix(transpyv): 跨模块链表 Next 字段改用访问器(消除 __inherited_N 占位名 fail-fast)

c 源码违规:llvmlite 的 Value/ParamNode/Function/Param/GlobalVariable/PhiIncoming/
SwitchCase 的 Next 继承自泛型基类 GSListNode[T],而其泛型特化体不在任何 .vpi 中
⇒ 导入侧 class_members 只有 __inherited_N 占位名;严格属性解析(回退已移除)下
裸写 `x.Next` fail-fast。现场:CallGenCall.vp `cur_fb = cur_fb.Next` 报
"[fast-fail] 属性 Next 在类 ParamNode 中找不到(class_members=[__inherited_0, Ty])"。

按仓库既有约定(_Type.md:链表遍历用 paramnode_get_next/paramnode_set_next;
VarGenMixin/TypeSpec/StructGenMixin/VpiReader 等已如此书写)统一改为访问器:
  value_get_next/value_set_next、paramnode_get_next/paramnode_set_next、
  function_get_next、param_get_next、globalvariable_get_next、
  phiincoming_set_next、switchcase_set_next
覆盖 24 个文件共 110 处(含 CallGenProp.vp:122 的嵌套读 cur_arg_pc.Next)。

访问器在 includes 侧为定义模块内直通实现(None 守卫 + x.Next),语义等价、零行为
变化。已全量扫描 core\Gen 全 47 文件与 Stub/Phase/core/main:App 侧已无裸继承字段
访问(剩余 .Next 命中全部在注释里)。
This commit is contained in:
TermiNexus committed 2026-09-28 21:20:58 +08:00
1 parent 75ea6fb9b2
commit 13080f646f
24 files changed
+118 -114

No files matched your search

+3 -3
View File
@@ -2694,7 +2694,7 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*,
if first_node_c is None:
first_node_c = pnode_c
if prev_node_c is not None:
prev_node_c.Next = pnode_c
llvmlite.paramnode_set_next(prev_node_c, pnode_c)
prev_node_c = pnode_c
# 4. 命名结构体类型名 "sha1.ClassName"(与定义侧 ClassGenDef 一致)
type_name_c: str = cls_name
@@ -2868,7 +2868,7 @@ def _inject_global_variable_declare(pool: memhub.MemBuddy*,
while cur_v is not None:
if cur_v.Name is not None and string.strcmp(cur_v.Name, gv_name_m) == 0:
return
cur_v = cur_v.Next
cur_v = llvmlite.globalvariable_get_next(cur_v)
# 解析注解类型(裸类 → Ptr(struct),CArray → 元素指针)
resolved_v: llvmlite.LLVMType* = None
if aa.annotation is not None:
@@ -4065,7 +4065,7 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: llvmlite.LLVMModule*) -> int:
if first_node is None:
first_node = nd
if prev_node is not None:
prev_node.Next = nd
llvmlite.paramnode_set_next(prev_node, nd)
prev_node = nd
struct_ty: llvmlite.LLVMType* = llvmlite.Struct(pool, first_node, total, e.Key)
if struct_ty is None:
+10 -10
View File
@@ -722,7 +722,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
if head is None:
head = pnode
if prev is not None:
prev.Next = pnode
llvmlite.paramnode_set_next(prev, pnode)
prev = pnode
ty_name: str = pool.alloc(128)
if ty_name is not None:
@@ -789,7 +789,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
size_val: llvmlite.Value* = llvmlite.const_int64(pool, frame_size)
if size_val is None:
return 0
size_val.Next = None
llvmlite.value_set_next(size_val, None)
# M7 帧池:i64 池头(0 = 空);帧首 8 字节存 next(覆盖 state/done,弹池后统一清零)
pool_gv: llvmlite.GlobalVariable* = self._get_coro_pool(pool, mod, trans, name)
@@ -838,7 +838,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
inc2: llvmlite.PhiIncoming* = llvmlite.new_phi_incoming(pool, miss_frame, miss_bb)
if inc1 is None or inc2 is None:
return 0
inc1.Next = inc2
llvmlite.phiincoming_set_next(inc1, inc2)
frame_ref: llvmlite.Value* = llvmlite.build_phi(builder, frame_ptr_ty, inc1, 2)
if frame_ref is None:
return 0
@@ -884,7 +884,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
while g is not None:
if g.Name is not None and string.strcmp(g.Name, pn_buf) == 0:
return g
g = g.Next
g = llvmlite.globalvariable_get_next(g)
return llvmlite.create_global_int(pool, mod, pn_buf, 64, 0)
def _register_coro_wake(self, trans: HT.Translator*,
@@ -1094,7 +1094,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
sw_head = sc
sw_tail = sc
else:
sw_tail.Next = sc
llvmlite.switchcase_set_next(sw_tail, sc)
sw_tail = sc
sw_count = sw_count + 1
llvmlite.build_switch(builder, state_val, exit_bb, sw_head, sw_count)
@@ -2187,7 +2187,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
continue
llvmlite.build_br(builder, loop_bb)
llvmlite.position_at_end(builder, loop_bb)
frame_ptr.Next = None
llvmlite.value_set_next(frame_ptr, None)
status: llvmlite.Value* = llvmlite.build_call(builder, resume_mangled, frame_ptr, 1, i32_ty, 0)
done_cond: llvmlite.Value* = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, status, llvmlite.const_int32(pool, 0))
llvmlite.build_cond_br(builder, done_cond, after_bb, loop_bb)
@@ -2260,12 +2260,12 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
av: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cl_a.args.get(j), None, 0, trans)
if av is None:
av = llvmlite.const_int32(pool, 0)
av.Next = None
llvmlite.value_set_next(av, None)
if args_head is None:
args_head = av
args_tail = av
else:
args_tail.Next = av
llvmlite.value_set_next(args_tail, av)
args_tail = av
args_count = args_count + 1
@@ -2273,7 +2273,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
child: llvmlite.Value* = llvmlite.build_call(builder, create_mangled, args_head, args_count, child_ptr_ty, 0)
if child is None:
return llvmlite.const_int32(pool, 0)
child.Next = None
llvmlite.value_set_next(child, None)
llvmlite.build_call(builder, resume_mangled, child, 1, i32_ty, 0)
# 子帧 ret 槽 GEP [0,2] load
child_ret_ptr: llvmlite.Value* = llvmlite.build_gep_struct(builder, child_frame_ty, i32_ty, child, 2)
@@ -2378,7 +2378,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
return llvmlite.const_int32(pool, 0)
llvmlite.build_br(builder, loop_bb)
llvmlite.position_at_end(builder, loop_bb)
frame_ptr.Next = None
llvmlite.value_set_next(frame_ptr, None)
status: llvmlite.Value* = llvmlite.build_call(builder, resume_mangled, frame_ptr, 1, i32_ty, 0)
zero_cmp: llvmlite.Value* = llvmlite.const_int32(pool, 0)
done_cond: llvmlite.Value* = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, status, zero_cmp)
+5 -5
View File
@@ -715,7 +715,7 @@ novirtual class CallGenBase:
stdio.printf("[CALLGEN] 链表异常: func params(call_name=%s,参数链遍历超限,终止)\n", call_name)
# 终止点收敛:REPL 会话内 longjmp 回 REPL 循环(诊断已打印)
VLogger.repl_abort()
cur_p = cur_p.Next
cur_p = llvmlite.param_get_next(cur_p)
# 只追加缺失的参数(cur_count < param_count 时)
if cur_count < param_count:
# 定位到 param_head 的第 cur_count 个节点开始追加
@@ -723,7 +723,7 @@ novirtual class CallGenBase:
pi2: int = 0
# 跳过已有的 cur_count 个参数
while pnode2 is not None and pi2 < cur_count:
pnode2 = pnode2.Next
pnode2 = llvmlite.value_get_next(pnode2)
pi2 += 1
# 追加剩余参数
while pnode2 is not None and pi2 < param_count:
@@ -731,10 +731,10 @@ novirtual class CallGenBase:
param2: llvmlite.Param* = llvmlite.new_param(pool, pnode2.Ty, None)
if param2 is not None:
llvmlite.function_add_param(existing, param2)
pnode2 = pnode2.Next
pnode2 = llvmlite.value_get_next(pnode2)
pi2 += 1
return
existing = existing.Next
existing = llvmlite.function_get_next(existing)
# 裸名 C 库函数(如 string.memset → @memset):call_name 无 sha1 前缀,无法提取定义侧模块查 vpi 参数注解,故按标准签名建 declare(与 CallGenLib._ensure_c_lib_declare 白名单一致)
if call_name is not None and string.strchr(call_name, 46) is None:
std_lib_fn: llvmlite.Function* = self.Gen.CallGenLib._ensure_c_lib_declare(pool, mod, call_name)
@@ -798,7 +798,7 @@ novirtual class CallGenBase:
param: llvmlite.Param* = llvmlite.new_param(pool, param_ty_d, None)
if param is not None:
llvmlite.function_add_param(func, param)
pnode = pnode.Next
pnode = llvmlite.value_get_next(pnode)
pi += 1
if sha1_d is not None:
stdlib.free(sha1_d)
+2 -2
View File
@@ -627,7 +627,7 @@ class CallGenCBuiltin(CallGenBase.CallGenBase):
# 标记 t.CExport 使用裸名(如 gdt → @gdt)。
self.Gen.TypeGenErr.fatal_error(None, f"asm 模板引用的全局符号 '{bare_g}' 带 SHA1 混淆头({gname}),内联汇编必须引用裸名符号,请将该全局定义标记为 t.CExport", "TypeError")
return asm_text
cur = cur.Next
cur = llvmlite.globalvariable_get_next(cur)
if matched == 0:
if out_pos + 1 < asm_size * 2:
out[out_pos] = asm_text[i]
@@ -1265,7 +1265,7 @@ class CallGenCBuiltin(CallGenBase.CallGenBase):
if out_pn_head is None:
out_pn_head = pn5
else:
out_pn_last.Next = pn5
llvmlite.paramnode_set_next(out_pn_last, pn5)
out_pn_last = pn5
out_pn_n += 1
if out_pn_head is not None and out_pn_n > 0:
+9 -4
View File
@@ -581,7 +581,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
new_head_pc: llvmlite.Value* = head
prev_pc: llvmlite.Value* = None
while pc_node is not None:
pc_next_save: llvmlite.Value* = pc_node.Next
pc_next_save: llvmlite.Value* = llvmlite.value_get_next(pc_node)
coerced_pc: llvmlite.Value* = pc_node
if pc_param is not None:
pty_pc: llvmlite.LLVMType* = llvmlite.param_get_ty(pc_param)
@@ -590,11 +590,11 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
if c_pc is not None:
coerced_pc = c_pc
pc_param = llvmlite.param_get_next(pc_param)
coerced_pc.Next = None
llvmlite.value_set_next(coerced_pc, None)
if prev_pc is None:
new_head_pc = coerced_pc
else:
prev_pc.Next = coerced_pc
llvmlite.value_set_next(prev_pc, coerced_pc)
prev_pc = coerced_pc
pc_node = pc_next_save
head = new_head_pc
@@ -2031,7 +2031,12 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
if rem_fb != 0:
offset_fb += falign_fb - rem_fb
offset_fb += fsize_fb
cur_fb = cur_fb.Next
# 跨模块遍历用访问器(仓库既定写法,见 includes/mlirlite|llvmlite
# 的 paramnode_get_next 与 _Type.md):ParamNode 的 Next 继承自
# 泛型基类 GSListNode[ParamNode],跨模块导入时该继承字段名在
# class_members 中只有 __inherited_0 占位(父类特化体不在任何 .vpi
# 中),裸字段访问会 fail-fast。
cur_fb = llvmlite.paramnode_get_next(cur_fb)
i_fb += 1
# 字段自身对齐
if cur_fb is not None and cur_fb.Ty is not None:
+3 -3
View File
@@ -846,7 +846,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
len_self_ty2: llvmlite.LLVMType* = llvmlite.param_get_ty(len_first_param2)
if len_self_ty2 is not None and len_val.Ty is not None:
len_self_arg2 = llvmlite.build_bitcast(builder, len_val, len_self_ty2)
len_self_arg2.Next = None
llvmlite.value_set_next(len_self_arg2, None)
return llvmlite.build_call(builder, len_fn_name2, len_self_arg2, 1, len_ret_ty2, 0)
# len_fn2 未命中(跨模块方法):如 ndarray[t.CDouble].__len__
# 定义在 numpy——泛型特化方法无 stub declare,find_func_in_module
@@ -872,7 +872,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
# 同名类型链接匹配);len_val 已是 load 后的对象指针。
# Value 链直接作 param_head(同跨模块调用模式)。
len_self_x: llvmlite.Value* = len_val
len_self_x.Next = None
llvmlite.value_set_next(len_self_x, None)
self._ensure_method_declare(pool, mod, len_mangled_x, len_ret_x, len_self_x, 1)
return llvmlite.build_call(builder, len_mangled_x, len_self_x, 1, len_ret_x, 0)
# fail-fast:类没有 __len__(用户要求编译期报错)
@@ -908,7 +908,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
if self.Gen.ExprGenBase.is_ptr_type(len_arg_ty) != 0:
len_coerced = llvmlite.build_bitcast(builder, len_val, i8_ptr_ty_ln2)
# 构建单参数链表并调用 strlen
len_coerced.Next = None
llvmlite.value_set_next(len_coerced, None)
i64_ty_ln2: llvmlite.LLVMType* = llvmlite.Int64(pool)
return llvmlite.build_call(builder, "strlen", len_coerced, 1, i64_ty_ln2, 0)
# fail-fast:非字符串/数组/对象,无法求长度
+17 -17
View File
@@ -192,15 +192,15 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
if zero_code_g is not None:
llvmlite.build_store(builder, zero_code_g, code_ptr)
# ---- 3. 追加实参(链表末尾 + count+2)----
msg_ptr.Next = code_ptr
code_ptr.Next = None
llvmlite.value_set_next(msg_ptr, code_ptr)
llvmlite.value_set_next(code_ptr, None)
if head is None:
head = msg_ptr
else:
tail_g: llvmlite.Value* = head
while tail_g.Next is not None:
tail_g = tail_g.Next
tail_g.Next = msg_ptr
while llvmlite.value_get_next(tail_g) is not None:
tail_g = llvmlite.value_get_next(tail_g)
llvmlite.value_set_next(tail_g, msg_ptr)
count = count + 2
# ---- 4. 调用 + 检查 ----
result: llvmlite.Value* = llvmlite.build_call(builder, call_name, head, count, ret_ty, is_variadic)
@@ -584,17 +584,17 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
if arg is None: continue
arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans)
if arg_val is None or arg_val.Ty is None: continue
arg_val.Next = None
llvmlite.value_set_next(arg_val, None)
if arg_tail is not None:
arg_tail.Next = arg_val
llvmlite.value_set_next(arg_tail, arg_val)
arg_tail = arg_val
pn_new: llvmlite.ParamNode* = llvmlite.new_param_node(pool, arg_val.Ty)
if pn_new is not None:
pn_tail.Next = pn_new
llvmlite.paramnode_set_next(pn_tail, pn_new)
pn_tail = pn_new
total_args += 1
if total_args == 1:
env_ptr.Next = None
llvmlite.value_set_next(env_ptr, None)
# 5. bitcast fn_raw 到函数指针类型 i32(i8*, [args...])*
func_ty: llvmlite.LLVMType* = llvmlite.Func(pool, i32_ty, param_node, total_args)
@@ -786,11 +786,11 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
if arg is not None:
arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans)
if arg_val is not None:
arg_val.Next = None
llvmlite.value_set_next(arg_val, None)
if head is None:
head = arg_val
else:
tail.Next = arg_val
llvmlite.value_set_next(tail, arg_val)
tail = arg_val
arg_count += 1
@@ -871,10 +871,10 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
if arg_fbits != 0 and arg_fbits < 64:
double_ty: llvmlite.LLVMType* = llvmlite.Double(pool)
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, double_ty, arg)
arg_val.Next = None
prev.Next = arg_val
llvmlite.value_set_next(arg_val, None)
llvmlite.value_set_next(prev, arg_val)
prev = arg_val
prev.Next = None
llvmlite.value_set_next(prev, None)
# is_variadic=1: 生成带显式函数类型签名的 call(如 call i32 (i8*, ...) @printf),
# 让 llc 识别为 variadic 调用,生成正确的 Win64 ABI 代码(浮点参数同时传 XMM 和整数寄存器)
@@ -987,11 +987,11 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
viperlib.snprintf(fmt_buf + string.strlen(fmt_buf), 16, "%s", token)
# 链接参数
if chain_arg != 0:
arg_val.Next = None
llvmlite.value_set_next(arg_val, None)
if arg_tail is None:
arg_head = arg_val
else:
arg_tail.Next = arg_val
llvmlite.value_set_next(arg_tail, arg_val)
arg_tail = arg_val
arg_count += 1
@@ -1002,7 +1002,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
fmt_ptr: llvmlite.Value* = self.Gen.ExprGenConst.create_global_string(builder, pool, mod, fmt_buf, trans)
stdlib.free(fmt_buf)
if fmt_ptr is None: return
fmt_ptr.Next = arg_head
llvmlite.value_set_next(fmt_ptr, arg_head)
# is_variadic=1: 带显式函数类型签名(C ABI 变参调用)
llvmlite.build_call(builder, "printf", fmt_ptr, arg_count, i32_ty, 1)
+7 -7
View File
@@ -142,7 +142,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
cur: llvmlite.Value* = head
idx: int = 0
while cur is not None and idx < size_idx:
cur = cur.Next
cur = llvmlite.value_get_next(cur)
idx += 1
if cur is None or cur.Ty is None:
return head
@@ -174,9 +174,9 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
if new_head is None:
new_head = node_v
else:
new_tail.Next = node_v
llvmlite.value_set_next(new_tail, node_v)
new_tail = node_v
cur2 = cur2.Next
cur2 = llvmlite.value_get_next(cur2)
i2 += 1
return new_head
@@ -265,9 +265,9 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
if new_head is None:
new_head = node_v
else:
new_tail.Next = node_v
llvmlite.value_set_next(new_tail, node_v)
new_tail = node_v
cur = cur.Next
cur = llvmlite.value_get_next(cur)
idx += 1
stdlib.free(sha1_buf)
if cls_nm is not None:
@@ -757,11 +757,11 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
# 类型转换(按参数类型,使用访问器)
if param_ty is not None:
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, param_ty)
arg_val.Next = None
llvmlite.value_set_next(arg_val, None)
if head is None:
head = arg_val
else:
tail.Next = arg_val
llvmlite.value_set_next(tail, arg_val)
tail = arg_val
# memcpy 专用: 保存前三个参数的独立引用
if actual_count == 0:
+8 -8
View File
@@ -549,12 +549,12 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
av_an: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cl.args.get(j_an), None, 0, trans)
if av_an is None:
av_an = llvmlite.const_int32(pool, 0)
av_an.Next = None
llvmlite.value_set_next(av_an, None)
if arg_head_an is None:
arg_head_an = av_an
arg_tail_an = av_an
else:
arg_tail_an.Next = av_an
llvmlite.value_set_next(arg_tail_an, av_an)
arg_tail_an = av_an
arg_cnt_an = arg_cnt_an + 1
child_an: llvmlite.Value* = llvmlite.build_call(builder, create_an, arg_head_an, arg_cnt_an, ret_ptr_ty_an, 0)
@@ -1096,11 +1096,11 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
arg_val = llvmlite.build_sext(builder, arg_val, i64_va)
elif af_va == 32:
arg_val = llvmlite.build_fpext(builder, arg_val, llvmlite.Double(pool))
arg_val.Next = None
llvmlite.value_set_next(arg_val, None)
if head is None:
head = arg_val
else:
tail.Next = arg_val
llvmlite.value_set_next(tail, arg_val)
tail = arg_val
# memcpy 专用: 保存前三个参数的独立引用
if ai == 0:
@@ -1208,11 +1208,11 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
if df_default_node is not None:
df_arg_val = self.Gen.ExprGen.translate_value(builder, pool, mod, df_default_node, None, 0, trans)
if df_arg_val is not None:
df_arg_val.Next = None
llvmlite.value_set_next(df_arg_val, None)
if head is None:
head = df_arg_val
else:
tail.Next = df_arg_val
llvmlite.value_set_next(tail, df_arg_val)
tail = df_arg_val
# 追加的默认实参必须计入实参数:下方
# _coerce_args_to_def_params/_ensure_method_declare 等
@@ -1242,11 +1242,11 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
zero_ty_z: llvmlite.LLVMType* = llvmlite.param_get_ty(fp_z)
zero_val_z: llvmlite.Value* = llvmlite.ConstZero(pool, zero_ty_z)
if zero_val_z is not None:
zero_val_z.Next = None
llvmlite.value_set_next(zero_val_z, None)
if head is None:
head = zero_val_z
else:
tail.Next = zero_val_z
llvmlite.value_set_next(tail, zero_val_z)
tail = zero_val_z
can += 1 # 零值兜底实参同样计入实参数(同默认实参)
fp_z = llvmlite.param_get_next(fp_z)
+3 -4
View File
@@ -119,14 +119,14 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
coerced_pc: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, cur_arg_pc, param_ty_pc)
if coerced_pc is not None and coerced_pc != cur_arg_pc:
# 保持链表完整性:新 Value 继承原节点的 Next,前驱指向新节点
llvmlite.value_set_next(coerced_pc, cur_arg_pc.Next)
llvmlite.value_set_next(coerced_pc, llvmlite.value_get_next(cur_arg_pc))
if prev_pc is None:
call_head = coerced_pc
else:
llvmlite.value_set_next(prev_pc, coerced_pc)
cur_arg_pc = coerced_pc
prev_pc = cur_arg_pc
cur_arg_pc = cur_arg_pc.Next
cur_arg_pc = llvmlite.value_get_next(cur_arg_pc)
cur_param_pc = llvmlite.param_get_next(cur_param_pc)
# 确保 declare 存在,然后调用
@@ -431,8 +431,7 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
method_name: str,
cl: ast.Call*) -> int:
"""基于接收者实际类型判定 list 内建方法(实际类型不可得回退注解名)"""
sty: llvmlite.LLVMType* = \
self.Gen.StructGen.get_struct_type_from_value(recv_val)
sty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(recv_val)
if sty is not None:
ty_nm: str = llvmlite.get_struct_name(sty)
if ty_nm is not None and ty_nm[0] != '\0':
+8 -8
View File
@@ -307,7 +307,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
idx: int = 0
while cur is not None and idx < fixed_count:
prev = cur
cur = cur.Next
cur = llvmlite.value_get_next(cur)
idx += 1
# cur 指向第 fixed_count+1 个节点(第一个变长参数)
@@ -316,7 +316,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
double_ty_promote: llvmlite.LLVMType* = llvmlite.Double(pool)
v_idx: int = fixed_count
while cur is not None:
next_node: llvmlite.Value* = cur.Next
next_node: llvmlite.Value* = llvmlite.value_get_next(cur)
promoted: llvmlite.Value* = cur
# C ABI integer promotion: i8/i16 → i32
arg_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(cur.Ty)
@@ -345,17 +345,17 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
else:
promoted = self.Gen.ExprGenBase.coerce_to_type(builder, cur, i32_ty_promote, None)
if promoted is not None:
promoted.Next = next_node
llvmlite.value_set_next(promoted, next_node)
if prev is not None:
prev.Next = promoted
llvmlite.value_set_next(prev, promoted)
# C ABI float promotion: float → double
arg_fbits: int = self.Gen.ExprGenBase.get_llvm_float_bits(promoted.Ty)
if arg_fbits != 0 and arg_fbits < 64:
promoted = self.Gen.ExprGenBase.coerce_to_type(builder, promoted, double_ty_promote, None)
if promoted is not None:
promoted.Next = next_node
llvmlite.value_set_next(promoted, next_node)
if prev is not None:
prev.Next = promoted
llvmlite.value_set_next(prev, promoted)
# Win64 变参槽位 8 字节:i8/i16/i32 → i64
# TPV va_arg 读取端统一按 i64 读(_translate_va_arg_sugar),
# 调用方必须写满 8 字节槽,否则高 4 字节残留旧栈数据,%d 读到
@@ -378,9 +378,9 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
else:
promoted_va2 = llvmlite.build_sext(builder, promoted, i64_ty_promote)
if promoted_va2 is not None:
promoted_va2.Next = next_node
llvmlite.value_set_next(promoted_va2, next_node)
if prev is not None:
prev.Next = promoted_va2
llvmlite.value_set_next(prev, promoted_va2)
promoted = promoted_va2
prev = promoted
cur = next_node
+1 -1
View File
@@ -477,7 +477,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
if first_node is None:
first_node = pnode
if prev_node is not None:
prev_node.Next = pnode
llvmlite.paramnode_set_next(prev_node, pnode)
prev_node = pnode
# 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName"
+2 -2
View File
@@ -547,7 +547,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
total += fsize
if is_packed == 0 and falign > max_align:
max_align = falign
cur = cur.Next
cur = llvmlite.paramnode_get_next(cur)
i += 1
# packed 无尾部对齐;非 packed 总大小对齐到最大字段对齐的倍数
if is_packed != 0:
@@ -595,7 +595,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
fa: int = self._get_type_align(fty)
if fa > max_align:
max_align = fa
cur = cur.Next
cur = llvmlite.paramnode_get_next(cur)
i += 1
return max_align
case _:
+2 -2
View File
@@ -41,7 +41,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
if cur.Name is not None:
if string.strcmp(cur.Name, name) == 0:
return cur
cur = cur.Next
cur = llvmlite.globalvariable_get_next(cur)
# 第二遍: 后缀匹配 (.name)
cur = mod.GlobalHead
while cur is not None:
@@ -57,7 +57,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
break
if match == 1:
return cur
cur = cur.Next
cur = llvmlite.globalvariable_get_next(cur)
return None
# ============================================================
# make_global_ref - 创建全局变量引用 (@name,类型为 ty*)
+7 -7
View File
@@ -87,11 +87,11 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
cast_val: llvmlite.Value* = self._fstr_cast_value(builder, pool, val, c_fmt, fv.value, trans)
if cast_val is None:
cast_val = val
cast_val.Next = None
llvmlite.value_set_next(cast_val, None)
if arg_head is None:
arg_head = cast_val
else:
arg_tail.Next = cast_val
llvmlite.value_set_next(arg_tail, cast_val)
arg_tail = cast_val
arg_count += 1
@@ -132,7 +132,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
cast_val: llvmlite.Value* = self._fstr_cast_value(builder, pool, val, c_fmt, fv.value, trans)
if cast_val is None:
cast_val = val
cast_val.Next = None
llvmlite.value_set_next(cast_val, None)
arg_head = cast_val
arg_tail = cast_val
arg_count = 1
@@ -175,11 +175,11 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
if buf_ptr is None: return None
# snprintf(buf, FSTR_BUF_SIZE, fmt, args...)
size_val: llvmlite.Value* = llvmlite.const_int64(pool, FSTR_BUF_SIZE)
buf_ptr.Next = size_val
size_val.Next = fmt_ptr
fmt_ptr.Next = arg_head
llvmlite.value_set_next(buf_ptr, size_val)
llvmlite.value_set_next(size_val, fmt_ptr)
llvmlite.value_set_next(fmt_ptr, arg_head)
if arg_tail is not None:
arg_tail.Next = None
llvmlite.value_set_next(arg_tail, None)
llvmlite.build_call(builder, "snprintf", buf_ptr, 3 + arg_count, i32_ty, 1)
return buf_ptr
def _fstr_append_literal(self, fmt_buf: str,
+5 -5
View File
@@ -152,7 +152,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
# 之前错误写成 inc2.Next = inc1,导致 build_phi 从 inc1 遍历时
# inc1.Next 为 None,只输出一个 phi 条目,引发 LLVM 验证错误:
# "PHINode should have one entry for each predecessor"
inc1.Next = inc2
llvmlite.phiincoming_set_next(inc1, inc2)
return llvmlite.build_phi(builder, phi_ty, inc1, 2)
# ============================================================
# 翻译比较表达式 Compare(left, ops, comparators)
@@ -547,8 +547,8 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
cn_self = llvmlite.build_bitcast(builder, rhs, cn_self_ty)
if cn_self is not None:
# 参数链表: self → key(独立 null 结尾)
cn_self.Next = lhs
lhs.Next = None
llvmlite.value_set_next(cn_self, lhs)
llvmlite.value_set_next(lhs, None)
cn_res: llvmlite.Value* = llvmlite.build_call(builder, cn_fn_name, cn_self, 2, cn_ret, 0)
if cn_res is not None:
# 归一化到 i1(__contains__ 返回 int/i32 等)
@@ -1022,7 +1022,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
phi_head = inc
phi_tail = inc
else:
phi_tail.Next = inc
llvmlite.phiincoming_set_next(phi_tail, inc)
phi_tail = inc
# 定位到 next BB,求值下一个值
@@ -1051,7 +1051,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
if phi_head is None:
phi_head = inc
else:
phi_tail.Next = inc
llvmlite.phiincoming_set_next(phi_tail, inc)
phi_count += 1
# 定位到 merge,创建 phi 合并所有入边
+5 -5
View File
@@ -1203,8 +1203,8 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
else:
# 链尾追加
rt: llvmlite.Value* = rec_args
while rt.Next is not None:
rt = rt.Next
while llvmlite.value_get_next(rt) is not None:
rt = llvmlite.value_get_next(rt)
llvmlite.value_set_next(rt, av_r)
if ret_is_void != 0:
llvmlite.build_call(wb, orig_call_name, rec_args, n_params, ret_ty, 0)
@@ -1237,7 +1237,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
for fk in range(n_params - 1, -1, -1):
pn_n: llvmlite.ParamNode* = llvmlite.new_param_node(pool, (llvmlite.LLVMType*)(param_tys[fk]))
if pn_n is not None:
pn_n.Next = fields_head
llvmlite.paramnode_set_next(pn_n, fields_head)
fields_head = pn_n
args_ty: llvmlite.LLVMType* = llvmlite.Struct(pool, fields_head, n_params, None)
if args_ty is not None:
@@ -1330,8 +1330,8 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
call_args = fld_vk
else:
ct: llvmlite.Value* = call_args
while ct.Next is not None:
ct = ct.Next
while llvmlite.value_get_next(ct) is not None:
ct = llvmlite.value_get_next(ct)
llvmlite.value_set_next(ct, fld_vk)
res_v: llvmlite.Value* = llvmlite.build_call(wb, orig_call_name, call_args, n_params, ret_ty, 0)
if ret_alloca is not None and res_v is not None:
+9 -9
View File
@@ -277,7 +277,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
env_size: int64 = nested_nonlocal_count * 8
env_size_val: llvmlite.Value* = llvmlite.const_int64(pool, env_size)
if env_size_val is not None:
env_size_val.Next = None
llvmlite.value_set_next(env_size_val, None)
env_ptr = llvmlite.build_call(parent_builder, "malloc", env_size_val, 1, i8_ptr_ty, 0)
# 为每个 nonlocal 变量建立堆存储并注册到 env:
@@ -320,7 +320,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
st_size: int = self._type_byte_size(pool, nl_load_ty)
st_size_val: llvmlite.Value* = llvmlite.const_int64(pool, st_size)
if st_size_val is not None:
st_size_val.Next = None
llvmlite.value_set_next(st_size_val, None)
var_storage: llvmlite.Value* = llvmlite.build_call(parent_builder, "malloc", st_size_val, 1, i8_ptr_ty, 0)
if var_storage is not None:
# 拷贝当前值到堆存储
@@ -364,7 +364,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
# 13b. 创建闭包结构: malloc(16)
closure_size_val: llvmlite.Value* = llvmlite.const_int64(pool, 16)
if closure_size_val is not None:
closure_size_val.Next = None
llvmlite.value_set_next(closure_size_val, None)
closure_ptr: llvmlite.Value* = llvmlite.build_call(parent_builder, "malloc", closure_size_val, 1, i8_ptr_ty, 0)
if closure_ptr is None:
# malloc 失败,恢复状态
@@ -873,7 +873,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
while gcur is not None:
if gcur.Name is not None and string.strcmp(gcur.Name, gname) == 0:
return 1
gcur = gcur.Next
gcur = llvmlite.globalvariable_get_next(gcur)
return 0
# ============================================================
@@ -971,7 +971,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
st_size: int = self._type_byte_size(pool, nl_ty)
st_size_val: llvmlite.Value* = llvmlite.const_int64(pool, st_size)
if st_size_val is not None:
st_size_val.Next = None
llvmlite.value_set_next(st_size_val, None)
var_storage: llvmlite.Value* = llvmlite.build_call(builder, "malloc", st_size_val, 1, i8_ptr_ty, 0)
if var_storage is None:
continue
@@ -992,7 +992,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
if gcur.Name is not None and string.strcmp(gcur.Name, gname) == 0:
gv_found = gcur
break
gcur = gcur.Next
gcur = llvmlite.globalvariable_get_next(gcur)
if gv_found is None:
gv_found = llvmlite.new_global_variable(pool, gname, i8_ptr_ty)
if gv_found is not None:
@@ -1229,7 +1229,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
env_size: int64 = cap_count * 8
env_size_val: llvmlite.Value* = llvmlite.const_int64(pool, env_size)
if env_size_val is not None:
env_size_val.Next = None
llvmlite.value_set_next(env_size_val, None)
env_ptr = llvmlite.build_call(builder, "malloc", env_size_val, 1, i8_ptr_ty, 0)
if env_ptr is not None:
for ci3 in range(cap_count):
@@ -1252,7 +1252,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
st_size = ty_bits // 8
st_size_val: llvmlite.Value* = llvmlite.const_int64(pool, st_size)
if st_size_val is not None:
st_size_val.Next = None
llvmlite.value_set_next(st_size_val, None)
var_storage: llvmlite.Value* = llvmlite.build_call(builder, "malloc", st_size_val, 1, i8_ptr_ty, 0)
if var_storage is not None:
cur_val: llvmlite.Value* = llvmlite.build_load(builder, cap_ty2, var_alloca2)
@@ -1270,7 +1270,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
# 14. 在父函数中创建闭包 malloc(16)
closure_size_val: llvmlite.Value* = llvmlite.const_int64(pool, 16)
if closure_size_val is not None:
closure_size_val.Next = None
llvmlite.value_set_next(closure_size_val, None)
closure_ptr: llvmlite.Value* = llvmlite.build_call(builder, "malloc", closure_size_val, 1, i8_ptr_ty, 0)
if closure_ptr is None:
return None
+2 -2
View File
@@ -487,7 +487,7 @@ novirtual class MatchGenMixin:
sw_head = sc
sw_tail = sc
else:
sw_tail.Next = sc
llvmlite.switchcase_set_next(sw_tail, sc)
sw_tail = sc
sw_count = sw_count + 1
# 记录"应产出 case 值但未产出"的臂(MatchClass 变体 tag 查表失败 /
@@ -1237,7 +1237,7 @@ novirtual class MatchGenMixin:
sw_head = sc
sw_tail = sc
else:
sw_tail.Next = sc
llvmlite.switchcase_set_next(sw_tail, sc)
sw_tail = sc
sw_count = sw_count + 1
+3 -3
View File
@@ -2484,7 +2484,7 @@ novirtual class StmtGenCifMixin:
iter_self = llvmlite.build_bitcast(builder, obj_val, iter_self_ty)
if iter_self is None:
return 0
iter_self.Next = None
llvmlite.value_set_next(iter_self, None)
iter_result: llvmlite.Value* = llvmlite.build_call(builder, iter_fn_name, iter_self, 1, iter_ret_ty, 0)
if iter_result is None:
return 0
@@ -2551,8 +2551,8 @@ novirtual class StmtGenCifMixin:
if next_self is None:
return 0
# 参数链表: arg1(iter).Next = arg2(flag);flag 独立 null 结尾防自链接
next_self.Next = flag_alloca
flag_alloca.Next = None
llvmlite.value_set_next(next_self, flag_alloca)
llvmlite.value_set_next(flag_alloca, None)
next_val: llvmlite.Value* = llvmlite.build_call(builder, next_fn_name, next_self, 2, next_ret_ty, 0)
if next_val is None:
return 0
+2 -2
View File
@@ -156,8 +156,8 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
dl_self = llvmlite.build_bitcast(builder, dl_obj, dl_self_ty)
if dl_self is not None:
# 参数链表: self → key(独立 null 结尾)
dl_self.Next = dl_idx
dl_idx.Next = None
llvmlite.value_set_next(dl_self, dl_idx)
llvmlite.value_set_next(dl_idx, None)
llvmlite.build_call(builder, dl_fn_name, dl_self, 2, dl_ret, 0)
return 0
+1 -1
View File
@@ -1934,7 +1934,7 @@ novirtual class StructGenMixin:
case _:
pass
self._ensure_field_types_in_module(pool, mod, fld.Ty)
fld = fld.Next
fld = llvmlite.paramnode_get_next(fld)
case llvmlite.LLVMType.Ptr(pointee):
# 指针类型:pointee 只需 opaque 声明,不需要完整定义
# 但如果 pointee 是 Struct,确保 opaque 声明存在
+1 -1
View File
@@ -850,7 +850,7 @@ def _tb_module_has_global_ctors(mod: llvmlite.LLVMModule*) -> int:
break
if g.Name is not None and string.strcmp(g.Name, "llvm.global_ctors") == 0:
return 1
g = g.Next
g = llvmlite.globalvariable_get_next(g)
return 0
+3 -3
View File
@@ -758,7 +758,7 @@ novirtual class VarGenMixin:
pty_slot[0] = pty_chk
# ③ 实参:首实参 = 本片段 ctx,其后按签名类型逐个翻译并 coerce
head: llvmlite.Value* = ctx_val
head.Next = None
llvmlite.value_set_next(head, None)
tail: llvmlite.Value* = head
arg_count: int = 1
ai: int
@@ -777,8 +777,8 @@ novirtual class VarGenMixin:
if coerced is None:
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的第 {ai + 1} 个实参与签名类型不兼容", "TypeError")
return None
coerced.Next = None
tail.Next = coerced
llvmlite.value_set_next(coerced, None)
llvmlite.value_set_next(tail, coerced)
tail = coerced
arg_count += 1
# ④ 函数类型:ret + (i8*, P1..Pn)(ret=void 时用 llvmlite.Void,