fix(gen): @t.Object 类模块级变量转 Ptr(struct),t.CStruct 值类保持值,修复 devfs 虚表调用跳栈 #PF

This commit is contained in:
TermiNexus committed 2026-08-26 22:33:11 +08:00
1 parent 66fe13f407
commit e82664fa67
3 files changed
+237 -17

No files matched your search

+13 -7
View File
@@ -1672,13 +1672,19 @@ 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(_, _, _):
# 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
# 对象类(@t.Object/@t.CVTable:对象即指针,HasNew/HasVTable/IsOOP)
# → Ptr(struct),与定义端 handle_module_level_var 一致;否则纯
# t.CStruct 值类(如 pci_device)保持值实例。此前一律转 Ptr 导致
# 跨模块字段访问把实例前 8 字节当指针解引用 → 垃圾地址 #GP
# (uhci.vp pci._uhci_dev.irq 根因);一律保持值则 @t.Object 类
# 模块级变量(如 devfs.vp serial0_file.open)按指针访问读错 vtable
# → 调用跳栈 #PF。
gv_entry_v: GenTypes.StructEntry | t.CPtr = GenApi.find_struct_by_type(resolved_v)
if gv_entry_v is not None \
and (gv_entry_v.HasNew != 0 or gv_entry_v.HasVTable != 0 or gv_entry_v.IsOOP != 0):
gv_ty_v = llvmlite.Ptr(pool, resolved_v)
else:
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] 一致——此前一律
+105 -4
View File
@@ -142,22 +142,23 @@ def _is_ctypedef_annotation(annotation: ast.AST | t.CPtr) -> int:
# ---------------- resolve_annotation_type(委托 TypeGenResolve.resolve_annotation_type) ----------------
def resolve_annotation_type(pool: memhub.MemBuddy | t.CPtr, node: ast.AST | t.CPtr, imported_modules: str, from_imports: str, trans: HT.Translator | t.CPtr = None) -> llvmlite.LLVMType | t.CPtr:
def resolve_annotation_type(pool: memhub.MemBuddy | t.CPtr, node: ast.AST | t.CPtr, imported_modules: str, from_imports: str, trans: HT.Translator | t.CPtr = None, depth: int = 0) -> llvmlite.LLVMType | t.CPtr:
"""委托到 gen.resolve_annotation_type(原 Handles 壳)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.TypeGenResolve.resolve_annotation_type(pool, node, imported_modules, from_imports, trans)
return g.TypeGenResolve.resolve_annotation_type(pool, node, imported_modules, from_imports, trans, depth)
return None
# ---------------- has_decorator_marker(委托 TypeGenErr.has_decorator_marker) ----------------
def has_decorator_marker(node: ast.AST | t.CPtr, marker_name: str) -> int:
def has_decorator_marker(node: ast.AST | t.CPtr, marker_name: str,
depth: int = 0) -> int:
"""委托到 gen.has_decorator_marker(原 Handles 壳)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.TypeGenErr.has_decorator_marker(node, marker_name)
return g.TypeGenErr.has_decorator_marker(node, marker_name, depth)
return 0
@@ -200,6 +201,46 @@ def is_cdefine_found() -> int:
return 0
# ---------------- register_cdefine_constant(委托 TypeGenCDef.register_cdefine_constant) ----------------
def register_cdefine_constant(pool: memhub.MemBuddy | t.CPtr,
name: str, value: t.CInt64T) -> None:
"""委托到 gen.register_cdefine_constant(原 Handles 壳)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.TypeGenCDef.register_cdefine_constant(pool, name, value)
# ---------------- register_cdefine_double(委托 TypeGenCDef.register_cdefine_double) ----------------
def register_cdefine_double(pool: memhub.MemBuddy | t.CPtr,
name: str, value: double) -> None:
"""委托到 gen.register_cdefine_double(原 Handles 壳)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.TypeGenCDef.register_cdefine_double(pool, name, value)
# ---------------- is_cdefine_annotation(委托 AssignGenMixin.is_cdefine_annotation) ----------------
def is_cdefine_annotation(annot: ast.AST | t.CPtr) -> int:
"""委托到 gen.is_cdefine_annotation(原 Handles 壳)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.AssignGen.is_cdefine_annotation(annot)
return 0
# ---------------- extract_cdefine_int_value(委托 AssignGenMixin.extract_cdefine_int_value) ----------------
def extract_cdefine_int_value(val_node: ast.AST | t.CPtr) -> t.CInt64T:
"""委托到 gen.extract_cdefine_int_value(原 Handles 壳)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.AssignGen.extract_cdefine_int_value(val_node)
return 0
# ---------------- push_trace(委托 TypeGenBase.push_trace) ----------------
def push_trace(file_name: str, lineno: int, col_start: int = 0, col_end: int = 0) -> None:
"""委托到 gen.push_trace(原 Handles 壳)"""
@@ -276,6 +317,22 @@ def get_struct_type(class_name: str) -> llvmlite.LLVMType | t.CPtr:
return None
# ---------------- get_enum_base_type(委托 StmtGenDeclMixin.get_enum_base_type) ----------------
def get_enum_base_type(enum_name: str) -> llvmlite.LLVMType | t.CPtr:
"""委托到 gen.get_enum_base_type(原 Handles 壳)
枚举(t.CEnum)注册在独立的 EnumTable(EnumEntry),不进 StructTable,
get_struct_type 查不到。vpi 返回注解如 "types.FRESULT" 解析时 struct
落空必须回退枚举表取 BaseTy(通常 i32),否则跨模块函数返回类型
无法精确获取 → text.ll 缺失(依赖环)时永久 pending(Phase A 死锁根因)。
"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.StmtGenDecl.get_enum_base_type(enum_name)
return None
# ---------------- add_visible_struct(委托 StructGenMixin.add_visible_struct) ----------------
def add_visible_struct(pool: memhub.MemBuddy | t.CPtr, name: str) -> None:
"""委托到 gen.add_visible_struct(原 Handles 壳)"""
@@ -285,6 +342,50 @@ def add_visible_struct(pool: memhub.MemBuddy | t.CPtr, name: str) -> None:
return g.StructGen.add_visible_struct(pool, name)
# ---------------- find_struct_by_module(委托 StructGenMixin.find_struct_by_module) ----------------
def find_struct_by_module(name: str, sha1: str) -> GenTypes.StructEntry | t.CPtr:
"""委托到 gen.find_struct_by_module(原 Handles 壳)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.StructGen.find_struct_by_module(name, sha1)
return None
# ---------------- find_struct_by_type(委托 StructGenMixin.find_struct_by_type) ----------------
def find_struct_by_type(struct_ty: llvmlite.LLVMType | t.CPtr) -> GenTypes.StructEntry | t.CPtr:
"""委托到 gen.find_struct_by_type(原 Handles 壳)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.StructGen.find_struct_by_type(struct_ty)
return None
# ---------------- register_struct(委托 StructGenMixin.register_struct) ----------------
def register_struct(pool: memhub.MemBuddy | t.CPtr,
name: str,
struct_ty: llvmlite.LLVMType | t.CPtr,
sha1: str = None) -> GenTypes.StructEntry | t.CPtr:
"""委托到 gen.register_struct(原 Handles 壳)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.StructGen.register_struct(pool, name, struct_ty, sha1)
return None
# ---------------- get_stdlib_alloc(委托 StructGenMixin.get_stdlib_alloc) ----------------
def get_stdlib_alloc() -> int:
"""委托到 gen.get_stdlib_alloc(原 Handles 壳)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.StructGen.get_stdlib_alloc()
return 0
# ---------------- compute_package_from_relpath(委托 ImportsGenMixin.compute_package_from_relpath) ----------------
def compute_package_from_relpath(pool: memhub.MemBuddy | t.CPtr, rel_path: str) -> str:
"""委托到 gen.compute_package_from_relpath(原 Handles 壳)"""
+119 -6
View File
@@ -71,8 +71,8 @@ class TranslatorGenMixin:
has_export: int = 0
has_state: int = 0
if fd.returns is not None:
has_export = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CExport")
has_state = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State")
has_export = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CExport", 0)
has_state = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0)
if has_export != 0 or has_state != 0:
self.Gen.CallGenBase.register_cexport_func(trans.ModuleSha1, fd.name)
@@ -174,7 +174,7 @@ class TranslatorGenMixin:
imp: str = trans._imported_modules
fi: str = trans._from_imports
if fd.returns is not None:
self.Gen.TypeGenResolve.resolve_annotation_type(pool, fd.returns, imp, fi, trans)
self.Gen.TypeGenResolve.resolve_annotation_type(pool, fd.returns, imp, fi, trans, 0)
if fd.args is not None:
ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(fd.args)
if ags.args is not None:
@@ -184,7 +184,7 @@ class TranslatorGenMixin:
for ai in range(an):
ag: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(al.get(ai))
if ag is not None and ag.annotation is not None:
self.Gen.TypeGenResolve.resolve_annotation_type(pool, ag.annotation, imp, fi, trans)
self.Gen.TypeGenResolve.resolve_annotation_type(pool, ag.annotation, imp, fi, trans, 0)
# ============================================================
# _build_array_initializer_text - 从 AST List 生成 LLVM IR 数组初始化器
@@ -218,8 +218,10 @@ class TranslatorGenMixin:
# 确定元素类型的 IR 表示
elem_ir_ty: str = "i8"
is_int_elem: int = 1
match elem_ty:
case llvmlite.LLVMType.Int(bits):
is_int_elem = 1
if bits == 8:
elem_ir_ty = "i8"
elif bits == 16:
@@ -228,6 +230,8 @@ class TranslatorGenMixin:
elem_ir_ty = "i32"
elif bits == 64:
elem_ir_ty = "i64"
case _:
is_int_elem = 0
# 获取列表元素(通过 ln.elts 而非 list_node.elts,确保类型正确识别)
elts: list[ast.AST | t.CPtr] | t.CPtr = ln.elts
@@ -235,6 +239,93 @@ class TranslatorGenMixin:
return None
elts_count: t.CSizeT = len(elts)
# 非整数元素类型(struct/指针等聚合):不存在 "%s %lld" 文本展开。
# 仅当列表全零(元素缺失按零填充)时返回整体 "zeroinitializer"——
# 对任意聚合类型合法(devfs.directories: t.CArray[devfs_directory, N]
# = [0] 此前生成 [i8 0, ...] 与 [N x %devfs_directory] 类型不匹配,
# llc "constant expression type mismatch" 根因)。含非零/非整数常量
# 无法文本表达 → None → 调用方 fail-fast。
if is_int_elem == 0:
# 嵌套数组元素(t.CArray[t.CArray[t.CUInt8T, 16], 256] = [{...}, ...]):
# elem_ty 是 Array → 递归构建子数组初始化器文本。内层类型省略
# (由外层全局类型推断),llc 合法。vga.vp font 8x16 点阵字库根因:
# 此前只支持 Int 元素,嵌套数组走 zeroinitializer-only 检查,花括号
# 行(ast.Set)含非零常量 → None → "初始化器构建失败" fail-fast。
is_nested_arr: int = 0
match elem_ty:
case llvmlite.LLVMType.Array(_, _):
is_nested_arr = 1
case _:
pass
if is_nested_arr != 0:
cnt_total_n: t.CSizeT = t.CSizeT(arr_count)
buf_size_n: t.CSizeT = 128 + cnt_total_n * 192
buf_n: str = pool.alloc(buf_size_n)
if buf_n is None:
return None
written_n: t.CInt = viperlib.snprintf(buf_n, buf_size_n, "[")
pos_n: t.CSizeT = t.CSizeT(written_n)
# 子数组元素类型前缀(如 "[16 x i8]"):嵌套数组初始化器内层
# 必须显式类型(llc 对省略内层类型的 [[i8 0,...],...] 报
# "expected number in address space";用户规范要求
# [[16 x i8][i8 0, ...], ...] 形式)。TypePrint 序列化 elem_ty。
elem_ty_str_n: str = pool.alloc(96)
if elem_ty_str_n is None:
return None
llvmlite.TypePrint(elem_ty_str_n, 96, elem_ty, pool)
i_n: t.CSizeT = 0
while i_n < cnt_total_n:
sub_n: str = None
if i_n < elts_count:
en_n: ast.AST | t.CPtr = elts.get(i_n)
if en_n is not None:
ek_n: int = en_n.kind()
if ek_n == ast.ASTKind.List:
sub_n = self._build_array_initializer_text(
pool, elem_ty, (ast.List | t.CPtr)(en_n))
elif ek_n == ast.ASTKind.Set:
# 花括号行字面量(如点阵字库 {0x00, ...}):Set.elts
# 与 List 同构,包装为临时 List 递归生成子数组文本
se_n: ast.Set | t.CPtr = (ast.Set | t.CPtr)(en_n)
if se_n is not None and se_n.elts is not None:
sub_n = self._build_array_initializer_text(
pool, elem_ty, ast.List(pool, se_n.elts, ast.ASTCtx.Load))
if sub_n is None:
# 元素缺失/无法展开:子数组整体零初始化
sub_n = "zeroinitializer"
if i_n > 0:
written_n = viperlib.snprintf(buf_n + pos_n, buf_size_n - pos_n, ", ")
pos_n += t.CSizeT(written_n)
written_n = viperlib.snprintf(
buf_n + pos_n, buf_size_n - pos_n, "%s%s", elem_ty_str_n, sub_n)
pos_n += t.CSizeT(written_n)
i_n += 1
viperlib.snprintf(buf_n + pos_n, buf_size_n - pos_n, "]")
return buf_n
for zi in range(elts_count):
ze: ast.AST | t.CPtr = elts.get(zi)
if ze is None:
continue
zk: int = ze.kind()
if zk == ast.ASTKind.Constant:
zc: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(ze)
if zc is None:
continue
# None(CONST_NONE)视为零:函数指针数组
# irq_handlers: t.CArray[irq_handler_t, 16] = [None] 表示
# 全空(idt.vp L387)——CONST_NONE 不是 CONST_INT,此前
# 被拒 → "初始化器构建失败" fail-fast。None 归一零填充。
if zc.const_kind == ast.CONST_NONE:
continue
if zc.const_kind != ast.CONST_INT or zc.int_val != 0:
return None
elif zk == ast.ASTKind.UnaryOp:
if self.Gen.AssignGen.extract_cdefine_int_value(ze) != 0:
return None
else:
return None
return "zeroinitializer"
# 计算缓冲区大小: 每个元素最多 "i32 -9223372036854775808, " 约 26 字符
# 按数组声明长度 arr_count 计算(元素不足时补零,可能多于 elts_count)
cnt_total: t.CSizeT = t.CSizeT(arr_count)
@@ -411,6 +502,7 @@ class TranslatorGenMixin:
init_kind: int = 0 # 0=none, 1=int, 2=list, 3=str
init_str_val: str = None
init_list_node: ast.List | t.CPtr = None
annot_node: ast.AST | t.CPtr = None # 类型注解节点(检测 t.CExport 标记)
if k == ast.ASTKind.AnnAssign:
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node)
@@ -420,11 +512,23 @@ class TranslatorGenMixin:
return 0
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
var_name = nm.id
annot_node = aa.annotation
# 解析类型
if aa.annotation is not None:
resolved: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, aa.annotation, trans._imported_modules, trans._from_imports, trans)
pool, aa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
if resolved is not None:
# 对象类模块级变量(@t.Object/@t.CVTable:对象即指针)→ Ptr(struct)。
# 裸类名注解 resolve 返回 struct 值(参数层 FuncGenDef 会包装 Ptr,
# 模块级变量此处缺包装)→ 若建成值实例,跨模块字段访问/虚表调用
# 按指针处理读首 8 字节当 vtable → 垃圾地址 #PF(devfs.vp
# serial0_file.open = serial0_open 根因)。纯 t.CStruct(无方法
# 无虚表无 __new__,如 pci_device)保持值实例。
if resolved.kind() == llvmlite.LLVMType.Struct:
gv_entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct_by_type(resolved)
if gv_entry is not None \
and (gv_entry.HasNew != 0 or gv_entry.HasVTable != 0 or gv_entry.IsOOP != 0):
resolved = llvmlite.Ptr(pool, resolved)
var_ty = resolved
# 解析初始值(支持整数、列表字面量、字符串字面量)
if aa.value is not None:
@@ -494,7 +598,16 @@ class TranslatorGenMixin:
# 模块级全局命名带 SHA1 前缀(对齐函数名 mangling):多个模块声明同名
# 全局(如 _mbuddy)时各自独立命名,消除 ld.lld duplicate symbol。
# SymTab 注册 key 保持裸名(查找逻辑零改动),LLVM 符号名用 mangled 名。
mangled_name: str = self.Gen.FuncGenBase._mangle_name(trans, var_name)
# t.CExport 标记的全局用裸名(内联汇编引用 / 外部符号对接,如
# VKernel gdt/gp/_switch_old_rsp/_coro_* 被 c.Asm 引用,带 SHA1 前缀
# 无法在 LLVM MC 中解析)。
is_global_cexport: int = 0
if annot_node is not None:
is_global_cexport = self.Gen.TypeGenErr.has_decorator_marker(
annot_node, "CExport", 0)
mangled_name: str = var_name
if is_global_cexport == 0:
mangled_name = self.Gen.FuncGenBase._mangle_name(trans, var_name)
gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, mangled_name, var_ty)
if gv is None:
return 0