fix(CallGenCall): 拆开 vtable_base 类型推断的变量复用(LLVMType* 与 StructEntry* 不可同一变量)
严格指针规则下 struct↔struct 隐式转换已禁止(仅允许派生→基类上转),原写法把 get_struct_type_from_value 的返回(LLVMType*)赋给 vc_entry: StructEntry* 再转手交给 find_struct_by_type,靠的是旧的无条件 bitcast。 改为各用独立变量(vb_ty / sp_ty),语义与改前逐字一致(仅去掉两次隐式 bitcast)。
This commit is contained in:
1 parent
3bed3a70a6
commit
9c427aa548
1 file changed
+30
-26
@@ -71,17 +71,21 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
|
||||
vc_entry: GenTypes.StructEntry* = None
|
||||
struct_ty: llvmlite.LLVMType* = None
|
||||
if vtable_base is not None and vtable_base.Ty is not None:
|
||||
vc_entry = self.Gen.StructGen.get_struct_type_from_value(vtable_base)
|
||||
if vc_entry is not None:
|
||||
# vc_entry 是 struct_ty(LLVMType),需要找 StructEntry
|
||||
vc_entry = self.Gen.StructGen.find_struct_by_type(vc_entry)
|
||||
# 中间结果(LLVMType)与 vc_entry(StructEntry)是**两个不同的结构体**,
|
||||
# 不能复用同一个变量:严格指针规则禁止 struct↔struct 的隐式转换
|
||||
# (仅允许派生→基类上转),复用会让 LLVMType* 赋给 StructEntry* 变量时
|
||||
# 直接编译期报错。各自用独立变量,语义与改前逐字一致。
|
||||
vb_ty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(vtable_base)
|
||||
if vb_ty is not None:
|
||||
# vb_ty 是 struct_ty(LLVMType),需要找 StructEntry
|
||||
vc_entry = self.Gen.StructGen.find_struct_by_type(vb_ty)
|
||||
if vc_entry is not None:
|
||||
struct_ty = vc_entry.Ty
|
||||
if struct_ty is None and self_ptr is not None and self_ptr.Ty is not None:
|
||||
# fallback:vtable_base 无类型信息时退回 self_ptr(未调整场景两者一致)
|
||||
vc_entry = self.Gen.StructGen.get_struct_type_from_value(self_ptr)
|
||||
if vc_entry is not None:
|
||||
vc_entry = self.Gen.StructGen.find_struct_by_type(vc_entry)
|
||||
sp_ty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(self_ptr)
|
||||
if sp_ty is not None:
|
||||
vc_entry = self.Gen.StructGen.find_struct_by_type(sp_ty)
|
||||
if vc_entry is not None:
|
||||
struct_ty = vc_entry.Ty
|
||||
if struct_ty is None:
|
||||
@@ -637,25 +641,25 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
|
||||
head = self.Gen.CallGenLib._coerce_args_to_def_params(pool, builder, call_name, head, total_count, None, 1, trans)
|
||||
self._ensure_method_declare(pool, mod, call_name, call_ret_ty, head, total_count)
|
||||
|
||||
call_res_cmop: llvmlite.Value* = llvmlite.build_call(builder, call_name, head, total_count, call_ret_ty, 0)
|
||||
# 值位置 volatile 构造:call 指令本身无 volatile 限定符,构造语义只能落在
|
||||
# 内存存取上。逐字段 store 已由调用方(_translate_struct_ctor 等)带 volatile;
|
||||
# __new__/__before_init__/__init__ 的写入发生在被调函数内部,调用点无法逐条
|
||||
# 附加 volatile ⇒ 此处追加一次 volatile 屏障(对 self 指针做 i8 volatile load)。
|
||||
# volatile 访问有副作用:不会被 DCE,且禁止优化器假设其前后内存不变,从而
|
||||
# 保证本次构造对对象内存的写入不可被消除或跨越重排。仅对构造三方法生效,
|
||||
# 不给普通方法调用引入额外访存。
|
||||
if is_volatile != 0 and self_ptr is not None and self_ptr.Ty is not None:
|
||||
if string.strcmp(method_name, "__new__") == 0 \
|
||||
or string.strcmp(method_name, "__before_init__") == 0 \
|
||||
or string.strcmp(method_name, "__init__") == 0:
|
||||
cmop_i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
|
||||
cmop_i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, cmop_i8_ty)
|
||||
cmop_bar_ptr: llvmlite.Value* = self_ptr
|
||||
if uint64(self_ptr.Ty) != uint64(cmop_i8_ptr_ty):
|
||||
cmop_bar_ptr = llvmlite.build_bitcast(builder, self_ptr, cmop_i8_ptr_ty)
|
||||
if cmop_bar_ptr is not None:
|
||||
llvmlite.build_load(builder, cmop_i8_ty, cmop_bar_ptr, 1)
|
||||
call_res_cmop: llvmlite.Value* = llvmlite.build_call(builder, call_name, head, total_count, call_ret_ty, 0)
|
||||
# 值位置 volatile 构造:call 指令本身无 volatile 限定符,构造语义只能落在
|
||||
# 内存存取上。逐字段 store 已由调用方(_translate_struct_ctor 等)带 volatile;
|
||||
# __new__/__before_init__/__init__ 的写入发生在被调函数内部,调用点无法逐条
|
||||
# 附加 volatile ⇒ 此处追加一次 volatile 屏障(对 self 指针做 i8 volatile load)。
|
||||
# volatile 访问有副作用:不会被 DCE,且禁止优化器假设其前后内存不变,从而
|
||||
# 保证本次构造对对象内存的写入不可被消除或跨越重排。仅对构造三方法生效,
|
||||
# 不给普通方法调用引入额外访存。
|
||||
if is_volatile != 0 and self_ptr is not None and self_ptr.Ty is not None:
|
||||
if string.strcmp(method_name, "__new__") == 0 \
|
||||
or string.strcmp(method_name, "__before_init__") == 0 \
|
||||
or string.strcmp(method_name, "__init__") == 0:
|
||||
cmop_i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
|
||||
cmop_i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, cmop_i8_ty)
|
||||
cmop_bar_ptr: llvmlite.Value* = self_ptr
|
||||
if uint64(self_ptr.Ty) != uint64(cmop_i8_ptr_ty):
|
||||
cmop_bar_ptr = llvmlite.build_bitcast(builder, self_ptr, cmop_i8_ptr_ty)
|
||||
if cmop_bar_ptr is not None:
|
||||
llvmlite.build_load(builder, cmop_i8_ty, cmop_bar_ptr, 1)
|
||||
return call_res_cmop
|
||||
# ============================================================
|
||||
# _translate_method_call - 翻译方法调用 obj.method(args)
|
||||
|
||||
Reference in new issue
Block a user