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__)
|
||||
|
||||
Reference in new issue
Block a user