diff --git a/App/lib/core/Gen/Call/CallGenBase.vp b/App/lib/core/Gen/Call/CallGenBase.vp index af486f1..315adcd 100644 --- a/App/lib/core/Gen/Call/CallGenBase.vp +++ b/App/lib/core/Gen/Call/CallGenBase.vp @@ -560,6 +560,38 @@ novirtual class CallGenBase: return sha1 + def _FuncTyFromFunction(self, pool: memhub.MemBuddy*, + f_ref: llvmlite.Function*) -> llvmlite.LLVMType*: + """由 llvmlite.Function 的形参链表(Param 链)构造 LLVMType.Func 类型。 + + 为什么不能直接把 Param 链交给 llvmlite.Func:`Function.Params` 是 **Param** 链 + (__function.vp,`Param.Ty: rawptr[LLVMType]`),而 `LLVMType.Func` 的类型构造链表是 + **ParamNode** 链(__types.vp,由 new_param_node 建、paramnode_set_next 串)。两者是 + 互不相关的 class —— 严格指针规则下不可互传(旧的无条件 bitcast 掩盖了这点,且两者 + 字段顺序不同,bitcast 后读 Ty/Name 都是错位数据)。 + 这里逐个 new_param_node 重建 ParamNode 链再交给 Func:语义等价(两侧都只取各参数的 + 类型),类型也对得上 Func(params: rawptr[ParamNode]) 的形参。 + """ + pn_head: llvmlite.ParamNode* = None + pn_prev: llvmlite.ParamNode* = None + p_cnt: sizet = 0 + p_cur: llvmlite.Param* = llvmlite.function_get_param_head(f_ref) + while p_cur is not None: + p_ty: llvmlite.LLVMType* = llvmlite.param_get_ty(p_cur) + if p_ty is None: + return None + pn: llvmlite.ParamNode* = llvmlite.new_param_node(pool, p_ty) + if pn is None: + return None + if pn_head is None: + pn_head = pn + if pn_prev is not None: + llvmlite.paramnode_set_next(pn_prev, pn) + pn_prev = pn + p_cnt += 1 + p_cur = llvmlite.param_get_next(p_cur) + return llvmlite.Func(pool, f_ref.RetTy, pn_head, p_cnt) + def find_func_in_module(self, mod: llvmlite.LLVMModule*, name: str, owner_sha1: str = None) -> llvmlite.Function*: diff --git a/App/lib/core/Gen/Call/CallGenCBuiltin.vp b/App/lib/core/Gen/Call/CallGenCBuiltin.vp index 0c746df..9f030e1 100644 --- a/App/lib/core/Gen/Call/CallGenCBuiltin.vp +++ b/App/lib/core/Gen/Call/CallGenCBuiltin.vp @@ -320,13 +320,9 @@ class CallGenCBuiltin(CallGenBase.CallGenBase): if f_addr_ref is not None: f_addr_name: str = llvmlite.function_get_name(f_addr_ref) if f_addr_name is not None: - p_head_ca: llvmlite.Param* = llvmlite.function_get_param_head(f_addr_ref) - p_cnt_ca: sizet = 0 - p_cur_ca: llvmlite.Param* = p_head_ca - while p_cur_ca is not None: - p_cnt_ca += 1 - p_cur_ca = llvmlite.param_get_next(p_cur_ca) - fn_ty_ca: llvmlite.LLVMType* = llvmlite.Func(pool, f_addr_ref.RetTy, p_head_ca, p_cnt_ca) + # 形参链是 Param 链(__function.vp),而 llvmlite.Func 的类型构造链是 + # ParamNode 链(__types.vp)——不相关类,统一经 _FuncTyFromFunction 重建。 + fn_ty_ca: llvmlite.LLVMType* = self.Gen.CallGenBase._FuncTyFromFunction(pool, f_addr_ref) # 函数引用名需按需加引号(数字开头/含 '.' 的 sha1 前缀名 # 必须 @\"...\",否则 llc "expected 'to' after cast value", # uhci.vp c.Addr(_on_int_complete) 根因)。 @@ -392,13 +388,8 @@ class CallGenCBuiltin(CallGenBase.CallGenBase): fname2: str = llvmlite.function_get_name(f_ref2) if fname2 is not None: # 构造带 @ 名的 SSAValue(Ptr(FuncTy)):直接返回 Function 节点会被 IRBuilder 格式化成 RetTy(void)→ "bitcast void to i8*"。Function 无 Ty 字段,用 RetTy+Params 重建函数类型;Params 是 GSList,必须经 function_get_param_head 取链表头(当 Param 直接遍历会读出垃圾参数类型) - p_head2: llvmlite.Param* = llvmlite.function_get_param_head(f_ref2) - p_cnt2: sizet = 0 - p_cur2: llvmlite.Param* = p_head2 - while p_cur2 is not None: - p_cnt2 += 1 - p_cur2 = llvmlite.param_get_next(p_cur2) - fn_ty2: llvmlite.LLVMType* = llvmlite.Func(pool, f_ref2.RetTy, p_head2, p_cnt2) + # 同上:Function 的 Param 形参链 → 重建 ParamNode 链再交 Func + fn_ty2: llvmlite.LLVMType* = self.Gen.CallGenBase._FuncTyFromFunction(pool, f_ref2) # 函数引用名按需加引号(数字开头/含 '.' 的 # sha1 前缀名必须 @\"...\")。 fnlen2: sizet = string.strlen(fname2) @@ -1060,9 +1051,14 @@ class CallGenCBuiltin(CallGenBase.CallGenBase): # isr.s .comm):lookup_var 只查局部 → 全局 # 落空 → 操作数缺失 → asm 模板 "$0" 空 → # "mov , cr3" llc unknown token in expression。 - # 回退查模块全局(精确+后缀),全局 Value - # (@name,类型 i64*)直接当 store 目标。 - alloca = self.Gen.ExprGenAttr.find_global_in_module(mod, nm.id) + # 回退查模块全局,并**经 make_global_ref 转成 Value 引用**: + # GlobalVariable 与 Value 是不相关类(不可互转,且字段顺序不同 + # —— GlobalVariable.Name 在 Ty 之前,旧的无条件 bitcast 会让 + # .Ty 读到 Name),必须按 c.Addr(模块全局) 分支的同一写法构造 + # 带引号的 Ptr(Ty) 引用(见 L309 注释)。 + gv_asm: llvmlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(mod, nm.id) + if gv_asm is not None and gv_asm.Name is not None and gv_asm.Ty is not None: + alloca = self.Gen.ExprGenAttr.make_global_ref(pool, gv_asm.Name, gv_asm.Ty) elif val_node.kind() == ast.ASTKind.Attribute: # AsmOut(p.pml4_root)(p 为 Process 指针): # GEP 到字段地址(对齐 translate_c_addr Attribute diff --git a/App/lib/core/Gen/Expr/ExprGenOps.vp b/App/lib/core/Gen/Expr/ExprGenOps.vp index 4c849e0..c048835 100644 --- a/App/lib/core/Gen/Expr/ExprGenOps.vp +++ b/App/lib/core/Gen/Expr/ExprGenOps.vp @@ -869,13 +869,9 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if f_ao is not None: fname_ao: str = llvmlite.function_get_name(f_ao) if fname_ao is not None: - p_head_ao: llvmlite.Param* = llvmlite.function_get_param_head(f_ao) - p_cnt_ao: sizet = 0 - p_cur_ao: llvmlite.Param* = p_head_ao - while p_cur_ao is not None: - p_cnt_ao += 1 - p_cur_ao = llvmlite.param_get_next(p_cur_ao) - fn_ty_ao: llvmlite.LLVMType* = llvmlite.Func(pool, f_ao.RetTy, p_head_ao, p_cnt_ao) + # 形参链是 Param 链,而 llvmlite.Func 的类型构造链是 ParamNode 链 + # (不相关类)→ 经 _FuncTyFromFunction 重建(同 CallGenCBuiltin)。 + fn_ty_ao: llvmlite.LLVMType* = self.Gen.CallGenBase._FuncTyFromFunction(pool, f_ao) # 函数引用名按需加引号(数字开头/含 '.' 的 sha1 前缀名) fnlen_ao: sizet = string.strlen(fname_ao) needs_q_ao: int = self.Gen.ClassGenVTable._vtable_name_needs_quote(fname_ao)