fix(CallGen): 跨模块调用的 declare 形参与实参统一以定义侧为准
问题一(declare 形参被首个调用点冻结):CallGenBase._ensure_method_declare 新建跨模块方法 declare 时形参类型取"首个调用点的实参类型",而这条 declare 被同模块所有调用点共用 ⇒ 后续 调用传入另一种具体指针类型时,被这条被冻住的形参类型 coerce,报"非基本类型指针间隐式转换"。 现场:VarGenMixin.repl_ensure_entry 的 node: ast.AST*,先被 translate_annassign 以 ast.AnnAssign* 建 declare,后 translate_assign 传 ast.AST* 即报"源类型 …AST* → 目标类型 …AnnAssign*"。 ⇒ 指针形参与整数同口径,一律采用定义侧(.vpi 注解段)类型;解析不出指针时保留实参类型。 问题二(实参未对齐 declare):declare 改用定义侧类型后实参也必须对齐,否则首个调用点 (由它建立 declare、不走 coerce_to_type)原样传具体指针会与 declare 类型不一致(llc 报 argument type mismatch)。⇒ CallGenLib._coerce_arg_value_to_ty 的同层指针分支改为"类型内容 不一致即 bitcast 到定义侧类型"(原判据只覆盖一侧为 i8*、或模板注解来源两种情形)。
This commit is contained in:
1 parent
93e983f74e
commit
8e3811c490
2 files changed
+24
-23
No files matched your search
@@ -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:
|
||||
|
||||
@@ -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 _:
|
||||
|
||||
Reference in new issue
Block a user