修正了部分代码的表达方式,最后可用版本,mlirlite 已基本完善

This commit is contained in:
TermiNexus committed 2026-09-23 17:41:49 +08:00
1 parent 951b89be36
commit a7af34bd7e
36 files changed
+1755 -3656

No files matched your search

File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+29 -47
View File
@@ -16,37 +16,32 @@ import lib.core.Gen.Generator as Generator
# 方法元数据/类元数据/装饰器/异常表容量与编码;本地副本避免跨模块 CDefine 查找)
# ============================================================
# 方法元数据 flag 位(对齐 TPC HandlesBase _METHOD_META_*)
META_TLS: t.CDefine = 32
define META_TLS = 32
# 类编译期元数据表容量上限(__provides__/__requires__/__require_must__)
CLASS_META_MAX: t.CDefine = 256
define CLASS_META_MAX = 256
# 自定义装饰器 wrapper 表容量上限(带 @decor 的函数数)
DECOR_FUNC_MAX: t.CDefine = 64
define DECOR_FUNC_MAX = 64
# 装饰器表槽内函数名/wrapper 名长度(含 NUL)
DECOR_NAME_LEN: t.CDefine = 128
define DECOR_NAME_LEN = 128
# 异常类注册表容量上限(class X(Exception) 自定义异常类)
EXCEPTION_MAX: t.CDefine = 64
define EXCEPTION_MAX = 64
# 异常类表槽内类名/父类名长度(含 NUL)
EXCEPTION_NAME_LEN: t.CDefine = 128
define EXCEPTION_NAME_LEN = 128
# 内置异常编码(对齐 TPC HandlesBase.py EXCEPTION_CODE_MAP);
# KeyError=6 IOError=7 OSError=8 AssertionError=9 Exception=99;用户类从 100 起
BUILTIN_EH_VALUE_ERROR: t.CDefine = 1
BUILTIN_EH_RUNTIME_ERROR: t.CDefine = 3
BUILTIN_EH_EXCEPTION: t.CDefine = 99
EH_USER_CODE_START: t.CDefine = 100
define BUILTIN_EH_VALUE_ERROR = 1
define BUILTIN_EH_RUNTIME_ERROR = 3
define BUILTIN_EH_EXCEPTION = 99
define EH_USER_CODE_START = 100
# 方法元数据表容量(原 HandlesClassDef.META_MAX/META_KEY_LEN,阶段 D 拆分遗漏)
META_MAX: t.CDefine = 512
META_KEY_LEN: t.CDefine = 128
define META_MAX = 512
define META_KEY_LEN = 128
# ============================================================
# ClassGenBase - ClassGenMixin 拆分(阶段 D):字段 + 方法元数据/异常/继承检测/装饰器(Meta)
#
# 继承 ClassGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesClassDef 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ClassGenBase:
novirtual class ClassGenBase:
"""字段 + 方法元数据/异常/继承检测/装饰器(Meta)"""
# --- 方法元数据表(原 _g_method_meta_keys/_g_method_meta_flags/_g_method_meta_count) ---
@@ -100,7 +95,7 @@ class ClassGenBase:
DecoratorFuncNames: bytes
DecoratorWrapNames: bytes
# 装饰器首个常量参数(@repeat(3) 的 3),无参数为 0(每槽 8B,i64)
DecoratorArgs: int64 | t.CPtr
DecoratorArgs: int64*
# --- 异常类注册表(try-except,对齐 TPC HandlesClassDef.py L47-61) ---
# perm_pool 分配(跨 mark/reset 存活):每槽类名(128B) + 父类名(128B) + 编码(4B)
@@ -109,7 +104,7 @@ class ClassGenBase:
ExceptionCount: int
ExceptionNames: bytes
ExceptionParents: bytes
ExceptionCodes: int | t.CPtr
ExceptionCodes: int*
# 下一个待分配的异常编码(用户类,从 100 起)
NextExceptionCode: int
# 递归收集子孙编码用的临时计数(collect_descendant_codes 返回后无效)。
@@ -125,7 +120,7 @@ class ClassGenBase:
# --- 泛型模板表(原 HandlesClassDef._generic_class_names/
# _generic_class_nodes/_generic_class_sha1s) ---
GenericClassNames: list[str]*
GenericClassNodes: list[ast.ClassDef*] | t.CPtr
GenericClassNodes: list[ast.ClassDef*]*
GenericClassSha1s: list[str]*
# 泛型模板来源文件路径(与上面三表同序)。特化翻译模板方法体时 node.lineno 是模板
# 文件行号,若 CurrentFile 仍是调用方文件,fatal_error 会把模板行号套到调用方文件上
@@ -165,8 +160,7 @@ class ClassGenBase:
# 别名形式: from t import CEnum as en; class Color(en)
# 解析别名原始名(en → CEnum)再比较
if trans is not None and trans._from_imports is not None:
alias_orig: str = self.Gen.ImportsGen.lookup_from_import_original(
trans._from_imports, nm.id)
alias_orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, nm.id)
if alias_orig is not None:
og_len_ce: sizet = 0
while alias_orig[og_len_ce] != ' ' and alias_orig[og_len_ce] != '\0':
@@ -218,8 +212,7 @@ class ClassGenBase:
return 1
# 别名形式: from t import CUnion as un; class Data(un)
if trans is not None and trans._from_imports is not None:
alias_orig: str = self.Gen.ImportsGen.lookup_from_import_original(
trans._from_imports, nm.id)
alias_orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, nm.id)
if alias_orig is not None:
og_len_cu: sizet = 0
while alias_orig[og_len_cu] != ' ' and alias_orig[og_len_cu] != '\0':
@@ -271,8 +264,7 @@ class ClassGenBase:
return 1
# 别名形式: from t import REnum as ren; class Opt(ren)
if trans is not None and trans._from_imports is not None:
alias_orig: str = self.Gen.ImportsGen.lookup_from_import_original(
trans._from_imports, nm.id)
alias_orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, nm.id)
if alias_orig is not None:
og_len_cr: sizet = 0
while alias_orig[og_len_cr] != ' ' and alias_orig[og_len_cr] != '\0':
@@ -556,14 +548,10 @@ class ClassGenBase:
if pool is None or func_name is None or wrapper_name is None:
return -1
if self.DecoratorFuncNames is None:
self.DecoratorFuncNames = CompilerFactory.factory.PermPool.alloc(
DECOR_FUNC_MAX * DECOR_NAME_LEN)
self.DecoratorWrapNames = CompilerFactory.factory.PermPool.alloc(
DECOR_FUNC_MAX * DECOR_NAME_LEN)
self.DecoratorArgs = CompilerFactory.factory.PermPool.alloc(
DECOR_FUNC_MAX * 8)
if self.DecoratorFuncNames is None or self.DecoratorWrapNames is None \
or self.DecoratorArgs is None:
self.DecoratorFuncNames = CompilerFactory.factory.PermPool.alloc(DECOR_FUNC_MAX * DECOR_NAME_LEN)
self.DecoratorWrapNames = CompilerFactory.factory.PermPool.alloc(DECOR_FUNC_MAX * DECOR_NAME_LEN)
self.DecoratorArgs = CompilerFactory.factory.PermPool.alloc(DECOR_FUNC_MAX * 8)
if self.DecoratorFuncNames is None or self.DecoratorWrapNames is None or self.DecoratorArgs is None:
return -1
string.memset(self.DecoratorFuncNames, 0, DECOR_FUNC_MAX * DECOR_NAME_LEN)
string.memset(self.DecoratorWrapNames, 0, DECOR_FUNC_MAX * DECOR_NAME_LEN)
@@ -986,8 +974,7 @@ class ClassGenBase:
"""
if base_name is None or trans is None or trans._from_imports is None:
return base_name
orig: str = self.Gen.ImportsGen.lookup_from_import_original(
trans._from_imports, base_name)
orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, base_name)
if orig is not None:
# lookup_from_import_original 返回 from_imports 内部指针且未 NUL 结尾
# (如 "CStruct myint:t:CInt CChar:t CPtr:t" 整串直到真正的 NUL)。
@@ -1146,8 +1133,7 @@ class ClassGenBase:
# 用 SHA1 感知查找父类,规避跨模块同名找错
is_nvt: int = 0
if trans is not None:
p_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(
parent_name, trans.ModuleSha1)
p_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(parent_name, trans.ModuleSha1)
if p_entry is None:
# 跨模块父类回退全局查找(父类注册在父模块 SHA1 下,如 linkedlist.LinkedNode),
# 与字段展平(1.5 节)的回退保持一致,否则父类 NoVTable 被误判为有虚表 → 子类插 vptr
@@ -1171,8 +1157,7 @@ class ClassGenBase:
def _detect_vtable_status(self, cd: ast.ClassDef*,
trans: HT.Translator* = None) -> int:
"""检测类是否应该启用虚表"""
if cd is None:
return 0
if cd is None: return 0
# 检查类装饰器
if cd.decorator_list is not None:
@@ -1189,8 +1174,7 @@ class ClassGenBase:
# 用 SHA1 感知查找父类,规避跨模块同名找错
is_nvt: int = 0
if trans is not None:
p_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(
parent_name, trans.ModuleSha1)
p_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(parent_name, trans.ModuleSha1)
if p_entry is None:
# 跨模块父类回退全局查找(同 _detect_vtable_status 的回退)
p_entry = self.Gen.StructGen.find_struct(parent_name)
@@ -1204,10 +1188,8 @@ class ClassGenBase:
# 继承链统一虚表:父类有虚表 → 子类启用;父类无虚表 → 子类静态。
# 若父类无 vtable 而子类有,父类方法按无 vptr 布局(self.field@0)操作
# 子类实例(有 vptr@0)会字段错位 → 运行时错误(父类方法读 vptr 当字段)。
if p_entry is None:
return 1 # 父类信息未知(跨模块/未注册),保守启用虚表
if p_entry.HasVTable == 1:
return 1
if p_entry is None: return 1 # 父类信息未知(跨模块/未注册),保守启用虚表
if p_entry.HasVTable == 1: return 1
return 0
# 默认(无装饰器无继承),检查函数级 @t.CVTable
+29 -63
View File
@@ -16,27 +16,20 @@ from . import ClassGenBase
# ============================================================
# ClassGenDef - ClassGenMixin 拆分(阶段 D):translate_class_def 主入口
#
# 继承 ClassGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesClassDef 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ClassGenDef(ClassGenBase.ClassGenBase):
novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
"""translate_class_def 主入口"""
# ============================================================
# ============================================================
# translate_class_def — 翻译 class 定义(簇 D)
# ============================================================
def translate_class_def(self, trans: HT.Translator*,
node: ast.AST*) -> int:
"""翻译 class 定义,返回 0"""
if node is None or trans is None:
return 0
if node is None or trans is None: return 0
cd: ast.ClassDef* = ast.ClassDef*(node)
if cd is None or cd.name is None:
return 0
if cd is None or cd.name is None: return 0
pool: memhub.MemBuddy* = trans.Pool
class_name: str = cd.name
@@ -85,8 +78,7 @@ class ClassGenDef(ClassGenBase.ClassGenBase):
return self.Gen.ClassGenBase._register_exception_class_def(trans, cd)
# 检查是否已注册(用 SHA1 区分跨模块同名类)
existing: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(
class_name, trans.ModuleSha1)
existing: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(class_name, trans.ModuleSha1)
# 空类注册不完整检测:existing FieldCount==0 但源类体声明了字段(vpi 注入/注册缺陷)。
# 标记 _deps_pending 延迟会让空 entry 持久存在、多遍死锁不收敛 ⇒ 改为中和旧 entry
# (置空 Name + Ty=None,使 find_struct_by_module 不再命中),走下方完整注册路径重建。
@@ -112,8 +104,7 @@ class ClassGenDef(ClassGenBase.ClassGenBase):
# _ensure_field_types_in_module 遍历悬空字段 ParamNode 链表
# 读悬空挂起(G3 LinkedNode.prepend 挂起根因)。DeepCopyType
# 递归深拷贝字段链表/子类型/Name 到 stdlib(深度上限+链守卫)。
ty_deep: llvmlite.LLVMType* = llvmlite.DeepCopyType(
CompilerFactory.factory.PermPool, existing.Ty)
ty_deep: llvmlite.LLVMType* = llvmlite.DeepCopyType(CompilerFactory.factory.PermPool, existing.Ty)
if ty_deep is not None:
existing.Ty = ty_deep
old_name: str = llvmlite.get_struct_name(existing.Ty)
@@ -122,10 +113,7 @@ class ClassGenDef(ClassGenBase.ClassGenBase):
on_copy: str = CompilerFactory.factory.PermPool.alloc(on_len + 1)
if on_copy is not None:
string.strcpy(on_copy, old_name)
c.DerefAs(existing.Ty, llvmlite.LLVMType.Struct(
llvmlite.get_struct_fields(existing.Ty),
llvmlite.get_struct_fcount(existing.Ty),
on_copy))
*existing.Ty = llvmlite.LLVMType.Struct(llvmlite.get_struct_fields(existing.Ty), llvmlite.get_struct_fcount(existing.Ty), on_copy)
# Phase B: 将已存在的命名结构体注册到当前模块(输出类型定义行)
llvmlite.module_add_named_type(trans.Module, pool, existing.Ty)
# B5:existing 路径(Phase B 已注册类)同样需设置 packed/aligned——
@@ -185,8 +173,7 @@ class ClassGenDef(ClassGenBase.ClassGenBase):
# Phase B(declare_only==0)不延迟,避免死锁。
# ============================================================
if trans._declare_only == 1 and parent_name is not None:
parent_check: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(
parent_name, trans.ModuleSha1)
parent_check: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(parent_name, trans.ModuleSha1)
if parent_check is None:
parent_check = self.Gen.StructGen.find_struct(parent_name)
if parent_check is None:
@@ -237,14 +224,11 @@ class ClassGenDef(ClassGenBase.ClassGenBase):
if parents_count > 0 and parents_buf is not None:
for pi in range(parents_count):
pname_addr: sizet = parents_buf[pi]
if pname_addr == 0:
continue
if pname_addr == 0: continue
pname: str = (str | t.CPtr)(pname_addr)
if pname is None:
continue
if pname is None: continue
# 用 SHA1 感知查找父类,规避跨模块同名找错
parent_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(
pname, trans.ModuleSha1)
parent_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(pname, trans.ModuleSha1)
if parent_entry is None:
# 父类可能定义在另一个模块(不同 SHA1,如 HandlesBase.Mixin),
# find_struct_by_module 不回退全局查找,此处手动回退到 find_struct,
@@ -259,19 +243,14 @@ class ClassGenDef(ClassGenBase.ClassGenBase):
return 0
pfc: int = parent_entry.FieldCount
for pfi in range(pfc):
pfe: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(
parent_entry, pfi)
if pfe is None:
continue
pfe: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(parent_entry, pfi)
if pfe is None: continue
pfn: str = self.Gen.StructGen.get_field_name_ptr(pfe)
if pfn is None:
continue
if pfn is None: continue
# 跳过父类的 vtable 指针字段
if string.strcmp(pfn, "__vtable__") == 0:
continue
if string.strcmp(pfn, "__vtable__") == 0: continue
# 多继承去重:字段名已存在跳过(先声明父类优先)
if self.Gen.ClassGenBase._field_name_exists(field_names_buf, field_count, pfn) != 0:
continue
if self.Gen.ClassGenBase._field_name_exists(field_names_buf, field_count, pfn) != 0: continue
if field_count < GenTypes.FIELD_MAX:
pft: llvmlite.LLVMType* = self.Gen.StructGen.get_field_type_ptr(pfe)
pfd: ast.AST* = self.Gen.StructGen.get_field_default_ptr(pfe)
@@ -302,23 +281,19 @@ class ClassGenDef(ClassGenBase.ClassGenBase):
cn: sizet = len(children)
for ci in range(cn):
stmt: ast.AST* = children.get(ci)
if stmt is None:
continue
if stmt is None: continue
sk: int = stmt.kind()
if sk != ast.ASTKind.AnnAssign: continue
# AnnAssign(target=Name(id), annotation=type, value=...)
aa: ast.AnnAssign* = ast.AnnAssign*(stmt)
if aa is None or aa.target is None:
continue
if aa is None or aa.target is None: continue
# 获取字段名
if aa.target.kind() != ast.ASTKind.Name:
continue
if aa.target.kind() != ast.ASTKind.Name: continue
tgt: ast.Name* = ast.Name*(aa.target)
if tgt.id is None:
continue
if tgt.id is None: continue
# 类体 CDefine 常量(任意位置,2026-08-10):注册到全局 CDefine 表。
# 方法内裸名(如 ISINSTANCE_CLASS_MAX)经 translate_name_value 查
@@ -359,16 +334,14 @@ class ClassGenDef(ClassGenBase.ClassGenBase):
continue
# 解析字段类型
field_ty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, aa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
field_ty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, aa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
# 单参 t.CArray[elem] + 列表字面量 → 静态数组 [N x elem]
# (与局部 AnnAssign 路径一致,对齐 TPC ParseListAnnotation 语义):
# 否则字段保持 Ptr(elem)(如 t.CArray[str] → i8**),
# for x in self.field 会误走指针迭代(元素非整数 → null 终止符
# 检查失败报错)。推断为静态数组后走数组迭代(按长度 N)。
if field_ty is not None:
field_ty = self.Gen.AssignGen._infer_static_array_ty_from_literal(
pool, aa.annotation, aa.value, field_ty)
field_ty = self.Gen.AssignGen._infer_static_array_ty_from_literal(pool, aa.annotation, aa.value, field_ty)
if field_ty is None:
# BUG 5 方案1修改点1:消除 i32 静默回退
# Phase A-pre(declare_only=1):依赖的类可能尚未注册,延迟到下一遍
@@ -425,8 +398,7 @@ class ClassGenDef(ClassGenBase.ClassGenBase):
# 提取原始类型注解的类名(联合类型简化为 Ptr(i8) 时回退查找结构体)
# BUG 1 方案3:传 pool 使泛型 Subscript 返回 mangled name(如 "list[ast.AST|t.CPtr]")
if aa.annotation is not None:
annot_cn: str = self.Gen.TypeGenResolve.extract_class_name_from_annotation(
aa.annotation, trans._imported_modules, pool, trans._from_imports)
annot_cn: str = self.Gen.TypeGenResolve.extract_class_name_from_annotation(aa.annotation, trans._imported_modules, pool, trans._from_imports)
if annot_cn is not None:
diag_cn_val: sizet = sizet(annot_cn)
field_annot_buf[field_count] = diag_cn_val
@@ -434,23 +406,20 @@ class ClassGenDef(ClassGenBase.ClassGenBase):
field_annot_buf[field_count] = 0
# t.CVolatile 存储类标记 → 该字段经对象访问的 load/store 带
# volatile(如 Spinlock.locked: t.CVolatile | t.CInt)。
if self.Gen.TypeGenErr.has_decorator_marker(
aa.annotation, "CVolatile", 0) != 0:
if self.Gen.TypeGenErr.has_decorator_marker(aa.annotation, "CVolatile", 0) != 0:
field_volatile_buf[field_count] = 1
else:
field_volatile_buf[field_count] = 0
# rawptr[t.CVolatile | T](volatile 指针指向物,等价 C 的
# volatile T*)→ 经该字段解引用(self.ptr[i]/self.ptr.field)
# 的 load/store 带 volatile。
if self.Gen.TypeGenErr.has_pointee_volatile_marker(
aa.annotation) != 0:
if self.Gen.TypeGenErr.has_pointee_volatile_marker(aa.annotation) != 0:
field_pointee_volatile_buf[field_count] = 1
else:
field_pointee_volatile_buf[field_count] = 0
# const 对象字段(注解含 t.CConst 且字段类型非指针)→ 经对象给该
# 字段赋值 fail-fast。判据与 TPC 的 Gen.field_const_flags 一致。
if self.Gen.TypeGenErr.is_const_object_marker(
aa.annotation, field_ty) != 0:
if self.Gen.TypeGenErr.is_const_object_marker(aa.annotation, field_ty) != 0:
field_const_buf[field_count] = 1
else:
field_const_buf[field_count] = 0
@@ -544,8 +513,7 @@ class ClassGenDef(ClassGenBase.ClassGenBase):
# 后续文件字段类型引用(resolve → Ptr(entry.Ty))→ opaque 扫描遍历悬空 fields
# 崩溃(LoopTest _scan_type_for_cross_module_refs 0xFFFF 根因)。
if trans._declare_only == 0 or self.Gen.StructGen.get_stdlib_alloc() != 0:
st_copy: llvmlite.LLVMType* = llvmlite.DeepCopyType(
CompilerFactory.factory.PermPool, struct_ty)
st_copy: llvmlite.LLVMType* = llvmlite.DeepCopyType(CompilerFactory.factory.PermPool, struct_ty)
if st_copy is not None:
struct_ty = st_copy
type_name = llvmlite.get_struct_name(struct_ty)
@@ -556,8 +524,7 @@ class ClassGenDef(ClassGenBase.ClassGenBase):
# B5:@c.Attribute(t.attr.packed) 打包结构体 → 类型定义输出 <{...}>
# (LLVM packed struct,无字段填充,GEP 按 packed 布局计算偏移)。
# idt/gdt/elf/fat32 等二进制格式结构体依赖它读写硬件/磁盘布局。
is_packed_cd: int = self.Gen.ClassGenBase._class_has_tattr(
cd.decorator_list, "packed")
is_packed_cd: int = self.Gen.ClassGenBase._class_has_tattr(cd.decorator_list, "packed")
if is_packed_cd != 0:
llvmlite.module_set_named_type_packed(trans.Module, pool, struct_ty, 1)
@@ -573,8 +540,7 @@ class ClassGenDef(ClassGenBase.ClassGenBase):
# ============================================================
# 3. 注册到 HandlesStruct
# ============================================================
entry: GenTypes.StructEntry* = self.Gen.StructGen.register_struct(
pool, class_name, struct_ty, trans.ModuleSha1)
entry: GenTypes.StructEntry* = self.Gen.StructGen.register_struct(pool, class_name, struct_ty, trans.ModuleSha1)
if entry is None:
VLogger.error(f"failed to register {class_name}", "CLASS")
return 0
+61 -138
View File
@@ -18,20 +18,15 @@ from . import ClassGenBase
# 未定义名在常量上下文被 TPV 折叠为 0,会导致枚举成员收集被静默跳过、
# register_enum 永不调用 → 所有 CEnum 注册失败 → 裸名枚举访问 NameError)
# ============================================================
ENUM_MEMBER_MAX_LOCAL: t.CDefine = 128 # 与 StmtGenDeclMixin.ENUM_MEMBER_MAX 一致
RENUM_CLASS_MAX: t.CDefine = 64
RENUM_VARIANT_PER_CLASS: t.CDefine = 32
RENUM_ALIAS_MAX: t.CDefine = 512
define ENUM_MEMBER_MAX_LOCAL = 128
define RENUM_ENUM_CLASS_MAX = 64
define RENUM_ENUM_VARIANT_PER_CLASS = 32
define RENUM_ENUM_ALIAS_MAX = 512
# ============================================================
# ClassGenEnum - ClassGenMixin 拆分(阶段 D):enum/union/renum 定义与变体表
#
# 继承 ClassGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesClassDef 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ClassGenEnum(ClassGenBase.ClassGenBase):
novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
"""enum/union/renum 定义与变体表"""
def _resolve_enum_member_type(self, pool: memhub.MemBuddy*,
@@ -49,8 +44,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
at: ast.Attribute* = ast.Attribute*(ann_node)
if at.attr is None:
# [S4 fail-fast] Attribute 缺失成员名(AST 损坏),不再静默回退 i32
self.Gen.TypeGenErr.fatal_error(
ann_node, "枚举成员类型注解 Attribute 缺失成员名", "TypeError")
self.Gen.TypeGenErr.fatal_error(ann_node, "枚举成员类型注解 Attribute 缺失成员名", "TypeError")
return llvmlite.Int32(pool) # 不可达(fatal_error 已退出)
# t.State → 默认 i32
if string.strcmp(at.attr, "State") == 0:
@@ -62,13 +56,10 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
if string.strcmp(at.attr, "CBool") == 0:
return llvmlite.Int8(pool)
# 其他 t.CXxx 类型:统一口径(CTypedef 动态表优先,miss 回退 map_t_type)
ty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_typedef_or_map(
pool, at.attr, imported_modules, from_imports)
if ty is not None:
return ty
ty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_typedef_or_map(pool, at.attr, imported_modules, from_imports)
if ty is not None: return ty
# [S4 fail-fast] 有注解但解析失败 → 不再静默回退 i32
self.Gen.TypeGenErr.fatal_error(
ann_node, f"枚举成员类型注解解析失败: t.{at.attr}", "NameError")
self.Gen.TypeGenErr.fatal_error(ann_node, f"枚举成员类型注解解析失败: t.{at.attr}", "NameError")
return llvmlite.Int32(pool) # 不可达(fatal_error 已退出)
# Name 节点: from-import 形式(State / CInt)
@@ -76,8 +67,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
nm: ast.Name* = ast.Name*(ann_node)
if nm.id is None:
# [S4 fail-fast] Name 缺失标识符(AST 损坏),不再静默回退 i32
self.Gen.TypeGenErr.fatal_error(
ann_node, "枚举成员类型注解 Name 缺失标识符", "TypeError")
self.Gen.TypeGenErr.fatal_error(ann_node, "枚举成员类型注解 Name 缺失标识符", "TypeError")
return llvmlite.Int32(pool) # 不可达(fatal_error 已退出)
if string.strcmp(nm.id, "State") == 0:
return llvmlite.Int32(pool)
@@ -97,27 +87,23 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
# map_t_type 的 CBool,用于普通变量/形参/字段)。
# 两侧一致:TPC 侧枚举成员 bool 经 t.CBool.Size 亦为 8。
return llvmlite.Int8(pool)
ty2: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_typedef_or_map(
pool, nm.id, imported_modules, from_imports)
ty2: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_typedef_or_map(pool, nm.id, imported_modules, from_imports)
if ty2 is not None:
return ty2
# [S4 fail-fast] 有注解但解析失败 → 不再静默回退 i32
self.Gen.TypeGenErr.fatal_error(
ann_node, f"枚举成员类型注解解析失败: {nm.id}", "NameError")
self.Gen.TypeGenErr.fatal_error(ann_node, f"枚举成员类型注解解析失败: {nm.id}", "NameError")
return llvmlite.Int32(pool) # 不可达(fatal_error 已退出)
# BinOp 节点: t.State | int8(递归查找实际类型)
if k == ast.ASTKind.BinOp:
bop: ast.BinOp* = ast.BinOp*(ann_node)
if bop.op == ast.OpKind.BitOr:
left_ty: llvmlite.LLVMType* = self._resolve_enum_member_type(
pool, bop.left, imported_modules, from_imports)
left_ty: llvmlite.LLVMType* = self._resolve_enum_member_type(pool, bop.left, imported_modules, from_imports)
# 跳过 t.State(i32 默认),优先返回具体类型
left_bits: int = self.Gen.TypeGenErr.get_llvm_type_bits(left_ty)
if left_bits != 0 and not self._is_state_annotation(bop.left):
return left_ty
right_ty: llvmlite.LLVMType* = self._resolve_enum_member_type(
pool, bop.right, imported_modules, from_imports)
right_ty: llvmlite.LLVMType* = self._resolve_enum_member_type(pool, bop.right, imported_modules, from_imports)
if right_ty is not None and not self._is_state_annotation(bop.right):
return right_ty
# 两边都是 State 或无法确定,返回较宽的
@@ -126,13 +112,11 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
return left_ty
return right_ty
# fail-fast:BinOp 但非 BitOr(未知联合运算),不再静默回退 i32
self.Gen.TypeGenErr.fatal_error(
ann_node, f"枚举成员类型注解解析失败: {self.Gen.TypeGenResolve.annotation_to_str(ann_node)}", "TypeError")
self.Gen.TypeGenErr.fatal_error(ann_node, f"枚举成员类型注解解析失败: {self.Gen.TypeGenResolve.annotation_to_str(ann_node)}", "TypeError")
return llvmlite.Int32(pool) # 不可达(fatal_error 已退出)
# fail-fast:未知注解节点 kind,不再静默回退 i32
self.Gen.TypeGenErr.fatal_error(
ann_node, f"枚举成员类型注解解析失败: {self.Gen.TypeGenResolve.annotation_to_str(ann_node)}", "TypeError")
self.Gen.TypeGenErr.fatal_error(ann_node, f"枚举成员类型注解解析失败: {self.Gen.TypeGenResolve.annotation_to_str(ann_node)}", "TypeError")
return llvmlite.Int32(pool) # 不可达(fatal_error 已退出)
def _is_state_annotation(self, node: ast.AST*) -> int:
"""检查注解节点是否为 t.State,返回 1=是 / 0=否"""
@@ -385,25 +369,18 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
# 具体整数类型、rawptr[...] 又是 Subscript(非 Name/Attribute/BinOp)
# 会在解析里报笼统的"注解解析失败",两者都盖不住"指针成员"这个真因。
if self._enum_member_annotation_is_ptr(aa.annotation) == 1:
self.Gen.TypeGenErr.fatal_error(
aa,
f"枚举成员 '{tgt.id}' 不能是指针类型(枚举值只支持整数成员类型)",
"TypeError")
self.Gen.TypeGenErr.fatal_error(aa, f"枚举成员 '{tgt.id}' 不能是指针类型(枚举值只支持整数成员类型)", "TypeError")
return 0 # 不可达(fatal_error 已退出)
# 解析成员类型
member_ty: llvmlite.LLVMType* = self._resolve_enum_member_type(
pool, aa.annotation, trans._imported_modules, trans._from_imports)
member_ty: llvmlite.LLVMType* = self._resolve_enum_member_type(pool, aa.annotation, trans._imported_modules, trans._from_imports)
# [枚举规格 fail-fast] 成员类型必须是整数类型:浮点/void/结构体/
# 数组的位宽均为 0,无法参与"枚举宽度 = 最宽成员类型"的推导,
# 静默接受会让寄存器宽度与访问侧常量类型不一致。禁止静默降级。
member_bits: int = self.Gen.TypeGenErr.get_llvm_type_bits(member_ty)
if member_bits <= 0:
self.Gen.TypeGenErr.fatal_error(
aa,
f"枚举成员 '{tgt.id}' 的类型必须为整数类型(不允许指针/浮点/void/结构体/数组),无法推导枚举宽度",
"TypeError")
self.Gen.TypeGenErr.fatal_error(aa, f"枚举成员 '{tgt.id}' 的类型必须为整数类型(不允许指针/浮点/void/结构体/数组),无法推导枚举宽度", "TypeError")
return 0 # 不可达(fatal_error 已退出)
# 解析成员值
@@ -510,8 +487,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
base_ty = mty
# 注册枚举
entry: rawptr[GenTypes.EnumEntry] = self.Gen.StmtGenDecl.register_enum(
pool, class_name, base_ty)
entry: rawptr[GenTypes.EnumEntry] = self.Gen.StmtGenDecl.register_enum(pool, class_name, base_ty)
if entry is None:
VLogger.error("failed to register {class_name}", "ENUM")
return 0
@@ -627,8 +603,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
def _translate_union_def(self, trans: HT.Translator*,
cd: ast.ClassDef*) -> int:
"""翻译联合体定义,返回 0"""
if cd is None or cd.name is None or trans is None:
return 0
if cd is None or cd.name is None or trans is None: return 0
pool: memhub.MemBuddy* = trans.Pool
class_name: str = cd.name
@@ -637,8 +612,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
self.Gen.StructGen.add_visible_struct(pool, class_name)
# 检查是否已注册(用 SHA1 区分跨模块同名类)
existing: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(
class_name, trans.ModuleSha1)
existing: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(class_name, trans.ModuleSha1)
if existing is not None:
# Phase B: 将已存在的命名结构体注册到当前模块
if existing.Ty is not None:
@@ -666,36 +640,27 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
for ci in range(cn):
stmt: ast.AST* = children.get(ci)
if stmt is None:
continue
if stmt is None: continue
sk: int = stmt.kind()
if sk == ast.ASTKind.AnnAssign:
aa: ast.AnnAssign* = ast.AnnAssign*(stmt)
if aa is None or aa.target is None:
continue
if aa is None or aa.target is None: continue
# 获取字段名
if aa.target.kind() != ast.ASTKind.Name:
continue
if aa.target.kind() != ast.ASTKind.Name: continue
tgt: ast.Name* = ast.Name*(aa.target)
if tgt.id is None:
continue
if tgt.id is None: continue
# 解析字段类型
field_ty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, aa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
field_ty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, aa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
if field_ty is None:
# Phase A-pre(declare_only=1):依赖的类可能尚未注册,
# 静默 return 1 让多遍收敛机制生效(renum 返回 1=跳过该类)
if trans._declare_only == 1:
return 1
if trans._declare_only == 1: return 1
# Phase B(declare_only=0):真正的类型解析错误,fast-fail 终止
type_name: str = self.Gen.TypeGenResolve.annotation_to_str(aa.annotation)
self.Gen.TypeGenErr.fatal_error(
aa,
f"'{type_name}' is not defined",
"NameError")
self.Gen.TypeGenErr.fatal_error(aa, f"'{type_name}' is not defined", "NameError")
field_ty = llvmlite.Int32(pool)
# 计算字段大小,更新 max_size
@@ -747,8 +712,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
# entry.Ty 悬空 → 后续文件 opaque 扫描跨模块引用遍历悬空 fields 崩溃
# (LoopTest _scan_type_for_cross_module_refs 0xFFFF 根因)。
if trans._declare_only == 0 or self.Gen.StructGen.get_stdlib_alloc() != 0:
union_copy: llvmlite.LLVMType* = llvmlite.DeepCopyType(
CompilerFactory.factory.PermPool, union_ty)
union_copy: llvmlite.LLVMType* = llvmlite.DeepCopyType(CompilerFactory.factory.PermPool, union_ty)
if union_copy is not None:
union_ty = union_copy
@@ -756,8 +720,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
llvmlite.module_add_named_type(trans.Module, pool, union_ty)
# 注册到 HandlesStruct(传递 SHA1 在注册时直接设置,避免跨模块同名找错 entry)
entry: GenTypes.StructEntry* = self.Gen.StructGen.register_struct(
pool, class_name, union_ty, trans.ModuleSha1)
entry: GenTypes.StructEntry* = self.Gen.StructGen.register_struct(pool, class_name, union_ty, trans.ModuleSha1)
if entry is None:
VLogger.error(f"failed to register {class_name}", "UNION")
return 0
@@ -810,35 +773,20 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
if dyn_sz > 0:
return dyn_sz
# 内置类型
if string.strcmp(type_name, "int") == 0:
return 4
if string.strcmp(type_name, "CInt") == 0:
return 4
if string.strcmp(type_name, "CInt8T") == 0:
return 1
if string.strcmp(type_name, "CInt16T") == 0:
return 2
if string.strcmp(type_name, "CInt32T") == 0:
return 4
if string.strcmp(type_name, "CInt64T") == 0:
return 8
if string.strcmp(type_name, "CChar") == 0:
return 1
if string.strcmp(type_name, "CDouble") == 0:
return 8
if string.strcmp(type_name, "CFloat") == 0:
return 4
if string.strcmp(type_name, "CPtr") == 0:
return 8
if string.strcmp(type_name, "CSizeT") == 0:
return 8
if string.strcmp(type_name, "str") == 0:
return 8
if string.strcmp(type_name, "bytes") == 0:
return 8
if string.strcmp(type_name, "bool") == 0:
# bool = t.CBool = i8(1 字节)
return 1
if string.strcmp(type_name, "int") == 0: return 4
if string.strcmp(type_name, "CInt") == 0: return 4
if string.strcmp(type_name, "CInt8T") == 0: return 1
if string.strcmp(type_name, "CInt16T") == 0: return 2
if string.strcmp(type_name, "CInt32T") == 0: return 4
if string.strcmp(type_name, "CInt64T") == 0: return 8
if string.strcmp(type_name, "CChar") == 0: return 1
if string.strcmp(type_name, "CDouble") == 0: return 8
if string.strcmp(type_name, "CFloat") == 0: return 4
if string.strcmp(type_name, "CPtr") == 0: return 8
if string.strcmp(type_name, "CSizeT") == 0: return 8
if string.strcmp(type_name, "str") == 0: return 8
if string.strcmp(type_name, "bytes") == 0: return 8
if string.strcmp(type_name, "bool") == 0: return 1
# 已注册的结构体类型
struct_ty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(type_name)
if struct_ty is not None:
@@ -850,8 +798,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
def _translate_renum_def(self, trans: HT.Translator*,
cd: ast.ClassDef*) -> int:
"""翻译 REnum 类定义,返回 0"""
if cd is None or cd.name is None or trans is None:
return 0
if cd is None or cd.name is None or trans is None: return 0
pool: memhub.MemBuddy* = trans.Pool
class_name: str = cd.name
@@ -860,8 +807,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
self.Gen.StructGen.add_visible_struct(pool, class_name)
# 检查是否已注册(用 SHA1 区分跨模块同名类)
existing: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(
class_name, trans.ModuleSha1)
existing: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(class_name, trans.ModuleSha1)
if existing is not None:
# existing 只保证 struct entry 在,不保证 REnum 语义(变体表)在:struct entry
# 由 register_struct 写 StructTable,跨 Phase 存活(perm_pool);而变体表是 gen
@@ -885,9 +831,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
# [D32 fail-fast] 此前只 warning + return 0:变体表**静默不注册** →
# _is_renum_class_name 恒 0、变体构造拿不到 tag(__types.vp L703
# `LLVMType.Metadata()` 被当外部函数根因)。禁止静默跳过。
self.Gen.TypeGenErr.fatal_error(
cd, f"REnum 类 '{class_name}' 缺少类体(children 为 None),无法注册变体表",
"TypeError")
self.Gen.TypeGenErr.fatal_error(cd, f"REnum 类 '{class_name}' 缺少类体(children 为 None),无法注册变体表", "TypeError")
return 0
cn: sizet = len(children)
@@ -946,13 +890,8 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
if vnm is not None and vnm.id is not None:
mem_ty_l: llvmlite.LLVMType* = None
if trans is not None:
mem_ty_l = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, vaa.annotation,
trans._imported_modules,
trans._from_imports, trans, 0)
self._register_renum_field_alias(
pool, class_name, vnm.id, field_idx + 1,
mem_ty_l, variant_cd.name)
mem_ty_l = self.Gen.TypeGenResolve.resolve_annotation_type(pool, vaa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
self._register_renum_field_alias(pool, class_name, vnm.id, field_idx + 1, mem_ty_l, variant_cd.name)
field_idx += 1
if field_idx > max_field_count:
max_field_count = field_idx
@@ -980,9 +919,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
if variant_count == 0:
# [D32 fail-fast] 同上:变体数为 0 时此前静默 return → 变体表不注册。
# 对 `class X(t.REnum)` 而言变体数必 > 0,为 0 说明 AST 变体类丢失。
self.Gen.TypeGenErr.fatal_error(
cd, f"REnum 类 '{class_name}' 的变体数为 0(嵌套变体类丢失),无法注册变体表",
"TypeError")
self.Gen.TypeGenErr.fatal_error(cd, f"REnum 类 '{class_name}' 的变体数为 0(嵌套变体类丢失),无法注册变体表", "TypeError")
return 0
# 计算每个位置的最大字段大小
@@ -1046,8 +983,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
viperlib.snprintf(renum_name_buf, 64, "%s.%s", trans.ModuleSha1, class_name)
renum_type_name = renum_name_buf
renum_ty: llvmlite.LLVMType* = llvmlite.Struct(
pool, first_node, total_positions, renum_type_name)
renum_ty: llvmlite.LLVMType* = llvmlite.Struct(pool, first_node, total_positions, renum_type_name)
if renum_ty is None:
VLogger.error(f"failed to create type for {class_name}", "RENUM")
return 0
@@ -1056,8 +992,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
# 与 entry.Ty 保持同一指针,find_struct_by_type 匹配不失效)
# StdlibAlloc=1(Phase2 mark2 后)也必须深拷贝:同 union 的悬空根因。
if trans._declare_only == 0 or self.Gen.StructGen.get_stdlib_alloc() != 0:
renum_copy: llvmlite.LLVMType* = llvmlite.DeepCopyType(
CompilerFactory.factory.PermPool, renum_ty)
renum_copy: llvmlite.LLVMType* = llvmlite.DeepCopyType(CompilerFactory.factory.PermPool, renum_ty)
if renum_copy is not None:
renum_ty = renum_copy
@@ -1065,8 +1000,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
llvmlite.module_add_named_type(trans.Module, pool, renum_ty)
# 注册到 HandlesStruct
entry: GenTypes.StructEntry* = self.Gen.StructGen.register_struct(
pool, class_name, renum_ty, trans.ModuleSha1)
entry: GenTypes.StructEntry* = self.Gen.StructGen.register_struct(pool, class_name, renum_ty, trans.ModuleSha1)
if entry is None:
VLogger.error(f"failed to register {class_name}", "RENUM")
return 0
@@ -1152,29 +1086,20 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
# 与第一遍同规则:有效 AnnAssign 仍占用 payload 槽位
field_idx += 1
continue
mem_ty_l: llvmlite.LLVMType* = \
self.Gen.TypeGenResolve.resolve_annotation_type(
pool, vaa.annotation,
trans._imported_modules,
trans._from_imports, trans, 0)
mem_ty_l: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, vaa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
# 解析成功 → 触发别名表去重路径(类型槽为 0 时回填;非 0 跳过)
if mem_ty_l is not None:
self._register_renum_field_alias(
pool, class_name, vnm.id, field_idx + 1,
mem_ty_l, variant_cd.name)
self._register_renum_field_alias(pool, class_name, vnm.id, field_idx + 1, mem_ty_l, variant_cd.name)
field_idx += 1
def _register_renum_variants(self, pool: memhub.MemBuddy*,
class_name: str,
cd: ast.ClassDef*,
variant_count: int):
"""注册 REnum 类的变体名和 tag 值到全局变体表"""
if pool is None or class_name is None or cd is None:
return
if variant_count == 0:
return
if pool is None or class_name is None or cd is None: return
if variant_count == 0: return
children: list[ast.AST*]* = cd.children
if children is None:
return
if children is None: return
# 懒初始化表(首次注册时分配)
# 注意: 必须用 stdlib 分配——这些表在 1b 阶段(mark1 之后)首次分配,
@@ -1464,8 +1389,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
# _refill_renum_field_types)类型槽为 0 时,本次解析成功则
# 回填真实类型;非 0 槽保持原样(避免重复 DeepCopy 覆盖抖动)。
if self.RenumAliasTy[i] == 0 and field_ty is not None:
ty_copy_rf2: llvmlite.LLVMType* = llvmlite.DeepCopyType(
CompilerFactory.factory.PermPool, field_ty)
ty_copy_rf2: llvmlite.LLVMType* = llvmlite.DeepCopyType(CompilerFactory.factory.PermPool, field_ty)
if ty_copy_rf2 is not None:
self.RenumAliasTy[i] = sizet(ty_copy_rf2)
return
@@ -1492,8 +1416,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase):
# 未解析成功(自引用等)存 0,绑定回退槽位类型)
self.RenumAliasTy[idx] = 0
if field_ty is not None:
ty_copy_rfa: llvmlite.LLVMType* = llvmlite.DeepCopyType(
CompilerFactory.factory.PermPool, field_ty)
ty_copy_rfa: llvmlite.LLVMType* = llvmlite.DeepCopyType(CompilerFactory.factory.PermPool, field_ty)
if ty_copy_rfa is not None:
self.RenumAliasTy[idx] = sizet(ty_copy_rfa)
# 变体名同样 strcpy 到 perm_pool(1a reset 后 variant_cd.name 悬空)
+19 -40
View File
@@ -15,22 +15,16 @@ import lib.Stub.StubMerger.StubMergerStore as StubMergerStore
# 泛型特化递归深度上限(泛型循环套用防护)
# 正常嵌套特化深度 ≤ 3(如 list[list[str]]);64 远超合理值,命中即循环。
# (原 HandlesClassDef/ClassGenMixin 顶层常量,阶段 D 拆分时遗漏,补回)
GENERIC_SPEC_MAX_DEPTH: t.CDefine = 64
define GENERIC_SPEC_MAX_DEPTH = 64
# 泛型模板表容量上限(与 GenericClassNames 等 pool 表可容纳的模板数对齐;
# 原 ClassGenMixin 顶层常量,阶段 D 拆分时遗漏,补回)
GENERIC_TEMPLATE_MAX: t.CDefine = 512
# 泛型特化缓存表容量(原 HandlesClassDef.SPEC_CACHE_MAX,阶段 D 拆分遗漏)
SPEC_CACHE_MAX: t.CDefine = 512
define GENERIC_TEMPLATE_MAX = 512
# 泛型特化缓存表容量
define SPEC_CACHE_MAX = 512
# ============================================================
# ClassGenGeneric - 泛型模板注册/特化/克隆
#
# 继承链仅 1 级(TPV self 调用仅支持 1 级父类);跨 Mixin 调用统一走 HandlesClassDef 委托。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ClassGenGeneric(ClassGenBase.ClassGenBase):
novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase):
"""泛型模板注册/特化/克隆"""
# ============================================================
@@ -49,20 +43,16 @@ class ClassGenGeneric(ClassGenBase.ClassGenBase):
接收 type_params 而非 cd,避免 cd.type_params 属性访问
因跨模块类型推断失败返回 None。
"""
if tp is None:
return 0
if tp is None: return 0
return 1
def _dup_perm_str(self, s: str) -> str:
"""深拷贝字符串到永久池(无永久池/分配失败时原样返回入参)"""
if s is None:
return None
if s is None: return None
perm: memhub.MemBuddy* = CompilerFactory.factory.PermPool
if perm is None:
return s
if perm is None: return s
n: sizet = string.strlen(s)
b: str = perm.alloc(n + 1)
if b is None:
return s
if b is None: return s
string.strcpy(b, s)
return b
def _register_generic_template(self, pool: memhub.MemBuddy*,
@@ -92,8 +82,7 @@ class ClassGenGeneric(ClassGenBase.ClassGenBase):
(同样的类名/节点/ SHA1/文件路径,同样的插入顺序与查重),发射的 IR 与
符号名不受池选择影响 ⇒ 逐字不变。
"""
if cd is None or cd.name is None:
return
if cd is None or cd.name is None: return
perm: memhub.MemBuddy* = CompilerFactory.factory.PermPool
table_pool: memhub.MemBuddy* = perm
if table_pool is None:
@@ -104,11 +93,9 @@ class ClassGenGeneric(ClassGenBase.ClassGenBase):
self.GenericClassSha1s = list[str](table_pool, 8)
self.GenericClassFiles = list[str](table_pool, 8)
if self.GenericClassTpParams is None:
if perm is None:
return
if perm is None: return
self.GenericClassTpParams = perm.alloc(GENERIC_TEMPLATE_MAX * 8)
if self.GenericClassTpParams is None:
return
if self.GenericClassTpParams is None: return
string.memset(self.GenericClassTpParams, 0, GENERIC_TEMPLATE_MAX * 8)
# 用局部变量接收 list,触发类型推断(避免字段 __len__ 失败)
names_local: list[str]* = self.GenericClassNames
@@ -116,16 +103,14 @@ class ClassGenGeneric(ClassGenBase.ClassGenBase):
i: sizet
for i in range(cn):
nm: str = names_local.get(i)
if nm is not None and string.strcmp(nm, cd.name) == 0:
return
if nm is not None and string.strcmp(nm, cd.name) == 0: return
# type_params stdlib 深拷贝:模板节点的 type_params 是 pool 分配的
tp_names_buf: str = self._copy_type_params_stdlib(cd.type_params)
self.GenericClassNames.append(self._dup_perm_str(cd.name))
self.GenericClassNodes.append(cd)
self.GenericClassSha1s.append(self._dup_perm_str(module_sha1))
# 同时保存模板来源文件路径(错误定位用,见字段注释)
self.GenericClassFiles.append(
self._dup_perm_str(self.Gen.TypeGenResolve.get_current_file()))
self.GenericClassFiles.append(self._dup_perm_str(self.Gen.TypeGenResolve.get_current_file()))
if tp_names_buf is not None and cn < GENERIC_TEMPLATE_MAX:
self.GenericClassTpParams[cn] = sizet(tp_names_buf)
def _copy_type_params_stdlib(self, tp: list[str]*) -> str:
@@ -602,12 +587,10 @@ class ClassGenGeneric(ClassGenBase.ClassGenBase):
# 方法体永不发射 → 特化方法只有 call 无 define → 链接 undefined symbol。
pre_existing.MethodsEmitted = 1
# 从 stdlib 深拷贝表取 type_params(模板节点 pool list 跨 Phase 可能失效)
tp_names_pre: list[str]* = self._find_generic_template_tp_params(
pool, class_name)
tp_names_pre: list[str]* = self._find_generic_template_tp_params(pool, class_name)
if tp_names_pre is None:
tp_names_pre = template_cd.type_params
spec_cd_pre: ast.ClassDef* = self._clone_classdef_for_spec(
pool, template_cd, spec_name, tp_names_pre, type_args)
spec_cd_pre: ast.ClassDef* = self._clone_classdef_for_spec(pool, template_cd, spec_name, tp_names_pre, type_args)
if spec_cd_pre is not None:
trans.GenericTypeParamNames = tp_names_pre
trans.GenericTypeArgs = type_args
@@ -681,12 +664,10 @@ class ClassGenGeneric(ClassGenBase.ClassGenBase):
# 5. 拷贝 ClassDef 节点
# 从 stdlib 深拷贝表取 type_params(模板节点 pool list 跨 Phase 可能失效)
tp_names: list[str]* = self._find_generic_template_tp_params(
pool, class_name)
tp_names: list[str]* = self._find_generic_template_tp_params(pool, class_name)
if tp_names is None:
tp_names = template_cd.type_params
spec_cd: ast.ClassDef* = self._clone_classdef_for_spec(
pool, template_cd, spec_name, tp_names, type_args)
spec_cd: ast.ClassDef* = self._clone_classdef_for_spec(pool, template_cd, spec_name, tp_names, type_args)
if spec_cd is None:
self.GenericSpecDepth -= 1
return None
@@ -734,10 +715,8 @@ class ClassGenGeneric(ClassGenBase.ClassGenBase):
if string.strcmp(class_name, "GSListNode") == 0:
result_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(spec_name)
if result_entry is not None:
ri: int
for ri in range(result_entry.FieldCount):
rfe: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(
result_entry, ri)
rfe: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(result_entry, ri)
if rfe is not None:
rfn: str = self.Gen.StructGen.get_field_name_ptr(rfe)
if rfn is None:
+1 -5
View File
@@ -4,10 +4,6 @@ from . import ClassGenBase
# ============================================================
# ClassGenMixin - 类定义/继承/泛型/vtable/enum/union/renum
#
# 方法已全部拆至 ClassGenBase/Enum/Generic/VTable/Def,本文件保留类声明。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ClassGenMixin(ClassGenBase.ClassGenBase):
novirtual class ClassGenMixin(ClassGenBase.ClassGenBase):
"""类定义处理 Mixin(阶段 D 拆分后顶层,方法全部在子 Mixin)"""
+53 -111
View File
@@ -17,21 +17,15 @@ import lib.core.Gen.GenApi as GenApi
# 方法元数据 flag:TLS(@t.TLS 装饰器,对齐 ClassGenBase 本地常量;本地副本避免跨模块 CDefine 查找)
META_TLS: t.CDefine = 32
# 虚表方法数上限(原 HandlesClassDef.VTBL_METHOD_MAX,阶段 D 拆分遗漏)
VTBL_METHOD_MAX: t.CDefine = 32
SCOPE_FUNCTION: t.CDefine = 1
define META_TLS = 32
# 虚表方法数上限
define VTBL_METHOD_MAX = 32
define SCOPE_FUNCTION = 1
# ============================================================
# ClassGenVTable - ClassGenMixin 拆分(阶段 D):vtable 收集/生成/方法翻译
#
# 继承 ClassGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesClassDef 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ClassGenVTable(ClassGenBase.ClassGenBase):
novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
"""vtable 收集/生成/方法翻译"""
# ============================================================
@@ -45,8 +39,7 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
dlen: sizet = string.strlen(dst)
slen: sizet = string.strlen(src)
remain: sizet = dst_size - dlen
if remain <= 0:
return
if remain <= 0: return
i: sizet = 0
while i < slen and i + 1 < remain:
dst[dlen + i] = src[i]
@@ -114,8 +107,7 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
# 如果子类覆盖了方法,full_name 用子类的;否则用父类的。
# 用 SHA1 感知查找,规避跨模块同名 find_struct 找错
# ============================================================
vt_self_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(
class_name, trans.ModuleSha1)
vt_self_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(class_name, trans.ModuleSha1)
# 多继承:遍历所有父类(声明顺序),vtable 方法合并(短名去重,先声明父类优先)
parent_count: int = self.Gen.StructGen.get_parent_count(class_name)
if parent_count > 0:
@@ -124,8 +116,7 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
if pname is None:
continue
# 查找父类 entry(优先同模块 SHA1 匹配)
vt_parent_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(
pname, trans.ModuleSha1)
vt_parent_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(pname, trans.ModuleSha1)
if vt_parent_entry is None:
# 跨模块继承: 父类在不同模块定义(SHA1 不同),回退到按类名查找
vt_parent_entry = self.Gen.StructGen.find_struct(pname)
@@ -204,8 +195,7 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
method_parent_sha1s[method_count] = 0
else:
# 继承未覆盖: 用实际定义类的模块 SHA1(跨模块继承时 mangling 正确)
def_entry2: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(
def_class)
def_entry2: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(def_class)
if def_entry2 is not None and def_entry2.ModuleSha1 is not None:
method_parent_sha1s[method_count] = sizet(def_entry2.ModuleSha1)
else:
@@ -308,8 +298,7 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
method_parent_sha1s: sizet* = self.VtParentSha1s
method_count: int = self.VtMethodCount
# 重新获取 entry(后续存储 VTableMethods 用)
vt_self_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(
class_name, trans.ModuleSha1)
vt_self_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(class_name, trans.ModuleSha1)
# 2. 构造 VTable 类型: { i8*, i8*, ..., i8* }
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
@@ -370,8 +359,7 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
continue
func_ty_buf[0] = '\0'
if ge is None or ge.Spec is None or TSpec.SpecToLLVMText(ge.Spec, func_ty_buf, 1024) != 0:
self.Gen.TypeGenErr.fatal_error(
cd, f"vtable 方法 '{full_name}' 找不到函数类型", "InternalCompilerError")
self.Gen.TypeGenErr.fatal_error(cd, f"vtable 方法 '{full_name}' 找不到函数类型", "InternalCompilerError")
continue
# 构造 bitcast 字符串: i8* bitcast (func_ty* @mangled to i8*)
@@ -397,8 +385,7 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
vtable_mangled: str = self.Gen.FuncGenBase._mangle_name(trans, vtable_name_buf)
# 5. 创建全局变量
gv: llvmlite.GlobalVariable* = llvmlite.new_global_variable(
pool, vtable_mangled, vtable_ty)
gv: llvmlite.GlobalVariable* = llvmlite.new_global_variable(pool, vtable_mangled, vtable_ty)
if gv is None:
return 0
gv.Initializer = init_buf
@@ -636,8 +623,7 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
# 推断返回类型
ret_ty: llvmlite.LLVMType* = None
if fd.returns is not None:
ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, fd.returns, imported_modules, from_imports, trans, 0)
ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, fd.returns, imported_modules, from_imports, trans, 0)
if ret_ty is None and fd.returns is not None:
# 存储类标记(t.State / t.CExport / t.CExtern)语义为 Void:这类注解
# 不携带真实返回类型(extern/export 语法写成 "<原类型> | t.<标记>",
@@ -649,8 +635,7 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
else:
# [S4 fail-fast] 有返回注解但解析失败 → 不再退回 infer_return_type()
# (推断可能给出与真实注解不符的类型,静默错到运行期才暴露)
self.Gen.TypeGenErr.fatal_error(
fd, f"方法 '{class_name}.{method_name}' 返回类型注解解析失败", "NameError")
self.Gen.TypeGenErr.fatal_error(fd, f"方法 '{class_name}.{method_name}' 返回类型注解解析失败", "NameError")
return 0
if ret_ty is None:
# __init__ 和 __before_init__ 返回 void
@@ -661,12 +646,10 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
ret_ty = llvmlite.Ptr(pool, struct_ty)
else:
param_types_str: str = self.Gen.TypeGenErr.build_param_types_str(pool, fd.args)
ret_ty = self.Gen.TypeGenErr.infer_return_type(
pool, fd.children, param_types_str)
ret_ty = self.Gen.TypeGenErr.infer_return_type(pool, fd.children, param_types_str)
# 创建 LLVM 函数
func: llvmlite.Function* = llvmlite.create_function(
pool, mod, mangled_name, ret_ty)
func: llvmlite.Function* = llvmlite.create_function(pool, mod, mangled_name, ret_ty)
if func is None:
return 0
@@ -728,14 +711,11 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
if arg is not None and arg.arg is not None:
param_ty: llvmlite.LLVMType* = i32_ty
if arg.annotation is not None:
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, arg.annotation, imported_modules, from_imports, trans, 0)
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, imported_modules, from_imports, trans, 0)
if resolved is None:
# [S4 fail-fast] 有注解但解析失败:不再静默用 i32
# (方法签名与调用点/实现体三方不一致)
self.Gen.TypeGenErr.fatal_error(
arg, f"方法 '{class_name}.{method_name}' 形参 '{arg.arg}' 类型注解解析失败",
"NameError")
self.Gen.TypeGenErr.fatal_error(arg, f"方法 '{class_name}.{method_name}' 形参 '{arg.arg}' 类型注解解析失败", "NameError")
return 0
# 裸类形参 → Ptr(struct):按"对象即指针"引用传参。
# 若按 struct 值传参,self.Head = node 会取局部拷贝地址
@@ -783,8 +763,7 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
tls_m_flag_name: str = pool.alloc(128)
if tls_m_flag_name is not None:
viperlib.snprintf(tls_m_flag_name, 128, "__tls_init_done_%s", method_name)
tls_m_gv: llvmlite.GlobalVariable* = llvmlite.create_global_int(
pool, mod, tls_m_flag_name, 1, 0)
tls_m_gv: llvmlite.GlobalVariable* = llvmlite.create_global_int(pool, mod, tls_m_flag_name, 1, 0)
if tls_m_gv is not None:
i1_ty_m: llvmlite.LLVMType* = llvmlite.Int1(pool)
if i1_ty_m is not None:
@@ -793,46 +772,37 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
tls_m_rn: str = pool.alloc(64)
if tls_m_rn is not None:
viperlib.snprintf(tls_m_rn, 64, "@%s", tls_m_flag_name)
tls_m_ref: llvmlite.Value* = llvmlite.SSAValue(
pool, tls_m_ptr_ty, tls_m_rn)
tls_m_ref: llvmlite.Value* = llvmlite.SSAValue(pool, tls_m_ptr_ty, tls_m_rn)
if tls_m_ref is not None:
tls_m_ld: llvmlite.Value* = llvmlite.build_load(
func_builder, i1_ty_m, tls_m_ref)
tls_m_ld: llvmlite.Value* = llvmlite.build_load(func_builder, i1_ty_m, tls_m_ref)
lc_m: int = trans._label_counter
trans._label_counter = lc_m + 1
tls_m_buf: str = pool.alloc(64)
if tls_m_buf is not None:
viperlib.snprintf(tls_m_buf, 64, "tls.skip.%d", lc_m)
tls_m_skip: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(
pool, func, tls_m_buf)
tls_m_skip: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, tls_m_buf)
viperlib.snprintf(tls_m_buf, 64, "tls.cont.%d", lc_m)
tls_m_cont: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(
pool, func, tls_m_buf)
tls_m_cont: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, tls_m_buf)
if tls_m_skip is not None and tls_m_cont is not None:
llvmlite.build_cond_br(
func_builder, tls_m_ld, tls_m_skip, tls_m_cont)
llvmlite.build_cond_br(func_builder, tls_m_ld, tls_m_skip, tls_m_cont)
llvmlite.position_at_end(func_builder, tls_m_skip)
match ret_ty:
case llvmlite.LLVMType.Void():
llvmlite.build_ret_void(func_builder)
case llvmlite.LLVMType.Int(_):
tlm0: llvmlite.Value* = llvmlite.ConstInt(
pool, ret_ty, 0, "0")
tlm0: llvmlite.Value* = llvmlite.ConstInt(pool, ret_ty, 0, "0")
if tlm0 is not None:
llvmlite.build_ret(func_builder, tlm0)
case llvmlite.LLVMType.Float(_):
tlmf: llvmlite.Value* = llvmlite.ConstFloat(
pool, ret_ty, 0.0)
tlmf: llvmlite.Value* = llvmlite.ConstFloat(pool, ret_ty, 0.0)
if tlmf is not None:
llvmlite.build_ret(func_builder, tlmf)
case _:
tlmn: llvmlite.Value* = llvmlite.ConstNull(
pool, ret_ty, "null")
tlmn: llvmlite.Value* = llvmlite.ConstNull(pool, ret_ty, "null")
if tlmn is not None:
llvmlite.build_ret(func_builder, tlmn)
llvmlite.position_at_end(func_builder, tls_m_cont)
tlmo: llvmlite.Value* = llvmlite.ConstInt(
pool, i1_ty_m, 1, "1")
tlmo: llvmlite.Value* = llvmlite.ConstInt(pool, i1_ty_m, 1, "1")
if tlmo is not None:
llvmlite.build_store(func_builder, tlmo, tls_m_ref)
@@ -878,13 +848,10 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
if arg2 is not None and arg2.arg is not None:
param_ty2: llvmlite.LLVMType* = i32_ty
if arg2.annotation is not None:
resolved2: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, arg2.annotation, imported_modules, from_imports, trans, 0)
resolved2: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg2.annotation, imported_modules, from_imports, trans, 0)
if resolved2 is None:
# fail-fast:参数有注解但类型解析失败,不再静默保持 i32
self.Gen.TypeGenErr.fatal_error(
arg2, f"方法 '{class_name}.{method_name}' 参数 '{arg2.arg}' 类型解析失败",
"NameError")
self.Gen.TypeGenErr.fatal_error(arg2, f"方法 '{class_name}.{method_name}' 参数 '{arg2.arg}' 类型解析失败", "NameError")
resolved2 = i32_ty # 不可达(fatal_error 已退出)
if resolved2 is not None:
# 与 add_param 保持一致:裸类形参 → Ptr(struct)(对象即指针)
@@ -902,16 +869,13 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
# 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体)
# 传 pool:泛型 Subscript 返回 mangled name(对齐 HandlesAnnAssign 修复)
if arg2.annotation is not None:
cls_nm_oc: str = self.Gen.TypeGenResolve.extract_class_name_from_annotation(
arg2.annotation, imported_modules, pool, trans._from_imports)
cls_nm_oc: str = self.Gen.TypeGenResolve.extract_class_name_from_annotation(arg2.annotation, imported_modules, pool, trans._from_imports)
if cls_nm_oc is not None:
self.Gen.VarGen.set_var_annot_class_name(
trans.SymTab, arg2.arg, cls_nm_oc)
self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, arg2.arg, cls_nm_oc)
pname2: str = pool.alloc(32)
if pname2 is not None:
viperlib.snprintf(pname2, 32, "%%%s", arg2.arg)
param_val: llvmlite.Value* = llvmlite.SSAValue(
pool, param_ty2, pname2)
param_val: llvmlite.Value* = llvmlite.SSAValue(pool, param_ty2, pname2)
llvmlite.build_store(func_builder, param_val, alloca)
# OOP iter 协议:__next__ 的 stop-flag 参数初始化(store 0)并保存
@@ -922,12 +886,10 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
if i1_ty_sf is not None:
i1_ptr_ty_sf: llvmlite.LLVMType* = llvmlite.Ptr(pool, i1_ty_sf)
if i1_ptr_ty_sf is not None:
flag_ref_sf: llvmlite.Value* = llvmlite.SSAValue(
pool, i1_ptr_ty_sf, "%__stop_iter_flag__")
flag_ref_sf: llvmlite.Value* = llvmlite.SSAValue(pool, i1_ptr_ty_sf, "%__stop_iter_flag__")
if flag_ref_sf is not None:
trans._stop_iter_flag_ptr = flag_ref_sf
zero_i1_sf: llvmlite.Value* = llvmlite.ConstInt(
pool, i1_ty_sf, 0, "0")
zero_i1_sf: llvmlite.Value* = llvmlite.ConstInt(pool, i1_ty_sf, 0, "0")
if zero_i1_sf is not None:
llvmlite.build_store(func_builder, zero_i1_sf, flag_ref_sf)
@@ -1013,12 +975,10 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
# TypeGenResolve._is_cvoid_marker(TypeGenResolve.vp:1484)
# ③ -> None(CONST_NONE):解析即 Void(TypeGenResolve.vp:1996-1999)
if _is_void == 0 and fd.returns is not None:
if self.Gen.TypeGenResolve._is_cvoid_marker(
fd.returns, imported_modules) != 0:
if self.Gen.TypeGenResolve._is_cvoid_marker(fd.returns, imported_modules) != 0:
_is_void = 1
elif fd.returns.kind() == ast.ASTKind.Constant:
ret_none_cn_m: ast.Constant* = (
ast.Constant*)(fd.returns)
ret_none_cn_m: ast.Constant* = (ast.Constant*)(fd.returns)
if ret_none_cn_m.const_kind == ast.CONST_NONE:
_is_void = 1
if _is_void != 0:
@@ -1049,10 +1009,7 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
rt_name_m = "?"
err_fn_m: str = pool.alloc(256)
if err_fn_m is not None:
viperlib.snprintf(
err_fn_m, 256,
"方法 '%s' 流程掉出末尾但未显式 return(返回类型 %s),"
"请补显式 return(如 return 0 / return null)", method_name, rt_name_m)
viperlib.snprintf(err_fn_m, 256, "方法 '%s' 流程掉出末尾但未显式 return(返回类型 %s),请补显式 return(如 return 0 / return null)", method_name, rt_name_m)
self.Gen.TypeGenErr.fatal_error(fd, err_fn_m, "TypeError")
self.Gen.TypeGenErr.fatal_error(fd, "方法流程掉出末尾但未显式 return", "TypeError")
else:
@@ -1096,18 +1053,15 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
# 构建函数名: ClassName.__before_init__
full_name_buf: str = pool.alloc(128)
if full_name_buf is None:
return 0
if full_name_buf is None: return 0
viperlib.snprintf(full_name_buf, 128, "%s.__before_init__", class_name)
full_name: str = full_name_buf
mangled_name: str = self.Gen.FuncGenBase._mangle_name(trans, full_name)
# 创建函数
func: llvmlite.Function* = llvmlite.create_function(
pool, mod, mangled_name, void_ty)
if func is None:
return 0
func: llvmlite.Function* = llvmlite.create_function(pool, mod, mangled_name, void_ty)
if func is None: return 0
# 注册到函数表
max_funcs: int = 1024
@@ -1123,11 +1077,9 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
# 创建 entry 块 + builder
entry_blk: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, "entry")
if entry_blk is None:
return 0
if entry_blk is None: return 0
func_builder: llvmlite.IRBuilder* = llvmlite.new_builder(pool, func)
if func_builder is None:
return 0
if func_builder is None: return 0
llvmlite.position_at_end(func_builder, entry_blk)
# 注册 self 为 SSA 值
@@ -1181,8 +1133,7 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
vt_mangled: str = self.Gen.FuncGenBase._mangle_name(trans, vt_full_name)
# GEP 到 __vtable__ 字段(索引 0)
vt_slot: llvmlite.Value* = llvmlite.build_gep_struct(
func_builder, struct_ty, vt_i8_ptr_ty, self_val, 0)
vt_slot: llvmlite.Value* = llvmlite.build_gep_struct(func_builder, struct_ty, vt_i8_ptr_ty, self_val, 0)
if vt_slot is not None:
# 创建全局变量引用 Value
vt_ref: llvmlite.Value* = llvmlite.new_value(pool)
@@ -1200,16 +1151,14 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
llvmlite.value_set_name(vt_ref, vt_ref_name)
# bitcast 到 i8*
vt_as_i8: llvmlite.Value* = llvmlite.build_bitcast(
func_builder, vt_ref, vt_i8_ptr_ty)
vt_as_i8: llvmlite.Value* = llvmlite.build_bitcast(func_builder, vt_ref, vt_i8_ptr_ty)
if vt_as_i8 is not None:
llvmlite.build_store(func_builder, vt_as_i8, vt_slot)
# 2. 逐字段 store 默认值(用 bi_entry 直接访问,规避跨模块同名 find_struct 找错)
if bi_entry is not None:
for fi in range(bi_entry.FieldCount):
fe: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(
bi_entry, fi)
fe: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(bi_entry, fi)
if fe is None or fe.DefaultVal is None:
continue
# 静态数组字段 + 列表字面量默认值 → 整体置零 + 逐元素 GEP+store
@@ -1219,8 +1168,7 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
# 推断为静态数组,此处保证 __before_init__ 填充真实字符串指针。
if fe.Ty is not None and self.Gen.ExprGenBase.is_array_type(fe.Ty) != 0 \
and fe.DefaultVal.kind() == ast.ASTKind.List:
field_ptr_arr: llvmlite.Value* = llvmlite.build_gep_struct(
func_builder, struct_ty, fe.Ty, self_val, fe.Index)
field_ptr_arr: llvmlite.Value* = llvmlite.build_gep_struct(func_builder, struct_ty, fe.Ty, self_val, fe.Index)
if field_ptr_arr is not None:
zero_arr_f: llvmlite.Value* = llvmlite.ConstZero(pool, fe.Ty)
if zero_arr_f is not None:
@@ -1232,22 +1180,16 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
arr_ctx: str = pool.alloc(192)
if arr_ctx is not None:
fname_dbg_v: str = fe.Name
if fname_dbg_v is None:
fname_dbg_v = "?"
if fname_dbg_v is None: fname_dbg_v = "?"
viperlib.snprintf(arr_ctx, 192, "类 %s 字段 %s:", class_name, fname_dbg_v)
self.Gen.AssignGen._init_global_array_from_list(
func_builder, pool, mod, field_ptr_arr, fe.DefaultVal, trans, arr_ctx)
self.Gen.AssignGen._init_global_array_from_list(func_builder, pool, mod, field_ptr_arr, fe.DefaultVal, trans, arr_ctx)
continue
# 翻译默认值表达式
default_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
func_builder, pool, mod, fe.DefaultVal, None, 0, trans)
if default_val is None:
continue
default_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(func_builder, pool, mod, fe.DefaultVal, None, 0, trans)
if default_val is None: continue
# GEP 到字段
field_ptr: llvmlite.Value* = llvmlite.build_gep_struct(
func_builder, struct_ty, fe.Ty, self_val, fe.Index)
if field_ptr is None:
continue
field_ptr: llvmlite.Value* = llvmlite.build_gep_struct(func_builder, struct_ty, fe.Ty, self_val, fe.Index)
if field_ptr is None: continue
# 类型转换并 store
default_val = self.Gen.ExprGenBase.coerce_to_type(func_builder, default_val, fe.Ty, fe.DefaultVal)
llvmlite.build_store(func_builder, default_val, field_ptr)
+48 -104
View File
@@ -13,13 +13,8 @@ import lib.core.Gen.Type.TypeSpec as TSpec
# ============================================================
# ExprGenBase - ExprGenMixin 拆分(阶段 D):表达式基础工具(类型判断/指针层级/coerce)
#
# 最底层 Base(ExprGenMixin/Const/Fstr/Ops/Cdef/Name/Attr/Cls 均 1 级继承本类)。
# 跨 Mixin 调用统一走 HandlesExpr 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ExprGenBase:
novirtual class ExprGenBase:
"""表达式基础工具(类型判断/指针层级/coerce)"""
# --- docstring 登记表字段(__doc__ 魔法属性支持)---
@@ -44,8 +39,7 @@ class ExprGenBase:
# ============================================================
def get_func_name(self, func_node: ast.AST*) -> str:
"""从函数节点提取函数名"""
if func_node is None:
return None
if func_node is None: return None
k: int = func_node.kind()
if k == ast.ASTKind.Name:
nm: ast.Name* = ast.Name*(func_node)
@@ -60,13 +54,11 @@ class ExprGenBase:
def escape_llvm_string(self, pool: memhub.MemBuddy*,
src: str) -> str:
"""将字符串转换为 LLVM IR 字符串字面量 c"...\\00" """
if src is None:
return None
if src is None: return None
slen: sizet = string.strlen(src)
alloc_size: sizet = 4 * slen + 8
buf: str = pool.alloc(alloc_size)
if buf is None:
return None
if buf is None: return None
pos: sizet = 0
buf[pos] = 'c'
pos += 1
@@ -114,8 +106,7 @@ class ExprGenBase:
# ============================================================
def get_llvm_float_bits(self, ty: llvmlite.LLVMType*) -> int:
"""获取 LLVM 浮点类型的位宽,非浮点类型返回 0"""
if ty is None:
return 0
if ty is None: return 0
match ty:
case llvmlite.LLVMType.Float(bits):
return bits
@@ -128,8 +119,7 @@ class ExprGenBase:
# ============================================================
def is_ptr_type(self, ty: llvmlite.LLVMType*) -> int:
"""检查 ty 是否是 Ptr 类型,返回 1=是, 0=否"""
if ty is None:
return 0
if ty is None: return 0
match ty:
case llvmlite.LLVMType.Ptr(pointee):
return 1
@@ -166,15 +156,11 @@ class ExprGenBase:
# ============================================================
def _is_zero_int_literal(self, node: ast.AST*) -> int:
"""判断节点是否为整数字面量 0,返回 1=是 / 0=否"""
if node is None:
return 0
if node.kind() != ast.ASTKind.Constant:
return 0
if node is None: return 0
if node.kind() != ast.ASTKind.Constant: return 0
cn: ast.Constant* = ast.Constant*(node)
if cn is None or cn.const_kind != ast.CONST_INT:
return 0
if cn.int_val == 0:
return 1
if cn is None or cn.const_kind != ast.CONST_INT: return 0
if cn.int_val == 0: return 1
return 0
# ============================================================
# is_array_type - 检查类型是否为 Array
@@ -183,8 +169,7 @@ class ExprGenBase:
# ============================================================
def is_array_type(self, ty: llvmlite.LLVMType*) -> int:
"""检查 ty 是否是 Array 类型,返回 1=是, 0=否"""
if ty is None:
return 0
if ty is None: return 0
match ty:
case llvmlite.LLVMType.Array(_, _):
return 1
@@ -245,22 +230,16 @@ class ExprGenBase:
trans: HT.Translator*,
sub_node: ast.AST*) -> int:
"""判断下标基座是否为 list[T] 变量(1=是)"""
if sub_node is None or trans is None:
return 0
if sub_node is None or trans is None: return 0
sub: ast.Subscript* = ast.Subscript*(sub_node)
if sub is None or sub.value is None or sub.value.kind() != ast.ASTKind.Name:
return 0
if sub is None or sub.value is None or sub.value.kind() != ast.ASTKind.Name: return 0
nm: ast.Name* = ast.Name*(sub.value)
if nm.id is None:
return 0
if nm.id is None: return 0
alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
if alloca is None or alloca.Ty is None:
return 0
if self.is_ptr_type(alloca.Ty) == 0:
return 0
if alloca is None or alloca.Ty is None: return 0
if self.is_ptr_type(alloca.Ty) == 0: return 0
pointee: llvmlite.LLVMType* = alloca.Ty.Pointee
if pointee is None:
return 0
if pointee is None: return 0
match pointee:
case llvmlite.LLVMType.Ptr(inner_ty):
lsn_ls: str = None
@@ -281,22 +260,16 @@ class ExprGenBase:
trans: HT.Translator*,
sub_node: ast.AST*) -> str:
"""解析下标基座变量的结构体类名(无则 None)"""
if sub_node is None or trans is None:
return None
if sub_node is None or trans is None: return None
sub: ast.Subscript* = ast.Subscript*(sub_node)
if sub is None or sub.value is None or sub.value.kind() != ast.ASTKind.Name:
return None
if sub is None or sub.value is None or sub.value.kind() != ast.ASTKind.Name: return None
nm: ast.Name* = ast.Name*(sub.value)
if nm.id is None:
return None
if nm.id is None: return None
alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
if alloca is None or alloca.Ty is None:
return None
if self.is_ptr_type(alloca.Ty) == 0:
return None
if alloca is None or alloca.Ty is None: return None
if self.is_ptr_type(alloca.Ty) == 0: return None
pointee: llvmlite.LLVMType* = alloca.Ty.Pointee
if pointee is None:
return None
if pointee is None: return None
if self.is_ptr_type(pointee) != 0:
inner: llvmlite.LLVMType* = pointee.Pointee
if inner is not None:
@@ -316,17 +289,13 @@ class ExprGenBase:
trans: HT.Translator*,
sub_node: ast.AST*) -> int:
"""下标基座应走 __getitem__ 语义时返回 1,否则 0(应走 GEP 地址语义)"""
if self._is_list_subscript_base(pool, trans, sub_node) != 0:
return 1
if self._is_list_subscript_base(pool, trans, sub_node) != 0: return 1
cls_ugi: str = self._sub_base_class_name(pool, trans, sub_node)
if cls_ugi is None:
return 0
if cls_ugi is None: return 0
lookup_ugi: str = pool.alloc(128)
if lookup_ugi is None:
return 0
if lookup_ugi is None: return 0
viperlib.snprintf(lookup_ugi, 128, "%s.__getitem__", cls_ugi)
if self.Gen.CallGenBase.find_func_in_module(mod, lookup_ugi) is not None:
return 1
if self.Gen.CallGenBase.find_func_in_module(mod, lookup_ugi) is not None: return 1
return 0
# ============================================================
# _deref_if_ptr_ptr - 如果 obj_ptr 是 Ptr(Ptr(...)),load 解引用
@@ -338,19 +307,14 @@ class ExprGenBase:
def _deref_if_ptr_ptr(self, builder: llvmlite.IRBuilder*,
obj_ptr: llvmlite.Value*) -> llvmlite.Value*:
"""如果 obj_ptr 是 Ptr(Ptr(...)),load 解引用获取内层指针"""
if obj_ptr is None or obj_ptr.Ty is None:
return obj_ptr
if self.is_ptr_type(obj_ptr.Ty) == 0:
return obj_ptr
if obj_ptr is None or obj_ptr.Ty is None: return obj_ptr
if self.is_ptr_type(obj_ptr.Ty) == 0: return obj_ptr
pointee: llvmlite.LLVMType* = obj_ptr.Ty.Pointee
if pointee is None:
return obj_ptr
if self.is_ptr_type(pointee) == 0:
return obj_ptr
if pointee is None: return obj_ptr
if self.is_ptr_type(pointee) == 0: return obj_ptr
# obj_ptr 是 Ptr(Ptr(...)),load 解引用
loaded: llvmlite.Value* = llvmlite.build_load(builder, pointee, obj_ptr)
if loaded is None:
return obj_ptr
if loaded is None: return obj_ptr
return loaded
# ============================================================
# 类型强制转换:整数 sext/trunc,浮点 fpext/fptrunc,int↔float si2fp/fp2si
@@ -369,8 +333,7 @@ class ExprGenBase:
node: AST 节点(用于错误定位),可为 None
"""
if val is None or target_ty is None:
return val
if val is None or target_ty is None: return val
# 函数 → 指针: bitcast(如 CreateThread(..., _thread_alloc_free, ...) 传函数指针)
# 函数 Value 的 Ty 是 Func,既不是整数也不是指针,需在整数/浮点转换之前处理
match val.Ty:
@@ -397,12 +360,8 @@ class ExprGenBase:
# 属标准 C 空指针用法,须放行而非报 CastError。先拓宽到 i64
# (inttoptr 要求同宽,对齐 MatchGenMixin 模式),再 inttoptr 成空指针。
if val.IsConst == 1 and val.IntVal == 0:
return llvmlite.build_inttoptr(
builder, llvmlite.const_int64(builder.Pool, 0), target_ty)
self.Gen.TypeGenErr.fatal_error(
node,
"整数隐式转指针已禁止:必须显式强转为指针(如 t.CPtr(x))才能把整数赋给指针类型",
"CastError")
return llvmlite.build_inttoptr(builder, llvmlite.const_int64(builder.Pool, 0), target_ty)
self.Gen.TypeGenErr.fatal_error(node, "整数隐式转指针已禁止:必须显式强转为指针(如 t.CPtr(x))才能把整数赋给指针类型", "CastError")
return val
# 指针 → 整数: ptrtoint(当目标明确是整数而非指针时)
# 注意: target_bits == 8 时跳过 ptrtoint,走后面的 build_load 解引用首字符
@@ -434,10 +393,7 @@ class ExprGenBase:
target_max_u: uint64 = (uint64(1) << target_bits) - 1
if uint64(val.IntVal) > target_max_u:
max_print: int64 = int64(target_max_u)
self.Gen.TypeGenErr.fatal_error(
node,
f"窄化截断溢出:常量 {val.IntVal} 超出目标类型 {target_bits} 位范围 [0, {max_print}],赋值将被静默截断",
"OverflowError")
self.Gen.TypeGenErr.fatal_error(node, f"窄化截断溢出:常量 {val.IntVal} 超出目标类型 {target_bits} 位范围 [0, {max_print}],赋值将被静默截断", "OverflowError")
return llvmlite.build_trunc(builder, val, target_ty)
# 浮点转换
val_fbits: int = self.get_llvm_float_bits(val.Ty)
@@ -463,19 +419,16 @@ class ExprGenBase:
if self.is_ptr_type(val.Ty) == 0 and self.is_ptr_type(target_ty) != 0:
vk_agg: int = val.Ty.kind()
if vk_agg == llvmlite.LLVMType.Struct or vk_agg == llvmlite.LLVMType.Array:
tmp_agg: llvmlite.Value* = self.Gen.VarGen._alloca_at_entry(
builder, val.Ty)
tmp_agg: llvmlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, val.Ty)
if tmp_agg is not None:
llvmlite.build_store(builder, val, tmp_agg)
match target_ty:
case llvmlite.LLVMType.Ptr(pointee_agg):
if self.Gen.AssignGen._stg_ty_equal(
builder.Pool, pointee_agg, val.Ty) != 0:
if self.Gen.AssignGen._stg_ty_equal(builder.Pool, pointee_agg, val.Ty) != 0:
return tmp_agg
case _:
pass
bc_agg: llvmlite.Value* = llvmlite.build_bitcast(
builder, tmp_agg, target_ty)
bc_agg: llvmlite.Value* = llvmlite.build_bitcast(builder, tmp_agg, target_ty)
if bc_agg is not None:
return bc_agg
return tmp_agg
@@ -504,8 +457,7 @@ class ExprGenBase:
trans 供 _node_type_unsigned 经 SymTab 解析变量注解的符号性(Name/
Subscript 形态必需);省略则仅能识别显式 t.CUIntXXT 强转。
"""
if val is None or val.Ty is None:
return 0
if val is None or val.Ty is None: return 0
return self.Gen.ExprGenOps.should_zext_widen(pool, val, None, node, trans)
# translate_ptr_arith:指针算术 ptr±int,用 getelementptr(按 pointee 元素大小缩放索引,对齐 TPC ExprGen.emit_binary_op / HandlesAugAssign.py);数组 pointee([N x ty]*)先 decay 为元素指针(GEP 0,0),避免以整个数组为步长
@@ -515,8 +467,7 @@ class ExprGenBase:
int_val: llvmlite.Value*,
op: int) -> llvmlite.Value*:
"""指针算术: ptr + int / ptr - int → GEP(按元素大小缩放索引)"""
if ptr_val is None or int_val is None or ptr_val.Ty is None:
return None
if ptr_val is None or int_val is None or ptr_val.Ty is None: return None
# 提取 pointee 类型(非指针 → 不处理返回 None)
elem_ty: llvmlite.LLVMType* = None
match ptr_val.Ty:
@@ -524,19 +475,15 @@ class ExprGenBase:
elem_ty = pointee
case _:
return None
if elem_ty is None:
return None
if elem_ty is None: return None
# 索引统一到 i64(对齐 TPC zext 到 i64)
i64_ty: llvmlite.LLVMType* = llvmlite.Int64(pool)
idx: llvmlite.Value* = self.coerce_to_type(builder, int_val, i64_ty, None)
if idx is None:
return None
if idx is None: return None
# ptr - int → 负索引(LLVM GEP 索引为加法语义)
if op == ast.OpKind.Sub:
neg_idx: llvmlite.Value* = llvmlite.build_sub(
builder, llvmlite.const_int64(pool, 0), idx)
if neg_idx is None:
return None
neg_idx: llvmlite.Value* = llvmlite.build_sub(builder, llvmlite.const_int64(pool, 0), idx)
if neg_idx is None: return None
idx = neg_idx
# 数组 pointee → 先 decay 为元素指针(getelementptr [N x ty], [N x ty]* %p, i32 0, i32 0)
if self.is_array_type(elem_ty) != 0:
@@ -548,16 +495,13 @@ class ExprGenBase:
return None
if inner_ty is None:
return None
decayed: llvmlite.Value* = llvmlite.build_gep_array(
builder, elem_ty, inner_ty, ptr_val, llvmlite.const_int64(pool, 0))
if decayed is None:
return None
decayed: llvmlite.Value* = llvmlite.build_gep_array(builder, elem_ty, inner_ty, ptr_val, llvmlite.const_int64(pool, 0))
if decayed is None: return None
return llvmlite.build_gep(builder, inner_ty, decayed, idx)
return llvmlite.build_gep(builder, elem_ty, ptr_val, idx)
def InitExprGen(self) -> int:
"""初始化 ExprGen 族字段(构造时由 Generator 调用)"""
if self is None:
return 1
if self is None: return 1
self.DocKeys = None
self.DocValues = None
self.DocCount = 0
+6 -16
View File
@@ -19,37 +19,27 @@ import lib.Stub.StubMerger.StubMergerStore as StubMergerStore
# ============================================================
# ExprGenCdef - ExprGenMixin 拆分(阶段 D):跨模块 CDefine 查找
#
# 继承 ExprGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExpr 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ExprGenCdef(ExprGenBase.ExprGenBase):
novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
"""跨模块 CDefine 查找"""
# _build_source_path_from_sha1:通过 SHA1 从 StubMerger 全局存储器构建源 .vp/.py 文件路径(.vpi 未生成时回退读源 .py);rel_path 以 "lib/" 开头 → {Config.SourceDir}/{rel_path},其他 → {Config.IncludesDir}/{rel_path}。返回 stdlib.malloc 分配的路径字符串(调用者负责 free),失败返回 None
def _build_source_path_from_sha1(self, sha1: str) -> str:
"""通过 SHA1 从全局存储器构建源 .py 文件路径"""
if sha1 is None:
return None
if Config.IncludesDir is None:
return None
if sha1 is None: return None
if Config.IncludesDir is None: return None
# 从 StubMerger 全局存储器获取相对路径数组
rel_arr_ptr: bytes = StubMergerStore.GetSha1StoreRelArrPtr()
count: int = StubMergerStore.GetSha1StoreCount()
if rel_arr_ptr is None or count <= 0:
return None
if rel_arr_ptr is None or count <= 0: return None
sha1_arr_ptr: bytes = StubMergerStore.GetSha1StoreArrPtr()
if sha1_arr_ptr is None:
return None
if sha1_arr_ptr is None: return None
# 遍历查找匹配的 SHA1
idx_s: int = -1
for i in range(count):
sidx: sizet = sizet(i) * 17
cur_sha1: str = sha1_arr_ptr + sidx
if cur_sha1[0] == '\0':
continue
if cur_sha1[0] == '\0': continue
if string.strcmp(cur_sha1, sha1) == 0:
idx_s = i
break
+55 -116
View File
@@ -16,24 +16,17 @@ import lib.Stub.StubMerger.StubMergerStore as StubMergerStore
# ============================================================
# docstring 登记表容量常量(与 ExprGenMixin 保持一致,本地副本避免
# 跨模块 CDefine 查找 bug:ExprGenCls(C) 在 ExprGenMixin(M) 之前按
# 文件序编译时,跨模块 CDefine 全局表未注册 → NameError 未定义)
# docstring 登记表容量常量(与 ExprGenMixin 保持一致,存疑
# ============================================================
DOC_MAX: t.CDefine = 512
DOC_KEY_SZ: t.CDefine = 192
DOC_VAL_SZ: t.CDefine = 4096
define DOC_MAX = 512
define DOC_KEY_SZ = 192
define DOC_VAL_SZ = 4096
# ============================================================
# ExprGenCls - ExprGenMixin 拆分(阶段 D):类名推断/docstring 登记
#
# 继承 ExprGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExpr 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ExprGenCls(ExprGenBase.ExprGenBase):
novirtual class ExprGenCls(ExprGenBase.ExprGenBase):
"""类名推断/docstring 登记"""
# ============================================================
@@ -48,40 +41,30 @@ class ExprGenCls(ExprGenBase.ExprGenBase):
def _extract_docstring_from_body(self, body: list[ast.AST*]*) -> str:
"""从函数/类体提取 docstring:body[0] 为 Expr(Constant str) 时返回内容"""
if body is None or len(body) == 0:
return None
if body is None or len(body) == 0: return None
first: ast.AST* = body.get(0)
if first is None or first.kind() != ast.ASTKind.Expr:
return None
if first is None or first.kind() != ast.ASTKind.Expr: return None
ex: rawptr[ast.Expr] = rawptr[ast.Expr](first)
if ex is None or ex.value is None or ex.value.kind() != ast.ASTKind.Constant:
return None
if ex is None or ex.value is None or ex.value.kind() != ast.ASTKind.Constant: return None
cn: ast.Constant* = ast.Constant*(ex.value)
if cn is None or cn.const_kind != ast.CONST_STR:
return None
if cn is None or cn.const_kind != ast.CONST_STR: return None
return cn.str_val
def register_docstring(self, module_sha1: str, symbol: str, doc: str) -> None:
"""登记 docstring(key="{module_sha1}.{symbol}"),查重幂等"""
if module_sha1 is None or symbol is None or doc is None:
return
if string.strlen(doc) == 0:
return
if module_sha1 is None or symbol is None or doc is None: return
if string.strlen(doc) == 0: return
if self.DocKeys is None:
self.DocKeys = CompilerFactory.factory.PermPool.alloc(DOC_MAX * DOC_KEY_SZ)
self.DocValues = CompilerFactory.factory.PermPool.alloc(DOC_MAX * DOC_VAL_SZ)
if self.DocKeys is None or self.DocValues is None:
return
if self.DocKeys is None or self.DocValues is None: return
string.memset(self.DocKeys, 0, DOC_MAX * DOC_KEY_SZ)
string.memset(self.DocValues, 0, DOC_MAX * DOC_VAL_SZ)
if self.DocCount >= DOC_MAX:
return
if self.DocCount >= DOC_MAX: return
ml: sizet = string.strlen(module_sha1)
sl: sizet = string.strlen(symbol)
key_buf: bytes = stdlib.malloc(ml + sl + 2)
if key_buf is None:
return
if key_buf is None: return
viperlib.snprintf(key_buf, ml + sl + 2, "%s.%s", module_sha1, symbol)
i: int
for i in range(self.DocCount):
if string.strcmp(self.DocKeys + i * DOC_KEY_SZ, key_buf) == 0:
stdlib.free(key_buf)
@@ -92,15 +75,12 @@ class ExprGenCls(ExprGenBase.ExprGenBase):
stdlib.free(key_buf)
def lookup_docstring(self, module_sha1: str, symbol: str) -> str:
"""查找 docstring 内容(key="{module_sha1}.{symbol}"),未找到返回 None"""
if self.DocKeys is None or module_sha1 is None or symbol is None:
return None
if self.DocKeys is None or module_sha1 is None or symbol is None: return None
ml: sizet = string.strlen(module_sha1)
sl: sizet = string.strlen(symbol)
key_buf: bytes = stdlib.malloc(ml + sl + 2)
if key_buf is None:
return None
if key_buf is None: return None
viperlib.snprintf(key_buf, ml + sl + 2, "%s.%s", module_sha1, symbol)
i: int
for i in range(self.DocCount):
if string.strcmp(self.DocKeys + i * DOC_KEY_SZ, key_buf) == 0:
stdlib.free(key_buf)
@@ -109,16 +89,13 @@ class ExprGenCls(ExprGenBase.ExprGenBase):
return None
def extract_module_docstrings(self, tree: ast.AST*, module_sha1: str) -> None:
"""扫描模块 AST:登记模块级函数/类/方法的 docstring(幂等)"""
if tree is None or module_sha1 is None:
return
if tree is None or module_sha1 is None: return
ch: list[ast.AST*]* = tree.children
if ch is None:
return
if ch is None: return
cn: sizet = len(ch)
for ci in range(cn):
child: ast.AST* = ch.get(ci)
if child is None:
continue
if child is None: continue
kd: int = child.kind()
if kd == ast.ASTKind.FunctionDef:
fd: ast.FunctionDef* = ast.FunctionDef*(child)
@@ -129,8 +106,7 @@ class ExprGenCls(ExprGenBase.ExprGenBase):
self.register_docstring(module_sha1, fd.name, fdoc)
elif kd == ast.ASTKind.ClassDef:
cd: ast.ClassDef* = ast.ClassDef*(child)
if cd is None or cd.name is None:
continue
if cd is None or cd.name is None: continue
cd_body0: list[ast.AST*]* = cd.children
cdoc: str = self._extract_docstring_from_body(cd_body0)
if cdoc is not None:
@@ -141,11 +117,9 @@ class ExprGenCls(ExprGenBase.ExprGenBase):
cbn: sizet = len(cd_body)
for mi in range(cbn):
m: ast.AST* = cd_body.get(mi)
if m is None or m.kind() != ast.ASTKind.FunctionDef:
continue
if m is None or m.kind() != ast.ASTKind.FunctionDef: continue
mfd: ast.FunctionDef* = ast.FunctionDef*(m)
if mfd is None or mfd.name is None:
continue
if mfd is None or mfd.name is None: continue
mdoc: str = self._extract_docstring_from_body(mfd.children)
if mdoc is not None:
cl_nl: sizet = string.strlen(cd.name)
@@ -161,10 +135,8 @@ class ExprGenCls(ExprGenBase.ExprGenBase):
判定顺序:本地变量(函数变量)→ 结构体类(含跨模块预注册)→ 模块名。
"""
if trans is None or name_id is None or out_mod is None or out_sym is None:
return 0
if trans.ModuleSha1 is None:
return 0
if trans is None or name_id is None or out_mod is None or out_sym is None: return 0
if trans.ModuleSha1 is None: return 0
# 1. 本地变量(函数变量/全局变量)
if self.Gen.VarGen.lookup_var(trans.SymTab, name_id) is not None:
string.strcpy(out_mod, trans.ModuleSha1)
@@ -201,21 +173,17 @@ class ExprGenCls(ExprGenBase.ExprGenBase):
remote.RemoteClass.remote_method / LocalClass.local_method 等。
最左 Name 判定:模块名 → 该模块 sha1;变量/类 → 类所属模块 sha1。
"""
if trans is None or at is None or out_mod is None or out_sym is None:
return 0
if trans.ModuleSha1 is None:
return 0
if trans is None or at is None or out_mod is None or out_sym is None: return 0
if trans.ModuleSha1 is None: return 0
# 收集 Attribute 链(最外层 attr 在前)
DOC_CHAIN_MAX: int = 8
items: bytes = stdlib.malloc(DOC_CHAIN_MAX * 128)
if items is None:
return 0
if items is None: return 0
n_items: int = 0
cur: ast.AST* = (ast.AST*)(at)
while cur is not None and cur.kind() == ast.ASTKind.Attribute and n_items < DOC_CHAIN_MAX:
cat: ast.Attribute* = ast.Attribute*(cur)
if cat.attr is None:
break
if cat.attr is None: break
string.strcpy(items + n_items * 128, cat.attr)
n_items += 1
cur = cat.value
@@ -244,7 +212,6 @@ class ExprGenCls(ExprGenBase.ExprGenBase):
stdlib.free(items)
return 1
total: sizet = 0
j: int
for j in range(n_items):
total += string.strlen(items + j * 128) + 1
sym_buf: bytes = stdlib.malloc(total + 1)
@@ -304,27 +271,22 @@ class ExprGenCls(ExprGenBase.ExprGenBase):
node: ast.AST*,
trans: HT.Translator*) -> str:
"""从表达式推断结构体类名,无法推断返回 None"""
if node is None or trans is None:
return None
if node is None or trans is None: return None
k: int = node.kind()
# Call: 类实例化 / 方法调用
if k == ast.ASTKind.Call:
cl: ast.Call* = ast.Call*(node)
if cl is None or cl.func is None:
return None
if cl is None or cl.func is None: return None
if cl.func.kind() == ast.ASTKind.Name:
cand: str = (ast.Name*(cl.func)).id
if cand is None:
return None
if self.Gen.StructGen.find_struct(cand) is not None:
return cand
if cand is None: return None
if self.Gen.StructGen.find_struct(cand) is not None: return cand
return None
if cl.func.kind() == ast.ASTKind.Attribute:
# 方法调用 a.cross(b):vpi 返回注解缓存精确解析返回类名
# (方法可返回非同类对象,如 Transform.world_position → 'Vec3')。
ca: ast.Attribute* = ast.Attribute*(cl.func)
if ca is None or ca.attr is None or ca.value is None:
return None
if ca is None or ca.attr is None or ca.value is None: return None
# 模块级函数调用(Module.func()):接收者是已导入模块名而非类对象
if ca.value.kind() == ast.ASTKind.Name:
mod_nm2: str = (ast.Name*(ca.value)).id
@@ -344,10 +306,8 @@ class ExprGenCls(ExprGenBase.ExprGenBase):
if ret_cls2 is not None:
return ret_cls2
obj_cls: str = self.infer_expr_class(pool, mod, ca.value, trans)
if obj_cls is None:
return None
if self._cls_has_dunder(pool, mod, obj_cls, ca.attr) == 0:
return None
if obj_cls is None: return None
if self._cls_has_dunder(pool, mod, obj_cls, ca.attr) == 0: return None
cls_sha1: str = self.Gen.StructGen.get_struct_sha1(obj_cls)
if cls_sha1 is None and trans.ModuleSha1 is not None:
cls_sha1 = trans.ModuleSha1
@@ -359,8 +319,7 @@ class ExprGenCls(ExprGenBase.ExprGenBase):
temp_dir = self.Gen.CallGenBase.TempDir
if temp_dir is not None:
VpiReader._ensure_vpi_ret_annot_loaded(cls_sha1, temp_dir)
annot_ret: str = VpiReader._lookup_vpi_ret_annot(
cls_sha1, obj_cls, ca.attr)
annot_ret: str = VpiReader._lookup_vpi_ret_annot(cls_sha1, obj_cls, ca.attr)
if annot_ret is not None:
ret_cls = self._extract_annot_class_name(pool, annot_ret)
return ret_cls
@@ -368,15 +327,11 @@ class ExprGenCls(ExprGenBase.ExprGenBase):
# Name: 源变量注解
if k == ast.ASTKind.Name:
nm: ast.Name* = ast.Name*(node)
if nm is None or nm.id is None:
return None
ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, nm.id)
if ve is None:
return None
if nm is None or nm.id is None: return None
ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id)
if ve is None: return None
acn_n: str = self.Gen.VarGen.var_annot_class_name(ve)
if acn_n is None:
return None
if acn_n is None: return None
# 去模块前缀:json.JsonValue → JsonValue。AnnotClassName 可能带
# 模块限定(extract_class_name_from_annotation 的 Attribute 分支返回
# "memhub.MemBuddy" 形式),而 find_struct/_cls_has_dunder/
@@ -389,25 +344,19 @@ class ExprGenCls(ExprGenBase.ExprGenBase):
# BinOp/UnaryOp: 运算符重载返回同类对象
if k == ast.ASTKind.BinOp:
bop: ast.BinOp* = ast.BinOp*(node)
if bop is None or bop.left is None:
return None
if bop is None or bop.left is None: return None
dunder: str = self.Gen.ExprGenOps._binop_to_dunder(bop.op)
if dunder is None:
return None
if dunder is None: return None
lhs_cls: str = self.infer_expr_class(pool, mod, bop.left, trans)
if lhs_cls is None or self._cls_has_dunder(pool, mod, lhs_cls, dunder) == 0:
return None
if lhs_cls is None or self._cls_has_dunder(pool, mod, lhs_cls, dunder) == 0: return None
return lhs_cls
if k == ast.ASTKind.UnaryOp:
uop: ast.UnaryOp* = ast.UnaryOp*(node)
if uop is None or uop.operand is None:
return None
if uop is None or uop.operand is None: return None
dunder: str = self.Gen.ExprGenOps._unaryop_to_dunder(uop.op)
if dunder is None:
return None
if dunder is None: return None
opr_cls: str = self.infer_expr_class(pool, mod, uop.operand, trans)
if opr_cls is None or self._cls_has_dunder(pool, mod, opr_cls, dunder) == 0:
return None
if opr_cls is None or self._cls_has_dunder(pool, mod, opr_cls, dunder) == 0: return None
return opr_cls
# Attribute: 字段注解类名(属性链递归,如 p = r.origin)
if k == ast.ASTKind.Attribute:
@@ -420,18 +369,13 @@ class ExprGenCls(ExprGenBase.ExprGenBase):
# SHA1(stub 中声明)即视为存在。仅在确实存在时采用推断类名,
# 避免把原生运算误标为类类型。
# ============================================================
def _cls_has_dunder(self, pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
class_name: str, dunder: str) -> int:
def _cls_has_dunder(self, pool: memhub.MemBuddy*, mod: llvmlite.LLVMModule*, class_name: str, dunder: str) -> int:
"""类及其 MRO 祖先链中是否存在 dunder 方法,存在返回 1"""
if class_name is None or dunder is None or mod is None:
return 0
if class_name is None or dunder is None or mod is None: return 0
lookup_name: str = pool.alloc(128)
if lookup_name is None:
return 0
if lookup_name is None: return 0
viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, dunder)
if self.Gen.CallGenBase.find_func_in_module(mod, lookup_name) is not None:
return 1
if self.Gen.CallGenBase.find_func_in_module(mod, lookup_name) is not None: return 1
# 继承链祖先查找
mro_ptr: sizet* = self.Gen.StructGen.get_mro_chain(pool, class_name)
mi: int = 1
@@ -445,8 +389,7 @@ class ExprGenCls(ExprGenBase.ExprGenBase):
return 1
mi += 1
# 跨模块:类有 SHA1(stub 中声明该方法)视为存在
if self.Gen.StructGen.get_struct_sha1(class_name) is not None:
return 1
if self.Gen.StructGen.get_struct_sha1(class_name) is not None: return 1
return 0
# ============================================================
# _extract_annot_class_name - 从返回注解文本提取结构体类名
@@ -456,17 +399,13 @@ class ExprGenCls(ExprGenBase.ExprGenBase):
# CFloat64T/t.CPtr 等均不注册 struct,天然过滤)。"A | B" 联合
# 多候选时取首个命中段。
# ============================================================
def _extract_annot_class_name(self, pool: memhub.MemBuddy*,
annot: str) -> str:
def _extract_annot_class_name(self, pool: memhub.MemBuddy*, annot: str) -> str:
"""从返回注解文本提取已注册结构体类名,无命中返回 None"""
if pool is None or annot is None:
return None
if pool is None or annot is None: return None
alen: sizet = string.strlen(annot)
if alen == 0:
return None
if alen == 0: return None
seg: str = pool.alloc(256)
if seg is None:
return None
if seg is None: return None
start: sizet = 0
i: sizet
for i in range(alen):
+11 -27
View File
@@ -15,13 +15,8 @@ import lib.core.Gen.Expr.ExprGenBase as ExprGenBase
# ============================================================
# ExprGenConst - ExprGenMixin 拆分(阶段 D):常量/全局字符串/list 字面量翻译
#
# 继承 ExprGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExpr 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ExprGenConst(ExprGenBase.ExprGenBase):
novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
"""常量/全局字符串/list 字面量翻译"""
# ============================================================
@@ -34,8 +29,7 @@ class ExprGenConst(ExprGenBase.ExprGenBase):
trans: HT.Translator*) -> llvmlite.Value*:
"""创建全局字符串常量并返回 i8* bitcast"""
escaped: str = self.escape_llvm_string(pool, str_val)
if escaped is None:
return None
if escaped is None: return None
slen: sizet = string.strlen(str_val)
count: int = slen + 1
@@ -276,13 +270,11 @@ class ExprGenConst(ExprGenBase.ExprGenBase):
first_elem_val = self.Gen.ExprGen.translate_value(builder, pool, mod, first_elem_node, None, 0, trans)
if first_elem_val is None or first_elem_val.Ty is None:
# fail-fast:首元素翻译失败/Value 类型缺失,立即终止编译(暴露上游根因)
self.Gen.TypeGenErr.fatal_error(
first_elem_node, "list 字面量元素类型推断失败(Value 类型缺失)", "TypeError")
self.Gen.TypeGenErr.fatal_error(first_elem_node, "list 字面量元素类型推断失败(Value 类型缺失)", "TypeError")
inferred_type_name = self._infer_elem_type_from_value(pool, first_elem_val)
if inferred_type_name is None:
# fail-fast:首元素 Value 类型无法映射为 list 元素类型,立即终止编译
self.Gen.TypeGenErr.fatal_error(
first_elem_node, "list 字面量元素类型推断失败(Value 类型缺失)", "TypeError")
self.Gen.TypeGenErr.fatal_error(first_elem_node, "list 字面量元素类型推断失败(Value 类型缺失)", "TypeError")
else:
# 空 list 无元素可推断,保持默认 str(list[str])
inferred_type_name = "str"
@@ -338,25 +330,21 @@ class ExprGenConst(ExprGenBase.ExprGenBase):
return None
string.memset(new_args, 0, 8 * 32)
new_args[0] = sizet(pool_val)
new_ptr: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, spec_name, "__new__", tmp, new_args, 1, trans)
new_ptr: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__new__", tmp, new_args, 1, trans)
if new_ptr is not None:
storage_ptr = new_ptr
# 调用 __before_init__(storage_ptr)
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)
# 调用 __init__(storage_ptr, pool_val, elem_size=0)
init_args: sizet* = pool.alloc(8 * 32)
if init_args is None:
return None
if init_args is None: return None
string.memset(init_args, 0, 8 * 32)
init_args[0] = sizet(pool_val)
elem_size_val: llvmlite.Value* = llvmlite.const_int64(pool, 0)
init_args[1] = sizet(elem_size_val)
self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, spec_name, "__init__", storage_ptr, init_args, 2, trans)
self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__init__", storage_ptr, init_args, 2, trans)
# 对每个元素调用 append(storage_ptr, elem_val)
if elts_count > 0:
@@ -366,12 +354,10 @@ class ExprGenConst(ExprGenBase.ExprGenBase):
if append_args is not None:
string.memset(append_args, 0, 8 * 32)
append_args[0] = sizet(first_elem_val)
self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, spec_name, "append", storage_ptr, append_args, 1, trans)
self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "append", storage_ptr, append_args, 1, trans)
# 翻译剩余元素
i: sizet = 1
while i < elts_count:
for i in range(1, elts_count):
elem_node_i: ast.AST* = elts.get(i)
elem_val_i: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, elem_node_i, None, 0, trans)
if elem_val_i is not None:
@@ -379,8 +365,6 @@ class ExprGenConst(ExprGenBase.ExprGenBase):
if ap_args is not None:
string.memset(ap_args, 0, 8 * 32)
ap_args[0] = sizet(elem_val_i)
self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, spec_name, "append", storage_ptr, ap_args, 1, trans)
i += 1
self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "append", storage_ptr, ap_args, 1, trans)
return storage_ptr
+41 -82
View File
@@ -13,19 +13,14 @@ import lib.core.Gen.Expr.ExprGenBase as ExprGenBase
# CDefine 查找 bug:ExprGenFstr(F) 在 ExprGenMixin(M) 之前按文件序
# 编译时,跨模块 CDefine 全局表未注册 → NameError 未定义)
# ============================================================
FSTR_BUF_SIZE: t.CDefine = 1024
FSTR_SPEC_MAX: t.CDefine = 64
FSTR_FMT_MAX: t.CDefine = 64
define FSTR_BUF_SIZE = 1024
define FSTR_SPEC_MAX = 64
define FSTR_FMT_MAX = 64
# ============================================================
# ExprGenFstr - ExprGenMixin 拆分(阶段 D):f-string/格式化值翻译
#
# 继承 ExprGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExpr 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ExprGenFstr(ExprGenBase.ExprGenBase):
novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
"""f-string/格式化值翻译"""
# ============================================================
@@ -41,16 +36,13 @@ class ExprGenFstr(ExprGenBase.ExprGenBase):
node: ast.AST*,
trans: HT.Translator* = None) -> llvmlite.Value*:
"""f-string → snprintf 生成 i8* 栈缓冲"""
if node is None or builder is None or trans is None:
return None
if node is None or builder is None or trans is None: return None
js: rawptr[ast.JoinedStr] = rawptr[ast.JoinedStr](node)
if js is None or js.values is None:
return None
if js is None or js.values is None: return None
# 编译期格式串缓冲(pool 分配)
fmt_buf: str = pool.alloc(FSTR_BUF_SIZE)
if fmt_buf is None:
return None
if fmt_buf is None: return None
fmt_buf[0] = '\0'
# 运行时参数链表(Value.Next 链接,与 printf 调用一致)
@@ -62,24 +54,19 @@ class ExprGenFstr(ExprGenBase.ExprGenBase):
pn: sizet = len(parts)
for pi in range(pn):
part: ast.AST* = parts.get(pi)
if part is None:
continue
if part is None: continue
if part.kind() == ast.ASTKind.Constant:
pcn: ast.Constant* = ast.Constant*(part)
if pcn.const_kind == ast.CONST_STR and pcn.str_val is not None:
self._fstr_append_literal(fmt_buf, pcn.str_val)
continue
if part.kind() != ast.ASTKind.FormattedValue:
continue
continue
if part.kind() != ast.ASTKind.FormattedValue: continue
fv: rawptr[ast.FormattedValue] = rawptr[ast.FormattedValue](part)
if fv.value is None:
continue
val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, fv.value, None, 0, trans)
if fv.value is None: continue
val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fv.value, None, 0, trans)
if val is None:
# fail-fast:f-string 格式化值翻译失败必须终止编译,绝不在
self.Gen.TypeGenErr.fatal_error(
fv.value, "f-string 格式化值翻译失败(表达式返回 None)", "TypeError")
self.Gen.TypeGenErr.fatal_error(fv.value, "f-string 格式化值翻译失败(表达式返回 None)", "TypeError")
continue
# 确定 C 格式说明符(format_spec 优先,否则按值类型推断)
c_fmt: str = None
@@ -94,8 +81,7 @@ class ExprGenFstr(ExprGenBase.ExprGenBase):
if string.strlen(fmt_buf) + string.strlen(c_fmt) < FSTR_BUF_SIZE - 1:
string.strcat(fmt_buf, c_fmt)
# 转换参数类型(i8/i16→i32、bool→i32、f32→f64)
cast_val: llvmlite.Value* = self._fstr_cast_value(
builder, pool, val, c_fmt, fv.value, trans)
cast_val: llvmlite.Value* = self._fstr_cast_value(builder, pool, val, c_fmt, fv.value, trans)
if cast_val is None:
cast_val = val
cast_val.Next = None
@@ -125,12 +111,10 @@ class ExprGenFstr(ExprGenBase.ExprGenBase):
arg_head: llvmlite.Value* = None
arg_tail: llvmlite.Value* = None
arg_count: int = 0
val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, fv.value, None, 0, trans)
val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fv.value, None, 0, trans)
if val is None:
# fail-fast:裸 FormattedValue 翻译失败必须终止编译,绝不在
self.Gen.TypeGenErr.fatal_error(
fv.value, "f-string 格式化值翻译失败(表达式返回 None)", "TypeError")
self.Gen.TypeGenErr.fatal_error(fv.value, "f-string 格式化值翻译失败(表达式返回 None)", "TypeError")
else:
c_fmt: str = None
if fv.format_spec is not None:
@@ -142,8 +126,7 @@ class ExprGenFstr(ExprGenBase.ExprGenBase):
self.Gen.TypeGenErr.fatal_error(fv.value, "f-string 格式无法推断(值类型缺失)", "TypeError")
if string.strlen(fmt_buf) + string.strlen(c_fmt) < FSTR_BUF_SIZE - 1:
string.strcat(fmt_buf, c_fmt)
cast_val: llvmlite.Value* = self._fstr_cast_value(
builder, pool, val, c_fmt, fv.value, trans)
cast_val: llvmlite.Value* = self._fstr_cast_value(builder, pool, val, c_fmt, fv.value, trans)
if cast_val is None:
cast_val = val
cast_val.Next = None
@@ -166,20 +149,15 @@ class ExprGenFstr(ExprGenBase.ExprGenBase):
# 空 f-string(f"")→ 空字符串常量
return self.Gen.ExprGenConst.create_global_string(builder, pool, mod, "", trans)
# 格式串 → 全局字符串常量(i8*)
fmt_ptr: llvmlite.Value* = self.Gen.ExprGenConst.create_global_string(
builder, pool, mod, fmt_buf, trans)
if fmt_ptr is None:
return None
fmt_ptr: llvmlite.Value* = self.Gen.ExprGenConst.create_global_string(builder, pool, mod, fmt_buf, trans)
if fmt_ptr is None: return None
# 固定栈缓冲 [FSTR_BUF_SIZE x i8],GEP(0,0) 取 i8*
buf_ty: llvmlite.LLVMType* = llvmlite.Array(pool, i8_ty, FSTR_BUF_SIZE)
buf_alloca: llvmlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, buf_ty)
if buf_alloca is None:
return None
if buf_alloca is None: return None
zero_i32: llvmlite.Value* = llvmlite.const_int32(pool, 0)
buf_ptr: llvmlite.Value* = llvmlite.build_gep_array(
builder, buf_ty, i8_ty, buf_alloca, zero_i32)
if buf_ptr is None:
return None
buf_ptr: llvmlite.Value* = llvmlite.build_gep_array(builder, buf_ty, i8_ty, buf_alloca, zero_i32)
if buf_ptr is None: return None
# snprintf(buf, FSTR_BUF_SIZE, fmt, args...)
size_val: llvmlite.Value* = llvmlite.const_int64(pool, FSTR_BUF_SIZE)
buf_ptr.Next = size_val
@@ -192,12 +170,10 @@ class ExprGenFstr(ExprGenBase.ExprGenBase):
def _fstr_append_literal(self, fmt_buf: str,
lit: str) -> None:
"""追加字面量到格式串(% 转义为 %%)"""
if fmt_buf is None or lit is None:
return
if fmt_buf is None or lit is None: return
cur_len: sizet = string.strlen(fmt_buf)
rem: sizet = FSTR_BUF_SIZE - 1 - cur_len
if rem == 0:
return
if rem == 0: return
src_len: sizet = string.strlen(lit)
si: sizet = 0
while si < src_len and rem > 0:
@@ -238,18 +214,14 @@ class ExprGenFstr(ExprGenBase.ExprGenBase):
sk: int = spec_node.kind()
if sk == ast.ASTKind.JoinedStr:
jss: rawptr[ast.JoinedStr] = rawptr[ast.JoinedStr](spec_node)
if jss.values is None:
return None
if jss.values is None: return None
vn: sizet = len(jss.values)
for vi in range(vn):
vpart: ast.AST* = jss.values.get(vi)
if vpart is None:
continue
if vpart.kind() != ast.ASTKind.Constant:
return None
if vpart is None: continue
if vpart.kind() != ast.ASTKind.Constant: return None
vcn: ast.Constant* = ast.Constant*(vpart)
if vcn.const_kind != ast.CONST_STR or vcn.str_val is None:
return None
if vcn.const_kind != ast.CONST_STR or vcn.str_val is None: return None
if string.strlen(spec) + string.strlen(vcn.str_val) < FSTR_SPEC_MAX - 1:
string.strcat(spec, vcn.str_val)
elif sk == ast.ASTKind.Constant:
@@ -257,11 +229,9 @@ class ExprGenFstr(ExprGenBase.ExprGenBase):
if cn.const_kind != ast.CONST_STR or cn.str_val is None:
return None
string.strncpy(spec, cn.str_val, FSTR_SPEC_MAX - 1)
else:
return None
else: return None
slen: sizet = string.strlen(spec)
if slen == 0:
return None
if slen == 0: return None
# 2. 逐段解析: [fill]align / sign / # / 0 / width / , / .precision / type
pos: sizet = 0
@@ -279,8 +249,7 @@ class ExprGenFstr(ExprGenBase.ExprGenBase):
c_flags: str = pool.alloc(FSTR_FMT_MAX)
c_width: str = pool.alloc(32)
c_prec: str = pool.alloc(32)
if c_flags is None or c_width is None or c_prec is None:
return None
if c_flags is None or c_width is None or c_prec is None: return None
c_flags[0] = '\0'
c_width[0] = '\0'
c_prec[0] = '\0'
@@ -329,30 +298,24 @@ class ExprGenFstr(ExprGenBase.ExprGenBase):
if pos < slen:
fmt_type = spec[pos]
pos += 1
if pos != slen:
return None # 多余字符无法解析
if pos != slen: return None # 多余字符无法解析
# 3. 长度修饰(按值类型位宽)
len_mod: str = pool.alloc(4)
if len_mod is None:
return None
if len_mod is None: return None
len_mod[0] = '\0'
ibits: int = self.Gen.ExprGenBase.get_llvm_type_bits(val.Ty)
# 32 位**不写**长度修饰符(N14):`{x:08X}` 的实参是 i32,此前推导出
# `l` → 格式串 `%08lX`(long)与实参宽度不符(LP64 下 printf 按 64 位
# 读参 → 变参错位)。与同文件无 spec 路径 `_fstr_infer_c_fmt`(32 位用
# `%u/%d`)以及 TPC 侧 HandlesExprFormat.py 保持一致。
if ibits == 64:
string.strcpy(len_mod, "ll")
elif ibits == 16:
string.strcpy(len_mod, "h")
elif ibits == 8:
string.strcpy(len_mod, "hh")
if ibits == 64: string.strcpy(len_mod, "ll")
elif ibits == 16: string.strcpy(len_mod, "h")
elif ibits == 8: string.strcpy(len_mod, "hh")
# 4. 组装 C 格式串
out: str = pool.alloc(FSTR_FMT_MAX)
if out is None:
return None
if out is None: return None
out[0] = '\0'
string.strcat(out, "%")
string.strcat(out, c_flags)
@@ -411,18 +374,14 @@ class ExprGenFstr(ExprGenBase.ExprGenBase):
arg_node: ast.AST*,
trans: HT.Translator*) -> str:
"""无 format_spec 时按值类型推断 C printf 格式(对齐 TPC 无 spec 分支,带 % 前缀)"""
if val is None or pool is None:
return None
if val is None or pool is None: return None
out: str = pool.alloc(16)
if out is None:
return None
if out is None: return None
out[0] = '\0'
ibits: int = self.Gen.ExprGenBase.get_llvm_type_bits(val.Ty)
fbits: int = self.Gen.ExprGenBase.get_llvm_float_bits(val.Ty)
if ibits == 1:
return "%d" # bool
if ibits == 8:
return "%c" # 字符
if ibits == 1: return "%d" # bool
if ibits == 8: return "%c" # 字符
if ibits != 0:
if self.Gen.ExprGenOps._node_type_unsigned(pool, arg_node, trans) != 0:
if ibits == 64:
+24 -64
View File
@@ -15,9 +15,9 @@ import lib.core.Gen.Expr.ExprGenBase as ExprGenBase
# DOC_KEY_SZ: key "{module_sha1}.{symbol}" 缓冲宽度
# DOC_VAL_SZ: docstring 内容缓冲宽度
# ============================================================
DOC_MAX: t.CDefine = 512
DOC_KEY_SZ: t.CDefine = 192
DOC_VAL_SZ: t.CDefine = 4096
define DOC_MAX = 512
define DOC_KEY_SZ = 192
define DOC_VAL_SZ = 4096
# ============================================================
# f-string 翻译常量(对齐 TPC HandlesExprFormat)
@@ -26,37 +26,22 @@ DOC_VAL_SZ: t.CDefine = 4096
# FSTR_SPEC_MAX: 编译期 format_spec 解析缓冲宽度
# FSTR_FMT_MAX: 编译期 C printf 格式串缓冲宽度
# ============================================================
FSTR_BUF_SIZE: t.CDefine = 1024
FSTR_SPEC_MAX: t.CDefine = 64
FSTR_FMT_MAX: t.CDefine = 64
define FSTR_BUF_SIZE = 1024
define FSTR_SPEC_MAX = 64
define FSTR_FMT_MAX = 64
# ============================================================
# ExprGenMixin - 表达式处理 Mixin(对象化 P3,wiki/14-oo-refactor.md)
#
# 从 HandlesExpr.vp(48 函数,无全局状态)与 HandlesExprOps.vp
# 迁移:模块级纯函数 → 类方法(self 替代,参数保留含 builder/pool)。
#
# 迁移原则(与 P2 一致,行为零变化):
# 1. 方法保留原函数签名(含 builder/pool 首参),仅函数体内
# 本模块函数调用改为 self.xxx(...)
# 2. 外部模块调用(HandlesExprCall.xxx / HandlesType.xxx 等)保留模块前缀
# 3. HandlesExpr.vp / HandlesExprOps.vp 原函数保留为"委托":本地
# 模块级单例 _g_gen(BuildPipeline/main 注入)cast 成 Generator 类型
# 4. ExprHandle 类保留在 HandlesExpr.vp(translator handler 模式)
#
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整)。
# ============================================================
# ============================================================
# ExprGenMixin - 表达式/常量/下标/属性访问/运算符
# ============================================================
@t.NoVTable
class ExprGenMixin(ExprGenBase.ExprGenBase):
novirtual class ExprGenMixin(ExprGenBase.ExprGenBase):
"""表达式处理 Mixin(纯方法化迁移,无状态字段)"""
# ============================================================
# 翻译值表达式(RHS 分派)— 模块级版本
# ============================================================
@@ -78,11 +63,9 @@ class ExprGenMixin(ExprGenBase.ExprGenBase):
"""
if trans is not None:
if trans.TranslateDepth >= HT.TRANSLATE_MAX_DEPTH:
self.Gen.TypeGenErr.fatal_error(
node, "表达式翻译嵌套过深(疑似 AST 自引用环或翻译 bug)", "RecursionError")
self.Gen.TypeGenErr.fatal_error(node, "表达式翻译嵌套过深(疑似 AST 自引用环或翻译 bug)", "RecursionError")
trans.TranslateDepth += 1
rv: llvmlite.Value* = self._translate_value_impl(
builder, pool, mod, node, funcs_ptr, func_count, trans, target_ty, use_ctx)
rv: llvmlite.Value* = self._translate_value_impl(builder, pool, mod, node, funcs_ptr, func_count, trans, target_ty, use_ctx)
if trans is not None:
trans.TranslateDepth -= 1
return rv
@@ -103,40 +86,19 @@ class ExprGenMixin(ExprGenBase.ExprGenBase):
if k == ast.ASTKind.Constant:
rv: llvmlite.Value* = self.Gen.ExprGenConst.translate_constant(builder, pool, mod, node, trans, target_ty)
return rv
elif k == ast.ASTKind.Name:
# target_ty(使用处类型:赋值目标 / 形参 / 返回)与 use_ctx(真实站点
# 种类,仅供报文)下传给裸名翻译,供 CDefine 常量按使用处宽度物化;
# 非常量名不受影响(见 translate_name_value)。
return self.Gen.ExprGenName.translate_name_value(
builder, pool, node, trans, target_ty, use_ctx)
elif k == ast.ASTKind.BinOp:
return self.Gen.ExprGenOps.translate_binop(pool, builder, mod, node, trans)
elif k == ast.ASTKind.Call:
return self.Gen.CallGen.translate_call(pool, builder, mod, node, funcs_ptr, func_count, trans)
elif k == ast.ASTKind.Compare:
return self.Gen.ExprGenOps.translate_compare(builder, pool, mod, node, trans)
elif k == ast.ASTKind.UnaryOp:
return self.Gen.ExprGenOps.translate_unaryop(builder, pool, mod, node, trans)
elif k == ast.ASTKind.BoolOp:
return self.Gen.ExprGenOps.translate_boolop(builder, pool, mod, node, funcs_ptr, func_count, trans)
elif k == ast.ASTKind.Subscript:
return self.Gen.ExprGenName.translate_subscript(builder, pool, mod, node, trans)
elif k == ast.ASTKind.Attribute:
return self.Gen.ExprGenAttr.translate_attribute(builder, pool, mod, node, trans)
elif k == ast.ASTKind.List:
return self.Gen.ExprGenConst.translate_list_literal(builder, pool, mod, node, None, trans)
elif k == ast.ASTKind.IfExp:
return self.Gen.ExprGenOps.translate_ifexp(builder, pool, mod, node, trans)
elif k == ast.ASTKind.Lambda:
# 模块级委托:translate_lambda 定义在 FuncGenMixin(跨 Mixin
# 方法不能 self. 直接调用,见 HandlesExpr.translate_lambda)
return self.Gen.FuncGen.translate_lambda(builder, pool, mod, node, trans)
elif k == ast.ASTKind.JoinedStr:
return self.Gen.ExprGenFstr.translate_joined_str(builder, pool, mod, node, trans)
elif k == ast.ASTKind.FormattedValue:
# 解析器对 f"{expr:spec}"(单 FormattedValue 无字面量)返回裸 FormattedValue
# 而非 JoinedStr(见 ast/parser.vp _parse_fstring),需单独翻译
return self.Gen.ExprGenFstr.translate_formatted_value(builder, pool, mod, node, trans)
elif k == ast.ASTKind.Name: return self.Gen.ExprGenName.translate_name_value(builder, pool, node, trans, target_ty, use_ctx)
elif k == ast.ASTKind.BinOp: return self.Gen.ExprGenOps.translate_binop(pool, builder, mod, node, trans)
elif k == ast.ASTKind.Call: return self.Gen.CallGen.translate_call(pool, builder, mod, node, funcs_ptr, func_count, trans)
elif k == ast.ASTKind.Compare: return self.Gen.ExprGenOps.translate_compare(builder, pool, mod, node, trans)
elif k == ast.ASTKind.UnaryOp: return self.Gen.ExprGenOps.translate_unaryop(builder, pool, mod, node, trans)
elif k == ast.ASTKind.BoolOp: return self.Gen.ExprGenOps.translate_boolop(builder, pool, mod, node, funcs_ptr, func_count, trans)
elif k == ast.ASTKind.Subscript: return self.Gen.ExprGenName.translate_subscript(builder, pool, mod, node, trans)
elif k == ast.ASTKind.Attribute: return self.Gen.ExprGenAttr.translate_attribute(builder, pool, mod, node, trans)
elif k == ast.ASTKind.List: return self.Gen.ExprGenConst.translate_list_literal(builder, pool, mod, node, None, trans)
elif k == ast.ASTKind.IfExp: return self.Gen.ExprGenOps.translate_ifexp(builder, pool, mod, node, trans)
elif k == ast.ASTKind.Lambda: return self.Gen.FuncGen.translate_lambda(builder, pool, mod, node, trans)
elif k == ast.ASTKind.JoinedStr: return self.Gen.ExprGenFstr.translate_joined_str(builder, pool, mod, node, trans)
elif k == ast.ASTKind.FormattedValue: return self.Gen.ExprGenFstr.translate_formatted_value(builder, pool, mod, node, trans)
elif k == ast.ASTKind.Await:
# 协程 await(TPV-M1):await 目标是 async 函数调用时内联翻译
# (子帧创建 + resume 到 DONE + 取子帧 ret 存父帧 await 槽 + 父挂起),
@@ -158,10 +120,8 @@ class ExprGenMixin(ExprGenBase.ExprGenBase):
# 全代码库无调用点使用;按 C 语义视为单目解引用(*ptr → load pointee,
# 对齐 UnaryOp(Deref))。构造 Deref UnaryOp 复用既有翻译/错误路径。
st: rawptr[ast.Starred] = rawptr[ast.Starred](node)
if st is None or st.value is None:
return None
if st is None or st.value is None: return None
deref_node: ast.AST* = ast.UnaryOp(pool, ast.OpKind.Deref, st.value)
if deref_node is None:
return None
if deref_node is None: return None
return self.Gen.ExprGenOps.translate_unaryop(builder, pool, mod, deref_node, trans)
return None
+135 -285
View File
@@ -10,19 +10,14 @@ import viperlib
import lib.core.Gen.Translator as HT
import lib.Stub.StubMerger.StubMergerStore as StubMergerStore
import lib.core.Gen.Expr.ExprGenBase as ExprGenBase
import lib.core.Gen.GenApi as GenApi
# ============================================================
# ExprGenName - ExprGenMixin 拆分(阶段 D):Name/Subscript/下标访问
#
# 继承 ExprGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExpr 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ExprGenName(ExprGenBase.ExprGenBase):
novirtual class ExprGenName(ExprGenBase.ExprGenBase):
"""Name/Subscript/下标访问"""
def _cut_from_import_mod(self, pool: memhub.MemBuddy*,
@@ -36,16 +31,13 @@ class ExprGenName(ExprGenBase.ExprGenBase):
对齐 ExprGenCdef._lookup_cross_module_cdefine 的截断逻辑)。
截断到空格/冒号/NUL;raw 无效返回 None。
"""
if raw is None:
return None
if raw is None: return None
mbl_c: sizet = 0
while raw[mbl_c] != ' ' and raw[mbl_c] != '\0' and raw[mbl_c] != ':':
mbl_c += 1
if mbl_c == 0:
return None
if mbl_c == 0: return None
buf_c: str = pool.alloc(mbl_c + 1)
if buf_c is None:
return None
if buf_c is None: return None
string.strncpy(buf_c, raw, mbl_c)
buf_c[mbl_c] = '\0'
return buf_c
@@ -71,11 +63,9 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# "use of undefined value '@.str.{sha1}.N'(SysLibTest _cleanup 根因)"
mod: llvmlite.LLVMModule* = trans.Module
nm: ast.Name* = ast.Name*(node)
if nm is None:
return None
if nm is None: return None
nm_id: str = nm.id
if nm_id is None:
return None
if nm_id is None: return None
# CDefine 编译期常量:返回常量值(浮点 CDefine → double 常量,整数 → i32;否则 double 函数里 return 会生成 ret i32 0 报错)。注意同名变量优先——当前作用域已存在变量时不得被 CDefine 表条目遮蔽(vpi stub 注入会把依赖模块的 CDefine 注册进导入方表,可能误解析局部变量为常量),守卫与下方跨模块 CDefine 查找的 lookup_var 检查一致
cdef_val_d: double = self.Gen.TypeGenCDef.lookup_cdefine_double(nm_id)
if self.Gen.TypeGenCDef.is_cdefine_found() != 0:
@@ -95,8 +85,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# 使用处宽度(经 translate_value 的 target_ty 下传;站点种类由
# use_ctx 携带,仅供报文使用):
# 更宽 ⇒ 就地升宽物化;更窄 ⇒ fail-fast;取不到 ⇒ 既有默认 32/64。
uw_val: llvmlite.Value* = self.Gen.ExprGenCdef.cdefine_use_width_value(
pool, node, nm_id, cdef_val_c, target_ty, use_ctx)
uw_val: llvmlite.Value* = self.Gen.ExprGenCdef.cdefine_use_width_value(pool, node, nm_id, cdef_val_c, target_ty, use_ctx)
if uw_val is not None:
return uw_val
return self.Gen.ExprGenCdef._const_int_for_cdefine(pool, cdef_val_c)
@@ -114,8 +103,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# 文件,且多 includes 目录下还可能触发 XMOD-CD 误报
# (ExprGenCdef._build_source_path_from_sha1 拼错路径)。
if self.Gen.VarGen.lookup_var(trans.SymTab, nm_id) is None:
cdef_val: int64 = self.Gen.ExprGenCdef._lookup_cross_module_cdefine(
pool, nm_id, trans._from_imports, trans._imported_modules, 0, node)
cdef_val: int64 = self.Gen.ExprGenCdef._lookup_cross_module_cdefine(pool, nm_id, trans._from_imports, trans._imported_modules, 0, node)
if self.Gen.TypeGenCDef.is_cdefine_found() != 0:
if self.Gen.TypeGenCDef.is_cdefine_str() != 0:
cdef_sv2: str = self.Gen.TypeGenCDef.lookup_cdefine_string(nm_id)
@@ -128,8 +116,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
if self.Gen.TypeGenCDef.is_cdefine_double() != 0:
return llvmlite.ConstFloat(pool, llvmlite.Double(pool), dchk_nm)
# 使用处宽度同口径(跨模块 CDefine)
uw_x: llvmlite.Value* = self.Gen.ExprGenCdef.cdefine_use_width_value(
pool, node, nm_id, cdef_val, target_ty, use_ctx)
uw_x: llvmlite.Value* = self.Gen.ExprGenCdef.cdefine_use_width_value(pool, node, nm_id, cdef_val, target_ty, use_ctx)
if uw_x is not None:
return uw_x
return self.Gen.ExprGenCdef._const_int_for_cdefine(pool, cdef_val)
@@ -139,21 +126,17 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# i64 全局、非宏,语义同 C 的 extern size_t PYI_BUF_SIZE)。from-import
# 确认名称确实来自某模块后,按后缀匹配查找该全局并加载。
if trans is not None and trans._from_imports is not None:
fi_mod_raw: str = self.Gen.ImportsGen.lookup_from_import(
trans._from_imports, nm_id, 0)
fi_mod_raw: str = self.Gen.ImportsGen.lookup_from_import(trans._from_imports, nm_id, 0)
if fi_mod_raw is not None:
# 带源模块 SHA1 前缀精确查找,避免多模块同名全局后缀匹配串扰。
# fi_mod_raw 非 NUL 结尾,先截断再查 SHA1(否则整串查不到退化裸名)
fi_mod_cut: str = self._cut_from_import_mod(pool, fi_mod_raw)
if fi_mod_cut is None:
fi_mod_cut = fi_mod_raw
fi_gv_q: str = self.Gen.FuncGenBase._mangle_name_with_sha1(
StubMergerStore.LookupSha1ByModName(fi_mod_cut), nm_id)
fi_gv: llvmlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(
trans.Module, fi_gv_q)
fi_gv_q: str = self.Gen.FuncGenBase._mangle_name_with_sha1(StubMergerStore.LookupSha1ByModName(fi_mod_cut), nm_id)
fi_gv: llvmlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(trans.Module, fi_gv_q)
if fi_gv is not None and fi_gv.Ty is not None:
fi_ref: llvmlite.Value* = self.Gen.ExprGenAttr.make_global_ref(
pool, fi_gv.Name, fi_gv.Ty)
fi_ref: llvmlite.Value* = self.Gen.ExprGenAttr.make_global_ref(pool, fi_gv.Name, fi_gv.Ty)
if fi_ref is not None and fi_ref.Ty is not None:
fi_pty: llvmlite.LLVMType* = fi_ref.Ty.Pointee
if fi_pty is not None:
@@ -168,16 +151,14 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# global 变量:从模块作用域查找(global 声明优先级最高)
if trans is not None:
if GenApi.is_global_name(trans, nm_id) != 0:
mod_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_module_var(
trans.SymTab, nm_id)
mod_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm_id)
if mod_alloca is not None:
load_ty: llvmlite.LLVMType* = None
if mod_alloca.Ty is not None:
load_ty = mod_alloca.Ty.Pointee
if load_ty is None:
# fail-fast:global 变量存储类型缺失,立即终止编译(暴露上游根因)
self.Gen.TypeGenErr.fatal_error(
node, f"变量 '{nm_id}' 存储类型缺失", "TypeError")
self.Gen.TypeGenErr.fatal_error(node, f"变量 '{nm_id}' 存储类型缺失", "TypeError")
# 全局数组(如 pyzlib.pyzlib_error_msg: CArray[char, 512]):
# 按 C 语义衰减为基址返回(对齐下方局部数组分支 L3383-3388)。
# 否则 load [512 x i8] 数组值当 i8* 传 → set_error 的 strncpy
@@ -191,8 +172,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# t.CVolatile 全局:load 带 volatile 限定符(禁优化器消除重复读)
vol_g: int = 0
if trans is not None:
ve_g: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, nm_id)
ve_g: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm_id)
vol_g = self.Gen.VarGen.var_is_volatile(ve_g)
return llvmlite.build_load(builder, load_ty, mod_alloca, vol_g)
@@ -218,8 +198,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
load_ty = alloca.Ty.Pointee
if load_ty is None:
# fail-fast:局部变量存储类型缺失,立即终止编译(暴露上游根因)
self.Gen.TypeGenErr.fatal_error(
node, f"变量 '{nm_id}' 存储类型缺失", "TypeError")
self.Gen.TypeGenErr.fatal_error(node, f"变量 '{nm_id}' 存储类型缺失", "TypeError")
# 结构体值变量(alloca 类型为 Struct,如 `x: Cls | t.CPtr`):
# 按"对象即指针"语义返回其地址(alloca 指针),而非加载结构体值。
# 结构体值无法参与 ptrtoint/方法调用等地址相关操作,加载值会导致
@@ -236,8 +215,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# t.CVolatile 局部变量:load 带 volatile 限定符
vol_l: int = 0
if trans is not None:
ve_l: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, nm_id)
ve_l: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm_id)
vol_l = self.Gen.VarGen.var_is_volatile(ve_l)
return llvmlite.build_load(builder, load_ty, alloca, vol_l)
@@ -246,8 +224,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# ② 模块别名/模块函数引用之前(会话名不得被 printf 等本模块 declare 抢走)。
# 非 REPL(trans.ReplCtx is None)时 repl_try_read 立即返回 None ⇒ 原路径逐字不变。
if trans is not None and trans.ReplCtx is not None:
sess_val: llvmlite.Value* = self.Gen.VarGen.repl_try_read(
trans, nm_id, node)
sess_val: llvmlite.Value* = self.Gen.VarGen.repl_try_read(trans, nm_id, node)
if sess_val is not None:
return sess_val
@@ -268,8 +245,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# 最终打印出 `declare void @()` 空名函数。正确做法:按 Function 的
# RetTy/Params 构造真实函数类型,用 new_value 包装成普通 Value 再 bitcast。
if trans is not None and trans.Module is not None:
fn_ref: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(
trans.Module, nm_id)
fn_ref: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(trans.Module, nm_id)
if fn_ref is not None:
fn_name: str = llvmlite.function_get_name(fn_ref)
if fn_name is None:
@@ -278,8 +254,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
fn_ret_ty: llvmlite.LLVMType* = llvmlite.function_get_ret_ty(fn_ref)
if fn_ret_ty is None:
# fail-fast:函数返回类型缺失,无法构造函数指针(暴露上游根因)
self.Gen.TypeGenErr.fatal_error(
node, f"函数 '{nm_id}' 返回类型缺失,无法构造函数指针", "TypeError")
self.Gen.TypeGenErr.fatal_error(node, f"函数 '{nm_id}' 返回类型缺失,无法构造函数指针", "TypeError")
fn_pp: llvmlite.Param* = llvmlite.function_get_param_head(fn_ref)
fn_first_node: llvmlite.Function* = None
fn_prev_node: llvmlite.Function* = None
@@ -295,8 +270,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
fn_prev_node = fn_pn
fn_pcount += 1
fn_pp = llvmlite.param_get_next(fn_pp)
fn_ty: llvmlite.LLVMType* = llvmlite.Func(
pool, fn_ret_ty, fn_first_node, fn_pcount)
fn_ty: llvmlite.LLVMType* = llvmlite.Func(pool, fn_ret_ty, fn_first_node, fn_pcount)
if fn_ty is None:
return None
# 构造函数指针 Value(new_value 包装,避免触碰 Function.Next)
@@ -313,8 +287,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
else:
viperlib.snprintf(fn_ref_name, 256, "@%s", fn_name)
llvmlite.value_set_name(fn_ref_v, fn_ref_name)
fn_i8ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(
pool, llvmlite.Int8(pool))
fn_i8ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
return llvmlite.build_bitcast(builder, fn_ref_v, fn_i8ptr_ty)
# ============================================================
@@ -329,8 +302,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
if trans is not None and trans._from_imports is not None:
if trans.Module is not None:
# 是 from-import 名称(禁用 star 回退,避免误归 star 模块)
fi_mod: str = self.Gen.ImportsGen.lookup_from_import(
trans._from_imports, nm_id, 0)
fi_mod: str = self.Gen.ImportsGen.lookup_from_import(trans._from_imports, nm_id, 0)
if fi_mod is not None:
# 排除已注册类名/枚举名:这些是类型,不作为全局变量值读取
fi_is_class: int = 0
@@ -341,8 +313,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
fi_is_class = 1
if fi_is_class == 0:
fi_gname: str = nm_id
fi_orig: str = self.Gen.ImportsGen.lookup_from_import_original(
trans._from_imports, nm_id)
fi_orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, nm_id)
if fi_orig is not None:
og_len_fi: sizet = 0
while fi_orig[og_len_fi] != ' ' and fi_orig[og_len_fi] != '\0':
@@ -361,10 +332,8 @@ class ExprGenName(ExprGenBase.ExprGenBase):
fi_mod_cut2: str = self._cut_from_import_mod(pool, fi_mod)
if fi_mod_cut2 is None:
fi_mod_cut2 = fi_mod
gv_fi_q: str = self.Gen.FuncGenBase._mangle_name_with_sha1(
StubMergerStore.LookupSha1ByModName(fi_mod_cut2), fi_gname)
gv_fi: llvmlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(
trans.Module, gv_fi_q)
gv_fi_q: str = self.Gen.FuncGenBase._mangle_name_with_sha1(StubMergerStore.LookupSha1ByModName(fi_mod_cut2), fi_gname)
gv_fi: llvmlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(trans.Module, gv_fi_q)
ref_fi: llvmlite.Value* = None
if gv_fi is not None and gv_fi.Ty is not None:
ref_fi = self.Gen.ExprGenAttr.make_global_ref(pool, gv_fi.Name, gv_fi.Ty)
@@ -624,8 +593,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
s_val_ptr: llvmlite.Value* = self.coerce_to_type(builder, rhs_val, s_elem_ty, node)
if s_val_ptr is None:
return 0
s_ep: llvmlite.Value* = llvmlite.build_bitcast(
builder, s_addr, llvmlite.Ptr(pool, s_elem_ty))
s_ep: llvmlite.Value* = llvmlite.build_bitcast(builder, s_addr, llvmlite.Ptr(pool, s_elem_ty))
if s_ep is not None:
llvmlite.build_store(builder, s_val_ptr, s_ep)
return 0
@@ -695,24 +663,17 @@ class ExprGenName(ExprGenBase.ExprGenBase):
return None
match nl_ty:
case llvmlite.LLVMType.Array(elem_ty_nl, _cnt_nl):
arr_ptr_nl: llvmlite.Value* = llvmlite.build_bitcast(
builder, raw_nl, llvmlite.Ptr(pool, nl_ty))
arr_ptr_nl: llvmlite.Value* = llvmlite.build_bitcast(builder, raw_nl, llvmlite.Ptr(pool, nl_ty))
if arr_ptr_nl is None:
return None
return llvmlite.build_gep_array(
builder, nl_ty, elem_ty_nl, arr_ptr_nl,
self._zext_index_to_i32(builder, idx_val))
return llvmlite.build_gep_array(builder, nl_ty, elem_ty_nl, arr_ptr_nl, self._zext_index_to_i32(builder, idx_val))
case llvmlite.LLVMType.Ptr(inner_nl):
arr_ptr_nl2: llvmlite.Value* = llvmlite.build_bitcast(
builder, raw_nl, llvmlite.Ptr(pool, nl_ty))
if arr_ptr_nl2 is None:
return None
arr_ptr_nl2: llvmlite.Value* = llvmlite.build_bitcast(builder, raw_nl, llvmlite.Ptr(pool, nl_ty))
if arr_ptr_nl2 is None: return None
return llvmlite.build_gep(builder, inner_nl, arr_ptr_nl2, idx_val)
case _:
arr_ptr_nl3: llvmlite.Value* = llvmlite.build_bitcast(
builder, raw_nl, llvmlite.Ptr(pool, nl_ty))
if arr_ptr_nl3 is None:
return None
arr_ptr_nl3: llvmlite.Value* = llvmlite.build_bitcast(builder, raw_nl, llvmlite.Ptr(pool, nl_ty))
if arr_ptr_nl3 is None: return None
return llvmlite.build_gep(builder, nl_ty, arr_ptr_nl3, idx_val)
return None
# ============================================================
@@ -741,16 +702,11 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# p.entry 垃圾 → 用户进程 iretq 到垃圾地址 → PF)。
if sub.slice is not None and sub.slice.kind() == ast.ASTKind.Slice:
slc: rawptr[ast.Slice] = rawptr[ast.Slice](sub.slice)
base_v: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, sub.value, None, 0, trans)
if base_v is None:
return None
if slc.lower is None:
return base_v
start_v: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, slc.lower, None, 0, trans)
if start_v is None:
return None
base_v: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub.value, None, 0, trans)
if base_v is None: return None
if slc.lower is None: return base_v
start_v: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, slc.lower, None, 0, trans)
if start_v is None: return None
i64_sc: llvmlite.LLVMType* = llvmlite.Int64(pool)
start_w: llvmlite.Value* = start_v
if start_v.Ty is not None:
@@ -763,34 +719,26 @@ class ExprGenName(ExprGenBase.ExprGenBase):
return llvmlite.build_gep(builder, i8_sc, base_v, start_w)
# 翻译索引
idx_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, sub.slice, None, 0, trans)
if idx_val is None:
return None
idx_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub.slice, None, 0, trans)
if idx_val is None: return None
# 嵌套下标读取: a[i][j] —— 递归取内层指针后 load
# (与 get_subscript_ptr 嵌套分支对称;如 gfx.vp 的
# a.m[i][k] * b.m[k][j],内层 translate_value 会把行加载为
# Array 值(非指针)→ 通用路径失败 → "rhs 翻译失败")
if sub.value is not None and sub.value.kind() == ast.ASTKind.Subscript:
inner_ptr_r: llvmlite.Value* = self.get_subscript_ptr(
builder, pool, mod, sub.value, trans)
if inner_ptr_r is None or inner_ptr_r.Ty is None:
return None
inner_ptr_r: llvmlite.Value* = self.get_subscript_ptr(builder, pool, mod, sub.value, trans)
if inner_ptr_r is None or inner_ptr_r.Ty is None: return None
inner_elem_r: llvmlite.LLVMType* = inner_ptr_r.Ty.Pointee
if inner_elem_r is None:
return None
if inner_elem_r is None: return None
match inner_elem_r:
case llvmlite.LLVMType.Array(arr_ie_r, _):
elem_ptr_r: llvmlite.Value* = llvmlite.build_gep_array(
builder, inner_elem_r, arr_ie_r, inner_ptr_r,
self._zext_index_to_i32(builder, idx_val))
elem_ptr_r: llvmlite.Value* = llvmlite.build_gep_array(builder, inner_elem_r, arr_ie_r, inner_ptr_r, self._zext_index_to_i32(builder, idx_val))
if elem_ptr_r is not None:
return llvmlite.build_load(builder, arr_ie_r, elem_ptr_r)
return None
case _:
elem_ptr_r2: llvmlite.Value* = llvmlite.build_gep(
builder, inner_elem_r, inner_ptr_r, idx_val)
elem_ptr_r2: llvmlite.Value* = llvmlite.build_gep(builder, inner_elem_r, inner_ptr_r, idx_val)
if elem_ptr_r2 is not None:
return llvmlite.build_load(builder, inner_elem_r, elem_ptr_r2)
return None
@@ -802,14 +750,12 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# rawptr[t.CVolatile | T] 变量(volatile 指针指向物):本分支内
# 的**元素 load**(p[i] 解引用)带 volatile;仅读取指针值自身的
# load(alloca → 指针值)不带(那是指针变量而非所指物)。
vol_sub_rd: int = self.Gen.VarGen.var_pointee_is_volatile(
self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id))
vol_sub_rd: int = self.Gen.VarGen.var_pointee_is_volatile(self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id))
# nonlocal 数组/指针:从 env 读共享堆地址(提升函数内不能
# lookup_var 外层 alloca——SSA 编号跨函数错乱崩溃)
# 读路径:元素指针 load 出元素值
if GenApi.is_nonlocal_name(trans, nm.id) != 0:
nl_ptr_r: llvmlite.Value* = self._nonlocal_subscript_ptr(
builder, pool, trans, nm.id, idx_val)
nl_ptr_r: llvmlite.Value* = self._nonlocal_subscript_ptr(builder, pool, trans, nm.id, idx_val)
if nl_ptr_r is not None and nl_ptr_r.Ty is not None:
nl_elem_ty: llvmlite.LLVMType* = nl_ptr_r.Ty.Pointee
if nl_elem_ty is not None:
@@ -825,9 +771,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
match pointee:
case llvmlite.LLVMType.Array(elem_ty, count):
# 数组遍历: getelementptr [N x elem_ty], ... , i32 0, i32 %idx
elem_ptr: llvmlite.Value* = llvmlite.build_gep_array(
builder, pointee, elem_ty, alloca,
self._zext_index_to_i32(builder, idx_val))
elem_ptr: llvmlite.Value* = llvmlite.build_gep_array(builder, pointee, elem_ty, alloca, self._zext_index_to_i32(builder, idx_val))
if elem_ptr is not None:
return llvmlite.build_load(builder, elem_ty, elem_ptr)
return None
@@ -839,21 +783,15 @@ class ExprGenName(ExprGenBase.ExprGenBase):
#(对齐 Ptr(Ptr(list)) 变量路径,修复 parts[0] 崩溃)
if lsn_v is not None:
if string.strstr(lsn_v, "list[") is not None:
elem_addr_v: llvmlite.Value* = \
self.list_getitem_inline(
builder, pool, alloca, idx_val, node)
elem_addr_v: llvmlite.Value* = self.list_getitem_inline(builder, pool, alloca, idx_val, node)
if elem_addr_v is not None:
elem_ty_v: llvmlite.LLVMType* = \
self._list_elem_type_from_name(pool, lsn_v)
elem_ty_v: llvmlite.LLVMType* = self._list_elem_type_from_name(pool, lsn_v)
if elem_ty_v is not None:
elem_ptr_ty_v: llvmlite.LLVMType* = \
llvmlite.Ptr(pool, elem_ty_v)
elem_ptr_ty_v: llvmlite.LLVMType* = llvmlite.Ptr(pool, elem_ty_v)
casted_v: llvmlite.Value* = \
llvmlite.build_bitcast(
builder, elem_addr_v, elem_ptr_ty_v)
llvmlite.build_bitcast(builder, elem_addr_v, elem_ptr_ty_v)
if casted_v is not None:
return llvmlite.build_load(
builder, elem_ty_v, casted_v)
return llvmlite.build_load(builder, elem_ty_v, casted_v)
return None
case llvmlite.LLVMType.Ptr(inner_ty):
# 检查 inner_ty 是否是 list[T] 类型(泛型类不注册 struct)
@@ -867,23 +805,17 @@ class ExprGenName(ExprGenBase.ExprGenBase):
if list_struct_name is not None:
if string.strstr(list_struct_name, "list[") is not None:
# list[T] 类型: 内联生成 __getitem__ 逻辑
ptr_val_list: llvmlite.Value* = llvmlite.build_load(
builder, pointee, alloca)
ptr_val_list: llvmlite.Value* = llvmlite.build_load(builder, pointee, alloca)
if ptr_val_list is not None:
elem_addr_list: llvmlite.Value* = self.list_getitem_inline(
builder, pool, ptr_val_list, idx_val, node)
elem_addr_list: llvmlite.Value* = self.list_getitem_inline(builder, pool, ptr_val_list, idx_val, node)
if elem_addr_list is not None:
# 根据类型名提取元素类型,bitcast 后 load
elem_ty_list: llvmlite.LLVMType* = self._list_elem_type_from_name(
pool, list_struct_name)
elem_ty_list: llvmlite.LLVMType* = self._list_elem_type_from_name(pool, list_struct_name)
if elem_ty_list is not None:
elem_ptr_ty_list: llvmlite.LLVMType* = llvmlite.Ptr(
pool, elem_ty_list)
casted_addr_list: llvmlite.Value* = llvmlite.build_bitcast(
builder, elem_addr_list, elem_ptr_ty_list)
elem_ptr_ty_list: llvmlite.LLVMType* = llvmlite.Ptr(pool, elem_ty_list)
casted_addr_list: llvmlite.Value* = llvmlite.build_bitcast(builder, elem_addr_list, elem_ptr_ty_list)
if casted_addr_list is not None:
return llvmlite.build_load(
builder, elem_ty_list, casted_addr_list)
return llvmlite.build_load(builder, elem_ty_list, casted_addr_list)
return None
# inner_ty 是 Ptr 说明 alloca.Ty 是三重指针 Ptr(Ptr(Ptr(...))),
# 即 X|t.CPtr 当 X 本身是指针类型 (如 T=AST|t.CPtr, T|t.CPtr=AST**)。
@@ -892,11 +824,9 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# 对比 HashTable|t.CPtr: alloca.Ty=HashTable**, inner_ty=Struct(HashTable)
# (非 Ptr), 仍走下面的方法调用转发路径。
if self.is_ptr_type(inner_ty) != 0:
ptr_val_pp: llvmlite.Value* = llvmlite.build_load(
builder, pointee, alloca)
ptr_val_pp: llvmlite.Value* = llvmlite.build_load(builder, pointee, alloca)
if ptr_val_pp is not None:
elem_ptr_pp: llvmlite.Value* = llvmlite.build_gep(
builder, inner_ty, ptr_val_pp, idx_val)
elem_ptr_pp: llvmlite.Value* = llvmlite.build_gep(builder, inner_ty, ptr_val_pp, idx_val)
if elem_ptr_pp is not None:
# volatile 指针指向物:解引用 load 带 volatile
return llvmlite.build_load(builder, inner_ty, elem_ptr_pp, vol_sub_rd)
@@ -911,23 +841,18 @@ class ExprGenName(ExprGenBase.ExprGenBase):
if gi_lookup_rd is not None:
viperlib.snprintf(gi_lookup_rd, 128, "%s.__getitem__", cls_nm_rd_ptr)
if self.Gen.CallGenBase.find_func_in_module(mod, gi_lookup_rd) is not None:
obj_ptr_rd: llvmlite.Value* = llvmlite.build_load(
builder, pointee, alloca)
obj_ptr_rd: llvmlite.Value* = llvmlite.build_load(builder, pointee, alloca)
if not (obj_ptr_rd is None):
arg_vals_rd_p: sizet* = pool.alloc(8)
if not (arg_vals_rd_p is None):
arg_vals_rd_p[0] = sizet(idx_val)
ret_rd_p: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, cls_nm_rd_ptr, "__getitem__",
obj_ptr_rd, arg_vals_rd_p, 1, trans, sub)
ret_rd_p: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, cls_nm_rd_ptr, "__getitem__", obj_ptr_rd, arg_vals_rd_p, 1, trans, sub)
if not (ret_rd_p is None):
return ret_rd_p
# 无 __getitem__:结构体指针数组访问(GEP + load)
ptr_val_rd_g: llvmlite.Value* = llvmlite.build_load(
builder, pointee, alloca)
ptr_val_rd_g: llvmlite.Value* = llvmlite.build_load(builder, pointee, alloca)
if ptr_val_rd_g is not None:
elem_rd_g: llvmlite.Value* = llvmlite.build_gep(
builder, inner_ty, ptr_val_rd_g, idx_val)
elem_rd_g: llvmlite.Value* = llvmlite.build_gep(builder, inner_ty, ptr_val_rd_g, idx_val)
if elem_rd_g is not None:
# volatile 指针指向物:解引用 load 带 volatile
return llvmlite.build_load(builder, inner_ty, elem_rd_g, vol_sub_rd)
@@ -944,21 +869,17 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# 必须先 load alloca 得指针值,再 GEP i8*(步长 8)——
# 否则 GEP base 用 alloca(&elem_ptr)读到栈变量而非数据区,
# list.get 返回"元素地址"而非"元素值"(dump 虚调用读错 vtable)。
ptr_val_pe_ts: llvmlite.Value* = llvmlite.build_load(
builder, pointee, alloca)
ptr_val_pe_ts: llvmlite.Value* = llvmlite.build_load(builder, pointee, alloca)
if ptr_val_pe_ts is not None:
elem_ptr_ts: llvmlite.Value* = llvmlite.build_gep(
builder, pointee, ptr_val_pe_ts, idx_val)
elem_ptr_ts: llvmlite.Value* = llvmlite.build_gep(builder, pointee, ptr_val_pe_ts, idx_val)
if elem_ptr_ts is not None:
# volatile 指针指向物:解引用 load 带 volatile
return llvmlite.build_load(builder, pointee, elem_ptr_ts, vol_sub_rd)
return None
# 普通指针遍历: 先 load 指针值,再 GEP
ptr_val: llvmlite.Value* = llvmlite.build_load(
builder, pointee, alloca)
ptr_val: llvmlite.Value* = llvmlite.build_load(builder, pointee, alloca)
if ptr_val is not None:
elem_ptr2: llvmlite.Value* = llvmlite.build_gep(
builder, inner_ty, ptr_val, idx_val)
elem_ptr2: llvmlite.Value* = llvmlite.build_gep(builder, inner_ty, ptr_val, idx_val)
if elem_ptr2 is not None:
# volatile 指针指向物:解引用 load 带 volatile
return llvmlite.build_load(builder, inner_ty, elem_ptr2, vol_sub_rd)
@@ -975,13 +896,10 @@ class ExprGenName(ExprGenBase.ExprGenBase):
match pointee:
case llvmlite.LLVMType.Int(bits_rd):
if bits_rd == 8:
i8_ptr_rd: llvmlite.LLVMType* = llvmlite.Ptr(
pool, llvmlite.Int8(pool))
elem_ptr_rd: llvmlite.Value* = llvmlite.build_gep(
builder, i8_ptr_rd, alloca, idx_val)
i8_ptr_rd: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
elem_ptr_rd: llvmlite.Value* = llvmlite.build_gep(builder, i8_ptr_rd, alloca, idx_val)
if elem_ptr_rd is not None:
return llvmlite.build_load(
builder, i8_ptr_rd, elem_ptr_rd)
return llvmlite.build_load(builder, i8_ptr_rd, elem_ptr_rd)
case _:
pass
# 自定义类(结构体类型): 仅当类定义了 __getitem__
@@ -993,23 +911,18 @@ class ExprGenName(ExprGenBase.ExprGenBase):
if gi_lookup_sub is not None:
viperlib.snprintf(gi_lookup_sub, 128, "%s.__getitem__", cls_nm_sub)
if self.Gen.CallGenBase.find_func_in_module(mod, gi_lookup_sub) is not None:
obj_val_sub: llvmlite.Value* = llvmlite.build_load(
builder, pointee, alloca)
obj_val_sub: llvmlite.Value* = llvmlite.build_load(builder, pointee, alloca)
if not (obj_val_sub is None):
arg_vals_sub: sizet* = pool.alloc(8)
if not (arg_vals_sub is None):
arg_vals_sub[0] = sizet(idx_val)
ret_sub: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, cls_nm_sub, "__getitem__",
obj_val_sub, arg_vals_sub, 1, trans, sub)
ret_sub: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, cls_nm_sub, "__getitem__", obj_val_sub, arg_vals_sub, 1, trans, sub)
if not (ret_sub is None):
return ret_sub
# 无 __getitem__:结构体指针数组访问(GEP + load)
ptr_val_sub_g: llvmlite.Value* = llvmlite.build_load(
builder, pointee, alloca)
ptr_val_sub_g: llvmlite.Value* = llvmlite.build_load(builder, pointee, alloca)
if ptr_val_sub_g is not None:
elem_sub_g: llvmlite.Value* = llvmlite.build_gep(
builder, pointee, ptr_val_sub_g, idx_val)
elem_sub_g: llvmlite.Value* = llvmlite.build_gep(builder, pointee, ptr_val_sub_g, idx_val)
if elem_sub_g is not None:
# volatile 指针指向物:解引用 load 带 volatile
return llvmlite.build_load(builder, pointee, elem_sub_g, vol_sub_rd)
@@ -1017,8 +930,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
pass
# 通用路径:翻译 value 获取指针
ptr_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, sub.value, None, 0, trans)
ptr_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub.value, None, 0, trans)
if ptr_val is None or ptr_val.Ty is None:
return None
@@ -1027,16 +939,13 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# 通用路径基址(如 self.ptr / 复杂表达式):仅当基址可解析到
# VarEntry/FieldEntry 且其为 rawptr[t.CVolatile|T] 时,元素 load 带 volatile;
# 其余基址解析返回 0(明确不支持,见限制清单)。守卫为 0 时文本不变。
vol_sub_gen: int = self.Gen.ExprGenAttr.base_pointee_is_volatile(
pool, trans, sub.value)
vol_sub_gen: int = self.Gen.ExprGenAttr.base_pointee_is_volatile(pool, trans, sub.value)
elem_ty2: llvmlite.LLVMType* = ptr_val.Ty.Pointee
if elem_ty2 is not None:
# 数组类型: 双索引 GEP + load 元素
match elem_ty2:
case llvmlite.LLVMType.Array(arr_elem_ty2, arr_count2):
elem_ptr3: llvmlite.Value* = llvmlite.build_gep_array(
builder, elem_ty2, arr_elem_ty2, ptr_val,
self._zext_index_to_i32(builder, idx_val))
elem_ptr3: llvmlite.Value* = llvmlite.build_gep_array(builder, elem_ty2, arr_elem_ty2, ptr_val, self._zext_index_to_i32(builder, idx_val))
if elem_ptr3 is not None:
return llvmlite.build_load(builder, arr_elem_ty2, elem_ptr3, vol_sub_gen)
return None
@@ -1050,29 +959,20 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# 存指针",合法 C 联合读回应按指针读回。统一按 i8* load(同宽 8 字节,
# 位模式不变):指针目标直接 bitcast;整数目标隐式 ptrtoint 同样
# 保持位模式(对齐 MatchGenMixin 的 REnum 槽位按声明类型读机制)。
if trans is not None and sub.value is not None \
and sub.value.kind() == ast.ASTKind.Attribute:
fa_u64: str = self.Gen.ExprGenAttr._resolve_attr_field_class(
pool, trans, sub.value)
if trans is not None and sub.value is not None and sub.value.kind() == ast.ASTKind.Attribute:
fa_u64: str = self.Gen.ExprGenAttr._resolve_attr_field_class(pool, trans, sub.value)
if fa_u64 is not None and self._annot_is_64bit_scalar(fa_u64) != 0:
match elem_ty2:
case llvmlite.LLVMType.Int(eb_u64):
if eb_u64 == 64:
cell_p_u64: llvmlite.Value* = \
llvmlite.build_gep(builder, elem_ty2, ptr_val, idx_val)
cell_p_u64: llvmlite.Value* = llvmlite.build_gep(builder, elem_ty2, ptr_val, idx_val)
if cell_p_u64 is not None:
i8_ty_u64: llvmlite.LLVMType* = \
llvmlite.Int8(pool)
i8p_ty_u64: llvmlite.LLVMType* = \
llvmlite.Ptr(pool, i8_ty_u64)
i8pp_ty_u64: llvmlite.LLVMType* = \
llvmlite.Ptr(pool, i8p_ty_u64)
cast_cell_u64: llvmlite.Value* = \
llvmlite.build_bitcast(
builder, cell_p_u64, i8pp_ty_u64)
i8_ty_u64: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8p_ty_u64: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty_u64)
i8pp_ty_u64: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8p_ty_u64)
cast_cell_u64: llvmlite.Value* = llvmlite.build_bitcast(builder, cell_p_u64, i8pp_ty_u64)
if cast_cell_u64 is not None:
return llvmlite.build_load(
builder, i8p_ty_u64, cast_cell_u64, vol_sub_gen)
return llvmlite.build_load(builder, i8p_ty_u64, cast_cell_u64, vol_sub_gen)
case _:
pass
# 自定义结构体 (如 self._ht[key]): 仅当类定义了 __getitem__ 才转发方法调用;
@@ -1086,20 +986,16 @@ class ExprGenName(ExprGenBase.ExprGenBase):
arg_vals_rd_g: sizet* = pool.alloc(8)
if not (arg_vals_rd_g is None):
arg_vals_rd_g[0] = sizet(idx_val)
ret_rd_g: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, cls_nm_rd_gen, "__getitem__",
ptr_val, arg_vals_rd_g, 1, trans, sub)
ret_rd_g: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, cls_nm_rd_gen, "__getitem__", ptr_val, arg_vals_rd_g, 1, trans, sub)
if not (ret_rd_g is None):
return ret_rd_g
# 无 __getitem__:结构体指针数组访问(GEP + load)
elem_ptr_gen: llvmlite.Value* = llvmlite.build_gep(
builder, elem_ty2, ptr_val, idx_val)
elem_ptr_gen: llvmlite.Value* = llvmlite.build_gep(builder, elem_ty2, ptr_val, idx_val)
if elem_ptr_gen is not None:
return llvmlite.build_load(builder, elem_ty2, elem_ptr_gen, vol_sub_gen)
return None
# 指针类型: 单索引 GEP + load
elem_ptr4: llvmlite.Value* = llvmlite.build_gep(
builder, elem_ty2, ptr_val, idx_val)
elem_ptr4: llvmlite.Value* = llvmlite.build_gep(builder, elem_ty2, ptr_val, idx_val)
if elem_ptr4 is not None:
return llvmlite.build_load(builder, elem_ty2, elem_ptr4, vol_sub_gen)
return None
@@ -1110,14 +1006,10 @@ class ExprGenName(ExprGenBase.ExprGenBase):
"""注解是否为 64 位标量 | t.CPtr 联合(AnnotClassName 为提取出的
非 CPtr 侧类型名,如 int64|t.CPtr → "CInt64T")。此类联合的
8 字节单元格存 i64 标量,下标元素类型应为 Int64 而非指针。"""
if annot is None:
return 0
if string.strstr(annot, "CInt64T") is not None:
return 1
if string.strstr(annot, "CUInt64T") is not None:
return 1
if string.strstr(annot, "CSizeT") is not None:
return 1
if annot is None: return 0
if string.strstr(annot, "CInt64T") is not None: return 1
if string.strstr(annot, "CUInt64T") is not None: return 1
if string.strstr(annot, "CSizeT") is not None: return 1
return 0
# ============================================================
@@ -1140,49 +1032,36 @@ class ExprGenName(ExprGenBase.ExprGenBase):
trans: HT.Translator*,
node: ast.AST*) -> int:
"""下标基座存储形态:1=数组 / 0=指针 / -1=无法判定"""
if node is None or trans is None:
return -1
if node is None or trans is None: return -1
sub_bk: ast.Subscript* = ast.Subscript*(node)
if sub_bk is None or sub_bk.value is None:
return -1
if sub_bk is None or sub_bk.value is None: return -1
base_ty_bk: llvmlite.LLVMType* = None
if sub_bk.value.kind() == ast.ASTKind.Name:
nm_bk: ast.Name* = ast.Name*(sub_bk.value)
if nm_bk.id is None:
return -1
alloca_bk: llvmlite.Value* = self.Gen.VarGen.lookup_var(
trans.SymTab, nm_bk.id)
if nm_bk.id is None: return -1
alloca_bk: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm_bk.id)
if alloca_bk is None:
alloca_bk = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm_bk.id)
if alloca_bk is None or alloca_bk.Ty is None:
return -1
if self.is_ptr_type(alloca_bk.Ty) == 0:
return -1
if alloca_bk is None or alloca_bk.Ty is None: return -1
if self.is_ptr_type(alloca_bk.Ty) == 0: return -1
base_ty_bk = alloca_bk.Ty.Pointee
elif sub_bk.value.kind() == ast.ASTKind.Attribute:
# 单层 obj.field(如 self.arr):非 fatal 只读解析字段类型
fe_bk: GenTypes.FieldEntry* = \
self.Gen.ExprGenAttr._resolve_attr_field_entry(pool, trans, sub_bk.value)
if fe_bk is None or fe_bk.Ty is None:
return -1
fe_bk: GenTypes.FieldEntry* = self.Gen.ExprGenAttr._resolve_attr_field_entry(pool, trans, sub_bk.value)
if fe_bk is None or fe_bk.Ty is None: return -1
base_ty_bk = fe_bk.Ty
else:
return -1
if base_ty_bk is None:
return -1
if base_ty_bk is None: return -1
# 基座自身是数组值 → 数组存储
if self.is_array_type(base_ty_bk) != 0:
return 1
if self.is_array_type(base_ty_bk) != 0: return 1
if self.is_ptr_type(base_ty_bk) != 0:
inner_bk: llvmlite.LLVMType* = base_ty_bk.Pointee
if inner_bk is None:
return -1
if inner_bk is None: return -1
# Ptr(Array) → t.CArray[T,N] 局部/字段(数组存储)
if self.is_array_type(inner_bk) != 0:
return 1
if self.is_array_type(inner_bk) != 0: return 1
# Ptr(Struct) → rawptr[T](指针存储)
if inner_bk.kind() == llvmlite.LLVMType.Struct:
return 0
if inner_bk.kind() == llvmlite.LLVMType.Struct: return 0
return -1
def get_subscript_ptr(self, builder: llvmlite.IRBuilder*,
@@ -1191,17 +1070,13 @@ class ExprGenName(ExprGenBase.ExprGenBase):
node: ast.AST*,
trans: HT.Translator* = None) -> llvmlite.Value*:
"""获取下标表达式的元素指针(用于赋值 lhs)"""
if node is None or builder is None:
return None
if node is None or builder is None: return None
sub: ast.Subscript* = ast.Subscript*(node)
if sub is None:
return None
if sub is None: return None
# 翻译索引
idx_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, sub.slice, None, 0, trans)
if idx_val is None:
return None
idx_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub.slice, None, 0, trans)
if idx_val is None: return None
# 嵌套下标: a[i][j] = v —— 递归解析内层下标指针后 GEP
# (如 gfx.vp Mat4.m: t.CArray[t.CArray[float, 4], 4] 的 m.m[0][0] = 1;
@@ -1209,18 +1084,13 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# 会把内层元素加载为值(Array 类型)→ is_ptr_type 失败 → 返回 None →
# "subscript ptr is None" fail-fast。递归取内层指针再 GEP 根治。)
if sub.value is not None and sub.value.kind() == ast.ASTKind.Subscript:
inner_ptr: llvmlite.Value* = self.get_subscript_ptr(
builder, pool, mod, sub.value, trans)
if inner_ptr is None or inner_ptr.Ty is None:
return None
inner_ptr: llvmlite.Value* = self.get_subscript_ptr(builder, pool, mod, sub.value, trans)
if inner_ptr is None or inner_ptr.Ty is None: return None
inner_elem: llvmlite.LLVMType* = inner_ptr.Ty.Pointee
if inner_elem is None:
return None
if inner_elem is None: return None
match inner_elem:
case llvmlite.LLVMType.Array(arr_ie, _):
return llvmlite.build_gep_array(
builder, inner_elem, arr_ie, inner_ptr,
self._zext_index_to_i32(builder, idx_val))
return llvmlite.build_gep_array(builder, inner_elem, arr_ie, inner_ptr, self._zext_index_to_i32(builder, idx_val))
case _:
return llvmlite.build_gep(builder, inner_elem, inner_ptr, idx_val)
@@ -1231,8 +1101,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# nonlocal 数组/指针:从 env 读共享堆地址(提升函数内不能
# lookup_var 外层 alloca——SSA 编号跨函数错乱崩溃)
if GenApi.is_nonlocal_name(trans, nm.id) != 0:
return self._nonlocal_subscript_ptr(
builder, pool, trans, nm.id, idx_val)
return self._nonlocal_subscript_ptr(builder, pool, trans, nm.id, idx_val)
alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
if alloca is not None and alloca.Ty is not None:
if self.is_ptr_type(alloca.Ty) != 0:
@@ -1242,19 +1111,15 @@ class ExprGenName(ExprGenBase.ExprGenBase):
match pointee:
case llvmlite.LLVMType.Array(elem_ty, count):
# 数组遍历
return llvmlite.build_gep_array(
builder, pointee, elem_ty, alloca,
self._zext_index_to_i32(builder, idx_val))
return llvmlite.build_gep_array(builder, pointee, elem_ty, alloca, self._zext_index_to_i32(builder, idx_val))
case llvmlite.LLVMType.Ptr(inner_ty):
# inner_ty 是 Ptr 说明 alloca.Ty 是三重指针,
# 即 X|t.CPtr 当 X 本身是指针类型 (如 T=AST|t.CPtr, T|t.CPtr=AST**)。
# 此时 [i]=val 应该是指针解引用赋值, 而非调用 __setitem__。
if self.is_ptr_type(inner_ty) != 0:
ptr_val_gsp: llvmlite.Value* = llvmlite.build_load(
builder, pointee, alloca)
ptr_val_gsp: llvmlite.Value* = llvmlite.build_load(builder, pointee, alloca)
if ptr_val_gsp is not None:
return llvmlite.build_gep(
builder, inner_ty, ptr_val_gsp, idx_val)
return llvmlite.build_gep(builder, inner_ty, ptr_val_gsp, idx_val)
return None
# 自定义结构体 (如 HashTable|t.CPtr, JsonValue|t.CPtr):
# 仅当类定义了 __setitem__(当前模块定义或跨模块 stub declare 注入)
@@ -1279,8 +1144,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# alloca 得指针值,再 GEP——否则 GEP base 用 alloca(&elem_ptr)
# 读到栈变量而非数据区,赋值写不进 list 数据
# (data 全 0xbaadf00d,dump 虚调用读错 vtable 崩溃)。
ptr_val_pe: llvmlite.Value* = llvmlite.build_load(
builder, pointee, alloca)
ptr_val_pe: llvmlite.Value* = llvmlite.build_load(builder, pointee, alloca)
if ptr_val_pe is not None:
# [FIX 2026-08-30] 64 位标量联合(int64|t.CPtr /
# uint64|t.CPtr / sizet|t.CPtr):8 字节单元格存
@@ -1289,29 +1153,22 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# 否则元素类型为指针 → i64 存储触发整数隐式转指针
# fail-fast(把解引用写入误判为 int→ptr)。
pe_annot: str = self.Gen.VarGen.var_annot_class_name(ve_pe)
if pe_annot is not None \
and self._annot_is_64bit_scalar(pe_annot) != 0:
return llvmlite.build_gep(
builder, llvmlite.Int64(pool), ptr_val_pe, idx_val)
if pe_annot is not None and self._annot_is_64bit_scalar(pe_annot) != 0:
return llvmlite.build_gep(builder, llvmlite.Int64(pool), ptr_val_pe, idx_val)
match pointee:
case llvmlite.LLVMType.Int(bits_pe):
if bits_pe == 8:
i8_ptr_pe: llvmlite.LLVMType* = llvmlite.Ptr(
pool, llvmlite.Int8(pool))
return llvmlite.build_gep(
builder, i8_ptr_pe, ptr_val_pe, idx_val)
i8_ptr_pe: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
return llvmlite.build_gep(builder, i8_ptr_pe, ptr_val_pe, idx_val)
case _:
pass
return llvmlite.build_gep(
builder, pointee, ptr_val_pe, idx_val)
return llvmlite.build_gep(builder, pointee, ptr_val_pe, idx_val)
return None
# 普通指针遍历: 先 load 指针值,再 GEP
ptr_val: llvmlite.Value* = llvmlite.build_load(
builder, pointee, alloca)
ptr_val: llvmlite.Value* = llvmlite.build_load(builder, pointee, alloca)
if ptr_val is None:
return None
gep_r: llvmlite.Value* = llvmlite.build_gep(
builder, inner_ty, ptr_val, idx_val)
gep_r: llvmlite.Value* = llvmlite.build_gep(builder, inner_ty, ptr_val, idx_val)
return gep_r
case _:
# pointee 是普通标量类型 (如 i64, i32, i8):
@@ -1329,26 +1186,21 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# 得指针值,再按 i8* 步长 GEP——否则 GEP base 用 alloca
# (&elem_ptr)算到栈地址,赋值写不进 list 数据区
# (append 只增 count、data 全 0xbaadf00d)。
ptr_val_cs: llvmlite.Value* = llvmlite.build_load(
builder, pointee, alloca)
ptr_val_cs: llvmlite.Value* = llvmlite.build_load(builder, pointee, alloca)
if ptr_val_cs is not None:
match pointee:
case llvmlite.LLVMType.Int(bits_cs):
if bits_cs == 8:
i8_ptr_cs: llvmlite.LLVMType* = llvmlite.Ptr(
pool, llvmlite.Int8(pool))
return llvmlite.build_gep(
builder, i8_ptr_cs, ptr_val_cs, idx_val)
i8_ptr_cs: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
return llvmlite.build_gep(builder, i8_ptr_cs, ptr_val_cs, idx_val)
case _:
pass
return llvmlite.build_gep(
builder, pointee, ptr_val_cs, idx_val)
return llvmlite.build_gep(builder, pointee, ptr_val_cs, idx_val)
return None
return llvmlite.build_gep(builder, pointee, alloca, idx_val)
# 通用路径
ptr_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, sub.value, None, 0, trans)
ptr_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub.value, None, 0, trans)
if ptr_val is None or ptr_val.Ty is None:
return None
if self.is_ptr_type(ptr_val.Ty) != 0:
@@ -1357,9 +1209,7 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# 数组类型: 双索引 GEP (getelementptr [N x ty], ptr, i32 0, i32 idx)
match elem_ty2:
case llvmlite.LLVMType.Array(arr_elem_ty, arr_count):
return llvmlite.build_gep_array(
builder, elem_ty2, arr_elem_ty, ptr_val,
self._zext_index_to_i32(builder, idx_val))
return llvmlite.build_gep_array(builder, elem_ty2, arr_elem_ty, ptr_val, self._zext_index_to_i32(builder, idx_val))
case _:
pass
# 自定义结构体 (如 self._ht[key]): 仅当类定义了 __setitem__
+68 -143
View File
@@ -14,13 +14,8 @@ import lib.core.Gen.Expr.ExprGenBase as ExprGenBase
# ============================================================
# ExprGenOps - ExprGenMixin 拆分(阶段 D):比较/一元/布尔/binop 运算
#
# 继承 ExprGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExpr 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ExprGenOps(ExprGenBase.ExprGenBase):
novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
"""比较/一元/布尔/binop 运算"""
# ============================================================
@@ -37,21 +32,16 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
node: ast.AST*,
trans: HT.Translator* = None) -> llvmlite.Value*:
"""翻译三元表达式 (body if test else orelse),返回 phi 结果 Value"""
if node is None or builder is None or trans is None:
return None
if node is None or builder is None or trans is None: return None
ie: rawptr[ast.IfExp] = rawptr[ast.IfExp](node)
if ie is None:
return None
if ie is None: return None
func: llvmlite.Function* = trans._cur_func
if func is None:
return None
if func is None: return None
# 1. 求值条件
cond_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, ie.test, None, 0, trans)
if cond_val is None:
return None
cond_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, ie.test, None, 0, trans)
if cond_val is None: return None
# 转换为 i1
cond_bits: int = self.get_llvm_type_bits(cond_val.Ty)
if cond_bits == 1:
@@ -78,16 +68,14 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
viperlib.snprintf(name_buf, 32, "ifexp.merge.%d", cnt)
merge_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, name_buf)
if then_bb is None or else_bb is None or merge_bb is None:
return None
if then_bb is None or else_bb is None or merge_bb is None: return None
# 3. 条件跳转
llvmlite.build_cond_br(builder, cond_i1, then_bb, else_bb)
# 4. then 分支
llvmlite.position_at_end(builder, then_bb)
body_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, ie.body, None, 0, trans)
body_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, ie.body, None, 0, trans)
then_blk_for_phi: rawptr[llvmlite.BasicBlock] = trans._cur_builder.CurBlock
if body_val is None:
# fail-fast:三元表达式 then 分支翻译失败,立即终止编译(暴露上游根因)
@@ -106,8 +94,7 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
if self.is_ptr_type(body_val.Ty) != 0:
orelse_target_ty = body_val.Ty
llvmlite.position_at_end(builder, else_bb)
orelse_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, ie.orelse, None, 0, trans, orelse_target_ty)
orelse_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, ie.orelse, None, 0, trans, orelse_target_ty)
else_blk_for_phi: rawptr[llvmlite.BasicBlock] = trans._cur_builder.CurBlock
if orelse_val is None:
# fail-fast:三元表达式 else 分支翻译失败,立即终止编译(暴露上游根因)
@@ -157,10 +144,8 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
# fail-fast:三元表达式分支类型缺失,立即终止编译(暴露上游根因)
self.Gen.TypeGenErr.fatal_error(node, "三元表达式分支类型缺失", "TypeError")
inc1: rawptr[llvmlite.PhiIncoming] = llvmlite.new_phi_incoming(
pool, body_val, then_blk_for_phi)
inc2: rawptr[llvmlite.PhiIncoming] = llvmlite.new_phi_incoming(
pool, orelse_val, else_blk_for_phi)
inc1: llvmlite.PhiIncoming* = llvmlite.new_phi_incoming(pool, body_val, then_blk_for_phi)
inc2: llvmlite.PhiIncoming* = llvmlite.new_phi_incoming(pool, orelse_val, else_blk_for_phi)
if inc1 is None or inc2 is None:
return None
# 链表顺序: inc1 (head) -> inc2 (tail)
@@ -272,8 +257,7 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
return 1
# 2) 变量注解类型为无符号类型(trans 可用时查 SymTab)
if trans is not None:
ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, nm.id)
ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id)
if ve is not None:
# [S4 切读] Spec 明确无符号(TS_UINT)优先于字符串判定
if self._entry_spec_unsigned(ve.Spec) != 0:
@@ -302,8 +286,7 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
if sub_su.value is not None and sub_su.value.kind() == ast.ASTKind.Name:
snm_su: ast.Name* = ast.Name*(sub_su.value)
if snm_su.id is not None and trans is not None:
ve_su: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, snm_su.id)
ve_su: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, snm_su.id)
if ve_su is not None:
# [S4 切读] Spec 明确无符号优先(数组元素为无符号的联合注解场景
# 时 Spec 仍是 Ptr/Array ⇒ 返回 0,自动回退字符串路径)
@@ -322,8 +305,7 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
if at_u.value.kind() == ast.ASTKind.Name:
vn_u: ast.Name* = ast.Name*(at_u.value)
if vn_u.id is not None:
ve_u: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, vn_u.id)
ve_u: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, vn_u.id)
if ve_u is not None:
cls_nm_u = self.Gen.VarGen.var_annot_class_name(ve_u)
if cls_nm_u is not None:
@@ -383,8 +365,7 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
if self._spec_sign_from_annot(nm.id) == TSpec.TS_SIGN_SIGNED:
return 1
if trans is not None:
ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, nm.id)
ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id)
if ve is not None:
ncn_s: str = self.Gen.VarGen.var_annot_class_name(ve)
if ncn_s is not None:
@@ -396,8 +377,7 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
if sub_s.value is not None and sub_s.value.kind() == ast.ASTKind.Name:
snm: ast.Name* = ast.Name*(sub_s.value)
if snm.id is not None and trans is not None:
ve_s: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, snm.id)
ve_s: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, snm.id)
if ve_s is not None:
scn_s: str = self.Gen.VarGen.var_annot_class_name(ve_s)
if scn_s is not None:
@@ -483,8 +463,7 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
if comparators is None or len(comparators) == 0:
return None
rhs_node: ast.AST* = comparators.get(0)
rhs: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, rhs_node, None, 0, trans)
rhs: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, rhs_node, None, 0, trans)
if rhs is None:
return None
@@ -523,27 +502,22 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
if cmp_with_none == 0 and lhs_node is not None and lhs_node.kind() == ast.ASTKind.Name and trans is not None:
nm: ast.Name* = ast.Name*(lhs_node)
if nm is not None and nm.id is not None:
lhs_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(
trans.SymTab, nm.id)
lhs_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
if lhs_alloca is not None:
if cmp_zero == 0 or self.get_ptr_level(lhs_alloca.Ty) == 0:
ovl_self1: llvmlite.Value* = lhs_alloca
# Ptr(Ptr(Struct)) 对象存储槽:load 出对象指针作 self
# (与 translate_binop 路径 1 一致,避免槽地址当对象地址)
if lhs_alloca.Ty is not None and lhs_alloca.Ty.Pointee != 0 \
and self.Gen.ExprGenBase.is_ptr_type(lhs_alloca.Ty.Pointee) != 0:
load_self1: llvmlite.Value* = llvmlite.build_load(
builder, lhs_alloca.Ty.Pointee, lhs_alloca)
if lhs_alloca.Ty is not None and lhs_alloca.Ty.Pointee != 0 and self.Gen.ExprGenBase.is_ptr_type(lhs_alloca.Ty.Pointee) != 0:
load_self1: llvmlite.Value* = llvmlite.build_load(builder, lhs_alloca.Ty.Pointee, lhs_alloca)
if load_self1 is not None:
ovl_self1 = load_self1
ovl_result: llvmlite.Value* = self.try_operator_overload(
pool, builder, mod, ovl_self1, rhs, op, trans, 1)
ovl_result: llvmlite.Value* = self.try_operator_overload(pool, builder, mod, ovl_self1, rhs, op, trans, 1)
if ovl_result is not None:
return ovl_result
# 正常翻译 lhs
lhs: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, cmp.left, None, 0, trans)
lhs: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cmp.left, None, 0, trans)
if lhs is None:
return None
@@ -559,8 +533,7 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
cn_lookup: str = pool.alloc(128)
if cn_lookup is not None:
viperlib.snprintf(cn_lookup, 128, "%s.__contains__", cn_cls)
cn_fn: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(
mod, cn_lookup)
cn_fn: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, cn_lookup)
if cn_fn is not None:
cn_ret: llvmlite.LLVMType* = llvmlite.function_get_ret_ty(cn_fn)
cn_fn_name: str = llvmlite.function_get_name(cn_fn)
@@ -576,26 +549,22 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
# 参数链表: self → key(独立 null 结尾)
cn_self.Next = lhs
lhs.Next = None
cn_res: llvmlite.Value* = llvmlite.build_call(
builder, cn_fn_name, cn_self, 2, cn_ret, 0)
cn_res: llvmlite.Value* = llvmlite.build_call(builder, cn_fn_name, cn_self, 2, cn_ret, 0)
if cn_res is not None:
# 归一化到 i1(__contains__ 返回 int/i32 等)
cn_i1: llvmlite.Value* = cn_res
match cn_ret:
case llvmlite.LLVMType.Int(cn_bits):
if cn_bits > 1:
cn_zero: llvmlite.Value* = llvmlite.ConstInt(
pool, cn_ret, 0, "0")
cn_zero: llvmlite.Value* = llvmlite.ConstInt(pool, cn_ret, 0, "0")
if cn_zero is not None:
cn_i1 = llvmlite.build_icmp(
builder, llvmlite.ICMP_NE, cn_res, cn_zero)
cn_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cn_res, cn_zero)
case _:
pass
if op == ast.OpKind.NotIn:
i1_ty_ni: llvmlite.LLVMType* = llvmlite.Int1(pool)
if i1_ty_ni is not None and cn_i1 is not None:
one_i1_ni: llvmlite.Value* = llvmlite.ConstInt(
pool, i1_ty_ni, 1, "1")
one_i1_ni: llvmlite.Value* = llvmlite.ConstInt(pool, i1_ty_ni, 1, "1")
if one_i1_ni is not None:
cn_i1 = llvmlite.build_xor(builder, cn_i1, one_i1_ni)
if cn_i1 is not None:
@@ -610,8 +579,7 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
# Is/IsNot 不在 _cmpop_to_dunder 映射中,会自动返回 None 回退原生比较
# None 比较跳过重载(走身份比较);指针判空(cmp_zero + 指针)同样跳过
if cmp_with_none == 0 and (cmp_zero == 0 or self.get_ptr_level(lhs.Ty) == 0):
ovl_result2: llvmlite.Value* = self.try_operator_overload(
pool, builder, mod, lhs, rhs, op, trans, 1)
ovl_result2: llvmlite.Value* = self.try_operator_overload(pool, builder, mod, lhs, rhs, op, trans, 1)
if ovl_result2 is not None:
return ovl_result2
@@ -677,10 +645,7 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
rhs = llvmlite.build_ptrtoint(builder, rhs, lhs.Ty)
else:
# 不同级指针(1 vs 2 等)→ 禁止(fast-fail)
self.Gen.TypeGenErr.fatal_error(
cmp,
f"比较类型不匹配: 不同级指针比较 (lhs 层级={lhs_ptr_level}, rhs 层级={rhs_ptr_level})",
"TypeError")
self.Gen.TypeGenErr.fatal_error(cmp, f"比较类型不匹配: 不同级指针比较 (lhs 层级={lhs_ptr_level}, rhs 层级={rhs_ptr_level})", "TypeError")
else:
# None 比较: None 被翻译为 i8* null(一级指针)
# 如果 lhs 是指针,将 rhs (i8* null) bitcast 为 lhs 的指针类型
@@ -786,21 +751,16 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
trans: HT.Translator* = None) -> llvmlite.Value*:
"""翻译一元运算(-x, +x, not x, ~x)"""
uo: ast.UnaryOp* = ast.UnaryOp*(node)
if uo is None:
return None
if uo is None: return None
operand: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, uo.operand, None, 0, trans)
if operand is None:
return None
operand: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, uo.operand, None, 0, trans)
if operand is None: return None
# === 一元运算符重载: -obj/+obj/~obj 调用 __neg__/__pos__/__invert__ ===
# 仅 USub/UAdd/Invert 有重载语义(not 无 dunder 方法)
if uo.op == ast.OpKind.USub or uo.op == ast.OpKind.UAdd or uo.op == ast.OpKind.Invert:
ovl_u: llvmlite.Value* = self.try_unary_operator_overload(
pool, builder, mod, operand, uo.op, trans)
if ovl_u is not None:
return ovl_u
ovl_u: llvmlite.Value* = self.try_unary_operator_overload(pool, builder, mod, operand, uo.op, trans)
if ovl_u is not None: return ovl_u
if uo.op == ast.OpKind.USub:
# -x
@@ -854,8 +814,7 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
if d_pointee is not None:
return llvmlite.build_load(builder, d_pointee, operand)
# 非指针即类型推断退化:fail-fast,绝不按 i8 兜底读取
self.Gen.TypeGenErr.fatal_error(
node, "单目 '*' 解引用的操作数必须是指针类型(类型推断退化)", "TypeError")
self.Gen.TypeGenErr.fatal_error(node, "单目 '*' 解引用的操作数必须是指针类型(类型推断退化)", "TypeError")
return None
elif uo.op == ast.OpKind.AddrOf:
# &x → 左值地址(不 load):Name 变量 alloca / 模块全局 / 模块函数 /
@@ -868,8 +827,7 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
# self/cls 对象引用:返回对象指针本身(Ptr(Struct))而非
# 指针变量的地址(Ptr(Ptr(Struct)))
if string.strcmp(nm_ao.id, "self") == 0 or string.strcmp(nm_ao.id, "cls") == 0:
se_ao: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, nm_ao.id)
se_ao: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm_ao.id)
if se_ao is not None and se_ao.Alloca is not None and se_ao.Alloca.Ty is not None:
match se_ao.Alloca.Ty:
case llvmlite.LLVMType.Ptr(sa1):
@@ -930,18 +888,15 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
return llvmlite.SSAValue(pool, llvmlite.Ptr(pool, fn_ty_ao), fbuf_ao)
elif uo.operand.kind() == ast.ASTKind.Attribute:
# 字段地址(GEP,不 load)
fptr_ao: llvmlite.Value* = self.Gen.ExprGenAttr.get_attribute_ptr(
builder, pool, mod, uo.operand, trans)
fptr_ao: llvmlite.Value* = self.Gen.ExprGenAttr.get_attribute_ptr(builder, pool, mod, uo.operand, trans)
if fptr_ao is not None:
return fptr_ao
elif uo.operand.kind() == ast.ASTKind.Subscript:
# 元素地址(GEP,不 load)
sptr_ao: llvmlite.Value* = self.Gen.ExprGenName.get_subscript_ptr(
builder, pool, mod, uo.operand, trans)
sptr_ao: llvmlite.Value* = self.Gen.ExprGenName.get_subscript_ptr(builder, pool, mod, uo.operand, trans)
if sptr_ao is not None:
return sptr_ao
self.Gen.TypeGenErr.fatal_error(
node, "单目 '&' 取地址的操作数必须是左值(Name/Attribute/Subscript)", "TypeError")
self.Gen.TypeGenErr.fatal_error(node, "单目 '&' 取地址的操作数必须是左值(Name/Attribute/Subscript)", "TypeError")
return None
return operand
# ============================================================
@@ -991,16 +946,14 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
merge_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, name_buf)
# phi 入边链表头/尾
phi_head: rawptr[llvmlite.PhiIncoming] = None
phi_tail: rawptr[llvmlite.PhiIncoming] = None
phi_head: llvmlite.PhiIncoming* = None
phi_tail: llvmlite.PhiIncoming* = None
phi_count: int = count - 1 # 循环次数
# 对每个值(除最后一个)求值并短路
for i in range(count - 1):
val_node: ast.AST* = values.get(i)
val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, val_node,
funcs_ptr, func_count, trans)
val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, val_node, funcs_ptr, func_count, trans)
if val is None:
return None
@@ -1030,7 +983,7 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
# 添加 phi 入边:(val_i1, cond_br 所在 BB)
cur_bb: rawptr[llvmlite.BasicBlock] = builder.CurBlock
inc: rawptr[llvmlite.PhiIncoming] = llvmlite.new_phi_incoming(pool, val_i1, cur_bb)
inc: llvmlite.PhiIncoming* = llvmlite.new_phi_incoming(pool, val_i1, cur_bb)
if phi_head is None:
phi_head = inc
phi_tail = inc
@@ -1043,9 +996,7 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
# 最后一个值:求值后直接跳 merge
last_node: ast.AST* = values.get(count - 1)
last_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, last_node,
funcs_ptr, func_count, trans)
last_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, last_node, funcs_ptr, func_count, trans)
if last_val is None:
return None
last_bits: int = self.get_llvm_type_bits(last_val.Ty)
@@ -1194,35 +1145,28 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
mj += 1
# 既无函数定义也无 SHA1 → 该类没有此 dunder 方法,返回 None 回退原生运算
if found_func is None and cls_sha1 is None:
return None
if found_func is None and cls_sha1 is None: return None
# 方法在"定义它的模块"中确实不存在(同模块类但模块内无此 dunder):
# 返回 None 回退原生运算,绝不发出幽灵 call——否则 IR 残留
# `call void @...__div__`(副作用)且调用方回退原生 sdiv 双重发射,
# llc 报 invalid operand type for instruction(CPythonTest PyFloatObj 根因)
if found_func is None and trans is not None and trans.ModuleSha1 is not None:
if cls_sha1 is not None and string.strcmp(cls_sha1, trans.ModuleSha1) == 0:
return None
if cls_sha1 is not None and string.strcmp(cls_sha1, trans.ModuleSha1) == 0: return None
# 跨模块类:stub 可能未注入,方法存在性以依赖模块 vpi stub 为准。
# vpi 未命中(依赖模块确实无此 dunder)→ 回退原生比较(icmp),
# 绝不发幽灵 call——`call @{cls_sha1}.{Class}.{dunder}` 链接 undefined
# (MemBuddy 无 __eq__ 时 os._mbuddy == sys._mbuddy,SysLibTest 根因)。
vpi_dup: llvmlite.LLVMType* = self.Gen.CallGenBase._lookup_method_ret_ty_via_vpi(
pool, cls_sha1, search_class, dunder)
if vpi_dup is None:
return None
vpi_dup: llvmlite.LLVMType* = self.Gen.CallGenBase._lookup_method_ret_ty_via_vpi(pool, cls_sha1, search_class, dunder)
if vpi_dup is None: return None
# 构建 extra_args 数组(仅含 rhs 一个参数)
extra_args: sizet* = pool.alloc(8)
if extra_args is None:
return None
if extra_args is None: return None
extra_args[0] = sizet(rhs)
# 调用方法: lhs.__dunder__(rhs)
return self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, search_class, dunder,
lhs, extra_args, 1, trans)
return self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, search_class, dunder, lhs, extra_args, 1, trans)
# ============================================================
# try_unary_operator_overload - 尝试一元运算符重载
#
@@ -1305,9 +1249,7 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
return None
# 一元方法无额外参数(extra_args 为空)
return self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, search_class, dunder,
operand, None, 0, trans)
return self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, search_class, dunder, operand, None, 0, trans)
# ============================================================
# fail_if_double_ptr_binop - 双指针算术 fail-fast(**唯一实现**)
#
@@ -1404,8 +1346,7 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
op: int = binop.op
# 先翻译 rhs(只翻译一次,避免副作用重复)
rhs: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, rhs_node, None, 0, trans)
rhs: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, rhs_node, None, 0, trans)
if rhs is None:
return None
@@ -1415,8 +1356,7 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
if lhs_node is not None and lhs_node.kind() == ast.ASTKind.Name and trans is not None:
nm: ast.Name* = ast.Name*(lhs_node)
if nm is not None and nm.id is not None:
lhs_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(
trans.SymTab, nm.id)
lhs_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
if lhs_alloca is not None:
ovl_self1: llvmlite.Value* = lhs_alloca
# alloca 是 Ptr(Ptr(Struct))(X|t.CPtr 对象存储槽)时,
@@ -1424,32 +1364,27 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
# load 槽内容(对象指针值)当字段读 → 垃圾(MultiInheritTest
# Vec2Both __add__ 输出 (1.0,2.0) 根因;get_struct_type_from_value
# 递归解指针后路径 1 能识别 alloca,需同步修正 self 语义)
if lhs_alloca.Ty is not None and lhs_alloca.Ty.Pointee != 0 \
and self.Gen.ExprGenBase.is_ptr_type(lhs_alloca.Ty.Pointee) != 0:
load_self1: llvmlite.Value* = llvmlite.build_load(
builder, lhs_alloca.Ty.Pointee, lhs_alloca)
if lhs_alloca.Ty is not None and lhs_alloca.Ty.Pointee != 0 and self.Gen.ExprGenBase.is_ptr_type(lhs_alloca.Ty.Pointee) != 0:
load_self1: llvmlite.Value* = llvmlite.build_load(builder, lhs_alloca.Ty.Pointee, lhs_alloca)
if load_self1 is not None:
ovl_self1 = load_self1
ovl_result: llvmlite.Value* = self.try_operator_overload(
pool, builder, mod, ovl_self1, rhs, op, trans, 0)
ovl_result: llvmlite.Value* = self.try_operator_overload(pool, builder, mod, ovl_self1, rhs, op, trans, 0)
if ovl_result is not None:
return ovl_result
# 正常翻译 lhs
lhs: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, lhs_node, None, 0, trans)
lhs: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, lhs_node, None, 0, trans)
if lhs is None:
return None
# === 运算符重载路径 2: lhs 是 Ptr(Struct)(如 Counter|t.CPtr 变量 load 后)===
ovl_result2: llvmlite.Value* = self.try_operator_overload(
pool, builder, mod, lhs, rhs, op, trans, 0)
ovl_result2: llvmlite.Value* = self.try_operator_overload(pool, builder, mod, lhs, rhs, op, trans, 0)
if ovl_result2 is not None:
return ovl_result2
# 获取操作数类型信息
lhs_bits: int = self.get_llvm_type_bits(lhs.Ty)
rhs_bits: int = self.get_llvm_type_bits(rhs.Ty)
lhs_bits: int = self.get_llvm_type_bits(lhs.Ty)
rhs_bits: int = self.get_llvm_type_bits(rhs.Ty)
lhs_fbits: int = self.get_llvm_float_bits(lhs.Ty)
rhs_fbits: int = self.get_llvm_float_bits(rhs.Ty)
@@ -1523,17 +1458,11 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
if lhs_bits == 0 and rhs_bits == 0:
if op == ast.OpKind.BitOr or op == ast.OpKind.BitAnd or op == ast.OpKind.BitXor or op == ast.OpKind.LShift or op == ast.OpKind.RShift:
# fail-fast:位运算操作数类型非法,立即终止编译(暴露上游根因)
self.Gen.TypeGenErr.fatal_error(
node,
"位运算操作数类型非法: lhs/rhs 均为非整数类型(指针或结构体),无法执行位运算",
"TypeError")
self.Gen.TypeGenErr.fatal_error(node, "位运算操作数类型非法: lhs/rhs 均为非整数类型(指针或结构体),无法执行位运算", "TypeError")
if op == ast.OpKind.Add:
return llvmlite.build_add(builder, lhs, rhs)
elif op == ast.OpKind.Sub:
return llvmlite.build_sub(builder, lhs, rhs)
elif op == ast.OpKind.Mult:
return llvmlite.build_mul(builder, lhs, rhs)
if op == ast.OpKind.Add: return llvmlite.build_add(builder, lhs, rhs)
elif op == ast.OpKind.Sub: return llvmlite.build_sub(builder, lhs, rhs)
elif op == ast.OpKind.Mult: return llvmlite.build_mul(builder, lhs, rhs)
elif op == ast.OpKind.Div:
# 无符号操作数 → udiv(binop_unsigned 经 _node_type_unsigned 判定,
# 覆盖 sizet/uint64 及变量/数组元素的注解无符号性)。
@@ -1550,14 +1479,10 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
if binop_unsigned != 0:
return llvmlite.build_urem(builder, lhs, rhs)
return llvmlite.build_srem(builder, lhs, rhs)
elif op == ast.OpKind.BitAnd:
return llvmlite.build_and(builder, lhs, rhs)
elif op == ast.OpKind.BitOr:
return llvmlite.build_or(builder, lhs, rhs)
elif op == ast.OpKind.BitXor:
return llvmlite.build_xor(builder, lhs, rhs)
elif op == ast.OpKind.LShift:
return llvmlite.build_shl(builder, lhs, rhs)
elif op == ast.OpKind.BitAnd: return llvmlite.build_and(builder, lhs, rhs)
elif op == ast.OpKind.BitOr: return llvmlite.build_or(builder, lhs, rhs)
elif op == ast.OpKind.BitXor: return llvmlite.build_xor(builder, lhs, rhs)
elif op == ast.OpKind.LShift: return llvmlite.build_shl(builder, lhs, rhs)
elif op == ast.OpKind.RShift:
# 无符号 >> → lshr(逻辑右移),有符号 >> → ashr(算术右移)
# 对齐 TPC ExprGen.emit_binary_op:i8/i16 默认无符号;其余查操作数无符号性
+75 -160
View File
@@ -14,16 +14,11 @@ import lib.core.Gen.Call.CallGenBase as CallGenBase
# ============================================================
# FuncGenBase - FuncGenMixin 拆分(阶段 D):函数属性 / 命名 / mangle / create_function 基础工具
#
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class FuncGenBase(CallGenBase.CallGenBase):
novirtual class FuncGenBase(CallGenBase.CallGenBase):
"""函数属性 / 命名 / mangle / create_function 基础工具"""
# ============================================================
# ============================================================
# extract_func_attrs - 从 decorator_list 提取 c.Attribute 属性
#
# 支持 @c.Attribute(t.attr.xxx()) 和 @c.Attribute(t.attr.xxx) 形式
@@ -35,77 +30,58 @@ class FuncGenBase(CallGenBase.CallGenBase):
decorator_list: list[ast.AST*]*,
imported_modules: str) -> str:
"""从 decorator_list 提取 c.Attribute 属性,返回 LLVM IR 属性字符串"""
if decorator_list is None:
return None
if decorator_list is None: return None
dn: sizet = len(decorator_list)
if dn == 0:
return None
if dn == 0: return None
attrs_buf: str = pool.alloc(256)
if attrs_buf is None:
return None
if attrs_buf is None: return None
attrs_buf[0] = '\0'
found_any: int = 0
for di in range(dn):
deco: ast.AST* = decorator_list.get(di)
if deco is None:
continue
if deco is None: continue
dk: int = deco.kind()
if dk != ast.ASTKind.Call:
continue
if dk != ast.ASTKind.Call: continue
call_node: ast.Call* = ast.Call*(deco)
if call_node.func is None:
continue
if call_node.func is None: continue
cfk: int = call_node.func.kind()
if cfk != ast.ASTKind.Attribute:
continue
if cfk != ast.ASTKind.Attribute: continue
# 检测 c.Attribute
func_attr: ast.Attribute* = ast.Attribute*(call_node.func)
if func_attr.attr is None:
continue
if string.strcmp(func_attr.attr, "Attribute") != 0:
continue
if func_attr.value is None:
continue
if func_attr.attr is None: continue
if string.strcmp(func_attr.attr, "Attribute") != 0: continue
if func_attr.value is None: continue
fvk: int = func_attr.value.kind()
if fvk != ast.ASTKind.Name:
continue
if fvk != ast.ASTKind.Name: continue
c_name: ast.Name* = ast.Name*(func_attr.value)
if c_name.id is None:
continue
if string.strcmp(c_name.id, "c") != 0:
continue
if c_name.id is None: continue
if string.strcmp(c_name.id, "c") != 0: continue
imp_c: int = self.Gen.ImportsGen.is_module_imported(imported_modules, "c")
if imp_c == 0:
continue
if imp_c == 0: continue
# 遍历参数提取属性
if call_node.args is None:
continue
if call_node.args is None: continue
args_list: list[ast.AST*]* = call_node.args
an: sizet = len(args_list)
for ai in range(an):
arg_node: ast.AST* = args_list.get(ai)
if arg_node is None:
continue
if arg_node is None: continue
# 提取属性名(t.attr.xxx / t.attr.xxx() / t.attr.llvm.xxx)
attr_name: str = self._get_attr_name_from_node(arg_node)
if attr_name is None:
continue
if attr_name is None: continue
# B5:section 字符串属性(t.attr.section(".text.startup"))不能内联
# 在函数签名行(llc: expected string constant),必须走属性组
# #N(function_set_attr_group)→ 由 FuncGenDef 单独提取处理。
if string.strcmp(attr_name, "section") == 0:
continue
if string.strcmp(attr_name, "section") == 0: continue
# 映射到 LLVM 属性名并追加
ar: int = self._append_llvm_attr(attrs_buf, attr_name)
if ar != 0:
found_any = 1
if found_any == 0:
return None
if found_any == 0: return None
return attrs_buf
def extract_func_section(self, pool: memhub.MemBuddy*,
decorator_list: list[ast.AST*]*,
@@ -116,38 +92,28 @@ class FuncGenBase(CallGenBase.CallGenBase):
attributes #N = { ... }),不能内联(llc: expected string constant)。
main.vp boot 函数 t.attr.section(".text.startup") 供链接器按段放置。
"""
if pool is None or decorator_list is None:
return None
if pool is None or decorator_list is None: return None
dn: sizet = len(decorator_list)
if dn == 0:
return None
if dn == 0: return None
for di in range(dn):
deco: ast.AST* = decorator_list.get(di)
if deco is None or deco.kind() != ast.ASTKind.Call:
continue
if deco is None or deco.kind() != ast.ASTKind.Call: continue
call_node: ast.Call* = ast.Call*(deco)
if call_node.func is None or call_node.func.kind() != ast.ASTKind.Attribute:
continue
if call_node.func is None or call_node.func.kind() != ast.ASTKind.Attribute: continue
func_attr: ast.Attribute* = ast.Attribute*(call_node.func)
if func_attr.attr is None or string.strcmp(func_attr.attr, "Attribute") != 0:
continue
if call_node.args is None:
continue
if func_attr.attr is None or string.strcmp(func_attr.attr, "Attribute") != 0: continue
if call_node.args is None: continue
args_list: list[ast.AST*]* = call_node.args
an: sizet = len(args_list)
for ai in range(an):
arg_node: ast.AST* = args_list.get(ai)
if arg_node is None:
continue
if arg_node is None: continue
attr_name: str = self._get_attr_name_from_node(arg_node)
if attr_name is None or string.strcmp(attr_name, "section") != 0:
continue
if attr_name is None or string.strcmp(attr_name, "section") != 0: continue
sec_val: str = self._get_attr_call_arg_str(arg_node)
if sec_val is None:
continue
if sec_val is None: continue
sec_buf: str = pool.alloc(128)
if sec_buf is None:
return None
if sec_buf is None: return None
viperlib.snprintf(sec_buf, 128, "\"section\"=\"%s\"", sec_val)
return sec_buf
return None
@@ -159,15 +125,13 @@ class FuncGenBase(CallGenBase.CallGenBase):
- Attribute: t.attr.packed -> "packed"
- Attribute(t.attr.llvm.xxx): t.attr.llvm.nounwind -> "nounwind"
"""
if node is None:
return None
if node is None: return None
k: int = node.kind()
# Call 节点: t.attr.always_inline()
if k == ast.ASTKind.Call:
call: ast.Call* = ast.Call*(node)
if call.func is None or call.func.kind() != ast.ASTKind.Attribute:
return None
if call.func is None or call.func.kind() != ast.ASTKind.Attribute: return None
at: ast.Attribute* = ast.Attribute*(call.func)
return at.attr
@@ -179,55 +143,33 @@ class FuncGenBase(CallGenBase.CallGenBase):
return None
def _get_attr_call_arg_str(self, node: ast.AST*) -> str:
"""取 t.attr.xxx("val") 调用的首参字符串常量(如 section(".text.startup"))"""
if node is None or node.kind() != ast.ASTKind.Call:
return None
if node is None or node.kind() != ast.ASTKind.Call: return None
cl: ast.Call* = ast.Call*(node)
if cl.args is None or len(cl.args) == 0:
return None
if cl.args is None or len(cl.args) == 0: return None
a0: ast.AST* = cl.args.get(0)
if a0 is None or a0.kind() != ast.ASTKind.Constant:
return None
if a0 is None or a0.kind() != ast.ASTKind.Constant: return None
cn: ast.Constant* = ast.Constant*(a0)
if cn.const_kind != ast.CONST_STR:
return None
if cn.const_kind != ast.CONST_STR: return None
return cn.str_val
def _append_llvm_attr(self, attrs_buf: str, attr_name: str) -> int:
"""将属性名映射到 LLVM 属性名并追加到缓冲区
返回 1 表示已追加,0 表示不支持该属性
"""
if attrs_buf is None or attr_name is None:
return 0
if attrs_buf is None or attr_name is None: return 0
# 先确定映射的 LLVM 属性名
llvm_name: str = None
if string.strcmp(attr_name, "always_inline") == 0:
llvm_name = "alwaysinline"
elif string.strcmp(attr_name, "noinline") == 0:
llvm_name = "noinline"
elif string.strcmp(attr_name, "noreturn") == 0:
llvm_name = "noreturn"
elif string.strcmp(attr_name, "pure") == 0:
llvm_name = "readonly"
elif string.strcmp(attr_name, "const") == 0:
llvm_name = "readnone"
elif string.strcmp(attr_name, "nounwind") == 0:
llvm_name = "nounwind"
elif string.strcmp(attr_name, "noredzone") == 0:
llvm_name = "noredzone"
elif string.strcmp(attr_name, "stackrealign") == 0:
# 动态重对齐栈(LLVM 序言 and rsp,-16)。入口函数(_start)由 bootloader
# jmp 进入(rsp≡0 mod 16),而 llc 按 call 约定假设入口 rsp≡8 → 帧整体
# 偏 8 → 所有调用 rsp≡8 → 变参函数保存 xmm 的 movaps #GP。stackrealign
# 使序言动态对齐,与入口约定无关(sched started 后 movaps #GP 根因)。
# 注意:stackrealign 是 LLVM 字符串属性,必须带引号("stackrealign"),
# 与 noinline/nounwind 等枚举属性(无引号)区分,否则 llc 报
# "expected '{' in function body"。
llvm_name = '"stackrealign"'
elif string.strcmp(attr_name, "willreturn") == 0:
llvm_name = "willreturn"
elif string.strcmp(attr_name, "mustprogress") == 0:
llvm_name = "mustprogress"
if string.strcmp(attr_name, "always_inline") == 0: llvm_name = "alwaysinline"
elif string.strcmp(attr_name, "noinline") == 0: llvm_name = "noinline"
elif string.strcmp(attr_name, "noreturn") == 0: llvm_name = "noreturn"
elif string.strcmp(attr_name, "pure") == 0: llvm_name = "readonly"
elif string.strcmp(attr_name, "const") == 0: llvm_name = "readnone"
elif string.strcmp(attr_name, "nounwind") == 0: llvm_name = "nounwind"
elif string.strcmp(attr_name, "noredzone") == 0: llvm_name = "noredzone"
elif string.strcmp(attr_name, "stackrealign") == 0: llvm_name = '"stackrealign"'
elif string.strcmp(attr_name, "willreturn") == 0: llvm_name = "willreturn"
elif string.strcmp(attr_name, "mustprogress") == 0: llvm_name = "mustprogress"
else:
# packed/aligned/section/visibility/weak 等不支持作为函数内联属性
return 0
@@ -240,16 +182,14 @@ class FuncGenBase(CallGenBase.CallGenBase):
def _append_str(self, buf: str, s: str,
max_len: sizet = 256) -> None:
"""将字符串追加到 buf 末尾(有界,防 strcpy 越界写穿定长缓冲)"""
if buf is None or s is None:
return
if buf is None or s is None: return
# 防御:TPV 方法默认参数注册存在缺陷(缺参调用 max_len 落到 0),
# 显式兜底为 256,避免有界写入检查误判丢弃全部属性文本。
if max_len == 0:
max_len = 256
cur_len: sizet = string.strlen(buf)
s_len: sizet = string.strlen(s)
if cur_len + s_len + 1 > max_len:
return # 无剩余容量:丢弃本次追加,避免越界写
if cur_len + s_len + 1 > max_len: return # 无剩余容量:丢弃本次追加,避免越界写 存疑
string.strcpy(buf + cur_len, s)
# ============================================================
# _mangle_name - 为名称添加 SHA1 前缀
@@ -259,21 +199,17 @@ class FuncGenBase(CallGenBase.CallGenBase):
# ============================================================
def _mangle_name(self, trans: HT.Translator*, name: str) -> str:
"""为任意名称添加 SHA1 前缀(不做 main/export 检查)"""
if trans is None or name is None:
return name
if trans.ModuleSha1 is None:
return name
if trans is None or name is None: return name
if trans.ModuleSha1 is None: return name
name_len: sizet = string.strlen(name)
# 已带 SHA1 前缀("{16hex}.")则跳过
# [C10 收敛] 判定走唯一真源 `GenApi.sha1_prefix_len`。旧判据是 `name_len > 17`,
# 与真源的 `>= 17` 只差"前缀之后为空串"这一退化形态(无实际意义),一并对齐。
if GenApi.sha1_prefix_len(name) != 0:
return name
if GenApi.sha1_prefix_len(name) != 0: return name
sha1: str = trans.ModuleSha1
sha1_len: sizet = string.strlen(sha1)
mangled: str = stdlib.malloc(sha1_len + name_len + 2)
if mangled is None:
return name
if mangled is None: return name
string.strcpy(mangled, sha1)
mangled[sha1_len] = '.'
string.strcpy(mangled + sha1_len + 1, name)
@@ -286,17 +222,14 @@ class FuncGenBase(CallGenBase.CallGenBase):
# ============================================================
def _mangle_name_with_sha1(self, sha1: str, name: str) -> str:
"""用指定 SHA1 为名称添加前缀(不做 main/export 检查)"""
if sha1 is None or name is None:
return name
if sha1 is None or name is None: return name
name_len: sizet = string.strlen(name)
# 已带 SHA1 前缀("{16hex}.")则跳过
# [C10 收敛] 判定走唯一真源 `GenApi.sha1_prefix_len`(口径对齐同 _mangle_name)。
if GenApi.sha1_prefix_len(name) != 0:
return name
if GenApi.sha1_prefix_len(name) != 0: return name
sha1_len: sizet = string.strlen(sha1)
mangled: str = stdlib.malloc(sha1_len + name_len + 2)
if mangled is None:
return name
if mangled is None: return name
string.strcpy(mangled, sha1)
mangled[sha1_len] = '.'
string.strcpy(mangled + sha1_len + 1, name)
@@ -313,12 +246,9 @@ class FuncGenBase(CallGenBase.CallGenBase):
def _mangle_func_name(self, trans: HT.Translator*, name: str,
has_export: int) -> str:
"""为函数名添加 SHA1 前缀(检查 main/export)"""
if trans is None or name is None:
return name
if has_export != 0:
return name
if string.strcmp(name, "main") == 0:
return name
if trans is None or name is None: return name
if has_export != 0: return name
if string.strcmp(name, "main") == 0: return name
return self._mangle_name(trans, name)
# ============================================================
# _body_has_raise - 函数体是否含 raise(非 StopIteration)
@@ -335,13 +265,10 @@ class FuncGenBase(CallGenBase.CallGenBase):
bn_f: sizet = len(body_f)
for bi_f in range(bn_f):
stmt_f: ast.AST* = body_f.get(bi_f)
if stmt_f is None:
continue
if stmt_f.kind() != ast.ASTKind.Raise:
continue
if stmt_f is None: continue
if stmt_f.kind() != ast.ASTKind.Raise: continue
rn_f: rawptr[ast.Raise] = rawptr[ast.Raise](stmt_f)
if rn_f is None or rn_f.exc is None:
continue
if rn_f is None or rn_f.exc is None: continue
ek_f: int = rn_f.exc.kind()
is_stop_f: int = 0
if ek_f == ast.ASTKind.Name:
@@ -372,31 +299,24 @@ class FuncGenBase(CallGenBase.CallGenBase):
from_imports: str,
trans: HT.Translator*) -> llvmlite.LLVMType*:
"""解析 @c.CReturn 装饰器为 struct 返回类型;无 CReturn 返回 None"""
if fd is None or fd.decorator_list is None:
return None
if fd is None or fd.decorator_list is None: return None
cr_head: llvmlite.Function* = None
cr_last: llvmlite.Function* = None
cr_count: int = 0
cr_dn: sizet = len(fd.decorator_list)
for cdi in range(cr_dn):
deco_cr: ast.AST* = fd.decorator_list.get(cdi)
if deco_cr is None or deco_cr.kind() != ast.ASTKind.Call:
continue
if deco_cr is None or deco_cr.kind() != ast.ASTKind.Call: continue
deco_call_cr: ast.Call* = ast.Call*(deco_cr)
if deco_call_cr.func is None or deco_call_cr.func.kind() != ast.ASTKind.Attribute:
continue
if deco_call_cr.func is None or deco_call_cr.func.kind() != ast.ASTKind.Attribute: continue
deco_fa_cr: ast.Attribute* = ast.Attribute*(deco_call_cr.func)
if deco_fa_cr.attr is None or string.strcmp(deco_fa_cr.attr, "CReturn") != 0:
continue
if deco_fa_cr.attr is None or string.strcmp(deco_fa_cr.attr, "CReturn") != 0: continue
cr_args: list[ast.AST*]* = deco_call_cr.args
if cr_args is None:
continue
if cr_args is None: continue
cr_an: sizet = len(cr_args)
for cai in range(cr_an):
cr_aty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, cr_args.get(cai), imported_modules, from_imports, trans, 0)
if cr_aty is None:
continue
cr_aty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, cr_args.get(cai), imported_modules, from_imports, trans, 0)
if cr_aty is None: continue
cr_pn: llvmlite.Function* = llvmlite.new_param_node(pool, cr_aty)
if cr_pn is not None:
if cr_head is None:
@@ -417,12 +337,10 @@ class FuncGenBase(CallGenBase.CallGenBase):
args_node: ast.AST*,
ret_ty: llvmlite.LLVMType*) -> llvmlite.Function*:
"""创建 LLVM 函数并添加参数"""
if name is None or mod is None:
return None
if name is None or mod is None: return None
func: llvmlite.Function* = llvmlite.create_function(pool, mod, name, ret_ty)
if func is None:
return None
if func is None: return None
if args_node is not None:
ags: ast.Arguments* = ast.Arguments*(args_node)
@@ -437,18 +355,15 @@ class FuncGenBase(CallGenBase.CallGenBase):
if arg.annotation is not None:
if arg.annotation.kind() == ast.ASTKind.Attribute:
at_cf: ast.Attribute* = ast.Attribute*(arg.annotation)
if at_cf.attr is not None and string.strcmp(at_cf.attr, "CVoid") == 0:
continue
if at_cf.attr is not None and string.strcmp(at_cf.attr, "CVoid") == 0: continue
param_ty: llvmlite.LLVMType* = i32_ty
if arg.annotation is not None:
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, arg.annotation, None, None, None, 0)
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, None, None, None, 0)
if resolved is None:
# [S4 fail-fast] 有注解但解析失败:不再静默用 i32。
# 本函数不传 trans/imports 上下文,解析失败即调用方未补齐
# 上下文(暴露上游,不由本函数兜底)。
self.Gen.TypeGenErr.fatal_error(
arg, f"函数 '{name}' 形参 '{arg.arg}' 类型注解解析失败", "NameError")
self.Gen.TypeGenErr.fatal_error(arg, f"函数 '{name}' 形参 '{arg.arg}' 类型注解解析失败", "NameError")
return None
param_ty = resolved
pname: str = pool.alloc(32)
+93 -199
View File
@@ -17,12 +17,8 @@ import lib.core.Gen.GenApi as GenApi
# ============================================================
# FuncGenDef - 函数声明 / translate_function_def / decorator wrapper
#
# 继承链仅 1 级(TPV self 调用仅支持 1 级父类);跨 Mixin 调用统一走 HandlesExprCall 委托。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class FuncGenDef(CallGenBase.CallGenBase):
novirtual class FuncGenDef(CallGenBase.CallGenBase):
"""函数声明 / translate_function_def / decorator wrapper"""
# forward_declare_functions - 预扫描所有顶层 FunctionDef,创建前向声明
@@ -34,12 +30,10 @@ class FuncGenDef(CallGenBase.CallGenBase):
def forward_declare_functions(self, trans: HT.Translator*,
tree: ast.AST*) -> int:
"""预扫描所有顶层 FunctionDef,创建前向声明"""
if trans is None or tree is None:
return 0
if trans is None or tree is None: return 0
pool: memhub.MemBuddy* = trans.Pool
mod: llvmlite.LLVMModule* = trans.Module
if pool is None or mod is None:
return 0
if pool is None or mod is None: return 0
imported_modules: str = trans._imported_modules
from_imports: str = trans._from_imports
@@ -50,8 +44,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
ch: list[ast.AST*]* = tree.children
if ch is None:
return 0
if ch is None: return 0
# 解析函数签名期间临时切换到"仅声明"模式:
# 签名里的泛型类注解(如 _empty_like(a: ndarray[t.CDouble]))会触发泛型特化,
@@ -78,28 +71,20 @@ class FuncGenDef(CallGenBase.CallGenBase):
pre_i: sizet
for pre_i in range(cn_count):
pre_child: ast.AST* = ch.get(pre_i)
if pre_child is None:
continue
if pre_child.kind() != ast.ASTKind.ClassDef:
continue
if pre_child is None: continue
if pre_child.kind() != ast.ASTKind.ClassDef: continue
pre_cd: ast.ClassDef* = ast.ClassDef*(pre_child)
if pre_cd is None or pre_cd.name is None:
continue
pre_ex: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(
pre_cd.name, trans.ModuleSha1)
if pre_ex is not None and pre_ex.FieldCount > 0:
continue
if pre_cd is None or pre_cd.name is None: continue
pre_ex: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(pre_cd.name, trans.ModuleSha1)
if pre_ex is not None and pre_ex.FieldCount > 0: continue
self.Gen.ClassGenDef.translate_class_def(trans, pre_child)
for ci in range(cn_count):
child: ast.AST* = ch.get(ci)
if child is None:
continue
if child.kind() != ast.ASTKind.FunctionDef:
continue
if child is None: continue
if child.kind() != ast.ASTKind.FunctionDef: continue
fd: ast.FunctionDef* = ast.FunctionDef*(child)
if fd is None or fd.name is None:
continue
if fd is None or fd.name is None: continue
# PEP 695 泛型函数(def f[T](...) -> T)按普通函数编译(TPV 无泛型
# 函数特化机制,与 translate_function_def L678-691 一致):此处先设置
@@ -121,8 +106,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
# 推断返回类型
ret_ty: llvmlite.LLVMType* = None
if fd.returns is not None:
ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, fd.returns, imported_modules, from_imports, trans, 0)
ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, fd.returns, imported_modules, from_imports, trans, 0)
# 单独 t.CExport 返回注解(def free(...) -> t.CExport:)=
# 导出修饰符,无实际返回类型 → Void(根因:CExport 被 map_t_type
# 回退为 i32 → 掉尾检查强制 return i32,mm.vp free 根因)。
@@ -141,15 +125,13 @@ class FuncGenDef(CallGenBase.CallGenBase):
# 否则 declare i32 + define {i64,i64,i64} → llc "value doesn't
# match function result type"——GetMemoryStats 根因)
if ret_ty is None:
ret_ty = self.Gen.FuncGenBase._resolve_creturn_ret_ty(
pool, fd, imported_modules, from_imports, trans)
ret_ty = self.Gen.FuncGenBase._resolve_creturn_ret_ty(pool, fd, imported_modules, from_imports, trans)
if ret_ty is None and fd.returns is not None:
# 有返回注解但解析失败:编译期报错,不静默回退 i32。
# (i32 回退曾导致掉尾检查强制 return i32 / 跨模块调用返回类型错位,
# mm.vp free / GetMemoryStats 根因。)无返回注解函数(def foo():)
# 保留 i32 默认,不在此报错。
self.Gen.TypeGenErr.fatal_error(
fd, "函数返回类型解析失败:注解不可解析", "TypeError")
self.Gen.TypeGenErr.fatal_error(fd, "函数返回类型解析失败:注解不可解析", "TypeError")
return 0
if ret_ty is None:
ret_ty = i32_ty
@@ -193,8 +175,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
continue
# 创建 declare
func: llvmlite.Function* = llvmlite.create_declare(
pool, mod, mangled_name, ret_ty)
func: llvmlite.Function* = llvmlite.create_declare(pool, mod, mangled_name, ret_ty)
if func is None:
if tp_names_fd is not None:
self.Gen.TypeGenBase.clear_generic_context()
@@ -238,21 +219,17 @@ class FuncGenDef(CallGenBase.CallGenBase):
an: sizet = len(alist)
for ai in range(an):
arg: ast.Arg* = ast.Arg*(alist.get(ai))
if arg is None or arg.arg is None:
continue
if arg is None or arg.arg is None: continue
# CVoid 表示空参:跳过
if arg.annotation is not None:
if self.Gen.TypeGenResolve._is_t_attr(arg.annotation, "CVoid", imported_modules) != 0:
continue
if self.Gen.TypeGenResolve._is_t_attr(arg.annotation, "CVoid", imported_modules) != 0: continue
param_ty: llvmlite.LLVMType* = i32_ty
if arg.annotation is not None:
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, arg.annotation, imported_modules, from_imports, trans, 0)
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, imported_modules, from_imports, trans, 0)
if resolved is None:
# [S4 fail-fast] 有注解但解析失败:不再静默用 i32
# (declare 与 define 签名不一致 → ABI 错位,运行期读栈垃圾)
self.Gen.TypeGenErr.fatal_error(
arg, f"前向声明形参 '{arg.arg}' 类型注解解析失败", "NameError")
self.Gen.TypeGenErr.fatal_error(arg, f"前向声明形参 '{arg.arg}' 类型注解解析失败", "NameError")
return 0
# 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致)
# CArray 形参 → 元素指针 ty*(C 数组衰减,与 add_param 一致)
@@ -331,8 +308,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
# 推断返回类型:优先使用返回类型注解
ret_ty: llvmlite.LLVMType* = None
if fd.returns is not None:
ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, fd.returns, imported_modules, from_imports, trans, 0)
ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, fd.returns, imported_modules, from_imports, trans, 0)
# 单独 t.CExport 返回注解(def free(...) -> t.CExport:)= 导出
# 修饰符,无实际返回类型 → Void(根因:CExport 被 map_t_type 回退
# 为 i32 → 掉尾检查强制 return i32,mm.vp free 根因)。
@@ -357,8 +333,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
# declare 成 i32 → 定义阶段 ret {i64,i64,i64} 与 i32 不匹配。
# 公共方法 _resolve_creturn_ret_ty 保证声明/定义两阶段一致)
if ret_ty is None:
ret_ty = self.Gen.FuncGenBase._resolve_creturn_ret_ty(
pool, fd, imported_modules, from_imports, trans)
ret_ty = self.Gen.FuncGenBase._resolve_creturn_ret_ty(pool, fd, imported_modules, from_imports, trans)
# 如果仍然为 None,扫描 return 语句推断(至少返回 i32)
if ret_ty is None:
@@ -371,18 +346,13 @@ class FuncGenDef(CallGenBase.CallGenBase):
if self.Gen.TypeGenErr.body_has_value_return(pool, fd.children) != 0:
rtn_err: str = pool.alloc(256)
if rtn_err is not None:
viperlib.snprintf(
rtn_err, 256,
"函数 '%s' 无返回类型注解却返回了非 None 值,"
"请添加显式返回类型注解(如 -> int)", fd.name)
viperlib.snprintf(rtn_err, 256, "函数 '%s' 无返回类型注解却返回了非 None 值,请添加显式返回类型注解(如 -> int)", fd.name)
self.Gen.TypeGenErr.fatal_error(fd, rtn_err, "TypeError")
return 0
self.Gen.TypeGenErr.fatal_error(
fd, "函数无返回类型注解却返回了非 None 值", "TypeError")
self.Gen.TypeGenErr.fatal_error(fd, "函数无返回类型注解却返回了非 None 值", "TypeError")
return 0
param_types_str: str = self.Gen.TypeGenErr.build_param_types_str(pool, fd.args)
ret_ty = self.Gen.TypeGenErr.infer_return_type(
pool, fd.children, param_types_str)
ret_ty = self.Gen.TypeGenErr.infer_return_type(pool, fd.children, param_types_str)
# 检测是否为外部声明函数(t.CExtern 或 t.State)
# 语义:t.CExtern 忽略 body 体,仅生成 declare(由链接器解析符号)
# t.State = t.CExtern + t.CExport(既是声明又是导出)
@@ -493,14 +463,10 @@ class FuncGenDef(CallGenBase.CallGenBase):
# 外部声明函数:生成 declare(仅声明,不定义)
# 先检查是否已由 forward_declare_functions 创建,避免重复 declare
existing_extern: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, mangled_name)
if existing_extern is not None:
# 已存在前向声明,复用之,不再重复创建
return 0
if existing_extern is not None: return 0
func: llvmlite.Function* = llvmlite.create_declare(
pool, mod, mangled_name, ret_ty)
if func is None:
return 0
func: llvmlite.Function* = llvmlite.create_declare(pool, mod, mangled_name, ret_ty)
if func is None: return 0
# 注册到函数表
max_funcs_extern: int = 256
@@ -523,14 +489,11 @@ class FuncGenDef(CallGenBase.CallGenBase):
continue
param_ty_e: llvmlite.LLVMType* = i32_ty
if arg_e.annotation is not None:
resolved_e: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, arg_e.annotation, imported_modules, from_imports, trans, 0)
resolved_e: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg_e.annotation, imported_modules, from_imports, trans, 0)
if resolved_e is None:
# fail-fast:外部声明函数参数有注解但类型解析失败,
# 不再静默保持 i32(声明签名错误会在 ABI 层暴露)
self.Gen.TypeGenErr.fatal_error(
arg_e, f"参数 '{arg_e.arg}' 类型解析失败: {self.Gen.TypeGenResolve.annotation_to_str(arg_e.annotation)}",
"NameError")
self.Gen.TypeGenErr.fatal_error(arg_e, f"参数 '{arg_e.arg}' 类型解析失败: {self.Gen.TypeGenResolve.annotation_to_str(arg_e.annotation)}", "NameError")
resolved_e = i32_ty # 不可达(fatal_error 已退出)
if resolved_e is not None:
# 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致)
@@ -560,8 +523,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
if func_attrs_e is not None:
llvmlite.function_set_attrs(func, func_attrs_e)
# B5:section 字符串属性走属性组 #N
func_section_e: str = self.Gen.FuncGenBase.extract_func_section(
pool, fd.decorator_list, imported_modules)
func_section_e: str = self.Gen.FuncGenBase.extract_func_section(pool, fd.decorator_list, imported_modules)
if func_section_e is not None:
llvmlite.function_set_attr_group(func, func_section_e)
@@ -583,8 +545,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
if func_attrs_reuse is not None:
llvmlite.function_set_attrs(func, func_attrs_reuse)
# B5:section 字符串属性走属性组 #N
func_section_reuse: str = self.Gen.FuncGenBase.extract_func_section(
pool, fd.decorator_list, imported_modules)
func_section_reuse: str = self.Gen.FuncGenBase.extract_func_section(pool, fd.decorator_list, imported_modules)
if func_section_reuse is not None:
llvmlite.function_set_attr_group(func, func_section_reuse)
else:
@@ -599,8 +560,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
if func_attrs is not None:
llvmlite.function_set_attrs(func, func_attrs)
# B5:section 字符串属性走属性组 #N(LLVM 不接受内联 section="...")
func_section: str = self.Gen.FuncGenBase.extract_func_section(
pool, fd.decorator_list, imported_modules)
func_section: str = self.Gen.FuncGenBase.extract_func_section(pool, fd.decorator_list, imported_modules)
if func_section is not None:
llvmlite.function_set_attr_group(func, func_section)
@@ -640,13 +600,11 @@ class FuncGenDef(CallGenBase.CallGenBase):
continue
param_ty: llvmlite.LLVMType* = i32_ty
if arg.annotation is not None:
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, arg.annotation, imported_modules, from_imports, trans, 0)
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, imported_modules, from_imports, trans, 0)
if resolved is None:
# [S4 fail-fast] 有注解但解析失败:不再静默用 i32
# (形参类型错 → ABI 错位/字段访问错)
self.Gen.TypeGenErr.fatal_error(
arg, f"形参 '{arg.arg}' 类型注解解析失败", "NameError")
self.Gen.TypeGenErr.fatal_error(arg, f"形参 '{arg.arg}' 类型注解解析失败", "NameError")
return 0
# 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致)
# CArray 形参 → 元素指针 ty*(C 数组衰减:final(out: t.CArray[..., N])
@@ -707,8 +665,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
tls_flag_name: str = pool.alloc(128)
if tls_flag_name is not None:
viperlib.snprintf(tls_flag_name, 128, "__tls_init_done_%s", fd.name)
tls_flag_gv: llvmlite.GlobalVariable* = llvmlite.create_global_int(
pool, mod, tls_flag_name, 1, 0)
tls_flag_gv: llvmlite.GlobalVariable* = llvmlite.create_global_int(pool, mod, tls_flag_name, 1, 0)
if tls_flag_gv is not None:
i1_ty_t: llvmlite.LLVMType* = llvmlite.Int1(pool)
if i1_ty_t is not None:
@@ -719,49 +676,40 @@ class FuncGenDef(CallGenBase.CallGenBase):
tls_ref_name: str = pool.alloc(64)
if tls_ref_name is not None:
viperlib.snprintf(tls_ref_name, 64, "@%s", tls_flag_name)
tls_flag_ref: llvmlite.Value* = llvmlite.SSAValue(
pool, tls_gv_ptr_ty, tls_ref_name)
tls_flag_ref: llvmlite.Value* = llvmlite.SSAValue(pool, tls_gv_ptr_ty, tls_ref_name)
if tls_flag_ref is not None:
tls_flag_ld: llvmlite.Value* = llvmlite.build_load(
func_builder, i1_ty_t, tls_flag_ref)
tls_flag_ld: llvmlite.Value* = llvmlite.build_load(func_builder, i1_ty_t, tls_flag_ref)
# 块名唯一化(create_block 不自动编号,同函数同名 label 冲突)
lc_t: int = trans._label_counter
trans._label_counter = lc_t + 1
tls_bb_buf: str = pool.alloc(64)
if tls_bb_buf is not None:
viperlib.snprintf(tls_bb_buf, 64, "tls.skip.%d", lc_t)
tls_skip_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(
pool, func, tls_bb_buf)
tls_skip_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, tls_bb_buf)
viperlib.snprintf(tls_bb_buf, 64, "tls.cont.%d", lc_t)
tls_cont_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(
pool, func, tls_bb_buf)
tls_cont_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, tls_bb_buf)
if tls_skip_bb is not None and tls_cont_bb is not None:
llvmlite.build_cond_br(
func_builder, tls_flag_ld, tls_skip_bb, tls_cont_bb)
llvmlite.build_cond_br(func_builder, tls_flag_ld, tls_skip_bb, tls_cont_bb)
# skip 块:按返回类型生成默认值直接返回
llvmlite.position_at_end(func_builder, tls_skip_bb)
match ret_ty:
case llvmlite.LLVMType.Void():
llvmlite.build_ret_void(func_builder)
case llvmlite.LLVMType.Int(_):
tlz0: llvmlite.Value* = llvmlite.ConstInt(
pool, ret_ty, 0, "0")
tlz0: llvmlite.Value* = llvmlite.ConstInt(pool, ret_ty, 0, "0")
if tlz0 is not None:
llvmlite.build_ret(func_builder, tlz0)
case llvmlite.LLVMType.Float(_):
tlf0: llvmlite.Value* = llvmlite.ConstFloat(
pool, ret_ty, 0.0)
tlf0: llvmlite.Value* = llvmlite.ConstFloat(pool, ret_ty, 0.0)
if tlf0 is not None:
llvmlite.build_ret(func_builder, tlf0)
case _:
tln0: llvmlite.Value* = llvmlite.ConstNull(
pool, ret_ty, "null")
tln0: llvmlite.Value* = llvmlite.ConstNull(pool, ret_ty, "null")
if tln0 is not None:
llvmlite.build_ret(func_builder, tln0)
# cont 块:置标志=1,继续函数体
llvmlite.position_at_end(func_builder, tls_cont_bb)
tlone: llvmlite.Value* = llvmlite.ConstInt(
pool, i1_ty_t, 1, "1")
tlone: llvmlite.Value* = llvmlite.ConstInt(pool, i1_ty_t, 1, "1")
if tlone is not None:
llvmlite.build_store(func_builder, tlone, tls_flag_ref)
@@ -798,13 +746,10 @@ class FuncGenDef(CallGenBase.CallGenBase):
continue
param_ty2: llvmlite.LLVMType* = i32_ty
if arg2.annotation is not None:
resolved2: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, arg2.annotation, imported_modules, from_imports, trans, 0)
resolved2: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg2.annotation, imported_modules, from_imports, trans, 0)
if resolved2 is None:
# fail-fast:参数有注解但类型解析失败,不再静默保持 i32
self.Gen.TypeGenErr.fatal_error(
arg2, f"参数 '{arg2.arg}' 类型解析失败: {self.Gen.TypeGenResolve.annotation_to_str(arg2.annotation)}",
"NameError")
self.Gen.TypeGenErr.fatal_error(arg2, f"参数 '{arg2.arg}' 类型解析失败: {self.Gen.TypeGenResolve.annotation_to_str(arg2.annotation)}", "NameError")
resolved2 = i32_ty # 不可达(fatal_error 已退出)
if resolved2 is not None:
# 与 add_param 保持一致:裸类形参 → Ptr(struct)(对象即指针);
@@ -824,11 +769,9 @@ class FuncGenDef(CallGenBase.CallGenBase):
# 传 pool:泛型 Subscript 返回 mangled name(对齐 HandlesAnnAssign 修复)
cls_nm: str = None
if arg2.annotation is not None:
cls_nm = self.Gen.TypeGenResolve.extract_class_name_from_annotation(
arg2.annotation, imported_modules, pool, trans._from_imports)
cls_nm = self.Gen.TypeGenResolve.extract_class_name_from_annotation(arg2.annotation, imported_modules, pool, trans._from_imports)
if cls_nm is not None:
self.Gen.VarGen.set_var_annot_class_name(
trans.SymTab, arg2.arg, cls_nm)
self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, arg2.arg, cls_nm)
# t.CVolatile 形参:声明期标记,函数体内该参数名的
# load/store 带 volatile(volatile 参数对象的读改写不得
# 被优化器提升/合并,如自旋等待入参)。
@@ -837,28 +780,19 @@ class FuncGenDef(CallGenBase.CallGenBase):
# 是否含 t.CConst,不看指针层数)——TPC 形参登记点
# HandlesFunctions 的 IsParam=True 用同一条件,两侧逐条
# 对齐(见 Debugger/type-descriptors.md 已知差异)。
if self.Gen.TypeGenErr.has_decorator_marker(
arg2.annotation, "CConst", 0) != 0:
self.Gen.VarGen.set_var_const(
trans.SymTab, arg2.arg)
if self.Gen.TypeGenErr.has_decorator_marker(
arg2.annotation, "CVolatile", 0) != 0:
self.Gen.VarGen.set_var_volatile(
trans.SymTab, arg2.arg)
if self.Gen.TypeGenErr.has_decorator_marker(arg2.annotation, "CConst", 0) != 0:
self.Gen.VarGen.set_var_const(trans.SymTab, arg2.arg)
if self.Gen.TypeGenErr.has_decorator_marker(arg2.annotation, "CVolatile", 0) != 0:
self.Gen.VarGen.set_var_volatile(trans.SymTab, arg2.arg)
# rawptr[t.CVolatile | T] 形参(volatile 指针指向物):
# 函数体内该参数解引用(p[i]/p.field/c.Deref(p))带 volatile。
if self.Gen.TypeGenErr.has_pointee_volatile_marker(
arg2.annotation) != 0:
self.Gen.VarGen.set_var_pointee_volatile(
trans.SymTab, arg2.arg)
if self.Gen.TypeGenErr.has_pointee_volatile_marker(arg2.annotation) != 0:
self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, arg2.arg)
pname2: str = pool.alloc(32)
if pname2 is not None:
viperlib.snprintf(pname2, 32, "%%%s", arg2.arg)
param_val: llvmlite.Value* = llvmlite.SSAValue(
pool, param_ty2, pname2)
vol_p2: int = self.Gen.VarGen.var_is_volatile(
self.Gen.VarGen.lookup_var_entry(
trans.SymTab, arg2.arg))
param_val: llvmlite.Value* = llvmlite.SSAValue(pool, param_ty2, pname2)
vol_p2: int = self.Gen.VarGen.var_is_volatile(self.Gen.VarGen.lookup_var_entry(trans.SymTab, arg2.arg))
llvmlite.build_store(func_builder, param_val, alloca, vol_p2)
# *args 变长参数:创建 va_list 缓冲区 + 调用 va_start + 注册到符号表
@@ -879,12 +813,10 @@ class FuncGenDef(CallGenBase.CallGenBase):
i8_ty_va: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty_va: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty_va)
va_buf_ty: llvmlite.LLVMType* = llvmlite.Array(pool, i8_ty_va, 24)
va_list_alloca: llvmlite.Value* = llvmlite.build_alloca_aligned(
func_builder, va_buf_ty, 16)
va_list_alloca: llvmlite.Value* = llvmlite.build_alloca_aligned(func_builder, va_buf_ty, 16)
if va_list_alloca is not None:
# i8* 地址(指向 24 字节 va_list 缓冲区)——vararg 名的值语义
va_list_addr: llvmlite.Value* = llvmlite.build_bitcast(
func_builder, va_list_alloca, i8_ptr_ty_va)
va_list_addr: llvmlite.Value* = llvmlite.build_bitcast(func_builder, va_list_alloca, i8_ptr_ty_va)
if va_list_addr is not None:
# 注册到符号表(translate_name_value 对 vararg 名特殊处理返回地址)
self.Gen.VarGen.define_var(trans.SymTab, vararg_name_str, va_list_alloca)
@@ -916,10 +848,8 @@ class FuncGenDef(CallGenBase.CallGenBase):
i32_ty_eh2: llvmlite.LLVMType* = llvmlite.Int32(pool)
i32_ptr_ty_eh2: llvmlite.LLVMType* = llvmlite.Ptr(pool, i32_ty_eh2)
if i8_ptr_ptr_ty_eh2 is not None and i32_ptr_ty_eh2 is not None:
msg_out_ref: llvmlite.Value* = llvmlite.SSAValue(
pool, i8_ptr_ptr_ty_eh2, "%__eh_msg_out__")
code_out_ref: llvmlite.Value* = llvmlite.SSAValue(
pool, i32_ptr_ty_eh2, "%__eh_code_out__")
msg_out_ref: llvmlite.Value* = llvmlite.SSAValue(pool, i8_ptr_ptr_ty_eh2, "%__eh_msg_out__")
code_out_ref: llvmlite.Value* = llvmlite.SSAValue(pool, i32_ptr_ty_eh2, "%__eh_code_out__")
trans._eh_msg_out_param = msg_out_ref
trans._eh_code_out_param = code_out_ref
trans._cur_func_has_eh = 1
@@ -970,9 +900,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
# 嵌套函数定义前:预扫描其链内 nonlocal 并建堆
# (不同层捕获不同变量的场景,见 _prepare_chain_nonlocals)
if stmt2.kind() == ast.ASTKind.FunctionDef:
self.Gen.FuncGen._prepare_chain_nonlocals(
trans, stmt2, pool, func_builder, mod,
llvmlite.Int8(pool), llvmlite.Ptr(pool, llvmlite.Int8(pool)))
self.Gen.FuncGen._prepare_chain_nonlocals(trans, stmt2, pool, func_builder, mod, llvmlite.Int8(pool), llvmlite.Ptr(pool, llvmlite.Int8(pool)))
self.Gen.StmtGen.translate_stmt(trans, stmt2)
# 如果函数体最后一条语句不是 Return,添加隐式 ret
@@ -1026,12 +954,10 @@ class FuncGenDef(CallGenBase.CallGenBase):
# ② 裸名 CVoid(from t import CVoid)③ -> None(CONST_NONE);
# ①②统一经既有判据 TypeGenResolve._is_cvoid_marker 判定(不新增名字白名单)。
if _is_void == 0 and fd.returns is not None:
if self.Gen.TypeGenResolve._is_cvoid_marker(
fd.returns, imported_modules) != 0:
if self.Gen.TypeGenResolve._is_cvoid_marker(fd.returns, imported_modules) != 0:
_is_void = 1
elif fd.returns.kind() == ast.ASTKind.Constant:
ret_none_cn: ast.Constant* = (
ast.Constant*)(fd.returns)
ret_none_cn: ast.Constant* = (ast.Constant*)(fd.returns)
if ret_none_cn.const_kind == ast.CONST_NONE:
_is_void = 1
if _is_void != 0:
@@ -1068,10 +994,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
rt_name = "?"
err_fn: str = pool.alloc(256)
if err_fn is not None:
viperlib.snprintf(
err_fn, 256,
"函数 '%s' 流程掉出函数末尾但未显式 return(返回类型 %s),"
"请补显式 return(如 return 0 / return null)", fd.name, rt_name)
viperlib.snprintf(err_fn, 256, "函数 '%s' 流程掉出函数末尾但未显式 return(返回类型 %s),请补显式 return(如 return 0 / return null)", fd.name, rt_name)
self.Gen.TypeGenErr.fatal_error(node, err_fn, "TypeError")
self.Gen.TypeGenErr.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError")
else:
@@ -1105,9 +1028,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
if wb_name is not None:
viperlib.snprintf(wb_name, 128, "__decor_wrap_%s", fd.name)
self.Gen.ClassGenBase.register_decorator(pool, fd.name, wb_name, decor_arg0)
self._gen_decor_wrapper(
trans, pool, mod, func, fd.name, wb_name,
decor_handler, decor_arg0)
self._gen_decor_wrapper(trans, pool, mod, func, fd.name, wb_name, decor_handler, decor_arg0)
return 0
# ============================================================
@@ -1165,10 +1086,8 @@ class FuncGenDef(CallGenBase.CallGenBase):
pp = llvmlite.param_get_next(pp)
# ---- 创建 wrapper 函数并添加参数(名字 %a0..%aN)----
wrapper: llvmlite.Function* = llvmlite.create_function(
pool, mod, wrapper_name, ret_ty)
if wrapper is None:
return None
wrapper: llvmlite.Function* = llvmlite.create_function(pool, mod, wrapper_name, ret_ty)
if wrapper is None: return None
pi: int = 0
for pi in range(n_params):
pname_w: str = pool.alloc(16)
@@ -1217,8 +1136,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
return None
rec_val: llvmlite.Value* = llvmlite.build_load(wb, i8_ty, rec_flag_ref)
rec_zero: llvmlite.Value* = llvmlite.ConstInt(pool, i8_ty, 0, "0")
rec_is: llvmlite.Value* = llvmlite.build_icmp(
wb, llvmlite.ICMP_NE, rec_val, rec_zero)
rec_is: llvmlite.Value* = llvmlite.build_icmp(wb, llvmlite.ICMP_NE, rec_val, rec_zero)
llvmlite.build_cond_br(wb, rec_is, rec_bb, dec_bb)
# recursive_call:直接调用原函数返回(跳过所有装饰逻辑)
llvmlite.position_at_end(wb, rec_bb)
@@ -1229,8 +1147,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
if an_r is None:
continue
viperlib.snprintf(an_r, 16, "%%a%d", ri)
av_r: llvmlite.Value* = llvmlite.SSAValue(
pool, (llvmlite.LLVMType*)(param_tys[ri]), an_r)
av_r: llvmlite.Value* = llvmlite.SSAValue(pool, (llvmlite.LLVMType*)(param_tys[ri]), an_r)
if av_r is not None:
llvmlite.value_set_next(av_r, None)
if rec_args is None:
@@ -1245,8 +1162,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
llvmlite.build_call(wb, orig_call_name, rec_args, n_params, ret_ty, 0)
llvmlite.build_ret_void(wb)
else:
rc_res: llvmlite.Value* = llvmlite.build_call(
wb, orig_call_name, rec_args, n_params, ret_ty, 0)
rc_res: llvmlite.Value* = llvmlite.build_call(wb, orig_call_name, rec_args, n_params, ret_ty, 0)
if rc_res is not None:
llvmlite.build_ret(wb, rc_res)
else:
@@ -1271,26 +1187,22 @@ class FuncGenDef(CallGenBase.CallGenBase):
fields_head: llvmlite.Function* = None
fk: int = 0
for fk in range(n_params - 1, -1, -1):
pn_n: llvmlite.Function* = llvmlite.new_param_node(
pool, (llvmlite.LLVMType*)(param_tys[fk]))
pn_n: llvmlite.Function* = llvmlite.new_param_node(pool, (llvmlite.LLVMType*)(param_tys[fk]))
if pn_n is not None:
pn_n.Next = fields_head
fields_head = pn_n
args_ty: llvmlite.LLVMType* = llvmlite.Struct(
pool, fields_head, n_params, None)
args_ty: llvmlite.LLVMType* = llvmlite.Struct(pool, fields_head, n_params, None)
if args_ty is not None:
args_alloca = llvmlite.build_alloca(wb, args_ty)
fi2: int = 0
for fi2 in range(n_params):
fld_ty: llvmlite.LLVMType* = (llvmlite.LLVMType*)(param_tys[fi2])
fld_ptr: llvmlite.Value* = llvmlite.build_gep_struct(
wb, args_ty, fld_ty, args_alloca, fi2)
fld_ptr: llvmlite.Value* = llvmlite.build_gep_struct(wb, args_ty, fld_ty, args_alloca, fi2)
if fld_ptr is not None:
fld_nm: str = pool.alloc(16)
if fld_nm is not None:
viperlib.snprintf(fld_nm, 16, "%%a%d", fi2)
fld_v: llvmlite.Value* = llvmlite.SSAValue(
pool, fld_ty, fld_nm)
fld_v: llvmlite.Value* = llvmlite.SSAValue(pool, fld_ty, fld_nm)
if fld_v is not None:
llvmlite.build_store(wb, fld_v, fld_ptr)
args_ptr = llvmlite.build_bitcast(wb, args_alloca, i8_ptr_ty)
@@ -1313,15 +1225,13 @@ class FuncGenDef(CallGenBase.CallGenBase):
llvmlite.build_store(wb, ret_zero, ret_alloca)
# 4. 函数名字符串常量
fn_str: llvmlite.Value* = self.Gen.ExprGenConst.create_global_string(
wb, pool, mod, func_name, trans)
fn_str: llvmlite.Value* = self.Gen.ExprGenConst.create_global_string(wb, pool, mod, func_name, trans)
if fn_str is None:
fn_str = llvmlite.ConstNull(pool, i8_ptr_ty, "null")
# 5. handler 声明(未翻译时 declare,固定签名 i32 (i8*,i8*,i32,i8*,i8*,i8*))
if self.Gen.CallGenBase.find_func_in_module(mod, handler_name) is None:
handler_d: llvmlite.Function* = llvmlite.create_declare(
pool, mod, handler_name, i32_ty)
handler_d: llvmlite.Function* = llvmlite.create_declare(pool, mod, handler_name, i32_ty)
if handler_d is not None:
llvmlite.add_param(pool, handler_d, i8_ptr_ty, "ctx")
llvmlite.add_param(pool, handler_d, i8_ptr_ty, "func_name")
@@ -1336,18 +1246,12 @@ class FuncGenDef(CallGenBase.CallGenBase):
null_dec: llvmlite.Value* = llvmlite.ConstNull(pool, i8_ptr_ty, "null")
# 参数链表(6 个独立值):ctx_ptr → fn_str → 0 → args_ptr → null → null
# 注意:不能 self 链接(null.Next = null 会让 build_call 遍历死循环)
if ctx_ptr is not None:
llvmlite.value_set_next(ctx_ptr, fn_str)
if fn_str is not None:
llvmlite.value_set_next(fn_str, ph0)
if ph0 is not None:
llvmlite.value_set_next(ph0, args_ptr)
if args_ptr is not None:
llvmlite.value_set_next(args_ptr, null_ret)
if null_ret is not None:
llvmlite.value_set_next(null_ret, null_dec)
n_calls: llvmlite.Value* = llvmlite.build_call(
wb, handler_name, ctx_ptr, 6, i32_ty, 0)
if ctx_ptr is not None: llvmlite.value_set_next(ctx_ptr, fn_str)
if fn_str is not None: llvmlite.value_set_next(fn_str, ph0)
if ph0 is not None: llvmlite.value_set_next(ph0, args_ptr)
if args_ptr is not None: llvmlite.value_set_next(args_ptr, null_ret)
if null_ret is not None: llvmlite.value_set_next(null_ret, null_dec)
n_calls: llvmlite.Value* = llvmlite.build_call(wb, handler_name, ctx_ptr, 6, i32_ty, 0)
# 7. 计数器 alloca(TPV 用 alloca 计数器替代 phi)
cnt_alloca: llvmlite.Value* = llvmlite.build_alloca(wb, i32_ty)
@@ -1359,8 +1263,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
# 8. loop.header:cur = load cnt; cur < n_calls → body / post
llvmlite.position_at_end(wb, loop_h_bb)
cur_i: llvmlite.Value* = llvmlite.build_load(wb, i32_ty, cnt_alloca)
loop_cond: llvmlite.Value* = llvmlite.build_icmp(
wb, llvmlite.ICMP_SLT, cur_i, n_calls)
loop_cond: llvmlite.Value* = llvmlite.build_icmp(wb, llvmlite.ICMP_SLT, cur_i, n_calls)
llvmlite.build_cond_br(wb, loop_cond, loop_b_bb, post_bb)
# 9. loop.body:读回参数(装饰器可能已修改)→ 调用原函数 → store ret
@@ -1370,10 +1273,8 @@ class FuncGenDef(CallGenBase.CallGenBase):
k: int = 0
for k in range(n_params):
fld_ty_k: llvmlite.LLVMType* = (llvmlite.LLVMType*)(param_tys[k])
fld_pk: llvmlite.Value* = llvmlite.build_gep_struct(
wb, args_ty, fld_ty_k, args_alloca, k)
if fld_pk is None:
continue
fld_pk: llvmlite.Value* = llvmlite.build_gep_struct(wb, args_ty, fld_ty_k, args_alloca, k)
if fld_pk is None: continue
fld_vk: llvmlite.Value* = llvmlite.build_load(wb, fld_ty_k, fld_pk)
if fld_vk is not None:
llvmlite.value_set_next(fld_vk, None)
@@ -1384,12 +1285,10 @@ class FuncGenDef(CallGenBase.CallGenBase):
while ct.Next is not None:
ct = ct.Next
llvmlite.value_set_next(ct, fld_vk)
res_v: llvmlite.Value* = llvmlite.build_call(
wb, orig_call_name, call_args, n_params, ret_ty, 0)
res_v: llvmlite.Value* = llvmlite.build_call(wb, orig_call_name, call_args, n_params, ret_ty, 0)
if ret_alloca is not None and res_v is not None:
llvmlite.build_store(wb, res_v, ret_alloca)
nxt_i: llvmlite.Value* = llvmlite.build_add(
wb, cur_i, llvmlite.ConstInt(pool, i32_ty, 1, "1"))
nxt_i: llvmlite.Value* = llvmlite.build_add(wb, cur_i, llvmlite.ConstInt(pool, i32_ty, 1, "1"))
if nxt_i is not None and cnt_alloca is not None:
llvmlite.build_store(wb, nxt_i, cnt_alloca)
llvmlite.build_br(wb, loop_h_bb)
@@ -1401,16 +1300,11 @@ class FuncGenDef(CallGenBase.CallGenBase):
ret_ptr = llvmlite.build_bitcast(wb, ret_alloca, i8_ptr_ty)
ph1: llvmlite.Value* = llvmlite.ConstInt(pool, i32_ty, 1, "1")
# 后置参数链:ctx_ptr → fn_str → 1 → args_ptr → ret_ptr → null
if ctx_ptr is not None:
llvmlite.value_set_next(ctx_ptr, fn_str)
if fn_str is not None:
llvmlite.value_set_next(fn_str, ph1)
if ph1 is not None:
llvmlite.value_set_next(ph1, args_ptr)
if args_ptr is not None:
llvmlite.value_set_next(args_ptr, ret_ptr)
if ret_ptr is not None:
llvmlite.value_set_next(ret_ptr, null_dec)
if ctx_ptr is not None: llvmlite.value_set_next(ctx_ptr, fn_str)
if fn_str is not None: llvmlite.value_set_next(fn_str, ph1)
if ph1 is not None: llvmlite.value_set_next(ph1, args_ptr)
if args_ptr is not None: llvmlite.value_set_next(args_ptr, ret_ptr)
if ret_ptr is not None: llvmlite.value_set_next(ret_ptr, null_dec)
llvmlite.build_call(wb, handler_name, ctx_ptr, 6, i32_ty, 0)
if rec_flag_ref is not None:
rec_zero2: llvmlite.Value* = llvmlite.ConstInt(pool, i8_ty, 0, "0")
+112 -256
View File
@@ -15,55 +15,19 @@ import lib.core.Gen.GenApi as GenApi
# ============================================================
# FuncGenMixin - 函数/方法声明与翻译 Mixin(对象化 P5-1,wiki/14-oo-refactor.md)
#
# 从 HandlesFunctions.vp 迁移:模块级纯函数(trans 首参,无全局状态)
# → 类方法(self 替代,trans 参数保留)。
#
# 迁移原则(与 P2/P3/P4 一致,行为零变化):
# 1. 方法保留原函数签名(含 trans 首参),仅函数体内的
# 本模块函数调用改为 self.xxx(...)
# 2. 外部模块调用(HandlesExprCall.xxx/HandlesType.xxx 等)保留模块前缀
# 3. HandlesFunctions.vp 原函数保留为"委托":本地模块级单例 _g_gen
# (BuildPipeline/main 注入)cast 成 Generator 类型
#
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整)。
# FuncGenMixin - 函数/方法声明与翻译 Mixin
# ============================================================
# ============================================================
# HandlesFunctions - 函数定义处理(trans 单参模式)
#
# 参考 Python 版 TransPyC FunctionHandle
#
# 函数有自己的局部作用域,通过 HandlesVar.enter_scope/exit_scope
# 管理嵌套作用域链,翻译函数体前进入函数作用域,翻译完退出。
# ============================================================
# 作用域类型常量(本地副本,与 HandlesFunctions.vp 保持一致)
SCOPE_FUNCTION: t.CDefine = 1
# 作用域类型常量 存疑
define SCOPE_FUNCTION = 1
# ============================================================
# FuncGenMixin - 函数属性/命名/声明/翻译
# ============================================================
@t.NoVTable
class FuncGenMixin(CallGenBase.CallGenBase):
novirtual class FuncGenMixin(CallGenBase.CallGenBase):
"""函数/方法翻译 Mixin(纯方法化迁移,无状态字段)"""
# ============================================================
# translate_nested_function_def - 嵌套函数提升 + 闭包创建
#
@@ -74,12 +38,10 @@ class FuncGenMixin(CallGenBase.CallGenBase):
# 闭包结构: {i8* fn_ptr, i8* env_ptr} (16 字节, malloc 分配)
# Env 结构: {i8* ptr0, i8* ptr1, ...} (每个 nonlocal 变量 8 字节,指向父函数 alloca)
# ============================================================
def translate_nested_function_def(self, trans: HT.Translator*,
node: ast.AST*) -> int:
def translate_nested_function_def(self, trans: HT.Translator*, node: ast.AST*) -> int:
"""翻译嵌套函数定义:提升为顶层函数 + 创建闭包"""
fd: ast.FunctionDef* = ast.FunctionDef*(node)
if fd is None or fd.name is None:
return 0
if fd is None or fd.name is None: return 0
pool: memhub.MemBuddy* = trans.Pool
mod: llvmlite.LLVMModule* = trans.Module
@@ -96,10 +58,8 @@ class FuncGenMixin(CallGenBase.CallGenBase):
mangled_promoted: str = self.Gen.FuncGenBase._mangle_name(trans, promoted_name)
# 2. 创建提升后的函数: define i32 @__closure_{name}(i8* %env, args...)
func: llvmlite.Function* = llvmlite.create_function(
pool, mod, mangled_promoted, i32_ty)
if func is None:
return 0
func: llvmlite.Function* = llvmlite.create_function(pool, mod, mangled_promoted, i32_ty)
if func is None: return 0
llvmlite.add_param(pool, func, i8_ptr_ty, "%env")
# 2a. 嵌套函数参数:加入提升函数签名(i8* %env, 参数...),
@@ -117,15 +77,12 @@ class FuncGenMixin(CallGenBase.CallGenBase):
an_n: sizet = len(alist_n)
for ai_n in range(an_n):
arg_n: ast.Arg* = ast.Arg*(alist_n.get(ai_n))
if arg_n is None or arg_n.arg is None:
continue
if arg_n is None or arg_n.arg is None: continue
if arg_n.annotation is not None:
if self.Gen.TypeGenResolve._is_t_attr(arg_n.annotation, "CVoid", imported_modules) != 0:
continue
if self.Gen.TypeGenResolve._is_t_attr(arg_n.annotation, "CVoid", imported_modules) != 0: continue
pty_n: llvmlite.LLVMType* = i32_ty
if arg_n.annotation is not None:
resolved_n: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, arg_n.annotation, imported_modules, from_imports, trans, 0)
resolved_n: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg_n.annotation, imported_modules, from_imports, trans, 0)
if resolved_n is not None:
match resolved_n:
case llvmlite.LLVMType.Struct(_, _, _):
@@ -135,8 +92,7 @@ class FuncGenMixin(CallGenBase.CallGenBase):
case _:
pty_n = resolved_n
if param_count < 64 and param_tys is not None:
pty_slot_n: str | t.CPtr = (t.CPtr)(
uint64(param_tys) + param_count * 8)
pty_slot_n: str | t.CPtr = (t.CPtr)(uint64(param_tys) + param_count * 8)
pty_slot_n[0] = pty_n
pname_n: str = pool.alloc(32)
if pname_n is not None:
@@ -146,11 +102,9 @@ class FuncGenMixin(CallGenBase.CallGenBase):
# 3. 创建 entry 块 + builder
entry_blk: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, "entry")
if entry_blk is None:
return 0
if entry_blk is None: return 0
func_builder: llvmlite.IRBuilder* = llvmlite.new_builder(pool, func)
if func_builder is None:
return 0
if func_builder is None: return 0
llvmlite.position_at_end(func_builder, entry_blk)
# 4. 进入嵌套函数作用域(嵌套符号表)
@@ -191,36 +145,27 @@ class FuncGenMixin(CallGenBase.CallGenBase):
if p_alloca is not None:
self.Gen.VarGen.define_var(trans.SymTab, arg_p.arg, p_alloca)
if arg_p.annotation is not None:
cls_nm_p: str = self.Gen.TypeGenResolve.extract_class_name_from_annotation(
arg_p.annotation, imported_modules, pool, trans._from_imports)
cls_nm_p: str = self.Gen.TypeGenResolve.extract_class_name_from_annotation(arg_p.annotation, imported_modules, pool, trans._from_imports)
if cls_nm_p is not None:
self.Gen.VarGen.set_var_annot_class_name(
trans.SymTab, arg_p.arg, cls_nm_p)
self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, arg_p.arg, cls_nm_p)
# const 形参:沿用 TPC 形参的历史判据(只看注解是否含
# t.CConst,不看指针层数),两侧逐条对齐(见
# Debugger/type-descriptors.md 已知差异)。
if self.Gen.TypeGenErr.has_decorator_marker(
arg_p.annotation, "CConst", 0) != 0:
self.Gen.VarGen.set_var_const(
trans.SymTab, arg_p.arg)
if self.Gen.TypeGenErr.has_decorator_marker(arg_p.annotation, "CConst", 0) != 0:
self.Gen.VarGen.set_var_const(trans.SymTab, arg_p.arg)
# t.CVolatile 形参:声明期标记(与 FuncGenDef 主路径同款),
# 函数体内该参数名的 load/store 带 volatile。
if self.Gen.TypeGenErr.has_decorator_marker(
arg_p.annotation, "CVolatile", 0) != 0:
self.Gen.VarGen.set_var_volatile(
trans.SymTab, arg_p.arg)
if self.Gen.TypeGenErr.has_decorator_marker(arg_p.annotation, "CVolatile", 0) != 0:
self.Gen.VarGen.set_var_volatile(trans.SymTab, arg_p.arg)
# rawptr[t.CVolatile | T] 形参(volatile 指针指向物):
# 函数体内该参数解引用带 volatile(与 FuncGenDef 主路径同款)。
if self.Gen.TypeGenErr.has_pointee_volatile_marker(
arg_p.annotation) != 0:
self.Gen.VarGen.set_var_pointee_volatile(
trans.SymTab, arg_p.arg)
if self.Gen.TypeGenErr.has_pointee_volatile_marker(arg_p.annotation) != 0:
self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, arg_p.arg)
pname2_n: str = pool.alloc(32)
if pname2_n is not None:
viperlib.snprintf(pname2_n, 32, "%%%s", arg_p.arg)
p_val: llvmlite.Value* = llvmlite.SSAValue(pool, pty2_n, pname2_n)
vol_pn: int = self.Gen.VarGen.var_is_volatile(
self.Gen.VarGen.lookup_var_entry(trans.SymTab, arg_p.arg))
vol_pn: int = self.Gen.VarGen.var_is_volatile(self.Gen.VarGen.lookup_var_entry(trans.SymTab, arg_p.arg))
llvmlite.build_store(func_builder, p_val, p_alloca, vol_pn)
idx_p += 1
@@ -326,8 +271,7 @@ class FuncGenMixin(CallGenBase.CallGenBase):
env_size_val: llvmlite.Value* = llvmlite.const_int64(pool, env_size)
if env_size_val is not None:
env_size_val.Next = None
env_ptr = llvmlite.build_call(
parent_builder, "malloc", env_size_val, 1, i8_ptr_ty, 0)
env_ptr = llvmlite.build_call(parent_builder, "malloc", env_size_val, 1, i8_ptr_ty, 0)
# 为每个 nonlocal 变量建立堆存储并注册到 env:
# 运行时 env 链式共享(无需编译期映射——映射存编译期 Value 对象
@@ -352,44 +296,33 @@ class FuncGenMixin(CallGenBase.CallGenBase):
# 1. 优先查全局堆地址映射(_prepare_chain_nonlocals 已为
# 链内 nonlocal 建堆并 store 到 @nlheap.*;不同层捕获
# 不同变量时(ClosureTest2 Test 7)level2 的 b 经此共享)
gname_ck: str = self._nl_heap_global_name(
pool, trans, nl_name)
if gname_ck is not None \
and self._nl_heap_global_exists(mod, gname_ck) != 0:
gv_ref0: llvmlite.Value* = self._nl_heap_global_ref(
pool, trans, nl_name)
gname_ck: str = self._nl_heap_global_name(pool, trans, nl_name)
if gname_ck is not None and self._nl_heap_global_exists(mod, gname_ck) != 0:
gv_ref0: llvmlite.Value* = self._nl_heap_global_ref(pool, trans, nl_name)
if gv_ref0 is not None:
heap_store = llvmlite.build_load(
parent_builder, i8_ptr_ty, gv_ref0)
heap_store = llvmlite.build_load(parent_builder, i8_ptr_ty, gv_ref0)
if heap_store is None:
local_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_current(
trans.SymTab, nl_name)
local_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, nl_name)
if local_alloca is not None and local_alloca.Ty is not None:
# 父函数局部变量:新建堆存储 + 拷贝当前值 + 重定向
nl_load_ty: llvmlite.LLVMType* = local_alloca.Ty.Pointee
if nl_load_ty is not None:
cur_val_nl: llvmlite.Value* = llvmlite.build_load(
parent_builder, nl_load_ty, local_alloca)
cur_val_nl: llvmlite.Value* = llvmlite.build_load(parent_builder, nl_load_ty, local_alloca)
# 堆存储大小按类型字节数:数组(如 [4 x i32]=16 字节)
# 不能固定 8 字节(越界写崩溃);指针/标量 ≥ 8 字节
st_size: int = self._type_byte_size(pool, nl_load_ty)
st_size_val: llvmlite.Value* = llvmlite.const_int64(
pool, st_size)
st_size_val: llvmlite.Value* = llvmlite.const_int64(pool, st_size)
if st_size_val is not None:
st_size_val.Next = None
var_storage: llvmlite.Value* = llvmlite.build_call(
parent_builder, "malloc", st_size_val, 1, i8_ptr_ty, 0)
var_storage: llvmlite.Value* = llvmlite.build_call(parent_builder, "malloc", st_size_val, 1, i8_ptr_ty, 0)
if var_storage is not None:
# 拷贝当前值到堆存储
st_slot_nl: llvmlite.Value* = llvmlite.build_bitcast(
parent_builder, var_storage, llvmlite.Ptr(pool, nl_load_ty))
st_slot_nl: llvmlite.Value* = llvmlite.build_bitcast(parent_builder, var_storage, llvmlite.Ptr(pool, nl_load_ty))
if st_slot_nl is not None and cur_val_nl is not None:
llvmlite.build_store(parent_builder, cur_val_nl, st_slot_nl)
# 父函数 VarEntry.Alloca 重定向到堆(父函数读写走共享堆)
ve_nl: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, nl_name)
heap_typed: llvmlite.Value* = llvmlite.build_bitcast(
parent_builder, var_storage, llvmlite.Ptr(pool, nl_load_ty))
ve_nl: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nl_name)
heap_typed: llvmlite.Value* = llvmlite.build_bitcast(parent_builder, var_storage, llvmlite.Ptr(pool, nl_load_ty))
if ve_nl is not None and heap_typed is not None:
ve_nl.Alloca = heap_typed
# 记录到全局映射(后续层/父函数可见)
@@ -405,8 +338,7 @@ class FuncGenMixin(CallGenBase.CallGenBase):
llvmlite.module_add_global(mod, gv_new)
gv_ref_new = self._nl_heap_global_ref(pool, trans, nl_name)
if gv_ref_new is not None:
llvmlite.build_store(
parent_builder, var_storage, gv_ref_new)
llvmlite.build_store(parent_builder, var_storage, gv_ref_new)
heap_store = var_storage
else:
# 父函数中该变量是 nonlocal(多层嵌套):从父函数 env
@@ -416,11 +348,9 @@ class FuncGenMixin(CallGenBase.CallGenBase):
continue
# env[ni] = 堆存储地址(共享)
offset_val: llvmlite.Value* = llvmlite.const_int32(pool, ni * 8)
slot: llvmlite.Value* = llvmlite.build_gep(
parent_builder, i8_ty, env_ptr, offset_val)
slot: llvmlite.Value* = llvmlite.build_gep(parent_builder, i8_ty, env_ptr, offset_val)
if slot is not None:
slot_typed: llvmlite.Value* = llvmlite.build_bitcast(
parent_builder, slot, i8_ptr_ptr_ty)
slot_typed: llvmlite.Value* = llvmlite.build_bitcast(parent_builder, slot, i8_ptr_ptr_ty)
if slot_typed is not None:
llvmlite.build_store(parent_builder, heap_store, slot_typed)
@@ -428,8 +358,7 @@ class FuncGenMixin(CallGenBase.CallGenBase):
closure_size_val: llvmlite.Value* = llvmlite.const_int64(pool, 16)
if closure_size_val is not None:
closure_size_val.Next = None
closure_ptr: llvmlite.Value* = llvmlite.build_call(
parent_builder, "malloc", closure_size_val, 1, i8_ptr_ty, 0)
closure_ptr: llvmlite.Value* = llvmlite.build_call(parent_builder, "malloc", closure_size_val, 1, i8_ptr_ty, 0)
if closure_ptr is None:
# malloc 失败,恢复状态
trans._cur_func_name = old_func_name
@@ -457,20 +386,16 @@ class FuncGenMixin(CallGenBase.CallGenBase):
fn_ptr_val: llvmlite.Value* = llvmlite.SSAValue(pool, fn_func_ptr_ty, fn_ptr_name)
# bitcast 函数指针到 i8*(闭包存储 i8* 类型)
fn_as_i8ptr: llvmlite.Value* = llvmlite.build_bitcast(
parent_builder, fn_ptr_val, i8_ptr_ty)
fn_slot: llvmlite.Value* = llvmlite.build_bitcast(
parent_builder, closure_ptr, llvmlite.Ptr(pool, i8_ptr_ty))
fn_as_i8ptr: llvmlite.Value* = llvmlite.build_bitcast(parent_builder, fn_ptr_val, i8_ptr_ty)
fn_slot: llvmlite.Value* = llvmlite.build_bitcast(parent_builder, closure_ptr, llvmlite.Ptr(pool, i8_ptr_ty))
if fn_slot is not None and fn_as_i8ptr is not None:
llvmlite.build_store(parent_builder, fn_as_i8ptr, fn_slot)
# 13d. 存储 env_ptr 到 offset 8
eight_val: llvmlite.Value* = llvmlite.const_int32(pool, 8)
env_slot_addr: llvmlite.Value* = llvmlite.build_gep(
parent_builder, i8_ty, closure_ptr, eight_val)
env_slot_addr: llvmlite.Value* = llvmlite.build_gep(parent_builder, i8_ty, closure_ptr, eight_val)
if env_slot_addr is not None:
env_slot: llvmlite.Value* = llvmlite.build_bitcast(
parent_builder, env_slot_addr, llvmlite.Ptr(pool, i8_ptr_ty))
env_slot: llvmlite.Value* = llvmlite.build_bitcast(parent_builder, env_slot_addr, llvmlite.Ptr(pool, i8_ptr_ty))
if env_slot is not None:
if env_ptr is not None:
llvmlite.build_store(parent_builder, env_ptr, env_slot)
@@ -512,27 +437,19 @@ class FuncGenMixin(CallGenBase.CallGenBase):
k: int = node.kind()
if k == ast.ASTKind.Name:
nm: ast.Name* = ast.Name*(node)
if nm.id is None:
return 1
if nm.id is None: return 1
# 当前作用域已定义(参数 / AnnAssign 局部,含分支内)→ 非捕获
if self.Gen.VarGen.lookup_current(trans.SymTab, nm.id) is not None:
return 1
if self.Gen.VarGen.lookup_current(trans.SymTab, nm.id) is not None: return 1
# 已注册 nonlocal(显式 nonlocal 语句 / 已捕获)→ 跳过
if GenApi.is_nonlocal_name(trans, nm.id) != 0:
return 1
ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, nm.id)
if ve is None or ve.Alloca is None or ve.Alloca.Ty is None:
return 1
if GenApi.is_nonlocal_name(trans, nm.id) != 0: return 1
ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id)
if ve is None or ve.Alloca is None or ve.Alloca.Ty is None: return 1
nl_ty: llvmlite.LLVMType* = ve.Alloca.Ty.Pointee
if nl_ty is None:
return 1
if nl_ty is None: return 1
# 模块级全局直接解析,无需 env 捕获
mod_gv: llvmlite.Value* = self.Gen.VarGen.lookup_module_var(
trans.SymTab, nm.id)
mod_gv: llvmlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm.id)
if mod_gv is not None:
if uint64(mod_gv) == uint64(ve.Alloca):
return 1
if uint64(mod_gv) == uint64(ve.Alloca): return 1
# 外层函数局部变量 → 隐式捕获(注册为 nonlocal)
GenApi.add_nonlocal_name(trans, nm.id, nl_ty)
return 1
@@ -569,7 +486,7 @@ class FuncGenMixin(CallGenBase.CallGenBase):
self._closure_scan_captures(trans, ifn.orelse.get(bi_el))
return 1
if k == ast.ASTKind.For:
for_n: rawptr[ast.For] = rawptr[ast.For](node)
for_n: ast.For* = ast.For*(node)
# 循环目标是新局部变量,不参与捕获
if for_n.iter is not None:
self._closure_scan_captures(trans, for_n.iter)
@@ -880,22 +797,18 @@ class FuncGenMixin(CallGenBase.CallGenBase):
"""计算 LLVM 类型占用的字节大小(递归)"""
if ty is None:
# [S4 fail-fast] 类型缺失 → 不再保守 8 字节(分配不足会越界写邻块)
self.Gen.TypeGenErr.fatal_error(
None, "nonlocal 共享存储:类型缺失,无法计算尺寸", "TypeError")
self.Gen.TypeGenErr.fatal_error(None, "nonlocal 共享存储:类型缺失,无法计算尺寸", "TypeError")
return 0
match ty:
case llvmlite.LLVMType.Int(bits):
sz_i: int = (bits + 7) // 8
if sz_i < 8:
sz_i = 8
if sz_i < 8: sz_i = 8
return sz_i
case llvmlite.LLVMType.Ptr(_pe):
return 8
case llvmlite.LLVMType.Float(fb):
if fb == 64:
return 8
if fb >= 128:
return 16
if fb == 64: return 8
if fb >= 128: return 16
return 4
case llvmlite.LLVMType.Array(et, cnt):
esz: int = self._type_byte_size(pool, et)
@@ -995,13 +908,11 @@ class FuncGenMixin(CallGenBase.CallGenBase):
continue
dup: int = 0
for di in range(count):
if string.strcmp((str)(
uint64(names) + di * 8), nm_x.id) == 0:
if string.strcmp((str)(uint64(names) + di * 8), nm_x.id) == 0:
dup = 1
break
if dup == 0 and count < 64:
nm_slot: str | t.CPtr = (t.CPtr)(
uint64(names) + count * 8)
nm_slot: str* = (t.CPtr)(uint64(names) + count * 8)
nm_slot[0] = nm_x.id
count += 1
return count
@@ -1024,38 +935,28 @@ class FuncGenMixin(CallGenBase.CallGenBase):
i8_ty: llvmlite.LLVMType*,
i8_ptr_ty: llvmlite.LLVMType*) -> int:
"""预收集嵌套函数链内 nonlocal 并建堆,1 成功"""
if node is None or trans is None or builder is None or mod is None:
return 0
if node is None or trans is None or builder is None or mod is None: return 0
# 每函数只预建一次:多个嵌套函数定义共享同一堆(防重复 malloc +
# 二次重定向 VarEntry.Alloca 导致兄弟闭包各持一堆,计数不同步)
if trans._nl_chain_done != 0:
return 1
if trans._nl_chain_done != 0: return 1
if trans._nl_chain_names is None:
trans._nl_chain_names = pool.alloc(8 * 64)
if trans._nl_chain_names is not None:
string.memset(trans._nl_chain_names, 0, 8 * 64)
if trans._nl_chain_names is None:
return 0
trans._nl_chain_count = self._collect_chain_nonlocals(
trans, node, trans._nl_chain_names, 0)
if trans._nl_chain_names is None: return 0
trans._nl_chain_count = self._collect_chain_nonlocals(trans, node, trans._nl_chain_names, 0)
trans._nl_chain_done = 1
for ci in range(trans._nl_chain_count):
nm_slot: str | t.CPtr = (t.CPtr)(
uint64(trans._nl_chain_names) + ci * 8)
nm_slot: str* = (t.CPtr)(uint64(trans._nl_chain_names) + ci * 8)
nl_name: str = nm_slot[0]
if nl_name is None:
continue
if nl_name is None: continue
# 只在"定义它的函数"(当前顶层作用域有 alloca)中建堆
local_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_current(
trans.SymTab, nl_name)
if local_alloca is None or local_alloca.Ty is None:
continue
local_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, nl_name)
if local_alloca is None or local_alloca.Ty is None: continue
nl_ty: llvmlite.LLVMType* = local_alloca.Ty.Pointee
if nl_ty is None:
continue
if nl_ty is None: continue
gname: str = self._nl_heap_global_name(pool, trans, nl_name)
if gname is None:
continue
if gname is None: continue
# 建堆(按类型字节大小)并拷贝当前值——每次本函数执行都新建共享堆,并 store 到
# 模块级映射(跨函数可见)。不能因映射变量已存在就跳过:跳过会让本函数运行时
# @nlheap.* 保持上一函数的堆地址,env 读到错堆。映射变量仅首次 add(模块去重),
@@ -1064,22 +965,17 @@ class FuncGenMixin(CallGenBase.CallGenBase):
st_size_val: llvmlite.Value* = llvmlite.const_int64(pool, st_size)
if st_size_val is not None:
st_size_val.Next = None
var_storage: llvmlite.Value* = llvmlite.build_call(
builder, "malloc", st_size_val, 1, i8_ptr_ty, 0)
var_storage: llvmlite.Value* = llvmlite.build_call(builder, "malloc", st_size_val, 1, i8_ptr_ty, 0)
if var_storage is None:
continue
cur_val: llvmlite.Value* = llvmlite.build_load(
builder, nl_ty, local_alloca)
st_slot: llvmlite.Value* = llvmlite.build_bitcast(
builder, var_storage, llvmlite.Ptr(pool, nl_ty))
cur_val: llvmlite.Value* = llvmlite.build_load(builder, nl_ty, local_alloca)
st_slot: llvmlite.Value* = llvmlite.build_bitcast(builder, var_storage, llvmlite.Ptr(pool, nl_ty))
if st_slot is not None and cur_val is not None:
llvmlite.build_store(builder, cur_val, st_slot)
# 重定向 VarEntry(父函数读写走共享堆)
ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, nl_name)
ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nl_name)
if ve is not None:
heap_typed: llvmlite.Value* = llvmlite.build_bitcast(
builder, var_storage, llvmlite.Ptr(pool, nl_ty))
heap_typed: llvmlite.Value* = llvmlite.build_bitcast(builder, var_storage, llvmlite.Ptr(pool, nl_ty))
if heap_typed is not None:
ve.Alloca = heap_typed
# 创建/复用全局映射变量并 store 堆地址(跨函数可见)
@@ -1099,8 +995,7 @@ class FuncGenMixin(CallGenBase.CallGenBase):
gv_found.Initializer = "null"
llvmlite.module_add_global(mod, gv_found)
if gv_found is not None:
gv_ref: llvmlite.Value* = self._nl_heap_global_ref(
pool, trans, nl_name)
gv_ref: llvmlite.Value* = self._nl_heap_global_ref(pool, trans, nl_name)
if gv_ref is not None:
llvmlite.build_store(builder, var_storage, gv_ref)
return 1
@@ -1169,13 +1064,10 @@ class FuncGenMixin(CallGenBase.CallGenBase):
string.strncpy(param_names + param_count * 32, arg_n.arg, 31)
p_ty: llvmlite.LLVMType* = i32_ty
if arg_n.annotation is not None:
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, arg_n.annotation, trans._imported_modules, trans._from_imports, trans, 0)
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg_n.annotation, trans._imported_modules, trans._from_imports, trans, 0)
if resolved is None:
# fail-fast:lambda 参数有注解但类型解析失败,不再静默保持 i32
self.Gen.TypeGenErr.fatal_error(
arg_n, f"参数 '{arg_n.arg}' 类型解析失败: {self.Gen.TypeGenResolve.annotation_to_str(arg_n.annotation)}",
"NameError")
self.Gen.TypeGenErr.fatal_error(arg_n, f"参数 '{arg_n.arg}' 类型解析失败: {self.Gen.TypeGenResolve.annotation_to_str(arg_n.annotation)}", "NameError")
resolved = i32_ty # 不可达(fatal_error 已退出)
if resolved is not None:
match resolved:
@@ -1185,8 +1077,7 @@ class FuncGenMixin(CallGenBase.CallGenBase):
p_ty = llvmlite.Ptr(pool, aelem_ty_l)
case _:
p_ty = resolved
ty_slot_p: str | t.CPtr = (t.CPtr)(
uint64(param_tys) + param_count * 8)
ty_slot_p: str* = (t.CPtr)(uint64(param_tys) + param_count * 8)
ty_slot_p[0] = p_ty
param_count += 1
@@ -1203,19 +1094,15 @@ class FuncGenMixin(CallGenBase.CallGenBase):
if cap_tys is None:
return None
string.memset(cap_tys, 0, 8 * 64)
cap_count: int = self._lambda_scan_body(
trans, lam.body, param_names, param_count,
cap_names, cap_allocas, cap_tys, 0)
cap_count: int = self._lambda_scan_body(trans, lam.body, param_names, param_count, cap_names, cap_allocas, cap_tys, 0)
# 4. 创建提升函数 __lambda_{id}(i8* %env, [args...])
func: llvmlite.Function* = llvmlite.create_function(
pool, mod, mangled_promoted, i32_ty)
if func is None:
return None
func: llvmlite.Function* = llvmlite.create_function(pool, mod, mangled_promoted, i32_ty)
if func is None: return None
llvmlite.add_param(pool, func, i8_ptr_ty, "%env")
for pi2 in range(param_count):
ty_addr2: uint64 = uint64(param_tys) + pi2 * 8
ty_slot2: str | t.CPtr = (t.CPtr)(ty_addr2)
ty_slot2: str* = (t.CPtr)(ty_addr2)
p_ty2: llvmlite.LLVMType* = (llvmlite.LLVMType*)(ty_slot2[0])
if p_ty2 is None:
p_ty2 = i32_ty
@@ -1261,30 +1148,20 @@ class FuncGenMixin(CallGenBase.CallGenBase):
# 注意:不能用 (str)(cap_addr) 整数转换——TPV 将其编译为 itoa(整数转字符串),
# 会把 cap_slot 变成数字串,define_var 键名错乱,lambda body lookup 无法命中。
cap_slot: str = cap_names + ci * 64
if cap_slot[0] == '\0':
continue
if cap_slot[0] == '\0': continue
ty_addr3: uint64 = uint64(cap_tys) + ci * 8
ty_slot3: str | t.CPtr = (t.CPtr)(ty_addr3)
cap_ty: llvmlite.LLVMType* = (llvmlite.LLVMType*)(ty_slot3[0])
if cap_ty is None:
continue
if cap_ty is None: continue
off_val: llvmlite.Value* = llvmlite.const_int32(pool, ci * 8)
slot_addr: llvmlite.Value* = llvmlite.build_gep(
func_builder, i8_ty, env_param_val, off_val)
if slot_addr is None:
continue
storage_addr: llvmlite.Value* = llvmlite.build_load(
func_builder, i8_ptr_ty, slot_addr)
if storage_addr is None:
continue
st_typed: llvmlite.Value* = llvmlite.build_bitcast(
func_builder, storage_addr, llvmlite.Ptr(pool, cap_ty))
if st_typed is None:
continue
cap_val: llvmlite.Value* = llvmlite.build_load(
func_builder, cap_ty, st_typed)
if cap_val is None:
continue
slot_addr: llvmlite.Value* = llvmlite.build_gep(func_builder, i8_ty, env_param_val, off_val)
if slot_addr is None: continue
storage_addr: llvmlite.Value* = llvmlite.build_load(func_builder, i8_ptr_ty, slot_addr)
if storage_addr is None: continue
st_typed: llvmlite.Value* = llvmlite.build_bitcast(func_builder, storage_addr, llvmlite.Ptr(pool, cap_ty))
if st_typed is None: continue
cap_val: llvmlite.Value* = llvmlite.build_load(func_builder, cap_ty, st_typed)
if cap_val is None: continue
var_alloca: llvmlite.Value* = llvmlite.build_alloca(func_builder, cap_ty)
if var_alloca is not None:
llvmlite.build_store(func_builder, cap_val, var_alloca)
@@ -1297,8 +1174,7 @@ class FuncGenMixin(CallGenBase.CallGenBase):
p_ty3: llvmlite.LLVMType* = (llvmlite.LLVMType*)(ty_slot4[0])
if p_ty3 is None:
# fail-fast:lambda 参数类型槽缺失(内部状态不一致),不再静默保持 i32
self.Gen.TypeGenErr.fatal_error(
lam, f"lambda 参数 '{param_names + pi3 * 32}' 类型信息缺失", "InternalCompilerError")
self.Gen.TypeGenErr.fatal_error(lam, f"lambda 参数 '{param_names + pi3 * 32}' 类型信息缺失", "InternalCompilerError")
p_ty3 = i32_ty # 不可达(fatal_error 已退出)
pname_ref: str = pool.alloc(32)
if pname_ref is not None:
@@ -1310,15 +1186,12 @@ class FuncGenMixin(CallGenBase.CallGenBase):
self.Gen.VarGen.define_var(trans.SymTab, param_names + pi3 * 32, arg_alloca)
# 11. 翻译 body 表达式,coerce 到 i32 后 ret
body_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
func_builder, pool, mod, lam.body, None, 0, trans)
body_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(func_builder, pool, mod, lam.body, None, 0, trans)
if body_val is not None and body_val.Ty is not None:
if self.Gen.ExprGenBase.get_llvm_type_bits(body_val.Ty) == 32 \
and self.Gen.ExprGenBase.is_ptr_type(body_val.Ty) == 0:
if self.Gen.ExprGenBase.get_llvm_type_bits(body_val.Ty) == 32 and self.Gen.ExprGenBase.is_ptr_type(body_val.Ty) == 0:
llvmlite.build_ret(func_builder, body_val)
else:
ret_val: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(
func_builder, body_val, i32_ty, lam.body)
ret_val: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(func_builder, body_val, i32_ty, lam.body)
if ret_val is not None:
llvmlite.build_ret(func_builder, ret_val)
else:
@@ -1344,8 +1217,7 @@ class FuncGenMixin(CallGenBase.CallGenBase):
env_size_val: llvmlite.Value* = llvmlite.const_int64(pool, env_size)
if env_size_val is not None:
env_size_val.Next = None
env_ptr = llvmlite.build_call(
builder, "malloc", env_size_val, 1, i8_ptr_ty, 0)
env_ptr = llvmlite.build_call(builder, "malloc", env_size_val, 1, i8_ptr_ty, 0)
if env_ptr is not None:
for ci3 in range(cap_count):
# 与步骤 9 一致:str 指针偏移判空,避免整数转换 itoa 语义
@@ -1354,16 +1226,12 @@ class FuncGenMixin(CallGenBase.CallGenBase):
continue
al_addr: uint64 = uint64(cap_allocas) + ci3 * 8
al_slot: str | t.CPtr = (t.CPtr)(al_addr)
var_alloca2: llvmlite.Value* = (
llvmlite.Value*)(al_slot[0])
if var_alloca2 is None:
continue
var_alloca2: llvmlite.Value* = (llvmlite.Value*)(al_slot[0])
if var_alloca2 is None: continue
ty_addr5: uint64 = uint64(cap_tys) + ci3 * 8
ty_slot5: str | t.CPtr = (t.CPtr)(ty_addr5)
cap_ty2: llvmlite.LLVMType* = (
llvmlite.LLVMType*)(ty_slot5[0])
if cap_ty2 is None:
continue
cap_ty2: llvmlite.LLVMType* = (llvmlite.LLVMType*)(ty_slot5[0])
if cap_ty2 is None: continue
# 堆存储大小:位宽/8,至少 8 字节(容纳指针/标量)
ty_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(cap_ty2)
st_size: int = 8
@@ -1372,22 +1240,17 @@ class FuncGenMixin(CallGenBase.CallGenBase):
st_size_val: llvmlite.Value* = llvmlite.const_int64(pool, st_size)
if st_size_val is not None:
st_size_val.Next = None
var_storage: llvmlite.Value* = llvmlite.build_call(
builder, "malloc", st_size_val, 1, i8_ptr_ty, 0)
var_storage: llvmlite.Value* = llvmlite.build_call(builder, "malloc", st_size_val, 1, i8_ptr_ty, 0)
if var_storage is not None:
cur_val: llvmlite.Value* = llvmlite.build_load(
builder, cap_ty2, var_alloca2)
cur_val: llvmlite.Value* = llvmlite.build_load(builder, cap_ty2, var_alloca2)
if cur_val is not None:
st_slot5: llvmlite.Value* = llvmlite.build_bitcast(
builder, var_storage, llvmlite.Ptr(pool, cap_ty2))
st_slot5: llvmlite.Value* = llvmlite.build_bitcast(builder, var_storage, llvmlite.Ptr(pool, cap_ty2))
if st_slot5 is not None:
llvmlite.build_store(builder, cur_val, st_slot5)
off_val2: llvmlite.Value* = llvmlite.const_int32(pool, ci3 * 8)
slot2: llvmlite.Value* = llvmlite.build_gep(
builder, i8_ty, env_ptr, off_val2)
slot2: llvmlite.Value* = llvmlite.build_gep(builder, i8_ty, env_ptr, off_val2)
if slot2 is not None:
slot_typed2: llvmlite.Value* = llvmlite.build_bitcast(
builder, slot2, i8_ptr_ptr_ty)
slot_typed2: llvmlite.Value* = llvmlite.build_bitcast(builder, slot2, i8_ptr_ptr_ty)
if slot_typed2 is not None:
llvmlite.build_store(builder, var_storage, slot_typed2)
@@ -1395,8 +1258,7 @@ class FuncGenMixin(CallGenBase.CallGenBase):
closure_size_val: llvmlite.Value* = llvmlite.const_int64(pool, 16)
if closure_size_val is not None:
closure_size_val.Next = None
closure_ptr: llvmlite.Value* = llvmlite.build_call(
builder, "malloc", closure_size_val, 1, i8_ptr_ty, 0)
closure_ptr: llvmlite.Value* = llvmlite.build_call(builder, "malloc", closure_size_val, 1, i8_ptr_ty, 0)
if closure_ptr is None:
return None
@@ -1411,20 +1273,16 @@ class FuncGenMixin(CallGenBase.CallGenBase):
else:
viperlib.snprintf(fn_ptr_name, 64, "@%s", mangled_promoted)
fn_ptr_val: llvmlite.Value* = llvmlite.SSAValue(pool, fn_func_ptr_ty, fn_ptr_name)
fn_as_i8ptr: llvmlite.Value* = llvmlite.build_bitcast(
builder, fn_ptr_val, i8_ptr_ty)
fn_slot: llvmlite.Value* = llvmlite.build_bitcast(
builder, closure_ptr, llvmlite.Ptr(pool, i8_ptr_ty))
fn_as_i8ptr: llvmlite.Value* = llvmlite.build_bitcast(builder, fn_ptr_val, i8_ptr_ty)
fn_slot: llvmlite.Value* = llvmlite.build_bitcast(builder, closure_ptr, llvmlite.Ptr(pool, i8_ptr_ty))
if fn_slot is not None and fn_as_i8ptr is not None:
llvmlite.build_store(builder, fn_as_i8ptr, fn_slot)
# 16. [8] = env_ptr(无捕获存 null)
eight_val: llvmlite.Value* = llvmlite.const_int32(pool, 8)
env_slot_addr: llvmlite.Value* = llvmlite.build_gep(
builder, i8_ty, closure_ptr, eight_val)
env_slot_addr: llvmlite.Value* = llvmlite.build_gep(builder, i8_ty, closure_ptr, eight_val)
if env_slot_addr is not None:
env_slot: llvmlite.Value* = llvmlite.build_bitcast(
builder, env_slot_addr, llvmlite.Ptr(pool, i8_ptr_ty))
env_slot: llvmlite.Value* = llvmlite.build_bitcast(builder, env_slot_addr, llvmlite.Ptr(pool, i8_ptr_ty))
if env_slot is not None:
if env_ptr is not None:
llvmlite.build_store(builder, env_ptr, env_slot)
@@ -1481,11 +1339,9 @@ class FuncGenMixin(CallGenBase.CallGenBase):
if cap_count >= 64:
return cap_count
string.strncpy(cap_names + cap_count * 64, nm.id, 63)
al_slot: str | t.CPtr = (t.CPtr)(
uint64(cap_allocas) + cap_count * 8)
al_slot: str | t.CPtr = (t.CPtr)(uint64(cap_allocas) + cap_count * 8)
al_slot[0] = alloca
ty_slot: str | t.CPtr = (t.CPtr)(
uint64(cap_tys) + cap_count * 8)
ty_slot: str | t.CPtr = (t.CPtr)(uint64(cap_tys) + cap_count * 8)
ty_slot[0] = pointee
return cap_count + 1
# 递归遍历常见表达式子节点
+9 -18
View File
@@ -834,17 +834,14 @@ novirtual class ImportsGenMixin:
self._check_import_sha1(node, alias.name)
pool_val: memhub.MemBuddy* = trans.Pool
im_val: str = trans._imported_modules
trans._imported_modules = self.add_imported_module(
pool_val, im_val, alias.name)
trans._imported_modules = self.add_imported_module(pool_val, im_val, alias.name)
# 别名也加入导入模块列表(用于模块限定构造器检查 Module.Class())
if alias.asname is not None:
trans._imported_modules = self.add_imported_module(
pool_val, trans._imported_modules, alias.asname)
trans._imported_modules = self.add_imported_module(pool_val, trans._imported_modules, alias.asname)
# 别名也加入 from_imports(asname:fullname),
# 使 HT.func() 跨模块调用能通过 from_imports 查找别名→完整模块名→SHA1
# 否则 _lookup_module_sha1("HT") 找不到(mod_arr 只存文件名 HandlesTranslator)
trans._from_imports = self.add_from_import(
pool_val, trans._from_imports, alias.asname, alias.name)
trans._from_imports = self.add_from_import(pool_val, trans._from_imports, alias.asname, alias.name)
else:
# 无别名时(import a.b.c),将顶层包名 "a" 也加入 _imported_modules,
# 使 a.b.c 作为属性访问的 base 被翻译时能通过 is_module_imported("a") 检查
@@ -856,8 +853,7 @@ novirtual class ImportsGenMixin:
if pkg_buf is not None:
string.strncpy(pkg_buf, alias.name, pkg_len)
pkg_buf[pkg_len] = '\0'
trans._imported_modules = self.add_imported_module(
pool_val, trans._imported_modules, pkg_buf)
trans._imported_modules = self.add_imported_module(pool_val, trans._imported_modules, pkg_buf)
return 0
# ============================================================
@@ -875,8 +871,7 @@ novirtual class ImportsGenMixin:
if impf is None:
return 0
# 解析模块名:相对导入需补充包前缀
resolved: str = self._resolve_relative_module(
trans.Pool, trans.CurrentPackage,
resolved: str = self._resolve_relative_module(trans.Pool, trans.CurrentPackage,
impf.level, impf.module)
if resolved is not None:
# 导入时立即校验模块 SHA1 是否注册(fast-fail,仅全量翻译时检查)
@@ -887,8 +882,7 @@ novirtual class ImportsGenMixin:
# 下方 L759-762 逐个校验(LookupSha1ByModName / 本地兄弟文件)。
if trans._declare_only == 0 and impf.module is not None:
self._check_import_sha1(node, resolved)
trans._imported_modules = self.add_imported_module(
trans.Pool, trans._imported_modules, resolved)
trans._imported_modules = self.add_imported_module(trans.Pool, trans._imported_modules, resolved)
# from . import Y(impf.module is None):resolved 是包名(vpsdk),
# 各 name 是包的子模块 vpsdk.Y。须把完整子模块名也加入 _imported_modules,
# 否则别名 "syscall" 精确匹配不到包名 "vpsdk" → is_module_imported 返回 0
@@ -916,8 +910,7 @@ novirtual class ImportsGenMixin:
or self._is_local_module_file(alias_m.name) != 0):
if trans._declare_only == 0:
self._check_import_sha1(node, jb_m)
trans._imported_modules = self.add_imported_module(
trans.Pool, trans._imported_modules, jb_m)
trans._imported_modules = self.add_imported_module(trans.Pool, trans._imported_modules, jb_m)
return 0
# ============================================================
@@ -934,8 +927,7 @@ novirtual class ImportsGenMixin:
if impf is None:
return 0
# 解析模块名:相对导入需补充包前缀
resolved: str = self._resolve_relative_module(
trans.Pool, trans.CurrentPackage,
resolved: str = self._resolve_relative_module(trans.Pool, trans.CurrentPackage,
impf.level, impf.module)
if resolved is not None:
names: list[ast.AST*]* = impf.names
@@ -963,8 +955,7 @@ novirtual class ImportsGenMixin:
jb_t[fl_t] = '.'
string.strcpy(jb_t + fl_t + 1, alias.name)
fi_target = jb_t
trans._from_imports = self.add_from_import(
trans.Pool, trans._from_imports,
trans._from_imports = self.add_from_import(trans.Pool, trans._from_imports,
local_name, fi_target, orig_name)
# 命名空间隔离:from-import 的名称标记为可见结构体
self.Gen.StructGen.add_visible_struct(trans.Pool, local_name)
+74 -165
View File
@@ -16,14 +16,14 @@ import lib.core.Gen.Generator as Generator
# match case 数量上限(原 HandlesMatch.MAX_MATCH_CASES)
MAX_MATCH_CASES: t.CDefine = 32
define MAX_MATCH_CASES = 32
# 作用域种类常量(与 HandlesVar 的 Scope.Kind 区分,原 HandlesMatch.SCOPE_MATCH)
SCOPE_MATCH: t.CDefine = 6
define SCOPE_MATCH = 6
# match 翻译最大递归深度(match → case body → translate_value → 嵌套 match)。
# 入口计数出口递减,超限即 fail-fast:AST 自引用环可致无限递归 → 栈溢出。
MATCH_TRANSLATE_MAX_DEPTH: t.CDefine = 64
define MATCH_TRANSLATE_MAX_DEPTH = 64
novirtual class MatchGenMixin:
@@ -66,8 +66,7 @@ novirtual class MatchGenMixin:
"""match 语句翻译主入口(深度守卫包装器,原逻辑见 _translate_match_impl)"""
if trans is not None:
if trans.MatchTranslateDepth >= MATCH_TRANSLATE_MAX_DEPTH:
self.Gen.TypeGenErr.fatal_error(
node, "match 翻译嵌套过深(疑似 AST 自引用环或翻译 bug)", "RecursionError")
self.Gen.TypeGenErr.fatal_error(node, "match 翻译嵌套过深(疑似 AST 自引用环或翻译 bug)", "RecursionError")
trans.MatchTranslateDepth += 1
mret: int = self._translate_match_impl(trans, node)
if trans is not None:
@@ -101,8 +100,7 @@ novirtual class MatchGenMixin:
sk_seq: int = subject_node.kind()
if sk_seq == ast.ASTKind.Tuple or sk_seq == ast.ASTKind.List:
return self._handle_sequence_match(trans, m_node, subject_node)
subject_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, subject_node,
subject_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, subject_node,
trans._funcs, trans._func_count, trans)
if subject_val is None:
# fail-fast: match subject 翻译失败
@@ -117,14 +115,11 @@ novirtual class MatchGenMixin:
if subject_node.kind() == ast.ASTKind.Name:
nm: ast.Name* = ast.Name*(subject_node)
if nm.id is not None:
entry: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, nm.id)
entry: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id)
entry_annot: str = self.Gen.VarGen.var_annot_class_name(entry)
if entry_annot is not None \
and (self.Gen.ClassGenEnum._is_renum_class_name(
entry_annot) != 0
or self.Gen.ClassGenEnum._is_renum_by_entry(
entry_annot) != 0):
and (self.Gen.ClassGenEnum._is_renum_class_name(entry_annot) != 0
or self.Gen.ClassGenEnum._is_renum_by_entry(entry_annot) != 0):
is_renum = 1
renum_name = entry_annot
subject_ptr = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
@@ -139,8 +134,7 @@ novirtual class MatchGenMixin:
case_node: ast.AST* = cases_list.get(ci)
if case_node is not None \
and case_node.kind() == ast.ASTKind.MatchCase:
mc: rawptr[ast.MatchCase] = (
rawptr[ast.MatchCase])(case_node)
mc: rawptr[ast.MatchCase] = (rawptr[ast.MatchCase])(case_node)
pat: ast.AST* = mc.pattern
if pat is not None \
and pat.kind() == ast.ASTKind.MatchClass:
@@ -182,8 +176,7 @@ novirtual class MatchGenMixin:
inner_nm: ast.Name* = ast.Name*(at.value)
return inner_nm.id
if at.value.kind() == ast.ASTKind.Attribute:
inner_at: ast.Attribute* = (
ast.Attribute*)(at.value)
inner_at: ast.Attribute* = (ast.Attribute*)(at.value)
return inner_at.attr
# Name 形式:遍历所有 REnum 类反查
if cls_node.kind() == ast.ASTKind.Name:
@@ -240,12 +233,10 @@ novirtual class MatchGenMixin:
call_node: ast.Call* = ast.Call*(val)
fn: ast.AST* = call_node.func
if fn is not None and fn.kind() == ast.ASTKind.Attribute:
at: ast.Attribute* = (
ast.Attribute*)(fn)
at: ast.Attribute* = (ast.Attribute*)(fn)
if at.value is not None \
and at.value.kind() == ast.ASTKind.Name:
base_nm: ast.Name* = (
ast.Name*)(at.value)
base_nm: ast.Name* = (ast.Name*)(at.value)
if base_nm.id is not None \
and string.strcmp(base_nm.id, "c") == 0 \
and at.attr is not None \
@@ -287,25 +278,20 @@ novirtual class MatchGenMixin:
and subj_ty.Pointee != 0 \
and self.Gen.ExprGenBase.is_ptr_type(subj_ty.Pointee) != 0:
# 情况1: T** → load 一次得 T*
loaded_sub: llvmlite.Value* = llvmlite.build_load(
builder, subj_ty.Pointee, subject_ptr)
loaded_sub: llvmlite.Value* = llvmlite.build_load(builder, subj_ty.Pointee, subject_ptr)
if loaded_sub is not None:
subject_ptr = loaded_sub
# 情况2: 值型 subject(非指针)→ inttoptr 转回指针
# 值型 subject 来自 REnum payload 槽位 load(槽位类型 i64,存的是指针),
# 所以直接 inttoptr 到 renum_sty* 即可,无需 alloca+store
if subject_ptr.Ty is None or self.Gen.ExprGenBase.is_ptr_type(subject_ptr.Ty) == 0:
renum_se: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(
renum_name)
renum_se: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(renum_name)
renum_sty: llvmlite.LLVMType* = None
if renum_se is not None:
renum_sty = renum_se.Ty
if renum_sty is None:
# fail-fast: REnum 结构体未注册,无法构造
self.Gen.TypeGenErr.fatal_error(
node,
f"REnum 结构体 '{renum_name}' 未注册",
"NameError")
self.Gen.TypeGenErr.fatal_error(node, f"REnum 结构体 '{renum_name}' 未注册", "NameError")
i64_ty0: llvmlite.LLVMType* = llvmlite.Int64(pool)
int_val: llvmlite.Value* = subject_ptr
# 非 i64 整数值先扩展/截断到 i64(inttoptr 要求同宽)
@@ -317,21 +303,18 @@ novirtual class MatchGenMixin:
else:
int_val = llvmlite.build_zext(builder, subject_ptr, i64_ty0)
renum_ptr_ty0: llvmlite.LLVMType* = llvmlite.Ptr(pool, renum_sty)
subj_ptr0: llvmlite.Value* = llvmlite.build_inttoptr(
builder, int_val, renum_ptr_ty0)
subj_ptr0: llvmlite.Value* = llvmlite.build_inttoptr(builder, int_val, renum_ptr_ty0)
if subj_ptr0 is not None:
subject_ptr = subj_ptr0
# 1. bitcast subject 到 i32* 读 __tag
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i32_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i32_ty)
tag_ptr: llvmlite.Value* = llvmlite.build_bitcast(
builder, subject_ptr, i32_ptr_ty)
tag_ptr: llvmlite.Value* = llvmlite.build_bitcast(builder, subject_ptr, i32_ptr_ty)
if tag_ptr is None:
# fail-fast: REnum tag 指针转换失败
self.Gen.TypeGenErr.fatal_error(node, "REnum tag 指针转换失败", "TypeError")
tag_val: llvmlite.Value* = llvmlite.build_load(
builder, i32_ty, tag_ptr)
tag_val: llvmlite.Value* = llvmlite.build_load(builder, i32_ty, tag_ptr)
if tag_val is None:
# fail-fast: REnum tag 读取失败
self.Gen.TypeGenErr.fatal_error(node, "REnum tag 读取失败", "TypeError")
@@ -344,11 +327,9 @@ novirtual class MatchGenMixin:
# fail-fast: 标签缓冲区分配失败
self.Gen.TypeGenErr.fatal_error(node, "标签缓冲区分配失败", "TypeError")
viperlib.snprintf(name_buf, 32, "match.default.%d", cnt)
default_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(
pool, func, name_buf)
default_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, name_buf)
viperlib.snprintf(name_buf, 32, "match.end.%d", cnt)
end_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(
pool, func, name_buf)
end_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, name_buf)
# 3. 准备收集数组(用 CSizeT 数组存指针)
cases_list: list[ast.AST*]* = node.cases
@@ -427,11 +408,9 @@ novirtual class MatchGenMixin:
# 先用裸类名查表(变体表按裸类名注册,与模式侧 2b 路径同口径);
# 失败再用注解书写形态重试(泛型特化 mangled 名确需带点)。
# 两者都失败 → tag=-1 → step 5 前的硬校验 fail-fast。
tag = self.Gen.ClassGenEnum._lookup_renum_variant_in_class(
tag_cls_bare, vnm)
tag = self.Gen.ClassGenEnum._lookup_renum_variant_in_class(tag_cls_bare, vnm)
if tag < 0 and string.strcmp(tag_cls_bare, renum_name) != 0:
tag = self.Gen.ClassGenEnum._lookup_renum_variant_in_class(
renum_name, vnm)
tag = self.Gen.ClassGenEnum._lookup_renum_variant_in_class(renum_name, vnm)
if tag >= 0:
tag_buf: str = pool.alloc(32)
if tag_buf is not None:
@@ -445,9 +424,7 @@ novirtual class MatchGenMixin:
has_default = 1
elif pk == ast.ASTKind.MatchValue:
mv: rawptr[ast.MatchValue] = rawptr[ast.MatchValue](pat)
cv = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, mv.value,
trans._funcs, trans._func_count, trans)
cv = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, mv.value, trans._funcs, trans._func_count, trans)
elif pk == ast.ASTKind.MatchOr:
# MatchOr: 多个值共享一个 BB(取第一个值做 case)
mo: rawptr[ast.MatchOr] = rawptr[ast.MatchOr](pat)
@@ -456,19 +433,15 @@ novirtual class MatchGenMixin:
first_pat: ast.AST* = pats.get(0)
if first_pat is not None \
and first_pat.kind() == ast.ASTKind.MatchValue:
mv2: rawptr[ast.MatchValue] = (
rawptr[ast.MatchValue])(first_pat)
cv = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, mv2.value,
trans._funcs, trans._func_count, trans)
mv2: rawptr[ast.MatchValue] = (rawptr[ast.MatchValue])(first_pat)
cv = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, mv2.value, trans._funcs, trans._func_count, trans)
# 创建 case BB
if is_def == 0:
if collected >= MAX_MATCH_CASES:
break
viperlib.snprintf(name_buf, 32, "match.case.%d.%d", cnt, i)
bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(
pool, func, name_buf)
bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, name_buf)
else:
bb = default_bb
@@ -495,8 +468,7 @@ novirtual class MatchGenMixin:
# 构建 SwitchCase 链表(非 default case 且有值)
if is_def == 0 and cv is not None:
sc: rawptr[llvmlite.SwitchCase] = llvmlite.new_switch_case(
pool, cv, bb)
sc: rawptr[llvmlite.SwitchCase] = llvmlite.new_switch_case(pool, cv, bb)
if sc is not None:
if sw_head is None:
sw_head = sc
@@ -525,8 +497,7 @@ novirtual class MatchGenMixin:
# 结构性不可达。故不等即 fail-fast,打印类名/查表名/应提交数/实际数/
# 各未取到值臂的 序号(变体名,tag),便于定位变体表失配。
if need_case != sw_count:
self.Gen.TypeGenErr.fatal_error(
node,
self.Gen.TypeGenErr.fatal_error(node,
f"REnum match 分派丢失 case:class='{renum_name}'(查表名='{tag_cls_bare}')应提交 {need_case} 个 case,实际提交 {sw_count} 个;未取到值的臂:{miss_buf}",
"InternalCompilerError")
llvmlite.build_switch(builder, tag_val, default_bb, sw_head, sw_count)
@@ -551,8 +522,7 @@ novirtual class MatchGenMixin:
# 取 BB
bb_addr: sizet = bb_arr[i]
case_bb: rawptr[llvmlite.BasicBlock] = (
rawptr[llvmlite.BasicBlock])(bb_addr)
case_bb: rawptr[llvmlite.BasicBlock] = (rawptr[llvmlite.BasicBlock])(bb_addr)
is_def: int = def_arr[i]
nb: int = nb_arr[i]
@@ -570,9 +540,7 @@ novirtual class MatchGenMixin:
# 变体字段绑定(MatchClass)
if pat is not None and pat.kind() == ast.ASTKind.MatchClass \
and renum_entry is not None and renum_ty is not None:
self._bind_variant_fields(
pat, renum_name, renum_entry, renum_ty,
subject_ptr, trans, pool, builder)
self._bind_variant_fields(pat, renum_name, renum_entry, renum_ty, subject_ptr, trans, pool, builder)
# 翻译 case body
body_list: list[ast.AST*]* = mc.children
@@ -619,8 +587,7 @@ novirtual class MatchGenMixin:
if def_arr[di] == 1:
dcase: ast.AST* = cases_list.get(di)
if dcase is not None:
dmc: rawptr[ast.MatchCase] = (
rawptr[ast.MatchCase])(dcase)
dmc: rawptr[ast.MatchCase] = (rawptr[ast.MatchCase])(dcase)
self.Gen.VarGen.enter_scope(trans.SymTab, SCOPE_MATCH)
# dbody 预声明+重赋值会使 .get 误分派成 list[int].get
# (i32→inttoptr 截断指针 → translate_stmt 读垃圾节点崩溃,
@@ -674,13 +641,11 @@ novirtual class MatchGenMixin:
return
# bitcast subject_ptr 到 renum_ptr_ty(确保 GEP 类型匹配)
renum_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, renum_ty)
casted_ptr: llvmlite.Value* = llvmlite.build_bitcast(
builder, subject_ptr, renum_ptr_ty)
casted_ptr: llvmlite.Value* = llvmlite.build_bitcast(builder, subject_ptr, renum_ptr_ty)
if casted_ptr is None:
casted_ptr = subject_ptr
pn: sizet = len(pats)
j: int = 0
while j < pn:
for j in range(pn):
sub_pat: ast.AST* = pats.get(j)
if sub_pat is not None and sub_pat.kind() == ast.ASTKind.MatchAs:
ma: rawptr[ast.MatchAs] = rawptr[ast.MatchAs](sub_pat)
@@ -694,8 +659,7 @@ novirtual class MatchGenMixin:
# class_name 用 CSizeT 指针值比较:必须传 renum_entry.Name
# (注册时 _update_renum_alias_class_ptr 统一后的 perm_pool 指针);
# renum_name(AnnotClassName 等)是不同指针,恒不匹配 → 误报 fail-fast。
alt_idx: int = self.Gen.ClassGenEnum._lookup_renum_field_alias(
renum_entry.Name, bind_name)
alt_idx: int = self.Gen.ClassGenEnum._lookup_renum_field_alias(renum_entry.Name, bind_name)
if alt_idx >= 1:
payload_idx = alt_idx
else:
@@ -703,34 +667,20 @@ novirtual class MatchGenMixin:
# (node 在本函数不存在——参数是 pat/sub_pat,用 sub_pat
# 定位到具体 MatchAs 模式;TPC Python 语义下未定义名只在
# 运行时求值才报错,TPV 惰性编译方法体时即 NameError)
self.Gen.TypeGenErr.fatal_error(
sub_pat,
f"REnum 变体字段 '{bind_name}' 在结构体 '{renum_name}' 中越界且别名查找失败",
"TypeError")
self.Gen.TypeGenErr.fatal_error(sub_pat, f"REnum 变体字段 '{bind_name}' 在结构体 '{renum_name}' 中越界且别名查找失败", "TypeError")
# 获取字段类型
fe: GenTypes.FieldEntry* = (
self.Gen.StructGen._get_field_entry(
renum_entry, payload_idx))
fe: GenTypes.FieldEntry* = (self.Gen.StructGen._get_field_entry(renum_entry, payload_idx))
field_ty: llvmlite.LLVMType* = None
if fe is not None:
field_ty = fe.Ty
if field_ty is None:
# fail-fast: 变体字段类型缺失,禁止兜底 i8
self.Gen.TypeGenErr.fatal_error(
sub_pat,
f"REnum 变体字段类型缺失: {bind_name}",
"TypeError")
self.Gen.TypeGenErr.fatal_error(sub_pat, f"REnum 变体字段类型缺失: {bind_name}", "TypeError")
# GEP 取字段地址
elem_ptr: llvmlite.Value* = (
llvmlite.build_gep_struct(
builder, renum_ty, field_ty,
casted_ptr, payload_idx))
elem_ptr: llvmlite.Value* = llvmlite.build_gep_struct(builder, renum_ty, field_ty,casted_ptr, payload_idx)
if elem_ptr is None:
# fail-fast: 变体字段地址计算失败
self.Gen.TypeGenErr.fatal_error(
sub_pat,
f"REnum 变体字段 '{bind_name}' 地址计算失败",
"TypeError")
self.Gen.TypeGenErr.fatal_error(sub_pat, f"REnum 变体字段 '{bind_name}' 地址计算失败", "TypeError")
# 变体成员实际类型(对齐 TPC class_members):注册时别名表存了成员
# 注解解析出的类型(perm_pool 深拷贝),用它把槽位地址 bitcast 成
# Ptr(成员类型),使绑定变量按成员类型读 payload(否则按槽位 i64 读 →
@@ -742,19 +692,14 @@ novirtual class MatchGenMixin:
vnt_m: str = self._extract_variant_name_from_cls(pat)
if vnt_m is not None and renum_entry is not None \
and renum_entry.Name is not None:
mem_ty_m = self.Gen.ClassGenEnum._lookup_renum_member_ty(
renum_entry.Name, vnt_m, payload_idx)
mem_ty_m = self.Gen.ClassGenEnum._lookup_renum_member_ty(renum_entry.Name, vnt_m, payload_idx)
if mem_ty_m is not None:
mem_ptr_m: llvmlite.LLVMType* = llvmlite.Ptr(
pool, mem_ty_m)
mem_ptr_m: llvmlite.LLVMType* = llvmlite.Ptr(pool, mem_ty_m)
if mem_ptr_m is not None:
cast_m: llvmlite.Value* = llvmlite.build_bitcast(
builder, elem_ptr, mem_ptr_m)
cast_m: llvmlite.Value* = llvmlite.build_bitcast(builder, elem_ptr, mem_ptr_m)
if cast_m is not None:
elem_ptr = cast_m
self.Gen.VarGen.define_var(
trans.SymTab, bind_name, elem_ptr)
j = j + 1
self.Gen.VarGen.define_var(trans.SymTab, bind_name, elem_ptr)
# ============================================================
# _seq_cmp_eq - 序列匹配元素相等比较
@@ -842,12 +787,10 @@ novirtual class MatchGenMixin:
# 用内联别名接收者规避(对齐 Converter arg_defaults 内联模式)
elts_inl: list[ast.AST*]* = elts
elt: ast.AST* = elts_inl.get(ei)
sv: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, elt,
sv: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, elt,
trans._funcs, trans._func_count, trans)
if sv is None:
self.Gen.TypeGenErr.fatal_error(
elt, f"match 序列元素 {ei} 翻译失败", "TypeError")
self.Gen.TypeGenErr.fatal_error(elt, f"match 序列元素 {ei} 翻译失败", "TypeError")
subj_vals[ei] = sizet(sv)
# 2. 创建 default/end BB
@@ -857,11 +800,9 @@ novirtual class MatchGenMixin:
if name_buf is None:
return 0
viperlib.snprintf(name_buf, 32, "match.seq.default.%d", cnt)
default_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(
pool, func, name_buf)
default_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, name_buf)
viperlib.snprintf(name_buf, 32, "match.seq.end.%d", cnt)
end_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(
pool, func, name_buf)
end_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, name_buf)
# 3. 第一遍:收集 case 信息(check/body BB、default 标记、nobreak、guard)
cases_list: list[ast.AST*]* = node.cases
@@ -887,10 +828,7 @@ novirtual class MatchGenMixin:
# 否则 case 数超 MAX_MATCH_CASES 会越界写穿 pool 相邻块。超限直接
# fail-fast,不静默丢弃 case。
if collected >= MAX_MATCH_CASES:
self.Gen.TypeGenErr.fatal_error(
node,
f"match case 数量超过上限 MAX_MATCH_CASES={MAX_MATCH_CASES}",
"OverflowError")
self.Gen.TypeGenErr.fatal_error(node, f"match case 数量超过上限 MAX_MATCH_CASES={MAX_MATCH_CASES}", "OverflowError")
break
case_node: ast.AST* = cases_list.get(i)
if case_node is None or case_node.kind() != ast.ASTKind.MatchCase:
@@ -907,8 +845,7 @@ novirtual class MatchGenMixin:
is_def = 1
elif pk != ast.ASTKind.MatchSequence:
# fail-fast:序列匹配只接受 MatchSequence / 顶层 _ 通配
self.Gen.TypeGenErr.fatal_error(
pat, "序列匹配 case 只支持 (元素) 或 _ 模式", "TypeError")
self.Gen.TypeGenErr.fatal_error(pat, "序列匹配 case 只支持 (元素) 或 _ 模式", "TypeError")
if is_def == 1:
has_default = 1
check_arr[collected] = 0
@@ -917,11 +854,9 @@ novirtual class MatchGenMixin:
if collected >= MAX_MATCH_CASES:
break
viperlib.snprintf(name_buf, 32, "match.seq.check.%d.%d", cnt, i)
cbb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(
pool, func, name_buf)
cbb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, name_buf)
viperlib.snprintf(name_buf, 32, "match.seq.body.%d.%d", cnt, i)
bbb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(
pool, func, name_buf)
bbb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, name_buf)
check_arr[collected] = sizet(cbb)
body_arr[collected] = sizet(bbb)
if first_check < 0:
@@ -957,8 +892,7 @@ novirtual class MatchGenMixin:
cond: llvmlite.Value* = None
cnode: ast.AST* = cases_list.get(ci)
mc2: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](cnode)
ms: rawptr[ast.MatchSequence] = (
rawptr[ast.MatchSequence])(mc2.pattern)
ms: rawptr[ast.MatchSequence] = (rawptr[ast.MatchSequence])(mc2.pattern)
pats: list[ast.AST*]* = None
if ms is not None:
pats = ms.patterns
@@ -978,14 +912,10 @@ novirtual class MatchGenMixin:
continue
pk1: int = pat1.kind()
if pk1 == ast.ASTKind.MatchValue:
mv: rawptr[ast.MatchValue] = (
rawptr[ast.MatchValue])(pat1)
pv: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, mv.value,
trans._funcs, trans._func_count, trans)
mv: rawptr[ast.MatchValue] = (rawptr[ast.MatchValue])(pat1)
pv: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, mv.value, trans._funcs, trans._func_count, trans)
if pv is None:
self.Gen.TypeGenErr.fatal_error(
pat1, f"序列模式元素 {pi} 翻译失败", "TypeError")
self.Gen.TypeGenErr.fatal_error(pat1, f"序列模式元素 {pi} 翻译失败", "TypeError")
sv1: llvmlite.Value* = llvmlite.Value*(subj_vals[pi])
c1: llvmlite.Value* = self._seq_cmp_eq(trans, builder, sv1, pv)
if c1 is None:
@@ -1000,31 +930,25 @@ novirtual class MatchGenMixin:
continue # _ 通配:恒真
if ma2.name is not None:
# fail-fast:序列模式变量绑定暂不支持
self.Gen.TypeGenErr.fatal_error(
pat1, "序列模式变量绑定暂不支持", "NotImplementedError")
self.Gen.TypeGenErr.fatal_error(pat1, "序列模式变量绑定暂不支持", "NotImplementedError")
elif pk1 == ast.ASTKind.MatchStar:
continue # 剩余元素通配:恒真
else:
self.Gen.TypeGenErr.fatal_error(
pat1, "序列模式不支持的 pattern 类型", "TypeError")
self.Gen.TypeGenErr.fatal_error(pat1, "序列模式不支持的 pattern 类型", "TypeError")
# guard(若有):匹配成立且 guard 非零
g_addr: sizet = guard_arr[ci]
if g_addr != 0:
gnode: ast.AST* = (ast.AST*)(g_addr)
gv: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, gnode,
gv: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, gnode,
trans._funcs, trans._func_count, trans)
if gv is None:
self.Gen.TypeGenErr.fatal_error(
gnode, "match guard 翻译失败", "TypeError")
self.Gen.TypeGenErr.fatal_error(gnode, "match guard 翻译失败", "TypeError")
gbits: int = self.Gen.ExprGenBase.get_llvm_type_bits(gv.Ty)
if gbits == 1:
g1: llvmlite.Value* = gv
else:
gzero: llvmlite.Value* = llvmlite.const_int(
pool, gbits if gbits > 0 else 32, 0)
g1 = llvmlite.build_icmp(
builder, llvmlite.ICMP_NE, gv, gzero)
gzero: llvmlite.Value* = llvmlite.const_int(pool, gbits if gbits > 0 else 32, 0)
g1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, gv, gzero)
if cond is None:
cond = g1
else:
@@ -1055,8 +979,7 @@ novirtual class MatchGenMixin:
bbb3: rawptr[llvmlite.BasicBlock] = rawptr[llvmlite.BasicBlock](body_arr[ci])
llvmlite.position_at_end(builder, bbb3)
cnode2: ast.AST* = cases_list.get(ci)
mc3: rawptr[ast.MatchCase] = (
rawptr[ast.MatchCase])(cnode2)
mc3: rawptr[ast.MatchCase] = (rawptr[ast.MatchCase])(cnode2)
self.Gen.VarGen.enter_scope(trans.SymTab, SCOPE_MATCH)
body_list2: list[ast.AST*]* = mc3.children
if body_list2 is not None:
@@ -1098,8 +1021,7 @@ novirtual class MatchGenMixin:
if def_arr[di] == 1:
dnode: ast.AST* = cases_list.get(di)
if dnode is not None:
dmc: rawptr[ast.MatchCase] = (
rawptr[ast.MatchCase])(dnode)
dmc: rawptr[ast.MatchCase] = (rawptr[ast.MatchCase])(dnode)
self.Gen.VarGen.enter_scope(trans.SymTab, SCOPE_MATCH)
# dbody 预声明+重赋值会使 .get 误分派成 list[int].get
# (i32→inttoptr 截断指针 → translate_stmt 读垃圾节点崩溃,
@@ -1170,11 +1092,9 @@ novirtual class MatchGenMixin:
# fail-fast: 标签缓冲区分配失败
self.Gen.TypeGenErr.fatal_error(node, "标签缓冲区分配失败", "TypeError")
viperlib.snprintf(name_buf, 32, "match.default.%d", cnt)
default_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(
pool, func, name_buf)
default_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, name_buf)
viperlib.snprintf(name_buf, 32, "match.end.%d", cnt)
end_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(
pool, func, name_buf)
end_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, name_buf)
# 3. 收集 case 信息
cases_list: list[ast.AST*]* = node.cases
@@ -1217,12 +1137,10 @@ novirtual class MatchGenMixin:
pk: int = pat.kind()
if pk == ast.ASTKind.MatchValue:
mv: rawptr[ast.MatchValue] = rawptr[ast.MatchValue](pat)
cv = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, mv.value,
cv = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, mv.value,
trans._funcs, trans._func_count, trans)
elif pk == ast.ASTKind.MatchSingleton:
ms: rawptr[ast.MatchSingleton] = (
rawptr[ast.MatchSingleton])(pat)
ms: rawptr[ast.MatchSingleton] = (rawptr[ast.MatchSingleton])(pat)
# None -> 0
cv = llvmlite.const_int32(pool, 0)
elif pk == ast.ASTKind.MatchAs:
@@ -1237,22 +1155,16 @@ novirtual class MatchGenMixin:
first_pat: ast.AST* = pats.get(0)
if first_pat is not None \
and first_pat.kind() == ast.ASTKind.MatchValue:
mv2: rawptr[ast.MatchValue] = (
rawptr[ast.MatchValue])(first_pat)
cv = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, mv2.value,
trans._funcs, trans._func_count, trans)
mv2: rawptr[ast.MatchValue] = (rawptr[ast.MatchValue])(first_pat)
cv = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, mv2.value, trans._funcs, trans._func_count, trans)
elif pk == ast.ASTKind.MatchClass:
# 本路径(非 REnum 分派)不为 class-pattern 臂产出 case 值 → 该臂被
# 静默丢弃、臂体不可达。若该 class-pattern 确实指向已注册 REnum
# (_is_renum_class_name / _is_renum_by_entry 命中),说明是 REnum
# 分派失配,必须 fail-fast 暴露,不得静默丢 case(禁止兜底掩盖)。
rnm_nr: str = self._extract_renum_name_from_cls(pat)
if rnm_nr is not None and (
self.Gen.ClassGenEnum._is_renum_class_name(rnm_nr) != 0
or self.Gen.ClassGenEnum._is_renum_by_entry(rnm_nr) != 0):
self.Gen.TypeGenErr.fatal_error(
pat,
if rnm_nr is not None and (self.Gen.ClassGenEnum._is_renum_class_name(rnm_nr) != 0 or self.Gen.ClassGenEnum._is_renum_by_entry(rnm_nr) != 0):
self.Gen.TypeGenErr.fatal_error(pat,
f"非 REnum 路径收到 REnum 变体模式 'case {rnm_nr}.*':case 值无法产出,该臂会被静默丢弃(REnum 分派失配)",
"InternalCompilerError")
@@ -1260,8 +1172,7 @@ novirtual class MatchGenMixin:
if collected >= MAX_MATCH_CASES:
break
viperlib.snprintf(name_buf, 32, "match.case.%d.%d", cnt, i)
bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(
pool, func, name_buf)
bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, name_buf)
else:
bb = default_bb
@@ -1276,8 +1187,7 @@ novirtual class MatchGenMixin:
collected = collected + 1
if is_def == 0 and cv is not None:
sc: rawptr[llvmlite.SwitchCase] = llvmlite.new_switch_case(
pool, cv, bb)
sc: rawptr[llvmlite.SwitchCase] = llvmlite.new_switch_case(pool, cv, bb)
if sc is not None:
if sw_head is None:
sw_head = sc
@@ -1351,8 +1261,7 @@ novirtual class MatchGenMixin:
if def_arr[di] == 1:
dcase: ast.AST* = cases_list.get(di)
if dcase is not None:
dmc: rawptr[ast.MatchCase] = (
rawptr[ast.MatchCase])(dcase)
dmc: rawptr[ast.MatchCase] = (rawptr[ast.MatchCase])(dcase)
self.Gen.VarGen.enter_scope(trans.SymTab, SCOPE_MATCH)
# dbody 预声明+重赋值会使 .get 误分派成 list[int].get
# (i32→inttoptr 截断指针 → translate_stmt 读垃圾节点崩溃,
+100 -212
View File
@@ -14,24 +14,17 @@ import lib.core.Gen.Translator as HT
import lib.core.Gen.Type.TypeSpec as TSpec
import lib.core.CompilerFactory as CompilerFactory
import lib.Projectrans.Config as Config
# ============================================================
# StmtGenCifMixin - StmtGen 拆分 1/3:CIf 编译期求值 + NewXxxHandle 工厂
#
# 按功能域从 StmtGenMixin.vp 拆出(500~1500 行/文件架构重构,试点):
# 簇 B(CIf 宏求值)+ NewIfHandle/NewWhileHandle/NewForHandle/
# NewReturnHandle/NewMatchHandle 工厂。
# 全部字段保留在本最底层父类(顺序 CifEvalOk->EnumTable->EnumCount->
# DiagStmtCount 与 Generator 组合布局一致,见下方字段注释)。
#
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整)。
# StmtGenCifMixin - CIf 编译期求值 + NewXxxHandle 工厂
# ============================================================
# ============================================================
# StmtGenCifMixin - CIf 求值 + 工厂(最底层父类)
# ============================================================
@t.NoVTable
class StmtGenCifMixin:
novirtual class StmtGenCifMixin:
"""CIf 编译期求值 + NewXxxHandle 工厂(StmtGen 拆分 1/3,最底层)"""
# --- 编译期 CIf 求值状态(原 HandlesIf._g_cif_eval_ok) ---
@@ -135,8 +128,7 @@ class StmtGenCifMixin:
if self.Gen.TypeGenCDef.is_cdefine_found() != 0:
self.CifEvalOk = 1
return v
v2: int = self.Gen.ExprGenCdef._lookup_cross_module_cdefine(
pool, name, trans._from_imports, trans._imported_modules)
v2: int = self.Gen.ExprGenCdef._lookup_cross_module_cdefine(pool, name, trans._from_imports, trans._imported_modules)
if self.Gen.TypeGenCDef.is_cdefine_found() != 0:
self.CifEvalOk = 1
return v2
@@ -167,8 +159,7 @@ class StmtGenCifMixin:
# 跨模块: 确定真实模块名(解析 from_imports 别名)
real_mod: str = vn.id
if trans._from_imports is not None:
resolved: str = self.Gen.ImportsGen.lookup_from_import(
trans._from_imports, vn.id, 0)
resolved: str = self.Gen.ImportsGen.lookup_from_import(trans._from_imports, vn.id, 0)
if resolved is not None:
rm_len: sizet = 0
while resolved[rm_len] != ' ' and resolved[rm_len] != '\0' and resolved[rm_len] != ':':
@@ -485,8 +476,7 @@ class StmtGenCifMixin:
rt_tail: llvmlite.Function* = None
rvi: sizet
for rvi in range(rt_n):
ev_i: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, rtp_elts.get(rvi),
ev_i: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, rtp_elts.get(rvi),
trans._funcs, trans._func_count, trans)
if ev_i is None:
rt_val_ok = 0
@@ -519,8 +509,7 @@ class StmtGenCifMixin:
rvi3: sizet
for rvi3 in range(rt_n):
rv3: llvmlite.Value* = llvmlite.Value*(rt_vals[rvi3])
rfp: llvmlite.Value* = llvmlite.build_gep_struct(
builder, rt_struct_ty, rv3.Ty, rt_tmp, rvi3)
rfp: llvmlite.Value* = llvmlite.build_gep_struct(builder, rt_struct_ty, rv3.Ty, rt_tmp, rvi3)
if rfp is None:
rt_val_ok = 0
break
@@ -535,8 +524,7 @@ class StmtGenCifMixin:
ret_nm: ast.Name* = ast.Name*(rt.value)
if ret_nm is not None and ret_nm.id is not None \
and string.strcmp(ret_nm.id, "self") == 0:
self_ptr: llvmlite.Value* = self.Gen.VarGen.lookup_var(
trans.SymTab, "self")
self_ptr: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, "self")
if self_ptr is not None:
# 检查 self_ptr 是否是 Ptr(Ptr(...))(alloca 存储指针)
self_pointee_ty: llvmlite.LLVMType* = None
@@ -560,8 +548,7 @@ class StmtGenCifMixin:
# 构造(`-> Stack[int]` 里 `return Stack()`)用 CurFuncRetAnnot
# 里的类型实参特化;仅该直接值生效(identity 判定在 CallGenCtor)。
trans.CurRetNode = rt.value
val = self.Gen.ExprGen.translate_value(
builder, pool, mod, rt.value,
val = self.Gen.ExprGen.translate_value(builder, pool, mod, rt.value,
trans._funcs, trans._func_count, trans, ret_val_ty, "返回注解")
trans.CurRetNode = None
@@ -741,8 +728,7 @@ class StmtGenCifMixin:
return 0
# 1. 求值条件表达式
cond_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, if_node.test,
cond_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, if_node.test,
trans._funcs, trans._func_count, trans)
# 2. 转换为 i1 条件
@@ -756,12 +742,10 @@ class StmtGenCifMixin:
elif self.Gen.ExprGenBase.is_ptr_type(cond_val.Ty) != 0:
# 指针类型:与 null 比较(不能用整数 0,否则 llc 报 "integer constant must have integer type")
null_cond: llvmlite.Value* = llvmlite.ConstNull(pool, cond_val.Ty, "null")
cond_i1 = llvmlite.build_icmp(
builder, llvmlite.ICMP_NE, cond_val, null_cond)
cond_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cond_val, null_cond)
else:
zero: llvmlite.Value* = llvmlite.const_int32(pool, 0)
cond_i1 = llvmlite.build_icmp(
builder, llvmlite.ICMP_NE, cond_val, zero)
cond_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cond_val, zero)
# 3. 创建基本块(使用 trans._label_counter 生成唯一标签名,不与 SSA 名共享)
cnt: int = trans._label_counter
@@ -898,8 +882,7 @@ class StmtGenCifMixin:
# 3. cond 块: 求值条件,条件分支
llvmlite.position_at_end(builder, cond_bb)
cond_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, while_node.test,
cond_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, while_node.test,
trans._funcs, trans._func_count, trans)
if cond_val is None:
# fail-fast: while 条件表达式翻译失败
@@ -912,12 +895,10 @@ class StmtGenCifMixin:
elif self.Gen.ExprGenBase.is_ptr_type(cond_val.Ty) != 0:
# 指针类型:与 null 比较(不能用整数 0,否则 llc 报 "integer constant must have integer type")
null_cond: llvmlite.Value* = llvmlite.ConstNull(pool, cond_val.Ty, "null")
cond_i1 = llvmlite.build_icmp(
builder, llvmlite.ICMP_NE, cond_val, null_cond)
cond_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cond_val, null_cond)
else:
zero: llvmlite.Value* = llvmlite.const_int32(pool, 0)
cond_i1 = llvmlite.build_icmp(
builder, llvmlite.ICMP_NE, cond_val, zero)
cond_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cond_val, zero)
llvmlite.build_cond_br(builder, cond_i1, body_bb, end_bb)
# 4. body 块: 翻译循环体,跳回 cond
@@ -1048,7 +1029,7 @@ class StmtGenCifMixin:
if builder is None or func is None:
return 0
for_node: rawptr[ast.For] = rawptr[ast.For](node)
for_node: ast.For* = ast.For*(node)
# 1. 获取循环变量(Name 单变量 / Tuple 多变量)
target: ast.AST* = for_node.target
@@ -1125,16 +1106,14 @@ class StmtGenCifMixin:
if iter_node.kind() == ast.ASTKind.Name and trans is not None:
nm_lst: ast.Name* = ast.Name*(iter_node)
if nm_lst.id is not None:
ve_lst: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, nm_lst.id)
ve_lst: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm_lst.id)
lst_annot: str = self.Gen.VarGen.var_annot_class_name(ve_lst)
if lst_annot is not None:
# dict 容器变量:按 __count__/__keys__ 布局迭代(__iter__ 协议内联)
# [S4] 容器基名精确比较(SpecTypeNameBaseIs):原 strstr("dict") 子串匹配
# 会误命中任何含 "dict" 的类名(如 MyDictHelper)。
if TSpec.SpecTypeNameBaseIs(lst_annot, "dict") != 0:
lst_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, iter_node,
lst_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, iter_node,
trans._funcs, trans._func_count, trans)
if lst_val is not None and lst_val.Ty is not None \
and self.Gen.ExprGenBase.is_ptr_type(lst_val.Ty) != 0:
@@ -1142,53 +1121,42 @@ class StmtGenCifMixin:
# [S4] 同上:原 strstr("list") 会误命中 playlist / GSList 等;
# 非 list 基名的用户类改由下方 OOP __iter__/__next__ 路径处理(更正确)。
if TSpec.SpecTypeNameBaseIs(lst_annot, "list") != 0:
lst_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, iter_node,
trans._funcs, trans._func_count, trans)
lst_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, iter_node, trans._funcs, trans._func_count, trans)
if lst_val is not None and lst_val.Ty is not None \
and self.Gen.ExprGenBase.is_ptr_type(lst_val.Ty) != 0:
return self._handle_list_iter(trans, for_node, var_name, lst_val)
# OOP iter 协议:迭代源是类对象且类有 __iter__/__next__ 方法 →
# 走 __iter__/__next__ 调用迭代(对齐 TPC HandlesFor.py L142-166
# _HandleForIterLlvm)。dict/list 是内置泛型容器已在上方内联处理。
ov_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, iter_node,
ov_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, iter_node,
trans._funcs, trans._func_count, trans)
if ov_val is not None and ov_val.Ty is not None \
and self.Gen.ExprGenBase.is_ptr_type(ov_val.Ty) != 0:
ov_st: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(
ov_val)
ov_st: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(ov_val)
if ov_st is not None:
ov_cn: str = self.Gen.StructGen.get_class_name_by_type(pool, ov_st)
if ov_cn is not None:
oi_lookup: str = pool.alloc(128)
if oi_lookup is not None:
viperlib.snprintf(oi_lookup, 128, "%s.__iter__", ov_cn)
oi_fn: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(
trans.Module, oi_lookup)
oi_fn: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(trans.Module, oi_lookup)
if oi_fn is not None:
on_lookup: str = pool.alloc(128)
if on_lookup is not None:
viperlib.snprintf(on_lookup, 128, "%s.__next__", ov_cn)
on_fn: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(
trans.Module, on_lookup)
on_fn: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(trans.Module, on_lookup)
if on_fn is not None:
return self._handle_oop_iter(
trans, for_node, var_name, ov_cn, ov_val)
return self._handle_oop_iter(trans, for_node, var_name, ov_cn, ov_val)
# 其它不支持的字面量:fast-fail 显式报错,
# 避免 translate_value 触发 list[T] 特化崩溃或语义歧义。
ik: int = iter_node.kind()
if ik == ast.ASTKind.Constant:
cn_ik: ast.Constant* = ast.Constant*(iter_node)
if cn_ik.const_kind != ast.CONST_STR:
self.Gen.TypeGenErr.fatal_error(
iter_node,
"for 迭代不支持该常量(仅支持字符串、数组、列表字面量、range())")
self.Gen.TypeGenErr.fatal_error(iter_node, "for 迭代不支持该常量(仅支持字符串、数组、列表字面量、range())")
elif ik == ast.ASTKind.Dict or ik == ast.ASTKind.Set or ik == ast.ASTKind.Tuple \
or ik == ast.ASTKind.SetComp or ik == ast.ASTKind.DictComp:
self.Gen.TypeGenErr.fatal_error(
iter_node,
"for 迭代不支持字典/集合/元组字面量,请使用 range()、t.CArray 数组或列表字面量")
self.Gen.TypeGenErr.fatal_error(iter_node, "for 迭代不支持字典/集合/元组字面量,请使用 range()、t.CArray 数组或列表字面量")
return self._handle_ptr_iter(trans, for_node, var_name)
call: ast.Call* = ast.Call*(iter_node)
@@ -1208,29 +1176,21 @@ class StmtGenCifMixin:
# fail-fast: range 无参数,立即终止
self.Gen.TypeGenErr.fatal_error(call, "range 需要至少一个参数", "SyntaxError")
elif arg_count == 1:
stop_val = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, args.get(0),
trans._funcs, trans._func_count, trans)
stop_val = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, args.get(0), trans._funcs, trans._func_count, trans)
if stop_val is None:
# fail-fast: range 参数翻译失败
self.Gen.TypeGenErr.fatal_error(args.get(0), "range 参数翻译失败", "TypeError")
elif arg_count >= 2:
start_val = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, args.get(0),
trans._funcs, trans._func_count, trans)
start_val = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, args.get(0), trans._funcs, trans._func_count, trans)
if start_val is None:
# fail-fast: range 参数翻译失败
self.Gen.TypeGenErr.fatal_error(args.get(0), "range 参数翻译失败", "TypeError")
stop_val = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, args.get(1),
trans._funcs, trans._func_count, trans)
stop_val = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, args.get(1), trans._funcs, trans._func_count, trans)
if stop_val is None:
# fail-fast: range 参数翻译失败
self.Gen.TypeGenErr.fatal_error(args.get(1), "range 参数翻译失败", "TypeError")
if arg_count >= 3:
step_val = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, args.get(2),
trans._funcs, trans._func_count, trans)
step_val = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, args.get(2), trans._funcs, trans._func_count, trans)
if step_val is None:
# fail-fast: range 参数翻译失败
self.Gen.TypeGenErr.fatal_error(args.get(2), "range 参数翻译失败", "TypeError")
@@ -1330,8 +1290,7 @@ class StmtGenCifMixin:
# 命中父函数同名变量(如父函数自己的循环计数器 i)→ 循环计数写到
# 父函数存储 → 跨函数 SSA 错乱(llc "instruction expected to be
# numbered",Terminal _cmd_cd 的 for i in range(1,64) 根因)。
var_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_current(
trans.SymTab, var_name)
var_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, var_name)
new_vars: int = 0
if var_alloca is None:
# 用 _alloca_at_entry:alloca 放函数入口块,保证支配性
@@ -1343,8 +1302,7 @@ class StmtGenCifMixin:
# 位宽随 range 参数类型(loop_store_ty),不再固定 i32:
# uint64 上界 → i64 alloca,避免 trunc i64→i32 丢失高位。
var_alloca = self.Gen.VarGen._alloca_at_entry(builder, loop_store_ty)
if self.Gen.VarGen.define_var(
trans.SymTab, var_name, var_alloca) == 0:
if self.Gen.VarGen.define_var(trans.SymTab, var_name, var_alloca) == 0:
new_vars = 1
# 获取循环变量的实际元素类型(alloca 是指针类型,需解引用 Pointee)
@@ -1416,8 +1374,7 @@ class StmtGenCifMixin:
range_cmp_op = llvmlite.ICMP_UGT
else:
range_cmp_op = llvmlite.ICMP_ULT
cond_i1: llvmlite.Value* = llvmlite.build_icmp(
builder, range_cmp_op, cmp_lhs, cmp_rhs)
cond_i1: llvmlite.Value* = llvmlite.build_icmp(builder, range_cmp_op, cmp_lhs, cmp_rhs)
llvmlite.build_cond_br(builder, cond_i1, body_bb, end_bb)
# 9. body 块: 翻译循环体,跳到 incr
@@ -1517,8 +1474,7 @@ class StmtGenCifMixin:
if k == ast.ASTKind.Name:
nm_s: ast.Name* = ast.Name*(src)
if nm_s.id is not None and trans is not None:
ve_s: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, nm_s.id)
ve_s: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm_s.id)
sq_annot: str = self.Gen.VarGen.var_annot_class_name(ve_s)
if sq_annot is not None:
# [S4] 容器基名精确比较(原 strstr("list") 子串匹配会误命中 playlist 等)
@@ -1528,7 +1484,7 @@ class StmtGenCifMixin:
return 0
def _build_seq_loop(self, trans: HT.Translator*,
for_node: rawptr[ast.For],
for_node: ast.For*,
t1: str, t2: str,
src1: ast.AST*,
src2: ast.AST*,
@@ -1570,50 +1526,37 @@ class StmtGenCifMixin:
if cargs1 is not None:
n1: sizet = len(cargs1)
if n1 >= 1:
sv: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, cargs1.get(0),
sv: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs1.get(0),
trans._funcs, trans._func_count, trans)
if sv is None:
# fail-fast: range 参数翻译失败
self.Gen.TypeGenErr.fatal_error(cargs1.get(0), "range 参数翻译失败", "TypeError")
r1_stop = self.Gen.ExprGenBase.coerce_to_type(builder, sv, i64_ty, cargs1.get(0))
if n1 >= 2:
sv2: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, cargs1.get(1),
trans._funcs, trans._func_count, trans)
sv2: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs1.get(1), trans._funcs, trans._func_count, trans)
if sv2 is None:
# fail-fast: range 参数翻译失败
self.Gen.TypeGenErr.fatal_error(cargs1.get(1), "range 参数翻译失败", "TypeError")
r1_start = self.Gen.ExprGenBase.coerce_to_type(builder, sv2, i64_ty, cargs1.get(1))
if n1 >= 3:
sv3: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, cargs1.get(2),
trans._funcs, trans._func_count, trans)
sv3: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs1.get(2), trans._funcs, trans._func_count, trans)
if sv3 is None:
# fail-fast: range 参数翻译失败
self.Gen.TypeGenErr.fatal_error(cargs1.get(2), "range 参数翻译失败", "TypeError")
r1_step = self.Gen.ExprGenBase.coerce_to_type(builder, sv3, i64_ty, cargs1.get(2))
elif kind1 == GenTypes.SEQ_KIND_STR:
elem1_ty = i8_ty
s1_ptr = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, src1,
trans._funcs, trans._func_count, trans)
s1_ptr = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, src1, trans._funcs, trans._func_count, trans)
if s1_ptr is None:
self.Gen.TypeGenErr.fatal_error(for_node, "序列迭代: 字符串源翻译失败")
elif kind1 == GenTypes.SEQ_KIND_LIST:
elem1_ty = i8_ptr_ty
l1_obj: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, src1,
trans._funcs, trans._func_count, trans)
if l1_obj is None or l1_obj.Ty is None \
or self.Gen.ExprGenBase.is_ptr_type(l1_obj.Ty) == 0:
l1_obj: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, src1, trans._funcs, trans._func_count, trans)
if l1_obj is None or l1_obj.Ty is None or self.Gen.ExprGenBase.is_ptr_type(l1_obj.Ty) == 0:
self.Gen.TypeGenErr.fatal_error(for_node, "序列迭代: list 源不是指针类型")
l1_count = llvmlite.build_load(builder, i64_ty,
llvmlite.build_gep(builder, i64_ty, l1_obj, llvmlite.const_int64(pool, 1)))
l1_data = llvmlite.build_load(builder, i8_ptr_ty,
llvmlite.build_gep(builder, i64_ty, l1_obj, llvmlite.const_int64(pool, 0)))
l1_esize = llvmlite.build_load(builder, i64_ty,
llvmlite.build_gep(builder, i64_ty, l1_obj, llvmlite.const_int64(pool, 4)))
l1_count = llvmlite.build_load(builder, i64_ty, llvmlite.build_gep(builder, i64_ty, l1_obj, llvmlite.const_int64(pool, 1)))
l1_data = llvmlite.build_load(builder, i8_ptr_ty, llvmlite.build_gep(builder, i64_ty, l1_obj, llvmlite.const_int64(pool, 0)))
l1_esize = llvmlite.build_load(builder, i64_ty, llvmlite.build_gep(builder, i64_ty, l1_obj, llvmlite.const_int64(pool, 4)))
# ---- 源 2 准备(zip)----
kind2: int = 0
@@ -1640,50 +1583,36 @@ class StmtGenCifMixin:
if cargs2 is not None:
n2: sizet = len(cargs2)
if n2 >= 1:
svz: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, cargs2.get(0),
trans._funcs, trans._func_count, trans)
svz: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs2.get(0), trans._funcs, trans._func_count, trans)
if svz is None:
# fail-fast: range 参数翻译失败
self.Gen.TypeGenErr.fatal_error(cargs2.get(0), "range 参数翻译失败", "TypeError")
r2_stop = self.Gen.ExprGenBase.coerce_to_type(builder, svz, i64_ty, cargs2.get(0))
if n2 >= 2:
svz2: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, cargs2.get(1),
trans._funcs, trans._func_count, trans)
svz2: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs2.get(1), trans._funcs, trans._func_count, trans)
if svz2 is None:
# fail-fast: range 参数翻译失败
self.Gen.TypeGenErr.fatal_error(cargs2.get(1), "range 参数翻译失败", "TypeError")
r2_start = self.Gen.ExprGenBase.coerce_to_type(builder, svz2, i64_ty, cargs2.get(1))
if n2 >= 3:
svz3: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, cargs2.get(2),
trans._funcs, trans._func_count, trans)
svz3: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs2.get(2), trans._funcs, trans._func_count, trans)
if svz3 is None:
# fail-fast: range 参数翻译失败
self.Gen.TypeGenErr.fatal_error(cargs2.get(2), "range 参数翻译失败", "TypeError")
r2_step = self.Gen.ExprGenBase.coerce_to_type(builder, svz3, i64_ty, cargs2.get(2))
elif kind2 == GenTypes.SEQ_KIND_STR:
elem2_ty = i8_ty
s2_ptr = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, src2,
trans._funcs, trans._func_count, trans)
s2_ptr = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, src2, trans._funcs, trans._func_count, trans)
if s2_ptr is None:
self.Gen.TypeGenErr.fatal_error(for_node, "序列迭代: 字符串源 2 翻译失败")
elif kind2 == GenTypes.SEQ_KIND_LIST:
elem2_ty = i8_ptr_ty
l2_obj: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, src2,
trans._funcs, trans._func_count, trans)
if l2_obj is None or l2_obj.Ty is None \
or self.Gen.ExprGenBase.is_ptr_type(l2_obj.Ty) == 0:
l2_obj: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, src2, trans._funcs, trans._func_count, trans)
if l2_obj is None or l2_obj.Ty is None or self.Gen.ExprGenBase.is_ptr_type(l2_obj.Ty) == 0:
self.Gen.TypeGenErr.fatal_error(for_node, "序列迭代: list 源 2 不是指针类型")
l2_count = llvmlite.build_load(builder, i64_ty,
llvmlite.build_gep(builder, i64_ty, l2_obj, llvmlite.const_int64(pool, 1)))
l2_data = llvmlite.build_load(builder, i8_ptr_ty,
llvmlite.build_gep(builder, i64_ty, l2_obj, llvmlite.const_int64(pool, 0)))
l2_esize = llvmlite.build_load(builder, i64_ty,
llvmlite.build_gep(builder, i64_ty, l2_obj, llvmlite.const_int64(pool, 4)))
l2_count = llvmlite.build_load(builder, i64_ty, llvmlite.build_gep(builder, i64_ty, l2_obj, llvmlite.const_int64(pool, 1)))
l2_data = llvmlite.build_load(builder, i8_ptr_ty, llvmlite.build_gep(builder, i64_ty, l2_obj, llvmlite.const_int64(pool, 0)))
l2_esize = llvmlite.build_load(builder, i64_ty, llvmlite.build_gep(builder, i64_ty, l2_obj, llvmlite.const_int64(pool, 4)))
# ---- 循环变量 alloca ----
# t1: enumerate → 序号 (i32);zip → 源 1 元素
@@ -1860,7 +1789,7 @@ class StmtGenCifMixin:
# end:
# ============================================================
def _handle_ptr_iter(self, trans: HT.Translator*,
for_node: rawptr[ast.For],
for_node: ast.For*,
var_name: str) -> int:
"""指针迭代: for x in ptr: 直到解引用为空"""
pool: memhub.MemBuddy* = trans.Pool
@@ -1868,9 +1797,7 @@ class StmtGenCifMixin:
func: llvmlite.Function* = trans._cur_func
# 翻译迭代器表达式,获取指针值
ptr_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, for_node.iter,
trans._funcs, trans._func_count, trans)
ptr_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, for_node.iter, trans._funcs, trans._func_count, trans)
if ptr_val is None:
self.Gen.TypeGenErr.fatal_error(for_node, "指针迭代: 无法翻译迭代器表达式")
@@ -1904,13 +1831,11 @@ class StmtGenCifMixin:
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
# 创建循环变量 alloca(存储元素值)
var_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(
trans.SymTab, var_name)
var_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, var_name)
new_vars: int = 0
if var_alloca is None:
var_alloca = self.Gen.VarGen._alloca_at_entry(builder, elem_ty)
if self.Gen.VarGen.define_var(
trans.SymTab, var_name, var_alloca) == 0:
if self.Gen.VarGen.define_var(trans.SymTab, var_name, var_alloca) == 0:
new_vars = 1
# 创建隐式 index 变量,初始为 0
@@ -1940,8 +1865,7 @@ class StmtGenCifMixin:
# cond 块: load index, GEP, load elem, 空值判定(整数==0 / 指针==null / 浮点==0.0)
llvmlite.position_at_end(builder, cond_bb)
cur_idx: llvmlite.Value* = llvmlite.build_load(builder, i32_ty, idx_alloca)
elem_ptr: llvmlite.Value* = llvmlite.build_gep(
builder, elem_ty, ptr_val, cur_idx)
elem_ptr: llvmlite.Value* = llvmlite.build_gep(builder, elem_ty, ptr_val, cur_idx)
cur_elem: llvmlite.Value* = llvmlite.build_load(builder, elem_ty, elem_ptr)
is_null: llvmlite.Value* = None
if elem_is_ptr2 != 0:
@@ -2024,7 +1948,7 @@ class StmtGenCifMixin:
# end:
# ============================================================
def _handle_array_iter(self, trans: HT.Translator*,
for_node: rawptr[ast.For],
for_node: ast.For*,
var_name: str,
array_val: llvmlite.Value*) -> int:
"""数组迭代: for x in arr: 按数组长度迭代"""
@@ -2054,13 +1978,11 @@ class StmtGenCifMixin:
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
# 循环变量 alloca(存储元素值)
var_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(
trans.SymTab, var_name)
var_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, var_name)
new_vars: int = 0
if var_alloca is None:
var_alloca = self.Gen.VarGen._alloca_at_entry(builder, elem_ty)
if self.Gen.VarGen.define_var(
trans.SymTab, var_name, var_alloca) == 0:
if self.Gen.VarGen.define_var(trans.SymTab, var_name, var_alloca) == 0:
new_vars = 1
# 隐式 index 变量,初始为 0
@@ -2093,16 +2015,14 @@ class StmtGenCifMixin:
llvmlite.position_at_end(builder, cond_bb)
cur_idx: llvmlite.Value* = llvmlite.build_load(builder, i32_ty, idx_alloca)
count_val: llvmlite.Value* = llvmlite.const_int32(pool, elem_count)
in_bounds: llvmlite.Value* = llvmlite.build_icmp(
builder, llvmlite.ICMP_SLT, cur_idx, count_val)
in_bounds: llvmlite.Value* = llvmlite.build_icmp(builder, llvmlite.ICMP_SLT, cur_idx, count_val)
llvmlite.build_cond_br(builder, in_bounds, elem_check_bb, end_bb)
# elem_check 块: GEP(0, idx) → load elem → 空值判定(NULL 终止)
# 用户语义:整数/指针/浮点元素按"解引用为空"提前终止(如 split 尾哨兵
# 的 str 数组),同时保留长度上限防越界读;聚合元素只按长度迭代。
llvmlite.position_at_end(builder, elem_check_bb)
elem_ptr: llvmlite.Value* = llvmlite.build_gep_array(
builder, arr_ty, elem_ty, arr_tmp, cur_idx)
elem_ptr: llvmlite.Value* = llvmlite.build_gep_array(builder, arr_ty, elem_ty, arr_tmp, cur_idx)
cur_elem: llvmlite.Value* = llvmlite.build_load(builder, elem_ty, elem_ptr)
elem_bits_a: int = self.Gen.ExprGenBase.get_llvm_type_bits(elem_ty)
elem_ptr_a: int = self.Gen.ExprGenBase.is_ptr_type(elem_ty)
@@ -2170,7 +2090,7 @@ class StmtGenCifMixin:
# 元素类型取第一个元素的值类型,其余元素 coerce 到该类型。
# ============================================================
def _handle_list_literal_iter(self, trans: HT.Translator*,
for_node: rawptr[ast.For],
for_node: ast.For*,
var_name: str,
list_node: ast.AST*) -> int:
"""列表字面量迭代: for x in [a, b, c]: 按元素顺序迭代"""
@@ -2193,8 +2113,7 @@ class StmtGenCifMixin:
# 列表元素计数 > 实际填充 ⇒ 该槽为裸 0 ⇒ 上层某处产生了空 AST 元素。
# 不给下游 translate_value 的守卫吞掉(那会静默跳过 store、产出错值),此处响亮失败。
if first_el is None:
self.Gen.TypeGenErr.fatal_error(
for_node,
self.Gen.TypeGenErr.fatal_error(for_node,
f"列表字面量迭代遇到空 AST 元素:第 0 个元素为裸空指针(0),"
f"但元素计数为 {elts_count}(元素与计数不一致);上层某处产生了空 AST 元素,已终止编译。",
"ValueError")
@@ -2202,14 +2121,12 @@ class StmtGenCifMixin:
# @t.CVTable 类对象首字即 vptr,为 0 时下游任意虚调用(kind()/dump())都会
# `load [0+slot]` ⇒ ASan READ at 0x0。读首字的唯一可用写法是 c.Deref((uint64*)(p))。
if c.Deref((uint64*)(first_el)) == 0:
self.Gen.TypeGenErr.fatal_error(
for_node,
self.Gen.TypeGenErr.fatal_error(for_node,
f"列表字面量迭代遇到【对象无效】的 AST 元素(vptr 为 0):第 0 个元素指针非 0"
f"(地址 {uint64(first_el)})但其对象首字(vtable 指针)为 0,元素计数 {elts_count};"
f"上层某处产生了「未初始化 vptr 的 AST 节点」(典型源:深拷贝只搬字段未搬 vptr),已终止编译。",
"ValueError")
first_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, first_el,
first_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, first_el,
trans._funcs, trans._func_count, trans)
if first_val is None or first_val.Ty is None:
self.Gen.TypeGenErr.fatal_error(first_el, "列表字面量迭代: 无法确定元素类型")
@@ -2221,8 +2138,7 @@ class StmtGenCifMixin:
tmp_alloca: llvmlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, arr_ty)
if tmp_alloca is None:
self.Gen.TypeGenErr.fatal_error(for_node, "列表字面量迭代: 临时数组分配失败")
first_ptr: llvmlite.Value* = llvmlite.build_gep_array(
builder, arr_ty, elem_ty, tmp_alloca, llvmlite.const_int32(pool, 0))
first_ptr: llvmlite.Value* = llvmlite.build_gep_array(builder, arr_ty, elem_ty, tmp_alloca, llvmlite.const_int32(pool, 0))
if first_ptr is not None:
llvmlite.build_store(builder, first_val, first_ptr)
# 写其余元素(coerce 到 elem_ty)
@@ -2231,27 +2147,21 @@ class StmtGenCifMixin:
el_node: ast.AST* = elts.get(i)
# 显式判空(同上,用 `is None`):不得让空元素被 translate_value 的 None 守卫静默吞掉。
if el_node is None:
self.Gen.TypeGenErr.fatal_error(
for_node,
self.Gen.TypeGenErr.fatal_error(for_node,
f"列表字面量迭代遇到空 AST 元素:第 {i} 个元素为裸空指针(0),"
f"但元素计数为 {elts_count}(元素与计数不一致);上层某处产生了空 AST 元素,已终止编译。",
"ValueError")
# 对象有效性校验(vptr 非 0),同第 0 元素处:同族"取元素后即用"路径。
if c.Deref((uint64*)(el_node)) == 0:
self.Gen.TypeGenErr.fatal_error(
for_node,
self.Gen.TypeGenErr.fatal_error(for_node,
f"列表字面量迭代遇到【对象无效】的 AST 元素(vptr 为 0):第 {i} 个元素指针非 0"
f"(地址 {uint64(el_node)})但其对象首字(vtable 指针)为 0,元素计数 {elts_count};"
f"上层某处产生了「未初始化 vptr 的 AST 节点」(典型源:深拷贝只搬字段未搬 vptr),已终止编译。",
"ValueError")
el_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, el_node,
trans._funcs, trans._func_count, trans)
el_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, el_node, trans._funcs, trans._func_count, trans)
if el_val is not None:
el_val = self.Gen.ExprGenBase.coerce_to_type(builder, el_val, elem_ty, el_node)
el_ptr: llvmlite.Value* = llvmlite.build_gep_array(
builder, arr_ty, elem_ty, tmp_alloca,
llvmlite.const_int32(pool, i))
el_ptr: llvmlite.Value* = llvmlite.build_gep_array(builder, arr_ty, elem_ty, tmp_alloca, llvmlite.const_int32(pool, i))
if el_ptr is not None:
llvmlite.build_store(builder, el_val, el_ptr)
i += 1
@@ -2291,7 +2201,7 @@ class StmtGenCifMixin:
# end:
# ============================================================
def _handle_list_iter(self, trans: HT.Translator*,
for_node: rawptr[ast.For],
for_node: ast.For*,
var_name: str,
list_val: llvmlite.Value*) -> int:
"""list[T] 容器迭代: for v in lst: 按 __count__ 动态长度迭代"""
@@ -2304,20 +2214,17 @@ class StmtGenCifMixin:
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
# 读取 __count__ (偏移 8, GEP index 1)
cnt_ptr: llvmlite.Value* = llvmlite.build_gep(
builder, i64_ty, list_val, llvmlite.const_int64(pool, 1))
cnt_ptr: llvmlite.Value* = llvmlite.build_gep(builder, i64_ty, list_val, llvmlite.const_int64(pool, 1))
if cnt_ptr is None:
self.Gen.TypeGenErr.fatal_error(for_node, "list 迭代: 无法定位 __count__")
count_val: llvmlite.Value* = llvmlite.build_load(builder, i64_ty, cnt_ptr)
# 循环变量 alloca(元素类型 i8*,与 list.get 内联一致)
var_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(
trans.SymTab, var_name)
var_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, var_name)
new_vars: int = 0
if var_alloca is None:
var_alloca = self.Gen.VarGen._alloca_at_entry(builder, i8_ptr_ty)
if self.Gen.VarGen.define_var(
trans.SymTab, var_name, var_alloca) == 0:
if self.Gen.VarGen.define_var(trans.SymTab, var_name, var_alloca) == 0:
new_vars = 1
# 隐式 index 变量 (i64,与 __count__ 类型对齐)
@@ -2346,21 +2253,17 @@ class StmtGenCifMixin:
# cond 块: load index, icmp slt idx, count
llvmlite.position_at_end(builder, cond_bb)
cur_idx: llvmlite.Value* = llvmlite.build_load(builder, i64_ty, idx_alloca)
in_bounds: llvmlite.Value* = llvmlite.build_icmp(
builder, llvmlite.ICMP_SLT, cur_idx, count_val)
in_bounds: llvmlite.Value* = llvmlite.build_icmp(builder, llvmlite.ICMP_SLT, cur_idx, count_val)
llvmlite.build_cond_br(builder, in_bounds, body_bb, end_bb)
# body 块: __data__ + idx*__elem_size__ → load 元素 → store to var
llvmlite.position_at_end(builder, body_bb)
dpp: llvmlite.Value* = llvmlite.build_gep(
builder, i64_ty, list_val, llvmlite.const_int64(pool, 0))
dpp: llvmlite.Value* = llvmlite.build_gep(builder, i64_ty, list_val, llvmlite.const_int64(pool, 0))
data_ptr: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty, dpp)
epp: llvmlite.Value* = llvmlite.build_gep(
builder, i64_ty, list_val, llvmlite.const_int64(pool, 4))
epp: llvmlite.Value* = llvmlite.build_gep(builder, i64_ty, list_val, llvmlite.const_int64(pool, 4))
esize: llvmlite.Value* = llvmlite.build_load(builder, i64_ty, epp)
offset: llvmlite.Value* = llvmlite.build_mul(builder, cur_idx, esize)
elem_addr: llvmlite.Value* = llvmlite.build_gep(
builder, i8_ty, data_ptr, offset)
elem_addr: llvmlite.Value* = llvmlite.build_gep(builder, i8_ty, data_ptr, offset)
cur_elem: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty, elem_addr)
llvmlite.build_store(builder, cur_elem, var_alloca)
@@ -2398,7 +2301,7 @@ class StmtGenCifMixin:
return new_vars
def _handle_dict_iter(self, trans: HT.Translator*,
for_node: rawptr[ast.For],
for_node: ast.For*,
var_name: str,
dict_val: llvmlite.Value*) -> int:
"""dict 容器迭代: for key in d: 按 __count__/__keys__ 布局迭代
@@ -2417,20 +2320,17 @@ class StmtGenCifMixin:
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
# 读取 __count__(槽 2,字节偏移 16)
cnt_ptr: llvmlite.Value* = llvmlite.build_gep(
builder, i64_ty, dict_val, llvmlite.const_int64(pool, 2))
cnt_ptr: llvmlite.Value* = llvmlite.build_gep(builder, i64_ty, dict_val, llvmlite.const_int64(pool, 2))
if cnt_ptr is None:
self.Gen.TypeGenErr.fatal_error(for_node, "dict 迭代: 无法定位 __count__")
count_val: llvmlite.Value* = llvmlite.build_load(builder, i64_ty, cnt_ptr)
# 循环变量 alloca(元素类型 i8*,与 dict.__next__ 返回 str 一致)
var_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(
trans.SymTab, var_name)
var_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, var_name)
new_vars: int = 0
if var_alloca is None:
var_alloca = self.Gen.VarGen._alloca_at_entry(builder, i8_ptr_ty)
if self.Gen.VarGen.define_var(
trans.SymTab, var_name, var_alloca) == 0:
if self.Gen.VarGen.define_var(trans.SymTab, var_name, var_alloca) == 0:
new_vars = 1
# 隐式 index 变量 (i64,与 __count__ 类型对齐)
@@ -2459,19 +2359,16 @@ class StmtGenCifMixin:
# cond 块: load index, icmp slt idx, count
llvmlite.position_at_end(builder, cond_bb)
cur_idx: llvmlite.Value* = llvmlite.build_load(builder, i64_ty, idx_alloca)
in_bounds: llvmlite.Value* = llvmlite.build_icmp(
builder, llvmlite.ICMP_SLT, cur_idx, count_val)
in_bounds: llvmlite.Value* = llvmlite.build_icmp(builder, llvmlite.ICMP_SLT, cur_idx, count_val)
llvmlite.build_cond_br(builder, in_bounds, body_bb, end_bb)
# body 块: __keys__ + idx*8 → load key (i8*) → store to var
llvmlite.position_at_end(builder, body_bb)
kpp: llvmlite.Value* = llvmlite.build_gep(
builder, i64_ty, dict_val, llvmlite.const_int64(pool, 0))
kpp: llvmlite.Value* = llvmlite.build_gep(builder, i64_ty, dict_val, llvmlite.const_int64(pool, 0))
keys_ptr: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty, kpp)
eight_val: llvmlite.Value* = llvmlite.const_int64(pool, 8)
key_offset: llvmlite.Value* = llvmlite.build_mul(builder, cur_idx, eight_val)
key_addr: llvmlite.Value* = llvmlite.build_gep(
builder, i8_ty, keys_ptr, key_offset)
key_addr: llvmlite.Value* = llvmlite.build_gep(builder, i8_ty, keys_ptr, key_offset)
cur_key: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty, key_addr)
llvmlite.build_store(builder, cur_key, var_alloca)
@@ -2535,7 +2432,7 @@ class StmtGenCifMixin:
# VpiReader stub 声明同步该参数(_inject_method_declare)。
# ============================================================
def _handle_oop_iter(self, trans: HT.Translator*,
for_node: rawptr[ast.For],
for_node: ast.For*,
var_name: str,
class_name: str,
obj_val: llvmlite.Value*) -> int:
@@ -2557,11 +2454,9 @@ class StmtGenCifMixin:
if iter_lookup is None:
return 0
viperlib.snprintf(iter_lookup, 128, "%s.__iter__", class_name)
iter_fn: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(
mod, iter_lookup)
iter_fn: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, iter_lookup)
if iter_fn is None:
self.Gen.TypeGenErr.fatal_error(
for_node, f"OOP 迭代: 类 '{class_name}' 没有 __iter__ 方法")
self.Gen.TypeGenErr.fatal_error(for_node, f"OOP 迭代: 类 '{class_name}' 没有 __iter__ 方法")
iter_ret_ty: llvmlite.LLVMType* = llvmlite.function_get_ret_ty(iter_fn)
iter_fn_name: str = llvmlite.function_get_name(iter_fn)
if iter_ret_ty is None or iter_fn_name is None:
@@ -2576,8 +2471,7 @@ class StmtGenCifMixin:
if iter_self is None:
return 0
iter_self.Next = None
iter_result: llvmlite.Value* = llvmlite.build_call(
builder, iter_fn_name, iter_self, 1, iter_ret_ty, 0)
iter_result: llvmlite.Value* = llvmlite.build_call(builder, iter_fn_name, iter_self, 1, iter_ret_ty, 0)
if iter_result is None:
return 0
@@ -2586,25 +2480,21 @@ class StmtGenCifMixin:
if next_lookup is None:
return 0
viperlib.snprintf(next_lookup, 128, "%s.__next__", class_name)
next_fn: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(
mod, next_lookup)
next_fn: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, next_lookup)
if next_fn is None:
self.Gen.TypeGenErr.fatal_error(
for_node, f"OOP 迭代: 类 '{class_name}' 没有 __next__ 方法")
self.Gen.TypeGenErr.fatal_error(for_node, f"OOP 迭代: 类 '{class_name}' 没有 __next__ 方法")
next_ret_ty: llvmlite.LLVMType* = llvmlite.function_get_ret_ty(next_fn)
next_fn_name: str = llvmlite.function_get_name(next_fn)
if next_ret_ty is None or next_fn_name is None:
return 0
# 3. 循环变量 alloca(元素类型 = __next__ 返回类型)
var_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(
trans.SymTab, var_name)
var_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, var_name)
new_vars: int = 0
if var_alloca is None:
var_alloca = self.Gen.VarGen._alloca_at_entry(builder, next_ret_ty)
if var_alloca is not None:
if self.Gen.VarGen.define_var(
trans.SymTab, var_name, var_alloca) == 0:
if self.Gen.VarGen.define_var(trans.SymTab, var_name, var_alloca) == 0:
new_vars = 1
# 4. stop flag alloca(i1,初始 0)
@@ -2649,8 +2539,7 @@ class StmtGenCifMixin:
# 参数链表: arg1(iter).Next = arg2(flag);flag 独立 null 结尾防自链接
next_self.Next = flag_alloca
flag_alloca.Next = None
next_val: llvmlite.Value* = llvmlite.build_call(
builder, next_fn_name, next_self, 2, next_ret_ty, 0)
next_val: llvmlite.Value* = llvmlite.build_call(builder, next_fn_name, next_self, 2, next_ret_ty, 0)
if next_val is None:
return 0
stop_val: llvmlite.Value* = llvmlite.build_load(builder, i1_ty, flag_alloca)
@@ -2659,8 +2548,7 @@ class StmtGenCifMixin:
flag_zero2: llvmlite.Value* = llvmlite.ConstInt(pool, i1_ty, 0, "0")
continue_i1: llvmlite.Value* = None
if flag_zero2 is not None:
continue_i1 = llvmlite.build_icmp(
builder, llvmlite.ICMP_EQ, stop_val, flag_zero2)
continue_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_EQ, stop_val, flag_zero2)
if continue_i1 is None:
return 0
llvmlite.build_cond_br(builder, continue_i1, body_bb, end_bb)
@@ -2694,7 +2582,7 @@ class StmtGenCifMixin:
return new_vars
def _handle_enumerate_iter(self, trans: HT.Translator*,
for_node: rawptr[ast.For],
for_node: ast.For*,
t1: str, t2: str,
call: ast.Call*) -> int:
"""enumerate 迭代: for i, v in enumerate(x)"""
@@ -2706,7 +2594,7 @@ class StmtGenCifMixin:
return self._build_seq_loop(trans, for_node, t1, t2, cargs.get(0), None, 1)
def _handle_zip_iter(self, trans: HT.Translator*,
for_node: rawptr[ast.For],
for_node: ast.For*,
t1: str, t2: str,
call: ast.Call*) -> int:
"""zip 迭代: for a, b in zip(x, y)"""
+15 -33
View File
@@ -18,26 +18,19 @@ import lib.core.Gen.GenApi as GenApi
# ============================================================
# StmtGenDeclMixin - StmtGen 拆分 2/3:声明/枚举/nonlocal 访问
#
# 按功能域从 StmtGenMixin.vp 拆出(500~1500 行/文件架构重构,试点):
# translate_global/nonlocal/expr_stmt/pre_scan、break/continue、
# nonlocal 闭包 env 访问、枚举注册表。继承 StmtGenCifMixin。
#
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整)。
# ============================================================
# ============================================================
# 常量(与 HandlesEnum 保持一致,本地副本避免跨模块 CDefine 查找 bug)
# 常量
# ============================================================
ENUM_MAX: t.CDefine = 64
ENUM_MEMBER_MAX: t.CDefine = 128
define ENUM_MAX = 64
define ENUM_MEMBER_MAX = 128
# ============================================================
# StmtGenDeclMixin - 声明/枚举/nonlocal(中层级)
# ============================================================
@t.NoVTable
class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
"""声明/枚举/nonlocal 访问(StmtGen 拆分 2/3,继承 Cif)"""
def translate_global(self, trans: HT.Translator*,
@@ -78,8 +71,7 @@ class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
if nm.id is not None:
# 查找父作用域中的变量 alloca,获取类型信息
var_ty: llvmlite.LLVMType* = None
var_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(
trans.SymTab, nm.id)
var_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
if var_alloca is not None and var_alloca.Ty is not None:
var_ty = var_alloca.Ty.Pointee
# Void 类型视为无效(Pointee 访问异常时可能返回 Void),
@@ -127,11 +119,9 @@ class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
# printf / print 走特殊路径(print 是类型感知格式化,不映射到 printf)
if string.strcmp(func_name, "printf") == 0:
self.Gen.CallGenLeafKit.translate_printf_call(
trans.Pool, trans._cur_builder, trans.Module, cl, trans)
self.Gen.CallGenLeafKit.translate_printf_call(trans.Pool, trans._cur_builder, trans.Module, cl, trans)
elif string.strcmp(func_name, "print") == 0:
self.Gen.CallGenLeafKit.translate_print_call(
trans.Pool, trans._cur_builder, trans.Module, cl, trans)
self.Gen.CallGenLeafKit.translate_print_call(trans.Pool, trans._cur_builder, trans.Module, cl, trans)
else:
# 通用函数调用(返回值丢弃)
# M3:裸名调用**会话函数**(跨片段)时额外把返回值写进 ctx 结果区回显
@@ -147,20 +137,15 @@ class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
sfn_ent: rawptr[GenTypes.ReplFuncEntry] = \
self.Gen.VarGen.repl_find_func_entry(trans.ReplCtx, func_name)
if sfn_ent is not None and sfn_ent.RetTag != GenTypes.REPL_TY_VOID:
sfn_v: llvmlite.Value* = self.Gen.CallGen.translate_call(
trans.Pool, trans._cur_builder, trans.Module, call_node,
sfn_v: llvmlite.Value* = self.Gen.CallGen.translate_call(trans.Pool, trans._cur_builder, trans.Module, call_node,
trans._funcs, trans._func_count, trans)
if sfn_v is not None:
ctx_v: llvmlite.Value* = self.Gen.VarGen.repl_ctx_ptr(
trans, trans.ReplCtx, call_node)
ctx_v: llvmlite.Value* = self.Gen.VarGen.repl_ctx_ptr(trans, trans.ReplCtx, call_node)
if ctx_v is not None:
self.Gen.VarGen.repl_emit_result(
trans, ctx_v, sfn_v, sfn_ent.RetTag, sfn_ent.RetBits,
self.Gen.VarGen.repl_emit_result(trans, ctx_v, sfn_v, sfn_ent.RetTag, sfn_ent.RetBits,
call_node)
return 0
self.Gen.CallGen.translate_call(
trans.Pool, trans._cur_builder, trans.Module, call_node,
trans._funcs, trans._func_count, trans)
self.Gen.CallGen.translate_call(trans.Pool, trans._cur_builder, trans.Module, call_node, trans._funcs, trans._func_count, trans)
return 0
def pre_scan_allocas(self, trans: HT.Translator*,
@@ -192,7 +177,7 @@ class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
self.pre_scan_allocas(trans, ifn.orelse.get(bi_pre_e))
return 0
if k == ast.ASTKind.For:
for_n: rawptr[ast.For] = rawptr[ast.For](node)
for_n: ast.For* = ast.For*(node)
if for_n.children is not None:
bn_pre_f: sizet = len(for_n.children)
for bi_pre_f in range(bn_pre_f):
@@ -340,8 +325,7 @@ class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
def get_env_ptr_var(self, trans: HT.Translator*) -> llvmlite.Value*:
"""获取或创建 _env_ptr 变量(存储闭包 env 指针)"""
env_var: llvmlite.Value* = self.Gen.VarGen.lookup_var(
trans.SymTab, "_env_ptr")
env_var: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, "_env_ptr")
if env_var is not None:
return env_var
# 创建 alloca 存储 env
@@ -519,8 +503,7 @@ class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
# 注意:StdlibAlloc 是 StructGenMixin 字段,本 Mixin 方法体不能直接 self.StdlibAlloc
# (NoVTable 按本 Mixin 字段布局编译),走模块级委托。
if self.Gen.StructGen.get_stdlib_alloc() != 0:
base_ty_copy: llvmlite.LLVMType* = llvmlite.DeepCopyType(
CompilerFactory.factory.PermPool, base_ty)
base_ty_copy: llvmlite.LLVMType* = llvmlite.DeepCopyType(CompilerFactory.factory.PermPool, base_ty)
if base_ty_copy is not None:
entry.BaseTy = base_ty_copy
else:
@@ -544,8 +527,7 @@ class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
# 去重:同名成员已存在则跳过(跨模块同名枚举合并注册 / 同模块
# 重复处理幂等——如 w32.fileio 与 fat32_types 都有 FRESULT)
for ei_d in range(enum_entry.MemberCount):
ex_d: rawptr[GenTypes.EnumMember] = self._get_enum_member(
enum_entry, ei_d)
ex_d: rawptr[GenTypes.EnumMember] = self._get_enum_member(enum_entry, ei_d)
if ex_d is not None and ex_d.Name is not None:
if string.strcmp(ex_d.Name, member_name) == 0:
return ei_d
+42 -94
View File
@@ -19,22 +19,13 @@ import lib.core.Gen.Stmt.StmtGenDeclMixin as StmtGenDeclMixin
# ============================================================
# StmtGenMixin - 语句/流程翻译 Mixin(P6 对象化重构 A 组,拆分后顶层)
#
# 按功能域拆分(500~1500 行/文件架构重构,试点):
# 顶层保留语句分派中枢簇 A(translate_stmt/try/raise/with/delete/
# _eh_ret_default/_with_ctx_call);global/nonlocal/枚举/CIf 已拆至
# StmtGenDeclMixin / StmtGenCifMixin(本类继承链 1/3、2/3)。
# 外部引用(Generator.vp import + HandlesBody 委托)零改动。
#
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整)。
# ============================================================
# ============================================================
# StmtGenMixin - 语句分派中枢(顶层)
# ============================================================
@t.NoVTable
class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
"""语句/流程翻译 Mixin(拆分后顶层,继承 Decl)"""
def translate_stmt(self, trans: HT.Translator*,
@@ -42,8 +33,7 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
"""翻译单条语句,返回新增的变量数(深度守卫包装器,原逻辑见 _translate_stmt_impl)"""
if trans is not None:
if trans.TranslateDepth >= HT.TRANSLATE_MAX_DEPTH:
self.Gen.TypeGenErr.fatal_error(
node, "语句翻译嵌套过深(疑似 AST 自引用环或翻译 bug)", "RecursionError")
self.Gen.TypeGenErr.fatal_error(node, "语句翻译嵌套过深(疑似 AST 自引用环或翻译 bug)", "RecursionError")
trans.TranslateDepth += 1
mret: int = self._translate_stmt_impl(trans, node)
if trans is not None:
@@ -129,28 +119,23 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
if tgt.kind() == ast.ASTKind.Attribute:
del_at: ast.Attribute* = ast.Attribute*(tgt)
if del_at is not None:
self.Gen.CallGenProp._try_property_deleter(
pool, builder, mod, del_at, trans)
self.Gen.CallGenProp._try_property_deleter(pool, builder, mod, del_at, trans)
# del obj[key] → __delitem__(obj, key)(对齐 TPC HandlesDelete.py)。
# 不能静默忽略 Subscript 目标——否则 del 不生效(len 不变)。
elif tgt.kind() == ast.ASTKind.Subscript:
dl_sub: ast.Subscript* = ast.Subscript*(tgt)
if dl_sub is not None and dl_sub.value is not None and dl_sub.slice is not None:
dl_obj: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, dl_sub.value, None, 0, trans)
dl_idx: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, dl_sub.slice, None, 0, trans)
dl_obj: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, dl_sub.value, None, 0, trans)
dl_idx: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, dl_sub.slice, None, 0, trans)
if dl_obj is not None and dl_idx is not None:
dl_st: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(
dl_obj)
dl_st: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(dl_obj)
if dl_st is not None:
dl_cls: str = self.Gen.StructGen.get_class_name_by_type(pool, dl_st)
if dl_cls is not None:
dl_lookup: str = pool.alloc(128)
if dl_lookup is not None:
viperlib.snprintf(dl_lookup, 128, "%s.__delitem__", dl_cls)
dl_fn: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(
mod, dl_lookup)
dl_fn: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, dl_lookup)
if dl_fn is not None:
dl_ret: llvmlite.LLVMType* = llvmlite.function_get_ret_ty(dl_fn)
dl_fn_name: str = llvmlite.function_get_name(dl_fn)
@@ -166,8 +151,7 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
# 参数链表: self → key(独立 null 结尾)
dl_self.Next = dl_idx
dl_idx.Next = None
llvmlite.build_call(
builder, dl_fn_name, dl_self, 2, dl_ret, 0)
llvmlite.build_call(builder, dl_fn_name, dl_self, 2, dl_ret, 0)
return 0
# ============================================================
@@ -290,17 +274,14 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
# 无 except(非法 try,防御):直接吞掉
llvmlite.build_br(builder, unhandled_bb)
else:
eh_code_val: llvmlite.Value* = llvmlite.build_load(
builder, i32_ty_t, exception_code)
eh_code_val: llvmlite.Value* = llvmlite.build_load(builder, i32_ty_t, exception_code)
next_check_t: rawptr[llvmlite.BasicBlock] = None
for i_t in range(n_handlers_t):
hdr_t: ast.ExceptHandler* = ast.ExceptHandler*(
tr.handlers.get(i_t))
hdr_t: ast.ExceptHandler* = ast.ExceptHandler*(tr.handlers.get(i_t))
match_bb_t: rawptr[llvmlite.BasicBlock] = match_bbs.get(i_t)
if i_t > 0 and next_check_t is not None:
llvmlite.position_at_end(builder, next_check_t)
eh_code_val = llvmlite.build_load(
builder, i32_ty_t, exception_code)
eh_code_val = llvmlite.build_load(builder, i32_ty_t, exception_code)
if hdr_t is None or hdr_t.type is None:
# 裸 except:无条件匹配
llvmlite.build_br(builder, match_bb_t)
@@ -320,8 +301,7 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
return 0
n_codes_t: int = 0
if hname_t is not None and self.Gen.ClassGenBase.is_exception_name(hname_t) != 0:
n_codes_t = self.Gen.ClassGenBase.collect_descendant_codes(
hname_t, codes_buf_t, 64)
n_codes_t = self.Gen.ClassGenBase.collect_descendant_codes(hname_t, codes_buf_t, 64)
else:
c0_t: int = 1
if hname_t is not None:
@@ -332,22 +312,18 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
n_codes_t = 1
match_cond_t: llvmlite.Value* = None
for ci_t in range(n_codes_t):
code_val_t: llvmlite.Value* = llvmlite.const_int32(
pool, codes_buf_t[ci_t])
is_match_t: llvmlite.Value* = llvmlite.build_icmp(
builder, llvmlite.ICMP_EQ, eh_code_val, code_val_t)
code_val_t: llvmlite.Value* = llvmlite.const_int32(pool, codes_buf_t[ci_t])
is_match_t: llvmlite.Value* = llvmlite.build_icmp(builder, llvmlite.ICMP_EQ, eh_code_val, code_val_t)
if match_cond_t is None:
match_cond_t = is_match_t
elif is_match_t is not None:
match_cond_t = llvmlite.build_or(
builder, match_cond_t, is_match_t)
match_cond_t = llvmlite.build_or(builder, match_cond_t, is_match_t)
if i_t < n_handlers_t - 1:
viperlib.snprintf(bb_buf_t, 64, "try.check.%d.%d", lc_t, i_t)
next_check_t = llvmlite.create_block(pool, func, bb_buf_t)
else:
next_check_t = unhandled_bb
llvmlite.build_cond_br(
builder, match_cond_t, match_bb_t, next_check_t)
llvmlite.build_cond_br(builder, match_cond_t, match_bb_t, next_check_t)
# MatchBB:绑定 handler 变量(e = 消息指针),跳 ExceptBB
llvmlite.position_at_end(builder, match_bb_t)
if hdr_t is not None and hdr_t.name is not None and hdr_t.name[0] != '\0':
@@ -355,8 +331,7 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
# 重复 define_var 不 shadow——多 try 共用 `as e` 时各 MatchBB
# 各自 store 消息,各 ExceptBB 读同一入口 alloca,避免
# 非支配 alloca 触发 "does not dominate all uses")。
h_ent_t: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, hdr_t.name)
h_ent_t: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, hdr_t.name)
if h_ent_t is not None and h_ent_t.Alloca is not None:
h_alloca_t: llvmlite.Value* = h_ent_t.Alloca
else:
@@ -364,8 +339,7 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
if h_alloca_t is not None:
self.Gen.VarGen.define_var(trans.SymTab, hdr_t.name, h_alloca_t)
if h_alloca_t is not None:
h_msg_t: llvmlite.Value* = llvmlite.build_load(
builder, i8_ptr_ty_t, eh_message)
h_msg_t: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty_t, eh_message)
if h_msg_t is not None:
llvmlite.build_store(builder, h_msg_t, h_alloca_t)
except_bb_t: rawptr[llvmlite.BasicBlock] = except_bbs.get(i_t)
@@ -375,10 +349,8 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
llvmlite.position_at_end(builder, unhandled_bb)
if trans._cur_func_has_eh != 0 and trans._eh_msg_out_param is not None \
and trans._eh_code_out_param is not None:
un_msg_t: llvmlite.Value* = llvmlite.build_load(
builder, i8_ptr_ty_t, eh_message)
un_code_t: llvmlite.Value* = llvmlite.build_load(
builder, i32_ty_t, exception_code)
un_msg_t: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty_t, eh_message)
un_code_t: llvmlite.Value* = llvmlite.build_load(builder, i32_ty_t, exception_code)
if un_msg_t is not None:
llvmlite.build_store(builder, un_msg_t, trans._eh_msg_out_param)
if un_code_t is not None:
@@ -391,8 +363,7 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
# ---- 7. Except 体 ----
for i_t in range(n_handlers_t):
hdr2_t: ast.ExceptHandler* = ast.ExceptHandler*(
tr.handlers.get(i_t))
hdr2_t: ast.ExceptHandler* = ast.ExceptHandler*(tr.handlers.get(i_t))
except_bb2_t: rawptr[llvmlite.BasicBlock] = except_bbs.get(i_t)
llvmlite.position_at_end(builder, except_bb2_t)
if hdr2_t is not None and hdr2_t.children is not None:
@@ -467,11 +438,9 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
if trans._stop_iter_flag_ptr is not None:
i1_ty_r: llvmlite.LLVMType* = llvmlite.Int1(pool)
if i1_ty_r is not None:
one_i1_r: llvmlite.Value* = llvmlite.ConstInt(
pool, i1_ty_r, 1, "1")
one_i1_r: llvmlite.Value* = llvmlite.ConstInt(pool, i1_ty_r, 1, "1")
if one_i1_r is not None:
llvmlite.build_store(
builder, one_i1_r, trans._stop_iter_flag_ptr)
llvmlite.build_store(builder, one_i1_r, trans._stop_iter_flag_ptr)
self._eh_ret_default(trans, pool, builder)
return 0
@@ -497,8 +466,7 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
if exc_code == 0:
exc_code = 1
if ecl2.args is not None and len(ecl2.args) > 0:
exc_msg = self.Gen.ExprGen.translate_value(
builder, pool, mod, ecl2.args.get(0), None, 0, trans)
exc_msg = self.Gen.ExprGen.translate_value(builder, pool, mod, ecl2.args.get(0), None, 0, trans)
# ---- 异常分发 ----
# 1. try 内:写入 try 的 eh_code/eh_message alloca,分支 DispatchBB
@@ -507,8 +475,7 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
if code_val_r is not None:
llvmlite.build_store(builder, code_val_r, trans._eh_code_ptr)
if exc_msg is None:
exc_msg = llvmlite.ConstNull(
pool, llvmlite.Ptr(pool, llvmlite.Int8(pool)), "null")
exc_msg = llvmlite.ConstNull(pool, llvmlite.Ptr(pool, llvmlite.Int8(pool)), "null")
if exc_msg is not None and trans._eh_msg_ptr is not None:
llvmlite.build_store(builder, exc_msg, trans._eh_msg_ptr)
llvmlite.build_br(builder, trans._eh_dispatch_bb)
@@ -520,8 +487,7 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
if code_val_r2 is not None:
llvmlite.build_store(builder, code_val_r2, trans._eh_code_out_param)
if exc_msg is None:
exc_msg = llvmlite.ConstNull(
pool, llvmlite.Ptr(pool, llvmlite.Int8(pool)), "null")
exc_msg = llvmlite.ConstNull(pool, llvmlite.Ptr(pool, llvmlite.Int8(pool)), "null")
if exc_msg is not None:
llvmlite.build_store(builder, exc_msg, trans._eh_msg_out_param)
self._eh_ret_default(trans, pool, builder)
@@ -603,8 +569,7 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
n: sizet = len(items)
# 保存外层 __with_ctx(嵌套 with 时退出后恢复)
old_ctx_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(
trans.SymTab, "__with_ctx")
old_ctx_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, "__with_ctx")
# 记录每个 item 的类名(__exit__ 调用时设置 __with_ctx 类型用)
ctx_class_buf: sizet* = pool.alloc(8 * n)
@@ -623,9 +588,7 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
if item is None or item.context_expr is None:
continue
# 翻译 context_expr(对象构造,如 MemPool(arena, 4096))
ctx_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, item.context_expr,
trans._funcs, trans._func_count, trans)
ctx_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, item.context_expr, trans._funcs, trans._func_count, trans)
if ctx_val is None:
continue
# 提取类名(注解类名,Attribute 时带模块前缀,如 "memhub.MemPool"——
@@ -651,19 +614,16 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
elif cfn.kind() == ast.ASTKind.Name:
cls_name = (ast.Name*(cfn)).id
# context 对象存入 __with_ctx(方法调用解析 self 用)
ctx_alloca: llvmlite.Value* = llvmlite.build_alloca(
builder, ctx_val.Ty)
ctx_alloca: llvmlite.Value* = llvmlite.build_alloca(builder, ctx_val.Ty)
if ctx_alloca is None:
continue
llvmlite.build_store(builder, ctx_val, ctx_alloca)
self.Gen.VarGen.define_var(trans.SymTab, "__with_ctx", ctx_alloca)
if cls_name is not None:
self.Gen.VarGen.set_var_annot_class_name(
trans.SymTab, "__with_ctx", cls_name)
self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, "__with_ctx", cls_name)
ctx_class_buf[i] = sizet(cls_name)
# 调用 __enter__()
enter_val: llvmlite.Value* = self._with_ctx_call(
trans, pool, builder, mod, "__enter__")
enter_val: llvmlite.Value* = self._with_ctx_call(trans, pool, builder, mod, "__enter__")
# asname 绑定(__enter__ 返回值,缺失时退回 context 对象)
if item.optional_vars is not None:
ov: ast.AST* = item.optional_vars
@@ -674,14 +634,12 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
if bind_val is None:
bind_val = ctx_val
if bind_val is not None:
asn_alloca: llvmlite.Value* = llvmlite.build_alloca(
builder, bind_val.Ty)
asn_alloca: llvmlite.Value* = llvmlite.build_alloca(builder, bind_val.Ty)
if asn_alloca is not None:
llvmlite.build_store(builder, bind_val, asn_alloca)
self.Gen.VarGen.define_var(trans.SymTab, asname, asn_alloca)
if cls_name is not None:
self.Gen.VarGen.set_var_annot_class_name(
trans.SymTab, asname, cls_name)
self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, asname, cls_name)
# FakeDuck: __provides__ 元数据 → 生成 _push_provider 调用
# (对齐 TPC HandlesWith.py L138-159;经 gen 单例委托 CallGenMixin。
# 类名去模块前缀后查 __provides__ 表,如 memhub.MemBuddy → MemBuddy)
@@ -691,8 +649,7 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
if fd_dot is not None:
fd_cls_bare = fd_dot + 1
if fd_cls_bare is not None:
self.Gen.CallGenFd._emit_provider_push(
trans, pool, builder, mod, fd_cls_bare, ctx_val)
self.Gen.CallGenFd._emit_provider_push(trans, pool, builder, mod, fd_cls_bare, ctx_val)
# 2. 翻译 body
body: list[ast.AST*]* = wt.children
@@ -714,16 +671,14 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
if fd_dot_p is not None:
fd_cls_bare_p = fd_dot_p + 1
if fd_cls_bare_p is not None:
self.Gen.CallGenFd._emit_provider_pop(
trans, pool, builder, mod, fd_cls_bare_p)
self.Gen.CallGenFd._emit_provider_pop(trans, pool, builder, mod, fd_cls_bare_p)
# 3. 逆序调用 __exit__()(Python with 语义:后进先出)
for i in range(n):
ci: int = n - 1 - i
if ctx_class_buf[ci] != 0:
cls_ci: str = (str | t.CPtr)(ctx_class_buf[ci])
self.Gen.VarGen.set_var_annot_class_name(
trans.SymTab, "__with_ctx", cls_ci)
self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, "__with_ctx", cls_ci)
self._with_ctx_call(trans, pool, builder, mod, "__exit__")
# 4. 恢复外层 __with_ctx
@@ -737,18 +692,11 @@ class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
mod: llvmlite.LLVMModule*,
method_name: str) -> llvmlite.Value*:
"""构造并翻译 __with_ctx.<method_name>() 调用(__enter__/__exit__)"""
if pool is None or method_name is None:
return None
if pool is None or method_name is None: return None
name_node: ast.AST* = ast.Name(pool, "__with_ctx", ast.ASTCtx.Load)
if name_node is None:
return None
attr_node: ast.AST* = ast.Attribute(
pool, name_node, method_name, ast.ASTCtx.Load)
if attr_node is None:
return None
if name_node is None: return None
attr_node: ast.AST* = ast.Attribute(pool, name_node, method_name, ast.ASTCtx.Load)
if attr_node is None: return None
call_node: ast.AST* = ast.Call(pool, attr_node, None, None)
if call_node is None:
return None
return self.Gen.ExprGen.translate_value(
builder, pool, mod, call_node,
trans._funcs, trans._func_count, trans)
if call_node is None: return None
return self.Gen.ExprGen.translate_value(builder, pool, mod, call_node, trans._funcs, trans._func_count, trans)
+9 -19
View File
@@ -578,8 +578,7 @@ novirtual class StructGenMixin:
if default_val.kind() == ast.ASTKind.List: return self._deep_copy_list_ast(pool, default_val)
if default_val.kind() != ast.ASTKind.Constant: return None
src_c: ast.Constant* = ast.Constant*(default_val)
dst_c: ast.Constant* = ast.Constant*(
pool.alloc_tagged(ast.Constant.__sizeof__(), memhub.DETSITE_STRUCTGENMIXIN_641))
dst_c: ast.Constant* = ast.Constant*(pool.alloc_tagged(ast.Constant.__sizeof__(), memhub.DETSITE_STRUCTGENMIXIN_641))
if dst_c is None:
return None
string.memset(dst_c, 0, ast.Constant.__sizeof__())
@@ -639,8 +638,7 @@ novirtual class StructGenMixin:
src_elts_l: list[ast.AST*]* = src_l.elts
if src_elts_l is not None:
cnt_l: sizet = len(src_elts_l)
lst_copy_l: list[ast.AST*]* = (list[ast.AST*] | t.CPtr)(
pool.alloc_tagged(list[ast.AST*].__sizeof__(), memhub.DETSITE_STRUCTGENMIXIN_693))
lst_copy_l: list[ast.AST*]* = (list[ast.AST*] | t.CPtr)(pool.alloc_tagged(list[ast.AST*].__sizeof__(), memhub.DETSITE_STRUCTGENMIXIN_693))
if lst_copy_l is not None:
string.memset(lst_copy_l, 0, list[ast.AST*].__sizeof__())
# 计数**绝不先按源计数写死**:必须在填充循环里按"实际写入槽数"落定
@@ -672,8 +670,7 @@ novirtual class StructGenMixin:
# 源列表自身存在空元素,说明产生源已损坏(计数 > 实际填充)
# ——响亮失败,绝不静默补 0。
if elem_src_l is None:
self.Gen.TypeGenErr.fatal_error(
default_val,
self.Gen.TypeGenErr.fatal_error(default_val,
f"字段默认值深拷贝:列表字面量第 {li_l} 个元素为空 AST 元素(指针为 0)。"
f"上层某处产生了空 AST 元素(元素计数与实际填充不一致),"
f"拒绝静默补 0 生成残缺的默认值;已终止编译。",
@@ -681,8 +678,7 @@ novirtual class StructGenMixin:
return None
elem_dst_l: ast.AST* = self._deep_copy_default_ast(pool, elem_src_l)
if elem_dst_l is None:
self.Gen.TypeGenErr.fatal_error(
elem_src_l,
self.Gen.TypeGenErr.fatal_error(elem_src_l,
f"字段默认值深拷贝:列表字面量第 {li_l} 个元素(kind={elem_src_l.kind()})"
f"既非 Constant 也非 List,无法深拷贝到永久池。若在此静默跳过该槽,"
f"会形成【计数 > 实际填充数】的空槽(后续 elts.get 读到裸 0 崩溃);"
@@ -1175,11 +1171,9 @@ novirtual class StructGenMixin:
self.Gen.ClassGenEnum._is_renum_class_name(rn_cls_q)
rn_alias_q: int = -1
if rn_is_renum_q != 0:
rn_alias_q = self.Gen.ClassGenEnum._lookup_renum_field_alias(
rn_cls_q, field_name)
rn_alias_q = self.Gen.ClassGenEnum._lookup_renum_field_alias(rn_cls_q, field_name)
if rn_alias_q < 1 and bare_q is not rn_cls_q:
rn_alias_q = self.Gen.ClassGenEnum._lookup_renum_field_alias(
bare_q, field_name)
rn_alias_q = self.Gen.ClassGenEnum._lookup_renum_field_alias(bare_q, field_name)
if rn_alias_q >= 1:
rn_fe_q: GenTypes.FieldEntry* = \
self._get_field_entry(mod_entry_q, rn_alias_q)
@@ -1233,13 +1227,11 @@ novirtual class StructGenMixin:
rn_is_renum_l = self.Gen.ClassGenEnum._is_renum_class_name(rn_cls_l)
rn_alias_l: int = -1
if rn_is_renum_l != 0:
rn_alias_l = self.Gen.ClassGenEnum._lookup_renum_field_alias(
rn_cls_l, field_name)
rn_alias_l = self.Gen.ClassGenEnum._lookup_renum_field_alias(rn_cls_l, field_name)
if rn_alias_l < 1 and class_name is not rn_cls_l:
# 双保险:别名表可能仍持有旧 AST 指针(_update_renum_alias_class_ptr
# 未执行/多模块重复注册场景),用调用方 class_name 再试一次
rn_alias_l = self.Gen.ClassGenEnum._lookup_renum_field_alias(
class_name, field_name)
rn_alias_l = self.Gen.ClassGenEnum._lookup_renum_field_alias(class_name, field_name)
if rn_alias_l >= 1:
rn_fe_l: GenTypes.FieldEntry* = \
self.Gen.StructGen._get_field_entry(entry, rn_alias_l)
@@ -1835,9 +1827,7 @@ novirtual class StructGenMixin:
# (G3 LinkedNode.prepend 挂起候选),超限立即报错终止
cnt_ef += 1
if cnt_ef > 100000:
VLogger.error(
"字段链表疑似成环(_ensure_field_types_in_module),强制终止",
"STRUCT")
VLogger.error("字段链表疑似成环(_ensure_field_types_in_module),强制终止", "STRUCT")
stdlib.exit(1)
if fld.Ty is not None:
# 值类型子结构体(如 FILETIME)需要完整定义
+8 -17
View File
@@ -463,8 +463,7 @@ novirtual class Translator:
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
# 声明 printf
printf_func: llvmlite.Function* = llvmlite.create_declare(
pool, mod, "printf", i32_ty)
printf_func: llvmlite.Function* = llvmlite.create_declare(pool, mod, "printf", i32_ty)
if printf_func is None:
VLogger.error("CreateDeclare printf returned NULL", "TR")
return 1
@@ -474,18 +473,15 @@ novirtual class Translator:
# declare void @llvm.va_start(i8*)
# declare void @llvm.va_end(i8*)
void_ty_decl: llvmlite.LLVMType* = llvmlite.Void(pool)
va_start_func: llvmlite.Function* = llvmlite.create_declare(
pool, mod, "llvm.va_start", void_ty_decl)
va_start_func: llvmlite.Function* = llvmlite.create_declare(pool, mod, "llvm.va_start", void_ty_decl)
if va_start_func is not None:
llvmlite.add_param(pool, va_start_func, i8_ptr_ty, "ap")
va_end_func: llvmlite.Function* = llvmlite.create_declare(
pool, mod, "llvm.va_end", void_ty_decl)
va_end_func: llvmlite.Function* = llvmlite.create_declare(pool, mod, "llvm.va_end", void_ty_decl)
if va_end_func is not None:
llvmlite.add_param(pool, va_end_func, i8_ptr_ty, "ap")
# 声明 malloc(闭包分配用)
malloc_func: llvmlite.Function* = llvmlite.create_declare(
pool, mod, "malloc", i8_ptr_ty)
malloc_func: llvmlite.Function* = llvmlite.create_declare(pool, mod, "malloc", i8_ptr_ty)
if malloc_func is not None:
i64_ty: llvmlite.LLVMType* = llvmlite.Int64(pool)
llvmlite.add_param(pool, malloc_func, i64_ty, "size")
@@ -571,9 +567,7 @@ novirtual class Translator:
if self._imported_modules is not None:
# 错误上下文帧:当前模块触发依赖 stub 加载的 import 位置
GenApi.push_trace(GenApi.get_current_file(), cur_imp_lineno)
StubMergerBuild.LoadDepVpiIntoModule(
pool, mod, self._imported_modules, self._from_imports,
GenApi.get_temp_dir(), self)
StubMergerBuild.LoadDepVpiIntoModule(pool, mod, self._imported_modules, self._from_imports, GenApi.get_temp_dir(), self)
GenApi.pop_trace()
# 预注册模块级变量(AnnAssign/Assign)到 SymTab
# 解决时序问题:class Logger 的 __init__ 引用 _mbuddy 时,
@@ -629,15 +623,13 @@ novirtual class Translator:
# (Phase1 1b / Phase2 pre-inc / PhaseA)——否则 _list/_dict 显式
# import memhub 且 memhub 用容器泛型时成 2-环,Phase A 永不收敛。
if self._ContainerInjectionCreatesCycle("_dict") == 0:
self._imported_modules = GenApi.add_imported_module(
pool, self._imported_modules, "_dict")
self._imported_modules = GenApi.add_imported_module(pool, self._imported_modules, "_dict")
if need_list_box[0] != 0:
GenApi.add_visible_struct(pool, "list")
if self._imported_modules is None or \
GenApi.is_module_imported(self._imported_modules, "_list") == 0:
if self._ContainerInjectionCreatesCycle("_list") == 0:
self._imported_modules = GenApi.add_imported_module(
pool, self._imported_modules, "_list")
self._imported_modules = GenApi.add_imported_module(pool, self._imported_modules, "_list")
stdlib.free(need_list_box)
stdlib.free(need_dict_box)
@@ -736,8 +728,7 @@ novirtual class Translator:
if arg_s is not None:
ag_s: ast.Arg* = ast.Arg*(arg_s)
if ag_s.annotation is not None:
self._check_container_type_node(
ag_s.annotation, need_list_box, need_dict_box)
self._check_container_type_node(ag_s.annotation, need_list_box, need_dict_box)
# `[...]`/`{}` 字面量不触发 _list/_dict 导入:字面量广泛用于编译期常量列表
# (c.Asm 的 op/inp/out CLOBBER 参数、数组数据初始化),并非 list 容器使用。
# list/dict 容器的真实使用由类型位置检测覆盖:`x: list` / `list[...]` 注解、
+36 -79
View File
@@ -209,10 +209,7 @@ novirtual class TranslatorGenMixin:
# 元素数超过声明长度 → fail-fast(不按声明长度截断、静默丢弃多余元素)。
if sizet(arr_count) < elts_count:
self.Gen.TypeGenErr.fatal_error(
list_node,
f"数组初始化元素数 {elts_count} 超过数组声明长度 {arr_count},不允许静默截断",
"OverflowError")
self.Gen.TypeGenErr.fatal_error(list_node, f"数组初始化元素数 {elts_count} 超过数组声明长度 {arr_count},不允许静默截断", "OverflowError")
return None
# 非整数元素类型(struct/指针等聚合):不存在 "%s %lld" 文本展开,仅当列表
@@ -252,23 +249,20 @@ novirtual class TranslatorGenMixin:
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*(en_n))
sub_n = self._build_array_initializer_text(pool, elem_ty, ast.List*(en_n))
elif ek_n == ast.ASTKind.Set:
# 花括号行字面量(如点阵字库 {0x00, ...}):Set.elts
# 与 List 同构,包装为临时 List 递归生成子数组文本
se_n: rawptr[ast.Set] = rawptr[ast.Set](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))
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 += sizet(written_n)
written_n = viperlib.snprintf(
buf_n + pos_n, buf_size_n - pos_n, "%s%s", elem_ty_str_n, sub_n)
written_n = viperlib.snprintf(buf_n + pos_n, buf_size_n - pos_n, "%s%s", elem_ty_str_n, sub_n)
pos_n += sizet(written_n)
i_n += 1
viperlib.snprintf(buf_n + pos_n, buf_size_n - pos_n, "]")
@@ -408,8 +402,7 @@ novirtual class TranslatorGenMixin:
viperlib.snprintf(str_name_buf, 64, ".str.%s", var_name)
# 调用 llvmlite.create_global_string 创建字符串常量全局
str_gv: llvmlite.GlobalVariable* = llvmlite.create_global_string(
pool, mod, str_name_buf, str_val)
str_gv: llvmlite.GlobalVariable* = llvmlite.create_global_string(pool, mod, str_name_buf, str_val)
if str_gv is None:
return None
@@ -604,9 +597,7 @@ novirtual class TranslatorGenMixin:
return None
sec_val: str = self.Gen.FuncGenBase._get_attr_call_arg_str(hit)
if sec_val is None or sec_val[0] == 0:
self.Gen.TypeGenErr.fatal_error(
node, f"模块级变量 '{var_name}' 的 t.attr.section(...) 段名缺失或为空",
"ValueError")
self.Gen.TypeGenErr.fatal_error(node, f"模块级变量 '{var_name}' 的 t.attr.section(...) 段名缺失或为空", "ValueError")
return None
return sec_val
def _extract_global_attr_aligned(self, node: ast.AST*,
@@ -621,9 +612,7 @@ novirtual class TranslatorGenMixin:
return 0
al_val: int = self.Gen.ClassGenBase._tattr_aligned_int(hit)
if al_val <= 0:
self.Gen.TypeGenErr.fatal_error(
node, f"模块级变量 '{var_name}' 的 t.attr.aligned(N) 需要正整数字面量 N",
"ValueError")
self.Gen.TypeGenErr.fatal_error(node, f"模块级变量 '{var_name}' 的 t.attr.aligned(N) 需要正整数字面量 N", "ValueError")
return 0
return al_val
def _extract_global_attr_weak(self, node: ast.AST*) -> int:
@@ -656,16 +645,14 @@ novirtual class TranslatorGenMixin:
if nm_cd.id is not None:
if self.Gen.AssignGen.is_cdefine_annotation(aa_cd.annotation) != 0:
# 浮点/整数自动识别注册(浮点 CDefine 如 vipermath U_M_PI)
self.Gen.AssignGen._register_cdefine_from_value(
pool, nm_cd.id, aa_cd.value, aa_cd.annotation)
self.Gen.AssignGen._register_cdefine_from_value(pool, nm_cd.id, aa_cd.value, aa_cd.annotation)
return 0
# CTypedef 注解(如 posix.vp mode_t: t.CTypedef = uint32):
# 不创建全局变量(否则生成 @mode_t 符号 → 链接 duplicate symbol)。
# 预注册阶段按需注册到 CTypedef 表:翻译期表已被 clear_ctypedefs 清空
# (每文件隔离),不注册则函数参数注解查表失败 → NameError。
if self.Gen.TypeGenCType._is_ctypedef_annotation(aa_cd.annotation) != 0:
ctd_str: str = self.Gen.TypeGenResolve._get_type_name_from_annotation(
pool, aa_cd.value)
ctd_str: str = self.Gen.TypeGenResolve._get_type_name_from_annotation(pool, aa_cd.value)
if ctd_str is not None:
self.Gen.TypeGenCType.register_ctypedef(pool, nm_cd.id, ctd_str)
return 0
@@ -712,20 +699,15 @@ novirtual class TranslatorGenMixin:
# (CallGenLeafKit.vp:698-699、:783-788),跨文件查找可见。
# t.CDefine/t.CTypedef 等分支已在 :675-689 提前返回,行为不变。
if annot_node is not None:
ml_callable_ret: llvmlite.LLVMType* = (
self.Gen.TypeGenErr.try_extract_callable_ret(
pool, annot_node, trans._imported_modules,
trans._from_imports, trans))
ml_callable_ret: llvmlite.LLVMType* = self.Gen.TypeGenErr.try_extract_callable_ret(pool, annot_node, trans._imported_modules,trans._from_imports, trans)
if ml_callable_ret is not None:
# 返回值:0=成功/同类型幂等命中;非 0 已在 register_func_ptr_sig
# 内部 fatal_error 终止编译,此处分支仅防御(见 AssignGenMixin 同处)。
if self.Gen.CallGenLeafKit.register_func_ptr_sig(
pool, var_name, ml_callable_ret, aa) != 0:
if self.Gen.CallGenLeafKit.register_func_ptr_sig(pool, var_name, ml_callable_ret, aa) != 0:
return 0
# 解析类型
if aa.annotation is not None:
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, aa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, aa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
if resolved is not None:
# 对象类模块级变量(@t.Object/@t.CVTable:对象即指针)→ Ptr(struct):
# 裸类名注解 resolve 返回 struct 值,模块级变量此处需包装 Ptr;若建成
@@ -757,8 +739,7 @@ novirtual class TranslatorGenMixin:
# [S4 fail-fast] 模块级变量有注解但解析失败 → 不再静默用 i32
# (类型错会使全局存储尺寸/字段访问/ABI 全错);前向引用未注册类
# 应收敛为多遍注册而非回退 i32。
self.Gen.TypeGenErr.fatal_error(
aa.annotation, f"模块级变量 '{var_name}' 类型注解解析失败", "NameError")
self.Gen.TypeGenErr.fatal_error(aa.annotation, f"模块级变量 '{var_name}' 类型注解解析失败", "NameError")
return 0
# 解析初始值(支持整数、负数字面量、列表字面量、字符串字面量)
if aa.value is not None:
@@ -853,20 +834,15 @@ novirtual class TranslatorGenMixin:
case _:
pass
if is_fty_g == 0:
self.Gen.TypeGenErr.fatal_error(
node, f"模块级变量 '{var_name}' 用浮点字面量初始化,但注解不是浮点类型",
self.Gen.TypeGenErr.fatal_error(node, f"模块级变量 '{var_name}' 用浮点字面量初始化,但注解不是浮点类型",
"TypeError")
return 0
if self.Gen.AssignGen._recover_float_literal(
var_name, t.CPtr(c.Addr(init_fval)), 0) != 1:
self.Gen.TypeGenErr.fatal_error(
node, f"模块级浮点变量 '{var_name}' 初始化值源文件恢复失败",
"InternalCompilerError")
if self.Gen.AssignGen._recover_float_literal(var_name, t.CPtr(c.Addr(init_fval)), 0) != 1:
self.Gen.TypeGenErr.fatal_error(node, f"模块级浮点变量 '{var_name}' 初始化值源文件恢复失败", "InternalCompilerError")
return 0
# 检查是否已注册
existing: llvmlite.Value* = self.Gen.VarGen.lookup_module_var(
trans.SymTab, var_name)
existing: llvmlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, var_name)
if existing is not None:
return 0
@@ -884,8 +860,7 @@ novirtual class TranslatorGenMixin:
# 无法在 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)
is_global_cexport = self.Gen.TypeGenErr.has_decorator_marker(annot_node, "CExport", 0)
# 全局变量侧 t.attr.* 属性(`T | t.attr.xxx` 注解联合形态):
# section→gv.Section、aligned→gv.Align、weak→gv.Linkage(见下方应用点)。
# 仅在 AnnAssign(annot_node 非 None)时存在,与 t.CExport 同一条路。
@@ -956,13 +931,11 @@ novirtual class TranslatorGenMixin:
case _:
pass
if is_arr_g != 0:
arr_str_init: str = self._build_string_array_initializer_text(
pool, var_ty, init_str_val)
arr_str_init: str = self._build_string_array_initializer_text(pool, var_ty, init_str_val)
if arr_str_init is not None:
gv.Initializer = arr_str_init
else:
self.Gen.TypeGenErr.fatal_error(
node, f"模块级数组变量 '{var_name}' 字符串初始化器构建失败", "TypeError")
self.Gen.TypeGenErr.fatal_error(node, f"模块级数组变量 '{var_name}' 字符串初始化器构建失败", "TypeError")
else:
# 指针类型(如 b64_tab: t.CArray[char, None] = "ABC..."):
# 创建字符串常量全局 + GEP 引用
@@ -970,8 +943,7 @@ novirtual class TranslatorGenMixin:
if str_init is not None:
gv.Initializer = str_init
else:
self.Gen.TypeGenErr.fatal_error(
node, f"模块级变量 '{var_name}' 初始化器构建失败", "TypeError")
self.Gen.TypeGenErr.fatal_error(node, f"模块级变量 '{var_name}' 初始化器构建失败", "TypeError")
elif init_kind == 4:
# 浮点初始值:LLVM IR 的浮点常量必须写成位模式文本(0x%016llx / 0x%08x)——
# 十进制文本经 llc 解析对部分值有 ±1 ulp 误差(见 llvmlite.ConstFloat 注释)。
@@ -980,8 +952,7 @@ novirtual class TranslatorGenMixin:
if fc_g is not None and fc_g.Name is not None:
gv.Initializer = fc_g.Name
else:
self.Gen.TypeGenErr.fatal_error(
node, f"模块级变量 '{var_name}' 浮点初始化器构建失败", "TypeError")
self.Gen.TypeGenErr.fatal_error(node, f"模块级变量 '{var_name}' 浮点初始化器构建失败", "TypeError")
else:
# 使用 zeroinitializer 而非 "0":指针类型必须用 null/zeroinitializer,
# 整数/聚合类型也兼容 zeroinitializer,避免 "integer constant must have integer type"
@@ -1019,8 +990,7 @@ novirtual class TranslatorGenMixin:
vt_sha1 = resolved_stg_entry.ModuleSha1
if vt_sha1 is None:
vt_sha1 = trans.ModuleSha1
vt_mangled: str = self.Gen.FuncGenBase._mangle_name_with_sha1(
vt_sha1, vt_name_buf)
vt_mangled: str = self.Gen.FuncGenBase._mangle_name_with_sha1(vt_sha1, vt_name_buf)
if vt_mangled is not None:
# 完整 struct 初始化器(LLVM 拒绝部分初始化):
# 字段 0 = __vtable__(i8* @vtable),其余用户字段按类型零值。
@@ -1038,16 +1008,14 @@ novirtual class TranslatorGenMixin:
# 如 `_mbuddy: MemBuddy` 的字段默认不再丢失);
# 全部默认值恰为零时回退逐字段零值,避免无谓文本。
# 两者均列全字段(LLVM 要求初始化器元素数匹配)。
rest_v: str = self._build_stg_struct_body_text(
pool, resolved_stg_entry, 1)
rest_v: str = self._build_stg_struct_body_text(pool, resolved_stg_entry, 1)
if rest_v is not None:
written_v = viperlib.snprintf(init_full + pos_v, init_full_len - pos_v, ", %s", rest_v)
pos_v += sizet(written_v)
else:
fc_v: int = resolved_stg_entry.FieldCount
for fi_v in range(1, fc_v):
fe_v: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(
resolved_stg_entry, fi_v)
fe_v: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(resolved_stg_entry, fi_v)
if fe_v is None or fe_v.Ty is None:
continue
ty_buf_v: str = pool.alloc(128)
@@ -1065,16 +1033,14 @@ novirtual class TranslatorGenMixin:
# 无 vtable 的对象全局(@t.Object / 普通类):按字段默认值生成常量初始化器;
# 一律 zeroinitializer 会丢掉全部字段默认值(模块级 X: T = T() 的构造调用
# 不发射)。无任何非零默认值时返回 None → 保持 zeroinitializer(零开销)。
stg_default_text: str = self._build_stg_struct_init_text(
pool, resolved_stg_entry, 0)
stg_default_text: str = self._build_stg_struct_init_text(pool, resolved_stg_entry, 0)
if stg_default_text is not None:
stg_init_text = stg_default_text
stg_name_len: sizet = sizet(string.strlen(mangled_name)) + 8
stg_name_buf: str = pool.alloc(stg_name_len)
if stg_name_buf is not None:
viperlib.snprintf(stg_name_buf, stg_name_len, "%s.stg", mangled_name)
stg_gv: llvmlite.GlobalVariable* = llvmlite.new_global_variable(
pool, stg_name_buf, resolved_stg_ty)
stg_gv: llvmlite.GlobalVariable* = llvmlite.new_global_variable(pool, stg_name_buf, resolved_stg_ty)
if stg_gv is not None:
llvmlite.module_add_global(mod, stg_gv)
stg_gv.Linkage = None
@@ -1093,8 +1059,7 @@ novirtual class TranslatorGenMixin:
gv.Initializer = stg_init_buf
# 注册 storage 引用(key: var_name.__stg),供 AssignGenMixin
# 全局赋值分支检测对象类全局并复制对象到 storage。
stg_ref: llvmlite.Value* = self.Gen.ExprGenAttr.make_global_ref(
pool, stg_name_buf, resolved_stg_ty)
stg_ref: llvmlite.Value* = self.Gen.ExprGenAttr.make_global_ref(pool, stg_name_buf, resolved_stg_ty)
if stg_ref is not None:
stg_key_len: sizet = sizet(string.strlen(var_name)) + 8
stg_key: str = pool.alloc(stg_key_len)
@@ -1122,8 +1087,7 @@ novirtual class TranslatorGenMixin:
# const 对象全局:注解含 t.CConst 且类型非指针 ⇒ 登记 IsConst,
# 之后对该全局名的赋值/增量赋值/元素赋值 fail-fast(判据同 TPC
# 的 Gen.global_const_flags,见 Debugger/type-descriptors.md)。
if self.Gen.TypeGenErr.is_const_object_marker(
annot_node, var_ty) != 0:
if self.Gen.TypeGenErr.is_const_object_marker(annot_node, var_ty) != 0:
self.Gen.VarGen.set_var_const(trans.SymTab, var_name)
if self.Gen.TypeGenErr.has_decorator_marker(annot_node, "CVolatile", 0) != 0:
self.Gen.VarGen.set_var_volatile(trans.SymTab, var_name)
@@ -1137,11 +1101,9 @@ novirtual class TranslatorGenMixin:
if k == ast.ASTKind.AnnAssign:
aa_ml: ast.AnnAssign* = ast.AnnAssign*(node)
if aa_ml is not None and aa_ml.annotation is not None:
cls_nm_ml: str = self.Gen.TypeGenResolve.extract_class_name_from_annotation(
aa_ml.annotation, trans._imported_modules, pool, trans._from_imports)
cls_nm_ml: str = self.Gen.TypeGenResolve.extract_class_name_from_annotation(aa_ml.annotation, trans._imported_modules, pool, trans._from_imports)
if cls_nm_ml is not None:
self.Gen.VarGen.set_var_annot_class_name(
trans.SymTab, var_name, cls_nm_ml)
self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, var_name, cls_nm_ml)
# 模块级 str|t.CPtr / bytes|t.CPtr 全局:标记 IsPtrElement
# (i8** 语义,var[i] 按 8 字节指针步长),对齐 TPC 的
# global_var_ptr_element(_argv 等字符串指针数组)。否则
@@ -1149,12 +1111,9 @@ novirtual class TranslatorGenMixin:
if aa_ml.annotation.kind() == ast.ASTKind.BinOp:
bop_ml: ast.BinOp* = ast.BinOp*(aa_ml.annotation)
if bop_ml.op == ast.OpKind.BitOr:
if self.Gen.AssignGen._annotation_contains_name(
aa_ml.annotation, "str") != 0 \
or self.Gen.AssignGen._annotation_contains_name(
aa_ml.annotation, "bytes") != 0:
self.Gen.VarGen.set_var_ptr_element(
trans.SymTab, var_name)
if self.Gen.AssignGen._annotation_contains_name(aa_ml.annotation, "str") != 0 \
or self.Gen.AssignGen._annotation_contains_name(aa_ml.annotation, "bytes") != 0:
self.Gen.VarGen.set_var_ptr_element(trans.SymTab, var_name)
return 1
return 0
@@ -1181,14 +1140,12 @@ novirtual class TranslatorGenMixin:
pool: memhub.MemBuddy* = trans.Pool
mod: llvmlite.LLVMModule* = trans.Module
main_func: llvmlite.Function* = llvmlite.create_function(
pool, mod, "main", i32_ty)
main_func: llvmlite.Function* = llvmlite.create_function(pool, mod, "main", i32_ty)
if main_func is None:
VLogger.error("CreateFunction main returned NULL", "TR")
return 0
entry_blk: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(
pool, main_func, "entry")
entry_blk: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, main_func, "entry")
if entry_blk is None:
VLogger.error("CreateBlock returned NULL", "TR")
return 0
+12 -28
View File
@@ -23,12 +23,8 @@ import lib.core.Gen.Type.TypeSpec as TSpec
# ============================================================
# TypeGenBase - 类型表基础设施:字段 + InitTypeGen + trace/临时目录/generic 上下文
#
# 继承链仅 1 级(TPV self 调用仅支持 1 级父类);跨 Mixin 调用统一走 HandlesType 委托。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class TypeGenBase:
novirtual class TypeGenBase:
"""字段 + InitTypeGen + trace/临时目录/generic 上下文"""
# --- 仿 Python Traceback 调用栈(原 _g_trace_frames/_g_trace_count) ---
@@ -128,8 +124,7 @@ class TypeGenBase:
Specs: TSpec.TypeSpecArena*
def InitTypeGen(self) -> int:
"""初始化类型 Mixin 字段(子类构造时内联调用,规避 NoVTable 继承符号不转发)"""
if self is None:
return 1
if self is None: return 1
self.TraceFrames = None
self.TraceCount = 0
self.GenericTpNames = None
@@ -181,15 +176,12 @@ class TypeGenBase:
# ============================================================
def ensure_spec_arena(self) -> TSpec.TypeSpecArena*:
"""确保 TypeSpec 驻留表已创建,返回 arena;失败返回 None"""
if self.Specs is not None:
return self.Specs
if self.Specs is not None: return self.Specs
size: sizet = TSpec.TypeSpecArena.__sizeof__()
arena: TSpec.TypeSpecArena* = TSpec.TypeSpecArena*(CompilerFactory.factory.PermPool.alloc(size))
if arena is None:
return None
if arena is None: return None
string.memset(arena, 0, size)
if TSpec.SpecArenaInit(arena, 0) != 0:
return None
if TSpec.SpecArenaInit(arena, 0) != 0: return None
self.Specs = arena
return arena
# ============================================================
@@ -199,30 +191,24 @@ class TypeGenBase:
def _ensure_trace_init(self) -> int:
"""确保调用栈已初始化(懒加载,用 malloc 不依赖 pool)"""
if self.TraceFrames is not None:
return 1
if self.TraceFrames is not None: return 1
entry_size: sizet = GenTypes.TraceFrame.__sizeof__()
self.TraceFrames = CompilerFactory.factory.PermPool.alloc(entry_size * TypeGenMixin.TRACE_MAX)
if self.TraceFrames is None:
return 0
if self.TraceFrames is None: return 0
string.memset(self.TraceFrames, 0, entry_size * TypeGenMixin.TRACE_MAX)
return 1
def _get_trace_frame(self, i: int) -> rawptr[GenTypes.TraceFrame]:
"""获取第 i 个 TraceFrame 槽位"""
if self.TraceFrames is None or i < 0 or i >= TypeGenMixin.TRACE_MAX:
return None
if self.TraceFrames is None or i < 0 or i >= TypeGenMixin.TRACE_MAX: return None
entry_size: sizet = GenTypes.TraceFrame.__sizeof__()
addr: uint64 = uint64(self.TraceFrames) + i * entry_size
return rawptr[GenTypes.TraceFrame](addr)
def push_trace(self, file_name: str, lineno: int, col_start: int = 0, col_end: int = 0) -> None:
"""压入一个翻译上下文帧(进入新的翻译作用域时调用)"""
if self._ensure_trace_init() == 0:
return
if self.TraceCount >= TypeGenMixin.TRACE_MAX:
return
if self._ensure_trace_init() == 0: return
if self.TraceCount >= TypeGenMixin.TRACE_MAX: return
frame: rawptr[GenTypes.TraceFrame] = self._get_trace_frame(self.TraceCount)
if frame is None:
return
if frame is None: return
frame.file_name = file_name
frame.lineno = lineno
frame.col_start = col_start
@@ -230,8 +216,7 @@ class TypeGenBase:
self.TraceCount += 1
def pop_trace(self) -> None:
"""弹出栈顶帧(退出翻译作用域时调用)"""
if self.TraceCount <= 0:
return
if self.TraceCount <= 0: return
self.TraceCount -= 1
frame: rawptr[GenTypes.TraceFrame] = self._get_trace_frame(self.TraceCount)
if frame is not None:
@@ -241,7 +226,6 @@ class TypeGenBase:
frame.col_end = 0
def clear_trace(self) -> None:
"""清空调用栈(每个文件翻译开始前调用)"""
i: int
for i in range(self.TraceCount):
frame: rawptr[GenTypes.TraceFrame] = self._get_trace_frame(i)
if frame is not None:
+12 -23
View File
@@ -22,22 +22,17 @@ import lib.core.Gen.Type.TypeGenBase as TypeGenBase
# 槽存槽下标 + 1(0=空槽)。CDefineNames 只追加不重排 ⇒ 槽下标稳定;
# Built == len(CDefineNames) 才可信。
# ============================================================
CDEFINE_IDX_CAP: t.CDefine = 4096
# 索引哈希常量(32 位 FNV-1a,与 StructGenMixin 范式一致)
CDEF_IDX_FNV_OFFSET: t.CDefine = 2166136261
CDEF_IDX_FNV_PRIME: t.CDefine = 16777619
CDEF_IDX_FNV_MASK: t.CDefine = 4294967295
define CDEFINE_IDX_CAP = 4096
# 索引哈希常量(32 位 FNV-1a)
define CDEF_IDX_FNV_OFFSET = 2166136261
define CDEF_IDX_FNV_PRIME = 16777619
define CDEF_IDX_FNV_MASK = 4294967295
# ============================================================
# TypeGenCDef - TypeGenMixin 拆分(阶段 D):CDefine 编译期常量表(register/lookup/is/set/clear)
#
# 继承 TypeGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesType 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class TypeGenCDef(TypeGenBase.TypeGenBase):
novirtual class TypeGenCDef(TypeGenBase.TypeGenBase):
"""CDefine 编译期常量表(register/lookup/is/set/clear)"""
# ============================================================
@@ -169,8 +164,7 @@ class TypeGenCDef(TypeGenBase.TypeGenBase):
# 建表失败(池不可用/耗尽)⇒ 明确报错并返回,绝不让下面的 append
# 落到 None 或未初始化地址(原实现无检查 ⇒ append 写进 NULL/0xCD 区崩)
if tn is None or tv is None or td is None or tsf is None:
self.Gen.TypeGenErr.fatal_error(
None, "CDefine 表分配失败(表本体池不可用或耗尽)", "MemoryError")
self.Gen.TypeGenErr.fatal_error(None, "CDefine 表分配失败(表本体池不可用或耗尽)", "MemoryError")
return
self.CDefineNames = tn
self.CDefineValues = tv
@@ -181,8 +175,7 @@ class TypeGenCDef(TypeGenBase.TypeGenBase):
# 不写垃圾(append 之前必有非空断言)
if self.CDefineNames is None or self.CDefineValues is None \
or self.CDefineDoubleFlags is None or self.CDefineStrFlags is None:
self.Gen.TypeGenErr.fatal_error(
None, "CDefine 表未就绪(CDefineNames/Values/Flags 为空)", "MemoryError")
self.Gen.TypeGenErr.fatal_error(None, "CDefine 表未就绪(CDefineNames/Values/Flags 为空)", "MemoryError")
return
name_copy: str = pool.alloc(string.strlen(name) + 1)
if name_copy is None:
@@ -223,8 +216,7 @@ class TypeGenCDef(TypeGenBase.TypeGenBase):
td: list[int] | t.CPtr = list[int](tp, 64)
tsf: list[int] | t.CPtr = list[int](tp, 64)
if tn is None or tv is None or td is None or tsf is None:
self.Gen.TypeGenErr.fatal_error(
None, "CDefine 浮点表分配失败(表本体池不可用或耗尽)", "MemoryError")
self.Gen.TypeGenErr.fatal_error(None, "CDefine 浮点表分配失败(表本体池不可用或耗尽)", "MemoryError")
return
self.CDefineNames = tn
self.CDefineValues = tv
@@ -234,8 +226,7 @@ class TypeGenCDef(TypeGenBase.TypeGenBase):
# 表就绪守卫(同 register_cdefine_constant):append 之前必有非空断言
if self.CDefineNames is None or self.CDefineValues is None \
or self.CDefineDoubleFlags is None or self.CDefineStrFlags is None:
self.Gen.TypeGenErr.fatal_error(
None, "CDefine 浮点表未就绪(CDefineNames/Values/Flags 为空)", "MemoryError")
self.Gen.TypeGenErr.fatal_error(None, "CDefine 浮点表未就绪(CDefineNames/Values/Flags 为空)", "MemoryError")
return
name_copy_d: str = pool.alloc(string.strlen(name) + 1)
if name_copy_d is None:
@@ -281,8 +272,7 @@ class TypeGenCDef(TypeGenBase.TypeGenBase):
td: list[int] | t.CPtr = list[int](tp, 64)
tsf: list[int] | t.CPtr = list[int](tp, 64)
if tn is None or tv is None or td is None or tsf is None:
self.Gen.TypeGenErr.fatal_error(
None, "CDefine 字符串表分配失败(表本体池不可用或耗尽)", "MemoryError")
self.Gen.TypeGenErr.fatal_error(None, "CDefine 字符串表分配失败(表本体池不可用或耗尽)", "MemoryError")
return
self.CDefineNames = tn
self.CDefineValues = tv
@@ -292,8 +282,7 @@ class TypeGenCDef(TypeGenBase.TypeGenBase):
# 表就绪守卫(同 register_cdefine_constant):append 之前必有非空断言
if self.CDefineNames is None or self.CDefineValues is None \
or self.CDefineDoubleFlags is None or self.CDefineStrFlags is None:
self.Gen.TypeGenErr.fatal_error(
None, "CDefine 字符串表未就绪(CDefineNames/Values/Flags 为空)", "MemoryError")
self.Gen.TypeGenErr.fatal_error(None, "CDefine 字符串表未就绪(CDefineNames/Values/Flags 为空)", "MemoryError")
return
ncopy_s: str = pool.alloc(string.strlen(name) + 1)
if ncopy_s is None:
+9 -14
View File
@@ -23,18 +23,17 @@ import lib.core.Gen.Type.TypeSpec as TSpec
# 槽存槽下标 + 1(0=空槽)。CTypedefNames 只追加不重排(同名注册原地更新类型串)
# ⇒ 槽下标稳定;Built == len(CTypedefNames) 才可信。
# ============================================================
CTYPEDEF_IDX_CAP: t.CDefine = 4096
define CTYPEDEF_IDX_CAP = 4096
# 索引哈希常量(32 位 FNV-1a,与 StructGenMixin 范式一致)
CTYPEDEF_IDX_FNV_OFFSET: t.CDefine = 2166136261
CTYPEDEF_IDX_FNV_PRIME: t.CDefine = 16777619
CTYPEDEF_IDX_FNV_MASK: t.CDefine = 4294967295
define CTYPEDEF_IDX_FNV_OFFSET = 2166136261
define CTYPEDEF_IDX_FNV_PRIME = 16777619
define CTYPEDEF_IDX_FNV_MASK = 4294967295
def _ctypedef_idx_hash(name: str) -> uint64:
"""CTypedef 名 → 64 位哈希(32 位 FNV-1a,逐字节到 NUL 结束)"""
h: uint64 = uint64(CTYPEDEF_IDX_FNV_OFFSET)
if name is None:
return h
if name is None: return h
i: sizet = 0
while name[i] != '\0':
h = (h ^ uint64(int(name[i]))) * uint64(CTYPEDEF_IDX_FNV_PRIME)
@@ -222,15 +221,13 @@ class TypeGenCType(TypeGenBase.TypeGenBase):
if self.LastBuiltinsTypedefNameBuf is None:
self.LastBuiltinsTypedefNameBuf = stdlib.malloc(need)
else:
self.LastBuiltinsTypedefNameBuf = stdlib.realloc(
self.LastBuiltinsTypedefNameBuf, need)
self.LastBuiltinsTypedefNameBuf = stdlib.realloc(self.LastBuiltinsTypedefNameBuf, need)
buf: str = self.LastBuiltinsTypedefNameBuf
else:
if self.LastBuiltinsTypedefResultBuf is None:
self.LastBuiltinsTypedefResultBuf = stdlib.malloc(need)
else:
self.LastBuiltinsTypedefResultBuf = stdlib.realloc(
self.LastBuiltinsTypedefResultBuf, need)
self.LastBuiltinsTypedefResultBuf = stdlib.realloc(self.LastBuiltinsTypedefResultBuf, need)
buf = self.LastBuiltinsTypedefResultBuf
if buf is None:
return None
@@ -707,8 +704,7 @@ class TypeGenCType(TypeGenBase.TypeGenBase):
# ExprGenMixin 方法,TypeGenMixin 直接调用会生成未定义引用)
if (from_imports is not None or imported_modules is not None) \
and pool is not None:
x_val: int = self.Gen.ExprGenCdef._lookup_cross_module_cdefine(
pool, nm.id, from_imports, imported_modules)
x_val: int = self.Gen.ExprGenCdef._lookup_cross_module_cdefine(pool, nm.id, from_imports, imported_modules)
if self.Gen.TypeGenCDef.is_cdefine_found() != 0:
self.ConstEvalOk = 1
return x_val
@@ -739,8 +735,7 @@ class TypeGenCType(TypeGenBase.TypeGenBase):
for mi in range(mod_len):
fi_buf[2 + mi] = at_mod.id[mi]
fi_buf[2 + mod_len] = '\0'
av: int = self.Gen.ExprGenCdef._lookup_cross_module_cdefine(
pool, at.attr, fi_buf, imported_modules)
av: int = self.Gen.ExprGenCdef._lookup_cross_module_cdefine(pool, at.attr, fi_buf, imported_modules)
if self.Gen.TypeGenCDef.is_cdefine_found() != 0:
self.ConstEvalOk = 1
return av
+6 -15
View File
@@ -22,21 +22,15 @@ import lib.core.Gen.Type.TypeSpec as TSpec
# ============================================================
# TypeGenErr - 错误上报/源行读取/类型推断(fatal_error/infer_* 等)
#
# 继承链仅 1 级(TPV self 调用仅支持 1 级父类);跨 Mixin 调用统一走 HandlesType 委托。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class TypeGenErr(TypeGenBase.TypeGenBase):
novirtual class TypeGenErr(TypeGenBase.TypeGenBase):
"""错误上报/源行读取/类型推断(fatal_error/infer_* 等)"""
def _read_source_line(self, file_path: str, lineno: int) -> str:
"""从源文件读取第 lineno 行内容"""
if file_path is None or lineno <= 0:
return None
if file_path is None or lineno <= 0: return None
f: rawptr[fileio.File] = fileio.File(file_path, fileio.MODE.R)
if f.closed:
return None
if f.closed: return None
# 按文件实际大小分配缓冲区:固定 256KB 会截断大源文件,末尾行号读不到 →
# 误报"文件不存在或行号超出范围"(如 CallGenMixin.vp 555KB/9236 行的第
# 8390 行)。64MB 上限防御异常超大文件整体读取。
@@ -355,10 +349,8 @@ class TypeGenErr(TypeGenBase.TypeGenBase):
elif k == ast.ASTKind.BinOp:
binop: ast.BinOp* = ast.BinOp*(node)
lhs_ty: llvmlite.LLVMType* = self.infer_expr_type(
pool, binop.left, param_types)
rhs_ty: llvmlite.LLVMType* = self.infer_expr_type(
pool, binop.right, param_types)
lhs_ty: llvmlite.LLVMType* = self.infer_expr_type(pool, binop.left, param_types)
rhs_ty: llvmlite.LLVMType* = self.infer_expr_type(pool, binop.right, param_types)
lhs_bits: int = self.get_llvm_type_bits(lhs_ty)
rhs_bits: int = self.get_llvm_type_bits(rhs_ty)
if lhs_bits >= rhs_bits:
@@ -380,8 +372,7 @@ class TypeGenErr(TypeGenBase.TypeGenBase):
if stmt is not None and stmt.kind() == ast.ASTKind.Return:
rt: rawptr[ast.Return] = rawptr[ast.Return](stmt)
if rt.value is not None:
expr_ty: llvmlite.LLVMType* = self.infer_expr_type(
pool, rt.value, param_types)
expr_ty: llvmlite.LLVMType* = self.infer_expr_type(pool, rt.value, param_types)
if expr_ty is not None:
cur_bits: int = self.get_llvm_type_bits(ret_ty)
new_bits: int = self.get_llvm_type_bits(expr_ty)
+3 -4
View File
@@ -26,13 +26,12 @@ import lib.core.Gen.Type.TypeGenBase as TypeGenBase
# ============================================================
# 常量(与 HandlesType 保持一致)
# ============================================================
TRACE_MAX: t.CDefine = 32
MAX_CTYPEDEF_DEPTH: t.CDefine = 10
define TRACE_MAX = 32
define MAX_CTYPEDEF_DEPTH = 10
# ============================================================
# TypeGenMixin - 类型映射/注解解析/编译期常量表/错误上报
# ============================================================
@t.NoVTable
class TypeGenMixin(TypeGenBase.TypeGenBase):
novirtual class TypeGenMixin(TypeGenBase.TypeGenBase):
"""类型映射与解析 Mixin(阶段 D 拆分后顶层,方法全部在子 Mixin)"""
+53 -110
View File
@@ -27,13 +27,8 @@ import w32.fileio as fileio
# ============================================================
# TypeGenResolve - TypeGenMixin 拆分(阶段 D):类型映射/注解解析(map_t_type/resolve_annotation_type 等)
#
# 继承 TypeGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesType 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class TypeGenResolve(TypeGenBase.TypeGenBase):
novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
"""类型映射/注解解析(map_t_type/resolve_annotation_type 等)"""
def _get_type_name_from_annotation(self, pool: memhub.MemBuddy*,
@@ -179,8 +174,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
es3: str = self._subscript_slice_to_str(pool, e3)
if es3 is None:
# 类型名缺失 ⇒ 立即报错(静默丢弃会拼出错误类型串)
self.Gen.TypeGenErr.fatal_error(
e3, "类型注解的元素无法解析为类型名(列表/元组注解)", "NameError")
self.Gen.TypeGenErr.fatal_error(e3, "类型注解的元素无法解析为类型名(列表/元组注解)", "NameError")
return None
cnt3 += 1
total3 += string.strlen(es3)
@@ -468,8 +462,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
mod_buf[mod_len] = '\0'
# 4a. mod 是 import 别名(import X as mod 注册 "mod:X")→ 完整模块名 → SHA1
if from_imports is not None:
orig_mod: str = self.Gen.ImportsGen.lookup_from_import(
from_imports, mod_buf, 0)
orig_mod: str = self.Gen.ImportsGen.lookup_from_import(from_imports, mod_buf, 0)
if orig_mod is not None:
sha1a: str = self.Gen.CallGenBase._lookup_sha1_from_modname_raw(pool, orig_mod)
if sha1a is not None:
@@ -486,8 +479,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
return type_name
# ---- 5. 裸名 "Class":查 from_imports 所属模块 SHA1 ----
if from_imports is not None:
sha1c: str = self.Gen.CallGenBase._lookup_mod_sha1(
pool, from_imports, type_name, 0)
sha1c: str = self.Gen.CallGenBase._lookup_mod_sha1(pool, from_imports, type_name, 0)
if sha1c is not None:
res_c: str = self._concat_sha1_class(pool, sha1c, type_name)
if res_c is not None:
@@ -572,8 +564,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
left_buf[left_len] = '\0'
left_node: ast.AST* = self._parse_type_string(pool, left_buf, ctx)
# 右段前导空格由递归入口跳过
right_node: ast.AST* = self._parse_type_string(
pool, type_str + pipe_idx + 1, ctx)
right_node: ast.AST* = self._parse_type_string(pool, type_str + pipe_idx + 1, ctx)
stdlib.free(left_buf)
if left_node is not None and right_node is not None:
return ast.BinOp(pool, left_node, ast.OpKind.BitOr, right_node)
@@ -726,8 +717,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
inner_rt: ast.AST* = self._parse_type_string(pool, ts_rt, ast.ASTCtx.Load)
if inner_rt is not None:
self.Gen.TypeGenCType.CTypedefResolveDepth += 1
ity_rt: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, inner_rt, imported_modules, from_imports, trans, 1)
ity_rt: llvmlite.LLVMType* = self.resolve_annotation_type(pool, inner_rt, imported_modules, from_imports, trans, 1)
self.Gen.TypeGenCType.CTypedefResolveDepth -= 1
self.Gen.TypeGenCType._ctypedef_pop_visiting()
if ity_rt is not None:
@@ -742,8 +732,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
if btd_node_r is not None:
if self.Gen.TypeGenCType.CTypedefResolveDepth < TypeGenMixin.MAX_CTYPEDEF_DEPTH:
self.Gen.TypeGenCType.CTypedefResolveDepth += 1
btd_ty_r: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, btd_node_r, imported_modules, from_imports, trans, 1)
btd_ty_r: llvmlite.LLVMType* = self.resolve_annotation_type(pool, btd_node_r, imported_modules, from_imports, trans, 1)
self.Gen.TypeGenCType.CTypedefResolveDepth -= 1
if btd_ty_r is not None:
return btd_ty_r
@@ -759,8 +748,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
if lib_node is not None:
if self.Gen.TypeGenCType.CTypedefResolveDepth < TypeGenMixin.MAX_CTYPEDEF_DEPTH:
self.Gen.TypeGenCType.CTypedefResolveDepth += 1
lib_ty: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, lib_node, imported_modules, from_imports, trans, 1)
lib_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, lib_node, imported_modules, from_imports, trans, 1)
self.Gen.TypeGenCType.CTypedefResolveDepth -= 1
if lib_ty is not None:
return lib_ty
@@ -1267,8 +1255,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
string.strncpy(m_tb, m_buf + m_ls + m_vs, m_vlen)
m_tb[m_vlen] = '\0'
# 写入持久缓存(首次遇到的名字为准)
self._register_lib_typedef_cache(
m_real, m_buf + m_ls, m_nl, m_tb)
self._register_lib_typedef_cache(m_real, m_buf + m_ls, m_nl, m_tb)
# 原实现语义:attr 的首次匹配值
if m_res is None and m_nl == attr_len:
m_nm_ok: int = 1
@@ -1581,8 +1568,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
if at.value is not None:
prefix: str = self.annotation_to_str(at.value)
if prefix is not None:
buf: str = stdlib.malloc(
string.strlen(prefix) + string.strlen(at.attr) + 2)
buf: str = stdlib.malloc(string.strlen(prefix) + string.strlen(at.attr) + 2)
if buf is not None:
viperlib.snprintf(buf,
string.strlen(prefix) + string.strlen(at.attr) + 2,
@@ -1608,8 +1594,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
left_s: str = self.annotation_to_str(bo.left)
right_s: str = self.annotation_to_str(bo.right)
if left_s is not None and right_s is not None:
buf3: str = stdlib.malloc(
string.strlen(left_s) + string.strlen(right_s) + 5)
buf3: str = stdlib.malloc(string.strlen(left_s) + string.strlen(right_s) + 5)
if buf3 is not None:
viperlib.snprintf(buf3,
string.strlen(left_s) + string.strlen(right_s) + 5,
@@ -1727,8 +1712,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
if alias_mod2 is not None:
real_mod2 = alias_mod2
# 返回模块限定名 "module.Class"(如 "memhub.MemBuddy")
mod_qual_buf: str = stdlib.malloc(
string.strlen(real_mod2) + string.strlen(at.attr) + 2)
mod_qual_buf: str = stdlib.malloc(string.strlen(real_mod2) + string.strlen(at.attr) + 2)
if mod_qual_buf is not None:
viperlib.snprintf(mod_qual_buf,
string.strlen(real_mod2) + string.strlen(at.attr) + 2,
@@ -1782,15 +1766,13 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
rp_nm: ast.Name* = ast.Name*(sub.value)
if rp_nm.id is not None and string.strcmp(rp_nm.id, "rawptr") == 0:
if sub.slice is not None:
return self.extract_class_name_from_annotation(
sub.slice, imported_modules, pool, from_imports)
return self.extract_class_name_from_annotation(sub.slice, imported_modules, pool, from_imports)
return None
# 递归取 base 时必须把 from_imports 一并下传:否则同一份注解在派发名/查表键/
# 注册键三处算出的 mangled 名不一致(如 list[ast.AST*] 的元素段),
# 出现「alloca 裸 list* / pass1 按 list[ast.ASTptr] / pass2 按 list[ast.ClassDefptr]」
# 的分裂崩溃。其余调用点均已传。
base_name: str = self.extract_class_name_from_annotation(
sub.value, imported_modules, pool, from_imports)
base_name: str = self.extract_class_name_from_annotation(sub.value, imported_modules, pool, from_imports)
if base_name is None:
return None
# pool 不可用时,只返回裸类名(向后兼容)
@@ -1888,8 +1870,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
tup_elt: ast.AST* = tp_elts.get(tui)
if tup_elt is None:
continue
tup_ety: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, tup_elt, imported_modules, from_imports, trans, depth + 1)
tup_ety: llvmlite.LLVMType* = self.resolve_annotation_type(pool, tup_elt, imported_modules, from_imports, trans, depth + 1)
if tup_ety is None:
return None
tup_node: llvmlite.Function* = llvmlite.new_param_node(pool, tup_ety)
@@ -1978,8 +1959,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
if inj_owner is None:
inj_owner = StubMergerStore.LookupGenericOwnerSha1(gen_cls_name)
if inj_owner is not None:
ty_inj: llvmlite.LLVMType* = self._repl_opaque_class_ty(
pool, inj_owner, gen_mangled)
ty_inj: llvmlite.LLVMType* = self._repl_opaque_class_ty(pool, inj_owner, gen_mangled)
if ty_inj is not None:
return ty_inj
# 归属未知(模板/归属均未登记)⇒ 保持原口径返回 None,由上层按
@@ -2007,14 +1987,12 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
if trans is not None:
template_cd_chk: ast.ClassDef* = self.Gen.ClassGenGeneric._find_generic_template(gen_cls_name)
if template_cd_chk is not None:
type_args_chk: list[str]* = self.Gen.CallGenCtor._extract_type_args_from_slice(
pool, sub.slice, from_imports)
type_args_chk: list[str]* = self.Gen.CallGenCtor._extract_type_args_from_slice(pool, sub.slice, from_imports)
if type_args_chk is not None and len(type_args_chk) > 0:
# 错误定位:压入触发特化的调用方帧(注解所在文件+行号)
gen_cur_f2: str = self.Gen.TypeGenResolve.get_current_file()
self.Gen.TypeGenBase.push_trace(gen_cur_f2, sub.lineno)
spec_name_chk: str = self.Gen.ClassGenGeneric._specialize_generic_class(
trans, gen_cls_name, type_args_chk)
spec_name_chk: str = self.Gen.ClassGenGeneric._specialize_generic_class(trans, gen_cls_name, type_args_chk)
self.Gen.TypeGenBase.pop_trace()
if spec_name_chk is not None:
gen_spec_ty = self.Gen.StructGen.get_struct_type(gen_mangled)
@@ -2042,8 +2020,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
# 与实际模板名。仅当基名确为泛型模板时才触发(避免误伤 rawptr/CArray 等 builtin)。
if trans is not None and trans._declare_only == 0 \
and self.Gen.ClassGenGeneric._find_generic_template(gen_cls_name) is not None:
self.Gen.TypeGenErr.fatal_error(
sub,
self.Gen.TypeGenErr.fatal_error(sub,
f"泛型下标 '{gen_mangled}' 未解析出特化结构体(泛型模板='{gen_cls_name}');"
f"该注解将退化为裸基类/i8* → 后续 .get() 按错误元素类型分派并截断指针",
"TypeError")
@@ -2063,8 +2040,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
if trans is not None and trans.ReplCtx is not None:
gowner_sha1: str = StubMergerStore.LookupGenericOwnerSha1(gen_cls_name)
if gowner_sha1 is not None:
ty_repl_g: llvmlite.LLVMType* = self._repl_opaque_class_ty(
pool, gowner_sha1, gen_mangled)
ty_repl_g: llvmlite.LLVMType* = self._repl_opaque_class_ty(pool, gowner_sha1, gen_mangled)
if ty_repl_g is not None:
return ty_repl_g
# 未特化:返回 None(不报错,让后续流程处理)
@@ -2140,8 +2116,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
if string.strcmp(gp_ta, gp_tpn) == 0:
# 泛型类型参数自映射(T→T):编译期报错,不静默退化
# (静默退化会让运行时数据损坏难定位)。
self.Gen.TypeGenErr.fatal_error(
nm, f"泛型类型实参污染:类型参数 '{gp_tpn}' 自映射(实参='{gp_ta}'),无法特化", "TypeError")
self.Gen.TypeGenErr.fatal_error(nm, f"泛型类型实参污染:类型参数 '{gp_tpn}' 自映射(实参='{gp_ta}'),无法特化", "TypeError")
polluted: int = 0
gp_j: sizet
for gp_j in range(gp_n):
@@ -2159,8 +2134,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
# 实参串包含类型参数名(如 "T | t.CPtr"/"list[T]"):
# 解析后仍产出 Name(参数名) → 无条件自递归卡死。编译期
# 报错(此前 return None 静默退化)。
self.Gen.TypeGenErr.fatal_error(
nm, f"泛型类型实参污染:实参 '{gp_ta}' 包含类型参数名,无法特化", "TypeError")
self.Gen.TypeGenErr.fatal_error(nm, f"泛型类型实参污染:实参 '{gp_ta}' 包含类型参数名,无法特化", "TypeError")
# 用具体类型名递归解析(支持 BinOp/Attribute 类型实参)
gp_sub_node: ast.AST* = self._parse_type_string(pool, gp_ta, nm.ctx)
if gp_sub_node is not None:
@@ -2180,8 +2154,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
if sp_sha_buf2 is not None:
string.strncpy(sp_sha_buf2, nm.id, sp_len2 - 1)
sp_sha_buf2[sp_len2 - 1] = '\0'
sp_entry2: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(
nm.id + sp_len2, sp_sha_buf2)
sp_entry2: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(nm.id + sp_len2, sp_sha_buf2)
if sp_entry2 is not None and sp_entry2.Ty is not None:
if sp_entry2.HasNew != 0:
return llvmlite.Ptr(pool, sp_entry2.Ty)
@@ -2276,8 +2249,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
inner_node: ast.AST* = self._parse_type_string(pool, ctypedef_str, nm.ctx)
if inner_node is not None:
self.Gen.TypeGenCType.CTypedefResolveDepth += 1
inner_ty: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, inner_node, imported_modules, from_imports, trans, depth + 1)
inner_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, inner_node, imported_modules, from_imports, trans, depth + 1)
self.Gen.TypeGenCType.CTypedefResolveDepth -= 1
self.Gen.TypeGenCType._ctypedef_pop_visiting()
if inner_ty is not None:
@@ -2311,8 +2283,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
# 用原始名重建节点递归解析(depth 守卫复用 resolve 上限)
orig_node_a: ast.AST* = self._parse_type_string(pool, oa_buf, nm.ctx)
if orig_node_a is not None:
alias_ty: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, orig_node_a, imported_modules, from_imports, trans, depth + 1)
alias_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, orig_node_a, imported_modules, from_imports, trans, depth + 1)
if alias_ty is not None:
return alias_ty
# [builtins 最后匹配] 常规路径全部 miss 后的最终兜底:查
@@ -2322,8 +2293,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
if btd_n is not None:
btd_node_n: ast.AST* = self._parse_type_string(pool, btd_n, nm.ctx)
if btd_node_n is not None:
btd_ty_n: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, btd_node_n, imported_modules, from_imports, trans, depth + 1)
btd_ty_n: llvmlite.LLVMType* = self.resolve_annotation_type(pool, btd_node_n, imported_modules, from_imports, trans, depth + 1)
if btd_ty_n is not None:
return btd_ty_n
# 库 typedef 兜底:stdint / w32.win32base 等库模块的裸 typedef
@@ -2336,8 +2306,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
if lib_ts_n is not None:
lib_node_n: ast.AST* = self._parse_type_string(pool, lib_ts_n, nm.ctx)
if lib_node_n is not None:
lib_ty_n: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, lib_node_n, imported_modules, from_imports, trans, depth + 1)
lib_ty_n: llvmlite.LLVMType* = self.resolve_annotation_type(pool, lib_node_n, imported_modules, from_imports, trans, depth + 1)
if lib_ty_n is not None:
return lib_ty_n
# [REPL 会话] 归属模块已知(from_imports 解析出 sha1;或本模块自身 =
@@ -2359,8 +2328,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
and string.strcmp(trans.ModuleSha1, GenTypes.REPL_SESSION_SHA1) != 0:
own_sha_rn = trans.ModuleSha1
if own_sha_rn is not None:
ty_repl_n: llvmlite.LLVMType* = self._repl_opaque_class_ty(
pool, own_sha_rn, nm.id)
ty_repl_n: llvmlite.LLVMType* = self._repl_opaque_class_ty(pool, own_sha_rn, nm.id)
if ty_repl_n is not None:
return ty_repl_n
return None
@@ -2418,8 +2386,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
inner_attr: ast.AST* = self._parse_type_string(pool, ctypedef_attr, ast.ASTCtx.Load)
if inner_attr is not None:
self.Gen.TypeGenCType.CTypedefResolveDepth += 1
inner_ty_attr: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, inner_attr, imported_modules, from_imports, trans, depth + 1)
inner_ty_attr: llvmlite.LLVMType* = self.resolve_annotation_type(pool, inner_attr, imported_modules, from_imports, trans, depth + 1)
self.Gen.TypeGenCType.CTypedefResolveDepth -= 1
self.Gen.TypeGenCType._ctypedef_pop_visiting()
if inner_ty_attr is not None:
@@ -2453,8 +2420,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
if is_builtin_attr == 0:
# 模块名 → sha1(精确/后缀/import 别名还原,统一经
# StructGenMixin._resolve_module_sha1 逐级尝试)
mod_sha1_v: str = self.Gen.StructGen._resolve_module_sha1(
val_name.id, from_imports)
mod_sha1_v: str = self.Gen.StructGen._resolve_module_sha1(val_name.id, from_imports)
mod_sha1_rv = mod_sha1_v
if mod_sha1_v is not None:
full_q_v: str = self._concat_sha1_class(pool, mod_sha1_v, at.attr)
@@ -2486,12 +2452,10 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
mod_td_str: str = self.Gen.TypeGenCType.lookup_ctypedef(at.attr)
if mod_td_str is not None and self.Gen.TypeGenCType.CTypedefFound != 0:
if self.Gen.TypeGenCType._ctypedef_push_visiting(pool, at.attr) == 0:
mod_td_inner: ast.AST* = self._parse_type_string(
pool, mod_td_str, at.ctx)
mod_td_inner: ast.AST* = self._parse_type_string(pool, mod_td_str, at.ctx)
if mod_td_inner is not None:
self.Gen.TypeGenCType.CTypedefResolveDepth += 1
mod_td_ty: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, mod_td_inner, imported_modules, from_imports, trans, depth + 1)
mod_td_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, mod_td_inner, imported_modules, from_imports, trans, depth + 1)
self.Gen.TypeGenCType.CTypedefResolveDepth -= 1
self.Gen.TypeGenCType._ctypedef_pop_visiting()
if mod_td_ty is not None:
@@ -2503,8 +2467,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
# 不可解析被跳过)⇒ 用 opaque 具名类型占位(不写 StructTable ⇒
# 字段访问仍按"类未注册"明确报错)。批处理 trans.ReplCtx 恒 None。
if trans is not None and trans.ReplCtx is not None and mod_sha1_rv is not None:
ty_repl_a: llvmlite.LLVMType* = self._repl_opaque_class_ty(
pool, mod_sha1_rv, at.attr)
ty_repl_a: llvmlite.LLVMType* = self._repl_opaque_class_ty(pool, mod_sha1_rv, at.attr)
if ty_repl_a is not None:
return ty_repl_a
return None
@@ -2525,12 +2488,10 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
nested_td_str: str = self.Gen.TypeGenCType.lookup_ctypedef(at.attr)
if nested_td_str is not None and self.Gen.TypeGenCType.CTypedefFound != 0:
if self.Gen.TypeGenCType._ctypedef_push_visiting(pool, at.attr) == 0:
nested_inner: ast.AST* = self._parse_type_string(
pool, nested_td_str, at.ctx)
nested_inner: ast.AST* = self._parse_type_string(pool, nested_td_str, at.ctx)
if nested_inner is not None:
self.Gen.TypeGenCType.CTypedefResolveDepth += 1
nested_ty: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, nested_inner, imported_modules, from_imports, trans, depth + 1)
nested_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, nested_inner, imported_modules, from_imports, trans, depth + 1)
self.Gen.TypeGenCType.CTypedefResolveDepth -= 1
self.Gen.TypeGenCType._ctypedef_pop_visiting()
if nested_ty is not None:
@@ -2551,8 +2512,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
if lib_td_na is not None:
td_node_na: ast.AST* = self._parse_type_string(pool, lib_td_na, at.ctx)
if td_node_na is not None:
td_ty_na: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, td_node_na, imported_modules, from_imports, trans, depth + 1)
td_ty_na: llvmlite.LLVMType* = self.resolve_annotation_type(pool, td_node_na, imported_modules, from_imports, trans, depth + 1)
if td_ty_na is not None:
return td_ty_na
return None
@@ -2593,8 +2553,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
other_is_cvoid = 1
if other_is_cvoid != 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
other_ty: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, other_node, imported_modules, from_imports, trans, depth + 1)
other_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, other_node, imported_modules, from_imports, trans, depth + 1)
# 仅裸名(Name)场景验证解析结果必须是已注册 struct:
# 损坏节点可能解析出基础类型垃圾(如 Int8 → Ptr(i8))。
# Attribute 场景(Module.Class / t.XXX)resolve 结果直接可用
@@ -2664,8 +2623,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
case _:
td_res_is_ptr = 0
if td_res_is_ptr == 0:
td_alias_ty: llvmlite.LLVMType* = self.resolve_typedef_or_map(
pool, other_nm_td.id, imported_modules, from_imports, trans)
td_alias_ty: llvmlite.LLVMType* = self.resolve_typedef_or_map(pool, other_nm_td.id, imported_modules, from_imports, trans)
if td_alias_ty is not None:
keep_other_ty = 1
if keep_other_ty == 0:
@@ -2709,10 +2667,8 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
cptr_sub_side = bop.right
cptr_other = bop.left
if cptr_sub_side is not None and cptr_other is not None:
cptr_sub_ty: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, cptr_sub_side, imported_modules, from_imports, trans, depth + 1)
cptr_other_ty: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, cptr_other, imported_modules, from_imports, trans, depth + 1)
cptr_sub_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, cptr_sub_side, imported_modules, from_imports, trans, depth + 1)
cptr_other_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, cptr_other, imported_modules, from_imports, trans, depth + 1)
if cptr_sub_ty is not None and cptr_other_ty is not None:
# 计算 CPtr 侧外层 Ptr 嵌套数(如 t.CPtr[t.CPtr]=i8** → 2 层)
cptr_level: int = 0
@@ -2740,12 +2696,10 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
return res_ty
# 无 CPtr 标记:返回第一个非 None(装饰器标记如 CExport/CExtern 被忽略)
left_ty: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, bop.left, imported_modules, from_imports, trans, depth + 1)
left_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, bop.left, imported_modules, from_imports, trans, depth + 1)
if left_ty is not None:
return left_ty
right_ty: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, bop.right, imported_modules, from_imports, trans, depth + 1)
right_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, bop.right, imported_modules, from_imports, trans, depth + 1)
if right_ty is not None:
return right_ty
return None
@@ -2782,12 +2736,10 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
cnt_arr0: ast.Constant* = ast.Constant*(count_node_arr)
if cnt_arr0.const_kind == ast.CONST_NONE:
self.Gen.TypeGenErr.fatal_type_error(count_node_arr, "内建定长数组构造子 'array' 的长度必须是正整型常量(>0),不允许 None(长度自动推导请改用 t.CArray[E])。正确示例:state: array[uint32, 4]")
elem_ty_arr: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, elem_node_arr, imported_modules, from_imports, trans, depth + 1)
elem_ty_arr: llvmlite.LLVMType* = self.resolve_annotation_type(pool, elem_node_arr, imported_modules, from_imports, trans, depth + 1)
if elem_ty_arr is None:
return None
count_arr: int = self.Gen.TypeGenCType._eval_const_int_expr(
count_node_arr, pool, from_imports, imported_modules)
count_arr: int = self.Gen.TypeGenCType._eval_const_int_expr(count_node_arr, pool, from_imports, imported_modules)
if self.Gen.TypeGenCType.ConstEvalOk == 0:
self.Gen.TypeGenErr.fatal_type_error(count_node_arr, "内建定长数组构造子 'array' 的长度必须是整型常量表达式(字面量 / CDefine 常量名 / 常量算术表达式)。正确示例:state: array[uint8, MAX_LEN]")
if count_arr <= 0:
@@ -2799,8 +2751,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
if string.strcmp(gen_nm.id, "CArray") == 0 or string.strcmp(gen_nm.id, "rawarray") == 0:
# 单参数: CArray[elem_ty] → Ptr(elem_ty)(静态推导长度数组)
if sub.slice.kind() != ast.ASTKind.Tuple:
elem_n: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, sub.slice, imported_modules, from_imports, trans, depth + 1)
elem_n: llvmlite.LLVMType* = self.resolve_annotation_type(pool, sub.slice, imported_modules, from_imports, trans, depth + 1)
if elem_n is None:
return None
return llvmlite.Ptr(pool, elem_n)
@@ -2812,8 +2763,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
count_node_n: ast.AST* = tup_n.elts.get(1)
if elem_node_n is None or count_node_n is None:
return None
elem_ty_n: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, elem_node_n, imported_modules, from_imports, trans, depth + 1)
elem_ty_n: llvmlite.LLVMType* = self.resolve_annotation_type(pool, elem_node_n, imported_modules, from_imports, trans, depth + 1)
if elem_ty_n is None:
return None
# count=None → Ptr(elem)(等价单参)
@@ -2821,8 +2771,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
cnt_n: ast.Constant* = ast.Constant*(count_node_n)
if cnt_n.const_kind == ast.CONST_NONE:
return llvmlite.Ptr(pool, elem_ty_n)
count_n: int = self.Gen.TypeGenCType._eval_const_int_expr(
count_node_n, pool, from_imports, imported_modules)
count_n: int = self.Gen.TypeGenCType._eval_const_int_expr(count_node_n, pool, from_imports, imported_modules)
if self.Gen.TypeGenCType.ConstEvalOk == 0 or count_n <= 0:
return None
return llvmlite.Array(pool, elem_ty_n, count_n)
@@ -2831,14 +2780,12 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
# "函数返回类型解析失败:注解不可解析"。
if string.strcmp(gen_nm.id, "rawptr") == 0:
if sub.slice.kind() != ast.ASTKind.Tuple:
rp_elem: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, sub.slice, imported_modules, from_imports, trans, depth + 1)
rp_elem: llvmlite.LLVMType* = self.resolve_annotation_type(pool, sub.slice, imported_modules, from_imports, trans, depth + 1)
if rp_elem is None:
return None
return llvmlite.Ptr(pool, rp_elem)
return None
gen_ty_nm: llvmlite.LLVMType* = self._resolve_generic_subscript_ty(
pool, sub, gen_nm.id, trans,
gen_ty_nm: llvmlite.LLVMType* = self._resolve_generic_subscript_ty(pool, sub, gen_nm.id, trans,
imported_modules, from_imports, depth + 1)
if gen_ty_nm is not None:
return gen_ty_nm
@@ -2863,8 +2810,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
string.strcat(fb_str, "]")
fb_node: ast.AST* = self._parse_type_string(pool, fb_str, ast.ASTCtx.Load)
if fb_node is not None:
fb_ty: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, fb_node, imported_modules, from_imports, trans, depth + 1)
fb_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, fb_node, imported_modules, from_imports, trans, depth + 1)
if fb_ty is not None:
return fb_ty
return None
@@ -2899,8 +2845,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
if string.strcmp(arr_val_name.id, "t") != 0 and string.strcmp(arr_val_name.id, "c") != 0 \
and self.Gen.ImportsGen.is_module_imported(imported_modules, arr_val_name.id) == 0:
self.Gen.TypeGenErr.fatal_type_error(node, "t.CPtr 模块未导入")
inner_cptr_ty: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, sub.slice, imported_modules, from_imports, trans, depth + 1)
inner_cptr_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, sub.slice, imported_modules, from_imports, trans, depth + 1)
if inner_cptr_ty is None:
# 元素类型依赖未就绪(如 t.CPtr[类] 中类尚未注册):返回 None 交上层多遍
# 收敛,不在此 fatal 中断 Phase 1a 预注册(UINT 等只经 CTypedef 动态表解析,
@@ -2916,8 +2861,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
# 单参数形式: t.CArray[elem_ty] → Ptr(elem_ty)
# 相当于 t.CArray[elem_ty, None],表示静态推导长度数组
if sub.slice.kind() != ast.ASTKind.Tuple:
elem_ty_single: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, sub.slice, imported_modules, from_imports, trans, depth + 1)
elem_ty_single: llvmlite.LLVMType* = self.resolve_annotation_type(pool, sub.slice, imported_modules, from_imports, trans, depth + 1)
if elem_ty_single is None:
# 元素类型依赖未就绪(同 L1807 注释):返回 None 交多遍收敛
return None
@@ -2935,8 +2879,7 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
if elem_node is None or count_node is None:
self.Gen.TypeGenErr.fatal_type_error(node, "t.CArray Tuple 元素为 None")
# 递归解析元素类型
elem_ty: llvmlite.LLVMType* = self.resolve_annotation_type(
pool, elem_node, imported_modules, from_imports, trans, depth + 1)
elem_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, elem_node, imported_modules, from_imports, trans, depth + 1)
if elem_ty is None:
# 元素类型依赖未就绪(如 t.CArray[类, N] 中类尚未注册):返回 None 交上层多遍
# 收敛,不在此 fatal 中断 Phase 1a 预注册(UINT 等只经 CTypedef 动态表解析,
+107 -142
View File
@@ -25,46 +25,28 @@ import lib.core.Gen.GenApi as GenApi
# ============================================================
# Kind - 基础类型种类
# ============================================================
TS_UNKNOWN: t.CDefine = 0
TS_INT: t.CDefine = 1
TS_UINT: t.CDefine = 2
TS_FLOAT: t.CDefine = 3
TS_BOOL: t.CDefine = 4
TS_PTR: t.CDefine = 5
TS_ARRAY: t.CDefine = 6
TS_STRUCT: t.CDefine = 7
TS_VOID: t.CDefine = 8
TS_FUNC: t.CDefine = 9
TS_UNION: t.CDefine = 10
TS_ENUM: t.CDefine = 11
define TS_UNKNOWN = 0
define TS_INT = 1
define TS_UINT = 2
define TS_FLOAT = 3
define TS_BOOL = 4
define TS_PTR = 5
define TS_ARRAY = 6
define TS_STRUCT = 7
define TS_VOID = 8
define TS_FUNC = 9
define TS_UNION = 10
define TS_ENUM = 11
# ============================================================
# IsSigned - 符号性(单一真源,替代 _annot_str_unsigned 的子串扫描)
# ============================================================
TS_SIGN_UNKNOWN: t.CDefine = -1
TS_SIGN_UNSIGNED: t.CDefine = 0
TS_SIGN_SIGNED: t.CDefine = 1
define TS_SIGN_UNKNOWN = -1
define TS_SIGN_UNSIGNED = 0
define TS_SIGN_SIGNED = 1
# 驻留表默认容量与单条类型文本上限(超限 fail-fast,绝不静默丢弃/截断)
# 容量 × 文本上限即驻留表键缓冲的 PermPool 占用(8192 × 256 = 2MB)
# 注:键文本超 SPEC_TEXT_MAX 的长签名/深嵌套类型 ⇒ 不驻留(保留完整实例,
# 仅放弃去重),见 InternSpec —— 截断键会让 strcmp 撞类型、返回错误实例。
SPEC_INTERN_MAX: t.CDefine = 8192
SPEC_TEXT_MAX: t.CDefine = 256
# ============================================================
# 符号性精确名表 - 按「名字切片」判定(**不做子串扫描**)
#
# 必须精确匹配:strstr 子串扫描会误判 `BYTEPTR`(含 `BYTE`)以及任何含 `uint32`
# 子串的名字(含 sha1 前缀名)。
# 覆盖范围:本模块只认 t/c 核心原语名与少数内建名;stdint 别名(DWORD/WORD/size_t/
# uint32_t/…)由调用方沿 CTypedef 链逐层展开后再落到本函数(链展开需 CTypedef 表,
# 不在本模块做,避免反向依赖)。
# 口径:SSizeT 为**有符号**;BOOL 按 stdint.vp 定义是 int(**有符号**);
# 指针名(BYTEPTR/UINTPTR/INTPTR/CHARPTR/…)返回 UNKNOWN——指针的"无符号"语义
# 由 PtrLevel 表达,与整数符号性无关。
# ============================================================
define SPEC_INTERN_MAX = 8192
define SPEC_TEXT_MAX = 256
# ============================================================
@@ -72,18 +54,13 @@ SPEC_TEXT_MAX: t.CDefine = 256
# ============================================================
def _spec_name_eq(text: str, start: sizet, end: sizet, lit: str) -> int:
"""切片名比较:长度相同且逐字符相等返回 1,否则 0"""
if text is None or lit is None:
return 0
if end <= start:
return 0
if text is None or lit is None: return 0
if end <= start: return 0
ln: sizet = string.strlen(lit)
if end - start != ln:
return 0
k: sizet = 0
while k < ln:
if end - start != ln: return 0
for k in range(ln):
if text[start + k] != lit[k]:
return 0
k += 1
return 1
@@ -102,11 +79,9 @@ def _spec_name_eq(text: str, start: sizet, end: sizet, lit: str) -> int:
# ============================================================
def SpecTypeNameBaseIs(name: str, base: str) -> int:
"""类型名的容器基名是否精确等于 base(1=是 / 0=否)"""
if name is None or base is None:
return 0
if name is None or base is None: return 0
n: sizet = string.strlen(name)
if n == 0:
return 0
if n == 0: return 0
# 基名上界:第一个 '['(泛型实参起点;无 '[' 则到串尾)
end: sizet = n
lb: str = string.strchr(name, '[')
@@ -215,7 +190,7 @@ class TypeSpec:
Bits: int # 位宽;非整型/浮点为 0
IsSigned: int # TS_SIGN_* (-1 未知 / 0 无符号 / 1 有符号)
PtrLevel: int # 指针层级(0=非指针)
Elem: TypeSpec | t.CPtr # Ptr/Array 的指向或元素(None=无)
Elem: TypeSpec* # Ptr/Array 的指向或元素(None=无)
ArrayCount: int # Array 的元素个数(0=未知/动态)
BaseName: str # 结构体/枚举/类名(带模块 sha1;PermPool 深拷贝)
# SourceName: 注解侧「来源名」(替代 AnnotClassName)。
@@ -229,7 +204,7 @@ class TypeSpec:
# 入键会让 InternSpec 条目暴增且线性查找变慢;驻留本意只是跨 reset 存活,
# 而 PermPool 分配天然满足 ⇒ SpecWithSource 返回独立副本、不进表。
SourceName: str
Ret: TypeSpec | t.CPtr # Func:返回类型
Ret: TypeSpec* # Func:返回类型
Params: sizet* # Func:参数数组(连续 TypeSpec* 指针,ParamCount 个)
ParamCount: int # Func:参数个数
IsVarArg: int # Func:1=变参(...)
@@ -382,11 +357,11 @@ def SpecArenaInit(arena: TypeSpecArena | t.CPtr, cap: int) -> int:
# ============================================================
# _spec_alloc - 从 PermPool 分配一个清零的 TypeSpec(不驻留,内部用)
# ============================================================
def _spec_alloc() -> TypeSpec | t.CPtr:
def _spec_alloc() -> TypeSpec*:
"""分配并清零一个 TypeSpec(PermPool)"""
pp: memhub.MemBuddy* = CompilerFactory.factory.PermPool
size: sizet = TypeSpec.__sizeof__()
sp: TypeSpec | t.CPtr = (TypeSpec | t.CPtr)(pp.alloc(size))
sp: TypeSpec* = (TypeSpec*)(pp.alloc(size))
if sp is None:
return None
string.memset(sp, 0, size)
@@ -402,9 +377,9 @@ def _spec_alloc() -> TypeSpec | t.CPtr:
# ============================================================
# _spec_make - 构造一个基础 TypeSpec(不驻留)
# ============================================================
def _spec_make(kind: int, bits: int, is_signed: int) -> TypeSpec | t.CPtr:
def _spec_make(kind: int, bits: int, is_signed: int) -> TypeSpec*:
"""构造基础 TypeSpec(PermPool,不驻留)"""
sp: TypeSpec | t.CPtr = _spec_alloc()
sp: TypeSpec* = _spec_alloc()
if sp is None:
return None
sp.Kind = kind
@@ -416,7 +391,7 @@ def _spec_make(kind: int, bits: int, is_signed: int) -> TypeSpec | t.CPtr:
# ============================================================
# _spec_set_struct_name - 深拷贝类名到 PermPool(跨文件存活)
# ============================================================
def _spec_set_struct_name(sp: TypeSpec | t.CPtr, name: str) -> int:
def _spec_set_struct_name(sp: TypeSpec*, name: str) -> int:
"""把类名深拷贝到 PermPool 并写入 BaseName,返回 0=成功 / 1=失败"""
if sp is None or name is None:
return 1
@@ -435,9 +410,9 @@ def _spec_set_struct_name(sp: TypeSpec | t.CPtr, name: str) -> int:
# NewTypeSpec - 构造基础类型(驻留)
# ============================================================
def NewTypeSpec(arena: TypeSpecArena | t.CPtr, kind: int,
bits: int, is_signed: int) -> TypeSpec | t.CPtr:
bits: int, is_signed: int) -> TypeSpec*:
"""构造基础 TypeSpec 并驻留,失败返回 None"""
sp: TypeSpec | t.CPtr = _spec_make(kind, bits, is_signed)
sp: TypeSpec* = _spec_make(kind, bits, is_signed)
if sp is None:
return None
return InternSpec(arena, sp)
@@ -447,9 +422,9 @@ def NewTypeSpec(arena: TypeSpecArena | t.CPtr, kind: int,
# NewTypeStruct - 构造结构体/枚举/类类型(驻留)
# ============================================================
def NewTypeStruct(arena: TypeSpecArena | t.CPtr, kind: int,
base_name: str) -> TypeSpec | t.CPtr:
base_name: str) -> TypeSpec*:
"""构造 struct/union/enum 类型(BaseName 深拷贝 + 驻留),失败返回 None"""
sp: TypeSpec | t.CPtr = _spec_make(kind, 0, TS_SIGN_UNKNOWN)
sp: TypeSpec* = _spec_make(kind, 0, TS_SIGN_UNKNOWN)
if sp is None:
return None
if _spec_set_struct_name(sp, base_name) != 0:
@@ -461,11 +436,11 @@ def NewTypeStruct(arena: TypeSpecArena | t.CPtr, kind: int,
# NewTypePtr - 构造指针类型(PtrLevel = 元素 PtrLevel + 1,驻留)
# ============================================================
def NewTypePtr(arena: TypeSpecArena | t.CPtr,
elem: TypeSpec | t.CPtr) -> TypeSpec | t.CPtr:
elem: TypeSpec*) -> TypeSpec*:
"""构造指针类型:指向 elem(PtrLevel 逐层递增),失败返回 None"""
if elem is None:
return None
sp: TypeSpec | t.CPtr = _spec_make(TS_PTR, 0, TS_SIGN_UNKNOWN)
sp: TypeSpec* = _spec_make(TS_PTR, 0, TS_SIGN_UNKNOWN)
if sp is None:
return None
sp.Elem = elem
@@ -480,12 +455,12 @@ def NewTypePtr(arena: TypeSpecArena | t.CPtr,
# ============================================================
# NewTypeArray - 构造数组类型(ArrayCount 个 elem,驻留)
# ============================================================
def NewTypeArray(arena: TypeSpecArena | t.CPtr, elem: TypeSpec | t.CPtr,
count: int) -> TypeSpec | t.CPtr:
def NewTypeArray(arena: TypeSpecArena | t.CPtr, elem: TypeSpec*,
count: int) -> TypeSpec*:
"""构造数组类型:elem[count](count<=0 表示长度未知/动态),失败返回 None"""
if elem is None or count < 0:
return None
sp: TypeSpec | t.CPtr = _spec_make(TS_ARRAY, 0, TS_SIGN_UNKNOWN)
sp: TypeSpec* = _spec_make(TS_ARRAY, 0, TS_SIGN_UNKNOWN)
if sp is None:
return None
sp.Elem = elem
@@ -501,15 +476,15 @@ def NewTypeArray(arena: TypeSpecArena | t.CPtr, elem: TypeSpec | t.CPtr,
# NewTypeFunc - 构造函数签名类型(ret + 参数数组 + 变参,驻留)
# params:TypeSpec* 连续数组(由调用方预先构造并保证存活);count 个
# ============================================================
def NewTypeFunc(arena: TypeSpecArena | t.CPtr, ret: TypeSpec | t.CPtr,
def NewTypeFunc(arena: TypeSpecArena | t.CPtr, ret: TypeSpec*,
params: sizet*, count: int,
is_vararg: int) -> TypeSpec | t.CPtr:
is_vararg: int) -> TypeSpec*:
"""构造函数签名类型,失败返回 None"""
if ret is None or count < 0:
return None
if count > 0 and params is None:
return None
sp: TypeSpec | t.CPtr = _spec_make(TS_FUNC, 0, TS_SIGN_UNKNOWN)
sp: TypeSpec* = _spec_make(TS_FUNC, 0, TS_SIGN_UNKNOWN)
if sp is None:
return None
sp.Ret = ret
@@ -523,7 +498,7 @@ def NewTypeFunc(arena: TypeSpecArena | t.CPtr, ret: TypeSpec | t.CPtr,
# SpecBaseText - 基础类型(非 Ptr/Array/Func)的规范文本
# 返回 0=已写入 / 1=不适用/失败
# ============================================================
def SpecBaseText(sp: TypeSpec | t.CPtr, buf: str, buf_size: sizet) -> int:
def SpecBaseText(sp: TypeSpec*, buf: str, buf_size: sizet) -> int:
"""把基础类型写成规范文本;Ptr/Array/Func 不适用时返回 1"""
if sp is None or buf is None or buf_size == 0:
return 1
@@ -572,12 +547,12 @@ def SpecBaseText(sp: TypeSpec | t.CPtr, buf: str, buf_size: sizet) -> int:
# fn(INNER,INNER,...)->RET 函数签名(变参追加 "...")
# 递归深度上限 32(防环);超限或缓冲不足返回 1(fail-fast 由调用方决定)
# ============================================================
def SpecToText(sp: TypeSpec | t.CPtr, buf: str, buf_size: sizet) -> int:
def SpecToText(sp: TypeSpec*, buf: str, buf_size: sizet) -> int:
"""把 TypeSpec 编码为规范文本,返回 0=成功 / 1=失败"""
return _spec_to_text(sp, buf, buf_size, 0)
def _spec_to_text(sp: TypeSpec | t.CPtr, buf: str, buf_size: sizet,
def _spec_to_text(sp: TypeSpec*, buf: str, buf_size: sizet,
depth: int) -> int:
"""SpecToText 的递归实现(depth 上限 32)"""
if sp is None or buf is None or buf_size == 0 or depth > 32:
@@ -627,7 +602,7 @@ def _spec_to_text(sp: TypeSpec | t.CPtr, buf: str, buf_size: sizet,
pos = _spec_text_append(buf, buf_size, pos, ",")
if pos >= buf_size:
return 1
param: TypeSpec | t.CPtr = _spec_param_at(sp, i)
param: TypeSpec* = _spec_param_at(sp, i)
if param is None:
return 1
param_buf: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX)
@@ -686,7 +661,7 @@ def _spec_text_append(buf: str, buf_size: sizet, pos: sizet, text: str) -> sizet
# ============================================================
# _spec_param_at - 取函数签名第 i 个参数 TypeSpec 指针
# ============================================================
def _spec_param_at(sp: TypeSpec | t.CPtr, index: int) -> TypeSpec | t.CPtr:
def _spec_param_at(sp: TypeSpec*, index: int) -> TypeSpec*:
"""返回 Func 类型第 index 个参数的 TypeSpec 指针,越界返回 None"""
if sp is None or sp.Params is None or index < 0 or index >= sp.ParamCount:
return None
@@ -694,30 +669,30 @@ def _spec_param_at(sp: TypeSpec | t.CPtr, index: int) -> TypeSpec | t.CPtr:
slot: sizet* = (sizet*)(addr)
if slot is None:
return None
return (TypeSpec | t.CPtr)(uint64(slot[0]))
return (TypeSpec*)(uint64(slot[0]))
# ============================================================
# TextToSpec - 规范文本解码(SpecToText 的逆;不驻留,由调用方决定是否驻留)
# 解析失败返回 None(fail-fast 由调用方决定)
# ============================================================
def TextToSpec(text: str) -> TypeSpec | t.CPtr:
def TextToSpec(text: str) -> TypeSpec*:
"""把规范文本解码为 TypeSpec(PermPool,不驻留),失败返回 None"""
if text is None:
return None
return _text_to_spec(text, 0)
def _text_to_spec(text: str, depth: int) -> TypeSpec | t.CPtr:
def _text_to_spec(text: str, depth: int) -> TypeSpec*:
"""TextToSpec 的递归实现(depth 上限 32)"""
if text is None or depth > 32:
return None
# 指针:p:INNER
if string.strncmp(text, "p:", 2) == 0:
inner: TypeSpec | t.CPtr = _text_to_spec(text + 2, depth + 1)
inner: TypeSpec* = _text_to_spec(text + 2, depth + 1)
if inner is None:
return None
sp_p: TypeSpec | t.CPtr = _spec_make(TS_PTR, 0, TS_SIGN_UNKNOWN)
sp_p: TypeSpec* = _spec_make(TS_PTR, 0, TS_SIGN_UNKNOWN)
if sp_p is None:
return None
sp_p.Elem = inner
@@ -737,10 +712,10 @@ def _text_to_spec(text: str, depth: int) -> TypeSpec | t.CPtr:
colon: str = string.strchr(rb, ':')
if colon is None:
return None
inner_a: TypeSpec | t.CPtr = _text_to_spec(colon + 1, depth + 1)
inner_a: TypeSpec* = _text_to_spec(colon + 1, depth + 1)
if inner_a is None:
return None
sp_a: TypeSpec | t.CPtr = _spec_make(TS_ARRAY, 0, TS_SIGN_UNKNOWN)
sp_a: TypeSpec* = _spec_make(TS_ARRAY, 0, TS_SIGN_UNKNOWN)
if sp_a is None:
return None
sp_a.Elem = inner_a
@@ -779,11 +754,11 @@ def _text_to_spec(text: str, depth: int) -> TypeSpec | t.CPtr:
# ============================================================
# _spec_make_struct - 构造 struct(深拷贝名字)
# ============================================================
def _spec_make_struct(kind: int, name: str) -> TypeSpec | t.CPtr:
def _spec_make_struct(kind: int, name: str) -> TypeSpec*:
"""构造 struct/union/enum 类型(不驻留),失败返回 None"""
if name is None or name[0] == '\0':
return None
sp: TypeSpec | t.CPtr = _spec_make(kind, 0, TS_SIGN_UNKNOWN)
sp: TypeSpec* = _spec_make(kind, 0, TS_SIGN_UNKNOWN)
if sp is None:
return None
if _spec_set_struct_name(sp, name) != 0:
@@ -794,7 +769,7 @@ def _spec_make_struct(kind: int, name: str) -> TypeSpec | t.CPtr:
# ============================================================
# _text_to_func - 解析 "fn(p1,p2,...)->RET"
# ============================================================
def _text_to_func(text: str, depth: int) -> TypeSpec | t.CPtr:
def _text_to_func(text: str, depth: int) -> TypeSpec*:
"""解析函数签名文本,失败返回 None"""
lp: str = string.strchr(text, '(')
if lp is None:
@@ -839,7 +814,7 @@ def _text_to_func(text: str, depth: int) -> TypeSpec | t.CPtr:
continue
if pcount >= 64:
return None
psp: TypeSpec | t.CPtr = _text_to_spec(seg, depth + 1)
psp: TypeSpec* = _text_to_spec(seg, depth + 1)
if psp is None:
return None
slot_p: sizet* = (sizet*)(uint64(param_specs) + uint64(pcount * 8))
@@ -847,10 +822,10 @@ def _text_to_func(text: str, depth: int) -> TypeSpec | t.CPtr:
return None
slot_p[0] = sizet(psp)
pcount += 1
ret: TypeSpec | t.CPtr = _text_to_spec(arrow + 3, depth + 1)
ret: TypeSpec* = _text_to_spec(arrow + 3, depth + 1)
if ret is None:
return None
sp_f: TypeSpec | t.CPtr = _spec_make(TS_FUNC, 0, TS_SIGN_UNKNOWN)
sp_f: TypeSpec* = _spec_make(TS_FUNC, 0, TS_SIGN_UNKNOWN)
if sp_f is None:
return None
sp_f.Ret = ret
@@ -867,7 +842,7 @@ def _text_to_func(text: str, depth: int) -> TypeSpec | t.CPtr:
# (绝不写入截断键)。
# ============================================================
def InternSpec(arena: TypeSpecArena | t.CPtr,
sp: TypeSpec | t.CPtr) -> TypeSpec | t.CPtr:
sp: TypeSpec*) -> TypeSpec*:
"""按规范文本键驻留 TypeSpec;失败返回 None"""
if arena is None or sp is None:
return sp
@@ -891,7 +866,7 @@ def InternSpec(arena: TypeSpecArena | t.CPtr,
slot_e: sizet* = (sizet*)(uint64(arena.Specs) + uint64(found * 8))
if slot_e is None:
return None
return (TypeSpec | t.CPtr)(uint64(slot_e[0]))
return (TypeSpec*)(uint64(slot_e[0]))
if arena.Index is None:
# 索引不可用:回退原线性查找(规模与类型种数同阶)
i: int = 0
@@ -901,26 +876,21 @@ def InternSpec(arena: TypeSpecArena | t.CPtr,
slot_e2: sizet* = (sizet*)(uint64(arena.Specs) + uint64(i * 8))
if slot_e2 is None:
return None
return (TypeSpec | t.CPtr)(uint64(slot_e2[0]))
return (TypeSpec*)(uint64(slot_e2[0]))
i += 1
# 未命中:追加。**表满 = fail-fast**:不能返回 None——调用链会把 None 一路传到
# entry.Spec,条目静默失去类型信息(如符号性判定恒返回 0 ⇒ zext/sext 方向取错),
# 属静默数据损坏,与「不兜底 / fail-fast」原则直接冲突。
if arena.Count >= arena.Cap:
GenApi.fatal_error(
None,
f"TypeSpec 驻留表已满(上限 {arena.Cap} 条),无法登记新类型",
"InternalCompilerError")
GenApi.fatal_error(None, f"TypeSpec 驻留表已满(上限 {arena.Cap} 条),无法登记新类型", "InternalCompilerError")
# 仅在 fatal_error 无 gen 通道(no-op)时可达:退化为「不驻留但返回完整实例」,
# 守住"不返回 None"这一底线 —— 宁失去同型共享,也不让条目静默丢类型。
return sp
dst_key: str = _spec_key_at(arena.Keys, arena.Count)
if dst_key is None:
return None
if dst_key is None: return None
string.strcpy(dst_key, key_buf)
slot_n: sizet* = (sizet*)(uint64(arena.Specs) + uint64(arena.Count * 8))
if slot_n is None:
return None
if slot_n is None: return None
slot_n[0] = sizet(sp)
# 同步写入哈希索引(下标 = 追加前的 Count)。插入失败仅意味着后续查找对该键
# 回退线性扫描,不影响正确性。
@@ -932,19 +902,16 @@ def InternSpec(arena: TypeSpecArena | t.CPtr,
# ============================================================
# 只读访问器(供 S3 起替换旧的字符串判定)
# ============================================================
def SpecIsPtr(sp: TypeSpec | t.CPtr) -> int:
def SpecIsPtr(sp: TypeSpec*) -> int:
"""是否指针类型(PtrLevel>0)"""
if sp is None:
return 0
if sp.PtrLevel > 0:
return 1
if sp is None: return 0
if sp.PtrLevel > 0: return 1
return 0
def SpecPointedTo(sp: TypeSpec | t.CPtr) -> TypeSpec | t.CPtr:
def SpecPointedTo(sp: TypeSpec*) -> TypeSpec*:
"""指针的指向类型(非指针返回 None)"""
if sp is None or sp.Kind != TS_PTR:
return None
if sp is None or sp.Kind != TS_PTR: return None
return sp.Elem
@@ -955,13 +922,11 @@ def SpecPointedTo(sp: TypeSpec | t.CPtr) -> TypeSpec | t.CPtr:
# 供 SpecWithSign / SpecWithSource / SpecWithElemBits 复用,避免多处重复
# 逐字段拷贝(漏字段是最容易引入的隐蔽 bug:例如忘了 IsElemPtr)。
# ============================================================
def _spec_clone(sp: TypeSpec | t.CPtr) -> TypeSpec | t.CPtr:
def _spec_clone(sp: TypeSpec*) -> TypeSpec*:
"""浅拷贝 sp(含全部字段),分配失败返回 None"""
if sp is None:
return None
cp: TypeSpec | t.CPtr = _spec_alloc()
if cp is None:
return None
if sp is None: return None
cp: TypeSpec* = _spec_alloc()
if cp is None: return None
cp.Kind = sp.Kind
cp.Bits = sp.Bits
cp.IsSigned = sp.IsSigned
@@ -994,8 +959,8 @@ def _spec_clone(sp: TypeSpec | t.CPtr) -> TypeSpec | t.CPtr:
# 仅当符号性实际变化才复制并驻留,否则返回原实例。驻留去重 ⇒ 同「结构+符号」共享一份。
# ============================================================
def SpecWithSign(arena: TypeSpecArena | t.CPtr,
sp: TypeSpec | t.CPtr,
is_signed: int) -> TypeSpec | t.CPtr:
sp: TypeSpec*,
is_signed: int) -> TypeSpec*:
"""复制 sp 并覆盖整数符号性,驻留后返回;无变化返回原实例,失败返回 None"""
if sp is None:
return None
@@ -1009,7 +974,7 @@ def SpecWithSign(arena: TypeSpecArena | t.CPtr,
new_signed = TS_SIGN_SIGNED
if new_kind == sp.Kind:
return sp
cp: TypeSpec | t.CPtr = _spec_clone(sp)
cp: TypeSpec* = _spec_clone(sp)
if cp is None:
return None
cp.Kind = new_kind
@@ -1025,7 +990,7 @@ def SpecWithSign(arena: TypeSpecArena | t.CPtr,
# ============================================================
# _spec_set_source_name - 深拷贝注解来源名到 PermPool 并写入 SourceName
# ============================================================
def _spec_set_source_name(sp: TypeSpec | t.CPtr, name: str) -> int:
def _spec_set_source_name(sp: TypeSpec*, name: str) -> int:
"""把注解来源名深拷贝到 PermPool 并写入 SourceName,返回 0=成功 / 1=失败"""
if sp is None or name is None:
return 1
@@ -1053,13 +1018,13 @@ def _spec_set_source_name(sp: TypeSpec | t.CPtr, name: str) -> int:
#
# 幂等:sp.SourceName 已等于 name 时返回原实例(避免重复副本)。
# ============================================================
def SpecWithSource(sp: TypeSpec | t.CPtr, name: str) -> TypeSpec | t.CPtr:
def SpecWithSource(sp: TypeSpec*, name: str) -> TypeSpec*:
"""复制 sp 并设置 SourceName(独立副本,不驻留);name 为空返回原实例"""
if sp is None or name is None or name[0] == '\0':
return sp
if sp.SourceName is not None and string.strcmp(sp.SourceName, name) == 0:
return sp
cp: TypeSpec | t.CPtr = _spec_clone(sp)
cp: TypeSpec* = _spec_clone(sp)
if cp is None:
return sp
if _spec_set_source_name(cp, name) != 0:
@@ -1078,27 +1043,27 @@ def SpecWithSource(sp: TypeSpec | t.CPtr, name: str) -> TypeSpec | t.CPtr:
# ElemBits 是派生字段(**不在 SpecToText 键内**)⇒ 必须返回独立副本:
# 若走 InternSpec 会命中键相同但 ElemBits 未覆盖的实例,覆盖丢失。
# ============================================================
def SpecWithElemBits(sp: TypeSpec | t.CPtr, elem_bits: int) -> TypeSpec | t.CPtr:
def SpecWithElemBits(sp: TypeSpec*, elem_bits: int) -> TypeSpec*:
"""复制 sp 并设置 ElemBits(独立副本,不驻留);无变化返回原实例"""
if sp is None:
return sp
if sp.ElemBits == elem_bits:
return sp
cp: TypeSpec | t.CPtr = _spec_clone(sp)
cp: TypeSpec* = _spec_clone(sp)
if cp is None:
return sp
cp.ElemBits = elem_bits
return cp
def SpecSourceName(sp: TypeSpec | t.CPtr) -> str:
def SpecSourceName(sp: TypeSpec*) -> str:
"""Spec 的注解来源名(未设置返回 None)"""
if sp is None:
return None
return sp.SourceName
def SpecIsUnsigned(sp: TypeSpec | t.CPtr) -> int:
def SpecIsUnsigned(sp: TypeSpec*) -> int:
"""是否无符号整数(单一真源;未知返回 0)"""
if sp is None:
return 0
@@ -1107,7 +1072,7 @@ def SpecIsUnsigned(sp: TypeSpec | t.CPtr) -> int:
return 0
def SpecBitWidth(sp: TypeSpec | t.CPtr) -> int:
def SpecBitWidth(sp: TypeSpec*) -> int:
"""位宽(非整形/浮点返回 0)"""
if sp is None:
return 0
@@ -1184,7 +1149,7 @@ def SpecTypeBits(ty: llvmlite.LLVMType*) -> int:
SPEC_LLVM_TEXT_MAX_DEPTH: t.CDefine = 100
def SpecToLLVMText(sp: TypeSpec | t.CPtr, buf: str, buf_size: sizet) -> int:
def SpecToLLVMText(sp: TypeSpec*, buf: str, buf_size: sizet) -> int:
"""TypeSpec → LLVM IR 类型文本(对齐 TypePrint),返回 0=成功 / 1=失败"""
if sp is None or buf is None or buf_size == 0:
return 1
@@ -1204,7 +1169,7 @@ def _spec_llvm_append(buf: str, buf_size: sizet, src: str) -> int:
return 0
def _spec_llvm_text(sp: TypeSpec | t.CPtr, buf: str, buf_size: sizet,
def _spec_llvm_text(sp: TypeSpec*, buf: str, buf_size: sizet,
depth: int) -> int:
"""把 sp 的 LLVM 文本**追加**到 buf 末尾(buf 已有前缀时保持原前缀)"""
if sp is None or buf is None:
@@ -1238,7 +1203,7 @@ def _spec_llvm_text(sp: TypeSpec | t.CPtr, buf: str, buf_size: sizet,
return 0
# --- 指针 ---
if sp.Kind == TS_PTR:
inner: TypeSpec | t.CPtr = sp.Elem
inner: TypeSpec* = sp.Elem
if inner is None or inner.Kind == TS_VOID:
viperlib.snprintf(buf + pos, buf_size - pos, "i8*")
return 0
@@ -1277,7 +1242,7 @@ def _spec_llvm_text(sp: TypeSpec | t.CPtr, buf: str, buf_size: sizet,
if i > 0:
if _spec_llvm_append(buf, buf_size, ", ") != 0:
return 1
ps: TypeSpec | t.CPtr = _spec_param_at(sp, i)
ps: TypeSpec* = _spec_param_at(sp, i)
if ps is None:
return 1
if _spec_llvm_text(ps, buf, buf_size, depth + 1) != 0:
@@ -1315,7 +1280,7 @@ def _spec_llvm_text(sp: TypeSpec | t.CPtr, buf: str, buf_size: sizet,
# 本函数当前**无调用点**(S2 只入库;接线在后续步骤)。
# ============================================================
def SpecFromLLVMType(arena: TypeSpecArena | t.CPtr,
ty: llvmlite.LLVMType*) -> TypeSpec | t.CPtr:
ty: llvmlite.LLVMType*) -> TypeSpec*:
"""把已解析的 LLVM 类型翻译成 TypeSpec;不支持或为 None 时返回 None"""
if arena is None or ty is None:
return None
@@ -1341,9 +1306,9 @@ def SpecFromLLVMType(arena: TypeSpecArena | t.CPtr,
def _spec_from_ptr(arena: TypeSpecArena | t.CPtr,
pointee: llvmlite.LLVMType*) -> TypeSpec | t.CPtr:
pointee: llvmlite.LLVMType*) -> TypeSpec*:
"""Ptr(pointee) → TypeSpec(PtrLevel/ElemBits/IsElemPtr 由 NewTypePtr 填)"""
inner: TypeSpec | t.CPtr = SpecFromLLVMType(arena, pointee)
inner: TypeSpec* = SpecFromLLVMType(arena, pointee)
if inner is None:
return None
return NewTypePtr(arena, inner)
@@ -1351,9 +1316,9 @@ def _spec_from_ptr(arena: TypeSpecArena | t.CPtr,
def _spec_from_array(arena: TypeSpecArena | t.CPtr,
elem_ty: llvmlite.LLVMType*,
count: int) -> TypeSpec | t.CPtr:
count: int) -> TypeSpec*:
"""[count x elem] → TypeSpec(ArrayCount/ElemBits/IsElemPtr 由 NewTypeArray 填)"""
inner: TypeSpec | t.CPtr = SpecFromLLVMType(arena, elem_ty)
inner: TypeSpec* = SpecFromLLVMType(arena, elem_ty)
if inner is None:
return None
return NewTypeArray(arena, inner, count)
@@ -1362,9 +1327,9 @@ def _spec_from_array(arena: TypeSpecArena | t.CPtr,
def _spec_from_func(arena: TypeSpecArena | t.CPtr,
ret: llvmlite.LLVMType*,
params: llvmlite.Function*,
pcount: int) -> TypeSpec | t.CPtr:
pcount: int) -> TypeSpec*:
"""函数类型 → TypeSpec(形参沿 ParamNode 链表遍历;IsVarArg 恒 0,见上)"""
ret_s: TypeSpec | t.CPtr = SpecFromLLVMType(arena, ret)
ret_s: TypeSpec* = SpecFromLLVMType(arena, ret)
if ret_s is None:
return None
if pcount <= 0:
@@ -1377,7 +1342,7 @@ def _spec_from_func(arena: TypeSpecArena | t.CPtr,
i: int = 0
while node is not None and i < pcount:
pty: llvmlite.LLVMType* = llvmlite.paramnode_get_ty(node)
ps: TypeSpec | t.CPtr = SpecFromLLVMType(arena, pty)
ps: TypeSpec* = SpecFromLLVMType(arena, pty)
if ps is None:
return None
slot: sizet* = (sizet*)(uint64(params_arr) + uint64(i * 8))
@@ -1390,7 +1355,7 @@ def _spec_from_func(arena: TypeSpecArena | t.CPtr,
def _spec_from_struct(arena: TypeSpecArena | t.CPtr,
sname: str) -> TypeSpec | t.CPtr:
sname: str) -> TypeSpec*:
"""有名结构体 → TS_STRUCT + BaseName;匿名结构体 → 无名 TS_STRUCT"""
if sname is not None:
return NewTypeStruct(arena, TS_STRUCT, sname)
@@ -1413,28 +1378,28 @@ def SpecSelfCheck() -> int:
return 1
# 1) u64
s_u64: TypeSpec | t.CPtr = NewTypeSpec(arena, TS_UINT, 64, TS_SIGN_UNSIGNED)
s_u64: TypeSpec* = NewTypeSpec(arena, TS_UINT, 64, TS_SIGN_UNSIGNED)
if s_u64 is None:
return 1
if _check_roundtrip(s_u64, "u64") != 0:
return 1
# 2) i32
s_i32: TypeSpec | t.CPtr = NewTypeSpec(arena, TS_INT, 32, TS_SIGN_SIGNED)
s_i32: TypeSpec* = NewTypeSpec(arena, TS_INT, 32, TS_SIGN_SIGNED)
if s_i32 is None:
return 2
if _check_roundtrip(s_i32, "i32") != 0:
return 2
# 3) u64*
s_p: TypeSpec | t.CPtr = NewTypePtr(arena, s_u64)
s_p: TypeSpec* = NewTypePtr(arena, s_u64)
if s_p is None:
return 3
if _check_roundtrip(s_p, "p:u64") != 0:
return 3
# 4) i8[4]
s_arr: TypeSpec | t.CPtr = NewTypeArray(arena, s_i32, 4)
s_arr: TypeSpec* = NewTypeArray(arena, s_i32, 4)
if s_arr is None:
return 4
if _check_roundtrip(s_arr, "arr[4]:i32") != 0:
@@ -1452,14 +1417,14 @@ def SpecSelfCheck() -> int:
if slot1 is None:
return 5
slot1[0] = sizet(s_u64)
s_fn: TypeSpec | t.CPtr = NewTypeFunc(arena, s_i32, params, 2, 1)
s_fn: TypeSpec* = NewTypeFunc(arena, s_i32, params, 2, 1)
if s_fn is None:
return 5
if _check_roundtrip(s_fn, "fn(i32,u64,...)->i32") != 0:
return 5
# 6) 驻留去重:同一文本第二次应返回同一实例
s_u64_again: TypeSpec | t.CPtr = NewTypeSpec(arena, TS_UINT, 64, TS_SIGN_UNSIGNED)
s_u64_again: TypeSpec* = NewTypeSpec(arena, TS_UINT, 64, TS_SIGN_UNSIGNED)
if s_u64_again is None:
return 6
if uint64(s_u64_again) != uint64(s_u64):
@@ -1470,7 +1435,7 @@ def SpecSelfCheck() -> int:
# ============================================================
# _check_roundtrip - 自检辅助:编码应等于 expect,且解码再编码应一致
# ============================================================
def _check_roundtrip(sp: TypeSpec | t.CPtr, expect: str) -> int:
def _check_roundtrip(sp: TypeSpec*, expect: str) -> int:
"""编码比对 + 解码往返一致;返回 0=通过 / 1=失败"""
if sp is None or expect is None:
return 1
@@ -1481,7 +1446,7 @@ def _check_roundtrip(sp: TypeSpec | t.CPtr, expect: str) -> int:
return 1
if string.strcmp(buf1, expect) != 0:
return 1
back: TypeSpec | t.CPtr = TextToSpec(buf1)
back: TypeSpec* = TextToSpec(buf1)
if back is None:
return 1
buf2: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX)
+58 -134
View File
@@ -169,9 +169,7 @@ novirtual class VarGenMixin:
# PtrLevel>=1。不满足即上游异常(类型缺失/退化),fail-fast 暴露 ——
# 若静默放过,读点 var_is_ptr_element 返回 0 → 下标按 1 字节误算(数据损坏)。
if entry.Spec is None or entry.Spec.PtrLevel < 1:
self.Gen.TypeGenErr.fatal_error(
None, f"变量 '{name}' 标记为 ptr-element,但其 Spec 不可承载指针语义",
"InternalCompilerError")
self.Gen.TypeGenErr.fatal_error(None, f"变量 '{name}' 标记为 ptr-element,但其 Spec 不可承载指针语义", "InternalCompilerError")
return 1
entry.Spec = TSpec.SpecWithElemBits(entry.Spec, 64)
return 0
@@ -456,8 +454,7 @@ novirtual class VarGenMixin:
return None
scope: rawptr[GenTypes.Scope] = symtab.Current
while scope is not None:
result: llvmlite.Value* = self.find_var(
scope.Vars, scope.VarCount, name)
result: llvmlite.Value* = self.find_var(scope.Vars, scope.VarCount, name)
if result is not None:
return result
scope = scope.Parent
@@ -518,8 +515,7 @@ novirtual class VarGenMixin:
return None
scope: rawptr[GenTypes.Scope] = symtab.Current
while scope is not None:
result: llvmlite.Value* = self.find_var(
scope.Vars, scope.VarCount, name)
result: llvmlite.Value* = self.find_var(scope.Vars, scope.VarCount, name)
if result is not None:
return result
if scope.Kind == SCOPE_MATCH:
@@ -609,10 +605,7 @@ novirtual class VarGenMixin:
symtab: rawptr[GenTypes.SymbolTable] = trans.SymTab
param_alloca: llvmlite.Value* = self.lookup_var(symtab, ctx.CtxParam)
if param_alloca is None or param_alloca.Ty is None or param_alloca.Ty.Pointee == 0:
self.Gen.TypeGenErr.fatal_error(
node,
f"REPL: 片段函数缺少 ctx 形参 '{ctx.CtxParam}'(包裹模板与 M2 调用约定不一致)",
"InternalCompilerError")
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 片段函数缺少 ctx 形参 '{ctx.CtxParam}'(包裹模板与 M2 调用约定不一致)", "InternalCompilerError")
return None
return llvmlite.build_load(trans._cur_builder, param_alloca.Ty.Pointee, param_alloca)
@@ -731,17 +724,10 @@ novirtual class VarGenMixin:
return None
hit[0] = 1
if kw_count != 0:
self.Gen.TypeGenErr.fatal_error(
node,
f"REPL: 会话函数 '{func_name}' 不支持关键字实参(M3 仅支持位置实参)",
"TypeError")
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 不支持关键字实参(M3 仅支持位置实参)", "TypeError")
return None
if can != entry.ParamCount:
self.Gen.TypeGenErr.fatal_error(
node,
f"REPL: 会话函数 '{func_name}' 期待 {entry.ParamCount} 个位置实参,"
f"调用处给了 {can} 个(M3 不支持默认参数/缺省补全)",
"TypeError")
self.Gen.TypeGenErr.fatal_error( node, f"REPL: 会话函数 '{func_name}' 期待 {entry.ParamCount} 个位置实参,调用处给了 {can} 个(M3 不支持默认参数/缺省补全)", "TypeError")
return None
ctx_val: llvmlite.Value* = self.repl_ctx_ptr(trans, ctx, node)
if ctx_val is None:
@@ -749,16 +735,13 @@ novirtual class VarGenMixin:
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
# ① 槽内取函数地址:槽地址是 i8**(Ptr(i8*)),load 得 i8*
slot: llvmlite.Value* = self.repl_slot_ptr(
pool, builder, ctx_val, entry.SlotOff, i8_ptr_ty)
slot: llvmlite.Value* = self.repl_slot_ptr(pool, builder, ctx_val, entry.SlotOff, i8_ptr_ty)
if slot is None:
self.Gen.TypeGenErr.fatal_error(
node, "REPL: 会话函数指针槽地址生成失败", "InternalCompilerError")
self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话函数指针槽地址生成失败", "InternalCompilerError")
return None
fn_i8: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty, slot)
if fn_i8 is None:
self.Gen.TypeGenErr.fatal_error(
node, f"REPL: 会话函数 '{func_name}' 的地址读取失败", "InternalCompilerError")
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的地址读取失败", "InternalCompilerError")
return None
# ② 签名构造前先取形参类型(token → LLVM 类型;不支持 ⇒ 明确报错)
ptypes: t.CPtr = pool.alloc(8 * GenTypes.REPL_FUNC_PARAM_MAX)
@@ -767,14 +750,9 @@ novirtual class VarGenMixin:
string.memset(ptypes, 0, 8 * GenTypes.REPL_FUNC_PARAM_MAX)
ai_chk: int
for ai_chk in range(entry.ParamCount):
pty_chk: llvmlite.LLVMType* = self.repl_func_ty(
pool, int(entry.ParamTags[ai_chk]), int(entry.ParamBits[ai_chk]))
pty_chk: llvmlite.LLVMType* = self.repl_func_ty(pool, int(entry.ParamTags[ai_chk]), int(entry.ParamBits[ai_chk]))
if pty_chk is None:
self.Gen.TypeGenErr.fatal_error(
node,
f"REPL: 会话函数 '{func_name}' 第 {ai_chk + 1} 个形参的类型 token "
f"不受支持(M3 支持 iN/float/double/i8*)",
"TypeError")
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 第 {ai_chk + 1} 个形参的类型 token 不受支持(M3 支持 iN/float/double/i8*)", "TypeError")
return None
pty_slot: str | t.CPtr = (t.CPtr)(uint64(ptypes) + ai_chk * 8)
pty_slot[0] = pty_chk
@@ -787,26 +765,17 @@ novirtual class VarGenMixin:
for ai in range(entry.ParamCount):
arg: ast.AST* = cargs.get(ai)
if arg is None:
self.Gen.TypeGenErr.fatal_error(
node, f"REPL: 会话函数 '{func_name}' 的第 {ai + 1} 个实参缺失",
"SyntaxError")
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的第 {ai + 1} 个实参缺失", "SyntaxError")
return None
pty_slot2: str | t.CPtr = (t.CPtr)(uint64(ptypes) + ai * 8)
pty: llvmlite.LLVMType* = (llvmlite.LLVMType*)(pty_slot2[0])
arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, mod, arg, None, 0, trans, pty)
arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, pty)
if arg_val is None:
self.Gen.TypeGenErr.fatal_error(
node, f"REPL: 会话函数 '{func_name}' 的第 {ai + 1} 个实参翻译失败",
"TypeError")
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的第 {ai + 1} 个实参翻译失败", "TypeError")
return None
coerced: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(
builder, arg_val, pty, arg, trans)
coerced: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, pty, arg, trans)
if coerced is None:
self.Gen.TypeGenErr.fatal_error(
node,
f"REPL: 会话函数 '{func_name}' 的第 {ai + 1} 个实参与签名类型不兼容",
"TypeError")
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的第 {ai + 1} 个实参与签名类型不兼容", "TypeError")
return None
coerced.Next = None
tail.Next = coerced
@@ -818,11 +787,7 @@ novirtual class VarGenMixin:
if entry.RetTag != GenTypes.REPL_TY_VOID:
ret_ty = self.repl_func_ty(pool, entry.RetTag, entry.RetBits)
if ret_ty is None:
self.Gen.TypeGenErr.fatal_error(
node,
f"REPL: 会话函数 '{func_name}' 的返回类型 token 不受支持"
f"(M3 支持 void/iN/float/double/i8*)",
"TypeError")
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的返回类型 token 不受支持(M3 支持 void/iN/float/double/i8*)", "TypeError")
return None
fp_first: llvmlite.Function* = None
fp_prev: llvmlite.Function* = None
@@ -845,8 +810,7 @@ novirtual class VarGenMixin:
func_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, func_ty)
fn_typed: llvmlite.Value* = llvmlite.build_bitcast(builder, fn_i8, func_ptr_ty)
if fn_typed is None:
self.Gen.TypeGenErr.fatal_error(
node, f"REPL: 会话函数 '{func_name}' 的地址转换失败", "InternalCompilerError")
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的地址转换失败", "InternalCompilerError")
return None
return llvmlite.build_call_indirect(builder, fn_typed, head, arg_count, ret_ty)
@@ -874,8 +838,7 @@ novirtual class VarGenMixin:
# 同型时不发 bitcast:llvmlite 类型非 canonical(同类型不同实例地址不同),
# 而 LLVM 拒绝 `bitcast i8* %x to i8*`(同型 cast 非法)——val_ty 为 i8
# (char 会话变量)时目标恰是 i8*,必须直接返回 GEP 结果。
if base.Ty is not None and self.Gen.AssignGen._stg_ty_equal(
pool, base.Ty, target_ptr_ty) != 0:
if base.Ty is not None and self.Gen.AssignGen._stg_ty_equal(pool, base.Ty, target_ptr_ty) != 0:
return base
return llvmlite.build_bitcast(builder, base, target_ptr_ty)
@@ -1076,8 +1039,7 @@ novirtual class VarGenMixin:
return 1
perm: memhub.MemBuddy* = self.repl_perm_pool(trans)
if perm is None:
self.Gen.TypeGenErr.fatal_error(
node, "REPL: 会话永久池不可用(宿主未注入)", "InternalCompilerError")
self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话永久池不可用(宿主未注入)", "InternalCompilerError")
return 1
tag: int = 0
bits: int = 0
@@ -1126,15 +1088,13 @@ novirtual class VarGenMixin:
sz: int = self.repl_type_size(val_ty)
al: int = self.repl_type_align(val_ty)
if sz <= 0 or al <= 0:
self.Gen.TypeGenErr.fatal_error(
node,
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量 '{entry.Name}' 的结构体值 '{sname}' 尺寸/对齐未知"
f"(无法判定能否放入 {GenTypes.REPL_SLOT_SIZE} 字节槽)",
"TypeError")
return 1
if sz > GenTypes.REPL_SLOT_SIZE or al > GenTypes.REPL_SLOT_SIZE:
self.Gen.TypeGenErr.fatal_error(
node,
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量 '{entry.Name}' 的结构体值 '{sname}' 体积 {sz} 字节、"
f"对齐 {al} 字节,无法放入 {GenTypes.REPL_SLOT_SIZE} 字节槽"
f"(M2 结构体值须内联进槽;大对象请改用对象指针/堆分配)",
@@ -1145,8 +1105,7 @@ novirtual class VarGenMixin:
kind = GenTypes.REPL_KIND_SCALAR
tname = sname
else:
self.Gen.TypeGenErr.fatal_error(
node,
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量 '{entry.Name}' 的类型暂不支持"
f"(M2 支持 int/bool/浮点/str/bytes/指针/结构体值)",
"TypeError")
@@ -1160,8 +1119,7 @@ novirtual class VarGenMixin:
entry.TyName = self.repl_perm_strdup(perm, tname)
return 0
if entry.Kind != kind or entry.TyTag != tag:
self.Gen.TypeGenErr.fatal_error(
node,
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量 '{entry.Name}' 已定型为 {self.repl_tag_label(entry.TyTag, entry.Bits)},"
f"不能再赋成 {self.repl_tag_label(tag, bits)}(如需换型请重启会话)",
"TypeError")
@@ -1230,29 +1188,24 @@ novirtual class VarGenMixin:
if hit is not None:
return hit
if ctx.Table is None or ctx.Cap <= 0:
self.Gen.TypeGenErr.fatal_error(
node, "REPL: 会话变量表未初始化(宿主未建 ctx)", "InternalCompilerError")
self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话变量表未初始化(宿主未建 ctx)", "InternalCompilerError")
return None
if ctx.Count >= ctx.Cap:
self.Gen.TypeGenErr.fatal_error(
node,
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量已达上限 {ctx.Cap} 个(ctx 槽位用尽),"
f"无法为 '{name}' 再分配槽位;请重启会话",
"ResourceError")
return None
perm: memhub.MemBuddy* = self.repl_perm_pool(trans)
if perm is None:
self.Gen.TypeGenErr.fatal_error(
node, "REPL: 会话永久池不可用(宿主未注入)", "InternalCompilerError")
self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话永久池不可用(宿主未注入)", "InternalCompilerError")
return None
name_copy: str = self.repl_perm_strdup(perm, name)
if name_copy is None:
self.Gen.TypeGenErr.fatal_error(
node, f"REPL: 会话变量 '{name}' 的名字深拷贝失败", "InternalCompilerError")
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 的名字深拷贝失败", "InternalCompilerError")
return None
entry_size: sizet = GenTypes.ReplVarEntry.__sizeof__()
entry: rawptr[GenTypes.ReplVarEntry] = rawptr[GenTypes.ReplVarEntry](
uint64(ctx.Table) + uint64(ctx.Count) * uint64(entry_size))
entry: rawptr[GenTypes.ReplVarEntry] = rawptr[GenTypes.ReplVarEntry](uint64(ctx.Table) + uint64(ctx.Count) * uint64(entry_size))
if entry is None:
return None
entry.Name = name_copy
@@ -1296,8 +1249,7 @@ novirtual class VarGenMixin:
i64_ty: llvmlite.LLVMType* = llvmlite.Int64(pool)
zero64: llvmlite.Value* = llvmlite.const_int64(pool, 0)
if tag == GenTypes.REPL_TY_INT:
iv: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(
builder, val, i64_ty, node, trans)
iv: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, val, i64_ty, node, trans)
if iv is None:
return 1
if self._repl_store_res_i32(trans, ctx_val, GenTypes.REPL_RES_KIND_OFF,
@@ -1307,8 +1259,7 @@ novirtual class VarGenMixin:
return 1
return self._repl_store_res_i64(trans, ctx_val, GenTypes.REPL_RES_B_OFF, zero64)
if tag == GenTypes.REPL_TY_FLOAT:
dv: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(
builder, val, llvmlite.Double(pool), node, trans)
dv: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, val, llvmlite.Double(pool), node, trans)
if dv is None:
return 1
# double → i64 位模式(bitcast,不做数值转换):宿主按位重解释回 double
@@ -1331,8 +1282,7 @@ novirtual class VarGenMixin:
if pv is None:
return 1
# 指针 → i64(ptrtoint):宿主按整数读回后再 inttoptr 成地址
pbits: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(
builder, pv, i64_ty, node, trans)
pbits: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, pv, i64_ty, node, trans)
if pbits is None:
return 1
kind: int = GenTypes.REPL_RES_OBJ
@@ -1365,8 +1315,7 @@ novirtual class VarGenMixin:
return 1
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
slot: llvmlite.Value* = self.repl_slot_ptr(
pool, builder, ctx_val, off, llvmlite.Int64(pool))
slot: llvmlite.Value* = self.repl_slot_ptr(pool, builder, ctx_val, off, llvmlite.Int64(pool))
if slot is None:
return 1
llvmlite.build_store(builder, val, slot)
@@ -1383,8 +1332,7 @@ novirtual class VarGenMixin:
builder: llvmlite.IRBuilder* = trans._cur_builder
if pool is None or builder is None:
return 1
slot: llvmlite.Value* = self.repl_slot_ptr(
pool, builder, ctx_val, off, llvmlite.Int32(pool))
slot: llvmlite.Value* = self.repl_slot_ptr(pool, builder, ctx_val, off, llvmlite.Int32(pool))
if slot is None:
return 1
cv: llvmlite.Value* = llvmlite.const_int32(pool, val)
@@ -1409,16 +1357,14 @@ novirtual class VarGenMixin:
if self.repl_in_frag_scope(trans.SymTab) == 0:
return None
if entry.Kind == GenTypes.REPL_KIND_UNTYPED:
self.Gen.TypeGenErr.fatal_error(
node,
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量 '{name}' 尚未赋值(未定型,先执行一条 'x = ...' 或 'x: int = ...')",
"NameError")
return None
pool: memhub.MemBuddy* = trans.Pool
slot_ty: llvmlite.LLVMType* = self.repl_slot_ty(pool, entry)
if slot_ty is None:
self.Gen.TypeGenErr.fatal_error(
node,
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量 '{name}' 的类型 "
f"{self.repl_tag_label(entry.TyTag, entry.Bits)} 在当前片段不可用"
f"(跨片段类型可见性属 M4)",
@@ -1427,8 +1373,7 @@ novirtual class VarGenMixin:
ctx_val: llvmlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, node)
if ctx_val is None:
return None
slot: llvmlite.Value* = self.repl_slot_ptr(
pool, trans._cur_builder, ctx_val, entry.Offset, slot_ty)
slot: llvmlite.Value* = self.repl_slot_ptr(pool, trans._cur_builder, ctx_val, entry.Offset, slot_ty)
if slot is None:
self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话槽地址生成失败", "InternalCompilerError")
return None
@@ -1452,27 +1397,23 @@ novirtual class VarGenMixin:
if self.repl_in_frag_scope(trans.SymTab) == 0:
return None
if entry.Kind == GenTypes.REPL_KIND_UNTYPED:
self.Gen.TypeGenErr.fatal_error(
node,
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量 '{name}' 尚未赋值(未定型),无法取址(c.Addr)",
"NameError")
return None
pool: memhub.MemBuddy* = trans.Pool
slot_ty: llvmlite.LLVMType* = self.repl_slot_ty(pool, entry)
if slot_ty is None:
self.Gen.TypeGenErr.fatal_error(
node,
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量 '{name}' 的类型在当前片段不可用(跨片段类型可见性属 M4)",
"NameError")
return None
ctx_val: llvmlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, node)
if ctx_val is None:
return None
slot: llvmlite.Value* = self.repl_slot_ptr(
pool, trans._cur_builder, ctx_val, entry.Offset, slot_ty)
slot: llvmlite.Value* = self.repl_slot_ptr(pool, trans._cur_builder, ctx_val, entry.Offset, slot_ty)
if slot is None:
self.Gen.TypeGenErr.fatal_error(
node, "REPL: 会话槽地址生成失败", "InternalCompilerError")
self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话槽地址生成失败", "InternalCompilerError")
return None
# 值内联在槽里(无装箱间接层)⇒ 槽地址即值地址
return slot
@@ -1494,17 +1435,14 @@ novirtual class VarGenMixin:
builder: llvmlite.IRBuilder* = trans._cur_builder
slot_ty: llvmlite.LLVMType* = self.repl_slot_ty(pool, entry)
if slot_ty is None:
self.Gen.TypeGenErr.fatal_error(
node,
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量 '{entry.Name}' 的槽类型不可用"
f"(类型在当前片段不可解析,或结构体值体积超出槽容量)",
"TypeError")
return 1
store_val: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(
builder, rhs_val, slot_ty, node, trans)
store_val: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, slot_ty, node, trans)
if store_val is None:
self.Gen.TypeGenErr.fatal_error(
node,
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量 '{entry.Name}' 无法把右侧值转换为"
f" {self.repl_tag_label(entry.TyTag, entry.Bits)}",
"CastError")
@@ -1519,8 +1457,7 @@ novirtual class VarGenMixin:
if store_val is None:
self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话槽指针同型化失败", "CastError")
return 1
slot: llvmlite.Value* = self.repl_slot_ptr(
pool, builder, ctx_val, entry.Offset, slot_ty)
slot: llvmlite.Value* = self.repl_slot_ptr(pool, builder, ctx_val, entry.Offset, slot_ty)
if slot is None:
self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话槽写入失败", "InternalCompilerError")
return 1
@@ -1549,8 +1486,7 @@ novirtual class VarGenMixin:
if self.repl_in_frag_entry_scope(trans) == 0:
return 0
if rhs_val.Ty is None:
self.Gen.TypeGenErr.fatal_error(
node, f"REPL: 会话变量 '{name}' 的赋值右侧类型未知", "TypeError")
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 的赋值右侧类型未知", "TypeError")
return 1
if self.repl_seal(trans, entry, rhs_val.Ty, rhs_node) != 0:
return 1
@@ -1583,17 +1519,14 @@ novirtual class VarGenMixin:
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
if annot_node is None:
self.Gen.TypeGenErr.fatal_error(
node, f"REPL: 会话变量 '{name}' 的注解缺失", "SyntaxError")
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 的注解缺失", "SyntaxError")
return 1
# 与普通 AnnAssign 同口径:先注册泛型特化,避免 list[X] 退化为裸基类
# (裸 list* 会让后续 .get() 误分派并截断指针)
self.Gen.AssignGen._prespecialize_generic_annotation(trans, pool, annot_node)
annot_ty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, annot_node, trans._imported_modules, trans._from_imports, trans, 0)
annot_ty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, annot_node, trans._imported_modules, trans._from_imports, trans, 0)
if annot_ty is None:
self.Gen.TypeGenErr.fatal_error(
node,
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量 '{name}' 的类型注解解析失败"
f"(片段无 import;仅内建名 int/str/bytes/bool/float/double/char 等可解析)",
"NameError")
@@ -1607,13 +1540,11 @@ novirtual class VarGenMixin:
# 与普通 AnnAssign 四处同口径:翻译 RHS 前设置上下文(裸名泛型构造推断用)
trans.CurAssignAnnot = annot_node
trans.CurAssignNode = value_node
rhs_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, value_node, None, 0, trans, slot_ty)
rhs_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, value_node, None, 0, trans, slot_ty)
trans.CurAssignAnnot = None
trans.CurAssignNode = None
if rhs_val is None:
self.Gen.TypeGenErr.fatal_error(
node, f"REPL: 会话变量 '{name}' 的初值翻译失败", "TypeError")
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 的初值翻译失败", "TypeError")
return 1
ctx_val: llvmlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, node)
if ctx_val is None:
@@ -1642,24 +1573,20 @@ novirtual class VarGenMixin:
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
if entry.TyTag == GenTypes.REPL_TY_STRUCT:
self.Gen.TypeGenErr.fatal_error(
node,
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量 '{name}' 是结构体值,不支持增强赋值",
"TypeError")
return 1
cur_val: llvmlite.Value* = self.repl_try_read(trans, name, node)
if cur_val is None:
return 1
rhs_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, rhs_node, None, 0, trans)
rhs_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, rhs_node, None, 0, trans)
if rhs_val is None:
self.Gen.TypeGenErr.fatal_error(node, "REPL: 增强赋值右侧翻译失败", "TypeError")
return 1
result: llvmlite.Value* = self.Gen.AssignGen._apply_aug_op(
pool, builder, op, cur_val, rhs_val, node, trans, node)
result: llvmlite.Value* = self.Gen.AssignGen._apply_aug_op(pool, builder, op, cur_val, rhs_val, node, trans, node)
if result is None:
self.Gen.TypeGenErr.fatal_error(
node, f"REPL: 会话变量 '{name}' 的增强赋值运算失败 op={op}", "TypeError")
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 的增强赋值运算失败 op={op}", "TypeError")
return 1
# 写回槽(复用赋值路径:定型已存在 ⇒ 只做转换与存储)
return self.repl_try_assign(trans, name, result, node, node)
@@ -1676,11 +1603,9 @@ novirtual class VarGenMixin:
return 1
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
val: llvmlite.Value* = self.Gen.ExprGen.translate_value(
builder, pool, trans.Module, value_node, None, 0, trans)
val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, value_node, None, 0, trans)
if val is None or val.Ty is None:
self.Gen.TypeGenErr.fatal_error(
value_node, "REPL: 表达式片段求值失败", "TypeError")
self.Gen.TypeGenErr.fatal_error(value_node, "REPL: 表达式片段求值失败", "TypeError")
return 1
ctx_val: llvmlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, value_node)
if ctx_val is None:
@@ -1688,8 +1613,7 @@ novirtual class VarGenMixin:
# 类型分类用宿主的影子条目(不占会话槽、不进表):每次先复位为未定型
sh: rawptr[GenTypes.ReplVarEntry] = trans.ReplCtx.Scratch
if sh is None:
self.Gen.TypeGenErr.fatal_error(
value_node, "REPL: 会话缺少影子条目(宿主未初始化)", "InternalCompilerError")
self.Gen.TypeGenErr.fatal_error(value_node, "REPL: 会话缺少影子条目(宿主未初始化)", "InternalCompilerError")
return 1
sh.Kind = GenTypes.REPL_KIND_UNTYPED
sh.TyTag = 0
+18 -28
View File
@@ -1,4 +1,4 @@
import t, c
import t
from stdint import *
import stdio
import stdlib
@@ -40,7 +40,7 @@ import lib.Stub.StubGen.VpiReader as VpiReader
# ctx(会话内存,宿主 PermPool 一次性分配;布局见 GenTypes 顶部注释):
# 偏移 0..63 固定头(magic/version/result_kind/result_a/result_b/var_count/last_frag)
# 偏移 64 起为变量槽(每槽 16 字节)。宿主与片段在**同一进程**内共享该内存:
# 会话变量只存一份 ⇒ c.Addr(x) 得到的就是槽地址(地址同一性)。
# 会话变量只存一份 ⇒ &x 得到的就是槽地址(地址同一性)。
# 值的类型按首次赋值推导(`x = 1` 与 `x: int = 1` 等价,均定型并分配槽)。
#
# 错误可恢复依赖 VLogger 的 jit_flag + setjmp/longjmp:
@@ -57,18 +57,18 @@ import lib.Stub.StubGen.VpiReader as VpiReader
# ============================================================
# 输入行缓冲容量(含 NUL 终止符)
_REPL_LINE_CAP: t.CDefine = 4096
define _REPL_LINE_CAP = 4096
# 块输入缓冲容量(会话级 PermPool,含 NUL 终止符):续行状态下逐行追加的用户原文,
# 行间以一个 '\n' 连接、无行尾换行。
# 取 8 KiB 的理由:常见多行块(10 行 × 80 列 ≈ 0.8 KiB)绰绰有余;整段粘贴
# 100 行 × 80 列 ≈ 8 KiB 也刚好容纳;再大属异常输入,按"明确报错 + 丢弃该块"
# 处理(绝不截断后执行)。上界同时约束包裹源码缓冲的下界(见 _REPL_FRAG_SRC_CAP)。
_REPL_BLOCK_CAP: t.CDefine = 8192
define _REPL_BLOCK_CAP = 8192
# jmp_buf 实测大小:mingw-w64 x86_64 setjmp.h 中 _JBLEN=16、_JBTYPE=SETJMP_FLOAT128(16B)
# ⇒ 16 * 16 = 256 字节(已用 C 探针 sizeof(jmp_buf) 实测 = 256)
_REPL_JMPBUF_SIZE: t.CDefine = 256
define _REPL_JMPBUF_SIZE = 256
# setjmp/longjmp:mingw-w64 x86_64 的 _setjmp 第二参数为 frame 指针,
# setjmp 宏即展开为 _setjmp(buf, NULL)(非 SEH 场景传 None 即可)
@@ -171,8 +171,7 @@ _REPL_PROJECT_PROBE_CAP: t.CDefine = 16
# 片段把 double 的 IEEE754 位模式写进 result_a;宿主按本视图读回即得 double
# (位模式重解释,不做数值转换)。
# ============================================================
@t.NoVTable
class ReplFloatView:
novirtual class ReplFloatView:
"""ctx 头(+16 处按 double 读)"""
Magic: int
Version: int
@@ -188,8 +187,7 @@ class ReplFloatView:
# 16 字节(低 8 字节 = 地址,高 8 字节保留)。片段侧按同一偏移(i8** 视图)
# load 该地址后间接调用;宿主用本视图写入 ⇒ 两侧对"槽内是什么"只有一个约定。
# ============================================================
@t.NoVTable
class ReplFuncSlotView:
novirtual class ReplFuncSlotView:
"""ctx 函数指针槽(Addr = 定义片段 DLL 里该函数的入口地址)"""
Addr: VOIDPTR
Reserved: VOIDPTR
@@ -204,8 +202,7 @@ class ReplFuncSlotView:
# ReplFuncEntry 的签名 token;调用片段再用 token 重建同型签名 ⇒ 两侧一致。
# 形参/返回的 token 数组写进会话 scratch(ReplSigTags/ReplSigBits)。
# ============================================================
@t.NoVTable
class ReplSigOut:
novirtual class ReplSigOut:
"""签名解析结果(Bad/EHTag 非 0 时拒绝注册)"""
RetTag: int # GenTypes.REPL_TY_VOID / INT / FLOAT / STR
RetBits: int
@@ -529,11 +526,11 @@ def _read_line(h: win32base.HANDLE, buf: bytes, cap: int) -> int:
eof: int = 0
while total < cap - 1:
bytes_read = 0
ok = w32file.ReadFile(h, buf + total, 1, t.CPtr(c.Addr(bytes_read)), None)
ok = w32file.ReadFile(h, buf + total, 1, &bytes_read, None)
if ok == 0 or bytes_read == 0:
eof = 1
break
# 注意:不能用 c.Deref(buf + total)——其 IR 生成 i32 load(读 4 字节),
# 注意:不能用 &(buf + total)——其 IR 生成 i32 load(读 4 字节),
# 比较 '\n'/'\r' 永不命中;字节索引 buf[total] 才是 i8 load
ch: char = buf[total]
if ch == 10: # '\n':行结束
@@ -933,8 +930,7 @@ def ReplInitIncludesClasses(mb: memhub.MemBuddy*,
GenApi.SetTempDir(vpi_dir)
GenApi.set_current_file_type(vpi_dir)
tmp_mod: llvmlite.LLVMModule* = llvmlite.new_module(_perm_pool, _REPL_INC_MOD_NAME)
tr_inc: rawptr[HandlesTranslator.Translator] = _perm_pool.alloc(
HandlesTranslator.Translator.__sizeof__())
tr_inc: rawptr[HandlesTranslator.Translator] = _perm_pool.alloc(HandlesTranslator.Translator.__sizeof__())
if tmp_mod is None or tr_inc is None:
return 1
tr_inc.__before_init__()
@@ -978,8 +974,7 @@ def ReplInitIncludesClasses(mb: memhub.MemBuddy*,
"仍可按需注册)\n", GenApi.get_struct_count())
stdio.fflush(None)
return 0
ent: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](
uint64(sr.Entries) + uint64(i) * uint64(es))
ent: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](uint64(sr.Entries) + uint64(i) * uint64(es))
if ent is None or ent.Sha1 is None:
st[i] = sizet(1)
ReplIncClsFail += 1
@@ -1171,8 +1166,7 @@ def ReplInitSession() -> int:
ReplScratch.Bits = 0
# ⑤' 会话函数表(M3;PermPool,宿主写、Gen 只读)——条目数组清零
func_entry_size: sizet = GenTypes.ReplFuncEntry.__sizeof__()
ReplFuncTable: rawptr[GenTypes.ReplFuncEntry] = _perm_pool.alloc(
func_entry_size * GenTypes.REPL_FUNC_CAP)
ReplFuncTable: rawptr[GenTypes.ReplFuncEntry] = _perm_pool.alloc(func_entry_size * GenTypes.REPL_FUNC_CAP)
if ReplFuncTable is None:
return 1
string.memset(ReplFuncTable, 0, func_entry_size * GenTypes.REPL_FUNC_CAP)
@@ -1296,8 +1290,7 @@ def _repl_gen_includes_vpi(mb: memhub.MemBuddy*,
dl: sizet = string.strlen(vpi_dir)
n: int
for n in range(sr.Count):
ent: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](
uint64(sr.Entries) + uint64(n) * es)
ent: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](uint64(sr.Entries) + uint64(n) * es)
if ent is None or ent.Sha1 is None or ent.Path is None:
ReplIncVpiFail += 1
continue
@@ -1871,8 +1864,7 @@ def _repl_func_entry_find(name: str) -> rawptr[GenTypes.ReplFuncEntry]:
es: sizet = GenTypes.ReplFuncEntry.__sizeof__()
i: int
for i in range(ReplCtxObj.FuncCount):
e: rawptr[GenTypes.ReplFuncEntry] = rawptr[GenTypes.ReplFuncEntry](
uint64(ReplCtxObj.FuncTable) + uint64(i) * uint64(es))
e: rawptr[GenTypes.ReplFuncEntry] = rawptr[GenTypes.ReplFuncEntry](uint64(ReplCtxObj.FuncTable) + uint64(i) * uint64(es))
if e.Name is not None and string.strcmp(e.Name, name) == 0:
return e
return None
@@ -2045,8 +2037,7 @@ def _repl_register_session_funcs(h_lib: win32base.HANDLE, frag_no: int) -> int:
return 1
j: int = ReplCtxObj.FuncCount
es: sizet = GenTypes.ReplFuncEntry.__sizeof__()
ent = rawptr[GenTypes.ReplFuncEntry](
uint64(ReplCtxObj.FuncTable) + uint64(j) * uint64(es))
ent = rawptr[GenTypes.ReplFuncEntry](uint64(ReplCtxObj.FuncTable) + uint64(j) * uint64(es))
nm_c: str = _repl_perm_dup(nm)
nm_s: str = _repl_perm_dup(nm)
tags_b: bytes = _perm_pool.alloc(GenTypes.REPL_FUNC_PARAM_MAX)
@@ -2072,8 +2063,7 @@ def _repl_register_session_funcs(h_lib: win32base.HANDLE, frag_no: int) -> int:
# 重定义(同签名):只换地址与段号,槽偏移不变
ent.FragNo = frag_no
# 写 ctx 槽(低 8 字节=地址,高 8 字节保留 0)
sv: rawptr[ReplFuncSlotView] = rawptr[ReplFuncSlotView](
uint64(ReplCtxBuf) + uint64(ent.SlotOff))
sv: rawptr[ReplFuncSlotView] = rawptr[ReplFuncSlotView](uint64(ReplCtxBuf) + uint64(ent.SlotOff))
sv.Addr = addr
sv.Reserved = None
stdio.printf("会话函数 %s: 导出符号 %s → ctx 槽 +%d(定义片段 %d,签名 %s)\n",
@@ -2817,7 +2807,7 @@ def run(mb: memhub.MemBuddy*) -> int:
stdio.printf("TransPyV REPL (M2/M3/M4) - 会话变量 + 会话函数(跨片段)+ ctx 回传结果;\n")
stdio.printf(" 支持表达式(1+2)、定义(x = 1 / x: int = 5)、引用(x + 1)、\n")
stdio.printf(" 增强赋值(x += 2)、取址(p = c.Addr(x))等;空行跳过,Ctrl+Z 或 EOF 退出\n")
stdio.printf(" 增强赋值(x += 2)、取址(p = &x)等;空行跳过,Ctrl+Z 或 EOF 退出\n")
stdio.printf(" 多行块:行尾 ':' 进入续行(提示符 ...),空行结束并整块执行一次\n")
stdio.printf(" 跨片段函数:块里顶格的 def 会被提升为片段模块的 export def(裸名导出),\n")
stdio.printf(" 后续片段可直接调用(如 def f(x: int) -> int: 换行 +4 空格 return x + 1);\n")