diff --git a/App/lib/core/Gen/AssignGenMixin.vp b/App/lib/core/Gen/AssignGenMixin.vp index ae87137..428b407 100644 --- a/App/lib/core/Gen/AssignGenMixin.vp +++ b/App/lib/core/Gen/AssignGenMixin.vp @@ -2167,6 +2167,18 @@ novirtual class AssignGenMixin: if self.Gen.CallGenLeafKit.register_func_ptr_sig(pool, nm.id, callable_ret, aa) != 0: return 0 + # 值位置 volatile 调用前缀:`a: int = volatile f()` / `a: S = volatile S(...)` + # ⇒ 结果槽按 volatile 存取(下述三条"条目已先存在"的分支——global / + # nonlocal / mod_glob——在此统一登记,使各分支读取 var_is_volatile 时已置位)。 + # 函数内**新声明**的局部变量此刻条目尚未建立,由主分支(alloca 就绪后)登记。 + # LLVM 的 call 无 volatile 限定符,故语义落在内存存取上:本次 store 带 + # volatile,且此后该变量的 load/store 亦带,避免这次调用/构造的往返访问 + # 被优化器消除或提升。 + if aa.value is not None and aa.value.kind() == ast.ASTKind.Call \ + and (ast.Call*(aa.value)).IsVolatile != 0 and nm.id is not None: + if self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id) is not None: + self.Gen.VarGen.set_var_volatile(trans.SymTab, nm.id) + # global 变量:写入模块作用域中的全局变量 if GenApi.is_global_name(trans, nm.id) != 0: mod_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm.id) @@ -2565,6 +2577,15 @@ novirtual class AssignGenMixin: # PointeeVolatile;本 store 写的是指针变量自身,不影响。 if self.Gen.TypeGenErr.has_pointee_volatile_marker(aa.annotation) != 0: self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, nm.id) + # 值位置 volatile 调用前缀:`a: int = volatile f()` / + # `a: S = volatile S(...)`——LLVM 的 call 指令没有 volatile + # 限定符,故语义落在内存存取上:结果槽按 volatile 存取 + # (本次 store 立即带 volatile,且此后该变量的 load/store 也带), + # 使"这次调用/构造的往返内存访问"不会被优化器消除或提升。 + if aa.value is not None and aa.value.kind() == ast.ASTKind.Call \ + and (ast.Call*(aa.value)).IsVolatile != 0: + self.Gen.VarGen.set_var_volatile(trans.SymTab, nm.id) + vol_laa = 1 llvmlite.build_store(builder, rhs_val, alloca, vol_laa) # FakeDuck: 初始化影子结构体 __data__ 字段 = 初始字符串指针 # (对齐 TPC HandlesAnnAssign.py: 仅当有初值时写入 __data__) diff --git a/App/lib/core/Gen/Call/CallGenCall.vp b/App/lib/core/Gen/Call/CallGenCall.vp index 807af8b..f26f31c 100644 --- a/App/lib/core/Gen/Call/CallGenCall.vp +++ b/App/lib/core/Gen/Call/CallGenCall.vp @@ -206,11 +206,16 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): extra_args: sizet*, extra_count: int, trans: HT.Translator*, - node: ast.AST* = None) -> llvmlite.Value*: + node: ast.AST* = None, + is_volatile: int = 0) -> llvmlite.Value*: """在结构体指针上调用方法,返回 call 结果(void 方法返回 None) node: 触发本次调用的 AST 节点(如 Subscript 下标节点),用于 fatal_error - 准确报告出错行号(传 None 时行号显示 0,不利于定位)。""" + 准确报告出错行号(传 None 时行号显示 0,不利于定位)。 + is_volatile: 值位置 volatile 构造前缀(`a: T = volatile S(...)`)——LLVM + 的 call 指令没有 volatile 限定符,故仅对构造三方法(__new__/ + __before_init__/__init__)在调用后追加一次 volatile 内存屏障, + 使被调函数内部对对象内存的写入不可被优化器消除/跨越。""" if pool is None or builder is None or class_name is None or method_name is None: return None if self_ptr is None: @@ -632,7 +637,26 @@ 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) - return llvmlite.build_call(builder, call_name, head, total_count, call_ret_ty, 0) + 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) # diff --git a/App/lib/core/Gen/Call/CallGenCtor.vp b/App/lib/core/Gen/Call/CallGenCtor.vp index 06788c4..96e13d1 100644 --- a/App/lib/core/Gen/Call/CallGenCtor.vp +++ b/App/lib/core/Gen/Call/CallGenCtor.vp @@ -33,8 +33,12 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): struct_ty: llvmlite.LLVMType*, class_name: str, tmp: llvmlite.Value*, - trans: HT.Translator*): - """应用结构体字段的默认值""" + trans: HT.Translator*, + is_volatile: int = 0): + """应用结构体字段的默认值 + + is_volatile=1:`volatile S(...)` 构造——默认值写入也带 LLVM volatile + (构造期对对象内存的写入整体不可被优化器消除/提升)。""" # 用类型指针定位 entry,规避跨模块同名 find_struct 找错 entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_type(struct_ty) if entry is None: @@ -58,7 +62,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if field_ptr_arr2 is not None: zero_arr2: llvmlite.Value* = llvmlite.ConstZero(pool, fe.Ty) if zero_arr2 is not None: - llvmlite.build_store(builder, zero_arr2, field_ptr_arr2) + llvmlite.build_store(builder, zero_arr2, field_ptr_arr2, is_volatile) # owner_ctx 只服务空元素 fail-fast 报文(类名 + 字段名 + 下标) sd_ctx: str = pool.alloc(192) if sd_ctx is not None: @@ -79,7 +83,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): VLogger.error(f"字段 GEP 失败,类型不匹配: {class_name}", "HandlesExprCall") continue default_val = self.Gen.ExprGenBase.coerce_to_type(builder, default_val, fe.Ty, fe.DefaultVal) - llvmlite.build_store(builder, default_val, field_ptr) + llvmlite.build_store(builder, default_val, field_ptr, is_volatile) # ============================================================ # _translate_struct_ctor — 结构体构造函数 Point(10, 20) # @@ -101,11 +105,17 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): class_name: str, cargs: list[ast.AST*]*, can: sizet, - trans: HT.Translator*) -> llvmlite.Value*: + trans: HT.Translator*, + is_volatile: int = 0) -> llvmlite.Value*: """结构体构造函数:按字段顺序 store 参数值,返回结构体值 OOP 结构体:alloca → call __before_init__(ptr) → call __init__(ptr, args) 或 store 参数 → load 普通结构体:alloca → zero + defaults → store 参数 → load + + is_volatile=1:`volatile S(...)` 构造——本次构造对对象内存的所有写入 + (zero/默认值/逐字段 store)带 LLVM volatile,且 __new__/__before_init__/ + __init__ 调用后追加一次 volatile 屏障(见 _call_method_on_ptr), + 使构造过程整体不可被优化器消除或提升。 """ # 创建临时 alloca # 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间) @@ -173,7 +183,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): new_arg_vals[new_arg_count] = sizet(new_av) new_arg_count += 1 - new_ptr: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name, "__new__", tmp, new_arg_vals, new_arg_count, trans, diag_node_ct) + new_ptr: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name, "__new__", tmp, new_arg_vals, new_arg_count, trans, diag_node_ct, is_volatile) if new_ptr is not None: storage_ptr = new_ptr # __new__ 只保证返回"实例存储指针",声明类型通常是 @@ -190,7 +200,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): storage_ptr = nw_bc # OOP 结构体:调用 __before_init__ 进行零值填充和默认值赋值 - self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name,"__before_init__", storage_ptr, None, 0, trans, diag_node_ct) + self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name,"__before_init__", storage_ptr, None, 0, trans, diag_node_ct, is_volatile) # 如果有 __init__,调用 __init__(ptr, args...) # 注意: 仅依据 ctor_entry.HasInit 判断,不强制推断 @@ -214,7 +224,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): arg_vals[real_arg_count] = sizet(av) real_arg_count += 1 - self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name, "__init__", storage_ptr, arg_vals, real_arg_count, trans, diag_node_ct) + self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name, "__init__", storage_ptr, arg_vals, real_arg_count, trans, diag_node_ct, is_volatile) elif has_new_flag == 0: # 无 __init__ 且无 __new__:逐字段 store 参数值 # (有 __new__ 时参数已由 __new__ 消费,不应存入字段) @@ -253,17 +263,17 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): VLogger.error(f"构造函数字段 GEP 失败: {class_name}", "HandlesExprCall") continue arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, fe.Ty, arg) - llvmlite.build_store(builder, arg_val, field_ptr) + llvmlite.build_store(builder, arg_val, field_ptr, is_volatile) # 返回指针(而非结构体值),赋值时由 coerce_to_type 按目标类型决定是否 load return storage_ptr # 普通结构体:先 store zeroinitializer 清零(确保未赋值字段为零) zero: llvmlite.Value* = llvmlite.ConstZero(pool, struct_ty) - llvmlite.build_store(builder, zero, tmp) + llvmlite.build_store(builder, zero, tmp, is_volatile) # 应用默认值(显式参数会覆盖默认值) - self._apply_struct_defaults(pool, builder, mod, struct_ty, class_name, tmp, trans) + self._apply_struct_defaults(pool, builder, mod, struct_ty, class_name, tmp, trans, is_volatile) # 逐字段 store 参数值(覆盖默认值) for ai in range(can): @@ -293,7 +303,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): continue # 类型转换并 store arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, fe.Ty, arg) - llvmlite.build_store(builder, arg_val, field_ptr) + llvmlite.build_store(builder, arg_val, field_ptr, is_volatile) # 返回指针(而非结构体值),赋值时由 coerce_to_type 按目标类型决定是否 load return tmp @@ -325,7 +335,8 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): tag_value: int, cargs: list[ast.AST*]*, can: sizet, - trans: HT.Translator*) -> llvmlite.Value*: + trans: HT.Translator*, + is_volatile: int = 0) -> llvmlite.Value*: """构造 REnum 变体实例,返回指向 alloca 的指针 class_name: REnum 类名(如 "LLVMType") @@ -333,6 +344,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): tag_value: 变体的 tag 值(变体在类中的索引) cargs: 参数 AST 列表 can: 参数数量 + is_volatile=1:`volatile C.V(...)` 构造——清零/tag/payload 写入带 volatile """ if pool is None or builder is None or class_name is None: return None @@ -360,7 +372,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # 清零(确保未赋值的 payload 位置为零) zero: llvmlite.Value* = llvmlite.ConstZero(pool, renum_ty) - llvmlite.build_store(builder, zero, tmp) + llvmlite.build_store(builder, zero, tmp, is_volatile) # 写入 __tag 字段(索引 0) # tag 的类型取 __tag 的**字段声明类型**(FieldEntry.Ty),与 kind() @@ -378,7 +390,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): tag_name_buf if tag_name_buf is not None else "0") tag_ptr: llvmlite.Value* = llvmlite.build_gep_struct(builder, renum_ty, tag_field_ty, tmp, 0) if tag_ptr is not None: - llvmlite.build_store(builder, tag_const, tag_ptr) + llvmlite.build_store(builder, tag_const, tag_ptr, is_volatile) # 写入 payload 字段(索引 1, 2, ... 对应 _p1, _p2, ...) # 参数按位置顺序填充 payload,跳过 __tag(索引 0) @@ -409,7 +421,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): arg_val = casted_arg # 类型转换并 store(payload 位置可能是 i32 或 i64,按字段类型 coerce) arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, pfe.Ty, arg) - llvmlite.build_store(builder, arg_val, payload_ptr) + llvmlite.build_store(builder, arg_val, payload_ptr, is_volatile) # 返回指针(与 _translate_struct_ctor 一致,赋值时由 coerce_to_type 决定是否 load) return tmp @@ -433,8 +445,13 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): can: sizet, keywords: list[ast.AST*]*, kw_count: sizet, - trans: HT.Translator*) -> llvmlite.Value*: - """结构体构造函数(关键字参数版本)""" + trans: HT.Translator*, + is_volatile: int = 0) -> llvmlite.Value*: + """结构体构造函数(关键字参数版本) + + is_volatile=1:`volatile S(x=1)` 构造——同 _translate_struct_ctor, + 写入带 volatile 且 __new__/__before_init__/__init__ 后加 volatile 屏障。 + """ # 创建临时 alloca # 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间) self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, struct_ty) @@ -479,12 +496,12 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if is_oop != 0: self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name, - "__before_init__", tmp, None, 0, trans) + "__before_init__", tmp, None, 0, trans, None, is_volatile) else: # 普通结构体:store zeroinitializer + 应用默认值 zero: llvmlite.Value* = llvmlite.ConstZero(pool, struct_ty) - llvmlite.build_store(builder, zero, tmp) - self._apply_struct_defaults(pool, builder, mod, struct_ty, class_name, tmp, trans) + llvmlite.build_store(builder, zero, tmp, is_volatile) + self._apply_struct_defaults(pool, builder, mod, struct_ty, class_name, tmp, trans, is_volatile) # OOP 结构体且有 __init__:调用 __init__ 而非逐字段 store # 关键字构造调用此前总是逐字段 store,导致 __init__ 方法体不执行 @@ -528,7 +545,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if new_arg_count < 32: new_arg_vals[new_arg_count] = sizet(nkw_av) new_arg_count += 1 - new_ptr: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name, "__new__", tmp, new_arg_vals, new_arg_count, trans, diag_node_ct) + new_ptr: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name, "__new__", tmp, new_arg_vals, new_arg_count, trans, diag_node_ct, is_volatile) if new_ptr is not None: storage_ptr = new_ptr # __new__ 只保证返回"实例存储指针",声明类型通常是 @@ -569,7 +586,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): init_arg_count += 1 # 调用 __init__(storage_ptr, *args) - self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name, "__init__", storage_ptr, init_arg_vals, init_arg_count, trans, diag_node_ct) + self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name, "__init__", storage_ptr, init_arg_vals, init_arg_count, trans, diag_node_ct, is_volatile) # 返回指针 return storage_ptr @@ -594,7 +611,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): field_ptr: llvmlite.Value* = llvmlite.build_gep_struct(builder, struct_ty, fe.Ty, tmp, fe.Index) if field_ptr is None: continue arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, fe.Ty, arg) - llvmlite.build_store(builder, arg_val, field_ptr) + llvmlite.build_store(builder, arg_val, field_ptr, is_volatile) # 处理关键字参数(按字段名查找) # SHA1 从 kw_entry 获取(规避跨模块同名 find_struct 找错) @@ -614,7 +631,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): field_ptr: llvmlite.Value* = llvmlite.build_gep_struct(builder, struct_ty, fe.Ty, tmp, fe.Index) if field_ptr is None: continue kw_val = self.Gen.ExprGenBase.coerce_to_type(builder, kw_val, fe.Ty, kw.value) - llvmlite.build_store(builder, kw_val, field_ptr) + llvmlite.build_store(builder, kw_val, field_ptr, is_volatile) # 返回指针(而非结构体值),赋值时由 coerce_to_type 按目标类型决定是否 load return tmp @@ -1155,6 +1172,9 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if arg_max_filled >= 0: arg_count = arg_max_filled + 1 + # 值位置 volatile 前缀:`a: T = volatile list[int](mb)` —— 构造写入带 volatile + gc_volatile: int = cl.IsVolatile + # 存储指针:默认用 alloca,如果有 __new__ 则用 __new__ 返回的指针 # __new__ 是可选的,仅当泛型类模板定义了 __new__ 方法时才调用 # (与 _translate_struct_ctor 保持一致,避免为无 __new__ 的类生成过度声明) @@ -1163,7 +1183,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if struct_entry is not None: has_new_flag = struct_entry.HasNew if has_new_flag != 0: - new_ptr: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__new__", tmp, extra_args, arg_count, trans) + new_ptr: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__new__", tmp, extra_args, arg_count, trans, None, gc_volatile) if new_ptr is not None: storage_ptr = new_ptr # __new__ 只保证返回"实例存储指针",声明类型通常是 @@ -1180,9 +1200,9 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): storage_ptr = nw_bc # call __before_init__(storage_ptr)(TransPyV 自动生成,零值填充) - self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__before_init__", storage_ptr, None, 0, trans) + self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__before_init__", storage_ptr, None, 0, trans, None, gc_volatile) # call __init__(storage_ptr, *args)(arg_count = 槽位 0..已填最高槽) - self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__init__", storage_ptr, extra_args, arg_count, trans) + self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__init__", storage_ptr, extra_args, arg_count, trans, None, gc_volatile) return storage_ptr \ No newline at end of file diff --git a/App/lib/core/Gen/Call/CallGenDispatch.vp b/App/lib/core/Gen/Call/CallGenDispatch.vp index e7c9cb8..72e000d 100644 --- a/App/lib/core/Gen/Call/CallGenDispatch.vp +++ b/App/lib/core/Gen/Call/CallGenDispatch.vp @@ -1138,7 +1138,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if self.Gen.ClassGenEnum._is_renum_class_name(st_nm.id) != 0: rc_tag_sc: int = self.Gen.ClassGenEnum._lookup_renum_variant_in_class(st_nm.id, func_name) if rc_tag_sc >= 0: - return self.Gen.CallGenCtor._translate_renum_construct(pool, builder, mod, st_nm.id, func_name, rc_tag_sc, cargs, can, trans) + return self.Gen.CallGenCtor._translate_renum_construct(pool, builder, mod, st_nm.id, func_name, rc_tag_sc, cargs, can, trans, cl.IsVolatile) st_res: llvmlite.Value* = self.Gen.CallGenProp._translate_static_class_call(pool, builder, mod, st_nm.id, func_name, cl, trans) if st_res is not None: return st_res diff --git a/App/lib/core/Gen/Call/CallGenMixin.vp b/App/lib/core/Gen/Call/CallGenMixin.vp index e85f98f..570b096 100644 --- a/App/lib/core/Gen/Call/CallGenMixin.vp +++ b/App/lib/core/Gen/Call/CallGenMixin.vp @@ -309,7 +309,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if gen_ctor_entry is not None: ctor_is_oop = gen_ctor_entry.IsOOP if ctor_is_oop != 0: - return self.Gen.CallGenCtor._translate_struct_ctor(pool, builder, mod, struct_ty, func_name, cargs, sizet(0), trans) + return self.Gen.CallGenCtor._translate_struct_ctor(pool, builder, mod, struct_ty, func_name, cargs, sizet(0), trans, cl.IsVolatile) # @t.NoVTable 类(无方法、类语义/指针对象):无参构造也应分配内存 # 返回指针。否则按值结构体返回 ConstZero(struct_ty),LHS 联合注解 # (如 Plain|CPtr)存 0 指针 → p.v 解引用 NULL 段错误 @@ -318,7 +318,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if gen_ctor_entry is not None: ctor_is_novt = gen_ctor_entry.IsNoVTable if ctor_is_novt != 0: - return self.Gen.CallGenCtor._translate_struct_ctor(pool, builder, mod, struct_ty, func_name, cargs, sizet(0), trans) + return self.Gen.CallGenCtor._translate_struct_ctor(pool, builder, mod, struct_ty, func_name, cargs, sizet(0), trans, cl.IsVolatile) # 普通结构体:检查是否有默认值(用 entry 直接访问) gen_has_defaults: int = 0 if gen_ctor_entry is not None: @@ -331,14 +331,14 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): gen_has_defaults = self.Gen.StructGen.struct_has_defaults(func_name) if gen_has_defaults == 1: # 有默认值:走构造函数路径应用默认值 - return self.Gen.CallGenCtor._translate_struct_ctor(pool, builder, mod, struct_ty, func_name, cargs, sizet(0), trans) + return self.Gen.CallGenCtor._translate_struct_ctor(pool, builder, mod, struct_ty, func_name, cargs, sizet(0), trans, cl.IsVolatile) # 无默认值:返回 zeroinitializer ret: llvmlite.Value* = llvmlite.ConstZero(pool, struct_ty) return ret if kw_count > 0: # 有关键字参数:按字段名赋值 - return self.Gen.CallGenCtor._translate_struct_ctor_kw(pool, builder, mod, struct_ty, func_name, cargs, can, keywords, kw_count, trans) - return self.Gen.CallGenCtor._translate_struct_ctor(pool, builder, mod, struct_ty, func_name, cargs, can, trans) + return self.Gen.CallGenCtor._translate_struct_ctor_kw(pool, builder, mod, struct_ty, func_name, cargs, can, keywords, kw_count, trans, cl.IsVolatile) + return self.Gen.CallGenCtor._translate_struct_ctor(pool, builder, mod, struct_ty, func_name, cargs, can, trans, cl.IsVolatile) # 裸名泛型类模板构造: Box(42) → 从实参推断类型实参 → 特化 → 构造 # (TPC 参考: _HandleGenericClassNewLlvm;GenericTest Test4 Box(42)/Test5 @@ -437,7 +437,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): f"变体表未注册或变体名不匹配", "NameError") if rc_tag >= 0: - return self.Gen.CallGenCtor._translate_renum_construct(pool, builder, mod, rc_cls_name, func_name, rc_tag, cargs, can, trans) + return self.Gen.CallGenCtor._translate_renum_construct(pool, builder, mod, rc_cls_name, func_name, rc_tag, cargs, can, trans, cl.IsVolatile) elif rc_at.value is not None and rc_at.value.kind() == ast.ASTKind.Attribute: # 模块限定 REnum 变体构造: mod.Class.Variant(args...) # 如 llvmlite.LLVMType.Struct(...) → 构造 llvmlite 模块 LLVMType 的 Struct 变体。 @@ -467,7 +467,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if self.Gen.ClassGenEnum._is_renum_class_name(rc_mq_cls) != 0: rc_mq_tag: int = self.Gen.ClassGenEnum._lookup_renum_variant_in_class(rc_mq_cls, func_name) if rc_mq_tag >= 0: - return self.Gen.CallGenCtor._translate_renum_construct(pool, builder, mod, rc_mq_cls, func_name, rc_mq_tag, cargs, can, trans) + return self.Gen.CallGenCtor._translate_renum_construct(pool, builder, mod, rc_mq_cls, func_name, rc_mq_tag, cargs, can, trans, cl.IsVolatile) # async 裸名调用(TPV-M1/M2):普通函数调用 async 函数(如 task(5, 6))→ # 生成 create_(args...) 调用(返回 Ptr(帧),bitcast 成 i8* 供变量存储)。