feat(gen): volatile 构造写入落 LLVM volatile(逐字段 store + 构造三方法屏障)
值位置 volatile 前缀(a: int = volatile f() / a: S = volatile S(...))此前只在调用点无落点。LLVM 的 call 指令没有 volatile 限定符,故语义只能落在内存存取上: - AssignGenMixin:赋值目标的结果槽按 volatile 存取(本次 store 立即带 volatile,并登记 VarEntry.IsVolatile 使后续 load/store 亦带);对已存在的 global/nonlocal/mod_glob 条目在分支前统一登记。 - CallGenCtor:_translate_struct_ctor / _translate_struct_ctor_kw / _translate_renum_construct / _apply_struct_defaults 增加 is_volatile 参数,清零、tag、默认值、逐字段 store 全部带 volatile;_translate_generic_ctor_call 直接从 cl.IsVolatile 取。 - CallGenCall._call_method_on_ptr 增加 is_volatile 参数:__new__/__before_init__/__init__ 的写入发生在被调函数内部,调用点无法逐条附加 volatile,故在调用后对该 self 指针追加一次 i8 volatile load 作为内存屏障,使构造写入不被优化器消除或跨越重排。 - CallGenMixin / CallGenDispatch:结构体、关键字、泛型、REnum 构造调用点统一透传 cl.IsVolatile。
This commit is contained in:
1 parent
7d28c9649e
commit
cf815b17de
5 files changed
+104
-39
No files matched your search
@@ -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__)
|
||||
|
||||
@@ -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)
|
||||
#
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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_<name>(args...) 调用(返回 Ptr(帧),bitcast 成 i8* 供变量存储)。
|
||||
|
||||
Reference in new issue
Block a user