fix(vpireader): stub 全局变量声明保持 t.CStruct 值类型,修复跨模块字段访问当指针解引用
This commit is contained in:
1 parent
5d121f7166
commit
66fe13f407
1 file changed
+232
-39
@@ -1,5 +1,6 @@
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
@@ -911,6 +912,13 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy | t.CPtr,
|
||||
# t.XXX / c.XXX 内置类型映射
|
||||
if string.strncmp(seg, "t.", 2) == 0 or string.strncmp(seg, "c.", 2) == 0:
|
||||
attr_nm: str = seg + 2
|
||||
# t.CExport:导出标记,非真实类型。定义侧 FuncGenDef 已特判
|
||||
# CExport → Void(返回空),vpi 返回注解缓存原样缓存 "t.CExport",
|
||||
# 调用方解析必须同样归一 Void,否则 vpi 缓存 miss → 跨模块函数
|
||||
# 返回类型无法精确获取 fail-fast 误报(VKernel mm.free -> t.CExport
|
||||
# "1fdad1c76fb116bc.free 返回类型无法精确获取" 根因)。
|
||||
if string.strcmp(attr_nm, "CExport") == 0:
|
||||
return llvmlite.Void(pool)
|
||||
mapped_ty: llvmlite.LLVMType | t.CPtr = GenApi.map_t_type(pool, attr_nm)
|
||||
if mapped_ty is not None:
|
||||
return mapped_ty
|
||||
@@ -922,11 +930,23 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy | t.CPtr,
|
||||
mod_struct_ty: llvmlite.LLVMType | t.CPtr = GenApi.get_struct_type(cls_nm2)
|
||||
if mod_struct_ty is not None:
|
||||
return mod_struct_ty
|
||||
# 枚举兜底:t.CEnum 注册在独立 EnumTable(EnumEntry),不进 StructTable,
|
||||
# get_struct_type 查不到。如 fat32.close -> types.FRESULT(FRESULT 是枚举),
|
||||
# struct 落空必须回退枚举表取 BaseTy(通常 i32)。否则 vpi 返回注解解析
|
||||
# 失败 → 跨模块函数返回类型无法精确获取 → text.ll 缺失(依赖环)时
|
||||
# 永久 pending(VKernel fat32→sched→process→fat32 Phase A 死锁根因)。
|
||||
mod_enum_ty: llvmlite.LLVMType | t.CPtr = GenApi.get_enum_base_type(cls_nm2)
|
||||
if mod_enum_ty is not None:
|
||||
return mod_enum_ty
|
||||
return None
|
||||
# 裸类名 → 全局 struct 注册表
|
||||
bare_struct_ty: llvmlite.LLVMType | t.CPtr = GenApi.get_struct_type(seg)
|
||||
if bare_struct_ty is not None:
|
||||
return bare_struct_ty
|
||||
# 裸枚举名 → EnumTable 兜底(同上:枚举不在 StructTable)
|
||||
bare_enum_ty: llvmlite.LLVMType | t.CPtr = GenApi.get_enum_base_type(seg)
|
||||
if bare_enum_ty is not None:
|
||||
return bare_enum_ty
|
||||
# 裸 typedef 名(如 VOIDPTR)
|
||||
mapped_bare: llvmlite.LLVMType | t.CPtr = GenApi.map_t_type(pool, seg)
|
||||
if mapped_bare is not None:
|
||||
@@ -1333,8 +1353,6 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy | t.CPtr,
|
||||
sr_len_src: t.CSizeT = string.strlen(stub_rel_src)
|
||||
if sr_len_src > 3 and string.strncmp(stub_rel_src + sr_len_src - 3, ".vp", 3) == 0:
|
||||
sr_len_src -= 3
|
||||
elif sr_len_src > 3 and string.strncmp(stub_rel_src + sr_len_src - 3, ".py", 3) == 0:
|
||||
sr_len_src -= 3
|
||||
if sr_len_src > 0:
|
||||
src_mod_buf: str = stdlib.malloc(sr_len_src + 1)
|
||||
if src_mod_buf is not None:
|
||||
@@ -1357,6 +1375,47 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy | t.CPtr,
|
||||
funcs_ptr: GenTypes.FuncEntry | t.CPtr = trans._funcs
|
||||
max_funcs: int = 1024
|
||||
|
||||
# ============================================================
|
||||
# 第一遍:先注册所有 ClassDef(含字段 + 方法 declare),再处理
|
||||
# FunctionDef/AnnAssign。此前单遍顺序处理,类定义位于全局变量之后时
|
||||
# (如 devfs.vp:`directories: t.CArray[devfs_directory, MAX_DIRECTORIES]`
|
||||
# 在 `class devfs_directory` 之前),AnnAssign 全局变量解析裸类名时类
|
||||
# 未注册 → CArray 元素解析失败 fatal(VKernel PhaseA 根因)。
|
||||
# ============================================================
|
||||
i0: t.CSizeT
|
||||
for i0 in range(n):
|
||||
child0: ast.AST | t.CPtr = ch.get(i0)
|
||||
if child0 is None:
|
||||
continue
|
||||
if child0.kind() != ast.ASTKind.ClassDef:
|
||||
continue
|
||||
class_cd0: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(child0)
|
||||
if class_cd0 is None or class_cd0.name is None:
|
||||
continue
|
||||
cls_name_v0: str = class_cd0.name
|
||||
# 泛型类(class X[T])跳过:stub 模板签名含类级类型参数 T,注入时
|
||||
# T 无法确定;特化方法 define 已在 Phase1 生成,无需 stub 模板 declare。
|
||||
tp_stub0: list[str] | t.CPtr = class_cd0.type_params
|
||||
if tp_stub0 is not None and len(tp_stub0) > 0:
|
||||
continue
|
||||
_inject_class_struct_declare(pool, mod, class_cd0, cls_name_v0, trans,
|
||||
src_sha1, imported_modules, from_imports)
|
||||
cls_children0: list[ast.AST | t.CPtr] | t.CPtr = class_cd0.children
|
||||
if cls_children0 is not None:
|
||||
cn20: t.CSizeT = len(cls_children0)
|
||||
for ci20 in range(cn20):
|
||||
m_child0: ast.AST | t.CPtr = cls_children0.get(ci20)
|
||||
if m_child0 is None:
|
||||
continue
|
||||
if m_child0.kind() != ast.ASTKind.FunctionDef:
|
||||
continue
|
||||
m_fd0: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(m_child0)
|
||||
if m_fd0 is None or m_fd0.name is None:
|
||||
continue
|
||||
_inject_method_declare(pool, mod, m_fd0, cls_name_v0, trans,
|
||||
src_sha1, imported_modules, from_imports,
|
||||
i32_ty, i8_ptr_ty, funcs_ptr, max_funcs)
|
||||
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
child: ast.AST | t.CPtr = ch.get(i)
|
||||
@@ -1381,49 +1440,52 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy | t.CPtr,
|
||||
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(child)
|
||||
if aa is None:
|
||||
continue
|
||||
if aa.target is not None and aa.target.kind() == ast.ASTKind.Name:
|
||||
dbg_tn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
|
||||
if dbg_tn.id is not None and dbg_tn.id[0] != '\0': # 存疑
|
||||
if string.strcmp(dbg_tn.id, "irq_handler_t") == 0 \
|
||||
or string.strcmp(dbg_tn.id, "gdt") == 0 \
|
||||
or string.strcmp(dbg_tn.id, "KBD_BUF_SIZE") == 0:
|
||||
dbg_ct: int = GenApi._is_ctypedef_annotation(aa.annotation)
|
||||
dbg_cd: int = GenApi.is_cdefine_annotation(aa.annotation)
|
||||
if GenApi._is_ctypedef_annotation(aa.annotation) != 0:
|
||||
_register_ctypedef_from_annassign(pool, aa)
|
||||
elif GenApi.is_cdefine_annotation(aa.annotation) != 0:
|
||||
# vpi 里 CDefine 定义(如 keyboard.vp 的 KBD_BUF_SIZE: t.CDefine = 1024)
|
||||
# 注册到当前文件 CDefine 表,供同 vpi 后续 t.CArray count 引用解析
|
||||
# (否则跨模块 count 查找 [CDEF-MISS] fail-fast,VKernel PhaseA 根因)
|
||||
if aa.target is not None and aa.target.kind() == ast.ASTKind.Name \
|
||||
and aa.value is not None:
|
||||
cdef_tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
|
||||
if cdef_tgt.id is not None:
|
||||
# 字符串 CDefine(版本号等)跳过:extract_cdefine_int_value
|
||||
# 对字符串常量 fail-fast,且 count 引用只关心整数 CDefine
|
||||
cdef_is_str: int = 0
|
||||
cdef_is_float: int = 0
|
||||
cdef_float_val: double = 0.0
|
||||
if aa.value.kind() == ast.ASTKind.Constant:
|
||||
cn_v: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(aa.value)
|
||||
if cn_v.const_kind == ast.CONST_STR:
|
||||
cdef_is_str = 1
|
||||
elif cn_v.const_kind == ast.CONST_FLOAT:
|
||||
cdef_is_float = 1
|
||||
cdef_float_val = cn_v.float_val
|
||||
if cdef_is_str == 0 and cdef_is_float != 0:
|
||||
# 浮点 CDefine(如 FRAGMENTATION_THRESHOLD: t.CDefine = 0.7)
|
||||
# 用 register_cdefine_double 注册(走整数提取会 fail-fast)
|
||||
GenApi.register_cdefine_double(pool, cdef_tgt.id, cdef_float_val)
|
||||
elif cdef_is_str == 0:
|
||||
cdef_val: t.CInt64T = GenApi.extract_cdefine_int_value(aa.value)
|
||||
GenApi.register_cdefine_constant(pool, cdef_tgt.id, cdef_val)
|
||||
else:
|
||||
_inject_global_variable_declare(pool, mod, aa, trans,
|
||||
stub_imported_modules, stub_from_imports,
|
||||
i32_ty, i8_ptr_ty, src_sha1)
|
||||
continue
|
||||
|
||||
# ClassDef → 递归注入类内方法(如 MemBuddy.__init__/alloc)
|
||||
# 方法 declare 使用 {sha1}.{ClassName}.{method} 混淆名,
|
||||
# 参数类型从 vpi 注解解析(避免调用时 _ensure_method_declare 用实参类型
|
||||
# 创建错误 declare,如 size: t.CSizeT 被写成 i32 而非 i64)
|
||||
if kd == ast.ASTKind.ClassDef:
|
||||
class_cd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(child)
|
||||
if class_cd is None or class_cd.name is None:
|
||||
continue
|
||||
cls_name_v: str = class_cd.name
|
||||
# 泛型类(class X[T])跳过方法 declare 注入:stub 模板签名含类级
|
||||
# 类型参数 T(如 ndarray[T].__add__ 的返回 ndarray[T] | t.CPtr),
|
||||
# 注入时 T 无法确定具体类型,直接解析会触发
|
||||
# _specialize_generic_class("ndarray", ["T"]) 错误特化
|
||||
# (Phase2 翻译 App 文件注入 numpy stub 时崩溃)。
|
||||
# 具体特化的方法 define 已在 Phase1 生成,跨模块调用按特化类名
|
||||
# (ndarray[t.CDouble].__add__)查找命中,无需 stub 模板 declare。
|
||||
tp_stub: list[str] | t.CPtr = class_cd.type_params
|
||||
if tp_stub is not None and len(tp_stub) > 0:
|
||||
continue
|
||||
cls_children: list[ast.AST | t.CPtr] | t.CPtr = class_cd.children
|
||||
if cls_children is not None:
|
||||
cn2: t.CSizeT = len(cls_children)
|
||||
for ci2 in range(cn2):
|
||||
m_child: ast.AST | t.CPtr = cls_children.get(ci2)
|
||||
if m_child is None:
|
||||
continue
|
||||
if m_child.kind() != ast.ASTKind.FunctionDef:
|
||||
continue
|
||||
m_fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(m_child)
|
||||
if m_fd is None or m_fd.name is None:
|
||||
continue
|
||||
_inject_method_declare(pool, mod, m_fd, cls_name_v, trans,
|
||||
src_sha1, imported_modules, from_imports,
|
||||
i32_ty, i8_ptr_ty, funcs_ptr, max_funcs)
|
||||
continue
|
||||
# ClassDef → 已在第一遍统一注册(含字段 + 方法 declare),此处跳过
|
||||
# (原单遍顺序处理在类定义位于全局变量之后时,AnnAssign 全局变量
|
||||
# 解析裸类名找不到类 → CArray 元素解析失败 fatal,见上方第一遍注释)
|
||||
|
||||
# Import/ImportFrom → 跳过
|
||||
# (import 不需要处理)
|
||||
@@ -1436,6 +1498,118 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy | t.CPtr,
|
||||
return 1
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _inject_class_struct_declare - 从 vpi ClassDef 注册类为 struct 类型
|
||||
#
|
||||
# 背景:vpi stub 注入(ParseVpiIntoModule)此前只注入类内方法 declare,
|
||||
# 不注册类本身 → 严格模式下(strict_mode:true)同一 vpi 内后续 AnnAssign
|
||||
# 全局变量的裸类名注解(如 gdt.vp 的 `gdt: t.CArray[gdt_entry, 7]` 元素
|
||||
# gdt_entry)is_struct_visible=0 → resolve_annotation_type 返回 None →
|
||||
# TypeGenResolve CArray 元素解析失败 fatal(ViperOS VKernel apic.vp 编译
|
||||
# 根因)。源模块编译时 ClassGenDef.translate_class_def 会 add_visible_struct
|
||||
# + register_struct(含字段),vpi 注入缺同一注册 → 此处补齐:
|
||||
# 1. 已注册(find_struct_by_module 按 name+sha1 命中,含源模块编译时注册)
|
||||
# → 仅 add_visible_struct 标记当前文件可见
|
||||
# 2. 未注册 → 解析字段类型 → 创建命名 StructType("sha1.ClassName") →
|
||||
# register_struct + add_visible_struct
|
||||
# 字段解析失败不 fatal(不注册该类,留给源模块编译注册;若 vpi 内后续
|
||||
# 裸类名引用它则由调用侧 fail-fast 暴露)。
|
||||
# ============================================================
|
||||
def _inject_class_struct_declare(pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
class_cd: ast.ClassDef | t.CPtr,
|
||||
cls_name: str,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
src_sha1: str,
|
||||
imported_modules: str,
|
||||
from_imports: str) -> int:
|
||||
"""从 vpi ClassDef 注册类为 struct 类型(含字段),使同 vpi 内裸类名注解可解析"""
|
||||
if pool is None or mod is None or class_cd is None or cls_name is None:
|
||||
return 0
|
||||
# 1. 已注册检查(含源模块编译时注册的 entry):仅标记可见,避免重复注册
|
||||
if src_sha1 is not None and src_sha1[0] != '\0':
|
||||
existing_c: GenTypes.StructEntry | t.CPtr = GenApi.find_struct_by_module(cls_name, src_sha1)
|
||||
if existing_c is not None and existing_c.Ty is not None:
|
||||
GenApi.add_visible_struct(pool, cls_name)
|
||||
return 1
|
||||
# 2. 收集字段类型(AnnAssign 子节点,仿 ClassGenDef.translate_class_def)
|
||||
field_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * GenTypes.FIELD_MAX)
|
||||
field_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * GenTypes.FIELD_MAX)
|
||||
if field_names_buf is None or field_types_buf is None:
|
||||
return 0
|
||||
string.memset(field_names_buf, 0, 8 * GenTypes.FIELD_MAX)
|
||||
string.memset(field_types_buf, 0, 8 * GenTypes.FIELD_MAX)
|
||||
field_count: int = 0
|
||||
cls_children_c: list[ast.AST | t.CPtr] | t.CPtr = class_cd.children
|
||||
if cls_children_c is not None:
|
||||
cn_c: t.CSizeT = len(cls_children_c)
|
||||
for ci_c in range(cn_c):
|
||||
m_child_c: ast.AST | t.CPtr = cls_children_c.get(ci_c)
|
||||
if m_child_c is None:
|
||||
continue
|
||||
if m_child_c.kind() != ast.ASTKind.AnnAssign:
|
||||
continue
|
||||
m_aa_c: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(m_child_c)
|
||||
if m_aa_c is None or m_aa_c.target is None:
|
||||
continue
|
||||
if m_aa_c.target.kind() != ast.ASTKind.Name:
|
||||
continue
|
||||
m_tgt_c: ast.Name | t.CPtr = (ast.Name | t.CPtr)(m_aa_c.target)
|
||||
if m_tgt_c.id is None:
|
||||
continue
|
||||
field_ty_c: llvmlite.LLVMType | t.CPtr = GenApi.resolve_annotation_type(
|
||||
pool, m_aa_c.annotation, imported_modules, from_imports, trans, 0)
|
||||
if field_ty_c is None:
|
||||
# 字段类型解析失败:不注册该类(留给源模块编译注册),不 fatal
|
||||
return 0
|
||||
if field_count < GenTypes.FIELD_MAX:
|
||||
field_names_buf[field_count] = t.CSizeT(m_tgt_c.id)
|
||||
field_types_buf[field_count] = t.CSizeT(field_ty_c)
|
||||
field_count += 1
|
||||
# 3. 构建 ParamNode 链表
|
||||
first_node_c: llvmlite.ParamNode | t.CPtr = None
|
||||
prev_node_c: llvmlite.ParamNode | t.CPtr = None
|
||||
for fi_c in range(field_count):
|
||||
fty_c: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(
|
||||
t.CVoid(field_types_buf[fi_c], t.CPtr))
|
||||
pnode_c: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__())
|
||||
if pnode_c is None:
|
||||
continue
|
||||
string.memset(pnode_c, 0, llvmlite.ParamNode.__sizeof__())
|
||||
pnode_c.Ty = fty_c
|
||||
if first_node_c is None:
|
||||
first_node_c = pnode_c
|
||||
if prev_node_c is not None:
|
||||
prev_node_c.Next = pnode_c
|
||||
prev_node_c = pnode_c
|
||||
# 4. 命名结构体类型名 "sha1.ClassName"(与定义侧 ClassGenDef 一致)
|
||||
type_name_c: str = cls_name
|
||||
if src_sha1 is not None and src_sha1[0] != '\0':
|
||||
name_buf_c: str = pool.alloc(64)
|
||||
if name_buf_c is not None:
|
||||
viperlib.snprintf(name_buf_c, 64, "%s.%s", src_sha1, cls_name)
|
||||
type_name_c = name_buf_c
|
||||
struct_ty_c: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(
|
||||
pool, first_node_c, field_count, type_name_c)
|
||||
if struct_ty_c is None:
|
||||
return 0
|
||||
# 5. StdlibAlloc(Phase B)时深拷贝到 perm_pool,跨文件 reset 存活
|
||||
# (对齐 ClassGenDef.translate_class_def L489-494)
|
||||
if GenApi.get_stdlib_alloc() != 0:
|
||||
st_copy_c: llvmlite.LLVMType | t.CPtr = llvmlite.DeepCopyType(
|
||||
CompilerFactory.get_perm_pool(), struct_ty_c)
|
||||
if st_copy_c is not None:
|
||||
struct_ty_c = st_copy_c
|
||||
# 6. 注册到当前模块(输出类型定义行)+ 全局 StructTable + 可见性
|
||||
llvmlite.module_add_named_type(mod, pool, struct_ty_c)
|
||||
entry_c: GenTypes.StructEntry | t.CPtr = GenApi.register_struct(
|
||||
pool, cls_name, struct_ty_c, src_sha1)
|
||||
if entry_c is None:
|
||||
return 0
|
||||
GenApi.add_visible_struct(pool, cls_name)
|
||||
return 1
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _inject_global_variable_declare - 从 vpi AnnAssign 创建模块级全局变量 declare
|
||||
#
|
||||
@@ -1470,7 +1644,14 @@ def _inject_global_variable_declare(pool: memhub.MemBuddy | t.CPtr,
|
||||
# 注:a42923c 曾把此处写成未定义变量 gv_name_m(笔误,mangle 未实现),
|
||||
# 导致注入空名 @ = external global → llc "expected top-level entity"。
|
||||
gv_name_m: str = gname_v
|
||||
if src_sha1 is not None and src_sha1[0] != '\0':
|
||||
# CExport 全局:定义端用裸名(@gp),stub 声明必须同步裸名,否则跨模块
|
||||
# 引用生成 @sha1.gp → 与定义端 @gp 不匹配 → ld.lld undefined symbol
|
||||
# (gdt.vp gdt/gp、idt.vp idt、sched.vp _sched_ptr/_switch_*_rsp、
|
||||
# coroutine.vp _coro_*、process.vp _saved_cr3 等 CExport 全局根因)。
|
||||
is_gv_cexport: int = 0
|
||||
if aa.annotation is not None:
|
||||
is_gv_cexport = GenApi.has_decorator_marker(aa.annotation, "CExport")
|
||||
if src_sha1 is not None and src_sha1[0] != '\0' and is_gv_cexport == 0:
|
||||
ml_v: t.CSizeT = string.strlen(src_sha1) + 1 + string.strlen(gname_v) + 1
|
||||
gv_name_m = pool.alloc(ml_v)
|
||||
if gv_name_m is not None:
|
||||
@@ -1491,7 +1672,13 @@ def _inject_global_variable_declare(pool: memhub.MemBuddy | t.CPtr,
|
||||
gv_ty_v: llvmlite.LLVMType | t.CPtr = resolved_v
|
||||
match resolved_v:
|
||||
case llvmlite.LLVMType.Struct(_, _, _):
|
||||
gv_ty_v = llvmlite.Ptr(pool, resolved_v)
|
||||
# t.CStruct 值类(如 pci_device):模块级全局变量定义端是值实例
|
||||
# (handle_module_level_var 直接 new_global_variable(pool, name, resolved_v)),
|
||||
# stub 声明必须保持值类型(%struct),否则跨模块字段访问 mod.var.field
|
||||
# 生成 load %T**, %T** → 把实例前 8 字节当指针解引用 → 垃圾地址 #GP
|
||||
# (uhci.vp pci._uhci_dev.irq 根因)。@t.Object 类 resolve 已返回
|
||||
# Ptr(struct),不会命中本分支,对象即指针语义不受影响。
|
||||
gv_ty_v = resolved_v
|
||||
case llvmlite.LLVMType.Array(aelem_v, acount_v):
|
||||
# 定长数组(CArray[T, N]):保留完整数组类型 [N x T],与定义端
|
||||
# handle_module_level_var 生成的 global [N x T] 一致——此前一律
|
||||
@@ -1505,6 +1692,12 @@ def _inject_global_variable_declare(pool: memhub.MemBuddy | t.CPtr,
|
||||
gv_ty_v = llvmlite.Ptr(pool, aelem_v)
|
||||
case _:
|
||||
gv_ty_v = resolved_v
|
||||
# 确保跨模块结构体类型在模块中有 opaque 声明:external global 类型
|
||||
# (如 [7 x %gdt_entry])内嵌 struct 无任何定义时,llc 报 "use of
|
||||
# undefined type named 'sha1.gdt_entry'"(fpu/fat32 合并 IR 根因)。
|
||||
# 对齐 TranslatorGenMixin 创建全局前的 module_ensure_opaque_for_type
|
||||
# (_scan_type_for_cross_module_refs 递归 Array/Struct/Ptr)。
|
||||
llvmlite.module_ensure_opaque_for_type(mod, pool, gv_ty_v)
|
||||
gv_v: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, gv_name_m, gv_ty_v)
|
||||
if gv_v is None:
|
||||
return
|
||||
|
||||
Reference in new issue
Block a user