diff --git a/App/lib/core/Gen/Call/CallGenBase.vp b/App/lib/core/Gen/Call/CallGenBase.vp index 15a0d1e..645fde4 100644 --- a/App/lib/core/Gen/Call/CallGenBase.vp +++ b/App/lib/core/Gen/Call/CallGenBase.vp @@ -703,7 +703,12 @@ novirtual class CallGenBase: func: llvmlite.Function* = llvmlite.new_function(pool, call_name, ret_ty) if func is None: return func.IsDeclared = 1 - # 定义侧参数类型优先:从 call_name 提取 {sha1}.{cls}.{method} 查 vpi 参数注解取定义侧类型,仅当实参与定义都是整数且定义更宽时采用定义宽度(指针/联合保持实参类型)。反方向(定义更窄)由 CallGenLib._coerce_args_to_def_params 在调用点先窄化实参 + # 定义侧参数类型优先:从 call_name 提取 {sha1}.{cls}.{method} 查 vpi 参数注解取定义侧类型。 + # · 整数:仅当定义宽度更宽时采用定义宽度(反方向由 CallGenLib._coerce_args_to_def_params 在调用点先窄化实参) + # · 指针:**一律采用定义侧类型**——declare 被同模块所有调用点共用,若沿用"首个调用点的实参类型", + # 后续调用传入别的具体指针类型就会被这条被冻住的形参类型 coerce,报"非基本类型指针间隐式转换" + # (现场 VarGenMixin.repl_ensure_entry 的 node: ast.AST*:先被 translate_annassign 以 AnnAssign* + # 建 declare,后 translate_assign 传 AST* 即报"源类型 …AST* → 目标类型 …AnnAssign*") sha1_d: str = None cls_d: str = None meth_d: str = None @@ -752,6 +757,13 @@ novirtual class CallGenBase: param_ty_d = seg_ty_d case _: pass + case llvmlite.LLVMType.Ptr(_): + # 指针形参:定义侧为准(见上方注释)。定义侧解析不出指针时保留实参类型 + match seg_ty_d: + case llvmlite.LLVMType.Ptr(_): + param_ty_d = seg_ty_d + case _: + pass case _: pass if param_ty_d is not None: diff --git a/App/lib/core/Gen/Call/CallGenLib.vp b/App/lib/core/Gen/Call/CallGenLib.vp index 2c86cdf..43c2d3f 100644 --- a/App/lib/core/Gen/Call/CallGenLib.vp +++ b/App/lib/core/Gen/Call/CallGenLib.vp @@ -274,7 +274,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): stdlib.free(cls_nm) return new_head - # _coerce_arg_value_to_ty:单个实参 Value 转换到目标形参类型——整型同宽原样、窄化 trunc/按宽度重建常量、扩宽按源符号性 zext/sext;指针 i8* 性不同则 bitcast;其余原样返回(不可转换亦不改型) + # _coerce_arg_value_to_ty:单个实参 Value 转换到目标形参类型——整型同宽原样、窄化 trunc/按宽度重建常量、扩宽按源符号性 zext/sext;同层指针类型不一致则 bitcast 到目标类型;其余原样返回(不可转换亦不改型) def _coerce_arg_value_to_ty(self, pool: memhub.MemBuddy*, builder: llvmlite.IRBuilder*, val: llvmlite.Value*, @@ -322,30 +322,19 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): return val case _: pass - case llvmlite.LLVMType.Ptr(pointee_a): + case llvmlite.LLVMType.Ptr(_): match tgt_ty: - case llvmlite.LLVMType.Ptr(pointee_b): - ia: int = 0 - match pointee_a: - case llvmlite.LLVMType.Int(pa_bits): - if pa_bits == 8: - ia = 1 - case _: - pass - ib: int = 0 - match pointee_b: - case llvmlite.LLVMType.Int(pb_bits): - if pb_bits == 8: - ib = 1 - case _: - pass - if ia != ib: + case llvmlite.LLVMType.Ptr(_): + # 同层指针:实参类型与定义侧形参类型不一致就 bitcast 对齐(一致则不比, + # 避免生成非法 `bitcast T* to T*`)。跨模块调用的 call/declare 都以 + # 定义侧为准(declare 见 CallGenBase._ensure_method_declare),故这里 + # 必须对齐:首个调用点由它建立 declare、不走 coerce_to_type,原样传具体 + # 指针就会与 declare 的类型不一致(llc 报 argument type mismatch)。 + # 原判据只覆盖"一侧为 i8*"与"模板注解来源",漏了两侧同为具体结构体指针 + # 但基类型不同的情形(实参 MemBuddy* vs 定义侧形参 MemManager*)。 + if self.Gen.AssignGen._stg_ty_equal(pool, val.Ty, tgt_ty) == 0: nv_p: llvmlite.Value* = llvmlite.build_bitcast(builder, val, tgt_ty) if nv_p is not None: return nv_p - elif tpl_src != 0: - # 模板注解来源:两侧同为具体结构体指针但基类型不同(实参 MemBuddy* vs 定义侧形参 MemManager*)⇒ bitcast 使 declare 指针口径与 define 一致 - nv_p2: llvmlite.Value* = llvmlite.build_bitcast(builder, val, tgt_ty) - if nv_p2 is not None: return nv_p2 case _: pass case _: