diff --git a/App/lib/core/Gen/Call/CallGenCall.vp b/App/lib/core/Gen/Call/CallGenCall.vp index f26f31c..0e7efeb 100644 --- a/App/lib/core/Gen/Call/CallGenCall.vp +++ b/App/lib/core/Gen/Call/CallGenCall.vp @@ -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)