refactor(gen): 去除 Handles 委托层——链式化 + GenTypes/GenApi 迁移
- Gen 内部 1742 处 HandlesX.func() 改 self.Gen.Y.method() 链式调用 - 数据类/常量迁移 GenTypes.vp(10 类 + CLASS_META_*/META_*/SEQ_KIND_*/FIELD_MAX 等) - 管线/保留文件经 GenApi.vp 模块级入口(48 函数带类型注解,从 Gen 方法签名自动生成) - 删除 26 个纯委托 Handles 文件,仅留 5 个实体文件(Base/Translator/Expr/ExprCall/ExprCallTable) - 修复字段分裂:TypeGenErr CurrentFile/TraceCount 链式化;CallGenBase TempDir/Cexport 真源化
This commit is contained in:
1 parent
ca1453c0ec
commit
89995dffde
96 files changed
+50608
-62634
No files matched your search
+910
-909
File diff suppressed because it is too large.
Load diff
+1361
-1363
File diff suppressed because it is too large.
Load diff
+939
-977
File diff suppressed because it is too large.
Load diff
+2221
-2233
File diff suppressed because it is too large.
Load diff
@@ -1,58 +1,60 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import llvmlite
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
|
||||
|
||||
# ============================================================
|
||||
# BaseGenMixin - 生成器基座(状态容器)
|
||||
#
|
||||
# 对象化重构 P1(方案见 wiki/14-oo-refactor.md):
|
||||
# 将 Translator/Handles 的共享状态集中于此。后续 Mixin
|
||||
# (TypeGen/StructGen/ExprGen/CallGen/FuncGen/ClassGen/StmtGen/
|
||||
# ImportsGen)单继承本类,逐步把 Handles* 模块的函数迁移为
|
||||
# Generator 的方法,消除 (pool, builder, mod, node, ...) 六参连传。
|
||||
#
|
||||
# 注意:@t.NoVTable(静态绑定,骨架无多态需求;若未来需要
|
||||
# 运行时多态再改 @t.CVTable,字段布局由编译器统一管理)。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class BaseGenMixin:
|
||||
"""生成器状态容器(基座)"""
|
||||
|
||||
# 内存/IR 状态
|
||||
Pool: memhub.MemBuddy | t.CPtr # 内存池
|
||||
Module: llvmlite.LLVMModule | t.CPtr # 当前 LLVM 模块
|
||||
Builder: llvmlite.IRBuilder | t.CPtr # 当前 IRBuilder
|
||||
# 符号表/函数表
|
||||
SymTab: HandlesVar.SymbolTable | t.CPtr
|
||||
Funcs: HandlesExprCall.FuncEntry | t.CPtr
|
||||
FuncCount: int
|
||||
# 导入/模块信息
|
||||
ImportedModules: str
|
||||
FromImports: str
|
||||
ModuleSha1: str
|
||||
# 当前翻译上下文
|
||||
CurFunc: llvmlite.Function | t.CPtr
|
||||
CurBuilder: llvmlite.IRBuilder | t.CPtr
|
||||
CurClassName: str
|
||||
|
||||
def InitBaseGen(self, pool: memhub.MemBuddy | t.CPtr) -> int:
|
||||
"""初始化生成器状态(默认值;子类构造时调用)"""
|
||||
if self is None:
|
||||
return 1
|
||||
self.Pool = pool
|
||||
self.Module = None
|
||||
self.Builder = None
|
||||
self.SymTab = None
|
||||
self.Funcs = None
|
||||
self.FuncCount = 0
|
||||
self.ImportedModules = None
|
||||
self.FromImports = None
|
||||
self.ModuleSha1 = None
|
||||
self.CurFunc = None
|
||||
self.CurBuilder = None
|
||||
self.CurClassName = None
|
||||
return 0
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import llvmlite
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
|
||||
|
||||
# ============================================================
|
||||
# BaseGenMixin - 生成器基座(状态容器)
|
||||
#
|
||||
# 对象化重构 P1(方案见 wiki/14-oo-refactor.md):
|
||||
# 将 Translator/Handles 的共享状态集中于此。后续 Mixin
|
||||
# (TypeGen/StructGen/ExprGen/CallGen/FuncGen/ClassGen/StmtGen/
|
||||
# ImportsGen)单继承本类,逐步把 Handles* 模块的函数迁移为
|
||||
# Generator 的方法,消除 (pool, builder, mod, node, ...) 六参连传。
|
||||
#
|
||||
# 注意:@t.NoVTable(静态绑定,骨架无多态需求;若未来需要
|
||||
# 运行时多态再改 @t.CVTable,字段布局由编译器统一管理)。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class BaseGenMixin:
|
||||
"""生成器状态容器(基座)"""
|
||||
|
||||
# 内存/IR 状态
|
||||
Gen: Generator.Generator | t.CPtr
|
||||
Pool: memhub.MemBuddy | t.CPtr # 内存池
|
||||
Module: llvmlite.LLVMModule | t.CPtr # 当前 LLVM 模块
|
||||
Builder: llvmlite.IRBuilder | t.CPtr # 当前 IRBuilder
|
||||
# 符号表/函数表
|
||||
SymTab: GenTypes.SymbolTable | t.CPtr
|
||||
Funcs: GenTypes.FuncEntry | t.CPtr
|
||||
FuncCount: int
|
||||
# 导入/模块信息
|
||||
ImportedModules: str
|
||||
FromImports: str
|
||||
ModuleSha1: str
|
||||
# 当前翻译上下文
|
||||
CurFunc: llvmlite.Function | t.CPtr
|
||||
CurBuilder: llvmlite.IRBuilder | t.CPtr
|
||||
CurClassName: str
|
||||
|
||||
def InitBaseGen(self, pool: memhub.MemBuddy | t.CPtr) -> int:
|
||||
"""初始化生成器状态(默认值;子类构造时调用)"""
|
||||
if self is None:
|
||||
return 1
|
||||
self.Pool = pool
|
||||
self.Module = None
|
||||
self.Builder = None
|
||||
self.SymTab = None
|
||||
self.Funcs = None
|
||||
self.FuncCount = 0
|
||||
self.ImportedModules = None
|
||||
self.FromImports = None
|
||||
self.ModuleSha1 = None
|
||||
self.CurFunc = None
|
||||
self.CurBuilder = None
|
||||
self.CurClassName = None
|
||||
return 0
|
||||
+1015
-1018
File diff suppressed because it is too large.
Load diff
+1407
-1414
File diff suppressed because it is too large.
Load diff
+1566
-1575
File diff suppressed because it is too large.
Load diff
+980
-988
File diff suppressed because it is too large.
Load diff
+1509
-1526
File diff suppressed because it is too large.
Load diff
+403
-410
@@ -1,411 +1,404 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import sys
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
import lib.core.Gen.CallGenBase as CallGenBase
|
||||
|
||||
# ============================================================
|
||||
# CallGenFd - CallGenMixin 拆分(阶段 B):FakeDuck / requires 字段注入 / provider 栈
|
||||
#
|
||||
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class CallGenFd(CallGenBase.CallGenBase):
|
||||
"""FakeDuck / requires 字段注入 / provider 栈"""
|
||||
|
||||
# ============================================================
|
||||
# _translate_fakeduck_call - FakeDuck: str 变量方法调用 → 扩展类 _Type/_str
|
||||
#
|
||||
# 对齐 TPC HandlesExprCall.py L2841-2880:
|
||||
# ClassName 常规解析失败且对象是 char*(i8*)时,遍历扩展类查找
|
||||
# {CN}.{method} 函数。对象是 Name 变量且有影子({var}__meta__,fd2
|
||||
# 创建)时 self=影子;否则(字符串字面量/匿名 str)在入口创建临时
|
||||
# 影子,写 __data__=obj 值、__mbuddy__=NULL 后作 self,避免
|
||||
# bitcast i8* → _str* 读取垃圾指针导致 ACCESS_VIOLATION。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _translate_fakeduck_call(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cls_name: str,
|
||||
method_name: str,
|
||||
cl: ast.Call | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""FakeDuck: str 变量方法调用解析到扩展类 _Type/_str,返回 call 结果或 None"""
|
||||
if pool is None or builder is None or cl is None or trans is None:
|
||||
return None
|
||||
if method_name is None:
|
||||
return None
|
||||
# 仅对 str 类型触发(AnnotClassName == "str",对象是 char*);
|
||||
# cls_name 为 None(表达式接收者解析失败)时也尝试
|
||||
if cls_name is not None and string.strcmp(cls_name, "str") != 0:
|
||||
return None
|
||||
if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute:
|
||||
return None
|
||||
fd_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func)
|
||||
if fd_at is None or fd_at.value is None or fd_at.attr is None:
|
||||
return None
|
||||
if string.strcmp(fd_at.attr, method_name) != 0:
|
||||
return None
|
||||
# 候选扩展类:先 _Type(a.type_id())后 _str(a.upper() 等)
|
||||
fd_func: llvmlite.Function | t.CPtr = None
|
||||
fd_cls: str = None
|
||||
fd_key: str = pool.alloc(160)
|
||||
if fd_key is not None:
|
||||
for fd_ci in range(2):
|
||||
fd_cn: str = "_Type"
|
||||
if fd_ci == 1:
|
||||
fd_cn = "_str"
|
||||
viperlib.snprintf(fd_key, 160, "%s.%s", fd_cn, method_name)
|
||||
fd_func = self.find_func_in_module(mod, fd_key)
|
||||
if fd_func is not None:
|
||||
fd_cls = fd_cn
|
||||
break
|
||||
if fd_func is None or fd_cls is None:
|
||||
return None
|
||||
# 扩展类结构体必须已注册(GEP/临时影子需要类型)
|
||||
fd_sty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(fd_cls)
|
||||
if fd_sty is None:
|
||||
return None
|
||||
# 扩展类字段数:有字段(_str)时 self 用影子结构体指针;
|
||||
# 无字段(_Type)时 self 用对象值 bitcast 到扩展类指针(对齐 TPC L2856-2876)
|
||||
fd_entry_fd: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(fd_sty)
|
||||
fd_has_fields: int = 0
|
||||
if fd_entry_fd is not None and fd_entry_fd.FieldCount > 0:
|
||||
fd_has_fields = 1
|
||||
# self 参数:优先使用已有影子 {var}__meta__(fd2 创建,仅当扩展类有字段时)
|
||||
fd_self: llvmlite.Value | t.CPtr = None
|
||||
if fd_at.value.kind() == ast.ASTKind.Name:
|
||||
fd_onm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(fd_at.value)
|
||||
if fd_onm.id is not None:
|
||||
# pool 持久缓冲(f-string 栈缓冲在函数返回后失效)
|
||||
fd_mn: str = pool.alloc(256)
|
||||
if fd_mn is not None:
|
||||
viperlib.snprintf(fd_mn, 256, "%s__meta__", fd_onm.id)
|
||||
fd_meta: llvmlite.Value | t.CPtr = HandlesVar.lookup_current(
|
||||
trans.SymTab, fd_mn)
|
||||
if fd_meta is not None and fd_has_fields != 0:
|
||||
fd_self = fd_meta
|
||||
if fd_self is None:
|
||||
if fd_has_fields != 0:
|
||||
# 有字段扩展类且无影子(字符串字面量等):入口创建临时影子并初始化
|
||||
# 先确保 _str 完整定义(跨模块结构体默认 opaque,alloca 报 unsized)
|
||||
HandlesStruct.ensure_struct_def_in_module(pool, mod, fd_sty)
|
||||
fd_self = HandlesVar._alloca_at_entry(builder, fd_sty)
|
||||
if fd_self is None:
|
||||
return None
|
||||
fd_obj_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, fd_at.value, None, 0, trans)
|
||||
if fd_obj_val is not None:
|
||||
fd_dfe: HandlesStruct.FieldEntry | t.CPtr = \
|
||||
HandlesStruct.lookup_field(fd_sty, "__data__")
|
||||
if fd_dfe is not None and fd_dfe.Ty is not None:
|
||||
fd_dp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
|
||||
builder, fd_sty, fd_dfe.Ty, fd_self, fd_dfe.Index)
|
||||
if fd_dp is not None:
|
||||
llvmlite.build_store(builder, fd_obj_val, fd_dp)
|
||||
fd_bfe: HandlesStruct.FieldEntry | t.CPtr = \
|
||||
HandlesStruct.lookup_field(fd_sty, "__mbuddy__")
|
||||
if fd_bfe is not None and fd_bfe.Ty is not None:
|
||||
fd_bp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
|
||||
builder, fd_sty, fd_bfe.Ty, fd_self, fd_bfe.Index)
|
||||
fd_null: llvmlite.Value | t.CPtr = llvmlite.ConstNull(
|
||||
pool, fd_bfe.Ty, "null")
|
||||
if fd_bp is not None and fd_null is not None:
|
||||
llvmlite.build_store(builder, fd_null, fd_bp)
|
||||
# FakeDuck: with 上下文自动注入 requires 字段(如 __mbuddy__)
|
||||
self._inject_requires_fields(
|
||||
trans, pool, builder, mod, fd_self, fd_cls)
|
||||
else:
|
||||
# 无字段扩展类(_Type):对象值 bitcast 到扩展类指针
|
||||
fd_obj_v: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, fd_at.value, None, 0, trans)
|
||||
if fd_obj_v is None:
|
||||
return None
|
||||
fd_self = llvmlite.build_bitcast(
|
||||
builder, fd_obj_v, llvmlite.Ptr(pool, fd_sty))
|
||||
if fd_self is None:
|
||||
return None
|
||||
# 构建参数链表: self → 其余参数
|
||||
llvmlite.value_set_next(fd_self, None)
|
||||
fd_head: llvmlite.Value | t.CPtr = fd_self
|
||||
fd_tail: llvmlite.Value | t.CPtr = fd_self
|
||||
fd_args: list[ast.AST | t.CPtr] | t.CPtr = cl.args
|
||||
fd_can: int = 0
|
||||
if fd_args is not None:
|
||||
fd_can = len(fd_args)
|
||||
for fd_ai in range(fd_can):
|
||||
fd_arg: ast.AST | t.CPtr = fd_args.get(fd_ai)
|
||||
if fd_arg is not None:
|
||||
fd_av: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, fd_arg, None, 0, trans)
|
||||
# char 常量参数 → 单字符字符串(char 隐式转 str,
|
||||
# 如 s1.split(','):',' 是 i32 值 44,传给 str 参数须先字符串化,
|
||||
# 否则运行时 strlen/strncmp 解引用 44 崩溃)
|
||||
if fd_arg.kind() == ast.ASTKind.Constant:
|
||||
fd_ac: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(fd_arg)
|
||||
if fd_ac.const_kind == ast.CONST_CHAR:
|
||||
ch_buf: str = pool.alloc(2)
|
||||
if ch_buf is not None:
|
||||
ch_buf[0] = t.CChar(fd_ac.int_val)
|
||||
ch_buf[1] = '\0'
|
||||
fd_av = HandlesExpr.create_global_string(
|
||||
builder, pool, mod, ch_buf, trans)
|
||||
if fd_av is not None:
|
||||
llvmlite.value_set_next(fd_av, None)
|
||||
llvmlite.value_set_next(fd_tail, fd_av)
|
||||
fd_tail = fd_av
|
||||
# 返回类型与调用名(来自 find_func_in_module 命中的函数定义)
|
||||
fd_ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(fd_func)
|
||||
if fd_ret_ty is None:
|
||||
fd_ret_ty = llvmlite.Int32(pool)
|
||||
fd_fname: str = llvmlite.function_get_name(fd_func)
|
||||
if fd_fname is None:
|
||||
return None
|
||||
# 返回类型精确化:跨模块 declare 的 list[T] 特化返回类型可能被简化
|
||||
# 为 Ptr(i8),调用方变量 alloca 类型随之退化 → parts[0] 走字符下标
|
||||
# 路径而非 list 内联 __getitem__(printf %s 解引用字符值崩溃)。
|
||||
# 从定义模块 text.ll 读取精确返回类型(对齐普通方法调用 _translate_method_call)。
|
||||
fd_sha1: str = pool.alloc(17)
|
||||
if fd_sha1 is not None:
|
||||
string.strncpy(fd_sha1, fd_fname, 16)
|
||||
fd_sha1[16] = '\0'
|
||||
fd_exact: llvmlite.LLVMType | t.CPtr = self._LookupMethodRetTyFromTextLL(
|
||||
pool, fd_sha1, fd_cls, method_name)
|
||||
if fd_exact is not None:
|
||||
fd_ret_ty = fd_exact
|
||||
fd_total: int = 1 + fd_can
|
||||
return llvmlite.build_call(builder, fd_fname, fd_head, fd_total, fd_ret_ty, 0)
|
||||
# ============================================================
|
||||
# _inject_requires_fields - FakeDuck: with 上下文注入 requires 字段
|
||||
#
|
||||
# 对齐 TPC HandlesExprCall.py L4021-4079:
|
||||
# 对类 __requires__ 元数据(fd1 注册)中的每个字段,运行时调用
|
||||
# _find_provider(field) 查找 with 上下文提供的指针;非 NULL 时
|
||||
# bitcast 到字段类型写入 meta_ptr 对应槽位(条件注入,避免覆盖
|
||||
# 用户已手动设置的值)。_find_provider 未注册(未 import
|
||||
# _withcontent)时跳过注入,不影响非 with 场景。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _inject_requires_fields(self, trans: HT.Translator | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
meta_ptr: llvmlite.Value | t.CPtr,
|
||||
class_name: str) -> int:
|
||||
"""在 with 上下文注入 requires 字段,返回注入字段数"""
|
||||
if trans is None or pool is None or builder is None or mod is None:
|
||||
return 0
|
||||
if meta_ptr is None or class_name is None:
|
||||
return 0
|
||||
# _withcontent._find_provider(跨模块):仅当本模块可见(_withcontent
|
||||
# 被 import,vpi stub declare 已注入)时才注入。对齐 TPC L4048-4050
|
||||
# (Gen.functions.get('_find_provider') 不存在则跳过)——否则非 with
|
||||
# 项目(如 HashTableTest 未 import _withcontent)也会为每个 _str(...)
|
||||
# 构造发射 {sha1}._find_provider 调用 → ld.lld undefined symbol。
|
||||
fd_fn_probe: llvmlite.Function | t.CPtr = self.find_func_in_module(
|
||||
mod, "_find_provider")
|
||||
if fd_fn_probe is None:
|
||||
return 0
|
||||
fd_fname: str = llvmlite.function_get_name(fd_fn_probe)
|
||||
if fd_fname is None:
|
||||
return 0
|
||||
cnt: int = HandlesType.class_meta_count(
|
||||
HandlesType.CLASS_META_REQUIRES, class_name)
|
||||
if cnt <= 0:
|
||||
return 0
|
||||
sty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(class_name)
|
||||
if sty is None:
|
||||
return 0
|
||||
i8_ty_j: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
if i8_ty_j is None:
|
||||
return 0
|
||||
i8_ptr_ty_j: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_j)
|
||||
if i8_ptr_ty_j is None:
|
||||
return 0
|
||||
cur_func: llvmlite.Function | t.CPtr = trans._cur_func
|
||||
if cur_func is None:
|
||||
return 0
|
||||
injected: int = 0
|
||||
for ji in range(cnt):
|
||||
fname: str = HandlesType.class_meta_field_at(
|
||||
HandlesType.CLASS_META_REQUIRES, class_name, ji)
|
||||
if fname is None:
|
||||
continue
|
||||
fe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct.lookup_field(
|
||||
sty, fname)
|
||||
if fe is None or fe.Ty is None:
|
||||
continue
|
||||
# 参数:字段名字符串(i8*)
|
||||
fd_fstr: llvmlite.Value | t.CPtr = HandlesExpr.create_global_string(
|
||||
builder, pool, mod, fname, trans)
|
||||
if fd_fstr is None:
|
||||
continue
|
||||
llvmlite.value_set_next(fd_fstr, None)
|
||||
self._ensure_method_declare(
|
||||
pool, mod, fd_fname, i8_ptr_ty_j, fd_fstr, 1)
|
||||
fd_ptr: llvmlite.Value | t.CPtr = llvmlite.build_call(
|
||||
builder, fd_fname, fd_fstr, 1, i8_ptr_ty_j, 0)
|
||||
if fd_ptr is None:
|
||||
continue
|
||||
# 条件注入:ptr != NULL 才写入(保留用户手动设置的值)
|
||||
fd_null: llvmlite.Value | t.CPtr = llvmlite.ConstNull(
|
||||
pool, i8_ptr_ty_j, "null")
|
||||
if fd_null is None:
|
||||
continue
|
||||
fd_cmp: llvmlite.Value | t.CPtr = llvmlite.build_icmp(
|
||||
builder, llvmlite.ICMP_NE, fd_ptr, fd_null)
|
||||
if fd_cmp is None:
|
||||
continue
|
||||
# 块名唯一化(create_block 不自动编号,同名 label 在文本 IR 中
|
||||
# 冲突 → llc "Terminator found in the middle of a basic block")
|
||||
vtc2: int = trans._label_counter
|
||||
trans._label_counter = vtc2 + 1
|
||||
fd_bb_buf2: str = pool.alloc(64)
|
||||
if fd_bb_buf2 is None:
|
||||
continue
|
||||
viperlib.snprintf(fd_bb_buf2, 64, "fd.skip.%d", vtc2)
|
||||
fd_skip_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
|
||||
pool, cur_func, fd_bb_buf2)
|
||||
viperlib.snprintf(fd_bb_buf2, 64, "fd.inject.%d", vtc2)
|
||||
fd_inject_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
|
||||
pool, cur_func, fd_bb_buf2)
|
||||
if fd_skip_bb is None or fd_inject_bb is None:
|
||||
continue
|
||||
llvmlite.build_cond_br(builder, fd_cmp, fd_inject_bb, fd_skip_bb)
|
||||
# inject 块:bitcast + GEP + store,跳回 skip
|
||||
llvmlite.position_at_end(builder, fd_inject_bb)
|
||||
fd_cast: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||||
builder, fd_ptr, fe.Ty)
|
||||
if fd_cast is not None:
|
||||
fd_fp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
|
||||
builder, sty, fe.Ty, meta_ptr, fe.Index)
|
||||
if fd_fp is not None:
|
||||
llvmlite.build_store(builder, fd_cast, fd_fp)
|
||||
llvmlite.build_br(builder, fd_skip_bb)
|
||||
# skip 块:恢复 CurBlock,继续后续代码生成
|
||||
llvmlite.position_at_end(builder, fd_skip_bb)
|
||||
injected += 1
|
||||
return injected
|
||||
# ============================================================
|
||||
# _emit_provider_push / _emit_provider_pop - FakeDuck: with 上下文
|
||||
# provider push/pop(__provides__ 元数据,fd1 注册)
|
||||
#
|
||||
# 对齐 TPC HandlesWith.py L138-174:
|
||||
# with 进入时对每个提供字段生成 _push_provider(field_str, ctx_i8);
|
||||
# 退出时生成等量 _pop_provider()。运行时 _withcontent 模块负责
|
||||
# 维护 TLS provider 栈,供 _inject_requires_fields 查找。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _emit_provider_push(self, trans: HT.Translator | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cls_name: str,
|
||||
ctx_val: llvmlite.Value | t.CPtr) -> int:
|
||||
"""生成 _push_provider(field, ctx_i8) 调用(每提供字段一次),返回字段数"""
|
||||
if trans is None or pool is None or builder is None or mod is None:
|
||||
return 0
|
||||
if cls_name is None or ctx_val is None:
|
||||
return 0
|
||||
fd_pc: int = HandlesType.class_meta_count(
|
||||
HandlesType.CLASS_META_PROVIDES, cls_name)
|
||||
if fd_pc <= 0:
|
||||
return 0
|
||||
# _withcontent._push_provider(跨模块,同 _find_provider 的可见性守卫:
|
||||
# 本模块未 import _withcontent 时跳过,避免 undefined symbol)
|
||||
fd_pfn_probe: llvmlite.Function | t.CPtr = self.find_func_in_module(
|
||||
mod, "_push_provider")
|
||||
if fd_pfn_probe is None:
|
||||
return 0
|
||||
fd_pfn: str = llvmlite.function_get_name(fd_pfn_probe)
|
||||
if fd_pfn is None:
|
||||
return 0
|
||||
i8_ty_p: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
if i8_ty_p is None:
|
||||
return 0
|
||||
i8_ptr_ty_p: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_p)
|
||||
if i8_ptr_ty_p is None:
|
||||
return 0
|
||||
ret_i32_p: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
if ret_i32_p is None:
|
||||
return 0
|
||||
# ctx 值 bitcast 到 i8*(provider 栈存 void*)
|
||||
fd_ctx_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||||
builder, ctx_val, i8_ptr_ty_p)
|
||||
if fd_ctx_i8 is None:
|
||||
return 0
|
||||
for pi in range(fd_pc):
|
||||
fname: str = HandlesType.class_meta_field_at(
|
||||
HandlesType.CLASS_META_PROVIDES, cls_name, pi)
|
||||
if fname is None:
|
||||
continue
|
||||
fd_fstr: llvmlite.Value | t.CPtr = HandlesExpr.create_global_string(
|
||||
builder, pool, mod, fname, trans)
|
||||
if fd_fstr is None:
|
||||
continue
|
||||
llvmlite.value_set_next(fd_fstr, fd_ctx_i8)
|
||||
llvmlite.value_set_next(fd_ctx_i8, None)
|
||||
self._ensure_method_declare(
|
||||
pool, mod, fd_pfn, ret_i32_p, fd_fstr, 2)
|
||||
llvmlite.build_call(builder, fd_pfn, fd_fstr, 2, ret_i32_p, 0)
|
||||
return fd_pc
|
||||
def _emit_provider_pop(self, trans: HT.Translator | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cls_name: str) -> int:
|
||||
"""生成 _pop_provider() 调用(每提供字段一次),返回字段数"""
|
||||
if trans is None or pool is None or builder is None or mod is None:
|
||||
return 0
|
||||
if cls_name is None:
|
||||
return 0
|
||||
fd_pc: int = HandlesType.class_meta_count(
|
||||
HandlesType.CLASS_META_PROVIDES, cls_name)
|
||||
if fd_pc <= 0:
|
||||
return 0
|
||||
# _withcontent._pop_provider(跨模块,同 _find_provider 的可见性守卫:
|
||||
# 本模块未 import _withcontent 时跳过,避免 undefined symbol)
|
||||
fd_pon_probe: llvmlite.Function | t.CPtr = self.find_func_in_module(
|
||||
mod, "_pop_provider")
|
||||
if fd_pon_probe is None:
|
||||
return 0
|
||||
fd_pon: str = llvmlite.function_get_name(fd_pon_probe)
|
||||
if fd_pon is None:
|
||||
return 0
|
||||
ret_i32_q: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
if ret_i32_q is None:
|
||||
return 0
|
||||
self._ensure_method_declare(pool, mod, fd_pon, ret_i32_q, None, 0)
|
||||
for _pi in range(fd_pc):
|
||||
llvmlite.build_call(builder, fd_pon, None, 0, ret_i32_q, 0)
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import sys
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
import lib.core.Gen.CallGenBase as CallGenBase
|
||||
|
||||
# ============================================================
|
||||
# CallGenFd - CallGenMixin 拆分(阶段 B):FakeDuck / requires 字段注入 / provider 栈
|
||||
#
|
||||
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class CallGenFd(CallGenBase.CallGenBase):
|
||||
"""FakeDuck / requires 字段注入 / provider 栈"""
|
||||
|
||||
# ============================================================
|
||||
# _translate_fakeduck_call - FakeDuck: str 变量方法调用 → 扩展类 _Type/_str
|
||||
#
|
||||
# 对齐 TPC HandlesExprCall.py L2841-2880:
|
||||
# ClassName 常规解析失败且对象是 char*(i8*)时,遍历扩展类查找
|
||||
# {CN}.{method} 函数。对象是 Name 变量且有影子({var}__meta__,fd2
|
||||
# 创建)时 self=影子;否则(字符串字面量/匿名 str)在入口创建临时
|
||||
# 影子,写 __data__=obj 值、__mbuddy__=NULL 后作 self,避免
|
||||
# bitcast i8* → _str* 读取垃圾指针导致 ACCESS_VIOLATION。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _translate_fakeduck_call(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cls_name: str,
|
||||
method_name: str,
|
||||
cl: ast.Call | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""FakeDuck: str 变量方法调用解析到扩展类 _Type/_str,返回 call 结果或 None"""
|
||||
if pool is None or builder is None or cl is None or trans is None:
|
||||
return None
|
||||
if method_name is None:
|
||||
return None
|
||||
# 仅对 str 类型触发(AnnotClassName == "str",对象是 char*);
|
||||
# cls_name 为 None(表达式接收者解析失败)时也尝试
|
||||
if cls_name is not None and string.strcmp(cls_name, "str") != 0:
|
||||
return None
|
||||
if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute:
|
||||
return None
|
||||
fd_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func)
|
||||
if fd_at is None or fd_at.value is None or fd_at.attr is None:
|
||||
return None
|
||||
if string.strcmp(fd_at.attr, method_name) != 0:
|
||||
return None
|
||||
# 候选扩展类:先 _Type(a.type_id())后 _str(a.upper() 等)
|
||||
fd_func: llvmlite.Function | t.CPtr = None
|
||||
fd_cls: str = None
|
||||
fd_key: str = pool.alloc(160)
|
||||
if fd_key is not None:
|
||||
for fd_ci in range(2):
|
||||
fd_cn: str = "_Type"
|
||||
if fd_ci == 1:
|
||||
fd_cn = "_str"
|
||||
viperlib.snprintf(fd_key, 160, "%s.%s", fd_cn, method_name)
|
||||
fd_func = self.find_func_in_module(mod, fd_key)
|
||||
if fd_func is not None:
|
||||
fd_cls = fd_cn
|
||||
break
|
||||
if fd_func is None or fd_cls is None:
|
||||
return None
|
||||
# 扩展类结构体必须已注册(GEP/临时影子需要类型)
|
||||
fd_sty: llvmlite.LLVMType | t.CPtr = self.Gen.StructGen.get_struct_type(fd_cls)
|
||||
if fd_sty is None:
|
||||
return None
|
||||
# 扩展类字段数:有字段(_str)时 self 用影子结构体指针;
|
||||
# 无字段(_Type)时 self 用对象值 bitcast 到扩展类指针(对齐 TPC L2856-2876)
|
||||
fd_entry_fd: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct_by_type(fd_sty)
|
||||
fd_has_fields: int = 0
|
||||
if fd_entry_fd is not None and fd_entry_fd.FieldCount > 0:
|
||||
fd_has_fields = 1
|
||||
# self 参数:优先使用已有影子 {var}__meta__(fd2 创建,仅当扩展类有字段时)
|
||||
fd_self: llvmlite.Value | t.CPtr = None
|
||||
if fd_at.value.kind() == ast.ASTKind.Name:
|
||||
fd_onm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(fd_at.value)
|
||||
if fd_onm.id is not None:
|
||||
# pool 持久缓冲(f-string 栈缓冲在函数返回后失效)
|
||||
fd_mn: str = pool.alloc(256)
|
||||
if fd_mn is not None:
|
||||
viperlib.snprintf(fd_mn, 256, "%s__meta__", fd_onm.id)
|
||||
fd_meta: llvmlite.Value | t.CPtr = self.Gen.VarGen.lookup_current(
|
||||
trans.SymTab, fd_mn)
|
||||
if fd_meta is not None and fd_has_fields != 0:
|
||||
fd_self = fd_meta
|
||||
if fd_self is None:
|
||||
if fd_has_fields != 0:
|
||||
# 有字段扩展类且无影子(字符串字面量等):入口创建临时影子并初始化
|
||||
# 先确保 _str 完整定义(跨模块结构体默认 opaque,alloca 报 unsized)
|
||||
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, fd_sty)
|
||||
fd_self = self.Gen.VarGen._alloca_at_entry(builder, fd_sty)
|
||||
if fd_self is None:
|
||||
return None
|
||||
fd_obj_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
|
||||
builder, pool, mod, fd_at.value, None, 0, trans)
|
||||
if fd_obj_val is not None:
|
||||
fd_dfe: GenTypes.FieldEntry | t.CPtr = \
|
||||
self.Gen.StructGen.lookup_field(fd_sty, "__data__")
|
||||
if fd_dfe is not None and fd_dfe.Ty is not None:
|
||||
fd_dp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
|
||||
builder, fd_sty, fd_dfe.Ty, fd_self, fd_dfe.Index)
|
||||
if fd_dp is not None:
|
||||
llvmlite.build_store(builder, fd_obj_val, fd_dp)
|
||||
fd_bfe: GenTypes.FieldEntry | t.CPtr = \
|
||||
self.Gen.StructGen.lookup_field(fd_sty, "__mbuddy__")
|
||||
if fd_bfe is not None and fd_bfe.Ty is not None:
|
||||
fd_bp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
|
||||
builder, fd_sty, fd_bfe.Ty, fd_self, fd_bfe.Index)
|
||||
fd_null: llvmlite.Value | t.CPtr = llvmlite.ConstNull(
|
||||
pool, fd_bfe.Ty, "null")
|
||||
if fd_bp is not None and fd_null is not None:
|
||||
llvmlite.build_store(builder, fd_null, fd_bp)
|
||||
# FakeDuck: with 上下文自动注入 requires 字段(如 __mbuddy__)
|
||||
self._inject_requires_fields(
|
||||
trans, pool, builder, mod, fd_self, fd_cls)
|
||||
else:
|
||||
# 无字段扩展类(_Type):对象值 bitcast 到扩展类指针
|
||||
fd_obj_v: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
|
||||
builder, pool, mod, fd_at.value, None, 0, trans)
|
||||
if fd_obj_v is None:
|
||||
return None
|
||||
fd_self = llvmlite.build_bitcast(
|
||||
builder, fd_obj_v, llvmlite.Ptr(pool, fd_sty))
|
||||
if fd_self is None:
|
||||
return None
|
||||
# 构建参数链表: self → 其余参数
|
||||
llvmlite.value_set_next(fd_self, None)
|
||||
fd_head: llvmlite.Value | t.CPtr = fd_self
|
||||
fd_tail: llvmlite.Value | t.CPtr = fd_self
|
||||
fd_args: list[ast.AST | t.CPtr] | t.CPtr = cl.args
|
||||
fd_can: int = 0
|
||||
if fd_args is not None:
|
||||
fd_can = len(fd_args)
|
||||
for fd_ai in range(fd_can):
|
||||
fd_arg: ast.AST | t.CPtr = fd_args.get(fd_ai)
|
||||
if fd_arg is not None:
|
||||
fd_av: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
|
||||
builder, pool, mod, fd_arg, None, 0, trans)
|
||||
# char 常量参数 → 单字符字符串(char 隐式转 str,
|
||||
# 如 s1.split(','):',' 是 i32 值 44,传给 str 参数须先字符串化,
|
||||
# 否则运行时 strlen/strncmp 解引用 44 崩溃)
|
||||
if fd_arg.kind() == ast.ASTKind.Constant:
|
||||
fd_ac: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(fd_arg)
|
||||
if fd_ac.const_kind == ast.CONST_CHAR:
|
||||
ch_buf: str = pool.alloc(2)
|
||||
if ch_buf is not None:
|
||||
ch_buf[0] = t.CChar(fd_ac.int_val)
|
||||
ch_buf[1] = '\0'
|
||||
fd_av = self.Gen.ExprGenConst.create_global_string(
|
||||
builder, pool, mod, ch_buf, trans)
|
||||
if fd_av is not None:
|
||||
llvmlite.value_set_next(fd_av, None)
|
||||
llvmlite.value_set_next(fd_tail, fd_av)
|
||||
fd_tail = fd_av
|
||||
# 返回类型与调用名(来自 find_func_in_module 命中的函数定义)
|
||||
fd_ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(fd_func)
|
||||
if fd_ret_ty is None:
|
||||
fd_ret_ty = llvmlite.Int32(pool)
|
||||
fd_fname: str = llvmlite.function_get_name(fd_func)
|
||||
if fd_fname is None:
|
||||
return None
|
||||
# 返回类型精确化:跨模块 declare 的 list[T] 特化返回类型可能被简化
|
||||
# 为 Ptr(i8),调用方变量 alloca 类型随之退化 → parts[0] 走字符下标
|
||||
# 路径而非 list 内联 __getitem__(printf %s 解引用字符值崩溃)。
|
||||
# 从定义模块 text.ll 读取精确返回类型(对齐普通方法调用 _translate_method_call)。
|
||||
fd_sha1: str = pool.alloc(17)
|
||||
if fd_sha1 is not None:
|
||||
string.strncpy(fd_sha1, fd_fname, 16)
|
||||
fd_sha1[16] = '\0'
|
||||
fd_exact: llvmlite.LLVMType | t.CPtr = self._LookupMethodRetTyFromTextLL(
|
||||
pool, fd_sha1, fd_cls, method_name)
|
||||
if fd_exact is not None:
|
||||
fd_ret_ty = fd_exact
|
||||
fd_total: int = 1 + fd_can
|
||||
return llvmlite.build_call(builder, fd_fname, fd_head, fd_total, fd_ret_ty, 0)
|
||||
# ============================================================
|
||||
# _inject_requires_fields - FakeDuck: with 上下文注入 requires 字段
|
||||
#
|
||||
# 对齐 TPC HandlesExprCall.py L4021-4079:
|
||||
# 对类 __requires__ 元数据(fd1 注册)中的每个字段,运行时调用
|
||||
# _find_provider(field) 查找 with 上下文提供的指针;非 NULL 时
|
||||
# bitcast 到字段类型写入 meta_ptr 对应槽位(条件注入,避免覆盖
|
||||
# 用户已手动设置的值)。_find_provider 未注册(未 import
|
||||
# _withcontent)时跳过注入,不影响非 with 场景。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _inject_requires_fields(self, trans: HT.Translator | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
meta_ptr: llvmlite.Value | t.CPtr,
|
||||
class_name: str) -> int:
|
||||
"""在 with 上下文注入 requires 字段,返回注入字段数"""
|
||||
if trans is None or pool is None or builder is None or mod is None:
|
||||
return 0
|
||||
if meta_ptr is None or class_name is None:
|
||||
return 0
|
||||
# _withcontent._find_provider(跨模块):仅当本模块可见(_withcontent
|
||||
# 被 import,vpi stub declare 已注入)时才注入。对齐 TPC L4048-4050
|
||||
# (Gen.functions.get('_find_provider') 不存在则跳过)——否则非 with
|
||||
# 项目(如 HashTableTest 未 import _withcontent)也会为每个 _str(...)
|
||||
# 构造发射 {sha1}._find_provider 调用 → ld.lld undefined symbol。
|
||||
fd_fn_probe: llvmlite.Function | t.CPtr = self.find_func_in_module(
|
||||
mod, "_find_provider")
|
||||
if fd_fn_probe is None:
|
||||
return 0
|
||||
fd_fname: str = llvmlite.function_get_name(fd_fn_probe)
|
||||
if fd_fname is None:
|
||||
return 0
|
||||
cnt: int = self.Gen.ClassGenBase.class_meta_count(
|
||||
GenTypes.CLASS_META_REQUIRES, class_name)
|
||||
if cnt <= 0:
|
||||
return 0
|
||||
sty: llvmlite.LLVMType | t.CPtr = self.Gen.StructGen.get_struct_type(class_name)
|
||||
if sty is None:
|
||||
return 0
|
||||
i8_ty_j: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
if i8_ty_j is None:
|
||||
return 0
|
||||
i8_ptr_ty_j: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_j)
|
||||
if i8_ptr_ty_j is None:
|
||||
return 0
|
||||
cur_func: llvmlite.Function | t.CPtr = trans._cur_func
|
||||
if cur_func is None:
|
||||
return 0
|
||||
injected: int = 0
|
||||
for ji in range(cnt):
|
||||
fname: str = self.Gen.ClassGenBase.class_meta_field_at(
|
||||
GenTypes.CLASS_META_REQUIRES, class_name, ji)
|
||||
if fname is None:
|
||||
continue
|
||||
fe: GenTypes.FieldEntry | t.CPtr = self.Gen.StructGen.lookup_field(
|
||||
sty, fname)
|
||||
if fe is None or fe.Ty is None:
|
||||
continue
|
||||
# 参数:字段名字符串(i8*)
|
||||
fd_fstr: llvmlite.Value | t.CPtr = self.Gen.ExprGenConst.create_global_string(
|
||||
builder, pool, mod, fname, trans)
|
||||
if fd_fstr is None:
|
||||
continue
|
||||
llvmlite.value_set_next(fd_fstr, None)
|
||||
self._ensure_method_declare(
|
||||
pool, mod, fd_fname, i8_ptr_ty_j, fd_fstr, 1)
|
||||
fd_ptr: llvmlite.Value | t.CPtr = llvmlite.build_call(
|
||||
builder, fd_fname, fd_fstr, 1, i8_ptr_ty_j, 0)
|
||||
if fd_ptr is None:
|
||||
continue
|
||||
# 条件注入:ptr != NULL 才写入(保留用户手动设置的值)
|
||||
fd_null: llvmlite.Value | t.CPtr = llvmlite.ConstNull(
|
||||
pool, i8_ptr_ty_j, "null")
|
||||
if fd_null is None:
|
||||
continue
|
||||
fd_cmp: llvmlite.Value | t.CPtr = llvmlite.build_icmp(
|
||||
builder, llvmlite.ICMP_NE, fd_ptr, fd_null)
|
||||
if fd_cmp is None:
|
||||
continue
|
||||
# 块名唯一化(create_block 不自动编号,同名 label 在文本 IR 中
|
||||
# 冲突 → llc "Terminator found in the middle of a basic block")
|
||||
vtc2: int = trans._label_counter
|
||||
trans._label_counter = vtc2 + 1
|
||||
fd_bb_buf2: str = pool.alloc(64)
|
||||
if fd_bb_buf2 is None:
|
||||
continue
|
||||
viperlib.snprintf(fd_bb_buf2, 64, "fd.skip.%d", vtc2)
|
||||
fd_skip_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
|
||||
pool, cur_func, fd_bb_buf2)
|
||||
viperlib.snprintf(fd_bb_buf2, 64, "fd.inject.%d", vtc2)
|
||||
fd_inject_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
|
||||
pool, cur_func, fd_bb_buf2)
|
||||
if fd_skip_bb is None or fd_inject_bb is None:
|
||||
continue
|
||||
llvmlite.build_cond_br(builder, fd_cmp, fd_inject_bb, fd_skip_bb)
|
||||
# inject 块:bitcast + GEP + store,跳回 skip
|
||||
llvmlite.position_at_end(builder, fd_inject_bb)
|
||||
fd_cast: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||||
builder, fd_ptr, fe.Ty)
|
||||
if fd_cast is not None:
|
||||
fd_fp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
|
||||
builder, sty, fe.Ty, meta_ptr, fe.Index)
|
||||
if fd_fp is not None:
|
||||
llvmlite.build_store(builder, fd_cast, fd_fp)
|
||||
llvmlite.build_br(builder, fd_skip_bb)
|
||||
# skip 块:恢复 CurBlock,继续后续代码生成
|
||||
llvmlite.position_at_end(builder, fd_skip_bb)
|
||||
injected += 1
|
||||
return injected
|
||||
# ============================================================
|
||||
# _emit_provider_push / _emit_provider_pop - FakeDuck: with 上下文
|
||||
# provider push/pop(__provides__ 元数据,fd1 注册)
|
||||
#
|
||||
# 对齐 TPC HandlesWith.py L138-174:
|
||||
# with 进入时对每个提供字段生成 _push_provider(field_str, ctx_i8);
|
||||
# 退出时生成等量 _pop_provider()。运行时 _withcontent 模块负责
|
||||
# 维护 TLS provider 栈,供 _inject_requires_fields 查找。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _emit_provider_push(self, trans: HT.Translator | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cls_name: str,
|
||||
ctx_val: llvmlite.Value | t.CPtr) -> int:
|
||||
"""生成 _push_provider(field, ctx_i8) 调用(每提供字段一次),返回字段数"""
|
||||
if trans is None or pool is None or builder is None or mod is None:
|
||||
return 0
|
||||
if cls_name is None or ctx_val is None:
|
||||
return 0
|
||||
fd_pc: int = self.Gen.ClassGenBase.class_meta_count(
|
||||
GenTypes.CLASS_META_PROVIDES, cls_name)
|
||||
if fd_pc <= 0:
|
||||
return 0
|
||||
# _withcontent._push_provider(跨模块,同 _find_provider 的可见性守卫:
|
||||
# 本模块未 import _withcontent 时跳过,避免 undefined symbol)
|
||||
fd_pfn_probe: llvmlite.Function | t.CPtr = self.find_func_in_module(
|
||||
mod, "_push_provider")
|
||||
if fd_pfn_probe is None:
|
||||
return 0
|
||||
fd_pfn: str = llvmlite.function_get_name(fd_pfn_probe)
|
||||
if fd_pfn is None:
|
||||
return 0
|
||||
i8_ty_p: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
if i8_ty_p is None:
|
||||
return 0
|
||||
i8_ptr_ty_p: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_p)
|
||||
if i8_ptr_ty_p is None:
|
||||
return 0
|
||||
ret_i32_p: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
if ret_i32_p is None:
|
||||
return 0
|
||||
# ctx 值 bitcast 到 i8*(provider 栈存 void*)
|
||||
fd_ctx_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||||
builder, ctx_val, i8_ptr_ty_p)
|
||||
if fd_ctx_i8 is None:
|
||||
return 0
|
||||
for pi in range(fd_pc):
|
||||
fname: str = self.Gen.ClassGenBase.class_meta_field_at(
|
||||
GenTypes.CLASS_META_PROVIDES, cls_name, pi)
|
||||
if fname is None:
|
||||
continue
|
||||
fd_fstr: llvmlite.Value | t.CPtr = self.Gen.ExprGenConst.create_global_string(
|
||||
builder, pool, mod, fname, trans)
|
||||
if fd_fstr is None:
|
||||
continue
|
||||
llvmlite.value_set_next(fd_fstr, fd_ctx_i8)
|
||||
llvmlite.value_set_next(fd_ctx_i8, None)
|
||||
self._ensure_method_declare(
|
||||
pool, mod, fd_pfn, ret_i32_p, fd_fstr, 2)
|
||||
llvmlite.build_call(builder, fd_pfn, fd_fstr, 2, ret_i32_p, 0)
|
||||
return fd_pc
|
||||
def _emit_provider_pop(self, trans: HT.Translator | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cls_name: str) -> int:
|
||||
"""生成 _pop_provider() 调用(每提供字段一次),返回字段数"""
|
||||
if trans is None or pool is None or builder is None or mod is None:
|
||||
return 0
|
||||
if cls_name is None:
|
||||
return 0
|
||||
fd_pc: int = self.Gen.ClassGenBase.class_meta_count(
|
||||
GenTypes.CLASS_META_PROVIDES, cls_name)
|
||||
if fd_pc <= 0:
|
||||
return 0
|
||||
# _withcontent._pop_provider(跨模块,同 _find_provider 的可见性守卫:
|
||||
# 本模块未 import _withcontent 时跳过,避免 undefined symbol)
|
||||
fd_pon_probe: llvmlite.Function | t.CPtr = self.find_func_in_module(
|
||||
mod, "_pop_provider")
|
||||
if fd_pon_probe is None:
|
||||
return 0
|
||||
fd_pon: str = llvmlite.function_get_name(fd_pon_probe)
|
||||
if fd_pon is None:
|
||||
return 0
|
||||
ret_i32_q: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
if ret_i32_q is None:
|
||||
return 0
|
||||
self._ensure_method_declare(pool, mod, fd_pon, ret_i32_q, None, 0)
|
||||
for _pi in range(fd_pc):
|
||||
llvmlite.build_call(builder, fd_pon, None, 0, ret_i32_q, 0)
|
||||
return fd_pc
|
||||
+1305
-1312
File diff suppressed because it is too large.
Load diff
+558
-567
File diff suppressed because it is too large.
Load diff
+1151
-1162
File diff suppressed because it is too large.
Load diff
+412
-419
@@ -1,420 +1,413 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import sys
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
import lib.core.Gen.CallGenBase as CallGenBase
|
||||
|
||||
# ============================================================
|
||||
# CallGenProp - CallGenMixin 拆分(阶段 B):属性访问(getter/setter/deleter / 静态类调用 / list 内置方法)
|
||||
#
|
||||
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class CallGenProp(CallGenBase.CallGenBase):
|
||||
"""属性访问(getter/setter/deleter / 静态类调用 / list 内置方法)"""
|
||||
|
||||
# ============================================================
|
||||
# _ensure_method_declare - 为跨模块方法调用创建 declare 声明
|
||||
#
|
||||
# 当 found_func 为 None(stub 未注入或跨模块调用)时,
|
||||
# 在当前模块中创建函数声明,避免 llc 报 undefined value。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# 属性方法(@property/@x.setter/@x.deleter)与静态/类方法调用辅助
|
||||
#
|
||||
# 元数据表由 HandlesClassDef 在类翻译/预注册阶段填充,
|
||||
# 这里负责把 obj.prop / obj.prop=v / del obj.prop / Class.method()
|
||||
# 翻译为对应的 {sha1}.ClassName.prop 系列函数调用。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# _translate_property_call — 翻译属性方法调用
|
||||
#
|
||||
# 与 _translate_method_call 的调用名/返回类型解析逻辑一致:
|
||||
# 1. 优先用模块中已有的函数(精确/后缀匹配,来自 stub 注入)
|
||||
# 2. 否则用类所属模块的 SHA1 构造 "{sha1}.ClassName.method" 调用名
|
||||
# 3. 返回类型:函数实类型 → text.ll 查找 → 按方法名推断(默认 i32)
|
||||
#
|
||||
# call_head/call_count: 已构建好的参数链表(如 getter 只有 obj 一个参数)
|
||||
# ============================================================
|
||||
def _translate_property_call(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
class_name: str,
|
||||
method_name: str,
|
||||
call_head: llvmlite.Value | t.CPtr,
|
||||
call_count: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译属性/静态方法调用,返回 call 结果 Value"""
|
||||
if pool is None or builder is None or class_name is None or method_name is None:
|
||||
return None
|
||||
|
||||
# 构造查找名: ClassName.method_name
|
||||
lookup_name: str = pool.alloc(128)
|
||||
if lookup_name is None:
|
||||
return None
|
||||
viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, method_name)
|
||||
|
||||
# 查找函数(精确/后缀匹配)
|
||||
found_func: llvmlite.Function | t.CPtr = self.find_func_in_module(mod, lookup_name)
|
||||
|
||||
# 确定调用名
|
||||
call_name: str = lookup_name
|
||||
if found_func is not None:
|
||||
found_name: str = llvmlite.function_get_name(found_func)
|
||||
if found_name is not None:
|
||||
call_name = found_name
|
||||
else:
|
||||
# 未找到:用类所属模块的 SHA1 构造调用名
|
||||
cls_sha1_pc: str = HandlesStruct.get_struct_sha1(class_name)
|
||||
if cls_sha1_pc is not None:
|
||||
mlen_pc: t.CSizeT = string.strlen(cls_sha1_pc) + string.strlen(lookup_name) + 2
|
||||
mangled_pc: str = pool.alloc(mlen_pc)
|
||||
if mangled_pc is not None:
|
||||
viperlib.snprintf(mangled_pc, mlen_pc, "%s.%s", cls_sha1_pc, lookup_name)
|
||||
call_name = mangled_pc
|
||||
|
||||
# 确定返回类型
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
call_ret_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||||
if found_func is not None:
|
||||
frt: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(found_func)
|
||||
if frt is not None:
|
||||
call_ret_ty = frt
|
||||
else:
|
||||
sp_ty1: llvmlite.LLVMType | t.CPtr = self._special_method_ret_ty(pool, class_name, method_name)
|
||||
if sp_ty1 is not None:
|
||||
call_ret_ty = sp_ty1
|
||||
else:
|
||||
cls_sha1_rt: str = HandlesStruct.get_struct_sha1(class_name)
|
||||
looked_up_ty: llvmlite.LLVMType | t.CPtr = self._LookupMethodRetTyFromTextLL(
|
||||
pool, cls_sha1_rt, class_name, method_name)
|
||||
if looked_up_ty is not None:
|
||||
call_ret_ty = looked_up_ty
|
||||
else:
|
||||
# 精确查找:vpi stub 返回注解缓存(方法定义处,不硬编码白名单)
|
||||
vpi_ret_ty: llvmlite.LLVMType | t.CPtr = self._lookup_method_ret_ty_via_vpi(
|
||||
pool, cls_sha1_rt, class_name, method_name)
|
||||
if vpi_ret_ty is not None:
|
||||
call_ret_ty = vpi_ret_ty
|
||||
else:
|
||||
# Phase A 依赖未就绪(cls_sha1_rt None / 定义模块 text.ll 未生成):
|
||||
# 标记 pending 下遍重译(对齐 _translate_method_call L4783-4790),
|
||||
# 绝不 fail-fast 中断多遍收敛;真实错误由收敛检查兜底。
|
||||
if cls_sha1_rt is None \
|
||||
or self._dep_text_ll_exists(pool, cls_sha1_rt) == 0:
|
||||
if trans is not None:
|
||||
trans._deps_pending = 1
|
||||
# 依赖未就绪:保持默认 i32(build_call(Void) 返回 None
|
||||
# 会破坏表达式翻译;pending 文件本遍不写盘,下遍重译)
|
||||
call_ret_ty = llvmlite.Int32(pool)
|
||||
else:
|
||||
call_ret_ty = self._fail_method_ret_ty(method_name)
|
||||
|
||||
# 参数类型对齐:按目标函数声明的参数类型转换实参(与 _translate_method_call
|
||||
# 一致)。例如 from_long(10) 的 i32 字面量 → i64 形参(v: t.CLong),
|
||||
# 不转换则 call(i32) 与 declare(i64) 不匹配,llc 报参数类型错误。
|
||||
# 目标函数优先用已找到的 found_func,否则按 mangled 调用名查模块 declare。
|
||||
tgt_func_pc: llvmlite.Function | t.CPtr = found_func
|
||||
if tgt_func_pc is None:
|
||||
tgt_func_pc = self.find_func_in_module(mod, call_name)
|
||||
if tgt_func_pc is not None:
|
||||
prev_pc: llvmlite.Value | t.CPtr = None
|
||||
cur_arg_pc: llvmlite.Value | t.CPtr = call_head
|
||||
cur_param_pc: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(tgt_func_pc)
|
||||
while cur_arg_pc is not None and cur_param_pc is not None:
|
||||
param_ty_pc: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(cur_param_pc)
|
||||
if param_ty_pc is not None and cur_arg_pc.Ty is not None:
|
||||
coerced_pc: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type(
|
||||
builder, cur_arg_pc, param_ty_pc)
|
||||
if coerced_pc is not None and coerced_pc != cur_arg_pc:
|
||||
# 保持链表完整性:新 Value 继承原节点的 Next,前驱指向新节点
|
||||
llvmlite.value_set_next(coerced_pc, cur_arg_pc.Next)
|
||||
if prev_pc is None:
|
||||
call_head = coerced_pc
|
||||
else:
|
||||
llvmlite.value_set_next(prev_pc, coerced_pc)
|
||||
cur_arg_pc = coerced_pc
|
||||
prev_pc = cur_arg_pc
|
||||
cur_arg_pc = cur_arg_pc.Next
|
||||
cur_param_pc = llvmlite.param_get_next(cur_param_pc)
|
||||
|
||||
# 确保 declare 存在,然后调用
|
||||
self._ensure_method_declare(pool, mod, call_name, call_ret_ty, call_head, call_count)
|
||||
return llvmlite.build_call(builder, call_name, call_head, call_count, call_ret_ty, 0)
|
||||
# ============================================================
|
||||
# _resolve_obj_class_name — 解析对象表达式的类名(短名)
|
||||
#
|
||||
# 优先从变量注解(AnnotClassName)解析(如 "memhub.MemBuddy" → "MemBuddy"),
|
||||
# 失败时从 LLVM 类型解析(Ptr(Struct) → 类名)。
|
||||
# 供属性访问/赋值/删除识别 property 时使用。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _resolve_obj_class_name(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
obj_node: ast.AST | t.CPtr) -> str:
|
||||
"""解析对象表达式的类名(短名),失败返回 None"""
|
||||
if pool is None or trans is None or obj_node is None:
|
||||
return None
|
||||
if obj_node.kind() == ast.ASTKind.Name:
|
||||
obj_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(obj_node)
|
||||
if obj_nm.id is not None:
|
||||
var_entry: HandlesVar.VarEntry | t.CPtr = HandlesVar.lookup_var_entry(
|
||||
trans.SymTab, obj_nm.id)
|
||||
if var_entry is not None and var_entry.AnnotClassName is not None:
|
||||
annot_val: str = var_entry.AnnotClassName
|
||||
dot_ptr: str = string.strrchr(annot_val, '.')
|
||||
if dot_ptr is not None:
|
||||
return dot_ptr + 1
|
||||
return annot_val
|
||||
return None
|
||||
# ============================================================
|
||||
# _try_property_getter_attr — 尝试将 obj.attr 翻译为 property getter 调用
|
||||
#
|
||||
# 检查 obj 的类是否有 @property/@x.getter 的 attr 方法;
|
||||
# 若有则生成 call Class.attr(obj) 并返回调用结果 Value;否则返回 None。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _try_property_getter_attr(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
at_node: ast.Attribute | t.CPtr,
|
||||
obj_ptr: llvmlite.Value | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
fallback_class_name: str = None) -> llvmlite.Value | t.CPtr:
|
||||
"""尝试 property getter 属性访问,返回调用结果 Value;非 getter 返回 None
|
||||
|
||||
fallback_class_name: 对象表达式非 Name 时从 LLVM 类型解析出的类名兜底。
|
||||
"""
|
||||
if at_node is None or at_node.attr is None or obj_ptr is None or trans is None:
|
||||
return None
|
||||
class_name: str = self._resolve_obj_class_name(pool, trans, at_node.value)
|
||||
if class_name is None:
|
||||
class_name = fallback_class_name
|
||||
if class_name is None:
|
||||
return None
|
||||
meta: int = HandlesClassDef.lookup_method_meta(class_name, at_node.attr)
|
||||
if meta & HandlesClassDef.META_PROP_GETTER == 0:
|
||||
return None
|
||||
# 单参数调用: obj → getter
|
||||
llvmlite.value_set_next(obj_ptr, None)
|
||||
return self._translate_property_call(
|
||||
pool, builder, mod, class_name, at_node.attr, obj_ptr, 1, trans)
|
||||
# ============================================================
|
||||
# _try_property_setter — 尝试将 obj.attr = v 翻译为 property setter 调用
|
||||
#
|
||||
# 检查 obj 的类是否有 @x.setter 的 attr 方法;
|
||||
# 若有则生成 call Class.attr$set(obj, v),返回 1;否则返回 0。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _try_property_setter(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
target_attr: ast.Attribute | t.CPtr,
|
||||
rhs_val: llvmlite.Value | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> int:
|
||||
"""尝试 property setter 赋值,返回 1=已处理(生成调用)"""
|
||||
if pool is None or builder is None or mod is None or trans is None:
|
||||
return 0
|
||||
if target_attr is None or target_attr.attr is None or rhs_val is None:
|
||||
return 0
|
||||
class_name: str = self._resolve_obj_class_name(pool, trans, target_attr.value)
|
||||
if class_name is None:
|
||||
return 0
|
||||
meta: int = HandlesClassDef.lookup_method_meta(class_name, target_attr.attr)
|
||||
if meta & HandlesClassDef.META_PROP_SETTER == 0:
|
||||
return 0
|
||||
# 翻译对象值(self 参数)
|
||||
obj_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, target_attr.value, None, 0, trans)
|
||||
if obj_val is None:
|
||||
return 0
|
||||
# 构建参数链表: obj → rhs
|
||||
llvmlite.value_set_next(obj_val, None)
|
||||
llvmlite.value_set_next(rhs_val, None)
|
||||
llvmlite.value_set_next(obj_val, rhs_val)
|
||||
# setter 函数名带 $set 后缀
|
||||
setter_name_buf: str = pool.alloc(128)
|
||||
if setter_name_buf is None:
|
||||
return 0
|
||||
viperlib.snprintf(setter_name_buf, 128, "%s$set", target_attr.attr)
|
||||
self._translate_property_call(pool, builder, mod, class_name,
|
||||
setter_name_buf, obj_val, 2, trans)
|
||||
return 1
|
||||
# ============================================================
|
||||
# _try_property_deleter — 尝试将 del obj.attr 翻译为 property deleter 调用
|
||||
#
|
||||
# 检查 obj 的类是否有 @x.deleter 的 attr 方法;
|
||||
# 若有则生成 call Class.attr$del(obj),返回 1;否则返回 0。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _try_property_deleter(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
target_attr: ast.Attribute | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> int:
|
||||
"""尝试 property deleter 删除,返回 1=已处理(生成调用)"""
|
||||
if pool is None or builder is None or mod is None or trans is None:
|
||||
return 0
|
||||
if target_attr is None or target_attr.attr is None:
|
||||
return 0
|
||||
class_name: str = self._resolve_obj_class_name(pool, trans, target_attr.value)
|
||||
if class_name is None:
|
||||
return 0
|
||||
meta: int = HandlesClassDef.lookup_method_meta(class_name, target_attr.attr)
|
||||
if meta & HandlesClassDef.META_PROP_DELETER == 0:
|
||||
return 0
|
||||
# 翻译对象值(self 参数)
|
||||
obj_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, target_attr.value, None, 0, trans)
|
||||
if obj_val is None:
|
||||
return 0
|
||||
llvmlite.value_set_next(obj_val, None)
|
||||
# deleter 函数名带 $del 后缀
|
||||
del_name_buf: str = pool.alloc(128)
|
||||
if del_name_buf is None:
|
||||
return 0
|
||||
viperlib.snprintf(del_name_buf, 128, "%s$del", target_attr.attr)
|
||||
self._translate_property_call(pool, builder, mod, class_name,
|
||||
del_name_buf, obj_val, 1, trans)
|
||||
return 1
|
||||
# ============================================================
|
||||
# _translate_static_class_call — 翻译 ClassName.method(args) 静态/类方法调用
|
||||
#
|
||||
# @staticmethod: 直接 call Class.method(args...),无 self
|
||||
# @classmethod: 在参数前插入栈上分配的类实例指针(与 TPC 一致)
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _translate_static_class_call(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
class_name: str,
|
||||
method_name: str,
|
||||
cl: ast.Call | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译类名静态/类方法调用,返回 call 结果 Value;非静态/类方法返回 None"""
|
||||
if pool is None or builder is None or mod is None or trans is None:
|
||||
return None
|
||||
if class_name is None or method_name is None or cl is None:
|
||||
return None
|
||||
meta: int = HandlesClassDef.lookup_method_meta(class_name, method_name)
|
||||
is_static: int = 0
|
||||
is_class: int = 0
|
||||
if meta & HandlesClassDef.META_STATIC != 0:
|
||||
is_static = 1
|
||||
if meta & HandlesClassDef.META_CLASS != 0:
|
||||
is_class = 1
|
||||
if is_static == 0 and is_class == 0:
|
||||
return None
|
||||
|
||||
# 构建参数链表
|
||||
head: llvmlite.Value | t.CPtr = None
|
||||
total_count: int = 0
|
||||
|
||||
# @classmethod: 插入栈上分配的类实例指针作为 cls 参数
|
||||
if is_class != 0:
|
||||
struct_ty_cc: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(class_name)
|
||||
if struct_ty_cc is None:
|
||||
return None
|
||||
cls_ptr: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, struct_ty_cc)
|
||||
if cls_ptr is None:
|
||||
return None
|
||||
llvmlite.value_set_next(cls_ptr, None)
|
||||
head = cls_ptr
|
||||
total_count = 1
|
||||
|
||||
# 翻译调用参数
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args
|
||||
can: t.CSizeT = 0
|
||||
if cargs is not None:
|
||||
can = len(cargs)
|
||||
tail: llvmlite.Value | t.CPtr = head
|
||||
for ai in range(can):
|
||||
arg_node: ast.AST | t.CPtr = cargs.get(ai)
|
||||
if arg_node is None:
|
||||
continue
|
||||
arg_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, arg_node, None, 0, trans)
|
||||
if arg_val is None:
|
||||
continue
|
||||
llvmlite.value_set_next(arg_val, None)
|
||||
if head is None:
|
||||
head = arg_val
|
||||
tail = arg_val
|
||||
else:
|
||||
llvmlite.value_set_next(tail, arg_val)
|
||||
tail = arg_val
|
||||
total_count += 1
|
||||
|
||||
# 零参 @staticmethod(如 PyListObj.new()):head 保持 None 是合法的
|
||||
# 无参调用,照常走 _translate_property_call(SHA1 前缀名 + 精确返回类型)。
|
||||
# 若此处 return None,调用方回退通用路径把方法名当裸函数解析,生成
|
||||
# call i32 @new() → 链接 undefined reference(CPythonTest 根因)。
|
||||
# @classmethod 恒有 cls_ptr(head 非 None),不受影响。
|
||||
return self._translate_property_call(pool, builder, mod, class_name,
|
||||
method_name, head, total_count, trans)
|
||||
# ============================================================
|
||||
# _is_list_builtin_method - 判断是否是 list 泛型内置容器方法
|
||||
#
|
||||
# list[T] 是内置泛型容器(_list.vp),其方法(append/get/set/pop/clear/
|
||||
# __iter__/__len__/__getitem__/__setitem__)由 translate_call 的 list
|
||||
# 内置分支内联 GEP 处理,不注册为方法函数。若 obj.method() 检测把
|
||||
# list 特化 struct(如 list[AST | CPtr])误当普通结构体走
|
||||
# _translate_method_call,会查不到 append 返回类型 → fail-fast
|
||||
# (NewAstTest body.append 根因)。此判断用于跳过 method_call 路径。
|
||||
#
|
||||
# 返回: 1=list 内置方法(应落到 list 内置分支),0=普通方法
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _is_list_builtin_method(self, class_name: str,
|
||||
method_name: str) -> int:
|
||||
"""判断 (class_name, method_name) 是否是 list 泛型内置方法"""
|
||||
if class_name is None or method_name is None:
|
||||
return 0
|
||||
# 类名必须以 "list" 开头(list / list[AST | CPtr] 特化名)
|
||||
if string.strncmp(class_name, "list", 4) != 0:
|
||||
return 0
|
||||
# 方法名必须是 list 内置方法集合
|
||||
if string.strcmp(method_name, "append") == 0: return 1
|
||||
if string.strcmp(method_name, "get") == 0: return 1
|
||||
if string.strcmp(method_name, "set") == 0: return 1
|
||||
if string.strcmp(method_name, "pop") == 0: return 1
|
||||
if string.strcmp(method_name, "clear") == 0: return 1
|
||||
if string.strcmp(method_name, "__iter__") == 0: return 1
|
||||
if string.strcmp(method_name, "__len__") == 0: return 1
|
||||
if string.strcmp(method_name, "__getitem__") == 0: return 1
|
||||
if string.strcmp(method_name, "__setitem__") == 0: return 1
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import sys
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
import lib.core.Gen.CallGenBase as CallGenBase
|
||||
|
||||
# ============================================================
|
||||
# CallGenProp - CallGenMixin 拆分(阶段 B):属性访问(getter/setter/deleter / 静态类调用 / list 内置方法)
|
||||
#
|
||||
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class CallGenProp(CallGenBase.CallGenBase):
|
||||
"""属性访问(getter/setter/deleter / 静态类调用 / list 内置方法)"""
|
||||
|
||||
# ============================================================
|
||||
# _ensure_method_declare - 为跨模块方法调用创建 declare 声明
|
||||
#
|
||||
# 当 found_func 为 None(stub 未注入或跨模块调用)时,
|
||||
# 在当前模块中创建函数声明,避免 llc 报 undefined value。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# 属性方法(@property/@x.setter/@x.deleter)与静态/类方法调用辅助
|
||||
#
|
||||
# 元数据表由 HandlesClassDef 在类翻译/预注册阶段填充,
|
||||
# 这里负责把 obj.prop / obj.prop=v / del obj.prop / Class.method()
|
||||
# 翻译为对应的 {sha1}.ClassName.prop 系列函数调用。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# _translate_property_call — 翻译属性方法调用
|
||||
#
|
||||
# 与 _translate_method_call 的调用名/返回类型解析逻辑一致:
|
||||
# 1. 优先用模块中已有的函数(精确/后缀匹配,来自 stub 注入)
|
||||
# 2. 否则用类所属模块的 SHA1 构造 "{sha1}.ClassName.method" 调用名
|
||||
# 3. 返回类型:函数实类型 → text.ll 查找 → 按方法名推断(默认 i32)
|
||||
#
|
||||
# call_head/call_count: 已构建好的参数链表(如 getter 只有 obj 一个参数)
|
||||
# ============================================================
|
||||
def _translate_property_call(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
class_name: str,
|
||||
method_name: str,
|
||||
call_head: llvmlite.Value | t.CPtr,
|
||||
call_count: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译属性/静态方法调用,返回 call 结果 Value"""
|
||||
if pool is None or builder is None or class_name is None or method_name is None:
|
||||
return None
|
||||
|
||||
# 构造查找名: ClassName.method_name
|
||||
lookup_name: str = pool.alloc(128)
|
||||
if lookup_name is None:
|
||||
return None
|
||||
viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, method_name)
|
||||
|
||||
# 查找函数(精确/后缀匹配)
|
||||
found_func: llvmlite.Function | t.CPtr = self.find_func_in_module(mod, lookup_name)
|
||||
|
||||
# 确定调用名
|
||||
call_name: str = lookup_name
|
||||
if found_func is not None:
|
||||
found_name: str = llvmlite.function_get_name(found_func)
|
||||
if found_name is not None:
|
||||
call_name = found_name
|
||||
else:
|
||||
# 未找到:用类所属模块的 SHA1 构造调用名
|
||||
cls_sha1_pc: str = self.Gen.StructGen.get_struct_sha1(class_name)
|
||||
if cls_sha1_pc is not None:
|
||||
mlen_pc: t.CSizeT = string.strlen(cls_sha1_pc) + string.strlen(lookup_name) + 2
|
||||
mangled_pc: str = pool.alloc(mlen_pc)
|
||||
if mangled_pc is not None:
|
||||
viperlib.snprintf(mangled_pc, mlen_pc, "%s.%s", cls_sha1_pc, lookup_name)
|
||||
call_name = mangled_pc
|
||||
|
||||
# 确定返回类型
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
call_ret_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||||
if found_func is not None:
|
||||
frt: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(found_func)
|
||||
if frt is not None:
|
||||
call_ret_ty = frt
|
||||
else:
|
||||
sp_ty1: llvmlite.LLVMType | t.CPtr = self._special_method_ret_ty(pool, class_name, method_name)
|
||||
if sp_ty1 is not None:
|
||||
call_ret_ty = sp_ty1
|
||||
else:
|
||||
cls_sha1_rt: str = self.Gen.StructGen.get_struct_sha1(class_name)
|
||||
looked_up_ty: llvmlite.LLVMType | t.CPtr = self._LookupMethodRetTyFromTextLL(
|
||||
pool, cls_sha1_rt, class_name, method_name)
|
||||
if looked_up_ty is not None:
|
||||
call_ret_ty = looked_up_ty
|
||||
else:
|
||||
# 精确查找:vpi stub 返回注解缓存(方法定义处,不硬编码白名单)
|
||||
vpi_ret_ty: llvmlite.LLVMType | t.CPtr = self._lookup_method_ret_ty_via_vpi(
|
||||
pool, cls_sha1_rt, class_name, method_name)
|
||||
if vpi_ret_ty is not None:
|
||||
call_ret_ty = vpi_ret_ty
|
||||
else:
|
||||
# Phase A 依赖未就绪(cls_sha1_rt None / 定义模块 text.ll 未生成):
|
||||
# 标记 pending 下遍重译(对齐 _translate_method_call L4783-4790),
|
||||
# 绝不 fail-fast 中断多遍收敛;真实错误由收敛检查兜底。
|
||||
if cls_sha1_rt is None \
|
||||
or self._dep_text_ll_exists(pool, cls_sha1_rt) == 0:
|
||||
if trans is not None:
|
||||
trans._deps_pending = 1
|
||||
# 依赖未就绪:保持默认 i32(build_call(Void) 返回 None
|
||||
# 会破坏表达式翻译;pending 文件本遍不写盘,下遍重译)
|
||||
call_ret_ty = llvmlite.Int32(pool)
|
||||
else:
|
||||
call_ret_ty = self._fail_method_ret_ty(method_name)
|
||||
|
||||
# 参数类型对齐:按目标函数声明的参数类型转换实参(与 _translate_method_call
|
||||
# 一致)。例如 from_long(10) 的 i32 字面量 → i64 形参(v: t.CLong),
|
||||
# 不转换则 call(i32) 与 declare(i64) 不匹配,llc 报参数类型错误。
|
||||
# 目标函数优先用已找到的 found_func,否则按 mangled 调用名查模块 declare。
|
||||
tgt_func_pc: llvmlite.Function | t.CPtr = found_func
|
||||
if tgt_func_pc is None:
|
||||
tgt_func_pc = self.find_func_in_module(mod, call_name)
|
||||
if tgt_func_pc is not None:
|
||||
prev_pc: llvmlite.Value | t.CPtr = None
|
||||
cur_arg_pc: llvmlite.Value | t.CPtr = call_head
|
||||
cur_param_pc: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(tgt_func_pc)
|
||||
while cur_arg_pc is not None and cur_param_pc is not None:
|
||||
param_ty_pc: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(cur_param_pc)
|
||||
if param_ty_pc is not None and cur_arg_pc.Ty is not None:
|
||||
coerced_pc: llvmlite.Value | t.CPtr = self.Gen.ExprGenBase.coerce_to_type(
|
||||
builder, cur_arg_pc, param_ty_pc)
|
||||
if coerced_pc is not None and coerced_pc != cur_arg_pc:
|
||||
# 保持链表完整性:新 Value 继承原节点的 Next,前驱指向新节点
|
||||
llvmlite.value_set_next(coerced_pc, cur_arg_pc.Next)
|
||||
if prev_pc is None:
|
||||
call_head = coerced_pc
|
||||
else:
|
||||
llvmlite.value_set_next(prev_pc, coerced_pc)
|
||||
cur_arg_pc = coerced_pc
|
||||
prev_pc = cur_arg_pc
|
||||
cur_arg_pc = cur_arg_pc.Next
|
||||
cur_param_pc = llvmlite.param_get_next(cur_param_pc)
|
||||
|
||||
# 确保 declare 存在,然后调用
|
||||
self._ensure_method_declare(pool, mod, call_name, call_ret_ty, call_head, call_count)
|
||||
return llvmlite.build_call(builder, call_name, call_head, call_count, call_ret_ty, 0)
|
||||
# ============================================================
|
||||
# _resolve_obj_class_name — 解析对象表达式的类名(短名)
|
||||
#
|
||||
# 优先从变量注解(AnnotClassName)解析(如 "memhub.MemBuddy" → "MemBuddy"),
|
||||
# 失败时从 LLVM 类型解析(Ptr(Struct) → 类名)。
|
||||
# 供属性访问/赋值/删除识别 property 时使用。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _resolve_obj_class_name(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
obj_node: ast.AST | t.CPtr) -> str:
|
||||
"""解析对象表达式的类名(短名),失败返回 None"""
|
||||
if pool is None or trans is None or obj_node is None:
|
||||
return None
|
||||
if obj_node.kind() == ast.ASTKind.Name:
|
||||
obj_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(obj_node)
|
||||
if obj_nm.id is not None:
|
||||
var_entry: GenTypes.VarEntry | t.CPtr = self.Gen.VarGen.lookup_var_entry(
|
||||
trans.SymTab, obj_nm.id)
|
||||
if var_entry is not None and var_entry.AnnotClassName is not None:
|
||||
annot_val: str = var_entry.AnnotClassName
|
||||
dot_ptr: str = string.strrchr(annot_val, '.')
|
||||
if dot_ptr is not None:
|
||||
return dot_ptr + 1
|
||||
return annot_val
|
||||
return None
|
||||
# ============================================================
|
||||
# _try_property_getter_attr — 尝试将 obj.attr 翻译为 property getter 调用
|
||||
#
|
||||
# 检查 obj 的类是否有 @property/@x.getter 的 attr 方法;
|
||||
# 若有则生成 call Class.attr(obj) 并返回调用结果 Value;否则返回 None。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _try_property_getter_attr(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
at_node: ast.Attribute | t.CPtr,
|
||||
obj_ptr: llvmlite.Value | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
fallback_class_name: str = None) -> llvmlite.Value | t.CPtr:
|
||||
"""尝试 property getter 属性访问,返回调用结果 Value;非 getter 返回 None
|
||||
|
||||
fallback_class_name: 对象表达式非 Name 时从 LLVM 类型解析出的类名兜底。
|
||||
"""
|
||||
if at_node is None or at_node.attr is None or obj_ptr is None or trans is None:
|
||||
return None
|
||||
class_name: str = self._resolve_obj_class_name(pool, trans, at_node.value)
|
||||
if class_name is None:
|
||||
class_name = fallback_class_name
|
||||
if class_name is None:
|
||||
return None
|
||||
meta: int = self.Gen.ClassGenBase.lookup_method_meta(class_name, at_node.attr)
|
||||
if meta & GenTypes.META_PROP_GETTER == 0:
|
||||
return None
|
||||
# 单参数调用: obj → getter
|
||||
llvmlite.value_set_next(obj_ptr, None)
|
||||
return self._translate_property_call(
|
||||
pool, builder, mod, class_name, at_node.attr, obj_ptr, 1, trans)
|
||||
# ============================================================
|
||||
# _try_property_setter — 尝试将 obj.attr = v 翻译为 property setter 调用
|
||||
#
|
||||
# 检查 obj 的类是否有 @x.setter 的 attr 方法;
|
||||
# 若有则生成 call Class.attr$set(obj, v),返回 1;否则返回 0。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _try_property_setter(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
target_attr: ast.Attribute | t.CPtr,
|
||||
rhs_val: llvmlite.Value | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> int:
|
||||
"""尝试 property setter 赋值,返回 1=已处理(生成调用)"""
|
||||
if pool is None or builder is None or mod is None or trans is None:
|
||||
return 0
|
||||
if target_attr is None or target_attr.attr is None or rhs_val is None:
|
||||
return 0
|
||||
class_name: str = self._resolve_obj_class_name(pool, trans, target_attr.value)
|
||||
if class_name is None:
|
||||
return 0
|
||||
meta: int = self.Gen.ClassGenBase.lookup_method_meta(class_name, target_attr.attr)
|
||||
if meta & GenTypes.META_PROP_SETTER == 0:
|
||||
return 0
|
||||
# 翻译对象值(self 参数)
|
||||
obj_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
|
||||
builder, pool, mod, target_attr.value, None, 0, trans)
|
||||
if obj_val is None:
|
||||
return 0
|
||||
# 构建参数链表: obj → rhs
|
||||
llvmlite.value_set_next(obj_val, None)
|
||||
llvmlite.value_set_next(rhs_val, None)
|
||||
llvmlite.value_set_next(obj_val, rhs_val)
|
||||
# setter 函数名带 $set 后缀
|
||||
setter_name_buf: str = pool.alloc(128)
|
||||
if setter_name_buf is None:
|
||||
return 0
|
||||
viperlib.snprintf(setter_name_buf, 128, "%s$set", target_attr.attr)
|
||||
self._translate_property_call(pool, builder, mod, class_name,
|
||||
setter_name_buf, obj_val, 2, trans)
|
||||
return 1
|
||||
# ============================================================
|
||||
# _try_property_deleter — 尝试将 del obj.attr 翻译为 property deleter 调用
|
||||
#
|
||||
# 检查 obj 的类是否有 @x.deleter 的 attr 方法;
|
||||
# 若有则生成 call Class.attr$del(obj),返回 1;否则返回 0。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _try_property_deleter(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
target_attr: ast.Attribute | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> int:
|
||||
"""尝试 property deleter 删除,返回 1=已处理(生成调用)"""
|
||||
if pool is None or builder is None or mod is None or trans is None:
|
||||
return 0
|
||||
if target_attr is None or target_attr.attr is None:
|
||||
return 0
|
||||
class_name: str = self._resolve_obj_class_name(pool, trans, target_attr.value)
|
||||
if class_name is None:
|
||||
return 0
|
||||
meta: int = self.Gen.ClassGenBase.lookup_method_meta(class_name, target_attr.attr)
|
||||
if meta & GenTypes.META_PROP_DELETER == 0:
|
||||
return 0
|
||||
# 翻译对象值(self 参数)
|
||||
obj_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
|
||||
builder, pool, mod, target_attr.value, None, 0, trans)
|
||||
if obj_val is None:
|
||||
return 0
|
||||
llvmlite.value_set_next(obj_val, None)
|
||||
# deleter 函数名带 $del 后缀
|
||||
del_name_buf: str = pool.alloc(128)
|
||||
if del_name_buf is None:
|
||||
return 0
|
||||
viperlib.snprintf(del_name_buf, 128, "%s$del", target_attr.attr)
|
||||
self._translate_property_call(pool, builder, mod, class_name,
|
||||
del_name_buf, obj_val, 1, trans)
|
||||
return 1
|
||||
# ============================================================
|
||||
# _translate_static_class_call — 翻译 ClassName.method(args) 静态/类方法调用
|
||||
#
|
||||
# @staticmethod: 直接 call Class.method(args...),无 self
|
||||
# @classmethod: 在参数前插入栈上分配的类实例指针(与 TPC 一致)
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _translate_static_class_call(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
class_name: str,
|
||||
method_name: str,
|
||||
cl: ast.Call | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译类名静态/类方法调用,返回 call 结果 Value;非静态/类方法返回 None"""
|
||||
if pool is None or builder is None or mod is None or trans is None:
|
||||
return None
|
||||
if class_name is None or method_name is None or cl is None:
|
||||
return None
|
||||
meta: int = self.Gen.ClassGenBase.lookup_method_meta(class_name, method_name)
|
||||
is_static: int = 0
|
||||
is_class: int = 0
|
||||
if meta & GenTypes.META_STATIC != 0:
|
||||
is_static = 1
|
||||
if meta & GenTypes.META_CLASS != 0:
|
||||
is_class = 1
|
||||
if is_static == 0 and is_class == 0:
|
||||
return None
|
||||
|
||||
# 构建参数链表
|
||||
head: llvmlite.Value | t.CPtr = None
|
||||
total_count: int = 0
|
||||
|
||||
# @classmethod: 插入栈上分配的类实例指针作为 cls 参数
|
||||
if is_class != 0:
|
||||
struct_ty_cc: llvmlite.LLVMType | t.CPtr = self.Gen.StructGen.get_struct_type(class_name)
|
||||
if struct_ty_cc is None:
|
||||
return None
|
||||
cls_ptr: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, struct_ty_cc)
|
||||
if cls_ptr is None:
|
||||
return None
|
||||
llvmlite.value_set_next(cls_ptr, None)
|
||||
head = cls_ptr
|
||||
total_count = 1
|
||||
|
||||
# 翻译调用参数
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args
|
||||
can: t.CSizeT = 0
|
||||
if cargs is not None:
|
||||
can = len(cargs)
|
||||
tail: llvmlite.Value | t.CPtr = head
|
||||
for ai in range(can):
|
||||
arg_node: ast.AST | t.CPtr = cargs.get(ai)
|
||||
if arg_node is None:
|
||||
continue
|
||||
arg_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
|
||||
builder, pool, mod, arg_node, None, 0, trans)
|
||||
if arg_val is None:
|
||||
continue
|
||||
llvmlite.value_set_next(arg_val, None)
|
||||
if head is None:
|
||||
head = arg_val
|
||||
tail = arg_val
|
||||
else:
|
||||
llvmlite.value_set_next(tail, arg_val)
|
||||
tail = arg_val
|
||||
total_count += 1
|
||||
|
||||
# 零参 @staticmethod(如 PyListObj.new()):head 保持 None 是合法的
|
||||
# 无参调用,照常走 _translate_property_call(SHA1 前缀名 + 精确返回类型)。
|
||||
# 若此处 return None,调用方回退通用路径把方法名当裸函数解析,生成
|
||||
# call i32 @new() → 链接 undefined reference(CPythonTest 根因)。
|
||||
# @classmethod 恒有 cls_ptr(head 非 None),不受影响。
|
||||
return self._translate_property_call(pool, builder, mod, class_name,
|
||||
method_name, head, total_count, trans)
|
||||
# ============================================================
|
||||
# _is_list_builtin_method - 判断是否是 list 泛型内置容器方法
|
||||
#
|
||||
# list[T] 是内置泛型容器(_list.vp),其方法(append/get/set/pop/clear/
|
||||
# __iter__/__len__/__getitem__/__setitem__)由 translate_call 的 list
|
||||
# 内置分支内联 GEP 处理,不注册为方法函数。若 obj.method() 检测把
|
||||
# list 特化 struct(如 list[AST | CPtr])误当普通结构体走
|
||||
# _translate_method_call,会查不到 append 返回类型 → fail-fast
|
||||
# (NewAstTest body.append 根因)。此判断用于跳过 method_call 路径。
|
||||
#
|
||||
# 返回: 1=list 内置方法(应落到 list 内置分支),0=普通方法
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _is_list_builtin_method(self, class_name: str,
|
||||
method_name: str) -> int:
|
||||
"""判断 (class_name, method_name) 是否是 list 泛型内置方法"""
|
||||
if class_name is None or method_name is None:
|
||||
return 0
|
||||
# 类名必须以 "list" 开头(list / list[AST | CPtr] 特化名)
|
||||
if string.strncmp(class_name, "list", 4) != 0:
|
||||
return 0
|
||||
# 方法名必须是 list 内置方法集合
|
||||
if string.strcmp(method_name, "append") == 0: return 1
|
||||
if string.strcmp(method_name, "get") == 0: return 1
|
||||
if string.strcmp(method_name, "set") == 0: return 1
|
||||
if string.strcmp(method_name, "pop") == 0: return 1
|
||||
if string.strcmp(method_name, "clear") == 0: return 1
|
||||
if string.strcmp(method_name, "__iter__") == 0: return 1
|
||||
if string.strcmp(method_name, "__len__") == 0: return 1
|
||||
if string.strcmp(method_name, "__getitem__") == 0: return 1
|
||||
if string.strcmp(method_name, "__setitem__") == 0: return 1
|
||||
return 0
|
||||
+325
-333
@@ -1,334 +1,326 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import sys
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
import lib.core.Gen.CallGenBase as CallGenBase
|
||||
|
||||
# ============================================================
|
||||
# CallGenVa - CallGenMixin 拆分(阶段 B):va_arg 变长参数(start/arg/end / 变长调用提升)
|
||||
#
|
||||
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class CallGenVa(CallGenBase.CallGenBase):
|
||||
"""va_arg 变长参数(start/arg/end / 变长调用提升)"""
|
||||
|
||||
# ============================================================
|
||||
# _func_has_eh_params - 被调函数签名是否含 try-except EH 输出参数
|
||||
#
|
||||
# EH 参数(%__eh_msg_out__/__eh_code_out__)由 translate_function_def/
|
||||
# _translate_method 在含 raise 的函数签名末尾注入(main 除外)。
|
||||
# ============================================================
|
||||
|
||||
def _va_arg_get_alloca_ptr(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
arg_node: ast.AST | t.CPtr,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""获取 va_list 变量的 alloca 指针(不 load)
|
||||
|
||||
va_arg/va_start/va_end 需要的是 va_list 对象的地址(alloca 指针),
|
||||
而非 va_list 的值。若 arg_node 是 Name,查符号表获取 alloca;
|
||||
否则用 translate_value 翻译(调用者负责确保传入的是指针)。
|
||||
"""
|
||||
if arg_node is None:
|
||||
return None
|
||||
# Name 节点:直接查符号表获取 alloca 指针(不 load)
|
||||
if arg_node.kind() == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(arg_node)
|
||||
if nm.id is not None:
|
||||
alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm.id)
|
||||
if alloca is not None:
|
||||
return alloca
|
||||
# 回退:translate_value(可能返回 load 后的值,仅适用于已是指针的情况)
|
||||
return HandlesExpr.translate_value(builder, pool, mod, arg_node, funcs_ptr, func_count, trans)
|
||||
def _resolve_va_arg_type(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
type_node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""解析 va_arg/arg 的类型参数为 LLVMType
|
||||
|
||||
支持的类型表达式:
|
||||
t.CInt / t.CInt32T → i32
|
||||
t.CInt64T → i64
|
||||
t.CDouble → double
|
||||
t.CPtr / str → i8*
|
||||
str / bytes → i8*
|
||||
无类型参数时默认 i32(vsnprintf 中 va_arg(ap) 常用于读取 i32)
|
||||
"""
|
||||
if type_node is None:
|
||||
return llvmlite.Int32(pool)
|
||||
# 使用 HandlesType.resolve_annotation_type 解析类型表达式
|
||||
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||||
pool, type_node, trans._imported_modules, trans._from_imports, trans)
|
||||
if resolved is not None:
|
||||
return resolved
|
||||
# 类型节点存在但解析失败:fail-fast,绝不回退 i32(会按错宽度读变参槽位)
|
||||
HandlesType.fatal_error(type_node, "va_arg 类型解析失败", "TypeError")
|
||||
return llvmlite.Int32(pool)
|
||||
def _translate_va_arg_sugar(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""va_arg(ap, type) / va_arg(ap) → %N = va_arg <ap_ty> <ap>, <type>
|
||||
|
||||
生成 LLVM va_arg 指令,从 va_list 读取下一个变长参数。
|
||||
"""
|
||||
if can == 0 or cargs is None:
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
|
||||
# 第一个参数:va_list(求值为 i8* 地址值,对齐 TPC _HandleVaArgLlvm)
|
||||
# 当前函数 *args:translate_value 经 vararg 名映射直接返回 va_list 缓冲区地址;
|
||||
# 转发场景(sprintf → vsnprintf 的 ap 参数):translate_value load 参数得到地址值。
|
||||
ap_node: ast.AST | t.CPtr = cargs.get(0)
|
||||
ap_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, ap_node, None, 0, trans)
|
||||
if ap_val is None:
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
ap_ptr: llvmlite.Value | t.CPtr = ap_val
|
||||
|
||||
# 第二个参数:目标类型(可选,默认 i32)
|
||||
arg_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
if can >= 2:
|
||||
type_node: ast.AST | t.CPtr = cargs.get(1)
|
||||
arg_ty = self._resolve_va_arg_type(pool, type_node, trans)
|
||||
|
||||
# Win64 变参槽位为 8 字节:<64 位整数按 i64 读取(对齐 TPC emit_va_arg L72-73)
|
||||
read_ty: llvmlite.LLVMType | t.CPtr = arg_ty
|
||||
abits_va: int = HandlesExpr.get_llvm_type_bits(arg_ty)
|
||||
if abits_va != 0 and abits_va < 64:
|
||||
read_ty = llvmlite.Int64(pool)
|
||||
|
||||
# 生成 va_arg 指令
|
||||
return llvmlite.build_va_arg(builder, ap_ptr, read_ty)
|
||||
def _translate_arg_sugar(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""arg(type) → %N = va_arg <va_list_ty> <trans._va_list_ptr>, <type>
|
||||
|
||||
使用当前函数的隐式 va_list(trans._va_list_ptr),
|
||||
简化 *args 函数体内的 va_arg 调用。
|
||||
"""
|
||||
if trans._va_list_ptr is None:
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
|
||||
# 第一个参数:目标类型(可选,默认 i32)
|
||||
arg_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
if can >= 1 and cargs is not None:
|
||||
type_node: ast.AST | t.CPtr = cargs.get(0)
|
||||
arg_ty = self._resolve_va_arg_type(pool, type_node, trans)
|
||||
|
||||
# Win64 变参槽位为 8 字节:<64 位整数按 i64 读取(与 _translate_va_arg_sugar 一致)
|
||||
read_ty: llvmlite.LLVMType | t.CPtr = arg_ty
|
||||
abits_arg: int = HandlesExpr.get_llvm_type_bits(arg_ty)
|
||||
if abits_arg != 0 and abits_arg < 64:
|
||||
read_ty = llvmlite.Int64(pool)
|
||||
|
||||
# 生成 va_arg 指令(使用 trans._va_list_ptr 作为 va_list 地址)
|
||||
return llvmlite.build_va_arg(builder, trans._va_list_ptr, read_ty)
|
||||
def _translate_va_start_sugar(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""va_start(ap, last_arg) → call void @llvm.va_start(i8* %ap)
|
||||
|
||||
初始化 va_list。第二个参数 last_arg 在 LLVM intrinsic 中不使用(C 宏兼容)。
|
||||
"""
|
||||
if can == 0 or cargs is None:
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
|
||||
# 第一个参数:va_list 指针(获取 alloca,不 load)
|
||||
ap_node: ast.AST | t.CPtr = cargs.get(0)
|
||||
ap_ptr: llvmlite.Value | t.CPtr = self._va_arg_get_alloca_ptr(
|
||||
pool, builder, mod, ap_node, funcs_ptr, func_count, trans)
|
||||
if ap_ptr is None:
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
|
||||
# bitcast 到 i8*(@llvm.va_start 接受 i8*)
|
||||
i8_ty_vs: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty_vs: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_vs)
|
||||
ap_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, ap_ptr, i8_ptr_ty_vs)
|
||||
if ap_i8 is None:
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
|
||||
void_ty_vs: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool)
|
||||
llvmlite.build_call(builder, "llvm.va_start", ap_i8, 1, void_ty_vs, 0)
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
def _translate_va_end_sugar(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""va_end(ap) → call void @llvm.va_end(i8* %ap)
|
||||
|
||||
清理 va_list。在大多数平台上是 no-op,但调用它是良好的 C ABI 习惯。
|
||||
"""
|
||||
if can == 0 or cargs is None:
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
|
||||
# 第一个参数:va_list 指针(获取 alloca,不 load)
|
||||
ap_node: ast.AST | t.CPtr = cargs.get(0)
|
||||
ap_ptr: llvmlite.Value | t.CPtr = self._va_arg_get_alloca_ptr(
|
||||
pool, builder, mod, ap_node, funcs_ptr, func_count, trans)
|
||||
if ap_ptr is None:
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
|
||||
# bitcast 到 i8*(@llvm.va_end 接受 i8*)
|
||||
i8_ty_ve: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty_ve: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_ve)
|
||||
ap_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, ap_ptr, i8_ptr_ty_ve)
|
||||
if ap_i8 is None:
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
|
||||
void_ty_ve: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool)
|
||||
llvmlite.build_call(builder, "llvm.va_end", ap_i8, 1, void_ty_ve, 0)
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
def _get_func_fixed_param_count(self, func: llvmlite.Function | t.CPtr) -> int:
|
||||
"""获取函数的固定参数数量(遍历 Params 链表)"""
|
||||
if func is None:
|
||||
return 0
|
||||
count: int = 0
|
||||
param: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(func)
|
||||
while param is not None:
|
||||
count += 1
|
||||
param = llvmlite.param_get_next(param)
|
||||
return count
|
||||
def _check_and_promote_variadic_call(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
call_name: str,
|
||||
head: llvmlite.Value | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
arg_nodes: list[ast.AST | t.CPtr] | t.CPtr = None,
|
||||
self_offset: int = 0,
|
||||
trans: HT.Translator | t.CPtr = None) -> int:
|
||||
"""检查被调用函数是否为变长函数,若是则对变长参数进行 C ABI 提升
|
||||
|
||||
返回: is_variadic (1=变长调用, 0=普通调用)
|
||||
副作用: 修改 head 链表中超过固定参数数量的节点(C ABI 提升)
|
||||
|
||||
arg_nodes: 实参 AST 链表(不含 self),用于 i8/i16 提升的无符号性判断
|
||||
self_offset: Value 链中 self 占用的偏移(方法调用=1,普通函数=0)
|
||||
trans: 供 _node_type_unsigned 查询变量注解
|
||||
"""
|
||||
if mod is None or call_name is None or head is None:
|
||||
return 0
|
||||
# 查找函数对象
|
||||
func: llvmlite.Function | t.CPtr = self.find_func_in_module(mod, call_name)
|
||||
if func is None:
|
||||
return 0
|
||||
if func.IsVarArg != 1:
|
||||
return 0
|
||||
|
||||
# 获取固定参数数量
|
||||
fixed_count: int = self._get_func_fixed_param_count(func)
|
||||
|
||||
# 无变长参数(实参数量 <= 固定参数数量),仍需 is_variadic=1
|
||||
if can <= fixed_count:
|
||||
return 1
|
||||
|
||||
# 遍历到第 fixed_count 个节点(固定参数的最后一个)
|
||||
cur: llvmlite.Value | t.CPtr = head
|
||||
prev: llvmlite.Value | t.CPtr = None
|
||||
idx: int = 0
|
||||
while cur is not None and idx < fixed_count:
|
||||
prev = cur
|
||||
cur = cur.Next
|
||||
idx += 1
|
||||
|
||||
# cur 指向第 fixed_count+1 个节点(第一个变长参数)
|
||||
# 对变长参数进行 C ABI 提升
|
||||
i32_ty_promote: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
double_ty_promote: llvmlite.LLVMType | t.CPtr = llvmlite.Double(pool)
|
||||
v_idx: int = fixed_count
|
||||
while cur is not None:
|
||||
next_node: llvmlite.Value | t.CPtr = cur.Next
|
||||
promoted: llvmlite.Value | t.CPtr = cur
|
||||
# C ABI integer promotion: i8/i16 → i32
|
||||
arg_bits: int = HandlesExpr.get_llvm_type_bits(cur.Ty)
|
||||
if arg_bits != 0 and arg_bits < 32:
|
||||
# 无符号整型(t.CUInt8T/CUInt16T 等)→ zext;有符号/未知 → sext。
|
||||
# 修复: printf("%02x", buf[i]) 中 buf[i] 是 CUInt8T,sext 得
|
||||
# 0xFFFFFFF3 打印 fffffff3(哈希摘要输出垃圾),应 zext 得 0xF3。
|
||||
is_u_va: int = 0
|
||||
if arg_nodes is not None and trans is not None:
|
||||
ast_idx_va: int = v_idx - self_offset
|
||||
if ast_idx_va >= 0 and ast_idx_va < len(arg_nodes):
|
||||
an_va: ast.AST | t.CPtr = arg_nodes.get(ast_idx_va)
|
||||
if an_va is not None:
|
||||
if HandlesExpr._node_type_unsigned(pool, an_va, trans) != 0:
|
||||
is_u_va = 1
|
||||
if is_u_va != 0:
|
||||
promoted = llvmlite.build_zext(builder, cur, i32_ty_promote)
|
||||
else:
|
||||
# is_u_va 判断失败(arg_nodes/trans 缺失或变量注解查不到)时,
|
||||
# i8 按系统编程惯例默认 zext(对齐 should_zext_widen 的
|
||||
# "i8 → zext(系统编程中 i8 几乎总是无符号字节)"策略),
|
||||
# 否则 printf("%02x", buf[i]) 中 uint8 字节被 sext 成
|
||||
# 0xFFFFFFF3,哈希摘要输出 ffffffXX 垃圾。
|
||||
if HandlesExpr.get_llvm_type_bits(cur.Ty) == 8:
|
||||
promoted = llvmlite.build_zext(builder, cur, i32_ty_promote)
|
||||
else:
|
||||
promoted = HandlesExpr.coerce_to_type(builder, cur, i32_ty_promote, None)
|
||||
if promoted is not None:
|
||||
promoted.Next = next_node
|
||||
if prev is not None:
|
||||
prev.Next = promoted
|
||||
# C ABI float promotion: float → double
|
||||
arg_fbits: int = HandlesExpr.get_llvm_float_bits(promoted.Ty)
|
||||
if arg_fbits != 0 and arg_fbits < 64:
|
||||
promoted = HandlesExpr.coerce_to_type(builder, promoted, double_ty_promote, None)
|
||||
if promoted is not None:
|
||||
promoted.Next = next_node
|
||||
if prev is not None:
|
||||
prev.Next = promoted
|
||||
prev = promoted
|
||||
cur = next_node
|
||||
v_idx += 1
|
||||
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import sys
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
import lib.core.Gen.CallGenBase as CallGenBase
|
||||
|
||||
# ============================================================
|
||||
# CallGenVa - CallGenMixin 拆分(阶段 B):va_arg 变长参数(start/arg/end / 变长调用提升)
|
||||
#
|
||||
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class CallGenVa(CallGenBase.CallGenBase):
|
||||
"""va_arg 变长参数(start/arg/end / 变长调用提升)"""
|
||||
|
||||
# ============================================================
|
||||
# _func_has_eh_params - 被调函数签名是否含 try-except EH 输出参数
|
||||
#
|
||||
# EH 参数(%__eh_msg_out__/__eh_code_out__)由 translate_function_def/
|
||||
# _translate_method 在含 raise 的函数签名末尾注入(main 除外)。
|
||||
# ============================================================
|
||||
|
||||
def _va_arg_get_alloca_ptr(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
arg_node: ast.AST | t.CPtr,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""获取 va_list 变量的 alloca 指针(不 load)
|
||||
|
||||
va_arg/va_start/va_end 需要的是 va_list 对象的地址(alloca 指针),
|
||||
而非 va_list 的值。若 arg_node 是 Name,查符号表获取 alloca;
|
||||
否则用 translate_value 翻译(调用者负责确保传入的是指针)。
|
||||
"""
|
||||
if arg_node is None:
|
||||
return None
|
||||
# Name 节点:直接查符号表获取 alloca 指针(不 load)
|
||||
if arg_node.kind() == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(arg_node)
|
||||
if nm.id is not None:
|
||||
alloca: llvmlite.Value | t.CPtr = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
|
||||
if alloca is not None:
|
||||
return alloca
|
||||
# 回退:translate_value(可能返回 load 后的值,仅适用于已是指针的情况)
|
||||
return self.Gen.ExprGen.translate_value(builder, pool, mod, arg_node, funcs_ptr, func_count, trans)
|
||||
def _resolve_va_arg_type(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
type_node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""解析 va_arg/arg 的类型参数为 LLVMType
|
||||
|
||||
支持的类型表达式:
|
||||
t.CInt / t.CInt32T → i32
|
||||
t.CInt64T → i64
|
||||
t.CDouble → double
|
||||
t.CPtr / str → i8*
|
||||
str / bytes → i8*
|
||||
无类型参数时默认 i32(vsnprintf 中 va_arg(ap) 常用于读取 i32)
|
||||
"""
|
||||
if type_node is None:
|
||||
return llvmlite.Int32(pool)
|
||||
# 使用 HandlesType.resolve_annotation_type 解析类型表达式
|
||||
resolved: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.resolve_annotation_type(
|
||||
pool, type_node, trans._imported_modules, trans._from_imports, trans)
|
||||
if resolved is not None:
|
||||
return resolved
|
||||
# 类型节点存在但解析失败:fail-fast,绝不回退 i32(会按错宽度读变参槽位)
|
||||
self.Gen.TypeGenErr.fatal_error(type_node, "va_arg 类型解析失败", "TypeError")
|
||||
return llvmlite.Int32(pool)
|
||||
def _translate_va_arg_sugar(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""va_arg(ap, type) / va_arg(ap) → %N = va_arg <ap_ty> <ap>, <type>
|
||||
|
||||
生成 LLVM va_arg 指令,从 va_list 读取下一个变长参数。
|
||||
"""
|
||||
if can == 0 or cargs is None:
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
|
||||
# 第一个参数:va_list(求值为 i8* 地址值,对齐 TPC _HandleVaArgLlvm)
|
||||
# 当前函数 *args:translate_value 经 vararg 名映射直接返回 va_list 缓冲区地址;
|
||||
# 转发场景(sprintf → vsnprintf 的 ap 参数):translate_value load 参数得到地址值。
|
||||
ap_node: ast.AST | t.CPtr = cargs.get(0)
|
||||
ap_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
|
||||
builder, pool, mod, ap_node, None, 0, trans)
|
||||
if ap_val is None:
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
ap_ptr: llvmlite.Value | t.CPtr = ap_val
|
||||
|
||||
# 第二个参数:目标类型(可选,默认 i32)
|
||||
arg_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
if can >= 2:
|
||||
type_node: ast.AST | t.CPtr = cargs.get(1)
|
||||
arg_ty = self._resolve_va_arg_type(pool, type_node, trans)
|
||||
|
||||
# Win64 变参槽位为 8 字节:<64 位整数按 i64 读取(对齐 TPC emit_va_arg L72-73)
|
||||
read_ty: llvmlite.LLVMType | t.CPtr = arg_ty
|
||||
abits_va: int = self.Gen.ExprGenBase.get_llvm_type_bits(arg_ty)
|
||||
if abits_va != 0 and abits_va < 64:
|
||||
read_ty = llvmlite.Int64(pool)
|
||||
|
||||
# 生成 va_arg 指令
|
||||
return llvmlite.build_va_arg(builder, ap_ptr, read_ty)
|
||||
def _translate_arg_sugar(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""arg(type) → %N = va_arg <va_list_ty> <trans._va_list_ptr>, <type>
|
||||
|
||||
使用当前函数的隐式 va_list(trans._va_list_ptr),
|
||||
简化 *args 函数体内的 va_arg 调用。
|
||||
"""
|
||||
if trans._va_list_ptr is None:
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
|
||||
# 第一个参数:目标类型(可选,默认 i32)
|
||||
arg_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
if can >= 1 and cargs is not None:
|
||||
type_node: ast.AST | t.CPtr = cargs.get(0)
|
||||
arg_ty = self._resolve_va_arg_type(pool, type_node, trans)
|
||||
|
||||
# Win64 变参槽位为 8 字节:<64 位整数按 i64 读取(与 _translate_va_arg_sugar 一致)
|
||||
read_ty: llvmlite.LLVMType | t.CPtr = arg_ty
|
||||
abits_arg: int = self.Gen.ExprGenBase.get_llvm_type_bits(arg_ty)
|
||||
if abits_arg != 0 and abits_arg < 64:
|
||||
read_ty = llvmlite.Int64(pool)
|
||||
|
||||
# 生成 va_arg 指令(使用 trans._va_list_ptr 作为 va_list 地址)
|
||||
return llvmlite.build_va_arg(builder, trans._va_list_ptr, read_ty)
|
||||
def _translate_va_start_sugar(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""va_start(ap, last_arg) → call void @llvm.va_start(i8* %ap)
|
||||
|
||||
初始化 va_list。第二个参数 last_arg 在 LLVM intrinsic 中不使用(C 宏兼容)。
|
||||
"""
|
||||
if can == 0 or cargs is None:
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
|
||||
# 第一个参数:va_list 指针(获取 alloca,不 load)
|
||||
ap_node: ast.AST | t.CPtr = cargs.get(0)
|
||||
ap_ptr: llvmlite.Value | t.CPtr = self._va_arg_get_alloca_ptr(
|
||||
pool, builder, mod, ap_node, funcs_ptr, func_count, trans)
|
||||
if ap_ptr is None:
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
|
||||
# bitcast 到 i8*(@llvm.va_start 接受 i8*)
|
||||
i8_ty_vs: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty_vs: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_vs)
|
||||
ap_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, ap_ptr, i8_ptr_ty_vs)
|
||||
if ap_i8 is None:
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
|
||||
void_ty_vs: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool)
|
||||
llvmlite.build_call(builder, "llvm.va_start", ap_i8, 1, void_ty_vs, 0)
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
def _translate_va_end_sugar(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""va_end(ap) → call void @llvm.va_end(i8* %ap)
|
||||
|
||||
清理 va_list。在大多数平台上是 no-op,但调用它是良好的 C ABI 习惯。
|
||||
"""
|
||||
if can == 0 or cargs is None:
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
|
||||
# 第一个参数:va_list 指针(获取 alloca,不 load)
|
||||
ap_node: ast.AST | t.CPtr = cargs.get(0)
|
||||
ap_ptr: llvmlite.Value | t.CPtr = self._va_arg_get_alloca_ptr(
|
||||
pool, builder, mod, ap_node, funcs_ptr, func_count, trans)
|
||||
if ap_ptr is None:
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
|
||||
# bitcast 到 i8*(@llvm.va_end 接受 i8*)
|
||||
i8_ty_ve: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty_ve: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_ve)
|
||||
ap_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, ap_ptr, i8_ptr_ty_ve)
|
||||
if ap_i8 is None:
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
|
||||
void_ty_ve: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool)
|
||||
llvmlite.build_call(builder, "llvm.va_end", ap_i8, 1, void_ty_ve, 0)
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
def _get_func_fixed_param_count(self, func: llvmlite.Function | t.CPtr) -> int:
|
||||
"""获取函数的固定参数数量(遍历 Params 链表)"""
|
||||
if func is None:
|
||||
return 0
|
||||
count: int = 0
|
||||
param: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(func)
|
||||
while param is not None:
|
||||
count += 1
|
||||
param = llvmlite.param_get_next(param)
|
||||
return count
|
||||
def _check_and_promote_variadic_call(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
call_name: str,
|
||||
head: llvmlite.Value | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
arg_nodes: list[ast.AST | t.CPtr] | t.CPtr = None,
|
||||
self_offset: int = 0,
|
||||
trans: HT.Translator | t.CPtr = None) -> int:
|
||||
"""检查被调用函数是否为变长函数,若是则对变长参数进行 C ABI 提升
|
||||
|
||||
返回: is_variadic (1=变长调用, 0=普通调用)
|
||||
副作用: 修改 head 链表中超过固定参数数量的节点(C ABI 提升)
|
||||
|
||||
arg_nodes: 实参 AST 链表(不含 self),用于 i8/i16 提升的无符号性判断
|
||||
self_offset: Value 链中 self 占用的偏移(方法调用=1,普通函数=0)
|
||||
trans: 供 _node_type_unsigned 查询变量注解
|
||||
"""
|
||||
if mod is None or call_name is None or head is None:
|
||||
return 0
|
||||
# 查找函数对象
|
||||
func: llvmlite.Function | t.CPtr = self.find_func_in_module(mod, call_name)
|
||||
if func is None:
|
||||
return 0
|
||||
if func.IsVarArg != 1:
|
||||
return 0
|
||||
|
||||
# 获取固定参数数量
|
||||
fixed_count: int = self._get_func_fixed_param_count(func)
|
||||
|
||||
# 无变长参数(实参数量 <= 固定参数数量),仍需 is_variadic=1
|
||||
if can <= fixed_count:
|
||||
return 1
|
||||
|
||||
# 遍历到第 fixed_count 个节点(固定参数的最后一个)
|
||||
cur: llvmlite.Value | t.CPtr = head
|
||||
prev: llvmlite.Value | t.CPtr = None
|
||||
idx: int = 0
|
||||
while cur is not None and idx < fixed_count:
|
||||
prev = cur
|
||||
cur = cur.Next
|
||||
idx += 1
|
||||
|
||||
# cur 指向第 fixed_count+1 个节点(第一个变长参数)
|
||||
# 对变长参数进行 C ABI 提升
|
||||
i32_ty_promote: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
double_ty_promote: llvmlite.LLVMType | t.CPtr = llvmlite.Double(pool)
|
||||
v_idx: int = fixed_count
|
||||
while cur is not None:
|
||||
next_node: llvmlite.Value | t.CPtr = cur.Next
|
||||
promoted: llvmlite.Value | t.CPtr = cur
|
||||
# C ABI integer promotion: i8/i16 → i32
|
||||
arg_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(cur.Ty)
|
||||
if arg_bits != 0 and arg_bits < 32:
|
||||
# 无符号整型(t.CUInt8T/CUInt16T 等)→ zext;有符号/未知 → sext。
|
||||
# 修复: printf("%02x", buf[i]) 中 buf[i] 是 CUInt8T,sext 得
|
||||
# 0xFFFFFFF3 打印 fffffff3(哈希摘要输出垃圾),应 zext 得 0xF3。
|
||||
is_u_va: int = 0
|
||||
if arg_nodes is not None and trans is not None:
|
||||
ast_idx_va: int = v_idx - self_offset
|
||||
if ast_idx_va >= 0 and ast_idx_va < len(arg_nodes):
|
||||
an_va: ast.AST | t.CPtr = arg_nodes.get(ast_idx_va)
|
||||
if an_va is not None:
|
||||
if self.Gen.ExprGenOps._node_type_unsigned(pool, an_va, trans) != 0:
|
||||
is_u_va = 1
|
||||
if is_u_va != 0:
|
||||
promoted = llvmlite.build_zext(builder, cur, i32_ty_promote)
|
||||
else:
|
||||
# is_u_va 判断失败(arg_nodes/trans 缺失或变量注解查不到)时,
|
||||
# i8 按系统编程惯例默认 zext(对齐 should_zext_widen 的
|
||||
# "i8 → zext(系统编程中 i8 几乎总是无符号字节)"策略),
|
||||
# 否则 printf("%02x", buf[i]) 中 uint8 字节被 sext 成
|
||||
# 0xFFFFFFF3,哈希摘要输出 ffffffXX 垃圾。
|
||||
if self.Gen.ExprGenBase.get_llvm_type_bits(cur.Ty) == 8:
|
||||
promoted = llvmlite.build_zext(builder, cur, i32_ty_promote)
|
||||
else:
|
||||
promoted = self.Gen.ExprGenBase.coerce_to_type(builder, cur, i32_ty_promote, None)
|
||||
if promoted is not None:
|
||||
promoted.Next = next_node
|
||||
if prev is not None:
|
||||
prev.Next = promoted
|
||||
# C ABI float promotion: float → double
|
||||
arg_fbits: int = self.Gen.ExprGenBase.get_llvm_float_bits(promoted.Ty)
|
||||
if arg_fbits != 0 and arg_fbits < 64:
|
||||
promoted = self.Gen.ExprGenBase.coerce_to_type(builder, promoted, double_ty_promote, None)
|
||||
if promoted is not None:
|
||||
promoted.Next = next_node
|
||||
if prev is not None:
|
||||
prev.Next = promoted
|
||||
prev = promoted
|
||||
cur = next_node
|
||||
v_idx += 1
|
||||
|
||||
return 1
|
||||
+230
-241
@@ -1,242 +1,231 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import sys
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
import lib.core.Gen.CallGenBase as CallGenBase
|
||||
import lib.core.Handles.ExprCallBase as ExprCallBase
|
||||
import lib.core.Handles.ExprCallHandle as ExprCallHandle
|
||||
|
||||
# ============================================================
|
||||
# CallGenVt - CallGenMixin 拆分(阶段 B):vtable 槽位写入
|
||||
#
|
||||
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class CallGenVt(CallGenBase.CallGenBase):
|
||||
"""vtable 槽位写入"""
|
||||
|
||||
# ============================================================
|
||||
# _write_vtable_slot / _write_vtable_attr — vtable 方法槽位直接写入
|
||||
#
|
||||
# serial0_file.open = serial0_open(devfs 驱动注册模式):把模块级函数
|
||||
# 指针写入对象 vtable 的方法槽位。vtable 方法不是数据字段(FieldEntry),
|
||||
# get_attribute_ptr 查不到 → 此前 fatal_error "属性写入失败"。
|
||||
# 对齐 TPC HandlesAssign.py L905-949 的写时复制:
|
||||
# 对象 vtable 仍指向类默认 vtable 时,先复制一份(internal 全局 +
|
||||
# llvm.memcpy)并让对象指向副本,再 GEP method_index 槽位 store
|
||||
# 函数指针(i8*)。多次写入互不覆盖(第二次起 vtable 已非默认,
|
||||
# 跳过复制直接写槽位)。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _write_vtable_slot(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
obj_ptr: llvmlite.Value | t.CPtr,
|
||||
class_name: str,
|
||||
method_index: int,
|
||||
func_val: llvmlite.Value | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> int:
|
||||
"""生成 vtable 槽位写入(写时复制),成功返回 1"""
|
||||
if pool is None or builder is None or mod is None or trans is None:
|
||||
return 0
|
||||
if obj_ptr is None or class_name is None or func_val is None:
|
||||
return 0
|
||||
if method_index < 0 or trans._cur_func is None:
|
||||
return 0
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
if i8_ty is None:
|
||||
return 0
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
if i8_ptr_ty is None:
|
||||
return 0
|
||||
i8_ptr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty)
|
||||
if i8_ptr_ptr_ty is None:
|
||||
return 0
|
||||
method_count: int = HandlesStruct.get_vtable_method_count(class_name)
|
||||
if method_count <= 0:
|
||||
return 0
|
||||
# 构造 vtable 类型 { i8*, i8*, ... }
|
||||
vt_first: llvmlite.ParamNode | t.CPtr = None
|
||||
vt_prev: llvmlite.ParamNode | t.CPtr = None
|
||||
for vi in range(method_count):
|
||||
pn: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, i8_ptr_ty)
|
||||
if pn is None:
|
||||
continue
|
||||
if vt_first is None:
|
||||
vt_first = pn
|
||||
if vt_prev is not None:
|
||||
llvmlite.paramnode_set_next(vt_prev, pn)
|
||||
vt_prev = pn
|
||||
vtable_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, vt_first, method_count, None)
|
||||
if vtable_ty is None:
|
||||
return 0
|
||||
# 对象 vtable 槽位(对象头 → i8**,vtable 指针总是第一个字段)
|
||||
vtable_slot: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||||
builder, obj_ptr, i8_ptr_ptr_ty)
|
||||
if vtable_slot is None:
|
||||
return 0
|
||||
vtable_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load(
|
||||
builder, i8_ptr_ty, vtable_slot)
|
||||
if vtable_ptr is None:
|
||||
return 0
|
||||
# 类默认 vtable 地址(比较用)
|
||||
class_vt: llvmlite.Value | t.CPtr = ExprCallHandle._make_vtable_ref_i8(
|
||||
pool, builder, mod, class_name, trans)
|
||||
if class_vt is None:
|
||||
return 0
|
||||
cmp_vt: llvmlite.Value | t.CPtr = llvmlite.build_icmp(
|
||||
builder, llvmlite.ICMP_EQ, vtable_ptr, class_vt)
|
||||
if cmp_vt is None:
|
||||
return 0
|
||||
# 块名唯一化(create_block 不自动编号;同函数多次 vtable 写入(如
|
||||
# devfs open/close/read/write 连续赋值)同名 label 冲突)
|
||||
vtc3: int = trans._label_counter
|
||||
trans._label_counter = vtc3 + 1
|
||||
vt_bb_buf3: str = pool.alloc(64)
|
||||
if vt_bb_buf3 is None:
|
||||
return 0
|
||||
viperlib.snprintf(vt_bb_buf3, 64, "vt.copy.%d", vtc3)
|
||||
vt_copy_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
|
||||
pool, trans._cur_func, vt_bb_buf3)
|
||||
viperlib.snprintf(vt_bb_buf3, 64, "vt.skip.%d", vtc3)
|
||||
vt_skip_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
|
||||
pool, trans._cur_func, vt_bb_buf3)
|
||||
if vt_copy_bb is None or vt_skip_bb is None:
|
||||
return 0
|
||||
llvmlite.build_cond_br(builder, cmp_vt, vt_copy_bb, vt_skip_bb)
|
||||
# copy 块:创建 internal 副本全局(zeroinit)+ memcpy + 对象指向副本
|
||||
llvmlite.position_at_end(builder, vt_copy_bb)
|
||||
vtc: int = trans._label_counter
|
||||
trans._label_counter = vtc + 1
|
||||
vcopy_buf: str = pool.alloc(256)
|
||||
if vcopy_buf is not None:
|
||||
viperlib.snprintf(vcopy_buf, 256, "%s.vtable.copy.%d", class_name, vtc)
|
||||
vcopy_gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(
|
||||
pool, vcopy_buf, vtable_ty)
|
||||
if vcopy_gv is not None:
|
||||
llvmlite.module_add_global(mod, vcopy_gv)
|
||||
vcopy_gv.Linkage = None
|
||||
vcopy_gv.Initializer = "zeroinitializer"
|
||||
vcopy_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue(
|
||||
pool, llvmlite.Ptr(pool, vtable_ty), vcopy_buf)
|
||||
if vcopy_ref is not None:
|
||||
vcopy_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||||
builder, vcopy_ref, i8_ptr_ty)
|
||||
if vcopy_i8 is not None:
|
||||
vt_size: llvmlite.Value | t.CPtr = llvmlite.ConstInt(
|
||||
pool, llvmlite.Int64(pool), method_count * 8, "vtsz")
|
||||
if vt_size is not None:
|
||||
ExprCallBase._emit_llvm_memcpy_intrinsic(
|
||||
pool, builder, mod, vcopy_i8, class_vt, vt_size)
|
||||
llvmlite.build_store(builder, vcopy_i8, vtable_slot)
|
||||
llvmlite.build_br(builder, vt_skip_bb)
|
||||
# skip 块:reload vtable → GEP 槽位 → store 函数指针(i8*)
|
||||
llvmlite.position_at_end(builder, vt_skip_bb)
|
||||
vt_ptr2: llvmlite.Value | t.CPtr = llvmlite.build_load(
|
||||
builder, i8_ptr_ty, vtable_slot)
|
||||
if vt_ptr2 is None:
|
||||
return 0
|
||||
vt_typed: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||||
builder, vt_ptr2, llvmlite.Ptr(pool, vtable_ty))
|
||||
if vt_typed is None:
|
||||
return 0
|
||||
vt_slotp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
|
||||
builder, vtable_ty, i8_ptr_ty, vt_typed, method_index)
|
||||
if vt_slotp is None:
|
||||
return 0
|
||||
fptr_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||||
builder, func_val, i8_ptr_ty)
|
||||
if fptr_i8 is not None:
|
||||
llvmlite.build_store(builder, fptr_i8, vt_slotp)
|
||||
return 1
|
||||
def _write_vtable_attr(self, builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
rhs_val: llvmlite.Value | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> int:
|
||||
"""属性写入 obj.method = func:检测 vtable 方法并生成槽位写入(成功返回 1)"""
|
||||
if node is None or builder is None or pool is None or mod is None:
|
||||
return 0
|
||||
if rhs_val is None or trans is None:
|
||||
return 0
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
|
||||
if at is None or at.value is None or at.attr is None:
|
||||
return 0
|
||||
# 解析类名(AnnotClassName;去模块前缀)
|
||||
class_nm_v: str = None
|
||||
if at.value.kind() == ast.ASTKind.Name:
|
||||
nm_v: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
|
||||
if nm_v.id is not None:
|
||||
ve_v: HandlesVar.VarEntry | t.CPtr = HandlesVar.lookup_var_entry(
|
||||
trans.SymTab, nm_v.id)
|
||||
if ve_v is not None:
|
||||
class_nm_v = ve_v.AnnotClassName
|
||||
elif at.value.kind() == ast.ASTKind.Attribute:
|
||||
# 跨 Mixin:_resolve_attr_field_class 定义在 ExprGenMixin,经 gen 单例调用
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g_vta: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(
|
||||
t.CVoid(HandlesExpr._g_gen, t.CPtr))
|
||||
if g_vta is not None:
|
||||
class_nm_v = g_vta._resolve_attr_field_class(pool, trans, at.value)
|
||||
if class_nm_v is None:
|
||||
return 0
|
||||
fd_dot_v: str = string.strrchr(class_nm_v, '.')
|
||||
if fd_dot_v is not None:
|
||||
class_nm_v = fd_dot_v + 1
|
||||
if HandlesStruct.get_struct_type(class_nm_v) is None:
|
||||
return 0
|
||||
vm_idx_v: int = HandlesStruct.get_vtable_method_index(class_nm_v, at.attr)
|
||||
if vm_idx_v < 0:
|
||||
return 0
|
||||
# 解析 obj_ptr(对齐 get_attribute_ptr 前半段:Name 直接查 alloca)
|
||||
obj_ptr_v: llvmlite.Value | t.CPtr = None
|
||||
if at.value.kind() == ast.ASTKind.Name:
|
||||
obj_ptr_v = HandlesVar.lookup_var(
|
||||
trans.SymTab, ((ast.Name | t.CPtr)(at.value)).id)
|
||||
else:
|
||||
obj_ptr_v = HandlesExpr.translate_value(
|
||||
builder, pool, mod, at.value, None, 0, trans)
|
||||
if obj_ptr_v is None or obj_ptr_v.Ty is None:
|
||||
return 0
|
||||
# X|t.CPtr 变量(Ptr(Ptr))load 解引用取对象指针
|
||||
match obj_ptr_v.Ty:
|
||||
case llvmlite.LLVMType.Ptr(inner_v):
|
||||
match inner_v:
|
||||
case llvmlite.LLVMType.Ptr(_):
|
||||
obj_ptr_v = llvmlite.build_load(builder, inner_v, obj_ptr_v)
|
||||
case _:
|
||||
pass
|
||||
case _:
|
||||
pass
|
||||
if obj_ptr_v is None:
|
||||
return 0
|
||||
return self._write_vtable_slot(
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import lib.core.Gen.ExprGenAttr as ExprGenAttr
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import sys
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
import lib.core.Gen.CallGenBase as CallGenBase
|
||||
|
||||
# ============================================================
|
||||
# CallGenVt - CallGenMixin 拆分(阶段 B):vtable 槽位写入
|
||||
#
|
||||
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class CallGenVt(CallGenBase.CallGenBase):
|
||||
"""vtable 槽位写入"""
|
||||
|
||||
# ============================================================
|
||||
# _write_vtable_slot / _write_vtable_attr — vtable 方法槽位直接写入
|
||||
#
|
||||
# serial0_file.open = serial0_open(devfs 驱动注册模式):把模块级函数
|
||||
# 指针写入对象 vtable 的方法槽位。vtable 方法不是数据字段(FieldEntry),
|
||||
# get_attribute_ptr 查不到 → 此前 fatal_error "属性写入失败"。
|
||||
# 对齐 TPC HandlesAssign.py L905-949 的写时复制:
|
||||
# 对象 vtable 仍指向类默认 vtable 时,先复制一份(internal 全局 +
|
||||
# llvm.memcpy)并让对象指向副本,再 GEP method_index 槽位 store
|
||||
# 函数指针(i8*)。多次写入互不覆盖(第二次起 vtable 已非默认,
|
||||
# 跳过复制直接写槽位)。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
def _write_vtable_slot(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
obj_ptr: llvmlite.Value | t.CPtr,
|
||||
class_name: str,
|
||||
method_index: int,
|
||||
func_val: llvmlite.Value | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> int:
|
||||
"""生成 vtable 槽位写入(写时复制),成功返回 1"""
|
||||
if pool is None or builder is None or mod is None or trans is None:
|
||||
return 0
|
||||
if obj_ptr is None or class_name is None or func_val is None:
|
||||
return 0
|
||||
if method_index < 0 or trans._cur_func is None:
|
||||
return 0
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
if i8_ty is None:
|
||||
return 0
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
if i8_ptr_ty is None:
|
||||
return 0
|
||||
i8_ptr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty)
|
||||
if i8_ptr_ptr_ty is None:
|
||||
return 0
|
||||
method_count: int = self.Gen.StructGen.get_vtable_method_count(class_name)
|
||||
if method_count <= 0:
|
||||
return 0
|
||||
# 构造 vtable 类型 { i8*, i8*, ... }
|
||||
vt_first: llvmlite.ParamNode | t.CPtr = None
|
||||
vt_prev: llvmlite.ParamNode | t.CPtr = None
|
||||
for vi in range(method_count):
|
||||
pn: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, i8_ptr_ty)
|
||||
if pn is None:
|
||||
continue
|
||||
if vt_first is None:
|
||||
vt_first = pn
|
||||
if vt_prev is not None:
|
||||
llvmlite.paramnode_set_next(vt_prev, pn)
|
||||
vt_prev = pn
|
||||
vtable_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, vt_first, method_count, None)
|
||||
if vtable_ty is None:
|
||||
return 0
|
||||
# 对象 vtable 槽位(对象头 → i8**,vtable 指针总是第一个字段)
|
||||
vtable_slot: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||||
builder, obj_ptr, i8_ptr_ptr_ty)
|
||||
if vtable_slot is None:
|
||||
return 0
|
||||
vtable_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load(
|
||||
builder, i8_ptr_ty, vtable_slot)
|
||||
if vtable_ptr is None:
|
||||
return 0
|
||||
# 类默认 vtable 地址(比较用)
|
||||
class_vt: llvmlite.Value | t.CPtr = self.Gen.CallGenLeafKit._make_vtable_ref_i8(
|
||||
pool, builder, mod, class_name, trans)
|
||||
if class_vt is None:
|
||||
return 0
|
||||
cmp_vt: llvmlite.Value | t.CPtr = llvmlite.build_icmp(
|
||||
builder, llvmlite.ICMP_EQ, vtable_ptr, class_vt)
|
||||
if cmp_vt is None:
|
||||
return 0
|
||||
# 块名唯一化(create_block 不自动编号;同函数多次 vtable 写入(如
|
||||
# devfs open/close/read/write 连续赋值)同名 label 冲突)
|
||||
vtc3: int = trans._label_counter
|
||||
trans._label_counter = vtc3 + 1
|
||||
vt_bb_buf3: str = pool.alloc(64)
|
||||
if vt_bb_buf3 is None:
|
||||
return 0
|
||||
viperlib.snprintf(vt_bb_buf3, 64, "vt.copy.%d", vtc3)
|
||||
vt_copy_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
|
||||
pool, trans._cur_func, vt_bb_buf3)
|
||||
viperlib.snprintf(vt_bb_buf3, 64, "vt.skip.%d", vtc3)
|
||||
vt_skip_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
|
||||
pool, trans._cur_func, vt_bb_buf3)
|
||||
if vt_copy_bb is None or vt_skip_bb is None:
|
||||
return 0
|
||||
llvmlite.build_cond_br(builder, cmp_vt, vt_copy_bb, vt_skip_bb)
|
||||
# copy 块:创建 internal 副本全局(zeroinit)+ memcpy + 对象指向副本
|
||||
llvmlite.position_at_end(builder, vt_copy_bb)
|
||||
vtc: int = trans._label_counter
|
||||
trans._label_counter = vtc + 1
|
||||
vcopy_buf: str = pool.alloc(256)
|
||||
if vcopy_buf is not None:
|
||||
viperlib.snprintf(vcopy_buf, 256, "%s.vtable.copy.%d", class_name, vtc)
|
||||
vcopy_gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(
|
||||
pool, vcopy_buf, vtable_ty)
|
||||
if vcopy_gv is not None:
|
||||
llvmlite.module_add_global(mod, vcopy_gv)
|
||||
vcopy_gv.Linkage = None
|
||||
vcopy_gv.Initializer = "zeroinitializer"
|
||||
vcopy_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue(
|
||||
pool, llvmlite.Ptr(pool, vtable_ty), vcopy_buf)
|
||||
if vcopy_ref is not None:
|
||||
vcopy_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||||
builder, vcopy_ref, i8_ptr_ty)
|
||||
if vcopy_i8 is not None:
|
||||
vt_size: llvmlite.Value | t.CPtr = llvmlite.ConstInt(
|
||||
pool, llvmlite.Int64(pool), method_count * 8, "vtsz")
|
||||
if vt_size is not None:
|
||||
self.Gen.CallGenLib._emit_llvm_memcpy_intrinsic(
|
||||
pool, builder, mod, vcopy_i8, class_vt, vt_size)
|
||||
llvmlite.build_store(builder, vcopy_i8, vtable_slot)
|
||||
llvmlite.build_br(builder, vt_skip_bb)
|
||||
# skip 块:reload vtable → GEP 槽位 → store 函数指针(i8*)
|
||||
llvmlite.position_at_end(builder, vt_skip_bb)
|
||||
vt_ptr2: llvmlite.Value | t.CPtr = llvmlite.build_load(
|
||||
builder, i8_ptr_ty, vtable_slot)
|
||||
if vt_ptr2 is None:
|
||||
return 0
|
||||
vt_typed: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||||
builder, vt_ptr2, llvmlite.Ptr(pool, vtable_ty))
|
||||
if vt_typed is None:
|
||||
return 0
|
||||
vt_slotp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
|
||||
builder, vtable_ty, i8_ptr_ty, vt_typed, method_index)
|
||||
if vt_slotp is None:
|
||||
return 0
|
||||
fptr_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||||
builder, func_val, i8_ptr_ty)
|
||||
if fptr_i8 is not None:
|
||||
llvmlite.build_store(builder, fptr_i8, vt_slotp)
|
||||
return 1
|
||||
def _write_vtable_attr(self, builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
rhs_val: llvmlite.Value | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> int:
|
||||
"""属性写入 obj.method = func:检测 vtable 方法并生成槽位写入(成功返回 1)"""
|
||||
if node is None or builder is None or pool is None or mod is None:
|
||||
return 0
|
||||
if rhs_val is None or trans is None:
|
||||
return 0
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
|
||||
if at is None or at.value is None or at.attr is None:
|
||||
return 0
|
||||
# 解析类名(AnnotClassName;去模块前缀)
|
||||
class_nm_v: str = None
|
||||
if at.value.kind() == ast.ASTKind.Name:
|
||||
nm_v: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
|
||||
if nm_v.id is not None:
|
||||
ve_v: GenTypes.VarEntry | t.CPtr = self.Gen.VarGen.lookup_var_entry(
|
||||
trans.SymTab, nm_v.id)
|
||||
if ve_v is not None:
|
||||
class_nm_v = ve_v.AnnotClassName
|
||||
elif at.value.kind() == ast.ASTKind.Attribute:
|
||||
# 跨 Mixin:_resolve_attr_field_class 定义在 ExprGenAttr,经 self.Gen 调用
|
||||
class_nm_v = self.Gen.ExprGenAttr._resolve_attr_field_class(pool, trans, at.value)
|
||||
if class_nm_v is None:
|
||||
return 0
|
||||
fd_dot_v: str = string.strrchr(class_nm_v, '.')
|
||||
if fd_dot_v is not None:
|
||||
class_nm_v = fd_dot_v + 1
|
||||
if self.Gen.StructGen.get_struct_type(class_nm_v) is None:
|
||||
return 0
|
||||
vm_idx_v: int = self.Gen.StructGen.get_vtable_method_index(class_nm_v, at.attr)
|
||||
if vm_idx_v < 0:
|
||||
return 0
|
||||
# 解析 obj_ptr(对齐 get_attribute_ptr 前半段:Name 直接查 alloca)
|
||||
obj_ptr_v: llvmlite.Value | t.CPtr = None
|
||||
if at.value.kind() == ast.ASTKind.Name:
|
||||
obj_ptr_v = self.Gen.VarGen.lookup_var(
|
||||
trans.SymTab, ((ast.Name | t.CPtr)(at.value)).id)
|
||||
else:
|
||||
obj_ptr_v = self.Gen.ExprGen.translate_value(
|
||||
builder, pool, mod, at.value, None, 0, trans)
|
||||
if obj_ptr_v is None or obj_ptr_v.Ty is None:
|
||||
return 0
|
||||
# X|t.CPtr 变量(Ptr(Ptr))load 解引用取对象指针
|
||||
match obj_ptr_v.Ty:
|
||||
case llvmlite.LLVMType.Ptr(inner_v):
|
||||
match inner_v:
|
||||
case llvmlite.LLVMType.Ptr(_):
|
||||
obj_ptr_v = llvmlite.build_load(builder, inner_v, obj_ptr_v)
|
||||
case _:
|
||||
pass
|
||||
case _:
|
||||
pass
|
||||
if obj_ptr_v is None:
|
||||
return 0
|
||||
return self._write_vtable_slot(
|
||||
pool, builder, mod, obj_ptr_v, class_nm_v, vm_idx_v, rhs_val, trans)
|
||||
+1161
-1119
File diff suppressed because it is too large.
Load diff
+570
-576
File diff suppressed because it is too large.
Load diff
+1155
-1161
File diff suppressed because it is too large.
Load diff
+708
-714
File diff suppressed because it is too large.
Load diff
@@ -1,32 +1,25 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.Gen.ClassGenBase as ClassGenBase
|
||||
|
||||
# ============================================================
|
||||
# ClassGenMixin - 类定义/继承/泛型/vtable/enum/union/renum
|
||||
#
|
||||
# 500~1500 行/文件架构重构阶段 D:全部方法已拆至
|
||||
# ClassGenBase/Enum/Generic/VTable/Def,本文件保留类声明。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class ClassGenMixin(ClassGenBase.ClassGenBase):
|
||||
"""类定义处理 Mixin(阶段 D 拆分后顶层,方法全部在子 Mixin)"""
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.Gen.ClassGenBase as ClassGenBase
|
||||
|
||||
# ============================================================
|
||||
# ClassGenMixin - 类定义/继承/泛型/vtable/enum/union/renum
|
||||
#
|
||||
# 500~1500 行/文件架构重构阶段 D:全部方法已拆至
|
||||
# ClassGenBase/Enum/Generic/VTable/Def,本文件保留类声明。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class ClassGenMixin(ClassGenBase.ClassGenBase):
|
||||
"""类定义处理 Mixin(阶段 D 拆分后顶层,方法全部在子 Mixin)"""
|
||||
+1308
-1314
File diff suppressed because it is too large.
Load diff
+1194
-1203
File diff suppressed because it is too large.
Load diff
+517
-513
File diff suppressed because it is too large.
Load diff
+1079
-1088
File diff suppressed because it is too large.
Load diff
+492
-502
@@ -1,503 +1,493 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprOps as HandlesExprOps
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.Projectrans.Config as Config
|
||||
import lib.Projectrans.Utils as Utils
|
||||
|
||||
|
||||
import lib.core.Gen.ExprGenBase as ExprGenBase
|
||||
import lib.core.StubMergerStore as StubMergerStore
|
||||
import lib.core.Handles.ExprCallBase as ExprCallBase
|
||||
|
||||
# ============================================================
|
||||
# docstring 登记表容量常量(与 ExprGenMixin 保持一致,本地副本避免
|
||||
# 跨模块 CDefine 查找 bug:ExprGenCls(C) 在 ExprGenMixin(M) 之前按
|
||||
# 文件序编译时,跨模块 CDefine 全局表未注册 → NameError 未定义)
|
||||
# ============================================================
|
||||
DOC_MAX: t.CDefine = 512
|
||||
DOC_KEY_SZ: t.CDefine = 192
|
||||
DOC_VAL_SZ: t.CDefine = 4096
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ExprGenCls - ExprGenMixin 拆分(阶段 D):类名推断/docstring 登记
|
||||
#
|
||||
# 继承 ExprGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesExpr 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class ExprGenCls(ExprGenBase.ExprGenBase):
|
||||
"""类名推断/docstring 登记"""
|
||||
|
||||
# ============================================================
|
||||
# docstring 提取/登记/查找(__doc__ 魔法属性支持)
|
||||
#
|
||||
# 预注册阶段(BuildPipeline.TranslateFileGetTrans)扫描所有
|
||||
# App/includes 文件的 AST,提取函数/类/方法的 docstring 内容
|
||||
# 登记到全局表(key = "{module_sha1}.{symbol}");__doc__ 属性
|
||||
# 访问时查表,命中则当前模块内联生成字符串常量(无跨模块 IR
|
||||
# 符号依赖),未命中返回 null。幂等查重,多遍翻译安全。
|
||||
# ============================================================
|
||||
|
||||
def _extract_docstring_from_body(self, body: list[ast.AST | t.CPtr] | t.CPtr) -> str:
|
||||
"""从函数/类体提取 docstring:body[0] 为 Expr(Constant str) 时返回内容"""
|
||||
if body is None or len(body) == 0:
|
||||
return None
|
||||
first: ast.AST | t.CPtr = body.get(0)
|
||||
if first is None or first.kind() != ast.ASTKind.Expr:
|
||||
return None
|
||||
ex: ast.Expr | t.CPtr = (ast.Expr | t.CPtr)(first)
|
||||
if ex is None or ex.value is None or ex.value.kind() != ast.ASTKind.Constant:
|
||||
return None
|
||||
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(ex.value)
|
||||
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 self.DocKeys is None:
|
||||
self.DocKeys = CompilerFactory.get_perm_pool().alloc(DOC_MAX * DOC_KEY_SZ)
|
||||
self.DocValues = CompilerFactory.get_perm_pool().alloc(DOC_MAX * DOC_VAL_SZ)
|
||||
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
|
||||
ml: t.CSizeT = string.strlen(module_sha1)
|
||||
sl: t.CSizeT = string.strlen(symbol)
|
||||
key_buf: bytes = stdlib.malloc(ml + sl + 2)
|
||||
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)
|
||||
return
|
||||
string.strcpy(self.DocKeys + self.DocCount * DOC_KEY_SZ, key_buf)
|
||||
string.strcpy(self.DocValues + self.DocCount * DOC_VAL_SZ, doc)
|
||||
self.DocCount += 1
|
||||
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
|
||||
ml: t.CSizeT = string.strlen(module_sha1)
|
||||
sl: t.CSizeT = string.strlen(symbol)
|
||||
key_buf: bytes = stdlib.malloc(ml + sl + 2)
|
||||
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)
|
||||
return self.DocValues + i * DOC_VAL_SZ
|
||||
stdlib.free(key_buf)
|
||||
return None
|
||||
def extract_module_docstrings(self, tree: ast.AST | t.CPtr, module_sha1: str) -> None:
|
||||
"""扫描模块 AST:登记模块级函数/类/方法的 docstring(幂等)"""
|
||||
if tree is None or module_sha1 is None:
|
||||
return
|
||||
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
|
||||
if ch is None:
|
||||
return
|
||||
cn: t.CSizeT = len(ch)
|
||||
for ci in range(cn):
|
||||
child: ast.AST | t.CPtr = ch.get(ci)
|
||||
if child is None:
|
||||
continue
|
||||
kd: int = child.kind()
|
||||
if kd == ast.ASTKind.FunctionDef:
|
||||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child)
|
||||
if fd is not None and fd.name is not None:
|
||||
fd_body: list[ast.AST | t.CPtr] | t.CPtr = fd.children
|
||||
fdoc: str = self._extract_docstring_from_body(fd_body)
|
||||
if fdoc is not None:
|
||||
self.register_docstring(module_sha1, fd.name, fdoc)
|
||||
elif kd == ast.ASTKind.ClassDef:
|
||||
cd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(child)
|
||||
if cd is None or cd.name is None:
|
||||
continue
|
||||
cd_body0: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||||
cdoc: str = self._extract_docstring_from_body(cd_body0)
|
||||
if cdoc is not None:
|
||||
self.register_docstring(module_sha1, cd.name, cdoc)
|
||||
# 类方法 docstring(key="{ClassName}.{method}")
|
||||
cd_body: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||||
if cd_body is not None:
|
||||
cbn: t.CSizeT = len(cd_body)
|
||||
for mi in range(cbn):
|
||||
m: ast.AST | t.CPtr = cd_body.get(mi)
|
||||
if m is None or m.kind() != ast.ASTKind.FunctionDef:
|
||||
continue
|
||||
mfd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(m)
|
||||
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: t.CSizeT = string.strlen(cd.name)
|
||||
mt_nl: t.CSizeT = string.strlen(mfd.name)
|
||||
sym_buf: bytes = stdlib.malloc(cl_nl + mt_nl + 2)
|
||||
if sym_buf is not None:
|
||||
viperlib.snprintf(sym_buf, cl_nl + mt_nl + 2, "%s.%s", cd.name, mfd.name)
|
||||
self.register_docstring(module_sha1, sym_buf, mdoc)
|
||||
stdlib.free(sym_buf)
|
||||
def _resolve_doc_symbol_name(self, trans: HT.Translator | t.CPtr, name_id: str,
|
||||
out_mod: str | t.CPtr, out_sym: str | t.CPtr) -> int:
|
||||
"""解析 Name 符号的 docstring 归属,写入 out_mod/out_sym,成功返回 1
|
||||
|
||||
判定顺序:本地变量(函数变量)→ 结构体类(含跨模块预注册)→ 模块名。
|
||||
"""
|
||||
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 HandlesVar.lookup_var(trans.SymTab, name_id) is not None:
|
||||
string.strcpy(out_mod, trans.ModuleSha1)
|
||||
string.strcpy(out_sym, name_id)
|
||||
return 1
|
||||
# 2. 结构体类(entry.ModuleSha1 区分跨模块预注册的类)
|
||||
se: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(name_id)
|
||||
if se is not None:
|
||||
if se.ModuleSha1 is not None:
|
||||
string.strcpy(out_mod, se.ModuleSha1)
|
||||
else:
|
||||
string.strcpy(out_mod, trans.ModuleSha1)
|
||||
string.strcpy(out_sym, name_id)
|
||||
return 1
|
||||
# 3. 模块名(模块本身,少见);用 StubMerger 模块级函数(避免
|
||||
# 跨 Mixin self 调用生成不存在符号)
|
||||
mod_sha1: str = StubMergerStore.LookupSha1ByModName(name_id)
|
||||
if mod_sha1 is None:
|
||||
mod_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(name_id)
|
||||
if mod_sha1 is not None:
|
||||
string.strcpy(out_mod, mod_sha1)
|
||||
string.strcpy(out_sym, name_id)
|
||||
return 1
|
||||
# 4. 兜底当前模块
|
||||
string.strcpy(out_mod, trans.ModuleSha1)
|
||||
string.strcpy(out_sym, name_id)
|
||||
return 1
|
||||
def _resolve_doc_symbol_attr(self, trans: HT.Translator | t.CPtr,
|
||||
at: ast.Attribute | t.CPtr,
|
||||
out_mod: str | t.CPtr, out_sym: str | t.CPtr) -> int:
|
||||
"""解析嵌套 Attribute 链的 docstring 归属,写入 out_mod/out_sym
|
||||
|
||||
支持形态:remote.remote_func / remote.RemoteClass /
|
||||
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
|
||||
# 收集 Attribute 链(最外层 attr 在前)
|
||||
DOC_CHAIN_MAX: t.CInt = 8
|
||||
items: bytes = stdlib.malloc(DOC_CHAIN_MAX * 128)
|
||||
if items is None:
|
||||
return 0
|
||||
n_items: int = 0
|
||||
cur: ast.AST | t.CPtr = (ast.AST | t.CPtr)(at)
|
||||
while cur is not None and cur.kind() == ast.ASTKind.Attribute and n_items < DOC_CHAIN_MAX:
|
||||
cat: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cur)
|
||||
if cat.attr is None:
|
||||
break
|
||||
string.strcpy(items + n_items * 128, cat.attr)
|
||||
n_items += 1
|
||||
cur = cat.value
|
||||
# 最左应为 Name
|
||||
head_id: str = None
|
||||
if cur is not None and cur.kind() == ast.ASTKind.Name:
|
||||
hnm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cur)
|
||||
head_id = hnm.id
|
||||
if head_id is None:
|
||||
stdlib.free(items)
|
||||
return 0
|
||||
# head 判定:模块名 or 变量/类
|
||||
is_mod: int = 0
|
||||
mod_sha1: str = None
|
||||
if HandlesVar.lookup_var(trans.SymTab, head_id) is None:
|
||||
mod_sha1 = StubMergerStore.LookupSha1ByModName(head_id)
|
||||
if mod_sha1 is None:
|
||||
mod_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(head_id)
|
||||
if mod_sha1 is not None:
|
||||
is_mod = 1
|
||||
if is_mod != 0:
|
||||
# 模块限定:symbol = items 反转(不含 head_id)
|
||||
if n_items == 0:
|
||||
string.strcpy(out_mod, mod_sha1)
|
||||
string.strcpy(out_sym, head_id)
|
||||
stdlib.free(items)
|
||||
return 1
|
||||
total: t.CSizeT = 0
|
||||
j: int
|
||||
for j in range(n_items):
|
||||
total += string.strlen(items + j * 128) + 1
|
||||
sym_buf: bytes = stdlib.malloc(total + 1)
|
||||
if sym_buf is None:
|
||||
stdlib.free(items)
|
||||
return 0
|
||||
sym_buf[0] = '\0'
|
||||
for j in range(n_items):
|
||||
if j > 0:
|
||||
string.strcat(sym_buf, ".")
|
||||
string.strcat(sym_buf, items + (n_items - 1 - j) * 128)
|
||||
string.strcpy(out_mod, mod_sha1)
|
||||
string.strcpy(out_sym, sym_buf)
|
||||
stdlib.free(sym_buf)
|
||||
stdlib.free(items)
|
||||
return 1
|
||||
# 变量/类:symbol = head_id + '.' + items 反转
|
||||
total2: t.CSizeT = string.strlen(head_id)
|
||||
for j in range(n_items):
|
||||
total2 += string.strlen(items + j * 128) + 1
|
||||
sym2: bytes = stdlib.malloc(total2 + 1)
|
||||
if sym2 is None:
|
||||
stdlib.free(items)
|
||||
return 0
|
||||
sym2[0] = '\0'
|
||||
string.strcat(sym2, head_id)
|
||||
for j in range(n_items):
|
||||
string.strcat(sym2, ".")
|
||||
string.strcat(sym2, items + (n_items - 1 - j) * 128)
|
||||
se2: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(head_id)
|
||||
if se2 is not None and se2.ModuleSha1 is not None:
|
||||
string.strcpy(out_mod, se2.ModuleSha1)
|
||||
else:
|
||||
string.strcpy(out_mod, trans.ModuleSha1)
|
||||
string.strcpy(out_sym, sym2)
|
||||
stdlib.free(sym2)
|
||||
stdlib.free(items)
|
||||
return 1
|
||||
# ============================================================
|
||||
# P3 迁移方法(来自 HandlesExprOps.vp:运算符重载 + 二元运算)
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# infer_expr_class - 从表达式推断结构体类名(共享推断)
|
||||
#
|
||||
# 无注解赋值(HandlesAssign)与方法调用分派(CallGenMixin)共用:
|
||||
# 联合类型 X|t.CPtr 简化为 Ptr(i8),不含类名,需按表达式结构推断:
|
||||
# Call → 类实例化(func 为已注册结构体名);func 为 Attribute
|
||||
# 时是方法调用,经 vpi 返回注解缓存解析返回类名
|
||||
# Name → 源变量的 AnnotClassName
|
||||
# BinOp/UnaryOp → lhs 类名 + 存在对应 dunder 方法(返回同类对象)
|
||||
# Attribute → 字段注解类名(_resolve_attr_field_class)
|
||||
# 仅采用已注册结构体;无法精确推断返回 None(fail-fast 由调用方暴露)。
|
||||
# ============================================================
|
||||
def infer_expr_class(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> str:
|
||||
"""从表达式推断结构体类名,无法推断返回 None"""
|
||||
if node is None or trans is None:
|
||||
return None
|
||||
k: int = node.kind()
|
||||
# Call: 类实例化 / 方法调用
|
||||
if k == ast.ASTKind.Call:
|
||||
cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node)
|
||||
if cl is None or cl.func is None:
|
||||
return None
|
||||
if cl.func.kind() == ast.ASTKind.Name:
|
||||
cand: str = ((ast.Name | t.CPtr)(cl.func)).id
|
||||
if cand is None:
|
||||
return None
|
||||
if HandlesStruct.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 | t.CPtr = (ast.Attribute | t.CPtr)(cl.func)
|
||||
if ca is None or ca.attr is None or ca.value is None:
|
||||
return None
|
||||
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
|
||||
cls_sha1: str = HandlesStruct.get_struct_sha1(obj_cls)
|
||||
if cls_sha1 is None and trans.ModuleSha1 is not None:
|
||||
cls_sha1 = trans.ModuleSha1
|
||||
ret_cls: str = None
|
||||
if cls_sha1 is not None:
|
||||
import lib.StubGen.VpiReader as VpiReader
|
||||
temp_dir: str = None
|
||||
# 跨 Mixin 不能 self 访问 Generator 的 TempDir 字段(字段按
|
||||
# 声明类隔离),经全局单例获取(同 HandlesAssign 模式)
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g2: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(
|
||||
t.CVoid(HandlesExpr._g_gen, t.CPtr))
|
||||
if g2 is not None and g2.TempDir is not None:
|
||||
temp_dir = g2.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)
|
||||
if annot_ret is not None:
|
||||
ret_cls = self._extract_annot_class_name(pool, annot_ret)
|
||||
return ret_cls
|
||||
return None
|
||||
# Name: 源变量注解
|
||||
if k == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
|
||||
if nm is None or nm.id is None:
|
||||
return None
|
||||
ve: HandlesVar.VarEntry | t.CPtr = HandlesVar.lookup_var_entry(
|
||||
trans.SymTab, nm.id)
|
||||
if ve is None:
|
||||
return None
|
||||
acn_n: str = ve.AnnotClassName
|
||||
if acn_n is None:
|
||||
return None
|
||||
# 去模块前缀:json.JsonValue → JsonValue。AnnotClassName 可能带
|
||||
# 模块限定(extract_class_name_from_annotation 的 Attribute 分支返回
|
||||
# "memhub.MemBuddy" 形式),而 find_struct/_cls_has_dunder/
|
||||
# get_struct_sha1 查找都用裸类名(struct 注册名)。泛型名
|
||||
# (list[str] 含 '[')不截断(方括号内可能有点号)。
|
||||
acn_dot_n: str = string.strrchr(acn_n, 46)
|
||||
if acn_dot_n is not None and string.strchr(acn_n, 91) is None:
|
||||
acn_n = acn_dot_n + 1
|
||||
return acn_n
|
||||
# BinOp/UnaryOp: 运算符重载返回同类对象
|
||||
if k == ast.ASTKind.BinOp:
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
|
||||
if bop is None or bop.left is None:
|
||||
return None
|
||||
dunder: str = HandlesExpr._binop_to_dunder(bop.op)
|
||||
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
|
||||
return lhs_cls
|
||||
if k == ast.ASTKind.UnaryOp:
|
||||
uop: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(node)
|
||||
if uop is None or uop.operand is None:
|
||||
return None
|
||||
dunder: str = HandlesExpr._unaryop_to_dunder(uop.op)
|
||||
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
|
||||
return opr_cls
|
||||
# Attribute: 字段注解类名(属性链递归,如 p = r.origin)
|
||||
if k == ast.ASTKind.Attribute:
|
||||
return HandlesExpr._resolve_attr_field_class(pool, trans, node)
|
||||
return None
|
||||
# ============================================================
|
||||
# _cls_has_dunder - 检查类(含继承链)是否存在 dunder/方法
|
||||
#
|
||||
# 与 try_operator_overload 的查找一致:当前模块内定义或跨模块类有
|
||||
# SHA1(stub 中声明)即视为存在。仅在确实存在时采用推断类名,
|
||||
# 避免把原生运算误标为类类型。
|
||||
# ============================================================
|
||||
def _cls_has_dunder(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
class_name: str, dunder: str) -> int:
|
||||
"""类及其 MRO 祖先链中是否存在 dunder 方法,存在返回 1"""
|
||||
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
|
||||
viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, dunder)
|
||||
if ExprCallBase.find_func_in_module(mod, lookup_name) is not None:
|
||||
return 1
|
||||
# 继承链祖先查找
|
||||
mro_ptr: t.CSizeT | t.CPtr = HandlesStruct.get_mro_chain(pool, class_name)
|
||||
mi: int = 1
|
||||
while mro_ptr is not None and mro_ptr[mi] != 0:
|
||||
anc: str = (str | t.CPtr)(t.CVoid(mro_ptr[mi], t.CPtr))
|
||||
if anc is not None:
|
||||
anc_lookup: str = pool.alloc(128)
|
||||
if anc_lookup is not None:
|
||||
viperlib.snprintf(anc_lookup, 128, "%s.%s", anc, dunder)
|
||||
if ExprCallBase.find_func_in_module(mod, anc_lookup) is not None:
|
||||
return 1
|
||||
mi += 1
|
||||
# 跨模块:类有 SHA1(stub 中声明该方法)视为存在
|
||||
if HandlesStruct.get_struct_sha1(class_name) is not None:
|
||||
return 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# _extract_annot_class_name - 从返回注解文本提取结构体类名
|
||||
#
|
||||
# vpi 返回注解文本(如 "'Vec3' | CPtr")按 '|' 分段,每段去除
|
||||
# 空格/引号后查结构体注册表:命中即类名(内置类型 str/int/
|
||||
# CFloat64T/t.CPtr 等均不注册 struct,天然过滤)。"A | B" 联合
|
||||
# 多候选时取首个命中段。
|
||||
# ============================================================
|
||||
def _extract_annot_class_name(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
annot: str) -> str:
|
||||
"""从返回注解文本提取已注册结构体类名,无命中返回 None"""
|
||||
if pool is None or annot is None:
|
||||
return None
|
||||
alen: t.CSizeT = string.strlen(annot)
|
||||
if alen == 0:
|
||||
return None
|
||||
seg: str = pool.alloc(256)
|
||||
if seg is None:
|
||||
return None
|
||||
start: t.CSizeT = 0
|
||||
i: t.CSizeT
|
||||
for i in range(alen):
|
||||
if annot[i] == '|':
|
||||
s: t.CSizeT = start
|
||||
e: t.CSizeT = i
|
||||
while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'):
|
||||
s += 1
|
||||
while e > s and (annot[e - 1] == ' ' or annot[e - 1] == '\'' or annot[e - 1] == '"'):
|
||||
e -= 1
|
||||
seglen: t.CSizeT = e - s
|
||||
if seglen > 0 and seglen < 256:
|
||||
string.strncpy(seg, annot + s, seglen)
|
||||
seg[seglen] = '\0'
|
||||
if HandlesStruct.find_struct(seg) is not None:
|
||||
return seg
|
||||
start = i + 1
|
||||
# 最后一段(无 '|' 后缀)
|
||||
s: t.CSizeT = start
|
||||
e: t.CSizeT = alen
|
||||
while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'):
|
||||
s += 1
|
||||
while e > s and (annot[e - 1] == ' ' or annot[e - 1] == '\'' or annot[e - 1] == '"'):
|
||||
e -= 1
|
||||
seglen: t.CSizeT = e - s
|
||||
if seglen > 0 and seglen < 256:
|
||||
string.strncpy(seg, annot + s, seglen)
|
||||
seg[seglen] = '\0'
|
||||
if HandlesStruct.find_struct(seg) is not None:
|
||||
return seg
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import lib.core.Gen.CallGenBase as CallGenBase
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.Projectrans.Config as Config
|
||||
import lib.Projectrans.Utils as Utils
|
||||
|
||||
|
||||
import lib.core.Gen.ExprGenBase as ExprGenBase
|
||||
import lib.core.StubMergerStore as StubMergerStore
|
||||
|
||||
# ============================================================
|
||||
# docstring 登记表容量常量(与 ExprGenMixin 保持一致,本地副本避免
|
||||
# 跨模块 CDefine 查找 bug:ExprGenCls(C) 在 ExprGenMixin(M) 之前按
|
||||
# 文件序编译时,跨模块 CDefine 全局表未注册 → NameError 未定义)
|
||||
# ============================================================
|
||||
DOC_MAX: t.CDefine = 512
|
||||
DOC_KEY_SZ: t.CDefine = 192
|
||||
DOC_VAL_SZ: t.CDefine = 4096
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ExprGenCls - ExprGenMixin 拆分(阶段 D):类名推断/docstring 登记
|
||||
#
|
||||
# 继承 ExprGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesExpr 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class ExprGenCls(ExprGenBase.ExprGenBase):
|
||||
"""类名推断/docstring 登记"""
|
||||
|
||||
# ============================================================
|
||||
# docstring 提取/登记/查找(__doc__ 魔法属性支持)
|
||||
#
|
||||
# 预注册阶段(BuildPipeline.TranslateFileGetTrans)扫描所有
|
||||
# App/includes 文件的 AST,提取函数/类/方法的 docstring 内容
|
||||
# 登记到全局表(key = "{module_sha1}.{symbol}");__doc__ 属性
|
||||
# 访问时查表,命中则当前模块内联生成字符串常量(无跨模块 IR
|
||||
# 符号依赖),未命中返回 null。幂等查重,多遍翻译安全。
|
||||
# ============================================================
|
||||
|
||||
def _extract_docstring_from_body(self, body: list[ast.AST | t.CPtr] | t.CPtr) -> str:
|
||||
"""从函数/类体提取 docstring:body[0] 为 Expr(Constant str) 时返回内容"""
|
||||
if body is None or len(body) == 0:
|
||||
return None
|
||||
first: ast.AST | t.CPtr = body.get(0)
|
||||
if first is None or first.kind() != ast.ASTKind.Expr:
|
||||
return None
|
||||
ex: ast.Expr | t.CPtr = (ast.Expr | t.CPtr)(first)
|
||||
if ex is None or ex.value is None or ex.value.kind() != ast.ASTKind.Constant:
|
||||
return None
|
||||
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(ex.value)
|
||||
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 self.DocKeys is None:
|
||||
self.DocKeys = CompilerFactory.get_perm_pool().alloc(DOC_MAX * DOC_KEY_SZ)
|
||||
self.DocValues = CompilerFactory.get_perm_pool().alloc(DOC_MAX * DOC_VAL_SZ)
|
||||
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
|
||||
ml: t.CSizeT = string.strlen(module_sha1)
|
||||
sl: t.CSizeT = string.strlen(symbol)
|
||||
key_buf: bytes = stdlib.malloc(ml + sl + 2)
|
||||
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)
|
||||
return
|
||||
string.strcpy(self.DocKeys + self.DocCount * DOC_KEY_SZ, key_buf)
|
||||
string.strcpy(self.DocValues + self.DocCount * DOC_VAL_SZ, doc)
|
||||
self.DocCount += 1
|
||||
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
|
||||
ml: t.CSizeT = string.strlen(module_sha1)
|
||||
sl: t.CSizeT = string.strlen(symbol)
|
||||
key_buf: bytes = stdlib.malloc(ml + sl + 2)
|
||||
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)
|
||||
return self.DocValues + i * DOC_VAL_SZ
|
||||
stdlib.free(key_buf)
|
||||
return None
|
||||
def extract_module_docstrings(self, tree: ast.AST | t.CPtr, module_sha1: str) -> None:
|
||||
"""扫描模块 AST:登记模块级函数/类/方法的 docstring(幂等)"""
|
||||
if tree is None or module_sha1 is None:
|
||||
return
|
||||
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
|
||||
if ch is None:
|
||||
return
|
||||
cn: t.CSizeT = len(ch)
|
||||
for ci in range(cn):
|
||||
child: ast.AST | t.CPtr = ch.get(ci)
|
||||
if child is None:
|
||||
continue
|
||||
kd: int = child.kind()
|
||||
if kd == ast.ASTKind.FunctionDef:
|
||||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child)
|
||||
if fd is not None and fd.name is not None:
|
||||
fd_body: list[ast.AST | t.CPtr] | t.CPtr = fd.children
|
||||
fdoc: str = self._extract_docstring_from_body(fd_body)
|
||||
if fdoc is not None:
|
||||
self.register_docstring(module_sha1, fd.name, fdoc)
|
||||
elif kd == ast.ASTKind.ClassDef:
|
||||
cd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(child)
|
||||
if cd is None or cd.name is None:
|
||||
continue
|
||||
cd_body0: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||||
cdoc: str = self._extract_docstring_from_body(cd_body0)
|
||||
if cdoc is not None:
|
||||
self.register_docstring(module_sha1, cd.name, cdoc)
|
||||
# 类方法 docstring(key="{ClassName}.{method}")
|
||||
cd_body: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||||
if cd_body is not None:
|
||||
cbn: t.CSizeT = len(cd_body)
|
||||
for mi in range(cbn):
|
||||
m: ast.AST | t.CPtr = cd_body.get(mi)
|
||||
if m is None or m.kind() != ast.ASTKind.FunctionDef:
|
||||
continue
|
||||
mfd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(m)
|
||||
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: t.CSizeT = string.strlen(cd.name)
|
||||
mt_nl: t.CSizeT = string.strlen(mfd.name)
|
||||
sym_buf: bytes = stdlib.malloc(cl_nl + mt_nl + 2)
|
||||
if sym_buf is not None:
|
||||
viperlib.snprintf(sym_buf, cl_nl + mt_nl + 2, "%s.%s", cd.name, mfd.name)
|
||||
self.register_docstring(module_sha1, sym_buf, mdoc)
|
||||
stdlib.free(sym_buf)
|
||||
def _resolve_doc_symbol_name(self, trans: HT.Translator | t.CPtr, name_id: str,
|
||||
out_mod: str | t.CPtr, out_sym: str | t.CPtr) -> int:
|
||||
"""解析 Name 符号的 docstring 归属,写入 out_mod/out_sym,成功返回 1
|
||||
|
||||
判定顺序:本地变量(函数变量)→ 结构体类(含跨模块预注册)→ 模块名。
|
||||
"""
|
||||
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)
|
||||
string.strcpy(out_sym, name_id)
|
||||
return 1
|
||||
# 2. 结构体类(entry.ModuleSha1 区分跨模块预注册的类)
|
||||
se: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct(name_id)
|
||||
if se is not None:
|
||||
if se.ModuleSha1 is not None:
|
||||
string.strcpy(out_mod, se.ModuleSha1)
|
||||
else:
|
||||
string.strcpy(out_mod, trans.ModuleSha1)
|
||||
string.strcpy(out_sym, name_id)
|
||||
return 1
|
||||
# 3. 模块名(模块本身,少见);用 StubMerger 模块级函数(避免
|
||||
# 跨 Mixin self 调用生成不存在符号)
|
||||
mod_sha1: str = StubMergerStore.LookupSha1ByModName(name_id)
|
||||
if mod_sha1 is None:
|
||||
mod_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(name_id)
|
||||
if mod_sha1 is not None:
|
||||
string.strcpy(out_mod, mod_sha1)
|
||||
string.strcpy(out_sym, name_id)
|
||||
return 1
|
||||
# 4. 兜底当前模块
|
||||
string.strcpy(out_mod, trans.ModuleSha1)
|
||||
string.strcpy(out_sym, name_id)
|
||||
return 1
|
||||
def _resolve_doc_symbol_attr(self, trans: HT.Translator | t.CPtr,
|
||||
at: ast.Attribute | t.CPtr,
|
||||
out_mod: str | t.CPtr, out_sym: str | t.CPtr) -> int:
|
||||
"""解析嵌套 Attribute 链的 docstring 归属,写入 out_mod/out_sym
|
||||
|
||||
支持形态:remote.remote_func / remote.RemoteClass /
|
||||
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
|
||||
# 收集 Attribute 链(最外层 attr 在前)
|
||||
DOC_CHAIN_MAX: t.CInt = 8
|
||||
items: bytes = stdlib.malloc(DOC_CHAIN_MAX * 128)
|
||||
if items is None:
|
||||
return 0
|
||||
n_items: int = 0
|
||||
cur: ast.AST | t.CPtr = (ast.AST | t.CPtr)(at)
|
||||
while cur is not None and cur.kind() == ast.ASTKind.Attribute and n_items < DOC_CHAIN_MAX:
|
||||
cat: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cur)
|
||||
if cat.attr is None:
|
||||
break
|
||||
string.strcpy(items + n_items * 128, cat.attr)
|
||||
n_items += 1
|
||||
cur = cat.value
|
||||
# 最左应为 Name
|
||||
head_id: str = None
|
||||
if cur is not None and cur.kind() == ast.ASTKind.Name:
|
||||
hnm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cur)
|
||||
head_id = hnm.id
|
||||
if head_id is None:
|
||||
stdlib.free(items)
|
||||
return 0
|
||||
# head 判定:模块名 or 变量/类
|
||||
is_mod: int = 0
|
||||
mod_sha1: str = None
|
||||
if self.Gen.VarGen.lookup_var(trans.SymTab, head_id) is None:
|
||||
mod_sha1 = StubMergerStore.LookupSha1ByModName(head_id)
|
||||
if mod_sha1 is None:
|
||||
mod_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(head_id)
|
||||
if mod_sha1 is not None:
|
||||
is_mod = 1
|
||||
if is_mod != 0:
|
||||
# 模块限定:symbol = items 反转(不含 head_id)
|
||||
if n_items == 0:
|
||||
string.strcpy(out_mod, mod_sha1)
|
||||
string.strcpy(out_sym, head_id)
|
||||
stdlib.free(items)
|
||||
return 1
|
||||
total: t.CSizeT = 0
|
||||
j: int
|
||||
for j in range(n_items):
|
||||
total += string.strlen(items + j * 128) + 1
|
||||
sym_buf: bytes = stdlib.malloc(total + 1)
|
||||
if sym_buf is None:
|
||||
stdlib.free(items)
|
||||
return 0
|
||||
sym_buf[0] = '\0'
|
||||
for j in range(n_items):
|
||||
if j > 0:
|
||||
string.strcat(sym_buf, ".")
|
||||
string.strcat(sym_buf, items + (n_items - 1 - j) * 128)
|
||||
string.strcpy(out_mod, mod_sha1)
|
||||
string.strcpy(out_sym, sym_buf)
|
||||
stdlib.free(sym_buf)
|
||||
stdlib.free(items)
|
||||
return 1
|
||||
# 变量/类:symbol = head_id + '.' + items 反转
|
||||
total2: t.CSizeT = string.strlen(head_id)
|
||||
for j in range(n_items):
|
||||
total2 += string.strlen(items + j * 128) + 1
|
||||
sym2: bytes = stdlib.malloc(total2 + 1)
|
||||
if sym2 is None:
|
||||
stdlib.free(items)
|
||||
return 0
|
||||
sym2[0] = '\0'
|
||||
string.strcat(sym2, head_id)
|
||||
for j in range(n_items):
|
||||
string.strcat(sym2, ".")
|
||||
string.strcat(sym2, items + (n_items - 1 - j) * 128)
|
||||
se2: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct(head_id)
|
||||
if se2 is not None and se2.ModuleSha1 is not None:
|
||||
string.strcpy(out_mod, se2.ModuleSha1)
|
||||
else:
|
||||
string.strcpy(out_mod, trans.ModuleSha1)
|
||||
string.strcpy(out_sym, sym2)
|
||||
stdlib.free(sym2)
|
||||
stdlib.free(items)
|
||||
return 1
|
||||
# ============================================================
|
||||
# P3 迁移方法(来自 HandlesExprOps.vp:运算符重载 + 二元运算)
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# infer_expr_class - 从表达式推断结构体类名(共享推断)
|
||||
#
|
||||
# 无注解赋值(HandlesAssign)与方法调用分派(CallGenMixin)共用:
|
||||
# 联合类型 X|t.CPtr 简化为 Ptr(i8),不含类名,需按表达式结构推断:
|
||||
# Call → 类实例化(func 为已注册结构体名);func 为 Attribute
|
||||
# 时是方法调用,经 vpi 返回注解缓存解析返回类名
|
||||
# Name → 源变量的 AnnotClassName
|
||||
# BinOp/UnaryOp → lhs 类名 + 存在对应 dunder 方法(返回同类对象)
|
||||
# Attribute → 字段注解类名(_resolve_attr_field_class)
|
||||
# 仅采用已注册结构体;无法精确推断返回 None(fail-fast 由调用方暴露)。
|
||||
# ============================================================
|
||||
def infer_expr_class(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> str:
|
||||
"""从表达式推断结构体类名,无法推断返回 None"""
|
||||
if node is None or trans is None:
|
||||
return None
|
||||
k: int = node.kind()
|
||||
# Call: 类实例化 / 方法调用
|
||||
if k == ast.ASTKind.Call:
|
||||
cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node)
|
||||
if cl is None or cl.func is None:
|
||||
return None
|
||||
if cl.func.kind() == ast.ASTKind.Name:
|
||||
cand: str = ((ast.Name | t.CPtr)(cl.func)).id
|
||||
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 | t.CPtr = (ast.Attribute | t.CPtr)(cl.func)
|
||||
if ca is None or ca.attr is None or ca.value is None:
|
||||
return None
|
||||
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
|
||||
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
|
||||
ret_cls: str = None
|
||||
if cls_sha1 is not None:
|
||||
import lib.StubGen.VpiReader as VpiReader
|
||||
temp_dir: str = None
|
||||
# 跨子对象访问经 self.Gen 取 CallGenBase.TempDir(双向引用)
|
||||
if self.Gen.CallGenBase.TempDir is not None:
|
||||
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)
|
||||
if annot_ret is not None:
|
||||
ret_cls = self._extract_annot_class_name(pool, annot_ret)
|
||||
return ret_cls
|
||||
return None
|
||||
# Name: 源变量注解
|
||||
if k == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
|
||||
if nm is None or nm.id is None:
|
||||
return None
|
||||
ve: GenTypes.VarEntry | t.CPtr = self.Gen.VarGen.lookup_var_entry(
|
||||
trans.SymTab, nm.id)
|
||||
if ve is None:
|
||||
return None
|
||||
acn_n: str = ve.AnnotClassName
|
||||
if acn_n is None:
|
||||
return None
|
||||
# 去模块前缀:json.JsonValue → JsonValue。AnnotClassName 可能带
|
||||
# 模块限定(extract_class_name_from_annotation 的 Attribute 分支返回
|
||||
# "memhub.MemBuddy" 形式),而 find_struct/_cls_has_dunder/
|
||||
# get_struct_sha1 查找都用裸类名(struct 注册名)。泛型名
|
||||
# (list[str] 含 '[')不截断(方括号内可能有点号)。
|
||||
acn_dot_n: str = string.strrchr(acn_n, 46)
|
||||
if acn_dot_n is not None and string.strchr(acn_n, 91) is None:
|
||||
acn_n = acn_dot_n + 1
|
||||
return acn_n
|
||||
# BinOp/UnaryOp: 运算符重载返回同类对象
|
||||
if k == ast.ASTKind.BinOp:
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
|
||||
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
|
||||
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
|
||||
return lhs_cls
|
||||
if k == ast.ASTKind.UnaryOp:
|
||||
uop: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(node)
|
||||
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
|
||||
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
|
||||
return opr_cls
|
||||
# Attribute: 字段注解类名(属性链递归,如 p = r.origin)
|
||||
if k == ast.ASTKind.Attribute:
|
||||
return self.Gen.ExprGenAttr._resolve_attr_field_class(pool, trans, node)
|
||||
return None
|
||||
# ============================================================
|
||||
# _cls_has_dunder - 检查类(含继承链)是否存在 dunder/方法
|
||||
#
|
||||
# 与 try_operator_overload 的查找一致:当前模块内定义或跨模块类有
|
||||
# SHA1(stub 中声明)即视为存在。仅在确实存在时采用推断类名,
|
||||
# 避免把原生运算误标为类类型。
|
||||
# ============================================================
|
||||
def _cls_has_dunder(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
class_name: str, dunder: str) -> int:
|
||||
"""类及其 MRO 祖先链中是否存在 dunder 方法,存在返回 1"""
|
||||
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
|
||||
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
|
||||
# 继承链祖先查找
|
||||
mro_ptr: t.CSizeT | t.CPtr = self.Gen.StructGen.get_mro_chain(pool, class_name)
|
||||
mi: int = 1
|
||||
while mro_ptr is not None and mro_ptr[mi] != 0:
|
||||
anc: str = (str | t.CPtr)(t.CVoid(mro_ptr[mi], t.CPtr))
|
||||
if anc is not None:
|
||||
anc_lookup: str = pool.alloc(128)
|
||||
if anc_lookup is not None:
|
||||
viperlib.snprintf(anc_lookup, 128, "%s.%s", anc, dunder)
|
||||
if self.Gen.CallGenBase.find_func_in_module(mod, anc_lookup) is not None:
|
||||
return 1
|
||||
mi += 1
|
||||
# 跨模块:类有 SHA1(stub 中声明该方法)视为存在
|
||||
if self.Gen.StructGen.get_struct_sha1(class_name) is not None:
|
||||
return 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# _extract_annot_class_name - 从返回注解文本提取结构体类名
|
||||
#
|
||||
# vpi 返回注解文本(如 "'Vec3' | CPtr")按 '|' 分段,每段去除
|
||||
# 空格/引号后查结构体注册表:命中即类名(内置类型 str/int/
|
||||
# CFloat64T/t.CPtr 等均不注册 struct,天然过滤)。"A | B" 联合
|
||||
# 多候选时取首个命中段。
|
||||
# ============================================================
|
||||
def _extract_annot_class_name(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
annot: str) -> str:
|
||||
"""从返回注解文本提取已注册结构体类名,无命中返回 None"""
|
||||
if pool is None or annot is None:
|
||||
return None
|
||||
alen: t.CSizeT = string.strlen(annot)
|
||||
if alen == 0:
|
||||
return None
|
||||
seg: str = pool.alloc(256)
|
||||
if seg is None:
|
||||
return None
|
||||
start: t.CSizeT = 0
|
||||
i: t.CSizeT
|
||||
for i in range(alen):
|
||||
if annot[i] == '|':
|
||||
s: t.CSizeT = start
|
||||
e: t.CSizeT = i
|
||||
while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'):
|
||||
s += 1
|
||||
while e > s and (annot[e - 1] == ' ' or annot[e - 1] == '\'' or annot[e - 1] == '"'):
|
||||
e -= 1
|
||||
seglen: t.CSizeT = e - s
|
||||
if seglen > 0 and seglen < 256:
|
||||
string.strncpy(seg, annot + s, seglen)
|
||||
seg[seglen] = '\0'
|
||||
if self.Gen.StructGen.find_struct(seg) is not None:
|
||||
return seg
|
||||
start = i + 1
|
||||
# 最后一段(无 '|' 后缀)
|
||||
s: t.CSizeT = start
|
||||
e: t.CSizeT = alen
|
||||
while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'):
|
||||
s += 1
|
||||
while e > s and (annot[e - 1] == ' ' or annot[e - 1] == '\'' or annot[e - 1] == '"'):
|
||||
e -= 1
|
||||
seglen: t.CSizeT = e - s
|
||||
if seglen > 0 and seglen < 256:
|
||||
string.strncpy(seg, annot + s, seglen)
|
||||
seg[seglen] = '\0'
|
||||
if self.Gen.StructGen.find_struct(seg) is not None:
|
||||
return seg
|
||||
return None
|
||||
+389
-398
@@ -1,399 +1,390 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprOps as HandlesExprOps
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.Projectrans.Config as Config
|
||||
import lib.Projectrans.Utils as Utils
|
||||
|
||||
|
||||
import lib.core.Gen.ExprGenBase as ExprGenBase
|
||||
import lib.core.Handles.ExprCallCtor as ExprCallCtor
|
||||
|
||||
# ============================================================
|
||||
# ExprGenConst - ExprGenMixin 拆分(阶段 D):常量/全局字符串/list 字面量翻译
|
||||
#
|
||||
# 继承 ExprGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesExpr 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class ExprGenConst(ExprGenBase.ExprGenBase):
|
||||
"""常量/全局字符串/list 字面量翻译"""
|
||||
|
||||
# ============================================================
|
||||
# 创建全局字符串常量
|
||||
# ============================================================
|
||||
def create_global_string(self, builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
str_val: str,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""创建全局字符串常量并返回 i8* bitcast"""
|
||||
escaped: str = self.escape_llvm_string(pool, str_val)
|
||||
if escaped is None:
|
||||
return None
|
||||
|
||||
slen: t.CSizeT = string.strlen(str_val)
|
||||
count: int = slen + 1
|
||||
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
arr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Array(pool, i8_ty, count)
|
||||
|
||||
# 使用模块级计数器(trans._label_counter)避免跨函数命名冲突
|
||||
str_idx: int = trans._label_counter
|
||||
trans._label_counter += 1
|
||||
|
||||
# 字符串名加 SHA1 前缀,和函数导出规则一致,避免跨模块重名
|
||||
gv_name: str = pool.alloc(48)
|
||||
if gv_name is None:
|
||||
return None
|
||||
if trans.ModuleSha1 is not None:
|
||||
viperlib.snprintf(gv_name, 48, ".str.%s.%d", trans.ModuleSha1, str_idx)
|
||||
else:
|
||||
viperlib.snprintf(gv_name, 48, ".str.%d", str_idx)
|
||||
|
||||
gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, gv_name, arr_ty)
|
||||
if gv is None:
|
||||
return None
|
||||
llvmlite.module_add_global(mod, gv)
|
||||
|
||||
# 去掉 private 链接,和函数一致:stub 中 declare,text 中 define
|
||||
llvmlite.global_set_unnamed_addr(gv, 1)
|
||||
llvmlite.global_set_constant(gv, 1)
|
||||
# LLVM 22+ 不允许 external linkage 全局变量带初始值,设为 internal
|
||||
gv.Linkage = "internal"
|
||||
gv.Initializer = escaped
|
||||
|
||||
arr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, arr_ty)
|
||||
gv_ref_name: str = pool.alloc(64)
|
||||
if gv_ref_name is None:
|
||||
return None
|
||||
viperlib.snprintf(gv_ref_name, 64, "@%s", gv.Name)
|
||||
gv_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, arr_ptr_ty, gv_ref_name)
|
||||
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
|
||||
bc: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, gv_ref, i8_ptr_ty)
|
||||
return bc
|
||||
# ============================================================
|
||||
# 翻译常量表达式
|
||||
# ============================================================
|
||||
def translate_constant(self, builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译常量(int/str/bool)"""
|
||||
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
|
||||
if cn is None:
|
||||
return None
|
||||
ck: int = cn.const_kind
|
||||
if cn.const_kind == ast.CONST_INT:
|
||||
# 超出 i32 范围则用 i64(避免常量创建时被截断)
|
||||
iv: t.CInt64T = cn.int_val
|
||||
if iv > 2147483647 or iv < -2147483648:
|
||||
return llvmlite.const_int64(pool, iv)
|
||||
return llvmlite.const_int32(pool, iv)
|
||||
elif cn.const_kind == ast.CONST_FLOAT:
|
||||
# 浮点常量默认创建为 double(64 位),赋值时由 coerce_to_type 自动 fptrunc
|
||||
double_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Double(pool)
|
||||
return llvmlite.ConstFloat(pool, double_ty, cn.float_val)
|
||||
elif cn.const_kind == ast.CONST_CHAR:
|
||||
# 单引号单字符 → i32 值(字符 ASCII 码),coerce_to_type 会 trunc 为 i8
|
||||
cv: t.CInt64T = cn.int_val
|
||||
return llvmlite.const_int32(pool, cv)
|
||||
elif cn.const_kind == ast.CONST_STR:
|
||||
sv: str = cn.str_val
|
||||
if sv is None:
|
||||
return None
|
||||
r: llvmlite.Value | t.CPtr = self.create_global_string(builder, pool, mod, sv, trans)
|
||||
return r
|
||||
elif cn.const_kind == ast.CONST_BOOL:
|
||||
if cn.int_val != 0:
|
||||
return llvmlite.const_int32(pool, 1)
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
elif cn.const_kind == ast.CONST_NONE:
|
||||
# None → i8* null(空指针常量),用于 `p is None` / `p is not None` 比较
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
if i8_ty is None:
|
||||
return None
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
if i8_ptr_ty is None:
|
||||
return None
|
||||
rv_none: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, i8_ptr_ty, "null")
|
||||
return rv_none
|
||||
return None
|
||||
# ============================================================
|
||||
# _infer_elem_type_from_value — 从 LLVM Value 推断 list 元素类型名
|
||||
#
|
||||
# 用于 list 字面量 [a, b, c] 的元素类型推断
|
||||
# ============================================================
|
||||
def _infer_elem_type_from_value(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
value: llvmlite.Value | t.CPtr) -> str:
|
||||
"""从 LLVM Value 的类型推断 list 元素类型名
|
||||
|
||||
fail-fast:值类型缺失/无法映射时返回 None(调用方携带节点报错终止),
|
||||
绝不静默回退 "str"(掩盖上游 Value 类型缺失根因)。
|
||||
"""
|
||||
if value is None or value.Ty is None:
|
||||
return None
|
||||
ty: llvmlite.LLVMType | t.CPtr = value.Ty
|
||||
bits: int = self.get_llvm_type_bits(ty)
|
||||
if bits != 0:
|
||||
if bits == 32:
|
||||
return "int"
|
||||
if bits == 64:
|
||||
return "CSizeT"
|
||||
if bits == 8:
|
||||
return "CInt8T"
|
||||
if bits == 16:
|
||||
return "CInt16T"
|
||||
return None
|
||||
if self.is_ptr_type(ty) != 0:
|
||||
return "str"
|
||||
fbits: int = self.get_llvm_float_bits(ty)
|
||||
if fbits != 0:
|
||||
if fbits == 64:
|
||||
return "CDouble"
|
||||
if fbits == 32:
|
||||
return "CFloat"
|
||||
return None
|
||||
# ============================================================
|
||||
# _find_pool_var — 查找上下文中的 pool 变量
|
||||
#
|
||||
# 依次尝试 "pool", "_mbuddy", "mbuddy", "mb"
|
||||
# ============================================================
|
||||
def _find_pool_var(self, trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""查找上下文中的 pool 变量,返回 alloca 或 None
|
||||
|
||||
查找顺序: pool → _mbuddy → mbuddy → mb
|
||||
兜底: 若都未找到,注册外部全局 @_mbuddy (i8*) 供函数内动态 list 创建使用。
|
||||
注意: 模块级 t.CArray 初始化不走此路径(由 _init_global_array_from_list 处理),
|
||||
此兜底仅用于函数内的动态 list 字面量(如 op=[...])。
|
||||
@_mbuddy 由入口模块(如 Phase2.py)定义并初始化,其他模块以 external 引用。
|
||||
"""
|
||||
if trans is None:
|
||||
return None
|
||||
alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, "pool")
|
||||
if alloca is not None:
|
||||
return alloca
|
||||
alloca = HandlesVar.lookup_var(trans.SymTab, "_mbuddy")
|
||||
if alloca is not None:
|
||||
return alloca
|
||||
alloca = HandlesVar.lookup_var(trans.SymTab, "mbuddy")
|
||||
if alloca is not None:
|
||||
return alloca
|
||||
alloca = HandlesVar.lookup_var(trans.SymTab, "mb")
|
||||
if alloca is not None:
|
||||
return alloca
|
||||
# 兜底: 创建当前模块 mangled 的 @_mbuddy 定义(linkonce_odr + zeroinitializer)
|
||||
# 对齐模块级全局带 SHA1 前缀命名:裸名 @_mbuddy 依赖链接合并共享
|
||||
# (--allow-multiple-definition),带前缀后每模块独立。linkonce_odr 允许
|
||||
# 链接器合并同模板重复特化定义,zeroinitializer 保证编译链接通过。
|
||||
# 运行时若该模块未在入口 main 赋值 _mbuddy(null pool 上动态建 list),
|
||||
# 由真实崩溃暴露(fail-fast 哲学,不掩盖上游未初始化)。
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
if pool is None or trans.Module is None or trans.SymTab is None:
|
||||
return None
|
||||
# 先检查是否已注册到模块作用域(避免重复创建全局变量)
|
||||
existing: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var(trans.SymTab, "_mbuddy")
|
||||
if existing is not None:
|
||||
return existing
|
||||
# 创建 i8* 类型(t.CVoid | t.CPtr = i8*)
|
||||
i8_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_fb)
|
||||
# 当前模块 mangled 名(@<模块sha1>._mbuddy)
|
||||
mb_name_fb: str = HandlesFunctions._mangle_name(trans, "_mbuddy")
|
||||
# 创建 linkonce_odr 定义(可被链接器合并,自给自足保证链接通过)
|
||||
gv_ext: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, mb_name_fb, i8_ptr_ty_fb)
|
||||
if gv_ext is not None:
|
||||
gv_ext.Linkage = "linkonce_odr"
|
||||
gv_ext.Initializer = "zeroinitializer"
|
||||
llvmlite.module_add_global(trans.Module, gv_ext)
|
||||
# 创建 Value 引用(@<模块sha1>._mbuddy, 类型为 i8**)
|
||||
i8_ptr_ptr_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty_fb)
|
||||
ref_name_fb: str = pool.alloc(96)
|
||||
if ref_name_fb is not None:
|
||||
# mangled 名带 SHA1 前缀(数字开头),引用必须加引号(见 make_global_ref)
|
||||
if HandlesClassDef._vtable_name_needs_quote(mb_name_fb) != 0:
|
||||
viperlib.snprintf(ref_name_fb, 96, "@\"%s\"", mb_name_fb)
|
||||
else:
|
||||
viperlib.snprintf(ref_name_fb, 96, "@%s", mb_name_fb)
|
||||
gv_ref_fb: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, i8_ptr_ptr_ty_fb, ref_name_fb)
|
||||
# 注册到模块作用域,避免重复创建
|
||||
HandlesVar.define_module_var(trans.SymTab, "_mbuddy", gv_ref_fb)
|
||||
return gv_ref_fb
|
||||
# ============================================================
|
||||
# translate_list_literal — 翻译 list 字面量 [a, b, c]
|
||||
#
|
||||
# 将 list 字面量翻译为 list[T](pool) 构造 + append 调用序列
|
||||
#
|
||||
# Args:
|
||||
# builder: IRBuilder
|
||||
# pool: 编译器内存池(MemBuddy)
|
||||
# mod: LLVMModule
|
||||
# node: ast.List 节点
|
||||
# elem_type_name: 元素类型名(如 "str", "int"),None 表示从元素推断
|
||||
# trans: Translator 对象
|
||||
#
|
||||
# Returns:
|
||||
# list 对象指针(Ptr(list[T] struct)),None 失败
|
||||
# ============================================================
|
||||
def translate_list_literal(self, builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
elem_type_name: str,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译 list 字面量 [a, b, c] → list[T](pool) + append 序列"""
|
||||
if node is None or trans is None:
|
||||
return None
|
||||
|
||||
list_node: ast.List | t.CPtr = (ast.List | t.CPtr)(node)
|
||||
if list_node is None:
|
||||
return None
|
||||
|
||||
elts: list[ast.AST | t.CPtr] | t.CPtr = list_node.elts
|
||||
elts_count: t.CSizeT = 0
|
||||
if elts is not None:
|
||||
elts_count = len(elts)
|
||||
|
||||
# 推断元素类型
|
||||
inferred_type_name: str = elem_type_name
|
||||
first_elem_val: llvmlite.Value | t.CPtr = None
|
||||
if inferred_type_name is None:
|
||||
if elts_count > 0:
|
||||
first_elem_node: ast.AST | t.CPtr = elts.get(0)
|
||||
first_elem_val = HandlesExpr.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 类型缺失,立即终止编译(暴露上游根因)
|
||||
HandlesType.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 元素类型,立即终止编译
|
||||
HandlesType.fatal_error(
|
||||
first_elem_node, "list 字面量元素类型推断失败(Value 类型缺失)", "TypeError")
|
||||
else:
|
||||
# 空 list 无元素可推断,保持默认 str(list[str])
|
||||
inferred_type_name = "str"
|
||||
|
||||
# 查找 pool 变量
|
||||
pool_alloca: llvmlite.Value | t.CPtr = self._find_pool_var(trans)
|
||||
if pool_alloca is None:
|
||||
HandlesType.fatal_error(node, "list literal requires pool variable in context")
|
||||
return None
|
||||
|
||||
# load pool 变量值(i8*)
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
pool_val: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, pool_alloca)
|
||||
if pool_val is None:
|
||||
return None
|
||||
|
||||
# 特化 list[T] 类(elem_size=8:str 是指针,4 会导致双元素重叠损坏)
|
||||
type_args: list[str] | t.CPtr = list[str](pool, 8)
|
||||
type_args.append(inferred_type_name)
|
||||
spec_name: str = HandlesClassDef._specialize_generic_class(trans, "list", type_args)
|
||||
if spec_name is None:
|
||||
HandlesType.fatal_error(node, "list literal generic specialization failed")
|
||||
return None
|
||||
|
||||
# 查找 struct entry
|
||||
struct_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name)
|
||||
if struct_entry is None:
|
||||
HandlesType.fatal_error(node, "list literal specialized class not registered")
|
||||
return None
|
||||
struct_ty: llvmlite.LLVMType | t.CPtr = struct_entry.Ty
|
||||
if struct_ty is None:
|
||||
return None
|
||||
|
||||
# alloca 临时 list 空间
|
||||
# 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间)
|
||||
HandlesStruct.ensure_struct_def_in_module(pool, mod, struct_ty)
|
||||
tmp: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, struct_ty)
|
||||
if tmp is None:
|
||||
return None
|
||||
|
||||
# 存储指针:默认用 alloca,如果有 __new__ 则用 __new__ 返回的指针
|
||||
# __new__ 是可选的,仅当泛型类模板定义了 __new__ 方法时才调用
|
||||
# (与 _translate_struct_ctor/_translate_generic_ctor_call 保持一致,
|
||||
# 避免为无 __new__ 的类生成过度声明)
|
||||
storage_ptr: llvmlite.Value | t.CPtr = tmp
|
||||
has_new_flag: int = 0
|
||||
if struct_entry is not None:
|
||||
has_new_flag = struct_entry.HasNew
|
||||
if has_new_flag != 0:
|
||||
new_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
|
||||
if new_args is None:
|
||||
return None
|
||||
string.memset(new_args, 0, 8 * 32)
|
||||
new_args[0] = t.CSizeT(pool_val)
|
||||
new_ptr: llvmlite.Value | t.CPtr = ExprCallCtor._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)
|
||||
ExprCallCtor._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: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
|
||||
if init_args is None:
|
||||
return None
|
||||
string.memset(init_args, 0, 8 * 32)
|
||||
init_args[0] = t.CSizeT(pool_val)
|
||||
elem_size_val: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, 0)
|
||||
init_args[1] = t.CSizeT(elem_size_val)
|
||||
ExprCallCtor._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:
|
||||
# 第一个元素可能已经翻译过
|
||||
if first_elem_val is not None:
|
||||
append_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
|
||||
if append_args is not None:
|
||||
string.memset(append_args, 0, 8 * 32)
|
||||
append_args[0] = t.CSizeT(first_elem_val)
|
||||
ExprCallCtor._call_method_on_ptr(
|
||||
pool, builder, mod, spec_name, "append", storage_ptr, append_args, 1, trans)
|
||||
|
||||
# 翻译剩余元素
|
||||
i: t.CSizeT = 1
|
||||
while i < elts_count:
|
||||
elem_node_i: ast.AST | t.CPtr = elts.get(i)
|
||||
elem_val_i: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(builder, pool, mod, elem_node_i, None, 0, trans)
|
||||
if elem_val_i is not None:
|
||||
ap_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
|
||||
if ap_args is not None:
|
||||
string.memset(ap_args, 0, 8 * 32)
|
||||
ap_args[0] = t.CSizeT(elem_val_i)
|
||||
ExprCallCtor._call_method_on_ptr(
|
||||
pool, builder, mod, spec_name, "append", storage_ptr, ap_args, 1, trans)
|
||||
i += 1
|
||||
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.Projectrans.Config as Config
|
||||
import lib.Projectrans.Utils as Utils
|
||||
|
||||
|
||||
import lib.core.Gen.ExprGenBase as ExprGenBase
|
||||
|
||||
# ============================================================
|
||||
# ExprGenConst - ExprGenMixin 拆分(阶段 D):常量/全局字符串/list 字面量翻译
|
||||
#
|
||||
# 继承 ExprGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesExpr 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class ExprGenConst(ExprGenBase.ExprGenBase):
|
||||
"""常量/全局字符串/list 字面量翻译"""
|
||||
|
||||
# ============================================================
|
||||
# 创建全局字符串常量
|
||||
# ============================================================
|
||||
def create_global_string(self, builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
str_val: str,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""创建全局字符串常量并返回 i8* bitcast"""
|
||||
escaped: str = self.escape_llvm_string(pool, str_val)
|
||||
if escaped is None:
|
||||
return None
|
||||
|
||||
slen: t.CSizeT = string.strlen(str_val)
|
||||
count: int = slen + 1
|
||||
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
arr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Array(pool, i8_ty, count)
|
||||
|
||||
# 使用模块级计数器(trans._label_counter)避免跨函数命名冲突
|
||||
str_idx: int = trans._label_counter
|
||||
trans._label_counter += 1
|
||||
|
||||
# 字符串名加 SHA1 前缀,和函数导出规则一致,避免跨模块重名
|
||||
gv_name: str = pool.alloc(48)
|
||||
if gv_name is None:
|
||||
return None
|
||||
if trans.ModuleSha1 is not None:
|
||||
viperlib.snprintf(gv_name, 48, ".str.%s.%d", trans.ModuleSha1, str_idx)
|
||||
else:
|
||||
viperlib.snprintf(gv_name, 48, ".str.%d", str_idx)
|
||||
|
||||
gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, gv_name, arr_ty)
|
||||
if gv is None:
|
||||
return None
|
||||
llvmlite.module_add_global(mod, gv)
|
||||
|
||||
# 去掉 private 链接,和函数一致:stub 中 declare,text 中 define
|
||||
llvmlite.global_set_unnamed_addr(gv, 1)
|
||||
llvmlite.global_set_constant(gv, 1)
|
||||
# LLVM 22+ 不允许 external linkage 全局变量带初始值,设为 internal
|
||||
gv.Linkage = "internal"
|
||||
gv.Initializer = escaped
|
||||
|
||||
arr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, arr_ty)
|
||||
gv_ref_name: str = pool.alloc(64)
|
||||
if gv_ref_name is None:
|
||||
return None
|
||||
viperlib.snprintf(gv_ref_name, 64, "@%s", gv.Name)
|
||||
gv_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, arr_ptr_ty, gv_ref_name)
|
||||
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
|
||||
bc: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, gv_ref, i8_ptr_ty)
|
||||
return bc
|
||||
# ============================================================
|
||||
# 翻译常量表达式
|
||||
# ============================================================
|
||||
def translate_constant(self, builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译常量(int/str/bool)"""
|
||||
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
|
||||
if cn is None:
|
||||
return None
|
||||
ck: int = cn.const_kind
|
||||
if cn.const_kind == ast.CONST_INT:
|
||||
# 超出 i32 范围则用 i64(避免常量创建时被截断)
|
||||
iv: t.CInt64T = cn.int_val
|
||||
if iv > 2147483647 or iv < -2147483648:
|
||||
return llvmlite.const_int64(pool, iv)
|
||||
return llvmlite.const_int32(pool, iv)
|
||||
elif cn.const_kind == ast.CONST_FLOAT:
|
||||
# 浮点常量默认创建为 double(64 位),赋值时由 coerce_to_type 自动 fptrunc
|
||||
double_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Double(pool)
|
||||
return llvmlite.ConstFloat(pool, double_ty, cn.float_val)
|
||||
elif cn.const_kind == ast.CONST_CHAR:
|
||||
# 单引号单字符 → i32 值(字符 ASCII 码),coerce_to_type 会 trunc 为 i8
|
||||
cv: t.CInt64T = cn.int_val
|
||||
return llvmlite.const_int32(pool, cv)
|
||||
elif cn.const_kind == ast.CONST_STR:
|
||||
sv: str = cn.str_val
|
||||
if sv is None:
|
||||
return None
|
||||
r: llvmlite.Value | t.CPtr = self.create_global_string(builder, pool, mod, sv, trans)
|
||||
return r
|
||||
elif cn.const_kind == ast.CONST_BOOL:
|
||||
if cn.int_val != 0:
|
||||
return llvmlite.const_int32(pool, 1)
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
elif cn.const_kind == ast.CONST_NONE:
|
||||
# None → i8* null(空指针常量),用于 `p is None` / `p is not None` 比较
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
if i8_ty is None:
|
||||
return None
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
if i8_ptr_ty is None:
|
||||
return None
|
||||
rv_none: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, i8_ptr_ty, "null")
|
||||
return rv_none
|
||||
return None
|
||||
# ============================================================
|
||||
# _infer_elem_type_from_value — 从 LLVM Value 推断 list 元素类型名
|
||||
#
|
||||
# 用于 list 字面量 [a, b, c] 的元素类型推断
|
||||
# ============================================================
|
||||
def _infer_elem_type_from_value(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
value: llvmlite.Value | t.CPtr) -> str:
|
||||
"""从 LLVM Value 的类型推断 list 元素类型名
|
||||
|
||||
fail-fast:值类型缺失/无法映射时返回 None(调用方携带节点报错终止),
|
||||
绝不静默回退 "str"(掩盖上游 Value 类型缺失根因)。
|
||||
"""
|
||||
if value is None or value.Ty is None:
|
||||
return None
|
||||
ty: llvmlite.LLVMType | t.CPtr = value.Ty
|
||||
bits: int = self.get_llvm_type_bits(ty)
|
||||
if bits != 0:
|
||||
if bits == 32:
|
||||
return "int"
|
||||
if bits == 64:
|
||||
return "CSizeT"
|
||||
if bits == 8:
|
||||
return "CInt8T"
|
||||
if bits == 16:
|
||||
return "CInt16T"
|
||||
return None
|
||||
if self.is_ptr_type(ty) != 0:
|
||||
return "str"
|
||||
fbits: int = self.get_llvm_float_bits(ty)
|
||||
if fbits != 0:
|
||||
if fbits == 64:
|
||||
return "CDouble"
|
||||
if fbits == 32:
|
||||
return "CFloat"
|
||||
return None
|
||||
# ============================================================
|
||||
# _find_pool_var — 查找上下文中的 pool 变量
|
||||
#
|
||||
# 依次尝试 "pool", "_mbuddy", "mbuddy", "mb"
|
||||
# ============================================================
|
||||
def _find_pool_var(self, trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""查找上下文中的 pool 变量,返回 alloca 或 None
|
||||
|
||||
查找顺序: pool → _mbuddy → mbuddy → mb
|
||||
兜底: 若都未找到,注册外部全局 @_mbuddy (i8*) 供函数内动态 list 创建使用。
|
||||
注意: 模块级 t.CArray 初始化不走此路径(由 _init_global_array_from_list 处理),
|
||||
此兜底仅用于函数内的动态 list 字面量(如 op=[...])。
|
||||
@_mbuddy 由入口模块(如 Phase2.py)定义并初始化,其他模块以 external 引用。
|
||||
"""
|
||||
if trans is None:
|
||||
return None
|
||||
alloca: llvmlite.Value | t.CPtr = self.Gen.VarGen.lookup_var(trans.SymTab, "pool")
|
||||
if alloca is not None:
|
||||
return alloca
|
||||
alloca = self.Gen.VarGen.lookup_var(trans.SymTab, "_mbuddy")
|
||||
if alloca is not None:
|
||||
return alloca
|
||||
alloca = self.Gen.VarGen.lookup_var(trans.SymTab, "mbuddy")
|
||||
if alloca is not None:
|
||||
return alloca
|
||||
alloca = self.Gen.VarGen.lookup_var(trans.SymTab, "mb")
|
||||
if alloca is not None:
|
||||
return alloca
|
||||
# 兜底: 创建当前模块 mangled 的 @_mbuddy 定义(linkonce_odr + zeroinitializer)
|
||||
# 对齐模块级全局带 SHA1 前缀命名:裸名 @_mbuddy 依赖链接合并共享
|
||||
# (--allow-multiple-definition),带前缀后每模块独立。linkonce_odr 允许
|
||||
# 链接器合并同模板重复特化定义,zeroinitializer 保证编译链接通过。
|
||||
# 运行时若该模块未在入口 main 赋值 _mbuddy(null pool 上动态建 list),
|
||||
# 由真实崩溃暴露(fail-fast 哲学,不掩盖上游未初始化)。
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
if pool is None or trans.Module is None or trans.SymTab is None:
|
||||
return None
|
||||
# 先检查是否已注册到模块作用域(避免重复创建全局变量)
|
||||
existing: llvmlite.Value | t.CPtr = self.Gen.VarGen.lookup_module_var(trans.SymTab, "_mbuddy")
|
||||
if existing is not None:
|
||||
return existing
|
||||
# 创建 i8* 类型(t.CVoid | t.CPtr = i8*)
|
||||
i8_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_fb)
|
||||
# 当前模块 mangled 名(@<模块sha1>._mbuddy)
|
||||
mb_name_fb: str = self.Gen.FuncGenBase._mangle_name(trans, "_mbuddy")
|
||||
# 创建 linkonce_odr 定义(可被链接器合并,自给自足保证链接通过)
|
||||
gv_ext: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, mb_name_fb, i8_ptr_ty_fb)
|
||||
if gv_ext is not None:
|
||||
gv_ext.Linkage = "linkonce_odr"
|
||||
gv_ext.Initializer = "zeroinitializer"
|
||||
llvmlite.module_add_global(trans.Module, gv_ext)
|
||||
# 创建 Value 引用(@<模块sha1>._mbuddy, 类型为 i8**)
|
||||
i8_ptr_ptr_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty_fb)
|
||||
ref_name_fb: str = pool.alloc(96)
|
||||
if ref_name_fb is not None:
|
||||
# mangled 名带 SHA1 前缀(数字开头),引用必须加引号(见 make_global_ref)
|
||||
if self.Gen.ClassGenVTable._vtable_name_needs_quote(mb_name_fb) != 0:
|
||||
viperlib.snprintf(ref_name_fb, 96, "@\"%s\"", mb_name_fb)
|
||||
else:
|
||||
viperlib.snprintf(ref_name_fb, 96, "@%s", mb_name_fb)
|
||||
gv_ref_fb: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, i8_ptr_ptr_ty_fb, ref_name_fb)
|
||||
# 注册到模块作用域,避免重复创建
|
||||
self.Gen.VarGen.define_module_var(trans.SymTab, "_mbuddy", gv_ref_fb)
|
||||
return gv_ref_fb
|
||||
# ============================================================
|
||||
# translate_list_literal — 翻译 list 字面量 [a, b, c]
|
||||
#
|
||||
# 将 list 字面量翻译为 list[T](pool) 构造 + append 调用序列
|
||||
#
|
||||
# Args:
|
||||
# builder: IRBuilder
|
||||
# pool: 编译器内存池(MemBuddy)
|
||||
# mod: LLVMModule
|
||||
# node: ast.List 节点
|
||||
# elem_type_name: 元素类型名(如 "str", "int"),None 表示从元素推断
|
||||
# trans: Translator 对象
|
||||
#
|
||||
# Returns:
|
||||
# list 对象指针(Ptr(list[T] struct)),None 失败
|
||||
# ============================================================
|
||||
def translate_list_literal(self, builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
elem_type_name: str,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译 list 字面量 [a, b, c] → list[T](pool) + append 序列"""
|
||||
if node is None or trans is None:
|
||||
return None
|
||||
|
||||
list_node: ast.List | t.CPtr = (ast.List | t.CPtr)(node)
|
||||
if list_node is None:
|
||||
return None
|
||||
|
||||
elts: list[ast.AST | t.CPtr] | t.CPtr = list_node.elts
|
||||
elts_count: t.CSizeT = 0
|
||||
if elts is not None:
|
||||
elts_count = len(elts)
|
||||
|
||||
# 推断元素类型
|
||||
inferred_type_name: str = elem_type_name
|
||||
first_elem_val: llvmlite.Value | t.CPtr = None
|
||||
if inferred_type_name is None:
|
||||
if elts_count > 0:
|
||||
first_elem_node: ast.AST | t.CPtr = elts.get(0)
|
||||
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")
|
||||
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")
|
||||
else:
|
||||
# 空 list 无元素可推断,保持默认 str(list[str])
|
||||
inferred_type_name = "str"
|
||||
|
||||
# 查找 pool 变量
|
||||
pool_alloca: llvmlite.Value | t.CPtr = self._find_pool_var(trans)
|
||||
if pool_alloca is None:
|
||||
self.Gen.TypeGenErr.fatal_error(node, "list literal requires pool variable in context")
|
||||
return None
|
||||
|
||||
# load pool 变量值(i8*)
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
pool_val: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, pool_alloca)
|
||||
if pool_val is None:
|
||||
return None
|
||||
|
||||
# 特化 list[T] 类(elem_size=8:str 是指针,4 会导致双元素重叠损坏)
|
||||
type_args: list[str] | t.CPtr = list[str](pool, 8)
|
||||
type_args.append(inferred_type_name)
|
||||
spec_name: str = self.Gen.ClassGenGeneric._specialize_generic_class(trans, "list", type_args)
|
||||
if spec_name is None:
|
||||
self.Gen.TypeGenErr.fatal_error(node, "list literal generic specialization failed")
|
||||
return None
|
||||
|
||||
# 查找 struct entry
|
||||
struct_entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct(spec_name)
|
||||
if struct_entry is None:
|
||||
self.Gen.TypeGenErr.fatal_error(node, "list literal specialized class not registered")
|
||||
return None
|
||||
struct_ty: llvmlite.LLVMType | t.CPtr = struct_entry.Ty
|
||||
if struct_ty is None:
|
||||
return None
|
||||
|
||||
# alloca 临时 list 空间
|
||||
# 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间)
|
||||
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, struct_ty)
|
||||
tmp: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, struct_ty)
|
||||
if tmp is None:
|
||||
return None
|
||||
|
||||
# 存储指针:默认用 alloca,如果有 __new__ 则用 __new__ 返回的指针
|
||||
# __new__ 是可选的,仅当泛型类模板定义了 __new__ 方法时才调用
|
||||
# (与 _translate_struct_ctor/_translate_generic_ctor_call 保持一致,
|
||||
# 避免为无 __new__ 的类生成过度声明)
|
||||
storage_ptr: llvmlite.Value | t.CPtr = tmp
|
||||
has_new_flag: int = 0
|
||||
if struct_entry is not None:
|
||||
has_new_flag = struct_entry.HasNew
|
||||
if has_new_flag != 0:
|
||||
new_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
|
||||
if new_args is None:
|
||||
return None
|
||||
string.memset(new_args, 0, 8 * 32)
|
||||
new_args[0] = t.CSizeT(pool_val)
|
||||
new_ptr: llvmlite.Value | t.CPtr = 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)
|
||||
|
||||
# 调用 __init__(storage_ptr, pool_val, elem_size=0)
|
||||
init_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
|
||||
if init_args is None:
|
||||
return None
|
||||
string.memset(init_args, 0, 8 * 32)
|
||||
init_args[0] = t.CSizeT(pool_val)
|
||||
elem_size_val: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, 0)
|
||||
init_args[1] = t.CSizeT(elem_size_val)
|
||||
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:
|
||||
# 第一个元素可能已经翻译过
|
||||
if first_elem_val is not None:
|
||||
append_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
|
||||
if append_args is not None:
|
||||
string.memset(append_args, 0, 8 * 32)
|
||||
append_args[0] = t.CSizeT(first_elem_val)
|
||||
self.Gen.CallGenCall._call_method_on_ptr(
|
||||
pool, builder, mod, spec_name, "append", storage_ptr, append_args, 1, trans)
|
||||
|
||||
# 翻译剩余元素
|
||||
i: t.CSizeT = 1
|
||||
while i < elts_count:
|
||||
elem_node_i: ast.AST | t.CPtr = elts.get(i)
|
||||
elem_val_i: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(builder, pool, mod, elem_node_i, None, 0, trans)
|
||||
if elem_val_i is not None:
|
||||
ap_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
|
||||
if ap_args is not None:
|
||||
string.memset(ap_args, 0, 8 * 32)
|
||||
ap_args[0] = t.CSizeT(elem_val_i)
|
||||
self.Gen.CallGenCall._call_method_on_ptr(
|
||||
pool, builder, mod, spec_name, "append", storage_ptr, ap_args, 1, trans)
|
||||
i += 1
|
||||
|
||||
return storage_ptr
|
||||
+501
-509
File diff suppressed because it is too large.
Load diff
+121
-130
@@ -1,130 +1,121 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import memhub
|
||||
import string
|
||||
import llvmlite
|
||||
import stdlib
|
||||
import stdio
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprOps as HandlesExprOps
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.Projectrans.Config as Config
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import lib.core.Gen.ExprGenBase as ExprGenBase
|
||||
import lib.core.Handles.ExprCallCall as ExprCallCall
|
||||
|
||||
# ============================================================
|
||||
# docstring 登记表容量(__doc__ 魔法属性支持)
|
||||
#
|
||||
# DOC_MAX: 登记条目上限(预注册阶段所有 App/includes 文件的
|
||||
# 函数/类/方法 docstring,幂等查重)
|
||||
# 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
|
||||
|
||||
# ============================================================
|
||||
# f-string 翻译常量(对齐 TPC HandlesExprFormat)
|
||||
#
|
||||
# FSTR_BUF_SIZE: 运行时栈缓冲大小(snprintf 结果缓冲)
|
||||
# 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
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 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):
|
||||
"""表达式处理 Mixin(纯方法化迁移,无状态字段)"""
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译值表达式(RHS 分派)— 模块级版本
|
||||
# ============================================================
|
||||
def translate_value(self, builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
funcs_ptr: t.CPtr = None,
|
||||
func_count: int = 0,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译值表达式为 LLVM Value"""
|
||||
if node is None:
|
||||
return None
|
||||
k: int = node.kind()
|
||||
if k == ast.ASTKind.Constant:
|
||||
rv: llvmlite.Value | t.CPtr = HandlesExpr.translate_constant(builder, pool, mod, node, trans)
|
||||
return rv
|
||||
elif k == ast.ASTKind.Name:
|
||||
return HandlesExpr.translate_name_value(builder, pool, node, trans)
|
||||
elif k == ast.ASTKind.BinOp:
|
||||
return HandlesExpr.translate_binop(pool, builder, mod, node, trans)
|
||||
elif k == ast.ASTKind.Call:
|
||||
return ExprCallCall.translate_call(pool, builder, mod, node,
|
||||
funcs_ptr, func_count, trans)
|
||||
elif k == ast.ASTKind.Compare:
|
||||
return HandlesExpr.translate_compare(builder, pool, mod, node, trans)
|
||||
elif k == ast.ASTKind.UnaryOp:
|
||||
return HandlesExpr.translate_unaryop(builder, pool, mod, node, trans)
|
||||
elif k == ast.ASTKind.BoolOp:
|
||||
return HandlesExpr.translate_boolop(builder, pool, mod, node,
|
||||
funcs_ptr, func_count, trans)
|
||||
elif k == ast.ASTKind.Subscript:
|
||||
return HandlesExpr.translate_subscript(builder, pool, mod, node, trans)
|
||||
elif k == ast.ASTKind.Attribute:
|
||||
return HandlesExpr.translate_attribute(builder, pool, mod, node, trans)
|
||||
elif k == ast.ASTKind.List:
|
||||
return HandlesExpr.translate_list_literal(builder, pool, mod, node, None, trans)
|
||||
elif k == ast.ASTKind.IfExp:
|
||||
return HandlesExpr.translate_ifexp(builder, pool, mod, node, trans)
|
||||
elif k == ast.ASTKind.Lambda:
|
||||
# 模块级委托:translate_lambda 定义在 FuncGenMixin(跨 Mixin
|
||||
# 方法不能 self. 直接调用,见 HandlesExpr.translate_lambda)
|
||||
return HandlesExpr.translate_lambda(builder, pool, mod, node, trans)
|
||||
elif k == ast.ASTKind.JoinedStr:
|
||||
return HandlesExpr.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 HandlesExpr.translate_formatted_value(builder, pool, mod, node, trans)
|
||||
return None
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import memhub
|
||||
import string
|
||||
import llvmlite
|
||||
import stdlib
|
||||
import stdio
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.Projectrans.Config as Config
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import lib.core.Gen.ExprGenBase as ExprGenBase
|
||||
|
||||
# ============================================================
|
||||
# docstring 登记表容量(__doc__ 魔法属性支持)
|
||||
#
|
||||
# DOC_MAX: 登记条目上限(预注册阶段所有 App/includes 文件的
|
||||
# 函数/类/方法 docstring,幂等查重)
|
||||
# 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
|
||||
|
||||
# ============================================================
|
||||
# f-string 翻译常量(对齐 TPC HandlesExprFormat)
|
||||
#
|
||||
# FSTR_BUF_SIZE: 运行时栈缓冲大小(snprintf 结果缓冲)
|
||||
# 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
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 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):
|
||||
"""表达式处理 Mixin(纯方法化迁移,无状态字段)"""
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译值表达式(RHS 分派)— 模块级版本
|
||||
# ============================================================
|
||||
def translate_value(self, builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
funcs_ptr: t.CPtr = None,
|
||||
func_count: int = 0,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译值表达式为 LLVM Value"""
|
||||
if node is None:
|
||||
return None
|
||||
k: int = node.kind()
|
||||
if k == ast.ASTKind.Constant:
|
||||
rv: llvmlite.Value | t.CPtr = self.Gen.ExprGenConst.translate_constant(builder, pool, mod, node, trans)
|
||||
return rv
|
||||
elif k == ast.ASTKind.Name:
|
||||
return self.Gen.ExprGenName.translate_name_value(builder, pool, node, trans)
|
||||
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)
|
||||
return None
|
||||
+1046
-1056
File diff suppressed because it is too large.
Load diff
+1222
-1231
File diff suppressed because it is too large.
Load diff
+326
-332
@@ -1,333 +1,327 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesBody as HandlesBody
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
|
||||
|
||||
# ============================================================
|
||||
# FuncGenBase - FuncGenMixin 拆分(阶段 D):函数属性 / 命名 / mangle / create_function 基础工具
|
||||
#
|
||||
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class FuncGenBase(CallGenBase.CallGenBase):
|
||||
"""函数属性 / 命名 / mangle / create_function 基础工具"""
|
||||
|
||||
# ============================================================
|
||||
# extract_func_attrs - 从 decorator_list 提取 c.Attribute 属性
|
||||
#
|
||||
# 支持 @c.Attribute(t.attr.xxx()) 和 @c.Attribute(t.attr.xxx) 形式
|
||||
# 也支持 @c.Attribute(t.attr.llvm.xxx) 形式
|
||||
#
|
||||
# 返回 LLVM IR 属性字符串(如 "alwaysinline nounwind"),无属性返回 None
|
||||
# ============================================================
|
||||
def extract_func_attrs(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
decorator_list: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
imported_modules: str) -> str:
|
||||
"""从 decorator_list 提取 c.Attribute 属性,返回 LLVM IR 属性字符串"""
|
||||
if decorator_list is None:
|
||||
return None
|
||||
dn: t.CSizeT = len(decorator_list)
|
||||
if dn == 0:
|
||||
return None
|
||||
|
||||
attrs_buf: str = pool.alloc(256)
|
||||
if attrs_buf is None:
|
||||
return None
|
||||
attrs_buf[0] = '\0'
|
||||
found_any: int = 0
|
||||
|
||||
for di in range(dn):
|
||||
deco: ast.AST | t.CPtr = decorator_list.get(di)
|
||||
if deco is None or deco.kind() != ast.ASTKind.Call:
|
||||
continue
|
||||
call_node: ast.Call | t.CPtr = (ast.Call | t.CPtr)(deco)
|
||||
if call_node.func is None or call_node.func.kind() != ast.ASTKind.Attribute:
|
||||
continue
|
||||
|
||||
# 检测 c.Attribute
|
||||
func_attr: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call_node.func)
|
||||
if func_attr.attr is None or string.strcmp(func_attr.attr, "Attribute") != 0:
|
||||
continue
|
||||
if func_attr.value is None or func_attr.value.kind() != ast.ASTKind.Name:
|
||||
continue
|
||||
c_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(func_attr.value)
|
||||
if c_name.id is None or string.strcmp(c_name.id, "c") != 0:
|
||||
continue
|
||||
if HandlesImports.is_module_imported(imported_modules, "c") == 0:
|
||||
continue
|
||||
|
||||
# 遍历参数提取属性
|
||||
if call_node.args is None:
|
||||
continue
|
||||
args_list: list[ast.AST | t.CPtr] | t.CPtr = call_node.args
|
||||
an: t.CSizeT = len(args_list)
|
||||
for ai in range(an):
|
||||
arg_node: ast.AST | t.CPtr = args_list.get(ai)
|
||||
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
|
||||
|
||||
# 映射到 LLVM 属性名并追加
|
||||
if self._append_llvm_attr(attrs_buf, attr_name) != 0:
|
||||
found_any = 1
|
||||
# 追加成功后,如果不是最后一个属性,添加空格分隔
|
||||
# 在下一次追加前由 _append_str 处理
|
||||
|
||||
if found_any == 0:
|
||||
return None
|
||||
return attrs_buf
|
||||
def _get_attr_name_from_node(self, node: ast.AST | t.CPtr) -> str:
|
||||
"""从 AST 节点提取属性名
|
||||
|
||||
支持:
|
||||
- Call(func=Attribute(...)): t.attr.always_inline() -> "always_inline"
|
||||
- Attribute: t.attr.packed -> "packed"
|
||||
- Attribute(t.attr.llvm.xxx): t.attr.llvm.nounwind -> "nounwind"
|
||||
"""
|
||||
if node is None:
|
||||
return None
|
||||
k: int = node.kind()
|
||||
|
||||
# Call 节点: t.attr.always_inline()
|
||||
if k == ast.ASTKind.Call:
|
||||
call: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node)
|
||||
if call.func is None or call.func.kind() != ast.ASTKind.Attribute:
|
||||
return None
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call.func)
|
||||
return at.attr
|
||||
|
||||
# Attribute 节点: t.attr.packed 或 t.attr.llvm.nounwind
|
||||
if k == ast.ASTKind.Attribute:
|
||||
at2: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
|
||||
return at2.attr
|
||||
|
||||
return None
|
||||
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
|
||||
|
||||
# 先确定映射的 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, "willreturn") == 0:
|
||||
llvm_name = "willreturn"
|
||||
elif string.strcmp(attr_name, "mustprogress") == 0:
|
||||
llvm_name = "mustprogress"
|
||||
else:
|
||||
# packed/aligned/section/visibility/weak 等不支持作为函数内联属性
|
||||
return 0
|
||||
|
||||
# 支持的属性:如果缓冲区非空,先追加空格分隔
|
||||
if attrs_buf[0] != '\0':
|
||||
self._append_str(attrs_buf, " ")
|
||||
self._append_str(attrs_buf, llvm_name)
|
||||
return 1
|
||||
def _append_str(self, buf: str, s: str,
|
||||
max_len: t.CSizeT = 256) -> None:
|
||||
"""将字符串追加到 buf 末尾(有界,防 strcpy 越界写穿定长缓冲)"""
|
||||
if buf is None or s is None:
|
||||
return
|
||||
cur_len: t.CSizeT = string.strlen(buf)
|
||||
s_len: t.CSizeT = string.strlen(s)
|
||||
if cur_len + s_len + 1 > max_len:
|
||||
return # 无剩余容量:丢弃本次追加,避免越界写
|
||||
string.strcpy(buf + cur_len, s)
|
||||
# ============================================================
|
||||
# _mangle_name - 为名称添加 SHA1 前缀
|
||||
#
|
||||
# 返回 "sha1.name" 格式的混淆名。若 ModuleSha1 为 None 或名称已带
|
||||
# SHA1 前缀(16 hex + '.'),则原样返回。
|
||||
# ============================================================
|
||||
def _mangle_name(self, trans: HT.Translator | t.CPtr, name: str) -> str:
|
||||
"""为任意名称添加 SHA1 前缀(不做 main/export 检查)"""
|
||||
if trans is None or name is None:
|
||||
return name
|
||||
if trans.ModuleSha1 is None:
|
||||
return name
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
# 已带 SHA1 前缀(16 hex + '.')则跳过
|
||||
if name_len > 17:
|
||||
is_sha1: int = 1
|
||||
for i in range(16):
|
||||
c: t.CChar = name[i]
|
||||
if not (('0' <= c <= '9') or ('a' <= c <= 'f')):
|
||||
is_sha1 = 0
|
||||
break
|
||||
if is_sha1 != 0 and name[16] == '.':
|
||||
return name
|
||||
sha1: str = trans.ModuleSha1
|
||||
sha1_len: t.CSizeT = string.strlen(sha1)
|
||||
mangled: str = stdlib.malloc(sha1_len + name_len + 2)
|
||||
if mangled is None:
|
||||
return name
|
||||
string.strcpy(mangled, sha1)
|
||||
mangled[sha1_len] = '.'
|
||||
string.strcpy(mangled + sha1_len + 1, name)
|
||||
return mangled
|
||||
# ============================================================
|
||||
# _mangle_name_with_sha1 — 用指定 SHA1 为名称添加前缀
|
||||
#
|
||||
# 用于跨模块 vtable 继承: 继承方法需要用父模块的 SHA1 做 mangling,
|
||||
# 而非当前模块的 SHA1。
|
||||
# ============================================================
|
||||
def _mangle_name_with_sha1(self, sha1: str, name: str) -> str:
|
||||
"""用指定 SHA1 为名称添加前缀(不做 main/export 检查)"""
|
||||
if sha1 is None or name is None:
|
||||
return name
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
# 已带 SHA1 前缀(16 hex + '.')则跳过
|
||||
if name_len > 17:
|
||||
is_sha1: int = 1
|
||||
for i in range(16):
|
||||
c2: t.CChar = name[i]
|
||||
if not (('0' <= c2 <= '9') or ('a' <= c2 <= 'f')):
|
||||
is_sha1 = 0
|
||||
break
|
||||
if is_sha1 != 0 and name[16] == '.':
|
||||
return name
|
||||
sha1_len: t.CSizeT = string.strlen(sha1)
|
||||
mangled: str = stdlib.malloc(sha1_len + name_len + 2)
|
||||
if mangled is None:
|
||||
return name
|
||||
string.strcpy(mangled, sha1)
|
||||
mangled[sha1_len] = '.'
|
||||
string.strcpy(mangled + sha1_len + 1, name)
|
||||
return mangled
|
||||
# ============================================================
|
||||
# _mangle_func_name - 为函数名添加 SHA1 前缀(含 main/export 检查)
|
||||
#
|
||||
# 规则:
|
||||
# - main 函数不加前缀(程序入口点)
|
||||
# - has_export 非 0 时不加前缀(t.CExport 导出函数)
|
||||
# - 已带 SHA1 前缀的不再加
|
||||
# - ModuleSha1 为 None 时不加前缀
|
||||
# ============================================================
|
||||
def _mangle_func_name(self, trans: HT.Translator | t.CPtr, 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
|
||||
return self._mangle_name(trans, name)
|
||||
# ============================================================
|
||||
# _body_has_raise - 函数体是否含 raise(非 StopIteration)
|
||||
#
|
||||
# 对齐 TPC HandlesFunctions.py L216-243 _body_contains_raise:函数签名
|
||||
# 追加 __eh_msg_out__/__eh_code_out__ 输出参数的条件。v1 只扫函数体
|
||||
# 顶层 raise(嵌套 if/for/try 内的 raise 未覆盖,后续扩展)。
|
||||
# ============================================================
|
||||
def _body_has_raise(self, fd: ast.FunctionDef | t.CPtr) -> int:
|
||||
"""函数体顶层是否含 raise(非 StopIteration),1=是 / 0=否"""
|
||||
if fd is None or fd.children is None:
|
||||
return 0
|
||||
body_f: list[ast.AST | t.CPtr] | t.CPtr = fd.children
|
||||
bn_f: t.CSizeT = len(body_f)
|
||||
for bi_f in range(bn_f):
|
||||
stmt_f: ast.AST | t.CPtr = body_f.get(bi_f)
|
||||
if stmt_f is None:
|
||||
continue
|
||||
if stmt_f.kind() != ast.ASTKind.Raise:
|
||||
continue
|
||||
rn_f: ast.Raise | t.CPtr = (ast.Raise | t.CPtr)(stmt_f)
|
||||
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:
|
||||
enm_f: ast.Name | t.CPtr = (ast.Name | t.CPtr)(rn_f.exc)
|
||||
if enm_f.id is not None and string.strcmp(enm_f.id, "StopIteration") == 0:
|
||||
is_stop_f = 1
|
||||
elif ek_f == ast.ASTKind.Call:
|
||||
ecl_f: ast.Call | t.CPtr = (ast.Call | t.CPtr)(rn_f.exc)
|
||||
if ecl_f.func is not None and ecl_f.func.kind() == ast.ASTKind.Name:
|
||||
ecn_f: ast.Name | t.CPtr = (ast.Name | t.CPtr)(ecl_f.func)
|
||||
if ecn_f.id is not None and string.strcmp(ecn_f.id, "StopIteration") == 0:
|
||||
is_stop_f = 1
|
||||
if is_stop_f == 0:
|
||||
return 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# 创建 LLVM 函数(简单版本,仅声明)
|
||||
# ============================================================
|
||||
def create_function(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
name: str,
|
||||
args_node: ast.AST | t.CPtr,
|
||||
ret_ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Function | t.CPtr:
|
||||
"""创建 LLVM 函数并添加参数"""
|
||||
if name is None or mod is None:
|
||||
return None
|
||||
|
||||
func: llvmlite.Function | t.CPtr = llvmlite.create_function(pool, mod, name, ret_ty)
|
||||
if func is None:
|
||||
return None
|
||||
|
||||
if args_node is not None:
|
||||
ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
|
||||
if ags.args is not None:
|
||||
alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args
|
||||
an: t.CSizeT = len(alist)
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
for ai in range(an):
|
||||
arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai))
|
||||
if arg is not None and arg.arg is not None:
|
||||
# t.CVoid 表示空参:跳过
|
||||
if arg.annotation is not None:
|
||||
if arg.annotation.kind() == ast.ASTKind.Attribute:
|
||||
at_cf: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg.annotation)
|
||||
if at_cf.attr is not None and string.strcmp(at_cf.attr, "CVoid") == 0:
|
||||
continue
|
||||
param_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||||
if arg.annotation is not None:
|
||||
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||||
pool, arg.annotation, None, None, None)
|
||||
if resolved is not None:
|
||||
param_ty = resolved
|
||||
pname: str = pool.alloc(32)
|
||||
if pname is not None:
|
||||
viperlib.snprintf(pname, 32, "%%%s", arg.arg)
|
||||
llvmlite.add_param(pool, func, param_ty, pname)
|
||||
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
|
||||
|
||||
# ============================================================
|
||||
# FuncGenBase - FuncGenMixin 拆分(阶段 D):函数属性 / 命名 / mangle / create_function 基础工具
|
||||
#
|
||||
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class FuncGenBase(CallGenBase.CallGenBase):
|
||||
"""函数属性 / 命名 / mangle / create_function 基础工具"""
|
||||
|
||||
# ============================================================
|
||||
# extract_func_attrs - 从 decorator_list 提取 c.Attribute 属性
|
||||
#
|
||||
# 支持 @c.Attribute(t.attr.xxx()) 和 @c.Attribute(t.attr.xxx) 形式
|
||||
# 也支持 @c.Attribute(t.attr.llvm.xxx) 形式
|
||||
#
|
||||
# 返回 LLVM IR 属性字符串(如 "alwaysinline nounwind"),无属性返回 None
|
||||
# ============================================================
|
||||
def extract_func_attrs(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
decorator_list: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
imported_modules: str) -> str:
|
||||
"""从 decorator_list 提取 c.Attribute 属性,返回 LLVM IR 属性字符串"""
|
||||
if decorator_list is None:
|
||||
return None
|
||||
dn: t.CSizeT = len(decorator_list)
|
||||
if dn == 0:
|
||||
return None
|
||||
|
||||
attrs_buf: str = pool.alloc(256)
|
||||
if attrs_buf is None:
|
||||
return None
|
||||
attrs_buf[0] = '\0'
|
||||
found_any: int = 0
|
||||
|
||||
for di in range(dn):
|
||||
deco: ast.AST | t.CPtr = decorator_list.get(di)
|
||||
if deco is None or deco.kind() != ast.ASTKind.Call:
|
||||
continue
|
||||
call_node: ast.Call | t.CPtr = (ast.Call | t.CPtr)(deco)
|
||||
if call_node.func is None or call_node.func.kind() != ast.ASTKind.Attribute:
|
||||
continue
|
||||
|
||||
# 检测 c.Attribute
|
||||
func_attr: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call_node.func)
|
||||
if func_attr.attr is None or string.strcmp(func_attr.attr, "Attribute") != 0:
|
||||
continue
|
||||
if func_attr.value is None or func_attr.value.kind() != ast.ASTKind.Name:
|
||||
continue
|
||||
c_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(func_attr.value)
|
||||
if c_name.id is None or string.strcmp(c_name.id, "c") != 0:
|
||||
continue
|
||||
if self.Gen.ImportsGen.is_module_imported(imported_modules, "c") == 0:
|
||||
continue
|
||||
|
||||
# 遍历参数提取属性
|
||||
if call_node.args is None:
|
||||
continue
|
||||
args_list: list[ast.AST | t.CPtr] | t.CPtr = call_node.args
|
||||
an: t.CSizeT = len(args_list)
|
||||
for ai in range(an):
|
||||
arg_node: ast.AST | t.CPtr = args_list.get(ai)
|
||||
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
|
||||
|
||||
# 映射到 LLVM 属性名并追加
|
||||
if self._append_llvm_attr(attrs_buf, attr_name) != 0:
|
||||
found_any = 1
|
||||
# 追加成功后,如果不是最后一个属性,添加空格分隔
|
||||
# 在下一次追加前由 _append_str 处理
|
||||
|
||||
if found_any == 0:
|
||||
return None
|
||||
return attrs_buf
|
||||
def _get_attr_name_from_node(self, node: ast.AST | t.CPtr) -> str:
|
||||
"""从 AST 节点提取属性名
|
||||
|
||||
支持:
|
||||
- Call(func=Attribute(...)): t.attr.always_inline() -> "always_inline"
|
||||
- Attribute: t.attr.packed -> "packed"
|
||||
- Attribute(t.attr.llvm.xxx): t.attr.llvm.nounwind -> "nounwind"
|
||||
"""
|
||||
if node is None:
|
||||
return None
|
||||
k: int = node.kind()
|
||||
|
||||
# Call 节点: t.attr.always_inline()
|
||||
if k == ast.ASTKind.Call:
|
||||
call: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node)
|
||||
if call.func is None or call.func.kind() != ast.ASTKind.Attribute:
|
||||
return None
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call.func)
|
||||
return at.attr
|
||||
|
||||
# Attribute 节点: t.attr.packed 或 t.attr.llvm.nounwind
|
||||
if k == ast.ASTKind.Attribute:
|
||||
at2: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
|
||||
return at2.attr
|
||||
|
||||
return None
|
||||
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
|
||||
|
||||
# 先确定映射的 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, "willreturn") == 0:
|
||||
llvm_name = "willreturn"
|
||||
elif string.strcmp(attr_name, "mustprogress") == 0:
|
||||
llvm_name = "mustprogress"
|
||||
else:
|
||||
# packed/aligned/section/visibility/weak 等不支持作为函数内联属性
|
||||
return 0
|
||||
|
||||
# 支持的属性:如果缓冲区非空,先追加空格分隔
|
||||
if attrs_buf[0] != '\0':
|
||||
self._append_str(attrs_buf, " ")
|
||||
self._append_str(attrs_buf, llvm_name)
|
||||
return 1
|
||||
def _append_str(self, buf: str, s: str,
|
||||
max_len: t.CSizeT = 256) -> None:
|
||||
"""将字符串追加到 buf 末尾(有界,防 strcpy 越界写穿定长缓冲)"""
|
||||
if buf is None or s is None:
|
||||
return
|
||||
cur_len: t.CSizeT = string.strlen(buf)
|
||||
s_len: t.CSizeT = string.strlen(s)
|
||||
if cur_len + s_len + 1 > max_len:
|
||||
return # 无剩余容量:丢弃本次追加,避免越界写
|
||||
string.strcpy(buf + cur_len, s)
|
||||
# ============================================================
|
||||
# _mangle_name - 为名称添加 SHA1 前缀
|
||||
#
|
||||
# 返回 "sha1.name" 格式的混淆名。若 ModuleSha1 为 None 或名称已带
|
||||
# SHA1 前缀(16 hex + '.'),则原样返回。
|
||||
# ============================================================
|
||||
def _mangle_name(self, trans: HT.Translator | t.CPtr, name: str) -> str:
|
||||
"""为任意名称添加 SHA1 前缀(不做 main/export 检查)"""
|
||||
if trans is None or name is None:
|
||||
return name
|
||||
if trans.ModuleSha1 is None:
|
||||
return name
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
# 已带 SHA1 前缀(16 hex + '.')则跳过
|
||||
if name_len > 17:
|
||||
is_sha1: int = 1
|
||||
for i in range(16):
|
||||
c: t.CChar = name[i]
|
||||
if not (('0' <= c <= '9') or ('a' <= c <= 'f')):
|
||||
is_sha1 = 0
|
||||
break
|
||||
if is_sha1 != 0 and name[16] == '.':
|
||||
return name
|
||||
sha1: str = trans.ModuleSha1
|
||||
sha1_len: t.CSizeT = string.strlen(sha1)
|
||||
mangled: str = stdlib.malloc(sha1_len + name_len + 2)
|
||||
if mangled is None:
|
||||
return name
|
||||
string.strcpy(mangled, sha1)
|
||||
mangled[sha1_len] = '.'
|
||||
string.strcpy(mangled + sha1_len + 1, name)
|
||||
return mangled
|
||||
# ============================================================
|
||||
# _mangle_name_with_sha1 — 用指定 SHA1 为名称添加前缀
|
||||
#
|
||||
# 用于跨模块 vtable 继承: 继承方法需要用父模块的 SHA1 做 mangling,
|
||||
# 而非当前模块的 SHA1。
|
||||
# ============================================================
|
||||
def _mangle_name_with_sha1(self, sha1: str, name: str) -> str:
|
||||
"""用指定 SHA1 为名称添加前缀(不做 main/export 检查)"""
|
||||
if sha1 is None or name is None:
|
||||
return name
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
# 已带 SHA1 前缀(16 hex + '.')则跳过
|
||||
if name_len > 17:
|
||||
is_sha1: int = 1
|
||||
for i in range(16):
|
||||
c2: t.CChar = name[i]
|
||||
if not (('0' <= c2 <= '9') or ('a' <= c2 <= 'f')):
|
||||
is_sha1 = 0
|
||||
break
|
||||
if is_sha1 != 0 and name[16] == '.':
|
||||
return name
|
||||
sha1_len: t.CSizeT = string.strlen(sha1)
|
||||
mangled: str = stdlib.malloc(sha1_len + name_len + 2)
|
||||
if mangled is None:
|
||||
return name
|
||||
string.strcpy(mangled, sha1)
|
||||
mangled[sha1_len] = '.'
|
||||
string.strcpy(mangled + sha1_len + 1, name)
|
||||
return mangled
|
||||
# ============================================================
|
||||
# _mangle_func_name - 为函数名添加 SHA1 前缀(含 main/export 检查)
|
||||
#
|
||||
# 规则:
|
||||
# - main 函数不加前缀(程序入口点)
|
||||
# - has_export 非 0 时不加前缀(t.CExport 导出函数)
|
||||
# - 已带 SHA1 前缀的不再加
|
||||
# - ModuleSha1 为 None 时不加前缀
|
||||
# ============================================================
|
||||
def _mangle_func_name(self, trans: HT.Translator | t.CPtr, 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
|
||||
return self._mangle_name(trans, name)
|
||||
# ============================================================
|
||||
# _body_has_raise - 函数体是否含 raise(非 StopIteration)
|
||||
#
|
||||
# 对齐 TPC HandlesFunctions.py L216-243 _body_contains_raise:函数签名
|
||||
# 追加 __eh_msg_out__/__eh_code_out__ 输出参数的条件。v1 只扫函数体
|
||||
# 顶层 raise(嵌套 if/for/try 内的 raise 未覆盖,后续扩展)。
|
||||
# ============================================================
|
||||
def _body_has_raise(self, fd: ast.FunctionDef | t.CPtr) -> int:
|
||||
"""函数体顶层是否含 raise(非 StopIteration),1=是 / 0=否"""
|
||||
if fd is None or fd.children is None:
|
||||
return 0
|
||||
body_f: list[ast.AST | t.CPtr] | t.CPtr = fd.children
|
||||
bn_f: t.CSizeT = len(body_f)
|
||||
for bi_f in range(bn_f):
|
||||
stmt_f: ast.AST | t.CPtr = body_f.get(bi_f)
|
||||
if stmt_f is None:
|
||||
continue
|
||||
if stmt_f.kind() != ast.ASTKind.Raise:
|
||||
continue
|
||||
rn_f: ast.Raise | t.CPtr = (ast.Raise | t.CPtr)(stmt_f)
|
||||
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:
|
||||
enm_f: ast.Name | t.CPtr = (ast.Name | t.CPtr)(rn_f.exc)
|
||||
if enm_f.id is not None and string.strcmp(enm_f.id, "StopIteration") == 0:
|
||||
is_stop_f = 1
|
||||
elif ek_f == ast.ASTKind.Call:
|
||||
ecl_f: ast.Call | t.CPtr = (ast.Call | t.CPtr)(rn_f.exc)
|
||||
if ecl_f.func is not None and ecl_f.func.kind() == ast.ASTKind.Name:
|
||||
ecn_f: ast.Name | t.CPtr = (ast.Name | t.CPtr)(ecl_f.func)
|
||||
if ecn_f.id is not None and string.strcmp(ecn_f.id, "StopIteration") == 0:
|
||||
is_stop_f = 1
|
||||
if is_stop_f == 0:
|
||||
return 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# 创建 LLVM 函数(简单版本,仅声明)
|
||||
# ============================================================
|
||||
def create_function(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
name: str,
|
||||
args_node: ast.AST | t.CPtr,
|
||||
ret_ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Function | t.CPtr:
|
||||
"""创建 LLVM 函数并添加参数"""
|
||||
if name is None or mod is None:
|
||||
return None
|
||||
|
||||
func: llvmlite.Function | t.CPtr = llvmlite.create_function(pool, mod, name, ret_ty)
|
||||
if func is None:
|
||||
return None
|
||||
|
||||
if args_node is not None:
|
||||
ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
|
||||
if ags.args is not None:
|
||||
alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args
|
||||
an: t.CSizeT = len(alist)
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
for ai in range(an):
|
||||
arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai))
|
||||
if arg is not None and arg.arg is not None:
|
||||
# t.CVoid 表示空参:跳过
|
||||
if arg.annotation is not None:
|
||||
if arg.annotation.kind() == ast.ASTKind.Attribute:
|
||||
at_cf: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg.annotation)
|
||||
if at_cf.attr is not None and string.strcmp(at_cf.attr, "CVoid") == 0:
|
||||
continue
|
||||
param_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||||
if arg.annotation is not None:
|
||||
resolved: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.resolve_annotation_type(
|
||||
pool, arg.annotation, None, None, None)
|
||||
if resolved is not None:
|
||||
param_ty = resolved
|
||||
pname: str = pool.alloc(32)
|
||||
if pname is not None:
|
||||
viperlib.snprintf(pname, 32, "%%%s", arg.arg)
|
||||
llvmlite.add_param(pool, func, param_ty, pname)
|
||||
|
||||
return func
|
||||
+1231
-1238
File diff suppressed because it is too large.
Load diff
+1173
-1180
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,491 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import lib.Projectrans.Config as Config
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.VLogger as VLogger
|
||||
import llvmlite
|
||||
import memhub
|
||||
import stdio
|
||||
import stdlib
|
||||
import string
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
|
||||
|
||||
# ============================================================
|
||||
# GenApi - 管线/保留文件访问 Gen 的模块级委托入口(去除 Handles 层)
|
||||
#
|
||||
# 由脚本从 Gen 子对象同名方法自动生成:签名取真源方法(含参数类型注解),
|
||||
# 函数体经 _g_gen 单例调用 gen 子对象。main/BuildPipeline 注入 _g_gen。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# 全局 gen 单例(main/BuildPipeline 创建 gen 后注入)
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ---------------- set_temp_dir(委托 TypeGenBase.set_temp_dir) ----------------
|
||||
def set_temp_dir(temp_dir: str) -> None:
|
||||
"""委托到 gen.set_temp_dir(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenBase.set_temp_dir(temp_dir)
|
||||
|
||||
|
||||
# ---------------- set_current_file_imports(委托 ImportsGenMixin.set_current_file) ----------------
|
||||
def set_current_file_imports(file_path: str) -> None:
|
||||
"""委托到 gen.set_current_file(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.ImportsGen.set_current_file(file_path)
|
||||
|
||||
|
||||
# ---------------- set_current_file_type(委托 TypeGenResolve.set_current_file) ----------------
|
||||
def set_current_file_type(file_path: str) -> None:
|
||||
"""委托到 gen.set_current_file(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenResolve.set_current_file(file_path)
|
||||
|
||||
|
||||
# ---------------- set_current_module_sha1(委托 TypeGenBase.set_current_module_sha1) ----------------
|
||||
def set_current_module_sha1(sha1: str) -> None:
|
||||
"""委托到 gen.set_current_module_sha1(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenBase.set_current_module_sha1(sha1)
|
||||
|
||||
|
||||
# ---------------- clear_trace(委托 TypeGenBase.clear_trace) ----------------
|
||||
def clear_trace() -> None:
|
||||
"""委托到 gen.clear_trace(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenBase.clear_trace()
|
||||
|
||||
|
||||
# ---------------- clear_cdefine_constants(委托 TypeGenCDef.clear_cdefine_constants) ----------------
|
||||
def clear_cdefine_constants() -> None:
|
||||
"""委托到 gen.clear_cdefine_constants(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenCDef.clear_cdefine_constants()
|
||||
|
||||
|
||||
# ---------------- clear_ctypedefs(委托 TypeGenCType.clear_ctypedefs) ----------------
|
||||
def clear_ctypedefs() -> None:
|
||||
"""委托到 gen.clear_ctypedefs(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenCType.clear_ctypedefs()
|
||||
|
||||
|
||||
# ---------------- RegisterCTypedefFromSource(委托 TypeGenCType.register_ctypedef_from_source) ----------------
|
||||
def RegisterCTypedefFromSource(pool: memhub.MemBuddy | t.CPtr, src: str) -> int:
|
||||
"""委托到 gen.register_ctypedef_from_source(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenCType.register_ctypedef_from_source(pool, src)
|
||||
return 0
|
||||
|
||||
|
||||
# ---------------- dump_parse_traceback(委托 TypeGenErr.dump_parse_traceback) ----------------
|
||||
def dump_parse_traceback(file_path: str) -> None:
|
||||
"""委托到 gen.dump_parse_traceback(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenErr.dump_parse_traceback(file_path)
|
||||
|
||||
|
||||
# ---------------- map_t_type(委托 TypeGenResolve.map_t_type) ----------------
|
||||
def map_t_type(pool: memhub.MemBuddy | t.CPtr, type_name: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""委托到 gen.map_t_type(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenResolve.map_t_type(pool, type_name)
|
||||
return None
|
||||
|
||||
|
||||
# ---------------- get_current_file(委托 TypeGenResolve.get_current_file) ----------------
|
||||
def get_current_file() -> str:
|
||||
"""委托到 gen.get_current_file(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenResolve.get_current_file()
|
||||
return None
|
||||
|
||||
|
||||
# ---------------- _is_ctypedef_annotation(委托 TypeGenCType._is_ctypedef_annotation) ----------------
|
||||
def _is_ctypedef_annotation(annotation: ast.AST | t.CPtr) -> int:
|
||||
"""委托到 gen._is_ctypedef_annotation(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenCType._is_ctypedef_annotation(annotation)
|
||||
return 0
|
||||
|
||||
|
||||
# ---------------- resolve_annotation_type(委托 TypeGenResolve.resolve_annotation_type) ----------------
|
||||
def resolve_annotation_type(pool: memhub.MemBuddy | t.CPtr, node: ast.AST | t.CPtr, imported_modules: str, from_imports: str, trans: HT.Translator | t.CPtr = None) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""委托到 gen.resolve_annotation_type(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenResolve.resolve_annotation_type(pool, node, imported_modules, from_imports, trans)
|
||||
return None
|
||||
|
||||
|
||||
# ---------------- has_decorator_marker(委托 TypeGenErr.has_decorator_marker) ----------------
|
||||
def has_decorator_marker(node: ast.AST | t.CPtr, marker_name: str) -> int:
|
||||
"""委托到 gen.has_decorator_marker(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenErr.has_decorator_marker(node, marker_name)
|
||||
return 0
|
||||
|
||||
|
||||
# ---------------- _get_type_name_from_annotation(委托 TypeGenResolve._get_type_name_from_annotation) ----------------
|
||||
def _get_type_name_from_annotation(pool: memhub.MemBuddy | t.CPtr, node: ast.AST | t.CPtr) -> str:
|
||||
"""委托到 gen._get_type_name_from_annotation(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenResolve._get_type_name_from_annotation(pool, node)
|
||||
return None
|
||||
|
||||
|
||||
# ---------------- register_ctypedef(委托 TypeGenCType.register_ctypedef) ----------------
|
||||
def register_ctypedef(pool: memhub.MemBuddy | t.CPtr, name: str, type_str: str) -> None:
|
||||
"""委托到 gen.register_ctypedef(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenCType.register_ctypedef(pool, name, type_str)
|
||||
|
||||
|
||||
# ---------------- lookup_cdefine_constant(委托 TypeGenCDef.lookup_cdefine_constant) ----------------
|
||||
def lookup_cdefine_constant(name: str) -> t.CInt64T:
|
||||
"""委托到 gen.lookup_cdefine_constant(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenCDef.lookup_cdefine_constant(name)
|
||||
return 0
|
||||
|
||||
|
||||
# ---------------- is_cdefine_found(委托 TypeGenCDef.is_cdefine_found) ----------------
|
||||
def is_cdefine_found() -> int:
|
||||
"""委托到 gen.is_cdefine_found(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenCDef.is_cdefine_found()
|
||||
return 0
|
||||
|
||||
|
||||
# ---------------- push_trace(委托 TypeGenBase.push_trace) ----------------
|
||||
def push_trace(file_name: str, lineno: int, col_start: int = 0, col_end: int = 0) -> None:
|
||||
"""委托到 gen.push_trace(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenBase.push_trace(file_name, lineno, col_start, col_end)
|
||||
|
||||
|
||||
# ---------------- pop_trace(委托 TypeGenBase.pop_trace) ----------------
|
||||
def pop_trace() -> None:
|
||||
"""委托到 gen.pop_trace(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenBase.pop_trace()
|
||||
|
||||
|
||||
# ---------------- get_temp_dir(委托 TypeGenBase.get_temp_dir) ----------------
|
||||
def get_temp_dir() -> str:
|
||||
"""委托到 gen.get_temp_dir(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TypeGenBase.get_temp_dir()
|
||||
return None
|
||||
|
||||
|
||||
# ---------------- reset_visible_structs(委托 StructGenMixin.reset_visible_structs) ----------------
|
||||
def reset_visible_structs(pool: memhub.MemBuddy | t.CPtr, strict: int) -> None:
|
||||
"""委托到 gen.reset_visible_structs(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.StructGen.reset_visible_structs(pool, strict)
|
||||
|
||||
|
||||
# ---------------- set_stdlib_alloc(委托 StructGenMixin.set_stdlib_alloc) ----------------
|
||||
def set_stdlib_alloc(flag: int) -> None:
|
||||
"""委托到 gen.set_stdlib_alloc(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.StructGen.set_stdlib_alloc(flag)
|
||||
|
||||
|
||||
# ---------------- get_struct_count(委托 StructGenMixin.get_struct_count) ----------------
|
||||
def get_struct_count() -> int:
|
||||
"""委托到 gen.get_struct_count(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.StructGen.get_struct_count()
|
||||
return 0
|
||||
|
||||
|
||||
# ---------------- reset_module_methods_emitted(委托 StructGenMixin.reset_module_methods_emitted) ----------------
|
||||
def reset_module_methods_emitted(sha1: str) -> int:
|
||||
"""委托到 gen.reset_module_methods_emitted(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.StructGen.reset_module_methods_emitted(sha1)
|
||||
return 0
|
||||
|
||||
|
||||
# ---------------- get_struct_type(委托 StructGenMixin.get_struct_type) ----------------
|
||||
def get_struct_type(class_name: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""委托到 gen.get_struct_type(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.StructGen.get_struct_type(class_name)
|
||||
return None
|
||||
|
||||
|
||||
# ---------------- add_visible_struct(委托 StructGenMixin.add_visible_struct) ----------------
|
||||
def add_visible_struct(pool: memhub.MemBuddy | t.CPtr, name: str) -> None:
|
||||
"""委托到 gen.add_visible_struct(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.StructGen.add_visible_struct(pool, name)
|
||||
|
||||
|
||||
# ---------------- compute_package_from_relpath(委托 ImportsGenMixin.compute_package_from_relpath) ----------------
|
||||
def compute_package_from_relpath(pool: memhub.MemBuddy | t.CPtr, rel_path: str) -> str:
|
||||
"""委托到 gen.compute_package_from_relpath(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.ImportsGen.compute_package_from_relpath(pool, rel_path)
|
||||
return None
|
||||
|
||||
|
||||
# ---------------- is_module_imported(委托 ImportsGenMixin.is_module_imported) ----------------
|
||||
def is_module_imported(imported_modules: str, name: str) -> int:
|
||||
"""委托到 gen.is_module_imported(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.ImportsGen.is_module_imported(imported_modules, name)
|
||||
return 0
|
||||
|
||||
|
||||
# ---------------- add_imported_module(委托 ImportsGenMixin.add_imported_module) ----------------
|
||||
def add_imported_module(pool: memhub.MemBuddy | t.CPtr, imported_modules: str, name: str) -> str:
|
||||
"""委托到 gen.add_imported_module(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.ImportsGen.add_imported_module(pool, imported_modules, name)
|
||||
return None
|
||||
|
||||
|
||||
# ---------------- translate_import(委托 ImportsGenMixin.translate_import) ----------------
|
||||
def translate_import(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int:
|
||||
"""委托到 gen.translate_import(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.ImportsGen.translate_import(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
# ---------------- translate_import_from_module(委托 ImportsGenMixin.translate_import_from_module) ----------------
|
||||
def translate_import_from_module(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int:
|
||||
"""委托到 gen.translate_import_from_module(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.ImportsGen.translate_import_from_module(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
# ---------------- translate_import_from_names(委托 ImportsGenMixin.translate_import_from_names) ----------------
|
||||
def translate_import_from_names(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int:
|
||||
"""委托到 gen.translate_import_from_names(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.ImportsGen.translate_import_from_names(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
# ---------------- _get_parent_class(委托 ClassGenBase._get_parent_class) ----------------
|
||||
def _get_parent_class(cd: ast.ClassDef | t.CPtr, trans: HT.Translator | t.CPtr = None) -> str:
|
||||
"""委托到 gen._get_parent_class(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.ClassGenBase._get_parent_class(cd, trans)
|
||||
return None
|
||||
|
||||
|
||||
# ---------------- _register_generic_template(委托 ClassGenGeneric._register_generic_template) ----------------
|
||||
def _register_generic_template(pool: memhub.MemBuddy | t.CPtr, cd: ast.ClassDef | t.CPtr, module_sha1: str) -> None:
|
||||
"""委托到 gen._register_generic_template(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.ClassGenGeneric._register_generic_template(pool, cd, module_sha1)
|
||||
|
||||
|
||||
# ---------------- _mangle_name_with_sha1(委托 FuncGenBase._mangle_name_with_sha1) ----------------
|
||||
def _mangle_name_with_sha1(sha1: str, name: str) -> str:
|
||||
"""委托到 gen._mangle_name_with_sha1(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.FuncGenBase._mangle_name_with_sha1(sha1, name)
|
||||
return None
|
||||
|
||||
|
||||
# ---------------- forward_declare_functions(委托 FuncGenDef.forward_declare_functions) ----------------
|
||||
def forward_declare_functions(trans: HT.Translator | t.CPtr, tree: ast.AST | t.CPtr) -> int:
|
||||
"""委托到 gen.forward_declare_functions(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.FuncGenDef.forward_declare_functions(trans, tree)
|
||||
return 0
|
||||
|
||||
|
||||
# ---------------- create_wrapper_main(委托 TranslatorGenMixin.create_wrapper_main) ----------------
|
||||
def create_wrapper_main(trans: HT.Translator | t.CPtr, tree: ast.AST | t.CPtr, i32_ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""委托到 gen.create_wrapper_main(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TranslatorGen.create_wrapper_main(trans, tree, i32_ty)
|
||||
return 0
|
||||
|
||||
|
||||
# ---------------- handle_module_level_var(委托 TranslatorGenMixin.handle_module_level_var) ----------------
|
||||
def handle_module_level_var(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int:
|
||||
"""委托到 gen.handle_module_level_var(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TranslatorGen.handle_module_level_var(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
# ---------------- translate_children(委托 TranslatorGenMixin.translate_children) ----------------
|
||||
def translate_children(trans: HT.Translator | t.CPtr, tree: ast.AST | t.CPtr) -> int:
|
||||
"""委托到 gen.translate_children(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.TranslatorGen.translate_children(trans, tree)
|
||||
return 0
|
||||
|
||||
|
||||
# ---------------- init_symbol_table(委托 VarGenMixin.init_symbol_table) ----------------
|
||||
def init_symbol_table(pool: memhub.MemBuddy | t.CPtr) -> GenTypes.SymbolTable | t.CPtr:
|
||||
"""委托到 gen.init_symbol_table(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.VarGen.init_symbol_table(pool)
|
||||
return None
|
||||
|
||||
|
||||
# ---------------- SetTempDir(委托 CallGenBase.SetTempDir) ----------------
|
||||
def SetTempDir(temp_dir: str) -> None:
|
||||
"""委托到 gen.SetTempDir(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenBase.SetTempDir(temp_dir)
|
||||
|
||||
|
||||
# ---------------- find_func_in_module(委托 CallGenBase.find_func_in_module) ----------------
|
||||
def find_func_in_module(mod: llvmlite.LLVMModule | t.CPtr, name: str) -> llvmlite.Function | t.CPtr:
|
||||
"""委托到 gen.find_func_in_module(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenBase.find_func_in_module(mod, name)
|
||||
return None
|
||||
|
||||
|
||||
# ---------------- add_func_to_table(委托 CallGenLeafKit.add_func_to_table) ----------------
|
||||
def add_func_to_table(funcs: GenTypes.FuncEntry | t.CPtr, func_count: int, name: str, func: llvmlite.Function | t.CPtr, max_count: int, defaults: t.CVoid | t.CPtr = None, default_count: int = 0, param_count: int = 0, pool: memhub.MemBuddy | t.CPtr = None) -> int:
|
||||
"""委托到 gen.add_func_to_table(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenLeafKit.add_func_to_table(funcs, func_count, name, func, max_count, defaults, default_count, param_count, pool)
|
||||
return 0
|
||||
|
||||
|
||||
# ---------------- init_func_table(委托 CallGenLeafKit.init_func_table) ----------------
|
||||
def init_func_table(pool: memhub.MemBuddy | t.CPtr, max_count: int) -> GenTypes.FuncEntry | t.CPtr:
|
||||
"""委托到 gen.init_func_table(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenLeafKit.init_func_table(pool, max_count)
|
||||
return None
|
||||
|
||||
|
||||
# ---------------- translate_call(委托 CallGenMixin.translate_call) ----------------
|
||||
def translate_call(pool: memhub.MemBuddy | t.CPtr, builder: llvmlite.IRBuilder | t.CPtr, mod: llvmlite.LLVMModule | t.CPtr, node: ast.AST | t.CPtr, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""委托到 gen.translate_call(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGen.translate_call(pool, builder, mod, node, funcs_ptr, func_count, trans)
|
||||
return None
|
||||
|
||||
|
||||
# ---------------- translate_printf_call(委托 CallGenLeafKit.translate_printf_call) ----------------
|
||||
def translate_printf_call(pool: memhub.MemBuddy | t.CPtr, builder: llvmlite.IRBuilder | t.CPtr, mod: llvmlite.LLVMModule | t.CPtr, cl: ast.Call | t.CPtr, trans: HT.Translator | t.CPtr = None) -> None:
|
||||
"""委托到 gen.translate_printf_call(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenLeafKit.translate_printf_call(pool, builder, mod, cl, trans)
|
||||
|
||||
|
||||
# ---------------- translate_print_call(委托 CallGenLeafKit.translate_print_call) ----------------
|
||||
def translate_print_call(pool: memhub.MemBuddy | t.CPtr, builder: llvmlite.IRBuilder | t.CPtr, mod: llvmlite.LLVMModule | t.CPtr, cl: ast.Call | t.CPtr, trans: HT.Translator | t.CPtr = None) -> None:
|
||||
"""委托到 gen.translate_print_call(原 Handles 壳)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenLeafKit.translate_print_call(pool, builder, mod, cl, trans)
|
||||
@@ -0,0 +1,193 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
|
||||
|
||||
# ============================================================
|
||||
# GenTypes - Gen 侧共享数据类型与常量(去除 Handles 层迁移目标)
|
||||
#
|
||||
# 原分布于 Handles 目录的数据类与常量集中于此,供 Gen 子对象、
|
||||
# 管线与保留实体文件引用。删除 Handles 目录后统一经本模块访问。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# 类编译期元数据(原 HandlesType.CLASS_META_*)
|
||||
# ============================================================
|
||||
CLASS_META_PROVIDES: t.CDefine = 1
|
||||
CLASS_META_REQUIRES: t.CDefine = 2
|
||||
CLASS_META_REQUIRE_MUST: t.CDefine = 3
|
||||
|
||||
# ============================================================
|
||||
# 属性/静态/类方法元数据(原 HandlesClassDef.META_*)
|
||||
# ============================================================
|
||||
META_STATIC: t.CDefine = 1
|
||||
META_CLASS: t.CDefine = 2
|
||||
META_PROP_GETTER: t.CDefine = 4
|
||||
META_PROP_SETTER: t.CDefine = 8
|
||||
META_PROP_DELETER: t.CDefine = 16
|
||||
|
||||
# ============================================================
|
||||
# 结构体容量(原 HandlesStruct.FIELD_MAX/FIELD_NAME_MAX/PARENT_MAX/MRO_MAX)
|
||||
# ============================================================
|
||||
FIELD_MAX: t.CDefine = 256
|
||||
FIELD_NAME_MAX: t.CDefine = 64
|
||||
PARENT_MAX: t.CDefine = 64
|
||||
MRO_MAX: t.CDefine = 64
|
||||
|
||||
# ============================================================
|
||||
# for 迭代序列种类(原 HandlesFor.SEQ_KIND_*)
|
||||
# ============================================================
|
||||
SEQ_KIND_RANGE: t.CDefine = 1
|
||||
SEQ_KIND_STR: t.CDefine = 2
|
||||
SEQ_KIND_LIST: t.CDefine = 3
|
||||
|
||||
# ============================================================
|
||||
# TraceFrame - 仿 Python Traceback 调用栈帧(原 HandlesType.TraceFrame)
|
||||
# ============================================================
|
||||
class TraceFrame:
|
||||
"""仿 Python Traceback 调用栈帧(push_trace/pop_trace 使用)"""
|
||||
file_name: str
|
||||
lineno: int
|
||||
col_start: int
|
||||
col_end: int
|
||||
|
||||
|
||||
# ============================================================
|
||||
# VarEntry - 变量表条目(原 HandlesVar.VarEntry)
|
||||
# ============================================================
|
||||
class VarEntry:
|
||||
"""变量表条目"""
|
||||
Name: str
|
||||
Alloca: llvmlite.Value | t.CPtr
|
||||
Used: t.CInt
|
||||
AnnotClassName: str # 原始类型注解的类名(str 别名在结构体字段中触发编译器 bug,改用显式联合类型)
|
||||
IsPtrElement: t.CInt # 标志: 1=注解为 bytes|t.CPtr 或 str|t.CPtr, 下标按 8 字节步长
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Scope - 作用域节点(原 HandlesVar.Scope)
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class Scope:
|
||||
"""作用域节点"""
|
||||
Parent: Scope | t.CPtr
|
||||
Vars: VarEntry | t.CPtr
|
||||
VarCount: t.CInt
|
||||
Kind: t.CInt
|
||||
|
||||
|
||||
# ============================================================
|
||||
# SymbolTable - 嵌套作用域符号表(原 HandlesVar.SymbolTable)
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class SymbolTable:
|
||||
"""嵌套作用域符号表"""
|
||||
Pool: memhub.MemBuddy | t.CPtr
|
||||
Root: Scope | t.CPtr
|
||||
Current: Scope | t.CPtr
|
||||
|
||||
|
||||
# ============================================================
|
||||
# FieldEntry - 字段信息条目(原 HandlesStruct.FieldEntry)
|
||||
# ============================================================
|
||||
class FieldEntry:
|
||||
Name: str # 字段名(字符串)
|
||||
Index: int # 字段在结构体中的索引
|
||||
Ty: llvmlite.LLVMType | t.CPtr # 字段的 LLVM 类型
|
||||
DefaultVal: ast.AST | t.CPtr # 默认值 AST 节点(None=无默认值)
|
||||
AnnotClassName: str # 原始类型注解的类名(str 别名在结构体字段中触发编译器 bug,改用显式联合类型)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# StructEntry - 结构体注册条目(原 HandlesStruct.StructEntry)
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class StructEntry:
|
||||
Name: str # 类名
|
||||
Ty: llvmlite.LLVMType | t.CPtr # LLVM StructType
|
||||
FieldCount: int # 字段数量
|
||||
Fields: FieldEntry | t.CPtr # 字段数组(FIELD_MAX 个槽位)
|
||||
IsUnion: int # 1=联合体 / 0=普通结构体
|
||||
IsOOP: int # 1=OOP结构体(有方法) / 0=纯内存结构体
|
||||
HasInit: int # 1=有__init__方法 / 0=无
|
||||
HasNew: int # 1=有__new__方法 / 0=无
|
||||
HasVTable: int # 1=有虚表 / 0=无虚表
|
||||
IsNoVTable: int # 1=明确标记 @t.NoVTable / 0=未标记
|
||||
ParentName: str # 父类名(None=无父类,多继承时为第一个父类,兼容旧调用)
|
||||
ParentNames: t.CSizeT | t.CPtr # 多继承父类名数组(每元素 str 指针,ParentCount 个;stdlib 深拷贝)
|
||||
ParentCount: t.CInt # 父类数量(0=无父类,1=单继承,>1=多继承)
|
||||
VTableMethodCount: int # 虚表中的方法数量
|
||||
VTableMethods: str # 虚表方法名数组(每个方法名 str,VTableMethodCount 个)
|
||||
ModuleSha1: str # 定义该类的模块 SHA1(None=无 SHA1)
|
||||
MethodsEmitted: int # 1=方法体已翻译 / 0=未译(Phase 1a mark_only 未译,Phase B 据此补译)
|
||||
SpecTriggerSha1: str # 泛型特化类的触发文件 SHA1(None=非特化类)。特化类 ModuleSha1=模板
|
||||
# sha1(方法名带模板前缀),作废重译时 reset_module_methods_emitted
|
||||
# 按触发文件 sha1 精确重置 MethodsEmitted,防特化方法体残留 1 不补译
|
||||
# → 链接 undefined symbol(list[ast.ClassDef|t.CPtr].* 根因)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# EnumMember - 枚举成员(原 HandlesEnum.EnumMember)
|
||||
# ============================================================
|
||||
class EnumMember:
|
||||
Name: str # 成员名(字符串)
|
||||
Value: t.CInt64T # 成员的整数值
|
||||
Ty: llvmlite.LLVMType | t.CPtr # 成员的 LLVM 类型(用于混用类型场景)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# EnumEntry - 枚举类型条目(原 HandlesEnum.EnumEntry)
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class EnumEntry:
|
||||
Name: str # 枚举类名
|
||||
BaseTy: llvmlite.LLVMType | t.CPtr # 基准类型(所有成员类型中最大的)
|
||||
MemberCount: int # 成员数量
|
||||
Members: EnumMember | t.CPtr # 成员数组(ENUM_MEMBER_MAX 个槽位)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# AsmOperand - 内联汇编操作数条目(原 HandlesExprCall.AsmOperand)
|
||||
# ============================================================
|
||||
class AsmOperand:
|
||||
"""内联汇编操作数条目"""
|
||||
Value: llvmlite.Value | t.CPtr # 输入值或输出 alloca
|
||||
Constraint: str # 约束字符串 (如 "r", "=r")
|
||||
IsOutput: int # 1=输出, 0=输入
|
||||
|
||||
|
||||
# ============================================================
|
||||
# FuncEntry - 函数表条目(原 HandlesExprCall.FuncEntry)
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class FuncEntry:
|
||||
"""函数表条目"""
|
||||
Name: str
|
||||
Func: llvmlite.Function | t.CPtr
|
||||
Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr]),None=无默认值
|
||||
DefaultCount: int # 默认值数量
|
||||
ParamCount: int # 形参数量(不含 self)
|
||||
# TypeStr: 函数类型文本(stdlib 深拷贝,跨文件安全)
|
||||
# 1b 每文件 reset_to(mark1) 回收 pool 内 Function 对象后,
|
||||
# vtable 生成 find_func_global 读类型改用此文本,避免悬空。
|
||||
TypeStr: str
|
||||
|
||||
|
||||
# ============================================================
|
||||
# FuncDefaultsEntry - 默认参数表条目(原 HandlesExprCall.FuncDefaultsEntry)
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class FuncDefaultsEntry:
|
||||
"""默认参数表条目"""
|
||||
Name: str
|
||||
Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr])(pool 内,可能被 reset)
|
||||
DefaultCount: int
|
||||
ParamCount: int # 形参数量(不含 self)
|
||||
# 常量快照(stdlib 分配,跨文件永久存活):
|
||||
# 注册时提取每个默认值 Constant 的值,跨模块调用时优先用快照重建常量 IR,
|
||||
# 避免读取已被 1b reset_to(mark1) 回收的 pool 内 AST。
|
||||
ConstKinds: t.CInt | t.CPtr # const_kind 数组(DefaultCount 个 i32)
|
||||
ConstInts: t.CInt64T | t.CPtr # int_val 数组(DefaultCount 个 i64)
|
||||
ConstStrs: t.CSizeT | t.CPtr # str_val 指针数组(DefaultCount 个 i8*)
|
||||
+405
-179
@@ -1,17 +1,21 @@
|
||||
import string
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import t, c
|
||||
from stdint import *
|
||||
import stdio
|
||||
import stdlib
|
||||
import memhub
|
||||
import llvmlite
|
||||
import lib.core.Gen.BaseGenMixin as BaseGenMixin
|
||||
import lib.core.Gen.TypeGenMixin as TypeGenMixin
|
||||
import lib.core.Gen.TypeGenBase as TypeGenBase
|
||||
import lib.core.Gen.TypeGenMixin as TypeGenMixin
|
||||
import lib.core.Gen.TypeGenCDef as TypeGenCDef
|
||||
import lib.core.Gen.TypeGenCType as TypeGenCType
|
||||
import lib.core.Gen.TypeGenResolve as TypeGenResolve
|
||||
import lib.core.Gen.TypeGenErr as TypeGenErr
|
||||
import lib.core.Gen.StructGenMixin as StructGenMixin
|
||||
import lib.core.Gen.ExprGenMixin as ExprGenMixin
|
||||
import lib.core.Gen.ExprGenBase as ExprGenBase
|
||||
import lib.core.Gen.ExprGenMixin as ExprGenMixin
|
||||
import lib.core.Gen.ExprGenConst as ExprGenConst
|
||||
import lib.core.Gen.ExprGenFstr as ExprGenFstr
|
||||
import lib.core.Gen.ExprGenOps as ExprGenOps
|
||||
@@ -19,215 +23,437 @@ import lib.core.Gen.ExprGenCdef as ExprGenCdef
|
||||
import lib.core.Gen.ExprGenName as ExprGenName
|
||||
import lib.core.Gen.ExprGenAttr as ExprGenAttr
|
||||
import lib.core.Gen.ExprGenCls as ExprGenCls
|
||||
import lib.core.Gen.CallGenMixin as CallGenMixin
|
||||
import lib.core.Gen.CallGenBase as CallGenBase
|
||||
import lib.core.Gen.CallGenLeafKit as CallGenLeafKit
|
||||
import lib.core.Gen.CallGenCBuiltin as CallGenCBuiltin
|
||||
import lib.core.Gen.CallGenLeafKit as CallGenLeafKit
|
||||
import lib.core.Gen.CallGenCtor as CallGenCtor
|
||||
import lib.core.Gen.CallGenCall as CallGenCall
|
||||
import lib.core.Gen.CallGenProp as CallGenProp
|
||||
import lib.core.Gen.CallGenFd as CallGenFd
|
||||
import lib.core.Gen.CallGenMixin as CallGenMixin
|
||||
import lib.core.Gen.CallGenDispatch as CallGenDispatch
|
||||
import lib.core.Gen.CallGenLib as CallGenLib
|
||||
import lib.core.Gen.CallGenVt as CallGenVt
|
||||
import lib.core.Gen.CallGenVa as CallGenVa
|
||||
import lib.core.Gen.CallGenLib as CallGenLib
|
||||
import lib.core.Gen.CallGenDispatch as CallGenDispatch
|
||||
import lib.core.Gen.CallGenProp as CallGenProp
|
||||
import lib.core.Gen.CallGenFd as CallGenFd
|
||||
import lib.core.Gen.FuncGenBase as FuncGenBase
|
||||
import lib.core.Gen.FuncGenDef as FuncGenDef
|
||||
import lib.core.Gen.FuncGenMixin as FuncGenMixin
|
||||
import lib.core.Gen.ClassGenMixin as ClassGenMixin
|
||||
import lib.core.Gen.ClassGenBase as ClassGenBase
|
||||
import lib.core.Gen.ClassGenMixin as ClassGenMixin
|
||||
import lib.core.Gen.ClassGenEnum as ClassGenEnum
|
||||
import lib.core.Gen.ClassGenGeneric as ClassGenGeneric
|
||||
import lib.core.Gen.ClassGenVTable as ClassGenVTable
|
||||
import lib.core.Gen.ClassGenDef as ClassGenDef
|
||||
import lib.core.Gen.ImportsGenMixin as ImportsGenMixin
|
||||
import lib.core.Gen.StmtGenCifMixin as StmtGenCifMixin
|
||||
import lib.core.Gen.StmtGenDeclMixin as StmtGenDeclMixin
|
||||
import lib.core.Gen.StmtGenMixin as StmtGenMixin
|
||||
import lib.core.Gen.MatchGenMixin as MatchGenMixin
|
||||
import lib.core.Gen.AssignGenMixin as AssignGenMixin
|
||||
import lib.core.Gen.VarGenMixin as VarGenMixin
|
||||
import lib.core.Gen.TranslatorGenMixin as TranslatorGenMixin
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Generator - 生成器(P1 骨架 + P2 多继承 Mixin 组合)
|
||||
# Generator - 生成器(双向引用组合架构)
|
||||
#
|
||||
# 对象化重构宿主(wiki/14-oo-refactor.md):
|
||||
# @t.NoVTable + 多继承(BaseGen 状态 + TypeGen 类型映射),方法沿
|
||||
# MRO 直接调用(Viper 多继承已支持,M1-M4)。后续 P3-P6 追加
|
||||
# StructGen/ExprGen/CallGen/FuncGen/ClassGen/StmtGen/ImportsGen Mixin。
|
||||
#
|
||||
# 注意:Viper NoVTable 继承只合并字段、不转发父类方法符号(子类调
|
||||
# 父类方法 mangle 成子类名 → undefined reference),因此字段初始化
|
||||
# 全部内联,不调用父类 Init* 方法。
|
||||
# 不再 46 路多继承 Mixin;改为组合:Generator 持所有 GenMixin
|
||||
# 子对象指针(永久池分配,全生命周期),每个 Mixin 持 Gen 回指。
|
||||
# 跨子对象访问 = self.Gen.<Mixin 字段>.<字段/方法>(链式有风险,
|
||||
# 统一用中间变量取子对象再访问)。高亮可推导(显式类型注解)。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class Generator(BaseGenMixin.BaseGenMixin, TypeGenMixin.TypeGenMixin,
|
||||
TypeGenBase.TypeGenBase, TypeGenCDef.TypeGenCDef,
|
||||
TypeGenCType.TypeGenCType, TypeGenResolve.TypeGenResolve,
|
||||
TypeGenErr.TypeGenErr,
|
||||
StructGenMixin.StructGenMixin, ExprGenMixin.ExprGenMixin,
|
||||
ExprGenBase.ExprGenBase, ExprGenConst.ExprGenConst,
|
||||
ExprGenFstr.ExprGenFstr, ExprGenOps.ExprGenOps,
|
||||
ExprGenCdef.ExprGenCdef, ExprGenName.ExprGenName,
|
||||
ExprGenAttr.ExprGenAttr, ExprGenCls.ExprGenCls,
|
||||
CallGenMixin.CallGenMixin, CallGenBase.CallGenBase,
|
||||
CallGenLeafKit.CallGenLeafKit, CallGenCBuiltin.CallGenCBuiltin,
|
||||
CallGenCtor.CallGenCtor, CallGenCall.CallGenCall,
|
||||
CallGenProp.CallGenProp, CallGenFd.CallGenFd,
|
||||
CallGenVt.CallGenVt, CallGenVa.CallGenVa,
|
||||
CallGenLib.CallGenLib, CallGenDispatch.CallGenDispatch,
|
||||
FuncGenBase.FuncGenBase, FuncGenDef.FuncGenDef,
|
||||
FuncGenMixin.FuncGenMixin,
|
||||
ClassGenMixin.ClassGenMixin, ClassGenBase.ClassGenBase,
|
||||
ClassGenEnum.ClassGenEnum, ClassGenGeneric.ClassGenGeneric,
|
||||
ClassGenVTable.ClassGenVTable, ClassGenDef.ClassGenDef,
|
||||
ImportsGenMixin.ImportsGenMixin,
|
||||
StmtGenMixin.StmtGenMixin, MatchGenMixin.MatchGenMixin,
|
||||
AssignGenMixin.AssignGenMixin,
|
||||
VarGenMixin.VarGenMixin, TranslatorGenMixin.TranslatorGenMixin):
|
||||
"""生成器:多继承 Mixin 组合(对象化迁移宿主)"""
|
||||
class Generator:
|
||||
"""生成器:持所有 GenMixin 子对象指针(双向引用组合)"""
|
||||
|
||||
# ---- 子对象指针(46 个,永久池) ----
|
||||
BaseGen: BaseGenMixin.BaseGenMixin | t.CPtr
|
||||
TypeGenBase: TypeGenBase.TypeGenBase | t.CPtr
|
||||
TypeGen: TypeGenMixin.TypeGenMixin | t.CPtr
|
||||
TypeGenCDef: TypeGenCDef.TypeGenCDef | t.CPtr
|
||||
TypeGenCType: TypeGenCType.TypeGenCType | t.CPtr
|
||||
TypeGenResolve: TypeGenResolve.TypeGenResolve | t.CPtr
|
||||
TypeGenErr: TypeGenErr.TypeGenErr | t.CPtr
|
||||
StructGen: StructGenMixin.StructGenMixin | t.CPtr
|
||||
ExprGenBase: ExprGenBase.ExprGenBase | t.CPtr
|
||||
ExprGen: ExprGenMixin.ExprGenMixin | t.CPtr
|
||||
ExprGenConst: ExprGenConst.ExprGenConst | t.CPtr
|
||||
ExprGenFstr: ExprGenFstr.ExprGenFstr | t.CPtr
|
||||
ExprGenOps: ExprGenOps.ExprGenOps | t.CPtr
|
||||
ExprGenCdef: ExprGenCdef.ExprGenCdef | t.CPtr
|
||||
ExprGenName: ExprGenName.ExprGenName | t.CPtr
|
||||
ExprGenAttr: ExprGenAttr.ExprGenAttr | t.CPtr
|
||||
ExprGenCls: ExprGenCls.ExprGenCls | t.CPtr
|
||||
CallGenBase: CallGenBase.CallGenBase | t.CPtr
|
||||
CallGenCBuiltin: CallGenCBuiltin.CallGenCBuiltin | t.CPtr
|
||||
CallGenLeafKit: CallGenLeafKit.CallGenLeafKit | t.CPtr
|
||||
CallGenCtor: CallGenCtor.CallGenCtor | t.CPtr
|
||||
CallGenCall: CallGenCall.CallGenCall | t.CPtr
|
||||
CallGen: CallGenMixin.CallGenMixin | t.CPtr
|
||||
CallGenDispatch: CallGenDispatch.CallGenDispatch | t.CPtr
|
||||
CallGenLib: CallGenLib.CallGenLib | t.CPtr
|
||||
CallGenVt: CallGenVt.CallGenVt | t.CPtr
|
||||
CallGenVa: CallGenVa.CallGenVa | t.CPtr
|
||||
CallGenProp: CallGenProp.CallGenProp | t.CPtr
|
||||
CallGenFd: CallGenFd.CallGenFd | t.CPtr
|
||||
FuncGenBase: FuncGenBase.FuncGenBase | t.CPtr
|
||||
FuncGenDef: FuncGenDef.FuncGenDef | t.CPtr
|
||||
FuncGen: FuncGenMixin.FuncGenMixin | t.CPtr
|
||||
ClassGenBase: ClassGenBase.ClassGenBase | t.CPtr
|
||||
ClassGen: ClassGenMixin.ClassGenMixin | t.CPtr
|
||||
ClassGenEnum: ClassGenEnum.ClassGenEnum | t.CPtr
|
||||
ClassGenGeneric: ClassGenGeneric.ClassGenGeneric | t.CPtr
|
||||
ClassGenVTable: ClassGenVTable.ClassGenVTable | t.CPtr
|
||||
ClassGenDef: ClassGenDef.ClassGenDef | t.CPtr
|
||||
ImportsGen: ImportsGenMixin.ImportsGenMixin | t.CPtr
|
||||
StmtGenCif: StmtGenCifMixin.StmtGenCifMixin | t.CPtr
|
||||
StmtGenDecl: StmtGenDeclMixin.StmtGenDeclMixin | t.CPtr
|
||||
StmtGen: StmtGenMixin.StmtGenMixin | t.CPtr
|
||||
MatchGen: MatchGenMixin.MatchGenMixin | t.CPtr
|
||||
AssignGen: AssignGenMixin.AssignGenMixin | t.CPtr
|
||||
VarGen: VarGenMixin.VarGenMixin | t.CPtr
|
||||
TranslatorGen: TranslatorGenMixin.TranslatorGenMixin | t.CPtr
|
||||
|
||||
def __init__(self, pool: memhub.MemBuddy | t.CPtr):
|
||||
if self is None:
|
||||
return
|
||||
# ---- BaseGenMixin 字段 ----
|
||||
self.Pool = pool
|
||||
self.Module = None
|
||||
self.Builder = None
|
||||
self.SymTab = None
|
||||
self.Funcs = None
|
||||
self.FuncCount = 0
|
||||
self.ImportedModules = None
|
||||
self.FromImports = None
|
||||
self.ModuleSha1 = None
|
||||
self.CurFunc = None
|
||||
self.CurBuilder = None
|
||||
self.CurClassName = None
|
||||
# ---- TypeGenMixin 字段 ----
|
||||
self.TraceFrames = None
|
||||
self.TraceCount = 0
|
||||
self.TempDir = None
|
||||
self.GenericTpNames = None
|
||||
self.GenericTypeArgs = None
|
||||
self.GenericCtxStack = None
|
||||
self.GenericCtxDepth = 0
|
||||
self.CDefineNames = None
|
||||
self.CDefineValues = None
|
||||
self.CDefineDoubleFlags = None
|
||||
self.CDefineStrFlags = None
|
||||
self.CDefineIsDouble = 0
|
||||
self.CDefineIsStr = 0
|
||||
self.CDefineFound = 0
|
||||
# 跨模块 CDefine 查找缓存(perm_pool 永久,跨文件复用)
|
||||
self.XmodCdefNames = None
|
||||
self.XmodCdefValues = None
|
||||
self.XmodCdefDoubleFlags = None
|
||||
self.XmodCdefStrFlags = None
|
||||
self.CurrentModuleSha1 = None
|
||||
self.CTypedefNames = None
|
||||
self.CTypedefTypeStrs = None
|
||||
self.CTypedefFound = 0
|
||||
self.CTypedefResolveDepth = 0
|
||||
self.CTypedefVisiting = None
|
||||
self.CurrentFile = None
|
||||
self.ConstEvalOk = 0
|
||||
# ---- StructGenMixin 字段 ----
|
||||
self.StructTable = None
|
||||
self.StructCount = 0
|
||||
self.StdlibAlloc = 0
|
||||
self.VisibleStructs = None
|
||||
self.StrictVisibility = 0
|
||||
# OOM 语句级诊断:translate_stmt 限频打印 used(定位单文件翻译暴涨起点)
|
||||
self.DiagStmtCount = 0
|
||||
# ---- CallGenMixin 字段 ----
|
||||
self.CexportSha1Arr = None
|
||||
self.CexportFuncArr = None
|
||||
self.CexportCount = 0
|
||||
self.LLVMIRRegSeq = 0
|
||||
self.TempDir = None
|
||||
self.TempDirLen = 0
|
||||
self.ClosureNames = None
|
||||
self.ClosureCount = 0
|
||||
self.FuncptrNames = None
|
||||
self.FuncptrRets = None
|
||||
self.FuncptrCount = 0
|
||||
self.GlobalFuncs = None
|
||||
self.GlobalFuncCount = 0
|
||||
self.GlobalDefaults = None
|
||||
self.GlobalDefaultsCount = 0
|
||||
# ---- ClassGenMixin 字段 ----
|
||||
self.MethodMetaKeys = None
|
||||
self.MethodMetaFlags = None
|
||||
self.MethodMetaCount = 0
|
||||
self.RenumClassNames = None
|
||||
self.RenumClassVariantCounts = None
|
||||
self.RenumVariantNames = None
|
||||
self.RenumVariantTags = None
|
||||
self.RenumClassCount = 0
|
||||
self.RenumAliasClass = None
|
||||
self.RenumAliasField = None
|
||||
self.RenumAliasIndex = None
|
||||
self.RenumAliasCount = 0
|
||||
self.SpecKeys = None
|
||||
self.SpecNames = None
|
||||
self.SpecCount = 0
|
||||
self.GenericClassNames = None
|
||||
self.GenericClassNodes = None
|
||||
self.GenericClassSha1s = None
|
||||
self.GenericClassFiles = None
|
||||
self.GenericClassTpParams = None
|
||||
self.VtFullNames = None
|
||||
self.VtMethodNames = None
|
||||
self.VtParentSha1s = None
|
||||
self.VtMethodCount = 0
|
||||
# ---- ClassGenBase 补漏字段(阶段 D 拆分新增,此前未初始化:
|
||||
# 结构体是 malloc 分配,未初始化字段是内存垃圾——非 null 垃圾
|
||||
# 指针能通过 `is not None` 检查,导致 is_exception_name 等查询
|
||||
# 直接 strcmp 越界崩溃;int 垃圾则导致循环次数失控) ----
|
||||
self.RenumAliasTy = None
|
||||
self.RenumAliasVariant = None
|
||||
self.ClassMetaKinds = None
|
||||
self.ClassMetaClss = None
|
||||
self.ClassMetaFields = None
|
||||
self.ClassMetaCount = 0
|
||||
self.DecoratorFuncCount = 0
|
||||
self.DecoratorFuncNames = None
|
||||
self.DecoratorWrapNames = None
|
||||
self.DecoratorArgs = None
|
||||
# 异常类注册表(_ensure_exception_tables 仍保留懒分配,但
|
||||
# ExceptionNames 必须初始化为 null——否则 `is not None` 误判垃圾
|
||||
# 指针为已初始化,跳过分配直接查表 → strcmp 越界)
|
||||
self.ExceptionCount = 0
|
||||
self.ExceptionNames = None
|
||||
self.ExceptionParents = None
|
||||
self.ExceptionCodes = None
|
||||
self.NextExceptionCode = 0
|
||||
self._exception_codes_tmp_count = 0
|
||||
self.GenericSpecDepth = 0
|
||||
# ---- ImportsGenMixin 字段 ----
|
||||
self.ReexportSha1s = None
|
||||
self.ReexportFuncs = None
|
||||
self.ReexportSrcs = None
|
||||
self.ReexportCount = 0
|
||||
# ---- StmtGenMixin 字段 ----
|
||||
self.CifEvalOk = 0
|
||||
self.EnumTable = None
|
||||
self.EnumCount = 0
|
||||
# ---- AssignGenMixin 字段 ----
|
||||
self.RecoverFound = 0
|
||||
# ---- ExprGenMixin docstring 字段(__doc__ 魔法属性支持)----
|
||||
self.DocKeys = None
|
||||
self.DocValues = None
|
||||
self.DocCount = 0
|
||||
# OOM 诊断计数:跨模块 CDefine 查找调用次数
|
||||
self.DiagCDefineCount = 0
|
||||
self.DiagNameValueCount = 0
|
||||
self.DiagTranslateValueCount = 0
|
||||
# ---- alloc 46 个子对象 + 回指(永久池,fail-fast) ----
|
||||
SubBaseGen: BaseGenMixin.BaseGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(BaseGenMixin.BaseGenMixin.__sizeof__())
|
||||
if SubBaseGen is None:
|
||||
stdio.printf("FAIL: BaseGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubBaseGen, 0, BaseGenMixin.BaseGenMixin.__sizeof__())
|
||||
SubBaseGen.Gen = self
|
||||
self.BaseGen = SubBaseGen
|
||||
SubTypeGenBase: TypeGenBase.TypeGenBase | t.CPtr = CompilerFactory.get_perm_pool().alloc(TypeGenBase.TypeGenBase.__sizeof__())
|
||||
if SubTypeGenBase is None:
|
||||
stdio.printf("FAIL: TypeGenBase alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubTypeGenBase, 0, TypeGenBase.TypeGenBase.__sizeof__())
|
||||
SubTypeGenBase.Gen = self
|
||||
self.TypeGenBase = SubTypeGenBase
|
||||
SubTypeGen: TypeGenMixin.TypeGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(TypeGenMixin.TypeGenMixin.__sizeof__())
|
||||
if SubTypeGen is None:
|
||||
stdio.printf("FAIL: TypeGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubTypeGen, 0, TypeGenMixin.TypeGenMixin.__sizeof__())
|
||||
SubTypeGen.Gen = self
|
||||
self.TypeGen = SubTypeGen
|
||||
SubTypeGenCDef: TypeGenCDef.TypeGenCDef | t.CPtr = CompilerFactory.get_perm_pool().alloc(TypeGenCDef.TypeGenCDef.__sizeof__())
|
||||
if SubTypeGenCDef is None:
|
||||
stdio.printf("FAIL: TypeGenCDef alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubTypeGenCDef, 0, TypeGenCDef.TypeGenCDef.__sizeof__())
|
||||
SubTypeGenCDef.Gen = self
|
||||
self.TypeGenCDef = SubTypeGenCDef
|
||||
SubTypeGenCType: TypeGenCType.TypeGenCType | t.CPtr = CompilerFactory.get_perm_pool().alloc(TypeGenCType.TypeGenCType.__sizeof__())
|
||||
if SubTypeGenCType is None:
|
||||
stdio.printf("FAIL: TypeGenCType alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubTypeGenCType, 0, TypeGenCType.TypeGenCType.__sizeof__())
|
||||
SubTypeGenCType.Gen = self
|
||||
self.TypeGenCType = SubTypeGenCType
|
||||
SubTypeGenResolve: TypeGenResolve.TypeGenResolve | t.CPtr = CompilerFactory.get_perm_pool().alloc(TypeGenResolve.TypeGenResolve.__sizeof__())
|
||||
if SubTypeGenResolve is None:
|
||||
stdio.printf("FAIL: TypeGenResolve alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubTypeGenResolve, 0, TypeGenResolve.TypeGenResolve.__sizeof__())
|
||||
SubTypeGenResolve.Gen = self
|
||||
self.TypeGenResolve = SubTypeGenResolve
|
||||
SubTypeGenErr: TypeGenErr.TypeGenErr | t.CPtr = CompilerFactory.get_perm_pool().alloc(TypeGenErr.TypeGenErr.__sizeof__())
|
||||
if SubTypeGenErr is None:
|
||||
stdio.printf("FAIL: TypeGenErr alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubTypeGenErr, 0, TypeGenErr.TypeGenErr.__sizeof__())
|
||||
SubTypeGenErr.Gen = self
|
||||
self.TypeGenErr = SubTypeGenErr
|
||||
SubStructGen: StructGenMixin.StructGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(StructGenMixin.StructGenMixin.__sizeof__())
|
||||
if SubStructGen is None:
|
||||
stdio.printf("FAIL: StructGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubStructGen, 0, StructGenMixin.StructGenMixin.__sizeof__())
|
||||
SubStructGen.Gen = self
|
||||
self.StructGen = SubStructGen
|
||||
SubExprGenBase: ExprGenBase.ExprGenBase | t.CPtr = CompilerFactory.get_perm_pool().alloc(ExprGenBase.ExprGenBase.__sizeof__())
|
||||
if SubExprGenBase is None:
|
||||
stdio.printf("FAIL: ExprGenBase alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubExprGenBase, 0, ExprGenBase.ExprGenBase.__sizeof__())
|
||||
SubExprGenBase.Gen = self
|
||||
self.ExprGenBase = SubExprGenBase
|
||||
SubExprGen: ExprGenMixin.ExprGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(ExprGenMixin.ExprGenMixin.__sizeof__())
|
||||
if SubExprGen is None:
|
||||
stdio.printf("FAIL: ExprGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubExprGen, 0, ExprGenMixin.ExprGenMixin.__sizeof__())
|
||||
SubExprGen.Gen = self
|
||||
self.ExprGen = SubExprGen
|
||||
SubExprGenConst: ExprGenConst.ExprGenConst | t.CPtr = CompilerFactory.get_perm_pool().alloc(ExprGenConst.ExprGenConst.__sizeof__())
|
||||
if SubExprGenConst is None:
|
||||
stdio.printf("FAIL: ExprGenConst alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubExprGenConst, 0, ExprGenConst.ExprGenConst.__sizeof__())
|
||||
SubExprGenConst.Gen = self
|
||||
self.ExprGenConst = SubExprGenConst
|
||||
SubExprGenFstr: ExprGenFstr.ExprGenFstr | t.CPtr = CompilerFactory.get_perm_pool().alloc(ExprGenFstr.ExprGenFstr.__sizeof__())
|
||||
if SubExprGenFstr is None:
|
||||
stdio.printf("FAIL: ExprGenFstr alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubExprGenFstr, 0, ExprGenFstr.ExprGenFstr.__sizeof__())
|
||||
SubExprGenFstr.Gen = self
|
||||
self.ExprGenFstr = SubExprGenFstr
|
||||
SubExprGenOps: ExprGenOps.ExprGenOps | t.CPtr = CompilerFactory.get_perm_pool().alloc(ExprGenOps.ExprGenOps.__sizeof__())
|
||||
if SubExprGenOps is None:
|
||||
stdio.printf("FAIL: ExprGenOps alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubExprGenOps, 0, ExprGenOps.ExprGenOps.__sizeof__())
|
||||
SubExprGenOps.Gen = self
|
||||
self.ExprGenOps = SubExprGenOps
|
||||
SubExprGenCdef: ExprGenCdef.ExprGenCdef | t.CPtr = CompilerFactory.get_perm_pool().alloc(ExprGenCdef.ExprGenCdef.__sizeof__())
|
||||
if SubExprGenCdef is None:
|
||||
stdio.printf("FAIL: ExprGenCdef alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubExprGenCdef, 0, ExprGenCdef.ExprGenCdef.__sizeof__())
|
||||
SubExprGenCdef.Gen = self
|
||||
self.ExprGenCdef = SubExprGenCdef
|
||||
SubExprGenName: ExprGenName.ExprGenName | t.CPtr = CompilerFactory.get_perm_pool().alloc(ExprGenName.ExprGenName.__sizeof__())
|
||||
if SubExprGenName is None:
|
||||
stdio.printf("FAIL: ExprGenName alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubExprGenName, 0, ExprGenName.ExprGenName.__sizeof__())
|
||||
SubExprGenName.Gen = self
|
||||
self.ExprGenName = SubExprGenName
|
||||
SubExprGenAttr: ExprGenAttr.ExprGenAttr | t.CPtr = CompilerFactory.get_perm_pool().alloc(ExprGenAttr.ExprGenAttr.__sizeof__())
|
||||
if SubExprGenAttr is None:
|
||||
stdio.printf("FAIL: ExprGenAttr alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubExprGenAttr, 0, ExprGenAttr.ExprGenAttr.__sizeof__())
|
||||
SubExprGenAttr.Gen = self
|
||||
self.ExprGenAttr = SubExprGenAttr
|
||||
SubExprGenCls: ExprGenCls.ExprGenCls | t.CPtr = CompilerFactory.get_perm_pool().alloc(ExprGenCls.ExprGenCls.__sizeof__())
|
||||
if SubExprGenCls is None:
|
||||
stdio.printf("FAIL: ExprGenCls alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubExprGenCls, 0, ExprGenCls.ExprGenCls.__sizeof__())
|
||||
SubExprGenCls.Gen = self
|
||||
self.ExprGenCls = SubExprGenCls
|
||||
SubCallGenBase: CallGenBase.CallGenBase | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenBase.CallGenBase.__sizeof__())
|
||||
if SubCallGenBase is None:
|
||||
stdio.printf("FAIL: CallGenBase alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenBase, 0, CallGenBase.CallGenBase.__sizeof__())
|
||||
SubCallGenBase.Gen = self
|
||||
self.CallGenBase = SubCallGenBase
|
||||
SubCallGenCBuiltin: CallGenCBuiltin.CallGenCBuiltin | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenCBuiltin.CallGenCBuiltin.__sizeof__())
|
||||
if SubCallGenCBuiltin is None:
|
||||
stdio.printf("FAIL: CallGenCBuiltin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenCBuiltin, 0, CallGenCBuiltin.CallGenCBuiltin.__sizeof__())
|
||||
SubCallGenCBuiltin.Gen = self
|
||||
self.CallGenCBuiltin = SubCallGenCBuiltin
|
||||
SubCallGenLeafKit: CallGenLeafKit.CallGenLeafKit | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenLeafKit.CallGenLeafKit.__sizeof__())
|
||||
if SubCallGenLeafKit is None:
|
||||
stdio.printf("FAIL: CallGenLeafKit alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenLeafKit, 0, CallGenLeafKit.CallGenLeafKit.__sizeof__())
|
||||
SubCallGenLeafKit.Gen = self
|
||||
self.CallGenLeafKit = SubCallGenLeafKit
|
||||
SubCallGenCtor: CallGenCtor.CallGenCtor | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenCtor.CallGenCtor.__sizeof__())
|
||||
if SubCallGenCtor is None:
|
||||
stdio.printf("FAIL: CallGenCtor alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenCtor, 0, CallGenCtor.CallGenCtor.__sizeof__())
|
||||
SubCallGenCtor.Gen = self
|
||||
self.CallGenCtor = SubCallGenCtor
|
||||
SubCallGenCall: CallGenCall.CallGenCall | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenCall.CallGenCall.__sizeof__())
|
||||
if SubCallGenCall is None:
|
||||
stdio.printf("FAIL: CallGenCall alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenCall, 0, CallGenCall.CallGenCall.__sizeof__())
|
||||
SubCallGenCall.Gen = self
|
||||
self.CallGenCall = SubCallGenCall
|
||||
SubCallGen: CallGenMixin.CallGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenMixin.CallGenMixin.__sizeof__())
|
||||
if SubCallGen is None:
|
||||
stdio.printf("FAIL: CallGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGen, 0, CallGenMixin.CallGenMixin.__sizeof__())
|
||||
SubCallGen.Gen = self
|
||||
self.CallGen = SubCallGen
|
||||
SubCallGenDispatch: CallGenDispatch.CallGenDispatch | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenDispatch.CallGenDispatch.__sizeof__())
|
||||
if SubCallGenDispatch is None:
|
||||
stdio.printf("FAIL: CallGenDispatch alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenDispatch, 0, CallGenDispatch.CallGenDispatch.__sizeof__())
|
||||
SubCallGenDispatch.Gen = self
|
||||
self.CallGenDispatch = SubCallGenDispatch
|
||||
SubCallGenLib: CallGenLib.CallGenLib | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenLib.CallGenLib.__sizeof__())
|
||||
if SubCallGenLib is None:
|
||||
stdio.printf("FAIL: CallGenLib alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenLib, 0, CallGenLib.CallGenLib.__sizeof__())
|
||||
SubCallGenLib.Gen = self
|
||||
self.CallGenLib = SubCallGenLib
|
||||
SubCallGenVt: CallGenVt.CallGenVt | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenVt.CallGenVt.__sizeof__())
|
||||
if SubCallGenVt is None:
|
||||
stdio.printf("FAIL: CallGenVt alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenVt, 0, CallGenVt.CallGenVt.__sizeof__())
|
||||
SubCallGenVt.Gen = self
|
||||
self.CallGenVt = SubCallGenVt
|
||||
SubCallGenVa: CallGenVa.CallGenVa | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenVa.CallGenVa.__sizeof__())
|
||||
if SubCallGenVa is None:
|
||||
stdio.printf("FAIL: CallGenVa alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenVa, 0, CallGenVa.CallGenVa.__sizeof__())
|
||||
SubCallGenVa.Gen = self
|
||||
self.CallGenVa = SubCallGenVa
|
||||
SubCallGenProp: CallGenProp.CallGenProp | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenProp.CallGenProp.__sizeof__())
|
||||
if SubCallGenProp is None:
|
||||
stdio.printf("FAIL: CallGenProp alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenProp, 0, CallGenProp.CallGenProp.__sizeof__())
|
||||
SubCallGenProp.Gen = self
|
||||
self.CallGenProp = SubCallGenProp
|
||||
SubCallGenFd: CallGenFd.CallGenFd | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenFd.CallGenFd.__sizeof__())
|
||||
if SubCallGenFd is None:
|
||||
stdio.printf("FAIL: CallGenFd alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenFd, 0, CallGenFd.CallGenFd.__sizeof__())
|
||||
SubCallGenFd.Gen = self
|
||||
self.CallGenFd = SubCallGenFd
|
||||
SubFuncGenBase: FuncGenBase.FuncGenBase | t.CPtr = CompilerFactory.get_perm_pool().alloc(FuncGenBase.FuncGenBase.__sizeof__())
|
||||
if SubFuncGenBase is None:
|
||||
stdio.printf("FAIL: FuncGenBase alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubFuncGenBase, 0, FuncGenBase.FuncGenBase.__sizeof__())
|
||||
SubFuncGenBase.Gen = self
|
||||
self.FuncGenBase = SubFuncGenBase
|
||||
SubFuncGenDef: FuncGenDef.FuncGenDef | t.CPtr = CompilerFactory.get_perm_pool().alloc(FuncGenDef.FuncGenDef.__sizeof__())
|
||||
if SubFuncGenDef is None:
|
||||
stdio.printf("FAIL: FuncGenDef alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubFuncGenDef, 0, FuncGenDef.FuncGenDef.__sizeof__())
|
||||
SubFuncGenDef.Gen = self
|
||||
self.FuncGenDef = SubFuncGenDef
|
||||
SubFuncGen: FuncGenMixin.FuncGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(FuncGenMixin.FuncGenMixin.__sizeof__())
|
||||
if SubFuncGen is None:
|
||||
stdio.printf("FAIL: FuncGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubFuncGen, 0, FuncGenMixin.FuncGenMixin.__sizeof__())
|
||||
SubFuncGen.Gen = self
|
||||
self.FuncGen = SubFuncGen
|
||||
SubClassGenBase: ClassGenBase.ClassGenBase | t.CPtr = CompilerFactory.get_perm_pool().alloc(ClassGenBase.ClassGenBase.__sizeof__())
|
||||
if SubClassGenBase is None:
|
||||
stdio.printf("FAIL: ClassGenBase alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubClassGenBase, 0, ClassGenBase.ClassGenBase.__sizeof__())
|
||||
SubClassGenBase.Gen = self
|
||||
self.ClassGenBase = SubClassGenBase
|
||||
SubClassGen: ClassGenMixin.ClassGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(ClassGenMixin.ClassGenMixin.__sizeof__())
|
||||
if SubClassGen is None:
|
||||
stdio.printf("FAIL: ClassGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubClassGen, 0, ClassGenMixin.ClassGenMixin.__sizeof__())
|
||||
SubClassGen.Gen = self
|
||||
self.ClassGen = SubClassGen
|
||||
SubClassGenEnum: ClassGenEnum.ClassGenEnum | t.CPtr = CompilerFactory.get_perm_pool().alloc(ClassGenEnum.ClassGenEnum.__sizeof__())
|
||||
if SubClassGenEnum is None:
|
||||
stdio.printf("FAIL: ClassGenEnum alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubClassGenEnum, 0, ClassGenEnum.ClassGenEnum.__sizeof__())
|
||||
SubClassGenEnum.Gen = self
|
||||
self.ClassGenEnum = SubClassGenEnum
|
||||
SubClassGenGeneric: ClassGenGeneric.ClassGenGeneric | t.CPtr = CompilerFactory.get_perm_pool().alloc(ClassGenGeneric.ClassGenGeneric.__sizeof__())
|
||||
if SubClassGenGeneric is None:
|
||||
stdio.printf("FAIL: ClassGenGeneric alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubClassGenGeneric, 0, ClassGenGeneric.ClassGenGeneric.__sizeof__())
|
||||
SubClassGenGeneric.Gen = self
|
||||
self.ClassGenGeneric = SubClassGenGeneric
|
||||
SubClassGenVTable: ClassGenVTable.ClassGenVTable | t.CPtr = CompilerFactory.get_perm_pool().alloc(ClassGenVTable.ClassGenVTable.__sizeof__())
|
||||
if SubClassGenVTable is None:
|
||||
stdio.printf("FAIL: ClassGenVTable alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubClassGenVTable, 0, ClassGenVTable.ClassGenVTable.__sizeof__())
|
||||
SubClassGenVTable.Gen = self
|
||||
self.ClassGenVTable = SubClassGenVTable
|
||||
SubClassGenDef: ClassGenDef.ClassGenDef | t.CPtr = CompilerFactory.get_perm_pool().alloc(ClassGenDef.ClassGenDef.__sizeof__())
|
||||
if SubClassGenDef is None:
|
||||
stdio.printf("FAIL: ClassGenDef alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubClassGenDef, 0, ClassGenDef.ClassGenDef.__sizeof__())
|
||||
SubClassGenDef.Gen = self
|
||||
self.ClassGenDef = SubClassGenDef
|
||||
SubImportsGen: ImportsGenMixin.ImportsGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(ImportsGenMixin.ImportsGenMixin.__sizeof__())
|
||||
if SubImportsGen is None:
|
||||
stdio.printf("FAIL: ImportsGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubImportsGen, 0, ImportsGenMixin.ImportsGenMixin.__sizeof__())
|
||||
SubImportsGen.Gen = self
|
||||
self.ImportsGen = SubImportsGen
|
||||
SubStmtGenCif: StmtGenCifMixin.StmtGenCifMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(StmtGenCifMixin.StmtGenCifMixin.__sizeof__())
|
||||
if SubStmtGenCif is None:
|
||||
stdio.printf("FAIL: StmtGenCifMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubStmtGenCif, 0, StmtGenCifMixin.StmtGenCifMixin.__sizeof__())
|
||||
SubStmtGenCif.Gen = self
|
||||
self.StmtGenCif = SubStmtGenCif
|
||||
SubStmtGenDecl: StmtGenDeclMixin.StmtGenDeclMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(StmtGenDeclMixin.StmtGenDeclMixin.__sizeof__())
|
||||
if SubStmtGenDecl is None:
|
||||
stdio.printf("FAIL: StmtGenDeclMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubStmtGenDecl, 0, StmtGenDeclMixin.StmtGenDeclMixin.__sizeof__())
|
||||
SubStmtGenDecl.Gen = self
|
||||
self.StmtGenDecl = SubStmtGenDecl
|
||||
SubStmtGen: StmtGenMixin.StmtGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(StmtGenMixin.StmtGenMixin.__sizeof__())
|
||||
if SubStmtGen is None:
|
||||
stdio.printf("FAIL: StmtGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubStmtGen, 0, StmtGenMixin.StmtGenMixin.__sizeof__())
|
||||
SubStmtGen.Gen = self
|
||||
self.StmtGen = SubStmtGen
|
||||
SubMatchGen: MatchGenMixin.MatchGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(MatchGenMixin.MatchGenMixin.__sizeof__())
|
||||
if SubMatchGen is None:
|
||||
stdio.printf("FAIL: MatchGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubMatchGen, 0, MatchGenMixin.MatchGenMixin.__sizeof__())
|
||||
SubMatchGen.Gen = self
|
||||
self.MatchGen = SubMatchGen
|
||||
SubAssignGen: AssignGenMixin.AssignGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(AssignGenMixin.AssignGenMixin.__sizeof__())
|
||||
if SubAssignGen is None:
|
||||
stdio.printf("FAIL: AssignGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubAssignGen, 0, AssignGenMixin.AssignGenMixin.__sizeof__())
|
||||
SubAssignGen.Gen = self
|
||||
self.AssignGen = SubAssignGen
|
||||
SubVarGen: VarGenMixin.VarGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(VarGenMixin.VarGenMixin.__sizeof__())
|
||||
if SubVarGen is None:
|
||||
stdio.printf("FAIL: VarGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubVarGen, 0, VarGenMixin.VarGenMixin.__sizeof__())
|
||||
SubVarGen.Gen = self
|
||||
self.VarGen = SubVarGen
|
||||
SubTranslatorGen: TranslatorGenMixin.TranslatorGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(TranslatorGenMixin.TranslatorGenMixin.__sizeof__())
|
||||
if SubTranslatorGen is None:
|
||||
stdio.printf("FAIL: TranslatorGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubTranslatorGen, 0, TranslatorGenMixin.TranslatorGenMixin.__sizeof__())
|
||||
SubTranslatorGen.Gen = self
|
||||
self.TranslatorGen = SubTranslatorGen
|
||||
|
||||
# ---- 初始化各子对象字段(Init* 方法内联调用) ----
|
||||
SubBaseGen.InitBaseGen(pool)
|
||||
SubTypeGenBase.InitTypeGen()
|
||||
SubCallGenBase.InitCallGen()
|
||||
SubStructGen.InitStructGen()
|
||||
SubClassGenBase.InitClassGen()
|
||||
SubExprGenBase.InitExprGen()
|
||||
SubImportsGen.InitImportsGen()
|
||||
SubStmtGenCif.InitStmtGen()
|
||||
SubAssignGen.InitAssignGen()
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局生成器单例(对象化 P2 兼容层)
|
||||
# 全局生成器单例(组合架构兼容层)
|
||||
# ============================================================
|
||||
_g_gen: Generator | t.CPtr = None
|
||||
+762
-752
File diff suppressed because it is too large.
Load diff
+1304
-1306
File diff suppressed because it is too large.
Load diff
+2515
-2517
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+745
-767
File diff suppressed because it is too large.
Load diff
+1341
-1339
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,3 +1,5 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
@@ -8,18 +10,6 @@ import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprOps as HandlesExprOps
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
@@ -37,12 +27,10 @@ class TypeGenBase:
|
||||
"""字段 + InitTypeGen + trace/临时目录/generic 上下文"""
|
||||
|
||||
# --- 仿 Python Traceback 调用栈(原 _g_trace_frames/_g_trace_count) ---
|
||||
TraceFrames: HandlesType.TraceFrame | t.CPtr # malloc 数组(TRACE_MAX 槽)
|
||||
Gen: Generator.Generator | t.CPtr
|
||||
TraceFrames: GenTypes.TraceFrame | t.CPtr # malloc 数组(TRACE_MAX 槽)
|
||||
TraceCount: int
|
||||
|
||||
# --- 全局 temp_dir(原 _g_temp_dir) ---
|
||||
TempDir: str
|
||||
|
||||
# --- 全局泛型特化上下文(原 _g_generic_tp_names/_g_generic_type_args) ---
|
||||
GenericTpNames: list[str] | t.CPtr
|
||||
GenericTypeArgs: list[str] | t.CPtr
|
||||
@@ -92,7 +80,6 @@ class TypeGenBase:
|
||||
return 1
|
||||
self.TraceFrames = None
|
||||
self.TraceCount = 0
|
||||
self.TempDir = None
|
||||
self.GenericTpNames = None
|
||||
self.GenericTypeArgs = None
|
||||
self.GenericCtxStack = None
|
||||
@@ -126,26 +113,26 @@ class TypeGenBase:
|
||||
"""确保调用栈已初始化(懒加载,用 malloc 不依赖 pool)"""
|
||||
if self.TraceFrames is not None:
|
||||
return 1
|
||||
entry_size: t.CSizeT = HandlesType.TraceFrame.__sizeof__()
|
||||
entry_size: t.CSizeT = GenTypes.TraceFrame.__sizeof__()
|
||||
self.TraceFrames = CompilerFactory.get_perm_pool().alloc(entry_size * TRACE_MAX)
|
||||
if self.TraceFrames is None:
|
||||
return 0
|
||||
string.memset(self.TraceFrames, 0, entry_size * TRACE_MAX)
|
||||
return 1
|
||||
def _get_trace_frame(self, i: int) -> HandlesType.TraceFrame | t.CPtr:
|
||||
def _get_trace_frame(self, i: int) -> GenTypes.TraceFrame | t.CPtr:
|
||||
"""获取第 i 个 TraceFrame 槽位"""
|
||||
if self.TraceFrames is None or i < 0 or i >= TRACE_MAX:
|
||||
return None
|
||||
entry_size: t.CSizeT = HandlesType.TraceFrame.__sizeof__()
|
||||
entry_size: t.CSizeT = GenTypes.TraceFrame.__sizeof__()
|
||||
addr: t.CUInt64T = t.CUInt64T(self.TraceFrames) + i * entry_size
|
||||
return (HandlesType.TraceFrame | t.CPtr)(t.CVoid(addr, t.CPtr))
|
||||
return (GenTypes.TraceFrame | t.CPtr)(t.CVoid(addr, t.CPtr))
|
||||
def push_trace(self, file_name: str, lineno: int, col_start: int = 0, col_end: int = 0):
|
||||
"""压入一个翻译上下文帧(进入新的翻译作用域时调用)"""
|
||||
if self._ensure_trace_init() == 0:
|
||||
return
|
||||
if self.TraceCount >= TRACE_MAX:
|
||||
return
|
||||
frame: HandlesType.TraceFrame | t.CPtr = self._get_trace_frame(self.TraceCount)
|
||||
frame: GenTypes.TraceFrame | t.CPtr = self._get_trace_frame(self.TraceCount)
|
||||
if frame is None:
|
||||
return
|
||||
frame.file_name = file_name
|
||||
@@ -158,7 +145,7 @@ class TypeGenBase:
|
||||
if self.TraceCount <= 0:
|
||||
return
|
||||
self.TraceCount -= 1
|
||||
frame: HandlesType.TraceFrame | t.CPtr = self._get_trace_frame(self.TraceCount)
|
||||
frame: GenTypes.TraceFrame | t.CPtr = self._get_trace_frame(self.TraceCount)
|
||||
if frame is not None:
|
||||
frame.file_name = None
|
||||
frame.lineno = 0
|
||||
@@ -168,7 +155,7 @@ class TypeGenBase:
|
||||
"""清空调用栈(每个文件翻译开始前调用)"""
|
||||
i: int
|
||||
for i in range(self.TraceCount):
|
||||
frame: HandlesType.TraceFrame | t.CPtr = self._get_trace_frame(i)
|
||||
frame: GenTypes.TraceFrame | t.CPtr = self._get_trace_frame(i)
|
||||
if frame is not None:
|
||||
frame.file_name = None
|
||||
frame.lineno = 0
|
||||
@@ -176,11 +163,11 @@ class TypeGenBase:
|
||||
frame.col_end = 0
|
||||
self.TraceCount = 0
|
||||
def set_temp_dir(self, temp_dir: str) -> None:
|
||||
"""设置全局 temp_dir(每个项目编译开始时由 BuildPipeline/Phase1 设置)"""
|
||||
self.TempDir = temp_dir
|
||||
"""设置全局 temp_dir(统一写入 CallGenBase.TempDir,跨子对象经 Gen 指针)"""
|
||||
self.Gen.CallGenBase.SetTempDir(temp_dir)
|
||||
def get_temp_dir(self) -> str:
|
||||
"""获取全局 temp_dir"""
|
||||
return self.TempDir
|
||||
"""获取全局 temp_dir(从 CallGenBase 读取)"""
|
||||
return self.Gen.CallGenBase.TempDir
|
||||
def set_current_module_sha1(self, sha1: str) -> None:
|
||||
"""设置当前正在编译的模块 SHA1(Phase1 在模块开始翻译前调用)"""
|
||||
self.CurrentModuleSha1 = sha1
|
||||
|
||||
+297
-305
@@ -1,306 +1,298 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprOps as HandlesExprOps
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
import lib.core.Gen.TypeGenBase as TypeGenBase
|
||||
|
||||
# ============================================================
|
||||
# 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):
|
||||
"""CDefine 编译期常量表(register/lookup/is/set/clear)"""
|
||||
|
||||
def register_cdefine_constant(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, value: t.CInt64T) -> None:
|
||||
"""注册 CDefine 编译期常量到本地表
|
||||
|
||||
值以十进制字符串存储(64 位 %lld)。大整数 CDefine(如
|
||||
sys.maxsize = 9223372036854775807)必须全精度保存,否则 %d 32 位截断
|
||||
成 -1(0xFFFFFFFF)→ 读回 4294967295(SysLibTest maxsize FAIL 根因)。
|
||||
0xFFFFFFFF 仍存为 "4294967295",常量生成端 const_int32 内部截断回 -1。
|
||||
"""
|
||||
if self.CDefineNames is None:
|
||||
self.CDefineNames = list[str](pool, 64)
|
||||
self.CDefineValues = list[str](pool, 64)
|
||||
self.CDefineDoubleFlags = list[int](pool, 64)
|
||||
self.CDefineStrFlags = list[int](pool, 64)
|
||||
self.CDefineNames.append(name)
|
||||
val_buf: str = pool.alloc(32)
|
||||
if val_buf is not None:
|
||||
viperlib.snprintf(val_buf, 32, "%lld", value)
|
||||
self.CDefineValues.append(val_buf)
|
||||
else:
|
||||
self.CDefineValues.append("0")
|
||||
if self.CDefineDoubleFlags is not None:
|
||||
self.CDefineDoubleFlags.append(0)
|
||||
if self.CDefineStrFlags is not None:
|
||||
self.CDefineStrFlags.append(0)
|
||||
def register_cdefine_double(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, value: double) -> None:
|
||||
"""注册浮点 CDefine 编译期常量(如 U_M_PI: t.CDefine = 3.14159...)
|
||||
|
||||
值以 %f 文本存储并标记浮点,供 translate_value 返回浮点常量。
|
||||
"""
|
||||
if self.CDefineNames is None:
|
||||
self.CDefineNames = list[str](pool, 64)
|
||||
self.CDefineValues = list[str](pool, 64)
|
||||
self.CDefineDoubleFlags = list[int](pool, 64)
|
||||
self.CDefineStrFlags = list[int](pool, 64)
|
||||
self.CDefineNames.append(name)
|
||||
val_buf: str = pool.alloc(32)
|
||||
if val_buf is not None:
|
||||
# 用 CRT stdio.snprintf 而非 viperlib.snprintf:viperlib 自实现格式化器的
|
||||
# %g 浮点路径有 bug(%.17g 输出错误值,如 pi 显示 3.1397985 而非 3.1415926,
|
||||
# 位模式 %a 正确),会导致 CDefine 表存错文本 → lookup 生成错 LLVM 常量。
|
||||
stdio.snprintf(val_buf, 32, "%.17g", value)
|
||||
self.CDefineValues.append(val_buf)
|
||||
else:
|
||||
self.CDefineValues.append("0")
|
||||
if self.CDefineDoubleFlags is not None:
|
||||
self.CDefineDoubleFlags.append(1)
|
||||
if self.CDefineStrFlags is not None:
|
||||
self.CDefineStrFlags.append(0)
|
||||
# fail-fast:CDefine 值缓冲区分配失败必须终止编译,
|
||||
if val_buf is None:
|
||||
VLogger.error("CDefine 浮点值缓冲区分配失败", "CDEF-DBG")
|
||||
HandlesType.fatal_error(None, "CDefine 浮点值缓冲区分配失败", "MemoryError")
|
||||
def register_cdefine_string(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, value: str) -> None:
|
||||
"""注册字符串 CDefine 编译期常量(如 ZLIB_VERSION: t.CDefine = "1.3.2")
|
||||
|
||||
字符串值深拷贝到 pool(AST 节点的 str_val 可能被 pool 操作覆写,
|
||||
与浮点 CDefine 的恢复同理)。
|
||||
"""
|
||||
if pool is None or name is None:
|
||||
return
|
||||
if value is None:
|
||||
HandlesType.fatal_error(None, f"CDefine 字符串值缺失: {name}", "InternalCompilerError")
|
||||
return
|
||||
if self.CDefineNames is None:
|
||||
self.CDefineNames = list[str](pool, 64)
|
||||
self.CDefineValues = list[str](pool, 64)
|
||||
self.CDefineDoubleFlags = list[int](pool, 64)
|
||||
self.CDefineStrFlags = list[int](pool, 64)
|
||||
self.CDefineNames.append(name)
|
||||
vlen: t.CSizeT = string.strlen(value)
|
||||
vcopy: str = pool.alloc(vlen + 1)
|
||||
if vcopy is None:
|
||||
HandlesType.fatal_error(None, f"CDefine 字符串值分配失败: {name}", "MemoryError")
|
||||
return
|
||||
string.strcpy(vcopy, value)
|
||||
self.CDefineValues.append(vcopy)
|
||||
if self.CDefineDoubleFlags is not None:
|
||||
self.CDefineDoubleFlags.append(0)
|
||||
if self.CDefineStrFlags is not None:
|
||||
self.CDefineStrFlags.append(1)
|
||||
# 同步设置"最近注册/查表结果为字符串"标志(is_cdefine_str() 读取)。
|
||||
# 跨模块字符串 CDefine 读回(_lookup_cross_module_cdefine 字符串分支只调
|
||||
# 本函数 + 尾部 set_cdefine_found,无 lookup_cdefine_string 回查)→ 若此处
|
||||
# 不设标志,属性路径 is_cdefine_str()==0 → 退化为整数分支返回 0 →
|
||||
# IR 生成 inttoptr i32 0(NULL)→ 运行时报 (null-) + strlen(NULL-) 崩溃
|
||||
# (test_pyzlib.vp pyzlib.ZLIB_VERSION 根因)。
|
||||
self.CDefineIsStr = 1
|
||||
self.CDefineFound = 1
|
||||
# ============================================================
|
||||
# 跨模块 CDefine 查找缓存(perm_pool 永久分配,跨文件复用)
|
||||
# ============================================================
|
||||
def register_xmod_cdefine(self, name: str, value_str: str,
|
||||
is_double: int, is_str: int) -> None:
|
||||
"""注册跨模块 CDefine 查找结果到 perm_pool 全局缓存(跨文件复用)
|
||||
|
||||
Args:
|
||||
name: CDefine 常量名(如 CONST_INT)
|
||||
value_str: 值文本(十进制/浮点/字符串)
|
||||
is_double: 1=浮点值
|
||||
is_str: 1=字符串值
|
||||
"""
|
||||
if name is None or value_str is None:
|
||||
return
|
||||
# 去重:同名已缓存则跳过(首次查找结果为准,CDefine 全局唯一约定)
|
||||
if self.XmodCdefNames is not None:
|
||||
x_n: t.CSizeT = len(self.XmodCdefNames)
|
||||
x_i: t.CSizeT
|
||||
for x_i in range(x_n):
|
||||
x_nm: str = self.XmodCdefNames.get(x_i)
|
||||
if x_nm is not None and string.strcmp(x_nm, name) == 0:
|
||||
return
|
||||
perm: memhub.MemBuddy | t.CPtr = CompilerFactory.get_perm_pool()
|
||||
if self.XmodCdefNames is None:
|
||||
self.XmodCdefNames = list[str](perm, 64)
|
||||
self.XmodCdefValues = list[str](perm, 64)
|
||||
self.XmodCdefDoubleFlags = list[int](perm, 64)
|
||||
self.XmodCdefStrFlags = list[int](perm, 64)
|
||||
# key/value 深拷贝到 perm_pool:入参(pool.alloc 临时缓冲)在
|
||||
# reset_to(mark2) 后悬空,append 只存指针 → 必须深拷贝跨 reset 存活
|
||||
klen: t.CSizeT = string.strlen(name)
|
||||
kcopy: str = perm.alloc(klen + 1)
|
||||
if kcopy is None:
|
||||
return
|
||||
string.strcpy(kcopy, name)
|
||||
vlen: t.CSizeT = string.strlen(value_str)
|
||||
vcopy: str = perm.alloc(vlen + 1)
|
||||
if vcopy is None:
|
||||
return
|
||||
string.strcpy(vcopy, value_str)
|
||||
self.XmodCdefNames.append(kcopy)
|
||||
self.XmodCdefValues.append(vcopy)
|
||||
if self.XmodCdefDoubleFlags is not None:
|
||||
self.XmodCdefDoubleFlags.append(is_double)
|
||||
if self.XmodCdefStrFlags is not None:
|
||||
self.XmodCdefStrFlags.append(is_str)
|
||||
def lookup_xmod_cdefine(self, name: str) -> str:
|
||||
"""查找跨模块 CDefine 缓存,命中设置 found/is_double/is_str 标志
|
||||
|
||||
Returns:
|
||||
值文本(命中),未命中返回 None
|
||||
"""
|
||||
self.CDefineFound = 0
|
||||
self.CDefineIsDouble = 0
|
||||
self.CDefineIsStr = 0
|
||||
if name is None or self.XmodCdefNames is None:
|
||||
return None
|
||||
n: t.CSizeT = len(self.XmodCdefNames)
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
nm: str = self.XmodCdefNames.get(i)
|
||||
if nm is not None and string.strcmp(nm, name) == 0:
|
||||
val_str: str = self.XmodCdefValues.get(i)
|
||||
if val_str is not None:
|
||||
self.CDefineFound = 1
|
||||
if self.XmodCdefStrFlags is not None and self.XmodCdefStrFlags.get(i) == 1:
|
||||
self.CDefineIsStr = 1
|
||||
elif self.XmodCdefDoubleFlags is not None and self.XmodCdefDoubleFlags.get(i) == 1:
|
||||
self.CDefineIsDouble = 1
|
||||
return val_str
|
||||
return None
|
||||
def lookup_cdefine_constant(self, name: str) -> t.CInt64T:
|
||||
"""查找 CDefine 编译期常量
|
||||
|
||||
返回找到的值(64 位,大整数 CDefine 如 sys.maxsize 全精度)。
|
||||
由于 -1 是合法值(如 INVALID_HANDLE_VALUE=0xFFFFFFFF=-1),
|
||||
用全局 _g_cdefine_found 标志区分"未找到"和值为 -1。
|
||||
调用方应在调用后检查 _g_cdefine_found。
|
||||
浮点 CDefine 项返回整数部分(与 _g_cdefine_is_double 标志配合)。
|
||||
"""
|
||||
self.CDefineFound = 0
|
||||
self.CDefineIsDouble = 0
|
||||
self.CDefineIsStr = 0
|
||||
if self.CDefineNames is None:
|
||||
return 0
|
||||
n: t.CSizeT = len(self.CDefineNames)
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
nm: str = self.CDefineNames.get(i)
|
||||
if nm is not None and string.strcmp(nm, name) == 0:
|
||||
val_str: str = self.CDefineValues.get(i)
|
||||
if val_str is not None:
|
||||
self.CDefineFound = 1
|
||||
if self.CDefineStrFlags is not None and self.CDefineStrFlags.get(i) == 1:
|
||||
# 字符串 CDefine(如 ZLIB_VERSION="1.3.2"):整数查询路径
|
||||
# 标记 is_str,调用方改用 lookup_cdefine_string 取字符串。
|
||||
self.CDefineIsStr = 1
|
||||
return 0
|
||||
if self.CDefineDoubleFlags is not None and self.CDefineDoubleFlags.get(i) == 1:
|
||||
self.CDefineIsDouble = 1
|
||||
return string.atoll(val_str)
|
||||
return string.atoll(val_str)
|
||||
return 0
|
||||
def lookup_cdefine_double(self, name: str) -> double:
|
||||
"""查找 CDefine 编译期常量,返回 double 值(浮点/整数统一)
|
||||
|
||||
与 lookup_cdefine_constant 共享 _g_cdefine_found / _g_cdefine_is_double
|
||||
(found=1 且 is_double=1 → 浮点 CDefine,应返回浮点常量)。
|
||||
"""
|
||||
self.CDefineFound = 0
|
||||
self.CDefineIsDouble = 0
|
||||
self.CDefineIsStr = 0
|
||||
if self.CDefineNames is None:
|
||||
return 0.0
|
||||
n: t.CSizeT = len(self.CDefineNames)
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
nm: str = self.CDefineNames.get(i)
|
||||
if nm is not None and string.strcmp(nm, name) == 0:
|
||||
val_str: str = self.CDefineValues.get(i)
|
||||
if val_str is not None:
|
||||
self.CDefineFound = 1
|
||||
if self.CDefineStrFlags is not None and self.CDefineStrFlags.get(i) == 1:
|
||||
self.CDefineIsStr = 1
|
||||
return 0.0
|
||||
if self.CDefineDoubleFlags is not None and self.CDefineDoubleFlags.get(i) == 1:
|
||||
self.CDefineIsDouble = 1
|
||||
ret_d: double = string.atof(val_str)
|
||||
return ret_d
|
||||
ret_i2: double = double(string.atoll(val_str))
|
||||
return ret_i2
|
||||
return 0.0
|
||||
def lookup_cdefine_string(self, name: str) -> str:
|
||||
"""查找 CDefine 编译期字符串值(found=1 且 is_str=1 时有效)
|
||||
|
||||
返回的字符串指针位于 pool 内(当前模块生命周期内有效),
|
||||
调用方应尽快用于 create_global_string 拷贝到 LLVM 常量。
|
||||
"""
|
||||
self.CDefineFound = 0
|
||||
self.CDefineIsDouble = 0
|
||||
self.CDefineIsStr = 0
|
||||
if self.CDefineNames is None:
|
||||
return None
|
||||
n: t.CSizeT = len(self.CDefineNames)
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
nm: str = self.CDefineNames.get(i)
|
||||
if nm is not None and string.strcmp(nm, name) == 0:
|
||||
val_str: str = self.CDefineValues.get(i)
|
||||
if val_str is not None:
|
||||
self.CDefineFound = 1
|
||||
if self.CDefineStrFlags is not None and self.CDefineStrFlags.get(i) == 1:
|
||||
self.CDefineIsStr = 1
|
||||
return val_str
|
||||
return val_str
|
||||
return None
|
||||
def is_cdefine_str(self) -> int:
|
||||
"""检查最近一次 CDefine 查找命中的是否是字符串常量"""
|
||||
return self.CDefineIsStr
|
||||
def is_cdefine_double(self) -> int:
|
||||
"""检查最近一次 CDefine 查找命中的是否是浮点常量"""
|
||||
return self.CDefineIsDouble
|
||||
def is_cdefine_found(self) -> int:
|
||||
"""检查上次 lookup_cdefine_constant 是否找到值"""
|
||||
return self.CDefineFound
|
||||
def set_cdefine_found(self, val: int) -> None:
|
||||
"""设置 cdefine_found 标志(供跨模块查找函数使用)"""
|
||||
self.CDefineFound = val
|
||||
def clear_cdefine_constants(self) -> None:
|
||||
"""清空 CDefine 常量表(模块切换时调用)"""
|
||||
self.CDefineNames = None
|
||||
self.CDefineValues = None
|
||||
self.CDefineDoubleFlags = None
|
||||
self.CDefineStrFlags = None
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
import lib.core.Gen.TypeGenBase as TypeGenBase
|
||||
|
||||
# ============================================================
|
||||
# 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):
|
||||
"""CDefine 编译期常量表(register/lookup/is/set/clear)"""
|
||||
|
||||
def register_cdefine_constant(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, value: t.CInt64T) -> None:
|
||||
"""注册 CDefine 编译期常量到本地表
|
||||
|
||||
值以十进制字符串存储(64 位 %lld)。大整数 CDefine(如
|
||||
sys.maxsize = 9223372036854775807)必须全精度保存,否则 %d 32 位截断
|
||||
成 -1(0xFFFFFFFF)→ 读回 4294967295(SysLibTest maxsize FAIL 根因)。
|
||||
0xFFFFFFFF 仍存为 "4294967295",常量生成端 const_int32 内部截断回 -1。
|
||||
"""
|
||||
if self.CDefineNames is None:
|
||||
self.CDefineNames = list[str](pool, 64)
|
||||
self.CDefineValues = list[str](pool, 64)
|
||||
self.CDefineDoubleFlags = list[int](pool, 64)
|
||||
self.CDefineStrFlags = list[int](pool, 64)
|
||||
self.CDefineNames.append(name)
|
||||
val_buf: str = pool.alloc(32)
|
||||
if val_buf is not None:
|
||||
viperlib.snprintf(val_buf, 32, "%lld", value)
|
||||
self.CDefineValues.append(val_buf)
|
||||
else:
|
||||
self.CDefineValues.append("0")
|
||||
if self.CDefineDoubleFlags is not None:
|
||||
self.CDefineDoubleFlags.append(0)
|
||||
if self.CDefineStrFlags is not None:
|
||||
self.CDefineStrFlags.append(0)
|
||||
def register_cdefine_double(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, value: double) -> None:
|
||||
"""注册浮点 CDefine 编译期常量(如 U_M_PI: t.CDefine = 3.14159...)
|
||||
|
||||
值以 %f 文本存储并标记浮点,供 translate_value 返回浮点常量。
|
||||
"""
|
||||
if self.CDefineNames is None:
|
||||
self.CDefineNames = list[str](pool, 64)
|
||||
self.CDefineValues = list[str](pool, 64)
|
||||
self.CDefineDoubleFlags = list[int](pool, 64)
|
||||
self.CDefineStrFlags = list[int](pool, 64)
|
||||
self.CDefineNames.append(name)
|
||||
val_buf: str = pool.alloc(32)
|
||||
if val_buf is not None:
|
||||
# 用 CRT stdio.snprintf 而非 viperlib.snprintf:viperlib 自实现格式化器的
|
||||
# %g 浮点路径有 bug(%.17g 输出错误值,如 pi 显示 3.1397985 而非 3.1415926,
|
||||
# 位模式 %a 正确),会导致 CDefine 表存错文本 → lookup 生成错 LLVM 常量。
|
||||
stdio.snprintf(val_buf, 32, "%.17g", value)
|
||||
self.CDefineValues.append(val_buf)
|
||||
else:
|
||||
self.CDefineValues.append("0")
|
||||
if self.CDefineDoubleFlags is not None:
|
||||
self.CDefineDoubleFlags.append(1)
|
||||
if self.CDefineStrFlags is not None:
|
||||
self.CDefineStrFlags.append(0)
|
||||
# fail-fast:CDefine 值缓冲区分配失败必须终止编译,
|
||||
if val_buf is None:
|
||||
VLogger.error("CDefine 浮点值缓冲区分配失败", "CDEF-DBG")
|
||||
self.Gen.TypeGenErr.fatal_error(None, "CDefine 浮点值缓冲区分配失败", "MemoryError")
|
||||
def register_cdefine_string(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, value: str) -> None:
|
||||
"""注册字符串 CDefine 编译期常量(如 ZLIB_VERSION: t.CDefine = "1.3.2")
|
||||
|
||||
字符串值深拷贝到 pool(AST 节点的 str_val 可能被 pool 操作覆写,
|
||||
与浮点 CDefine 的恢复同理)。
|
||||
"""
|
||||
if pool is None or name is None:
|
||||
return
|
||||
if value is None:
|
||||
self.Gen.TypeGenErr.fatal_error(None, f"CDefine 字符串值缺失: {name}", "InternalCompilerError")
|
||||
return
|
||||
if self.CDefineNames is None:
|
||||
self.CDefineNames = list[str](pool, 64)
|
||||
self.CDefineValues = list[str](pool, 64)
|
||||
self.CDefineDoubleFlags = list[int](pool, 64)
|
||||
self.CDefineStrFlags = list[int](pool, 64)
|
||||
self.CDefineNames.append(name)
|
||||
vlen: t.CSizeT = string.strlen(value)
|
||||
vcopy: str = pool.alloc(vlen + 1)
|
||||
if vcopy is None:
|
||||
self.Gen.TypeGenErr.fatal_error(None, f"CDefine 字符串值分配失败: {name}", "MemoryError")
|
||||
return
|
||||
string.strcpy(vcopy, value)
|
||||
self.CDefineValues.append(vcopy)
|
||||
if self.CDefineDoubleFlags is not None:
|
||||
self.CDefineDoubleFlags.append(0)
|
||||
if self.CDefineStrFlags is not None:
|
||||
self.CDefineStrFlags.append(1)
|
||||
# 同步设置"最近注册/查表结果为字符串"标志(is_cdefine_str() 读取)。
|
||||
# 跨模块字符串 CDefine 读回(_lookup_cross_module_cdefine 字符串分支只调
|
||||
# 本函数 + 尾部 set_cdefine_found,无 lookup_cdefine_string 回查)→ 若此处
|
||||
# 不设标志,属性路径 is_cdefine_str()==0 → 退化为整数分支返回 0 →
|
||||
# IR 生成 inttoptr i32 0(NULL)→ 运行时报 (null-) + strlen(NULL-) 崩溃
|
||||
# (test_pyzlib.vp pyzlib.ZLIB_VERSION 根因)。
|
||||
self.CDefineIsStr = 1
|
||||
self.CDefineFound = 1
|
||||
# ============================================================
|
||||
# 跨模块 CDefine 查找缓存(perm_pool 永久分配,跨文件复用)
|
||||
# ============================================================
|
||||
def register_xmod_cdefine(self, name: str, value_str: str,
|
||||
is_double: int, is_str: int) -> None:
|
||||
"""注册跨模块 CDefine 查找结果到 perm_pool 全局缓存(跨文件复用)
|
||||
|
||||
Args:
|
||||
name: CDefine 常量名(如 CONST_INT)
|
||||
value_str: 值文本(十进制/浮点/字符串)
|
||||
is_double: 1=浮点值
|
||||
is_str: 1=字符串值
|
||||
"""
|
||||
if name is None or value_str is None:
|
||||
return
|
||||
# 去重:同名已缓存则跳过(首次查找结果为准,CDefine 全局唯一约定)
|
||||
if self.XmodCdefNames is not None:
|
||||
x_n: t.CSizeT = len(self.XmodCdefNames)
|
||||
x_i: t.CSizeT
|
||||
for x_i in range(x_n):
|
||||
x_nm: str = self.XmodCdefNames.get(x_i)
|
||||
if x_nm is not None and string.strcmp(x_nm, name) == 0:
|
||||
return
|
||||
perm: memhub.MemBuddy | t.CPtr = CompilerFactory.get_perm_pool()
|
||||
if self.XmodCdefNames is None:
|
||||
self.XmodCdefNames = list[str](perm, 64)
|
||||
self.XmodCdefValues = list[str](perm, 64)
|
||||
self.XmodCdefDoubleFlags = list[int](perm, 64)
|
||||
self.XmodCdefStrFlags = list[int](perm, 64)
|
||||
# key/value 深拷贝到 perm_pool:入参(pool.alloc 临时缓冲)在
|
||||
# reset_to(mark2) 后悬空,append 只存指针 → 必须深拷贝跨 reset 存活
|
||||
klen: t.CSizeT = string.strlen(name)
|
||||
kcopy: str = perm.alloc(klen + 1)
|
||||
if kcopy is None:
|
||||
return
|
||||
string.strcpy(kcopy, name)
|
||||
vlen: t.CSizeT = string.strlen(value_str)
|
||||
vcopy: str = perm.alloc(vlen + 1)
|
||||
if vcopy is None:
|
||||
return
|
||||
string.strcpy(vcopy, value_str)
|
||||
self.XmodCdefNames.append(kcopy)
|
||||
self.XmodCdefValues.append(vcopy)
|
||||
if self.XmodCdefDoubleFlags is not None:
|
||||
self.XmodCdefDoubleFlags.append(is_double)
|
||||
if self.XmodCdefStrFlags is not None:
|
||||
self.XmodCdefStrFlags.append(is_str)
|
||||
def lookup_xmod_cdefine(self, name: str) -> str:
|
||||
"""查找跨模块 CDefine 缓存,命中设置 found/is_double/is_str 标志
|
||||
|
||||
Returns:
|
||||
值文本(命中),未命中返回 None
|
||||
"""
|
||||
self.CDefineFound = 0
|
||||
self.CDefineIsDouble = 0
|
||||
self.CDefineIsStr = 0
|
||||
if name is None or self.XmodCdefNames is None:
|
||||
return None
|
||||
n: t.CSizeT = len(self.XmodCdefNames)
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
nm: str = self.XmodCdefNames.get(i)
|
||||
if nm is not None and string.strcmp(nm, name) == 0:
|
||||
val_str: str = self.XmodCdefValues.get(i)
|
||||
if val_str is not None:
|
||||
self.CDefineFound = 1
|
||||
if self.XmodCdefStrFlags is not None and self.XmodCdefStrFlags.get(i) == 1:
|
||||
self.CDefineIsStr = 1
|
||||
elif self.XmodCdefDoubleFlags is not None and self.XmodCdefDoubleFlags.get(i) == 1:
|
||||
self.CDefineIsDouble = 1
|
||||
return val_str
|
||||
return None
|
||||
def lookup_cdefine_constant(self, name: str) -> t.CInt64T:
|
||||
"""查找 CDefine 编译期常量
|
||||
|
||||
返回找到的值(64 位,大整数 CDefine 如 sys.maxsize 全精度)。
|
||||
由于 -1 是合法值(如 INVALID_HANDLE_VALUE=0xFFFFFFFF=-1),
|
||||
用全局 _g_cdefine_found 标志区分"未找到"和值为 -1。
|
||||
调用方应在调用后检查 _g_cdefine_found。
|
||||
浮点 CDefine 项返回整数部分(与 _g_cdefine_is_double 标志配合)。
|
||||
"""
|
||||
self.CDefineFound = 0
|
||||
self.CDefineIsDouble = 0
|
||||
self.CDefineIsStr = 0
|
||||
if self.CDefineNames is None:
|
||||
return 0
|
||||
n: t.CSizeT = len(self.CDefineNames)
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
nm: str = self.CDefineNames.get(i)
|
||||
if nm is not None and string.strcmp(nm, name) == 0:
|
||||
val_str: str = self.CDefineValues.get(i)
|
||||
if val_str is not None:
|
||||
self.CDefineFound = 1
|
||||
if self.CDefineStrFlags is not None and self.CDefineStrFlags.get(i) == 1:
|
||||
# 字符串 CDefine(如 ZLIB_VERSION="1.3.2"):整数查询路径
|
||||
# 标记 is_str,调用方改用 lookup_cdefine_string 取字符串。
|
||||
self.CDefineIsStr = 1
|
||||
return 0
|
||||
if self.CDefineDoubleFlags is not None and self.CDefineDoubleFlags.get(i) == 1:
|
||||
self.CDefineIsDouble = 1
|
||||
return string.atoll(val_str)
|
||||
return string.atoll(val_str)
|
||||
return 0
|
||||
def lookup_cdefine_double(self, name: str) -> double:
|
||||
"""查找 CDefine 编译期常量,返回 double 值(浮点/整数统一)
|
||||
|
||||
与 lookup_cdefine_constant 共享 _g_cdefine_found / _g_cdefine_is_double
|
||||
(found=1 且 is_double=1 → 浮点 CDefine,应返回浮点常量)。
|
||||
"""
|
||||
self.CDefineFound = 0
|
||||
self.CDefineIsDouble = 0
|
||||
self.CDefineIsStr = 0
|
||||
if self.CDefineNames is None:
|
||||
return 0.0
|
||||
n: t.CSizeT = len(self.CDefineNames)
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
nm: str = self.CDefineNames.get(i)
|
||||
if nm is not None and string.strcmp(nm, name) == 0:
|
||||
val_str: str = self.CDefineValues.get(i)
|
||||
if val_str is not None:
|
||||
self.CDefineFound = 1
|
||||
if self.CDefineStrFlags is not None and self.CDefineStrFlags.get(i) == 1:
|
||||
self.CDefineIsStr = 1
|
||||
return 0.0
|
||||
if self.CDefineDoubleFlags is not None and self.CDefineDoubleFlags.get(i) == 1:
|
||||
self.CDefineIsDouble = 1
|
||||
ret_d: double = string.atof(val_str)
|
||||
return ret_d
|
||||
ret_i2: double = double(string.atoll(val_str))
|
||||
return ret_i2
|
||||
return 0.0
|
||||
def lookup_cdefine_string(self, name: str) -> str:
|
||||
"""查找 CDefine 编译期字符串值(found=1 且 is_str=1 时有效)
|
||||
|
||||
返回的字符串指针位于 pool 内(当前模块生命周期内有效),
|
||||
调用方应尽快用于 create_global_string 拷贝到 LLVM 常量。
|
||||
"""
|
||||
self.CDefineFound = 0
|
||||
self.CDefineIsDouble = 0
|
||||
self.CDefineIsStr = 0
|
||||
if self.CDefineNames is None:
|
||||
return None
|
||||
n: t.CSizeT = len(self.CDefineNames)
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
nm: str = self.CDefineNames.get(i)
|
||||
if nm is not None and string.strcmp(nm, name) == 0:
|
||||
val_str: str = self.CDefineValues.get(i)
|
||||
if val_str is not None:
|
||||
self.CDefineFound = 1
|
||||
if self.CDefineStrFlags is not None and self.CDefineStrFlags.get(i) == 1:
|
||||
self.CDefineIsStr = 1
|
||||
return val_str
|
||||
return val_str
|
||||
return None
|
||||
def is_cdefine_str(self) -> int:
|
||||
"""检查最近一次 CDefine 查找命中的是否是字符串常量"""
|
||||
return self.CDefineIsStr
|
||||
def is_cdefine_double(self) -> int:
|
||||
"""检查最近一次 CDefine 查找命中的是否是浮点常量"""
|
||||
return self.CDefineIsDouble
|
||||
def is_cdefine_found(self) -> int:
|
||||
"""检查上次 lookup_cdefine_constant 是否找到值"""
|
||||
return self.CDefineFound
|
||||
def set_cdefine_found(self, val: int) -> None:
|
||||
"""设置 cdefine_found 标志(供跨模块查找函数使用)"""
|
||||
self.CDefineFound = val
|
||||
def clear_cdefine_constants(self) -> None:
|
||||
"""清空 CDefine 常量表(模块切换时调用)"""
|
||||
self.CDefineNames = None
|
||||
self.CDefineValues = None
|
||||
self.CDefineDoubleFlags = None
|
||||
self.CDefineStrFlags = None
|
||||
self.CDefineIsStr = 0
|
||||
+415
-422
@@ -1,422 +1,415 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprOps as HandlesExprOps
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
import lib.core.Gen.TypeGenBase as TypeGenBase
|
||||
|
||||
# ============================================================
|
||||
# TypeGenCType - TypeGenMixin 拆分(阶段 D):CTypedef 表(register/lookup/ScanCTypedefDeclarations/_eval_const_int_expr)
|
||||
#
|
||||
# 继承 TypeGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesType 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class TypeGenCType(TypeGenBase.TypeGenBase):
|
||||
"""CTypedef 表(register/lookup/ScanCTypedefDeclarations/_eval_const_int_expr)"""
|
||||
|
||||
def register_ctypedef(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, type_str: str) -> None:
|
||||
"""注册 CTypedef 到本地表
|
||||
|
||||
Args:
|
||||
pool: 内存池
|
||||
name: CTypedef 名称(如 "HANDLE")
|
||||
type_str: 类型表达式字符串(如 "VOIDPTR" 或 "t.CVoid | t.CPtr")
|
||||
"""
|
||||
if name is None or type_str is None or pool is None:
|
||||
return
|
||||
if self.CTypedefNames is None:
|
||||
self.CTypedefNames = list[str](pool, 64)
|
||||
self.CTypedefTypeStrs = list[str](pool, 64)
|
||||
# 去重:若已存在同名 CTypedef,更新其类型字符串
|
||||
if self.CTypedefNames is not None:
|
||||
exist_n: t.CSizeT = len(self.CTypedefNames)
|
||||
ei: t.CSizeT
|
||||
for ei in range(exist_n):
|
||||
en: str = self.CTypedefNames.get(ei)
|
||||
if en is not None and string.strcmp(en, name) == 0:
|
||||
# 已存在,更新类型字符串
|
||||
self.CTypedefTypeStrs.set(ei, type_str)
|
||||
return
|
||||
self.CTypedefNames.append(name)
|
||||
self.CTypedefTypeStrs.append(type_str)
|
||||
def lookup_ctypedef(self, name: str) -> str:
|
||||
"""查找 CTypedef,返回类型表达式字符串
|
||||
|
||||
返回找到的类型表达式字符串,未找到返回 None。
|
||||
调用方应在调用后检查 _g_ctypedef_found 标志区分"未找到"和"空字符串"。
|
||||
"""
|
||||
self.CTypedefFound = 0
|
||||
if name is None:
|
||||
return None
|
||||
if self.CTypedefNames is None:
|
||||
return None
|
||||
n: t.CSizeT = len(self.CTypedefNames)
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
nm: str = self.CTypedefNames.get(i)
|
||||
if nm is not None and string.strcmp(nm, name) == 0:
|
||||
ts: str = self.CTypedefTypeStrs.get(i)
|
||||
self.CTypedefFound = 1
|
||||
return ts
|
||||
return None
|
||||
def is_ctypedef_found(self) -> int:
|
||||
"""检查上次 lookup_ctypedef 是否找到值"""
|
||||
return self.CTypedefFound
|
||||
def clear_ctypedefs(self) -> None:
|
||||
"""清空 CTypedef 表(模块切换时调用)"""
|
||||
self.CTypedefNames = None
|
||||
self.CTypedefTypeStrs = None
|
||||
self.CTypedefResolveDepth = 0
|
||||
self.CTypedefVisiting = None
|
||||
def _ctypedef_push_visiting(self, pool: memhub.MemBuddy | t.CPtr, name: str) -> int:
|
||||
"""将 CTypedef 名加入正在解析列表(循环检测)
|
||||
|
||||
Returns:
|
||||
0=成功加入(无循环),1=检测到循环
|
||||
"""
|
||||
if name is None:
|
||||
return 0
|
||||
if self.CTypedefVisiting is None:
|
||||
self.CTypedefVisiting = list[str](pool, 32)
|
||||
if self.CTypedefVisiting is None:
|
||||
return 0
|
||||
vn: t.CSizeT = len(self.CTypedefVisiting)
|
||||
vi: t.CSizeT
|
||||
for vi in range(vn):
|
||||
vs: str = self.CTypedefVisiting.get(vi)
|
||||
if vs is not None and string.strcmp(vs, name) == 0:
|
||||
return 1 # 循环检测
|
||||
self.CTypedefVisiting.append(name)
|
||||
return 0
|
||||
def _ctypedef_pop_visiting(self) -> None:
|
||||
"""从正在解析列表弹出最后一个 CTypedef 名"""
|
||||
if self.CTypedefVisiting is None:
|
||||
return
|
||||
vn: t.CSizeT = len(self.CTypedefVisiting)
|
||||
if vn > 0:
|
||||
self.CTypedefVisiting.pop()
|
||||
def _is_ctypedef_annotation(self, annotation: ast.AST | t.CPtr) -> int:
|
||||
"""检测类型注解是否为 t.CTypedef
|
||||
|
||||
Args:
|
||||
annotation: 类型注解 AST 节点
|
||||
|
||||
Returns:
|
||||
1=是 t.CTypedef,0=否
|
||||
"""
|
||||
if annotation is None:
|
||||
return 0
|
||||
k_v: int = annotation.kind()
|
||||
if k_v != ast.ASTKind.Attribute:
|
||||
return 0
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annotation)
|
||||
# 字段访问改用 ast 模块访问器(跨模块 stub 字段访问陷阱防护:
|
||||
# TypeGenCType 直接访问 at.attr 可能按 stub 类型生成错误 GEP,
|
||||
# 读垃圾地址 → strcmp 0xC0000005 崩溃,stdint.vp 根因)。
|
||||
at_attr_v: str = ast.attribute_get_attr(at)
|
||||
if at_attr_v is None:
|
||||
return 0
|
||||
# 限长比较替代 strcmp:attr 是零拷贝引用 src_buf 的 token 字符串,
|
||||
# 可能无 NUL 结尾("CTypedef" 后紧跟空格/其他字符),strcmp 会
|
||||
# 无限读穿到页边界 → 0xC0000005(stdint.vp 崩溃根因)。strncmp
|
||||
# 只读 8 字节,再校验第 9 字节为终止/分隔符(防 "CTypedefXXX" 误匹配)。
|
||||
if string.strncmp(at_attr_v, "CTypedef", 8) != 0:
|
||||
return 0
|
||||
sep_ch_d: t.CChar = at_attr_v[8]
|
||||
if sep_ch_d != '\0' and sep_ch_d != ' ' and sep_ch_d != '\n' \
|
||||
and sep_ch_d != '\r' and sep_ch_d != '\t' and sep_ch_d != '|':
|
||||
return 0
|
||||
at_val_v: ast.AST | t.CPtr = ast.attribute_get_value(at)
|
||||
if at_val_v is None or at_val_v.kind() != ast.ASTKind.Name:
|
||||
return 0
|
||||
mod_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at_val_v)
|
||||
mod_id_v: str = ast.name_get_id(mod_nm)
|
||||
if mod_id_v is None:
|
||||
return 0
|
||||
# 同样限长比较("t" 无 NUL 结尾时 strcmp 读穿)
|
||||
if string.strncmp(mod_id_v, "t", 1) != 0:
|
||||
return 0
|
||||
sep_ch_m: t.CChar = mod_id_v[1]
|
||||
if sep_ch_m != '\0' and sep_ch_m != ' ' and sep_ch_m != '\n' \
|
||||
and sep_ch_m != '\r' and sep_ch_m != '\t' and sep_ch_m != '|':
|
||||
return 0
|
||||
return 1
|
||||
def ScanCTypedefDeclarations(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
tree: ast.AST | t.CPtr) -> int:
|
||||
"""扫描 AST 顶层节点,注册所有 NAME: t.CTypedef = Type 声明
|
||||
|
||||
在 _translate_module_level 中、模块级变量预注册之前调用,
|
||||
确保 CTypedef 名称在类型解析时可用。
|
||||
|
||||
Args:
|
||||
pool: 内存池
|
||||
tree: 模块 AST 根节点
|
||||
|
||||
Returns:
|
||||
注册的 CTypedef 数量
|
||||
"""
|
||||
if pool is None or tree is None:
|
||||
return 0
|
||||
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
|
||||
if ch is None:
|
||||
return 0
|
||||
n: t.CSizeT = len(ch)
|
||||
count: int = 0
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
child: ast.AST | t.CPtr = ch.get(i)
|
||||
if child is None:
|
||||
continue
|
||||
if child.kind() != ast.ASTKind.AnnAssign:
|
||||
continue
|
||||
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(child)
|
||||
if aa.annotation is None:
|
||||
continue
|
||||
# 检测注解是否为 t.CTypedef
|
||||
if self._is_ctypedef_annotation(aa.annotation) == 0:
|
||||
continue
|
||||
# 提取目标名称(必须是 Name 节点)
|
||||
if aa.target is None or aa.target.kind() != ast.ASTKind.Name:
|
||||
continue
|
||||
tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
|
||||
tgt_id_v: str = ast.name_get_id(tgt)
|
||||
if tgt_id_v is None:
|
||||
continue
|
||||
# 提取类型表达式字符串(从 value AST 节点)
|
||||
if aa.value is None:
|
||||
continue
|
||||
type_str: str = HandlesType._get_type_name_from_annotation(pool, aa.value)
|
||||
if type_str is None:
|
||||
continue
|
||||
# 注册 CTypedef
|
||||
self.register_ctypedef(pool, tgt_id_v, type_str)
|
||||
count += 1
|
||||
return count
|
||||
def register_ctypedef_from_source(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
src: str) -> int:
|
||||
"""从源码文本逐行扫描注册 CTypedef(NAME: t.CTypedef = TYPE)
|
||||
|
||||
stdint.vp 崩溃根因修复:AST 字符串字段(attr/id)token 零拷贝指向
|
||||
src_buf,跨阶段内容不稳定(悬空),ScanCTypedefDeclarations 读
|
||||
attr 会 0xC0000005。本函数在 src_buf 有效期内(Phase1 1b translate
|
||||
前)用纯文本匹配注册,不依赖 AST 节点内容。
|
||||
"""
|
||||
if pool is None or src is None:
|
||||
return 0
|
||||
# 文件边界防护:clear_ctypedefs 只在 translate 前调用(Phase1Main
|
||||
# L800),文件级 reset_to(mark1) 回收本文件翻译期 pool 分配后,上一
|
||||
# 文件的 CTypedefNames 表指针悬空(非 None,list 本身也 pool 分配)。
|
||||
# 本函数去重遍历(register_ctypedef 内 strcmp)读已回收内存 →
|
||||
# 0xC0000005(1.log: stdint.vp 翻译时 strcmp 读地址 0x4)。先清表
|
||||
# 重建,杜绝悬空遍历。翻译期 Handle 按需注册不受影响(L800 会再清)。
|
||||
self.clear_ctypedefs()
|
||||
src_len: t.CSizeT = string.strlen(src)
|
||||
count: int = 0
|
||||
line_start: t.CSizeT = 0
|
||||
i: t.CSizeT = 0
|
||||
while i <= src_len:
|
||||
if i == src_len or src[i] == '\n':
|
||||
line_len: t.CSizeT = i - line_start
|
||||
if line_len > 0:
|
||||
# 找行内第一个 ':'(跳过注释行)
|
||||
j: t.CSizeT = 0
|
||||
found_colon: int = 0
|
||||
while j < line_len:
|
||||
ch_c: t.CChar = src[line_start + j]
|
||||
if ch_c == ':':
|
||||
found_colon = 1
|
||||
break
|
||||
if ch_c == '#' or ch_c == '\r':
|
||||
break
|
||||
j += 1
|
||||
if found_colon != 0:
|
||||
# 左段 NAME(trim 尾随空格)
|
||||
name_len: t.CSizeT = j
|
||||
while name_len > 0 and src[line_start + name_len - 1] == ' ':
|
||||
name_len -= 1
|
||||
if name_len > 0 and name_len < 128:
|
||||
# 右段必须含 "t.CTypedef"
|
||||
rest: str = src + line_start + j + 1
|
||||
if string.strstr(rest, "t.CTypedef") is not None:
|
||||
# 提取 "=" 后的类型表达式(trim 空格)
|
||||
eq_ptr: str = string.strstr(rest, "=")
|
||||
if eq_ptr is not None:
|
||||
ty_start: str = eq_ptr + 1
|
||||
while ty_start[0] == ' ':
|
||||
ty_start += 1
|
||||
ty_end: t.CSizeT = string.strlen(ty_start)
|
||||
while ty_end > 0 and (ty_start[ty_end - 1] == ' '
|
||||
or ty_start[ty_end - 1] == '\r'):
|
||||
ty_end -= 1
|
||||
if ty_end > 0:
|
||||
name_buf: str = pool.alloc(name_len + 1)
|
||||
ty_buf: str = pool.alloc(ty_end + 1)
|
||||
if name_buf is not None and ty_buf is not None:
|
||||
string.strncpy(name_buf, src + line_start, name_len)
|
||||
name_buf[name_len] = '\0'
|
||||
string.strncpy(ty_buf, ty_start, ty_end)
|
||||
ty_buf[ty_end] = '\0'
|
||||
self.register_ctypedef(pool, name_buf, ty_buf)
|
||||
count += 1
|
||||
line_start = i + 1
|
||||
i += 1
|
||||
return count
|
||||
def _eval_const_int_expr(self, node: ast.AST | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr = None,
|
||||
from_imports: str = None,
|
||||
imported_modules: str = None) -> int:
|
||||
"""递归计算常量整数表达式
|
||||
|
||||
pool/from_imports/imported_modules:跨模块 CDefine 查找上下文
|
||||
(t.CArray count 引用依赖模块的 CDefine,如 SHA512_BLOCK_LEN 定义在
|
||||
hashlib/__sha512.vp,本地 CDefine 表每模块清空,需跨模块回退查找)。
|
||||
"""
|
||||
if node is None:
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
k: int = node.kind()
|
||||
|
||||
# Constant: 整数字面量
|
||||
if k == ast.ASTKind.Constant:
|
||||
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
|
||||
if cn.const_kind == ast.CONST_INT:
|
||||
self.ConstEvalOk = 1
|
||||
return cn.int_val
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
|
||||
# Name: CDefine 常量名(本地表优先,未命中走跨模块查找)
|
||||
if k == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
|
||||
if nm.id is None:
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
val: int = HandlesType.lookup_cdefine_constant(nm.id)
|
||||
if HandlesType.is_cdefine_found() == 0:
|
||||
# 本地表未命中:跨模块 CDefine 查找
|
||||
# 用 HandlesExpr 模块级委托(self._lookup_cross_module_cdefine 是
|
||||
# ExprGenMixin 方法,TypeGenMixin 直接调用会生成未定义引用)
|
||||
if (from_imports is not None or imported_modules is not None) \
|
||||
and pool is not None:
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
x_val: int = HandlesExpr._lookup_cross_module_cdefine(
|
||||
pool, nm.id, from_imports, imported_modules)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
self.ConstEvalOk = 1
|
||||
return x_val
|
||||
# 定位日志:跨模块 CDefine 查找失败(t.CArray count 场景)
|
||||
fb_cdf: str = VLogger.fmt_buf()
|
||||
if fb_cdf is not None:
|
||||
viperlib.snprintf(fb_cdf, 1024,
|
||||
"[CDEF-MISS] name=%s fi=%s im=%s",
|
||||
nm.id,
|
||||
from_imports if from_imports is not None else "(null)",
|
||||
imported_modules if imported_modules is not None else "(null)")
|
||||
VLogger.error(fb_cdf, "CDEF")
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
self.ConstEvalOk = 1
|
||||
return val
|
||||
|
||||
# Attribute: 模块限定常量名,如 hashlib.MD5_DIGEST_LEN
|
||||
# (t.CArray[t.CUInt8T, hashlib.MD5_DIGEST_LEN] 的 count 是 Attribute,
|
||||
# 复用跨模块 CDefine 查找:*:模块 → 源文件提取;re-export 常量由
|
||||
# _lookup_cross_module_cdefine 的 from-import 递归子模块兜底)
|
||||
if k == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
|
||||
if at.attr is None:
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
if at.value is not None and at.value.kind() == ast.ASTKind.Name:
|
||||
at_mod: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
|
||||
if at_mod.id is not None:
|
||||
if (from_imports is not None or imported_modules is not None) \
|
||||
and pool is not None:
|
||||
mod_len: t.CSizeT = string.strlen(at_mod.id)
|
||||
fi_buf: str = pool.alloc(mod_len + 3)
|
||||
if fi_buf is not None:
|
||||
fi_buf[0] = '*'
|
||||
fi_buf[1] = ':'
|
||||
for mi in range(mod_len):
|
||||
fi_buf[2 + mi] = at_mod.id[mi]
|
||||
fi_buf[2 + mod_len] = '\0'
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
av: int = HandlesExpr._lookup_cross_module_cdefine(
|
||||
pool, at.attr, fi_buf, imported_modules)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
self.ConstEvalOk = 1
|
||||
return av
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
|
||||
# BinOp: 算术/位运算
|
||||
if k == ast.ASTKind.BinOp:
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
|
||||
# 递归计算左操作数
|
||||
lv: int = self._eval_const_int_expr(bop.left, pool, from_imports, imported_modules)
|
||||
if self.ConstEvalOk == 0:
|
||||
return 0
|
||||
# 递归计算右操作数
|
||||
rv: int = self._eval_const_int_expr(bop.right, pool, from_imports, imported_modules)
|
||||
if self.ConstEvalOk == 0:
|
||||
return 0
|
||||
# 根据运算符执行计算
|
||||
if bop.op == ast.OpKind.Add:
|
||||
self.ConstEvalOk = 1
|
||||
return lv + rv
|
||||
if bop.op == ast.OpKind.Sub:
|
||||
self.ConstEvalOk = 1
|
||||
return lv - rv
|
||||
if bop.op == ast.OpKind.Mult:
|
||||
self.ConstEvalOk = 1
|
||||
return lv * rv
|
||||
if bop.op == ast.OpKind.Div:
|
||||
# 整数常量除法:与 FloorDiv 一致(对齐 TPC ConstEvaluator L354-355)
|
||||
if rv == 0:
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
self.ConstEvalOk = 1
|
||||
return lv // rv
|
||||
if bop.op == ast.OpKind.FloorDiv:
|
||||
if rv == 0:
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
self.ConstEvalOk = 1
|
||||
return lv // rv
|
||||
if bop.op == ast.OpKind.BitOr:
|
||||
self.ConstEvalOk = 1
|
||||
return lv | rv
|
||||
if bop.op == ast.OpKind.BitAnd:
|
||||
self.ConstEvalOk = 1
|
||||
return lv & rv
|
||||
# 不支持的运算符
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
|
||||
# 不支持的节点类型
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
import lib.core.Gen.TypeGenBase as TypeGenBase
|
||||
|
||||
# ============================================================
|
||||
# TypeGenCType - TypeGenMixin 拆分(阶段 D):CTypedef 表(register/lookup/ScanCTypedefDeclarations/_eval_const_int_expr)
|
||||
#
|
||||
# 继承 TypeGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesType 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class TypeGenCType(TypeGenBase.TypeGenBase):
|
||||
"""CTypedef 表(register/lookup/ScanCTypedefDeclarations/_eval_const_int_expr)"""
|
||||
|
||||
def register_ctypedef(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, type_str: str) -> None:
|
||||
"""注册 CTypedef 到本地表
|
||||
|
||||
Args:
|
||||
pool: 内存池
|
||||
name: CTypedef 名称(如 "HANDLE")
|
||||
type_str: 类型表达式字符串(如 "VOIDPTR" 或 "t.CVoid | t.CPtr")
|
||||
"""
|
||||
if name is None or type_str is None or pool is None:
|
||||
return
|
||||
if self.CTypedefNames is None:
|
||||
self.CTypedefNames = list[str](pool, 64)
|
||||
self.CTypedefTypeStrs = list[str](pool, 64)
|
||||
# 去重:若已存在同名 CTypedef,更新其类型字符串
|
||||
if self.CTypedefNames is not None:
|
||||
exist_n: t.CSizeT = len(self.CTypedefNames)
|
||||
ei: t.CSizeT
|
||||
for ei in range(exist_n):
|
||||
en: str = self.CTypedefNames.get(ei)
|
||||
if en is not None and string.strcmp(en, name) == 0:
|
||||
# 已存在,更新类型字符串
|
||||
self.CTypedefTypeStrs.set(ei, type_str)
|
||||
return
|
||||
self.CTypedefNames.append(name)
|
||||
self.CTypedefTypeStrs.append(type_str)
|
||||
def lookup_ctypedef(self, name: str) -> str:
|
||||
"""查找 CTypedef,返回类型表达式字符串
|
||||
|
||||
返回找到的类型表达式字符串,未找到返回 None。
|
||||
调用方应在调用后检查 _g_ctypedef_found 标志区分"未找到"和"空字符串"。
|
||||
"""
|
||||
self.CTypedefFound = 0
|
||||
if name is None:
|
||||
return None
|
||||
if self.CTypedefNames is None:
|
||||
return None
|
||||
n: t.CSizeT = len(self.CTypedefNames)
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
nm: str = self.CTypedefNames.get(i)
|
||||
if nm is not None and string.strcmp(nm, name) == 0:
|
||||
ts: str = self.CTypedefTypeStrs.get(i)
|
||||
self.CTypedefFound = 1
|
||||
return ts
|
||||
return None
|
||||
def is_ctypedef_found(self) -> int:
|
||||
"""检查上次 lookup_ctypedef 是否找到值"""
|
||||
return self.CTypedefFound
|
||||
def clear_ctypedefs(self) -> None:
|
||||
"""清空 CTypedef 表(模块切换时调用)"""
|
||||
self.CTypedefNames = None
|
||||
self.CTypedefTypeStrs = None
|
||||
self.CTypedefResolveDepth = 0
|
||||
self.CTypedefVisiting = None
|
||||
def _ctypedef_push_visiting(self, pool: memhub.MemBuddy | t.CPtr, name: str) -> int:
|
||||
"""将 CTypedef 名加入正在解析列表(循环检测)
|
||||
|
||||
Returns:
|
||||
0=成功加入(无循环),1=检测到循环
|
||||
"""
|
||||
if name is None:
|
||||
return 0
|
||||
if self.CTypedefVisiting is None:
|
||||
self.CTypedefVisiting = list[str](pool, 32)
|
||||
if self.CTypedefVisiting is None:
|
||||
return 0
|
||||
vn: t.CSizeT = len(self.CTypedefVisiting)
|
||||
vi: t.CSizeT
|
||||
for vi in range(vn):
|
||||
vs: str = self.CTypedefVisiting.get(vi)
|
||||
if vs is not None and string.strcmp(vs, name) == 0:
|
||||
return 1 # 循环检测
|
||||
self.CTypedefVisiting.append(name)
|
||||
return 0
|
||||
def _ctypedef_pop_visiting(self) -> None:
|
||||
"""从正在解析列表弹出最后一个 CTypedef 名"""
|
||||
if self.CTypedefVisiting is None:
|
||||
return
|
||||
vn: t.CSizeT = len(self.CTypedefVisiting)
|
||||
if vn > 0:
|
||||
self.CTypedefVisiting.pop()
|
||||
def _is_ctypedef_annotation(self, annotation: ast.AST | t.CPtr) -> int:
|
||||
"""检测类型注解是否为 t.CTypedef
|
||||
|
||||
Args:
|
||||
annotation: 类型注解 AST 节点
|
||||
|
||||
Returns:
|
||||
1=是 t.CTypedef,0=否
|
||||
"""
|
||||
if annotation is None:
|
||||
return 0
|
||||
k_v: int = annotation.kind()
|
||||
if k_v != ast.ASTKind.Attribute:
|
||||
return 0
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annotation)
|
||||
# 字段访问改用 ast 模块访问器(跨模块 stub 字段访问陷阱防护:
|
||||
# TypeGenCType 直接访问 at.attr 可能按 stub 类型生成错误 GEP,
|
||||
# 读垃圾地址 → strcmp 0xC0000005 崩溃,stdint.vp 根因)。
|
||||
at_attr_v: str = ast.attribute_get_attr(at)
|
||||
if at_attr_v is None:
|
||||
return 0
|
||||
# 限长比较替代 strcmp:attr 是零拷贝引用 src_buf 的 token 字符串,
|
||||
# 可能无 NUL 结尾("CTypedef" 后紧跟空格/其他字符),strcmp 会
|
||||
# 无限读穿到页边界 → 0xC0000005(stdint.vp 崩溃根因)。strncmp
|
||||
# 只读 8 字节,再校验第 9 字节为终止/分隔符(防 "CTypedefXXX" 误匹配)。
|
||||
if string.strncmp(at_attr_v, "CTypedef", 8) != 0:
|
||||
return 0
|
||||
sep_ch_d: t.CChar = at_attr_v[8]
|
||||
if sep_ch_d != '\0' and sep_ch_d != ' ' and sep_ch_d != '\n' \
|
||||
and sep_ch_d != '\r' and sep_ch_d != '\t' and sep_ch_d != '|':
|
||||
return 0
|
||||
at_val_v: ast.AST | t.CPtr = ast.attribute_get_value(at)
|
||||
if at_val_v is None or at_val_v.kind() != ast.ASTKind.Name:
|
||||
return 0
|
||||
mod_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at_val_v)
|
||||
mod_id_v: str = ast.name_get_id(mod_nm)
|
||||
if mod_id_v is None:
|
||||
return 0
|
||||
# 同样限长比较("t" 无 NUL 结尾时 strcmp 读穿)
|
||||
if string.strncmp(mod_id_v, "t", 1) != 0:
|
||||
return 0
|
||||
sep_ch_m: t.CChar = mod_id_v[1]
|
||||
if sep_ch_m != '\0' and sep_ch_m != ' ' and sep_ch_m != '\n' \
|
||||
and sep_ch_m != '\r' and sep_ch_m != '\t' and sep_ch_m != '|':
|
||||
return 0
|
||||
return 1
|
||||
def ScanCTypedefDeclarations(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
tree: ast.AST | t.CPtr) -> int:
|
||||
"""扫描 AST 顶层节点,注册所有 NAME: t.CTypedef = Type 声明
|
||||
|
||||
在 _translate_module_level 中、模块级变量预注册之前调用,
|
||||
确保 CTypedef 名称在类型解析时可用。
|
||||
|
||||
Args:
|
||||
pool: 内存池
|
||||
tree: 模块 AST 根节点
|
||||
|
||||
Returns:
|
||||
注册的 CTypedef 数量
|
||||
"""
|
||||
if pool is None or tree is None:
|
||||
return 0
|
||||
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
|
||||
if ch is None:
|
||||
return 0
|
||||
n: t.CSizeT = len(ch)
|
||||
count: int = 0
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
child: ast.AST | t.CPtr = ch.get(i)
|
||||
if child is None:
|
||||
continue
|
||||
if child.kind() != ast.ASTKind.AnnAssign:
|
||||
continue
|
||||
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(child)
|
||||
if aa.annotation is None:
|
||||
continue
|
||||
# 检测注解是否为 t.CTypedef
|
||||
if self._is_ctypedef_annotation(aa.annotation) == 0:
|
||||
continue
|
||||
# 提取目标名称(必须是 Name 节点)
|
||||
if aa.target is None or aa.target.kind() != ast.ASTKind.Name:
|
||||
continue
|
||||
tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
|
||||
tgt_id_v: str = ast.name_get_id(tgt)
|
||||
if tgt_id_v is None:
|
||||
continue
|
||||
# 提取类型表达式字符串(从 value AST 节点)
|
||||
if aa.value is None:
|
||||
continue
|
||||
type_str: str = self.Gen.TypeGenResolve._get_type_name_from_annotation(pool, aa.value)
|
||||
if type_str is None:
|
||||
continue
|
||||
# 注册 CTypedef
|
||||
self.register_ctypedef(pool, tgt_id_v, type_str)
|
||||
count += 1
|
||||
return count
|
||||
def register_ctypedef_from_source(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
src: str) -> int:
|
||||
"""从源码文本逐行扫描注册 CTypedef(NAME: t.CTypedef = TYPE)
|
||||
|
||||
stdint.vp 崩溃根因修复:AST 字符串字段(attr/id)token 零拷贝指向
|
||||
src_buf,跨阶段内容不稳定(悬空),ScanCTypedefDeclarations 读
|
||||
attr 会 0xC0000005。本函数在 src_buf 有效期内(Phase1 1b translate
|
||||
前)用纯文本匹配注册,不依赖 AST 节点内容。
|
||||
"""
|
||||
if pool is None or src is None:
|
||||
return 0
|
||||
# 文件边界防护:clear_ctypedefs 只在 translate 前调用(Phase1Main
|
||||
# L800),文件级 reset_to(mark1) 回收本文件翻译期 pool 分配后,上一
|
||||
# 文件的 CTypedefNames 表指针悬空(非 None,list 本身也 pool 分配)。
|
||||
# 本函数去重遍历(register_ctypedef 内 strcmp)读已回收内存 →
|
||||
# 0xC0000005(1.log: stdint.vp 翻译时 strcmp 读地址 0x4)。先清表
|
||||
# 重建,杜绝悬空遍历。翻译期 Handle 按需注册不受影响(L800 会再清)。
|
||||
self.clear_ctypedefs()
|
||||
src_len: t.CSizeT = string.strlen(src)
|
||||
count: int = 0
|
||||
line_start: t.CSizeT = 0
|
||||
i: t.CSizeT = 0
|
||||
while i <= src_len:
|
||||
if i == src_len or src[i] == '\n':
|
||||
line_len: t.CSizeT = i - line_start
|
||||
if line_len > 0:
|
||||
# 找行内第一个 ':'(跳过注释行)
|
||||
j: t.CSizeT = 0
|
||||
found_colon: int = 0
|
||||
while j < line_len:
|
||||
ch_c: t.CChar = src[line_start + j]
|
||||
if ch_c == ':':
|
||||
found_colon = 1
|
||||
break
|
||||
if ch_c == '#' or ch_c == '\r':
|
||||
break
|
||||
j += 1
|
||||
if found_colon != 0:
|
||||
# 左段 NAME(trim 尾随空格)
|
||||
name_len: t.CSizeT = j
|
||||
while name_len > 0 and src[line_start + name_len - 1] == ' ':
|
||||
name_len -= 1
|
||||
if name_len > 0 and name_len < 128:
|
||||
# 右段必须含 "t.CTypedef"
|
||||
rest: str = src + line_start + j + 1
|
||||
if string.strstr(rest, "t.CTypedef") is not None:
|
||||
# 提取 "=" 后的类型表达式(trim 空格)
|
||||
eq_ptr: str = string.strstr(rest, "=")
|
||||
if eq_ptr is not None:
|
||||
ty_start: str = eq_ptr + 1
|
||||
while ty_start[0] == ' ':
|
||||
ty_start += 1
|
||||
ty_end: t.CSizeT = string.strlen(ty_start)
|
||||
while ty_end > 0 and (ty_start[ty_end - 1] == ' '
|
||||
or ty_start[ty_end - 1] == '\r'):
|
||||
ty_end -= 1
|
||||
if ty_end > 0:
|
||||
name_buf: str = pool.alloc(name_len + 1)
|
||||
ty_buf: str = pool.alloc(ty_end + 1)
|
||||
if name_buf is not None and ty_buf is not None:
|
||||
string.strncpy(name_buf, src + line_start, name_len)
|
||||
name_buf[name_len] = '\0'
|
||||
string.strncpy(ty_buf, ty_start, ty_end)
|
||||
ty_buf[ty_end] = '\0'
|
||||
self.register_ctypedef(pool, name_buf, ty_buf)
|
||||
count += 1
|
||||
line_start = i + 1
|
||||
i += 1
|
||||
return count
|
||||
def _eval_const_int_expr(self, node: ast.AST | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr = None,
|
||||
from_imports: str = None,
|
||||
imported_modules: str = None) -> int:
|
||||
"""递归计算常量整数表达式
|
||||
|
||||
pool/from_imports/imported_modules:跨模块 CDefine 查找上下文
|
||||
(t.CArray count 引用依赖模块的 CDefine,如 SHA512_BLOCK_LEN 定义在
|
||||
hashlib/__sha512.vp,本地 CDefine 表每模块清空,需跨模块回退查找)。
|
||||
"""
|
||||
if node is None:
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
k: int = node.kind()
|
||||
|
||||
# Constant: 整数字面量
|
||||
if k == ast.ASTKind.Constant:
|
||||
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
|
||||
if cn.const_kind == ast.CONST_INT:
|
||||
self.ConstEvalOk = 1
|
||||
return cn.int_val
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
|
||||
# Name: CDefine 常量名(本地表优先,未命中走跨模块查找)
|
||||
if k == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
|
||||
if nm.id is None:
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
val: int = self.Gen.TypeGenCDef.lookup_cdefine_constant(nm.id)
|
||||
if self.Gen.TypeGenCDef.is_cdefine_found() == 0:
|
||||
# 本地表未命中:跨模块 CDefine 查找
|
||||
# 用 HandlesExpr 模块级委托(self._lookup_cross_module_cdefine 是
|
||||
# ExprGenMixin 方法,TypeGenMixin 直接调用会生成未定义引用)
|
||||
if (from_imports is not None or imported_modules is not None) \
|
||||
and pool is not None:
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
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
|
||||
# 定位日志:跨模块 CDefine 查找失败(t.CArray count 场景)
|
||||
fb_cdf: str = VLogger.fmt_buf()
|
||||
if fb_cdf is not None:
|
||||
viperlib.snprintf(fb_cdf, 1024,
|
||||
"[CDEF-MISS] name=%s fi=%s im=%s",
|
||||
nm.id,
|
||||
from_imports if from_imports is not None else "(null)",
|
||||
imported_modules if imported_modules is not None else "(null)")
|
||||
VLogger.error(fb_cdf, "CDEF")
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
self.ConstEvalOk = 1
|
||||
return val
|
||||
|
||||
# Attribute: 模块限定常量名,如 hashlib.MD5_DIGEST_LEN
|
||||
# (t.CArray[t.CUInt8T, hashlib.MD5_DIGEST_LEN] 的 count 是 Attribute,
|
||||
# 复用跨模块 CDefine 查找:*:模块 → 源文件提取;re-export 常量由
|
||||
# _lookup_cross_module_cdefine 的 from-import 递归子模块兜底)
|
||||
if k == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
|
||||
if at.attr is None:
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
if at.value is not None and at.value.kind() == ast.ASTKind.Name:
|
||||
at_mod: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
|
||||
if at_mod.id is not None:
|
||||
if (from_imports is not None or imported_modules is not None) \
|
||||
and pool is not None:
|
||||
mod_len: t.CSizeT = string.strlen(at_mod.id)
|
||||
fi_buf: str = pool.alloc(mod_len + 3)
|
||||
if fi_buf is not None:
|
||||
fi_buf[0] = '*'
|
||||
fi_buf[1] = ':'
|
||||
for mi in range(mod_len):
|
||||
fi_buf[2 + mi] = at_mod.id[mi]
|
||||
fi_buf[2 + mod_len] = '\0'
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
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
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
|
||||
# BinOp: 算术/位运算
|
||||
if k == ast.ASTKind.BinOp:
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
|
||||
# 递归计算左操作数
|
||||
lv: int = self._eval_const_int_expr(bop.left, pool, from_imports, imported_modules)
|
||||
if self.ConstEvalOk == 0:
|
||||
return 0
|
||||
# 递归计算右操作数
|
||||
rv: int = self._eval_const_int_expr(bop.right, pool, from_imports, imported_modules)
|
||||
if self.ConstEvalOk == 0:
|
||||
return 0
|
||||
# 根据运算符执行计算
|
||||
if bop.op == ast.OpKind.Add:
|
||||
self.ConstEvalOk = 1
|
||||
return lv + rv
|
||||
if bop.op == ast.OpKind.Sub:
|
||||
self.ConstEvalOk = 1
|
||||
return lv - rv
|
||||
if bop.op == ast.OpKind.Mult:
|
||||
self.ConstEvalOk = 1
|
||||
return lv * rv
|
||||
if bop.op == ast.OpKind.Div:
|
||||
# 整数常量除法:与 FloorDiv 一致(对齐 TPC ConstEvaluator L354-355)
|
||||
if rv == 0:
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
self.ConstEvalOk = 1
|
||||
return lv // rv
|
||||
if bop.op == ast.OpKind.FloorDiv:
|
||||
if rv == 0:
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
self.ConstEvalOk = 1
|
||||
return lv // rv
|
||||
if bop.op == ast.OpKind.BitOr:
|
||||
self.ConstEvalOk = 1
|
||||
return lv | rv
|
||||
if bop.op == ast.OpKind.BitAnd:
|
||||
self.ConstEvalOk = 1
|
||||
return lv & rv
|
||||
# 不支持的运算符
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
|
||||
# 不支持的节点类型
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
@@ -9,20 +11,9 @@ import stdio
|
||||
import stdlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprOps as HandlesExprOps
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
|
||||
|
||||
import lib.core.Gen.TypeGenBase as TypeGenBase
|
||||
@@ -123,8 +114,8 @@ class TypeGenErr(TypeGenBase.TypeGenBase):
|
||||
stdio.printf("Traceback (most recent call last):\n")
|
||||
# 输出调用栈帧(从底到顶)
|
||||
i: int
|
||||
for i in range(self.TraceCount):
|
||||
frame: HandlesType.TraceFrame | t.CPtr = HandlesType._get_trace_frame(i)
|
||||
for i in range(self.Gen.TypeGenBase.TraceCount):
|
||||
frame: GenTypes.TraceFrame | t.CPtr = self.Gen.TypeGenBase._get_trace_frame(i)
|
||||
if frame is not None and frame.file_name is not None:
|
||||
if frame.lineno > 0:
|
||||
stdio.printf(' File "%s", line %d\n', frame.file_name, frame.lineno)
|
||||
@@ -138,16 +129,16 @@ class TypeGenErr(TypeGenBase.TypeGenBase):
|
||||
lineno: int = 0
|
||||
if node is not None:
|
||||
lineno = node.lineno
|
||||
file_name: str = self.CurrentFile
|
||||
file_name: str = self.Gen.TypeGenResolve.get_current_file()
|
||||
if file_name is None:
|
||||
file_name = "<unknown>"
|
||||
# 行号兜底:克隆/构造节点 lineno 可能为 0(如泛型特化 _clone_arguments 的
|
||||
# ast.Arg 构造器硬编码 0,astaux.vp L139)。此时回退到 trace 栈最后一个
|
||||
# 有效帧(文件+行号)作为出错位置,避免输出误导性的 "line 0"。
|
||||
if lineno <= 0 and self.TraceCount > 0:
|
||||
ti_b: int = self.TraceCount - 1
|
||||
if lineno <= 0 and self.Gen.TypeGenBase.TraceCount > 0:
|
||||
ti_b: int = self.Gen.TypeGenBase.TraceCount - 1
|
||||
while ti_b >= 0:
|
||||
tfb: HandlesType.TraceFrame | t.CPtr = HandlesType._get_trace_frame(ti_b)
|
||||
tfb: GenTypes.TraceFrame | t.CPtr = self.Gen.TypeGenBase._get_trace_frame(ti_b)
|
||||
if tfb is not None and tfb.file_name is not None and tfb.lineno > 0:
|
||||
file_name = tfb.file_name
|
||||
lineno = tfb.lineno
|
||||
@@ -213,7 +204,7 @@ class TypeGenErr(TypeGenBase.TypeGenBase):
|
||||
ret_node_cr: ast.AST | t.CPtr = tp_cr.elts.get(1)
|
||||
if ret_node_cr is None:
|
||||
return None
|
||||
return HandlesType.resolve_annotation_type(pool, ret_node_cr, imported_modules, from_imports, trans)
|
||||
return self.Gen.TypeGenResolve.resolve_annotation_type(pool, ret_node_cr, imported_modules, from_imports, trans)
|
||||
def has_decorator_marker(self, node: ast.AST | t.CPtr,
|
||||
marker_name: str) -> int:
|
||||
"""检测类型注解中是否包含指定的装饰器标记"""
|
||||
@@ -366,7 +357,7 @@ class TypeGenErr(TypeGenBase.TypeGenBase):
|
||||
if arg.annotation.kind() == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg.annotation)
|
||||
if at.attr is not None:
|
||||
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.map_t_type(pool, at.attr)
|
||||
resolved: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.map_t_type(pool, at.attr)
|
||||
if resolved is not None:
|
||||
param_ty = resolved
|
||||
bits: int = self.get_llvm_type_bits(param_ty)
|
||||
|
||||
@@ -1,44 +1,40 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import sys
|
||||
import stdlib
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Gen.TypeGenBase as TypeGenBase
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TypeGenMixin - 类型映射与解析 Mixin(对象化 P2,wiki/14-oo-refactor.md)
|
||||
#
|
||||
# 500~1500 行/文件架构重构阶段 D:全部方法已拆至
|
||||
# TypeGenBase/CDef/CType/Resolve/Err,本文件保留类声明(Generator 继承链入口)。
|
||||
#
|
||||
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整,无 vtable 开销)。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 常量(与 HandlesType 保持一致)
|
||||
# ============================================================
|
||||
TRACE_MAX: t.CDefine = 32
|
||||
MAX_CTYPEDEF_DEPTH: t.CDefine = 10
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TypeGenMixin - 类型映射/注解解析/编译期常量表/错误上报
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class TypeGenMixin(TypeGenBase.TypeGenBase):
|
||||
"""类型映射与解析 Mixin(阶段 D 拆分后顶层,方法全部在子 Mixin)"""
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import sys
|
||||
import stdlib
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Gen.TypeGenBase as TypeGenBase
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TypeGenMixin - 类型映射与解析 Mixin(对象化 P2,wiki/14-oo-refactor.md)
|
||||
#
|
||||
# 500~1500 行/文件架构重构阶段 D:全部方法已拆至
|
||||
# TypeGenBase/CDef/CType/Resolve/Err,本文件保留类声明(Generator 继承链入口)。
|
||||
#
|
||||
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整,无 vtable 开销)。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 常量(与 HandlesType 保持一致)
|
||||
# ============================================================
|
||||
TRACE_MAX: t.CDefine = 32
|
||||
MAX_CTYPEDEF_DEPTH: t.CDefine = 10
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TypeGenMixin - 类型映射/注解解析/编译期常量表/错误上报
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class TypeGenMixin(TypeGenBase.TypeGenBase):
|
||||
"""类型映射与解析 Mixin(阶段 D 拆分后顶层,方法全部在子 Mixin)"""
|
||||
+1449
-1452
File diff suppressed because it is too large.
Load diff
+404
-403
@@ -1,403 +1,404 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
|
||||
|
||||
# ============================================================
|
||||
# VarGenMixin - 变量/作用域符号表 Mixin(P6 对象化,wiki/14-oo-refactor.md)
|
||||
#
|
||||
# 从 HandlesVar.vp 迁移:模块级函数(init_vars/find_var/find_var_entry/
|
||||
# lookup_var_entry/set_var_annot_class_name/set_var_ptr_element/add_var/
|
||||
# _alloca_at_entry/get_or_create_var/_create_scope/init_symbol_table/
|
||||
# enter_scope/exit_scope/define_var/define_module_var/lookup_var/
|
||||
# lookup_current/lookup_module_var/is_module_scope/get_or_create_sym)
|
||||
# → 本类方法。
|
||||
#
|
||||
# 迁移原则(与 P1-P5 一致,行为零变化):
|
||||
# 1. 方法保留原函数签名(含 symtab/vars_ptr 等指针首参——self 是宿主
|
||||
# Generator,这些函数操作数据结构指针,self 可能少用,但为风格
|
||||
# 统一仍方法化)
|
||||
# 2. 函数体原样搬入,本模块内部函数调用改为 self.xxx(...);
|
||||
# 跨模块调用保留模块前缀(本模块无跨模块调用)
|
||||
# 3. HandlesVar.vp 原函数保留为"一行委托":本地模块级单例 _g_gen
|
||||
# (BuildPipeline/main 注入)cast 成 Generator 类型后调本类方法
|
||||
# 4. VarEntry/Scope/SymbolTable 数据结构类保留在 HandlesVar.vp
|
||||
# (本类方法签名/函数体经 HandlesVar 前缀引用)
|
||||
#
|
||||
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整,无 vtable 开销)。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 常量(与 HandlesVar 保持一致)
|
||||
# ============================================================
|
||||
# 作用域类型常量
|
||||
SCOPE_MODULE: t.CDefine = 0
|
||||
SCOPE_FUNCTION: t.CDefine = 1
|
||||
SCOPE_BLOCK: t.CDefine = 2
|
||||
|
||||
# 每个作用域最大变量数
|
||||
# 256 太小:NewAstTest main() 有 289 个局部变量(几十个测试用例),
|
||||
# add_var 超限静默失败导致变量未注册,后续使用报"未定义名称"(NameError)。
|
||||
MAX_VARS: t.CDefine = 1024
|
||||
|
||||
|
||||
# ============================================================
|
||||
# VarGenMixin - 变量/作用域符号表 Mixin
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class VarGenMixin:
|
||||
"""变量/作用域 Mixin(P6 方法化)"""
|
||||
# 迁移自 HandlesVar 的模块级函数
|
||||
|
||||
# ============================================================
|
||||
# init_vars — 分配并清零 VarEntry 数组
|
||||
# ============================================================
|
||||
def init_vars(self, pool: memhub.MemBuddy | t.CPtr) -> HandlesVar.VarEntry | t.CPtr:
|
||||
"""分配并清零变量表数组"""
|
||||
size: t.CSizeT = MAX_VARS * HandlesVar.VarEntry.__sizeof__()
|
||||
vars_ptr: HandlesVar.VarEntry | t.CPtr = pool.alloc(size)
|
||||
if vars_ptr is not None:
|
||||
string.memset(vars_ptr, 0, size)
|
||||
return vars_ptr
|
||||
|
||||
# ============================================================
|
||||
# find_var — 在变量表中按名称查找
|
||||
# ============================================================
|
||||
def find_var(self, vars_ptr: HandlesVar.VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""在变量表中按名称查找"""
|
||||
if name is None or vars_ptr is None:
|
||||
return None
|
||||
entry_size: t.CSizeT = HandlesVar.VarEntry.__sizeof__()
|
||||
for i in range(var_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + i * entry_size
|
||||
entry: HandlesVar.VarEntry | t.CPtr = (HandlesVar.VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
if entry.Name is not None and entry.Used != 0:
|
||||
if string.strcmp(entry.Name, name) == 0:
|
||||
return entry.Alloca
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
# find_var_entry — 在变量表中按名称查找,返回 VarEntry(含 AnnotTy)
|
||||
# ============================================================
|
||||
def find_var_entry(self, vars_ptr: HandlesVar.VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str) -> HandlesVar.VarEntry | t.CPtr:
|
||||
"""在变量表中按名称查找,返回 VarEntry 或 None"""
|
||||
if name is None or vars_ptr is None:
|
||||
return None
|
||||
entry_size: t.CSizeT = HandlesVar.VarEntry.__sizeof__()
|
||||
for i in range(var_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + i * entry_size
|
||||
entry: HandlesVar.VarEntry | t.CPtr = (HandlesVar.VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
if entry.Name is not None and entry.Used != 0:
|
||||
if string.strcmp(entry.Name, name) == 0:
|
||||
return entry
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
# lookup_var_entry — 从当前作用域逐级向上查找变量,返回 VarEntry
|
||||
# ============================================================
|
||||
def lookup_var_entry(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
name: str) -> HandlesVar.VarEntry | t.CPtr:
|
||||
"""从当前作用域逐级向上查找变量,返回 VarEntry 或 None"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: HandlesVar.Scope | t.CPtr = symtab.Current
|
||||
while scope is not None:
|
||||
result: HandlesVar.VarEntry | t.CPtr = self.find_var_entry(scope.Vars, scope.VarCount, name)
|
||||
if result is not None:
|
||||
return result
|
||||
scope = scope.Parent
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
# set_var_annot_class_name — 设置变量的原始类型注解类名
|
||||
#
|
||||
# 在函数参数定义后调用,存储原始类型注解的类名。
|
||||
# 方法调用检测时,当 alloca 类型是 Ptr(i8)(联合类型简化),
|
||||
# 通过 AnnotClassName 查找实际结构体类型。
|
||||
# ============================================================
|
||||
def set_var_annot_class_name(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
name: str,
|
||||
class_name: str) -> int:
|
||||
"""设置变量的原始类型注解类名,返回 0=成功 / 1=失败"""
|
||||
if symtab is None or name is None:
|
||||
return 1
|
||||
entry: HandlesVar.VarEntry | t.CPtr = self.lookup_var_entry(symtab, name)
|
||||
if entry is None:
|
||||
return 1
|
||||
entry.AnnotClassName = class_name
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# set_var_ptr_element — 标记变量为"指针到 str/bytes"类型
|
||||
#
|
||||
# 注解为 bytes|t.CPtr 或 str|t.CPtr 的变量,其 alloca 类型是 i8*,
|
||||
# 但下标访问应按 8 字节步长(i8** 语义),而非 1 字节步长(i8* 语义)。
|
||||
# 此标志在 HandlesAnnAssign 中根据注解形式设置。
|
||||
# ============================================================
|
||||
def set_var_ptr_element(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
name: str) -> int:
|
||||
"""标记变量为 ptr_element 类型,返回 0=成功 / 1=失败"""
|
||||
if symtab is None or name is None:
|
||||
return 1
|
||||
entry: HandlesVar.VarEntry | t.CPtr = self.lookup_var_entry(symtab, name)
|
||||
if entry is None:
|
||||
return 1
|
||||
entry.IsPtrElement = 1
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# add_var — 添加变量到变量表
|
||||
# ============================================================
|
||||
def add_var(self, vars_ptr: HandlesVar.VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str,
|
||||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""添加变量到变量表"""
|
||||
if name is None or alloca is None or vars_ptr is None:
|
||||
return 1
|
||||
if var_count >= MAX_VARS:
|
||||
return 1
|
||||
entry_size: t.CSizeT = HandlesVar.VarEntry.__sizeof__()
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + var_count * entry_size
|
||||
entry: HandlesVar.VarEntry | t.CPtr = (HandlesVar.VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
entry.Name = name
|
||||
entry.Alloca = alloca
|
||||
entry.Used = 1
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# _alloca_at_entry - 在函数入口块生成 alloca(确保支配性)
|
||||
#
|
||||
# LLVM IR 要求指令支配所有使用点。如果 alloca 在条件分支内生成,
|
||||
# 但在其他分支使用,会违反支配性(Instruction does not dominate all uses)。
|
||||
# 标准做法:所有 alloca 在函数入口块生成。
|
||||
#
|
||||
# 临时切换 builder.CurBlock 到入口块,生成 alloca,然后恢复。
|
||||
# ============================================================
|
||||
def _alloca_at_entry(self, builder: llvmlite.IRBuilder | t.CPtr,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""在函数入口块生成 alloca,返回 alloca 值
|
||||
|
||||
使用 llvmlite.build_alloca_at_entry 在入口块终止指令之前插入 alloca,
|
||||
确保所有 alloca 在入口块,避免支配性违规。
|
||||
"""
|
||||
if builder is None or ty is None:
|
||||
return None
|
||||
return llvmlite.build_alloca_at_entry(builder, ty)
|
||||
|
||||
# ============================================================
|
||||
# get_or_create_var — 查找或创建变量 alloca(旧版兼容)
|
||||
# ============================================================
|
||||
def get_or_create_var(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
vars_ptr: HandlesVar.VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""查找或创建变量 alloca"""
|
||||
existing: llvmlite.Value | t.CPtr = self.find_var(vars_ptr, var_count, name)
|
||||
if existing is not None:
|
||||
return existing
|
||||
alloca: llvmlite.Value | t.CPtr = self._alloca_at_entry(builder, ty)
|
||||
if alloca is None:
|
||||
return None
|
||||
if self.add_var(vars_ptr, var_count, name, alloca) != 0:
|
||||
return None
|
||||
return alloca
|
||||
|
||||
# ============================================================
|
||||
# _create_scope — 创建新作用域节点(内部辅助函数)
|
||||
# ============================================================
|
||||
def _create_scope(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
parent: HandlesVar.Scope | t.CPtr,
|
||||
kind: int) -> HandlesVar.Scope | t.CPtr:
|
||||
"""创建并初始化作用域节点"""
|
||||
scope: HandlesVar.Scope | t.CPtr = pool.alloc(HandlesVar.Scope.__sizeof__())
|
||||
if scope is None:
|
||||
return None
|
||||
string.memset(scope, 0, HandlesVar.Scope.__sizeof__())
|
||||
scope.Parent = parent
|
||||
scope.Vars = self.init_vars(pool)
|
||||
scope.VarCount = 0
|
||||
scope.Kind = kind
|
||||
if scope.Vars is None:
|
||||
return None
|
||||
return scope
|
||||
|
||||
# ============================================================
|
||||
# init_symbol_table — 创建符号表(含模块级根作用域)
|
||||
# ============================================================
|
||||
def init_symbol_table(self, pool: memhub.MemBuddy | t.CPtr) -> HandlesVar.SymbolTable | t.CPtr:
|
||||
"""创建并初始化符号表,包含模块级根作用域"""
|
||||
if pool is None:
|
||||
return None
|
||||
symtab: HandlesVar.SymbolTable | t.CPtr = pool.alloc(HandlesVar.SymbolTable.__sizeof__())
|
||||
if symtab is None:
|
||||
return None
|
||||
string.memset(symtab, 0, HandlesVar.SymbolTable.__sizeof__())
|
||||
symtab.Pool = pool
|
||||
|
||||
# 创建根作用域(模块级)
|
||||
root: HandlesVar.Scope | t.CPtr = self._create_scope(pool, None, SCOPE_MODULE)
|
||||
if root is None:
|
||||
return None
|
||||
|
||||
symtab.Root = root
|
||||
symtab.Current = root
|
||||
return symtab
|
||||
|
||||
# ============================================================
|
||||
# enter_scope — 进入新作用域
|
||||
# ============================================================
|
||||
def enter_scope(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
kind: int) -> HandlesVar.Scope | t.CPtr:
|
||||
"""进入新作用域,返回新创建的作用域"""
|
||||
if symtab is None:
|
||||
return None
|
||||
pool: memhub.MemBuddy | t.CPtr = symtab.Pool
|
||||
scope: HandlesVar.Scope | t.CPtr = self._create_scope(pool, symtab.Current, kind)
|
||||
if scope is None:
|
||||
return None
|
||||
symtab.Current = scope
|
||||
return scope
|
||||
|
||||
# ============================================================
|
||||
# exit_scope — 退出当前作用域
|
||||
# ============================================================
|
||||
def exit_scope(self, symtab: HandlesVar.SymbolTable | t.CPtr):
|
||||
"""退出当前作用域,恢复到父作用域"""
|
||||
if symtab is not None and symtab.Current is not None:
|
||||
symtab.Current = symtab.Current.Parent
|
||||
|
||||
# ============================================================
|
||||
# define_var — 在当前作用域定义变量
|
||||
# ============================================================
|
||||
def define_var(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
name: str,
|
||||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""在当前作用域定义变量,返回 0 成功"""
|
||||
if symtab is None or name is None or alloca is None:
|
||||
return 1
|
||||
scope: HandlesVar.Scope | t.CPtr = symtab.Current
|
||||
if scope is None:
|
||||
return 1
|
||||
ret: int = self.add_var(scope.Vars, scope.VarCount, name, alloca)
|
||||
if ret == 0:
|
||||
scope.VarCount = scope.VarCount + 1
|
||||
return ret
|
||||
|
||||
# ============================================================
|
||||
# define_module_var — 在模块作用域定义变量
|
||||
# ============================================================
|
||||
def define_module_var(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
name: str,
|
||||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""在模块作用域定义变量,返回 0 成功"""
|
||||
if symtab is None or name is None or alloca is None:
|
||||
return 1
|
||||
scope: HandlesVar.Scope | t.CPtr = symtab.Root
|
||||
if scope is None:
|
||||
return 1
|
||||
ret: int = self.add_var(scope.Vars, scope.VarCount, name, alloca)
|
||||
if ret == 0:
|
||||
scope.VarCount = scope.VarCount + 1
|
||||
return ret
|
||||
|
||||
# ============================================================
|
||||
# lookup_var — 从当前作用域逐级向上查找变量
|
||||
# ============================================================
|
||||
def lookup_var(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""从当前作用域逐级向上查找变量,返回 alloca 或 None"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: HandlesVar.Scope | t.CPtr = symtab.Current
|
||||
while scope is not None:
|
||||
result: llvmlite.Value | t.CPtr = self.find_var(
|
||||
scope.Vars, scope.VarCount, name)
|
||||
if result is not None:
|
||||
return result
|
||||
scope = scope.Parent
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
# lookup_current — 仅在当前作用域查找变量
|
||||
# ============================================================
|
||||
def lookup_current(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""仅在当前作用域查找变量"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: HandlesVar.Scope | t.CPtr = symtab.Current
|
||||
if scope is None:
|
||||
return None
|
||||
return self.find_var(scope.Vars, scope.VarCount, name)
|
||||
|
||||
# ============================================================
|
||||
# lookup_module_var — 在模块作用域查找变量
|
||||
# ============================================================
|
||||
def lookup_module_var(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""在模块作用域查找变量"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: HandlesVar.Scope | t.CPtr = symtab.Root
|
||||
if scope is None:
|
||||
return None
|
||||
return self.find_var(scope.Vars, scope.VarCount, name)
|
||||
|
||||
# ============================================================
|
||||
# is_module_scope - 判断当前是否在模块级作用域
|
||||
#
|
||||
# 用于区分模块级代码和函数内代码:
|
||||
# - 模块级代码:AnnAssign 应修改模块级变量(Python 语义)
|
||||
# - 函数内代码:无 global 声明时 AnnAssign 应创建局部变量(Python 语义)
|
||||
# ============================================================
|
||||
def is_module_scope(self, symtab: HandlesVar.SymbolTable | t.CPtr) -> int:
|
||||
"""判断当前作用域是否为模块级作用域(Current == Root)
|
||||
|
||||
Returns: 1=模块级作用域, 0=函数内作用域
|
||||
"""
|
||||
if symtab is None:
|
||||
return 0
|
||||
if symtab.Root is None or symtab.Current is None:
|
||||
return 0
|
||||
# 比较指针:Current 与 Root 相同则为模块级
|
||||
if t.CUInt64T(symtab.Current) == t.CUInt64T(symtab.Root):
|
||||
return 1
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# get_or_create_sym — 查找或创建变量(在当前作用域)
|
||||
# ============================================================
|
||||
def get_or_create_sym(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
name: str,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""查找或创建变量 alloca(在当前作用域)"""
|
||||
existing: llvmlite.Value | t.CPtr = self.lookup_current(symtab, name)
|
||||
if existing is not None:
|
||||
return existing
|
||||
alloca: llvmlite.Value | t.CPtr = self._alloca_at_entry(builder, ty)
|
||||
if alloca is None:
|
||||
return None
|
||||
if self.define_var(symtab, name, alloca) != 0:
|
||||
# fail-fast: 变量注册失败(如超过 MAX_VARS)必须立即终止。
|
||||
# 此前静默忽略返回值:alloca 已创建但未入符号表,后续读取该变量
|
||||
# 报"未定义名称"(NewAstTest main() 289 个局部变量 > MAX_VARS=256
|
||||
# 的 NameError 根因),误导排查。变量表超限暴露上游规模问题。
|
||||
HandlesType.fatal_error(
|
||||
None,
|
||||
f"变量 '{name}' 注册失败(作用域变量数超过上限 MAX_VARS)",
|
||||
"InternalCompilerError")
|
||||
return alloca
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import t, c
|
||||
from stdint import *
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
|
||||
|
||||
# ============================================================
|
||||
# VarGenMixin - 变量/作用域符号表 Mixin(P6 对象化,wiki/14-oo-refactor.md)
|
||||
#
|
||||
# 从 HandlesVar.vp 迁移:模块级函数(init_vars/find_var/find_var_entry/
|
||||
# lookup_var_entry/set_var_annot_class_name/set_var_ptr_element/add_var/
|
||||
# _alloca_at_entry/get_or_create_var/_create_scope/init_symbol_table/
|
||||
# enter_scope/exit_scope/define_var/define_module_var/lookup_var/
|
||||
# lookup_current/lookup_module_var/is_module_scope/get_or_create_sym)
|
||||
# → 本类方法。
|
||||
#
|
||||
# 迁移原则(与 P1-P5 一致,行为零变化):
|
||||
# 1. 方法保留原函数签名(含 symtab/vars_ptr 等指针首参——self 是宿主
|
||||
# Generator,这些函数操作数据结构指针,self 可能少用,但为风格
|
||||
# 统一仍方法化)
|
||||
# 2. 函数体原样搬入,本模块内部函数调用改为 self.xxx(...);
|
||||
# 跨模块调用保留模块前缀(本模块无跨模块调用)
|
||||
# 3. HandlesVar.vp 原函数保留为"一行委托":本地模块级单例 _g_gen
|
||||
# (BuildPipeline/main 注入)cast 成 Generator 类型后调本类方法
|
||||
# 4. VarEntry/Scope/SymbolTable 数据结构类保留在 HandlesVar.vp
|
||||
# (本类方法签名/函数体经 HandlesVar 前缀引用)
|
||||
#
|
||||
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整,无 vtable 开销)。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 常量(与 HandlesVar 保持一致)
|
||||
# ============================================================
|
||||
# 作用域类型常量
|
||||
SCOPE_MODULE: t.CDefine = 0
|
||||
SCOPE_FUNCTION: t.CDefine = 1
|
||||
SCOPE_BLOCK: t.CDefine = 2
|
||||
|
||||
# 每个作用域最大变量数
|
||||
# 256 太小:NewAstTest main() 有 289 个局部变量(几十个测试用例),
|
||||
# add_var 超限静默失败导致变量未注册,后续使用报"未定义名称"(NameError)。
|
||||
MAX_VARS: t.CDefine = 1024
|
||||
|
||||
|
||||
# ============================================================
|
||||
# VarGenMixin - 变量/作用域符号表 Mixin
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class VarGenMixin:
|
||||
"""变量/作用域 Mixin(P6 方法化)"""
|
||||
# 迁移自 HandlesVar 的模块级函数
|
||||
|
||||
# ============================================================
|
||||
# init_vars — 分配并清零 VarEntry 数组
|
||||
# ============================================================
|
||||
Gen: Generator.Generator | t.CPtr
|
||||
def init_vars(self, pool: memhub.MemBuddy | t.CPtr) -> GenTypes.VarEntry | t.CPtr:
|
||||
"""分配并清零变量表数组"""
|
||||
size: t.CSizeT = MAX_VARS * GenTypes.VarEntry.__sizeof__()
|
||||
vars_ptr: GenTypes.VarEntry | t.CPtr = pool.alloc(size)
|
||||
if vars_ptr is not None:
|
||||
string.memset(vars_ptr, 0, size)
|
||||
return vars_ptr
|
||||
|
||||
# ============================================================
|
||||
# find_var — 在变量表中按名称查找
|
||||
# ============================================================
|
||||
def find_var(self, vars_ptr: GenTypes.VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""在变量表中按名称查找"""
|
||||
if name is None or vars_ptr is None:
|
||||
return None
|
||||
entry_size: t.CSizeT = GenTypes.VarEntry.__sizeof__()
|
||||
for i in range(var_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + i * entry_size
|
||||
entry: GenTypes.VarEntry | t.CPtr = (GenTypes.VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
if entry.Name is not None and entry.Used != 0:
|
||||
if string.strcmp(entry.Name, name) == 0:
|
||||
return entry.Alloca
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
# find_var_entry — 在变量表中按名称查找,返回 VarEntry(含 AnnotTy)
|
||||
# ============================================================
|
||||
def find_var_entry(self, vars_ptr: GenTypes.VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str) -> GenTypes.VarEntry | t.CPtr:
|
||||
"""在变量表中按名称查找,返回 VarEntry 或 None"""
|
||||
if name is None or vars_ptr is None:
|
||||
return None
|
||||
entry_size: t.CSizeT = GenTypes.VarEntry.__sizeof__()
|
||||
for i in range(var_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + i * entry_size
|
||||
entry: GenTypes.VarEntry | t.CPtr = (GenTypes.VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
if entry.Name is not None and entry.Used != 0:
|
||||
if string.strcmp(entry.Name, name) == 0:
|
||||
return entry
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
# lookup_var_entry — 从当前作用域逐级向上查找变量,返回 VarEntry
|
||||
# ============================================================
|
||||
def lookup_var_entry(self, symtab: GenTypes.SymbolTable | t.CPtr,
|
||||
name: str) -> GenTypes.VarEntry | t.CPtr:
|
||||
"""从当前作用域逐级向上查找变量,返回 VarEntry 或 None"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: GenTypes.Scope | t.CPtr = symtab.Current
|
||||
while scope is not None:
|
||||
result: GenTypes.VarEntry | t.CPtr = self.find_var_entry(scope.Vars, scope.VarCount, name)
|
||||
if result is not None:
|
||||
return result
|
||||
scope = scope.Parent
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
# set_var_annot_class_name — 设置变量的原始类型注解类名
|
||||
#
|
||||
# 在函数参数定义后调用,存储原始类型注解的类名。
|
||||
# 方法调用检测时,当 alloca 类型是 Ptr(i8)(联合类型简化),
|
||||
# 通过 AnnotClassName 查找实际结构体类型。
|
||||
# ============================================================
|
||||
def set_var_annot_class_name(self, symtab: GenTypes.SymbolTable | t.CPtr,
|
||||
name: str,
|
||||
class_name: str) -> int:
|
||||
"""设置变量的原始类型注解类名,返回 0=成功 / 1=失败"""
|
||||
if symtab is None or name is None:
|
||||
return 1
|
||||
entry: GenTypes.VarEntry | t.CPtr = self.lookup_var_entry(symtab, name)
|
||||
if entry is None:
|
||||
return 1
|
||||
entry.AnnotClassName = class_name
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# set_var_ptr_element — 标记变量为"指针到 str/bytes"类型
|
||||
#
|
||||
# 注解为 bytes|t.CPtr 或 str|t.CPtr 的变量,其 alloca 类型是 i8*,
|
||||
# 但下标访问应按 8 字节步长(i8** 语义),而非 1 字节步长(i8* 语义)。
|
||||
# 此标志在 HandlesAnnAssign 中根据注解形式设置。
|
||||
# ============================================================
|
||||
def set_var_ptr_element(self, symtab: GenTypes.SymbolTable | t.CPtr,
|
||||
name: str) -> int:
|
||||
"""标记变量为 ptr_element 类型,返回 0=成功 / 1=失败"""
|
||||
if symtab is None or name is None:
|
||||
return 1
|
||||
entry: GenTypes.VarEntry | t.CPtr = self.lookup_var_entry(symtab, name)
|
||||
if entry is None:
|
||||
return 1
|
||||
entry.IsPtrElement = 1
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# add_var — 添加变量到变量表
|
||||
# ============================================================
|
||||
def add_var(self, vars_ptr: GenTypes.VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str,
|
||||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""添加变量到变量表"""
|
||||
if name is None or alloca is None or vars_ptr is None:
|
||||
return 1
|
||||
if var_count >= MAX_VARS:
|
||||
return 1
|
||||
entry_size: t.CSizeT = GenTypes.VarEntry.__sizeof__()
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + var_count * entry_size
|
||||
entry: GenTypes.VarEntry | t.CPtr = (GenTypes.VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
entry.Name = name
|
||||
entry.Alloca = alloca
|
||||
entry.Used = 1
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# _alloca_at_entry - 在函数入口块生成 alloca(确保支配性)
|
||||
#
|
||||
# LLVM IR 要求指令支配所有使用点。如果 alloca 在条件分支内生成,
|
||||
# 但在其他分支使用,会违反支配性(Instruction does not dominate all uses)。
|
||||
# 标准做法:所有 alloca 在函数入口块生成。
|
||||
#
|
||||
# 临时切换 builder.CurBlock 到入口块,生成 alloca,然后恢复。
|
||||
# ============================================================
|
||||
def _alloca_at_entry(self, builder: llvmlite.IRBuilder | t.CPtr,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""在函数入口块生成 alloca,返回 alloca 值
|
||||
|
||||
使用 llvmlite.build_alloca_at_entry 在入口块终止指令之前插入 alloca,
|
||||
确保所有 alloca 在入口块,避免支配性违规。
|
||||
"""
|
||||
if builder is None or ty is None:
|
||||
return None
|
||||
return llvmlite.build_alloca_at_entry(builder, ty)
|
||||
|
||||
# ============================================================
|
||||
# get_or_create_var — 查找或创建变量 alloca(旧版兼容)
|
||||
# ============================================================
|
||||
def get_or_create_var(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
vars_ptr: GenTypes.VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""查找或创建变量 alloca"""
|
||||
existing: llvmlite.Value | t.CPtr = self.find_var(vars_ptr, var_count, name)
|
||||
if existing is not None:
|
||||
return existing
|
||||
alloca: llvmlite.Value | t.CPtr = self._alloca_at_entry(builder, ty)
|
||||
if alloca is None:
|
||||
return None
|
||||
if self.add_var(vars_ptr, var_count, name, alloca) != 0:
|
||||
return None
|
||||
return alloca
|
||||
|
||||
# ============================================================
|
||||
# _create_scope — 创建新作用域节点(内部辅助函数)
|
||||
# ============================================================
|
||||
def _create_scope(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
parent: GenTypes.Scope | t.CPtr,
|
||||
kind: int) -> GenTypes.Scope | t.CPtr:
|
||||
"""创建并初始化作用域节点"""
|
||||
scope: GenTypes.Scope | t.CPtr = pool.alloc(GenTypes.Scope.__sizeof__())
|
||||
if scope is None:
|
||||
return None
|
||||
string.memset(scope, 0, GenTypes.Scope.__sizeof__())
|
||||
scope.Parent = parent
|
||||
scope.Vars = self.init_vars(pool)
|
||||
scope.VarCount = 0
|
||||
scope.Kind = kind
|
||||
if scope.Vars is None:
|
||||
return None
|
||||
return scope
|
||||
|
||||
# ============================================================
|
||||
# init_symbol_table — 创建符号表(含模块级根作用域)
|
||||
# ============================================================
|
||||
def init_symbol_table(self, pool: memhub.MemBuddy | t.CPtr) -> GenTypes.SymbolTable | t.CPtr:
|
||||
"""创建并初始化符号表,包含模块级根作用域"""
|
||||
if pool is None:
|
||||
return None
|
||||
symtab: GenTypes.SymbolTable | t.CPtr = pool.alloc(GenTypes.SymbolTable.__sizeof__())
|
||||
if symtab is None:
|
||||
return None
|
||||
string.memset(symtab, 0, GenTypes.SymbolTable.__sizeof__())
|
||||
symtab.Pool = pool
|
||||
|
||||
# 创建根作用域(模块级)
|
||||
root: GenTypes.Scope | t.CPtr = self._create_scope(pool, None, SCOPE_MODULE)
|
||||
if root is None:
|
||||
return None
|
||||
|
||||
symtab.Root = root
|
||||
symtab.Current = root
|
||||
return symtab
|
||||
|
||||
# ============================================================
|
||||
# enter_scope — 进入新作用域
|
||||
# ============================================================
|
||||
def enter_scope(self, symtab: GenTypes.SymbolTable | t.CPtr,
|
||||
kind: int) -> GenTypes.Scope | t.CPtr:
|
||||
"""进入新作用域,返回新创建的作用域"""
|
||||
if symtab is None:
|
||||
return None
|
||||
pool: memhub.MemBuddy | t.CPtr = symtab.Pool
|
||||
scope: GenTypes.Scope | t.CPtr = self._create_scope(pool, symtab.Current, kind)
|
||||
if scope is None:
|
||||
return None
|
||||
symtab.Current = scope
|
||||
return scope
|
||||
|
||||
# ============================================================
|
||||
# exit_scope — 退出当前作用域
|
||||
# ============================================================
|
||||
def exit_scope(self, symtab: GenTypes.SymbolTable | t.CPtr):
|
||||
"""退出当前作用域,恢复到父作用域"""
|
||||
if symtab is not None and symtab.Current is not None:
|
||||
symtab.Current = symtab.Current.Parent
|
||||
|
||||
# ============================================================
|
||||
# define_var — 在当前作用域定义变量
|
||||
# ============================================================
|
||||
def define_var(self, symtab: GenTypes.SymbolTable | t.CPtr,
|
||||
name: str,
|
||||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""在当前作用域定义变量,返回 0 成功"""
|
||||
if symtab is None or name is None or alloca is None:
|
||||
return 1
|
||||
scope: GenTypes.Scope | t.CPtr = symtab.Current
|
||||
if scope is None:
|
||||
return 1
|
||||
ret: int = self.add_var(scope.Vars, scope.VarCount, name, alloca)
|
||||
if ret == 0:
|
||||
scope.VarCount = scope.VarCount + 1
|
||||
return ret
|
||||
|
||||
# ============================================================
|
||||
# define_module_var — 在模块作用域定义变量
|
||||
# ============================================================
|
||||
def define_module_var(self, symtab: GenTypes.SymbolTable | t.CPtr,
|
||||
name: str,
|
||||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""在模块作用域定义变量,返回 0 成功"""
|
||||
if symtab is None or name is None or alloca is None:
|
||||
return 1
|
||||
scope: GenTypes.Scope | t.CPtr = symtab.Root
|
||||
if scope is None:
|
||||
return 1
|
||||
ret: int = self.add_var(scope.Vars, scope.VarCount, name, alloca)
|
||||
if ret == 0:
|
||||
scope.VarCount = scope.VarCount + 1
|
||||
return ret
|
||||
|
||||
# ============================================================
|
||||
# lookup_var — 从当前作用域逐级向上查找变量
|
||||
# ============================================================
|
||||
def lookup_var(self, symtab: GenTypes.SymbolTable | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""从当前作用域逐级向上查找变量,返回 alloca 或 None"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: GenTypes.Scope | t.CPtr = symtab.Current
|
||||
while scope is not None:
|
||||
result: llvmlite.Value | t.CPtr = self.find_var(
|
||||
scope.Vars, scope.VarCount, name)
|
||||
if result is not None:
|
||||
return result
|
||||
scope = scope.Parent
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
# lookup_current — 仅在当前作用域查找变量
|
||||
# ============================================================
|
||||
def lookup_current(self, symtab: GenTypes.SymbolTable | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""仅在当前作用域查找变量"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: GenTypes.Scope | t.CPtr = symtab.Current
|
||||
if scope is None:
|
||||
return None
|
||||
return self.find_var(scope.Vars, scope.VarCount, name)
|
||||
|
||||
# ============================================================
|
||||
# lookup_module_var — 在模块作用域查找变量
|
||||
# ============================================================
|
||||
def lookup_module_var(self, symtab: GenTypes.SymbolTable | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""在模块作用域查找变量"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: GenTypes.Scope | t.CPtr = symtab.Root
|
||||
if scope is None:
|
||||
return None
|
||||
return self.find_var(scope.Vars, scope.VarCount, name)
|
||||
|
||||
# ============================================================
|
||||
# is_module_scope - 判断当前是否在模块级作用域
|
||||
#
|
||||
# 用于区分模块级代码和函数内代码:
|
||||
# - 模块级代码:AnnAssign 应修改模块级变量(Python 语义)
|
||||
# - 函数内代码:无 global 声明时 AnnAssign 应创建局部变量(Python 语义)
|
||||
# ============================================================
|
||||
def is_module_scope(self, symtab: GenTypes.SymbolTable | t.CPtr) -> int:
|
||||
"""判断当前作用域是否为模块级作用域(Current == Root)
|
||||
|
||||
Returns: 1=模块级作用域, 0=函数内作用域
|
||||
"""
|
||||
if symtab is None:
|
||||
return 0
|
||||
if symtab.Root is None or symtab.Current is None:
|
||||
return 0
|
||||
# 比较指针:Current 与 Root 相同则为模块级
|
||||
if t.CUInt64T(symtab.Current) == t.CUInt64T(symtab.Root):
|
||||
return 1
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# get_or_create_sym — 查找或创建变量(在当前作用域)
|
||||
# ============================================================
|
||||
def get_or_create_sym(self, symtab: GenTypes.SymbolTable | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
name: str,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""查找或创建变量 alloca(在当前作用域)"""
|
||||
existing: llvmlite.Value | t.CPtr = self.lookup_current(symtab, name)
|
||||
if existing is not None:
|
||||
return existing
|
||||
alloca: llvmlite.Value | t.CPtr = self._alloca_at_entry(builder, ty)
|
||||
if alloca is None:
|
||||
return None
|
||||
if self.define_var(symtab, name, alloca) != 0:
|
||||
# fail-fast: 变量注册失败(如超过 MAX_VARS)必须立即终止。
|
||||
# 此前静默忽略返回值:alloca 已创建但未入符号表,后续读取该变量
|
||||
# 报"未定义名称"(NewAstTest main() 289 个局部变量 > MAX_VARS=256
|
||||
# 的 NameError 根因),误导排查。变量表超限暴露上游规模问题。
|
||||
self.Gen.TypeGenErr.fatal_error(
|
||||
None,
|
||||
f"变量 '{name}' 注册失败(作用域变量数超过上限 MAX_VARS)",
|
||||
"InternalCompilerError")
|
||||
return alloca
|
||||
@@ -1,246 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import sys
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.StubMerger as StubMerger
|
||||
|
||||
|
||||
import lib.core.Handles.ExprCallDeref as ExprCallDeref
|
||||
import lib.core.Handles.ExprCallCtor as ExprCallCtor
|
||||
import lib.core.Handles.ExprCallCall as ExprCallCall
|
||||
import lib.core.Handles.ExprCallTable as ExprCallTable
|
||||
import lib.core.Handles.ExprCallHandle as ExprCallHandle
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
|
||||
# ============================================================
|
||||
# ExprCallBase - HandlesExprCall 拆分(阶段 E):ExprCallBase
|
||||
#
|
||||
# 直接移动模式:委托函数迁至此模块,原 HandlesExprCall.vp 仅
|
||||
# 保留 _g_gen/常量/类;调用方经本模块前缀访问。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# _lookup_module_sha1 — 按模块名查找 SHA1(委托到 gen._lookup_module_sha1)
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 模块 SHA1 查询(委托给 StubMerger 全局存储器)
|
||||
#
|
||||
# 翻译时用于跨模块函数调用名混淆:
|
||||
# string.strchr(...) → call @{sha1_of_string}.strchr(...)
|
||||
#
|
||||
# 数据来源是 StubMerger.PopulateSha1MapStore/AppendToSha1MapStore
|
||||
# 填充的全局存储器,不再维护独立的 SHA1 映射表副本。
|
||||
# ============================================================
|
||||
|
||||
def _lookup_module_sha1(mod_name: str) -> str:
|
||||
"""查找模块名对应的 SHA1,找不到返回 None(委托到 gen._lookup_module_sha1)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._lookup_module_sha1(mod_name)
|
||||
return None
|
||||
def _lookup_module_sha1_suffix(mod_suffix: str) -> str:
|
||||
"""后缀匹配查找模块 SHA1(委托到 gen._lookup_module_sha1_suffix)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._lookup_module_sha1_suffix(mod_suffix)
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
# 全局 CExport 函数表(module_sha1 + func_name)
|
||||
#
|
||||
# t.CExport 函数定义时不加 SHA1 前缀(如 @strlen),
|
||||
# 跨模块调用时需要查表确认目标函数是否是 CExport 函数。
|
||||
# 若是,使用裸名调用(@strlen);否则使用 @{sha1}.func。
|
||||
# 必须包含模块 SHA1 记录,避免同名跨模块函数冲突
|
||||
# (一个模块有 CExport 的 strlen→@strlen,另一个没有→@{sha1}.strlen)。
|
||||
#
|
||||
# 注:表数据已迁入 gen 字段(CallGenMixin.CexportSha1Arr/CexportFuncArr/
|
||||
# CexportCount),本模块不再持有(P4 簇 1+2)。
|
||||
# ============================================================
|
||||
_CEXPORT_MAX: t.CDefine = 256
|
||||
def register_cexport_func(sha1: str, func_name: str) -> int:
|
||||
"""注册 CExport 函数到全局表(委托到 gen.register_cexport_func)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.register_cexport_func(sha1, func_name)
|
||||
return 0
|
||||
def is_cexport_func(sha1: str, func_name: str) -> int:
|
||||
"""检查(sha1, func_name) 是否是 CExport 函数(委托到 gen.is_cexport_func)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_cexport_func(sha1, func_name)
|
||||
return 0
|
||||
# ============================================================
|
||||
# _lookup_mod_sha1 - 从 from_imports 查找类所属模块的 SHA1
|
||||
#
|
||||
# lookup_from_import 返回指向 from_imports 内部的指针,不是 null 终止
|
||||
# (如 "namespace_defs Gadget:namespace_defs ...")。此函数手动截断
|
||||
# 模块名,复制到新缓冲区,再查找 SHA1(精确+后缀匹配)。
|
||||
# ============================================================
|
||||
def _lookup_mod_sha1(pool: memhub.MemBuddy | t.CPtr,
|
||||
from_imports: str, class_name: str,
|
||||
allow_star_fallback: int = 1) -> str:
|
||||
"""从 from_imports 查找类所属模块的 SHA1(委托到 gen._lookup_mod_sha1)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._lookup_mod_sha1(pool, from_imports, class_name, allow_star_fallback)
|
||||
return None
|
||||
# ============================================================
|
||||
# _lookup_sha1_from_modname_raw - 原始模块名 → SHA1
|
||||
#
|
||||
# 截断模块名(lookup_from_import 返回内部指针,空格/冒号/null 分隔),
|
||||
# 去掉相对导入前导点,再精确+后缀查找 SHA1。
|
||||
# 供 _lookup_mod_sha1 与 HandlesExpr._lookup_cross_module_cdefine 复用。
|
||||
# ============================================================
|
||||
def _lookup_sha1_from_modname_raw(pool: memhub.MemBuddy | t.CPtr,
|
||||
mod_name_raw: str) -> str:
|
||||
"""从原始模块名查找 SHA1(委托到 gen._lookup_sha1_from_modname_raw)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._lookup_sha1_from_modname_raw(pool, mod_name_raw)
|
||||
return None
|
||||
# ============================================================
|
||||
# HandlesExprCall - 函数调用表达式处理(Mixin 继承模式)
|
||||
#
|
||||
# 工具函数和 HandlesExprCall.FuncEntry 保留为模块级,HandlesExprCall.ExprCallHandle 提供 trans 接口
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# 在模块函数链表中按名称查找函数
|
||||
# ============================================================
|
||||
def find_func_in_module(mod: llvmlite.LLVMModule | t.CPtr,
|
||||
name: str) -> llvmlite.Function | t.CPtr:
|
||||
"""在模块的函数链表中按名称查找函数(委托到 gen.find_func_in_module)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.find_func_in_module(mod, name)
|
||||
return None
|
||||
# ============================================================
|
||||
# _ensure_c_lib_declare - 为已知的 C 库函数创建 declare 声明
|
||||
#
|
||||
# 对应 TPC 的 _C_LIB_FUNCS 机制。当裸名调用 memset/memmove/memcmp/
|
||||
# strcmp/strlen 等已知 C 库函数时,自动在当前模块创建 declare,
|
||||
# 避免报 "裸名调用未定义且未导入" 错误。
|
||||
# memcpy 不在此处理(已有 _emit_llvm_memcpy_intrinsic 映射到 @llvm.memcpy)。
|
||||
#
|
||||
# Args:
|
||||
# pool: 内存池
|
||||
# mod: LLVM 模块
|
||||
# name: 函数名
|
||||
#
|
||||
# Returns:
|
||||
# Function 指针(已创建 declare),或 None 如果不是已知 C 库函数
|
||||
# ============================================================
|
||||
def _ensure_c_lib_declare(pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
name: str) -> llvmlite.Function | t.CPtr:
|
||||
"""为已知的 C 库函数创建 declare 声明(委托到 gen._ensure_c_lib_declare)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._ensure_c_lib_declare(pool, mod, name)
|
||||
return None
|
||||
# ============================================================
|
||||
# _infer_external_func_ret_ty - 根据函数名推断外部函数返回类型
|
||||
#
|
||||
# stubs 在翻译后才注入 IR,翻译时模块中无 stub 函数声明,
|
||||
# 因此对 includes 库函数(如 string.strchr 返回 i8*)需根据
|
||||
# 函数名推断返回类型,避免指针被截断为 i32。
|
||||
#
|
||||
# 覆盖 includes/string.py 所有导出函数:
|
||||
# i8*: strcpy, strncpy, strchr, strrchr, strstr, memset, memset32, memcpy, memmove
|
||||
# i64: strlen, atoll
|
||||
# double: atof
|
||||
# i8: samestr
|
||||
# i32(默认): strcmp, strncmp, memcmp, strspn, atoi, split
|
||||
# ============================================================
|
||||
def _infer_external_func_ret_ty(pool: memhub.MemBuddy | t.CPtr,
|
||||
func_name: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""根据函数名推断外部 includes 函数的返回类型(委托到 gen._infer_external_func_ret_ty)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._infer_external_func_ret_ty(pool, func_name)
|
||||
return None
|
||||
# ============================================================
|
||||
# _get_external_func_param_ty - 获取外部函数第 idx 个参数的期望类型
|
||||
#
|
||||
# stubs 翻译时未注入,需推断参数类型以提升字面量(如 i32→i64),
|
||||
# 避免 declare(i64) 与 call(i32) 类型不匹配。
|
||||
#
|
||||
# 注意:stubs 翻译时 ULONG(t.CUnsignedLong) 在 LLVM IR 中被翻译为 i64
|
||||
# (因为 LLVM 中 long 是 64 位),因此 Win32 API 中所有 ULONG/DWORD/SIZE_T
|
||||
# 参数在 declare 中都是 i64。call 时必须匹配,否则类型不匹配。
|
||||
#
|
||||
# 策略:对 Win32 API 函数的所有非指针参数(字面量)都提升为 i64,
|
||||
# 以匹配 declare 中 ULONG 被翻译为 i64 的情况。
|
||||
#
|
||||
# 指针参数(VOIDPTR/HANDLE)不在此处理,由调用点的 inttoptr 处理。
|
||||
# ============================================================
|
||||
def _get_external_func_param_ty(pool: memhub.MemBuddy | t.CPtr,
|
||||
func_name: str,
|
||||
param_idx: int) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""获取外部函数第 param_idx 个参数的期望类型(委托到 gen._get_external_func_param_ty)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._get_external_func_param_ty(pool, func_name, param_idx)
|
||||
return None
|
||||
# ============================================================
|
||||
# _emit_llvm_memcpy_intrinsic — 将 memcpy 调用映射到 @llvm.memcpy 内联函数
|
||||
#
|
||||
# 背景: string.memcpy 是 t.CExport 函数,跨模块调用生成 @memcpy 裸名调用。
|
||||
# 但在 monomorphization 场景下,目标模块的 deps.txt 可能不含 string,
|
||||
# 导致 @memcpy 声明缺失,链接器报 undefined value。
|
||||
#
|
||||
# 解决: 将 memcpy 调用映射到 LLVM 内联函数 @llvm.memcpy,
|
||||
# 该内联函数在当前模块内声明,无需跨模块依赖。
|
||||
#
|
||||
# @llvm.memcpy 签名: void(i8* dst, i8* src, i64 len, i1 isvolatile)
|
||||
# C memcpy 签名: i8* (i8* dst, i8* src, i64 len) — 返回 dst
|
||||
#
|
||||
# Args:
|
||||
# args_head: 参数链表头(dst, src, num),通过 Value.Next 链接
|
||||
# arg_count: 参数数量(应为 3)
|
||||
#
|
||||
# Returns:
|
||||
# dst 值(匹配 C memcpy 语义: 返回 dest 指针)
|
||||
# ============================================================
|
||||
def _emit_llvm_memcpy_intrinsic(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
dst_val: llvmlite.Value | t.CPtr,
|
||||
src_val: llvmlite.Value | t.CPtr,
|
||||
num_val: llvmlite.Value | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""将 memcpy 调用映射到 @llvm.memcpy 内联函数(委托到 gen._emit_llvm_memcpy_intrinsic)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._emit_llvm_memcpy_intrinsic(pool, builder, mod, dst_val, src_val, num_val)
|
||||
return None
|
||||
@@ -1,338 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import sys
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.StubMerger as StubMerger
|
||||
|
||||
|
||||
import lib.core.Handles.ExprCallBase as ExprCallBase
|
||||
import lib.core.Handles.ExprCallDeref as ExprCallDeref
|
||||
import lib.core.Handles.ExprCallCtor as ExprCallCtor
|
||||
import lib.core.Handles.ExprCallTable as ExprCallTable
|
||||
import lib.core.Handles.ExprCallHandle as ExprCallHandle
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
|
||||
# ============================================================
|
||||
# ExprCallCall - HandlesExprCall 拆分(阶段 E):ExprCallCall
|
||||
#
|
||||
# 直接移动模式:委托函数迁至此模块,原 HandlesExprCall.vp 仅
|
||||
# 保留 _g_gen/常量/类;调用方经本模块前缀访问。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# 翻译函数调用 Call(func, args) — 模块级版本
|
||||
# ============================================================
|
||||
def translate_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译函数调用,返回 call 结果 Value(委托到 gen.translate_call)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_call(pool, builder, mod, node, funcs_ptr, func_count, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# 翻译闭包调用 — 通过闭包指针间接调用
|
||||
#
|
||||
# 闭包结构: {i8* fn_ptr, i8* env_ptr} (16 字节)
|
||||
# 调用过程:
|
||||
# 1. load closure_ptr 从变量 alloca
|
||||
# 2. load fn_ptr 从 offset 0
|
||||
# 3. load env_ptr 从 offset 8
|
||||
# 4. bitcast fn_ptr to i32(i8*)*
|
||||
# 5. call i32 %fn_typed(i8* %env_ptr)
|
||||
# ============================================================
|
||||
def translate_closure_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
closure_alloca: llvmlite.Value | t.CPtr,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""通过闭包指针间接调用(委托到 gen.translate_closure_call)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_closure_call(pool, builder, mod, closure_alloca, cargs, can, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# _is_func_ptr_alloca - 判断变量 alloca 是否为函数指针变量
|
||||
#
|
||||
# 函数指针变量(t.Callable 注解 → i8*)的 alloca 类型是 Ptr(Ptr(i8)) = i8**;
|
||||
# 闭包变量 alloca 是 i8*(Ptr(i8))。通过类型层级区分。
|
||||
# ============================================================
|
||||
def _is_func_ptr_alloca(alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""判断 alloca 是否为函数指针变量(类型 Ptr(Ptr(i8))),1=是 / 0=否(委托到 gen._is_func_ptr_alloca)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._is_func_ptr_alloca(alloca)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 闭包变量名集合(stdlib 分配,懒初始化)
|
||||
#
|
||||
# 背景: 嵌套函数提升后闭包变量 alloca 类型是 i8**(alloca i8*),
|
||||
# 与函数指针变量(t.Callable → i8** alloca)类型完全相同,_is_func_ptr_alloca
|
||||
# 无法区分,导致 inner() 被误判为函数指针调用(直接 bitcast 闭包对象到函数指针、
|
||||
# 无 env 参数调用 → 运行时崩溃)。translate_nested_function_def 创建闭包时
|
||||
# 注册嵌套函数名,调用时优先按闭包调用处理。
|
||||
# ============================================================
|
||||
MAX_CLOSURE_NAMES: t.CDefine = 128
|
||||
def _ensure_closure_names() -> int:
|
||||
"""确保闭包名表已分配,0 失败(委托到 gen._ensure_closure_names)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._ensure_closure_names()
|
||||
return 0
|
||||
def register_closure_name(name: str) -> int:
|
||||
"""注册嵌套函数(闭包变量)名,0 成功(委托到 gen.register_closure_name)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.register_closure_name(name)
|
||||
return 0
|
||||
def is_closure_name(name: str) -> int:
|
||||
"""检查 name 是否已注册为闭包变量名,1=是 / 0=否(委托到 gen.is_closure_name)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_closure_name(name)
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# 函数指针变量签名表(变量名 → 返回类型)
|
||||
#
|
||||
# AnnAssign 处理 t.Callable 注解时注册,函数指针间接调用时
|
||||
# 按注册的返回类型构造签名(而非默认 i32)。
|
||||
# ============================================================
|
||||
MAX_FUNC_PTR_SIGS: t.CDefine = 64
|
||||
def _ensure_funcptr_sigs() -> int:
|
||||
"""确保函数指针签名表已分配(stdlib.malloc,懒初始化)(委托到 gen._ensure_funcptr_sigs)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._ensure_funcptr_sigs()
|
||||
return 0
|
||||
def register_func_ptr_sig(name: str,
|
||||
ret_ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""注册函数指针变量的返回类型签名,0 成功(委托到 gen.register_func_ptr_sig)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.register_func_ptr_sig(name, ret_ty)
|
||||
return 0
|
||||
def lookup_func_ptr_ret(name: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""查函数指针变量的返回类型,None=未注册(调用时默认 i32)(委托到 gen.lookup_func_ptr_ret)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.lookup_func_ptr_ret(name)
|
||||
return None
|
||||
# ============================================================
|
||||
# _translate_func_ptr_call - 函数指针变量间接调用
|
||||
#
|
||||
# func_p: t.Callable[[A, B], Ret] 后调用 func_p(a, b):
|
||||
# 1. load 函数地址(i8*)
|
||||
# 2. 翻译实参并链接为 Value 链表
|
||||
# 3. 按实参类型 + 注册的返回类型构造签名(未注册时默认 i32)
|
||||
# 4. bitcast i8* → 函数指针类型,间接调用
|
||||
# ============================================================
|
||||
def _translate_func_ptr_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
fp_alloca: llvmlite.Value | t.CPtr,
|
||||
func_name: str,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""函数指针变量间接调用,返回结果 Value(委托到 gen._translate_func_ptr_call)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._translate_func_ptr_call(pool, builder, mod, fp_alloca, func_name, cargs, can, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# 翻译 printf 调用 — 模块级版本
|
||||
# ============================================================
|
||||
def translate_printf_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None):
|
||||
"""翻译 printf 调用(特殊处理格式字符串)(委托到 gen.translate_printf_call)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.translate_printf_call(pool, builder, mod, cl, trans)
|
||||
# ============================================================
|
||||
# 翻译 print 调用 — 类型感知格式化 + 默认换行
|
||||
#
|
||||
# 与 printf 不同,print 不需要用户提供格式串:每个参数按 LLVM
|
||||
# 类型自动选择格式(%s/%d/%f/0x%llx),结尾追加 "\n"(对齐 Python
|
||||
# print 默认 end="\n",以及 TPC HandlesExprBuiltin._HandlePrintLlvm)。
|
||||
#
|
||||
# 类型分派规则:
|
||||
# i8*(str/bytes) → %s
|
||||
# 其他指针(struct*/int*) → 0x%llx(ptrtoint 到 i64)
|
||||
# i1(bool) → %d(zext 到 i32)
|
||||
# i8/i16/i32 → %d(sext 到 i32,C ABI 整数提升)
|
||||
# i64 → %lld
|
||||
# float/double → %f(float fpext 到 double,C ABI 提升)
|
||||
# 无法识别的类型 → "(unknown)"(不传参)
|
||||
# ============================================================
|
||||
def translate_print_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None):
|
||||
"""翻译 print 调用(类型感知格式化 + 默认换行)(委托到 gen.translate_print_call)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.translate_print_call(pool, builder, mod, cl, trans)
|
||||
# ============================================================
|
||||
# stdarg 糖函数实现: va_arg / arg / va_start / va_end
|
||||
#
|
||||
# 这些函数对应 stdarg.vp 中的 pass 体声明,由编译器在翻译期
|
||||
# 转换为 LLVM 指令或 intrinsic 调用,不生成函数 call。
|
||||
#
|
||||
# va_list 在 TPV 中表示为 i8*(与 stdarg.vp 中 va_list = t.CUnsignedChar | t.CPtr 一致)。
|
||||
# va_list 对象存储在 alloca 中(i8**),va_arg/va_start/va_end 需要传入 alloca 指针。
|
||||
# ============================================================
|
||||
|
||||
def _va_arg_get_alloca_ptr(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
arg_node: ast.AST | t.CPtr,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""获取 va_list 变量的 alloca 指针(不 load)(委托到 gen._va_arg_get_alloca_ptr)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._va_arg_get_alloca_ptr(pool, builder, mod, arg_node, funcs_ptr, func_count, trans)
|
||||
return None
|
||||
def _resolve_va_arg_type(pool: memhub.MemBuddy | t.CPtr,
|
||||
type_node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""解析 va_arg/arg 的类型参数为 LLVMType(委托到 gen._resolve_va_arg_type)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._resolve_va_arg_type(pool, type_node, trans)
|
||||
return None
|
||||
def _translate_va_arg_sugar(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""va_arg(ap, type) / va_arg(ap) → %N = va_arg <ap_ty> <ap>, <type>(委托到 gen._translate_va_arg_sugar)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._translate_va_arg_sugar(pool, builder, mod, cl, cargs, can, funcs_ptr, func_count, trans)
|
||||
return None
|
||||
def _translate_arg_sugar(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""arg(type) → %N = va_arg <va_list_ty> <trans._va_list_ptr>, <type>(委托到 gen._translate_arg_sugar)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._translate_arg_sugar(pool, builder, mod, cl, cargs, can, funcs_ptr, func_count, trans)
|
||||
return None
|
||||
def _translate_va_start_sugar(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""va_start(ap, last_arg) → call void @llvm.va_start(i8* %ap)(委托到 gen._translate_va_start_sugar)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._translate_va_start_sugar(pool, builder, mod, cargs, can, funcs_ptr, func_count, trans)
|
||||
return None
|
||||
def _translate_va_end_sugar(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""va_end(ap) → call void @llvm.va_end(i8* %ap)(委托到 gen._translate_va_end_sugar)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._translate_va_end_sugar(pool, builder, mod, cargs, can, funcs_ptr, func_count, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# 变长函数调用支持: 检查 IsVarArg + C ABI 参数提升
|
||||
#
|
||||
# C ABI 要求变长参数(...部分)进行默认提升:
|
||||
# 整数提升: i8/i16 → i32(sext/zext)
|
||||
# 浮点提升: float → double(fpext)
|
||||
# 固定参数不需要提升(有明确类型签名)。
|
||||
# ============================================================
|
||||
|
||||
def _get_func_fixed_param_count(func: llvmlite.Function | t.CPtr) -> int:
|
||||
"""获取函数的固定参数数量(遍历 Params 链表)(委托到 gen._get_func_fixed_param_count)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._get_func_fixed_param_count(func)
|
||||
return 0
|
||||
def _check_and_promote_variadic_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
call_name: str,
|
||||
head: llvmlite.Value | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
arg_nodes: list[ast.AST | t.CPtr] | t.CPtr = None,
|
||||
self_offset: int = 0,
|
||||
trans: HT.Translator | t.CPtr = None) -> int:
|
||||
"""检查被调用函数是否为变长函数,若是则对变长参数进行 C ABI 提升(委托到 gen._check_and_promote_variadic_call)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._check_and_promote_variadic_call(pool, builder, mod, call_name, head, can,
|
||||
arg_nodes, self_offset, trans)
|
||||
return 0
|
||||
@@ -1,622 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import sys
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.StubMerger as StubMerger
|
||||
|
||||
|
||||
import lib.core.Handles.ExprCallBase as ExprCallBase
|
||||
import lib.core.Handles.ExprCallDeref as ExprCallDeref
|
||||
import lib.core.Handles.ExprCallCall as ExprCallCall
|
||||
import lib.core.Handles.ExprCallTable as ExprCallTable
|
||||
import lib.core.Handles.ExprCallHandle as ExprCallHandle
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
|
||||
# ============================================================
|
||||
# ExprCallCtor - HandlesExprCall 拆分(阶段 E):ExprCallCtor
|
||||
#
|
||||
# 直接移动模式:委托函数迁至此模块,原 HandlesExprCall.vp 仅
|
||||
# 保留 _g_gen/常量/类;调用方经本模块前缀访问。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# _apply_struct_defaults — 应用结构体字段的默认值
|
||||
#
|
||||
# 在 zeroinitializer 之后、显式参数之前调用
|
||||
# 遍历所有字段,对有默认值的字段翻译并 store
|
||||
# 显式参数(位置/关键字)后续会覆盖默认值
|
||||
# ============================================================
|
||||
def _apply_struct_defaults(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
struct_ty: llvmlite.LLVMType | t.CPtr,
|
||||
class_name: str,
|
||||
tmp: llvmlite.Value | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr):
|
||||
"""应用结构体字段的默认值(委托到 gen._apply_struct_defaults)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g._apply_struct_defaults(pool, builder, mod, struct_ty, class_name, tmp, trans)
|
||||
# ============================================================
|
||||
# _translate_struct_ctor — 结构体构造函数 Point(10, 20)
|
||||
#
|
||||
# 生成:
|
||||
# %tmp = alloca {i32, i32}
|
||||
# store {i32, i32} zeroinitializer, {i32, i32}* %tmp
|
||||
# %f0 = getelementptr {i32, i32}, {i32, i32}* %tmp, i32 0, i32 0
|
||||
# store i32 10, i32* %f0
|
||||
# %f1 = getelementptr {i32, i32}, {i32, i32}* %tmp, i32 0, i32 1
|
||||
# store i32 20, i32* %f1
|
||||
# %result = load {i32, i32}, {i32, i32}* %tmp
|
||||
# ============================================================
|
||||
def _translate_struct_ctor(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
struct_ty: llvmlite.LLVMType | t.CPtr,
|
||||
class_name: str,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""结构体构造函数:按字段顺序 store 参数值,返回结构体值(委托到 gen._translate_struct_ctor)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._translate_struct_ctor(pool, builder, mod, struct_ty, class_name, cargs, can, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# _translate_renum_construct — REnum 变体构造函数
|
||||
#
|
||||
# 语法: ClassName.VariantName(args...)
|
||||
# 如 LLVMType.Int(1) → 构造 LLVMType 的 Int 变体,__tag=0,_p1=1
|
||||
#
|
||||
# 生成 IR:
|
||||
# %tmp = alloca {i32, i32, ...} ; REnum 类型
|
||||
# store zeroinitializer, %tmp ; 清零
|
||||
# %tag_ptr = gep %tmp, 0, 0 ; __tag 字段
|
||||
# store i32 <tag_value>, %tag_ptr ; 写入 tag
|
||||
# %p1_ptr = gep %tmp, 0, 1 ; _p1 字段
|
||||
# store <coerced_arg0>, %p1_ptr ; 写入 payload[0]
|
||||
# ... (更多 payload 字段)
|
||||
# return %tmp ; 返回指针
|
||||
#
|
||||
# 对应 TPC 的 _HandleREnumConstructLlvm
|
||||
# ============================================================
|
||||
def _translate_renum_construct(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
class_name: str,
|
||||
variant_name: str,
|
||||
tag_value: int,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""构造 REnum 变体实例,返回指向 alloca 的指针(委托到 gen._translate_renum_construct)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._translate_renum_construct(pool, builder, mod, class_name, variant_name,
|
||||
tag_value, cargs, can, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# _do_virtual_call — 通过虚表间接调用虚方法
|
||||
#
|
||||
# IR 模式:
|
||||
# %1 = getelementptr StructTy, StructTy* %self, i32 0, i32 0 ; i8**
|
||||
# %2 = load i8*, i8** %1 ; i8* (vtable ptr)
|
||||
# %3 = bitcast i8* %2 to {i8*, ...}* ; vtable typed ptr
|
||||
# %4 = getelementptr {i8*, ...}, {i8*, ...}* %3, i32 0, i32 N ; i8**
|
||||
# %5 = load i8*, i8** %4 ; i8* (func ptr)
|
||||
# %6 = bitcast i8* %5 to RetTy(Params)* ; func typed ptr
|
||||
# call RetTy %6(Params %self, ...)
|
||||
#
|
||||
# 参数:
|
||||
# args_head — 已构建好的参数链表头(self_ptr 为首节点)
|
||||
# args_count — 参数总数(含 self)
|
||||
# found_func — 方法对应的 Function 对象(用于推断函数签名)
|
||||
# ret_ty — 返回类型
|
||||
# ============================================================
|
||||
def _do_virtual_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
class_name: str,
|
||||
method_name: str,
|
||||
self_ptr: llvmlite.Value | t.CPtr,
|
||||
args_head: llvmlite.Value | t.CPtr,
|
||||
args_count: int,
|
||||
found_func: llvmlite.Function | t.CPtr,
|
||||
ret_ty: llvmlite.LLVMType | t.CPtr,
|
||||
vtable_base: llvmlite.Value | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""通过虚表间接调用虚方法,返回 call 结果(void 方法返回 None)(委托到 gen._do_virtual_call)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._do_virtual_call(pool, builder, mod, class_name, method_name,
|
||||
self_ptr, args_head, args_count, found_func, ret_ty, vtable_base)
|
||||
return None
|
||||
# ============================================================
|
||||
# _call_method_on_ptr — 在结构体指针上调用方法
|
||||
#
|
||||
# 辅助函数:构造 ClassName.method_name 调用,self 指针为首个参数
|
||||
# 如果该方法在虚表中,则走虚方法分发路径(间接调用)
|
||||
# ============================================================
|
||||
def _call_method_on_ptr(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
class_name: str,
|
||||
method_name: str,
|
||||
self_ptr: llvmlite.Value | t.CPtr,
|
||||
extra_args: t.CSizeT | t.CPtr,
|
||||
extra_count: int,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""在结构体指针上调用方法,返回 call 结果(void 方法返回 None)(委托到 gen._call_method_on_ptr)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._call_method_on_ptr(pool, builder, mod, class_name, method_name,
|
||||
self_ptr, extra_args, extra_count, trans, node)
|
||||
return None
|
||||
# ============================================================
|
||||
# _ensure_method_declare - 为跨模块方法调用创建 declare 声明
|
||||
#
|
||||
# 当 found_func 为 None(stub 未注入或跨模块调用)时,
|
||||
# 在当前模块中创建函数声明,避免 llc 报 undefined value。
|
||||
# ============================================================
|
||||
def _ensure_method_declare(pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
call_name: str,
|
||||
ret_ty: llvmlite.LLVMType | t.CPtr,
|
||||
param_head: llvmlite.ParamNode | t.CPtr,
|
||||
param_count: int):
|
||||
"""为跨模块方法调用创建 declare 声明(委托到 gen._ensure_method_declare)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g._ensure_method_declare(pool, mod, call_name, ret_ty, param_head, param_count)
|
||||
# ============================================================
|
||||
# _lookup_method_ret_ty_via_vpi - 从 vpi stub 返回注解缓存精确获取方法返回类型
|
||||
#
|
||||
# 方法定义处(.vpi stub)的返回注解(如 json.JsonValue._pool_alloc →
|
||||
# "str")在 stub 注入时由 VpiReader 缓存(_cache_vpi_return_annots_text)。
|
||||
# 此函数按 模块SHA1 + 类名 + 方法名 查缓存并纯字符串解析为 LLVMType。
|
||||
# 无需硬编码白名单——返回类型始终来自方法定义处。
|
||||
# ============================================================
|
||||
def _lookup_method_ret_ty_via_vpi(pool: memhub.MemBuddy | t.CPtr,
|
||||
cls_sha1: str,
|
||||
cls_name: str,
|
||||
method_name: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""从 vpi stub 返回注解缓存获取方法返回类型,未命中返回 None(委托到 gen._lookup_method_ret_ty_via_vpi)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._lookup_method_ret_ty_via_vpi(pool, cls_sha1, cls_name, method_name)
|
||||
return None
|
||||
# ============================================================
|
||||
# _special_method_ret_ty - 编译器内置特殊方法的固定返回类型
|
||||
#
|
||||
# __before_init__ / __init__:编译器生成/约定返回 void
|
||||
# __new__:返回 Ptr(StructTy)(存储空间指针)
|
||||
#
|
||||
# 这些方法不存在于源码(vpi stub 无条目),跨模块调用时
|
||||
# found_func/text.ll/vpi 缓存必然未命中,但返回类型是编译器
|
||||
# 确定性语义(与 HandlesClassDef._translate_method 3543-3548 一致),
|
||||
# 在此直接固定,不触发 fail-fast 误报。非特殊方法返回 None。
|
||||
# ============================================================
|
||||
def _special_method_ret_ty(pool: memhub.MemBuddy | t.CPtr,
|
||||
class_name: str,
|
||||
method_name: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""编译器内置特殊方法的固定返回类型;非特殊返回 None(委托到 gen._special_method_ret_ty)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._special_method_ret_ty(pool, class_name, method_name)
|
||||
return None
|
||||
# ============================================================
|
||||
# _fail_method_ret_ty - 方法返回类型无法精确获取时 fail-fast
|
||||
#
|
||||
# 返回类型来源(按序):当前模块函数 → text.ll define → vpi stub 返回注解缓存。
|
||||
# 全部未命中时立即 ERROR + 错误堆栈终止,绝不按名推断白名单/静默默认 i32。
|
||||
#
|
||||
# node: 调用点 AST 节点(可选,用于 ERROR 堆栈定位)
|
||||
# ============================================================
|
||||
def _fail_method_ret_ty(method_name: str,
|
||||
node: ast.AST | t.CPtr = None) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""方法返回类型无法精确获取时 fail-fast(ERROR + 错误堆栈)(委托到 gen._fail_method_ret_ty)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._fail_method_ret_ty(method_name, node)
|
||||
return None
|
||||
# ============================================================
|
||||
# 跨模块方法返回类型查找(从 text.ll)
|
||||
#
|
||||
# Phase A 翻译每个源文件后生成 text.ll,其中 define 行包含
|
||||
# 方法的实际返回类型。当 Phase A 翻译后续文件调用跨模块方法时,
|
||||
# 方法调用默认返回 i32,导致指针返回值被截断。
|
||||
# _LookupMethodRetTyFromTextLL 读取依赖模块的 text.ll,从 define
|
||||
# 行提取实际返回类型,避免指针截断(未命中时回退 vpi stub 缓存)。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# SetTempDir - 设置 temp 目录路径
|
||||
#
|
||||
# 在 Phase2.py 的 Phase A 翻译前调用,使 CallGenMixin
|
||||
# 能够读取依赖模块的 text.ll 文件。
|
||||
# ============================================================
|
||||
def SetTempDir(temp_dir: str):
|
||||
"""设置 temp 目录路径(供跨模块方法返回类型查找使用)(委托到 gen.SetTempDir)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.SetTempDir(temp_dir)
|
||||
# ============================================================
|
||||
# _ParseLLVMRetTyStr - 将 LLVM IR 返回类型字符串转换为 llvmlite.LLVMType
|
||||
#
|
||||
# 从 define 行中提取的返回类型字符串(define 与 @ 之间的内容),
|
||||
# 转换为 llvmlite.LLVMType 对象。
|
||||
#
|
||||
# 支持的类型:
|
||||
# void → Void
|
||||
# i8/i16/i32/i64 → Int8/Int16/Int32/Int64
|
||||
# double → Double, float → Float
|
||||
# 任何含 * 的类型 → Ptr(Int8)(通用指针,保留 64 位地址)
|
||||
#
|
||||
# Args:
|
||||
# pool: 内存池
|
||||
# buf: 包含类型字符串的缓冲区
|
||||
# start: 类型字符串起始位置
|
||||
# end: 类型字符串结束位置(不含)
|
||||
#
|
||||
# Returns:
|
||||
# LLVM 类型对象,或 None(无法解析)
|
||||
# ============================================================
|
||||
def _ParseLLVMRetTyStr(pool: memhub.MemBuddy | t.CPtr,
|
||||
buf: bytes,
|
||||
start: t.CSizeT,
|
||||
end: t.CSizeT) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""将 LLVM IR 返回类型字符串转换为 llvmlite.LLVMType(委托到 gen._ParseLLVMRetTyStr)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._ParseLLVMRetTyStr(pool, buf, start, end)
|
||||
return None
|
||||
# ============================================================
|
||||
# _LookupMethodRetTyFromTextLL - 从依赖模块的 text.ll 查找方法返回类型
|
||||
#
|
||||
# 读取 {temp_dir}/{sha1[0:2]}/{sha1}.text.ll(level=1),搜索
|
||||
# define 行中包含 "{sha1}.{class_name}.{method_name}" 的函数,
|
||||
# 提取返回类型并转换为 llvmlite.LLVMType。
|
||||
#
|
||||
# 解决问题: 旧实现 _infer_method_ret_ty(已移除)默认返回 i32,导致指针返回值
|
||||
# 被 inttoptr 截断为 32 位(coerce_to_type line 238-239)。
|
||||
# 本函数从 text.ll 获取实际返回类型,避免截断。
|
||||
#
|
||||
# Args:
|
||||
# pool: 内存池
|
||||
# class_sha1: 类所属模块的 SHA1
|
||||
# class_name: 类名
|
||||
# method_name: 方法名
|
||||
#
|
||||
# Returns:
|
||||
# LLVM 类型对象,或 None(未找到/text.ll 不存在)
|
||||
# ============================================================
|
||||
def _LookupMethodRetTyFromTextLL(pool: memhub.MemBuddy | t.CPtr,
|
||||
class_sha1: str,
|
||||
class_name: str,
|
||||
method_name: str,
|
||||
use_bare: int = 0) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""从依赖模块的 text.ll 中查找方法返回类型(委托到 gen._LookupMethodRetTyFromTextLL)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._LookupMethodRetTyFromTextLL(pool, class_sha1, class_name, method_name, use_bare)
|
||||
return None
|
||||
# ============================================================
|
||||
# 属性方法(@property/@x.setter/@x.deleter)与静态/类方法调用辅助
|
||||
#
|
||||
# 元数据表由 HandlesClassDef 在类翻译/预注册阶段填充,
|
||||
# 这里负责把 obj.prop / obj.prop=v / del obj.prop / Class.method()
|
||||
# 翻译为对应的 {sha1}.ClassName.prop 系列函数调用。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# _translate_property_call — 翻译属性方法调用
|
||||
#
|
||||
# 与 _translate_method_call 的调用名/返回类型解析逻辑一致:
|
||||
# 1. 优先用模块中已有的函数(精确/后缀匹配,来自 stub 注入)
|
||||
# 2. 否则用类所属模块的 SHA1 构造 "{sha1}.ClassName.method" 调用名
|
||||
# 3. 返回类型:函数实类型 → text.ll 查找 → 按方法名推断(默认 i32)
|
||||
#
|
||||
# call_head/call_count: 已构建好的参数链表(如 getter 只有 obj 一个参数)
|
||||
# ============================================================
|
||||
def _translate_property_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
class_name: str,
|
||||
method_name: str,
|
||||
call_head: llvmlite.Value | t.CPtr,
|
||||
call_count: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译属性/静态方法调用,返回 call 结果 Value(委托到 gen._translate_property_call)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._translate_property_call(pool, builder, mod, class_name, method_name,
|
||||
call_head, call_count, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# _resolve_obj_class_name — 解析对象表达式的类名(短名)
|
||||
#
|
||||
# 优先从变量注解(AnnotClassName)解析(如 "memhub.MemBuddy" → "MemBuddy"),
|
||||
# 失败时从 LLVM 类型解析(Ptr(Struct) → 类名)。
|
||||
# 供属性访问/赋值/删除识别 property 时使用。
|
||||
# ============================================================
|
||||
def _resolve_obj_class_name(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
obj_node: ast.AST | t.CPtr) -> str:
|
||||
"""解析对象表达式的类名(短名),失败返回 None(委托到 gen._resolve_obj_class_name)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._resolve_obj_class_name(pool, trans, obj_node)
|
||||
return None
|
||||
# ============================================================
|
||||
# _try_property_getter_attr — 尝试将 obj.attr 翻译为 property getter 调用
|
||||
#
|
||||
# 检查 obj 的类是否有 @property/@x.getter 的 attr 方法;
|
||||
# 若有则生成 call Class.attr(obj) 并返回调用结果 Value;否则返回 None。
|
||||
# ============================================================
|
||||
def _try_property_getter_attr(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
at_node: ast.Attribute | t.CPtr,
|
||||
obj_ptr: llvmlite.Value | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
fallback_class_name: str = None) -> llvmlite.Value | t.CPtr:
|
||||
"""尝试 property getter 属性访问,返回调用结果 Value;非 getter 返回 None(委托到 gen._try_property_getter_attr)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._try_property_getter_attr(pool, builder, mod, at_node, obj_ptr,
|
||||
trans, fallback_class_name)
|
||||
return None
|
||||
# ============================================================
|
||||
# _try_property_setter — 尝试将 obj.attr = v 翻译为 property setter 调用
|
||||
#
|
||||
# 检查 obj 的类是否有 @x.setter 的 attr 方法;
|
||||
# 若有则生成 call Class.attr$set(obj, v),返回 1;否则返回 0。
|
||||
# ============================================================
|
||||
def _try_property_setter(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
target_attr: ast.Attribute | t.CPtr,
|
||||
rhs_val: llvmlite.Value | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> int:
|
||||
"""尝试 property setter 赋值,返回 1=已处理(生成调用)(委托到 gen._try_property_setter)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._try_property_setter(pool, builder, mod, target_attr, rhs_val, trans)
|
||||
return 0
|
||||
# ============================================================
|
||||
# _try_property_deleter — 尝试将 del obj.attr 翻译为 property deleter 调用
|
||||
#
|
||||
# 检查 obj 的类是否有 @x.deleter 的 attr 方法;
|
||||
# 若有则生成 call Class.attr$del(obj),返回 1;否则返回 0。
|
||||
# ============================================================
|
||||
def _try_property_deleter(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
target_attr: ast.Attribute | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> int:
|
||||
"""尝试 property deleter 删除,返回 1=已处理(生成调用)(委托到 gen._try_property_deleter)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._try_property_deleter(pool, builder, mod, target_attr, trans)
|
||||
return 0
|
||||
# ============================================================
|
||||
# _translate_static_class_call — 翻译 ClassName.method(args) 静态/类方法调用
|
||||
#
|
||||
# @staticmethod: 直接 call Class.method(args...),无 self
|
||||
# @classmethod: 在参数前插入栈上分配的类实例指针(与 TPC 一致)
|
||||
# ============================================================
|
||||
def _translate_static_class_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
class_name: str,
|
||||
method_name: str,
|
||||
cl: ast.Call | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译类名静态/类方法调用,返回 call 结果 Value;非静态/类方法返回 None(委托到 gen._translate_static_class_call)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._translate_static_class_call(pool, builder, mod, class_name, method_name, cl, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# _translate_method_call - 翻译方法调用 obj.method(args)
|
||||
#
|
||||
# 生成: call <ret_ty> @SHA1.ClassName.method_name(Ptr(StructTy) %obj, args...)
|
||||
#
|
||||
# obj_ptr 是对象变量的 alloca(Ptr(StructTy)),作为 self 参数传入
|
||||
# ============================================================
|
||||
def _translate_method_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
class_name: str,
|
||||
method_name: str,
|
||||
obj_ptr: llvmlite.Value | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译方法调用,返回 call 结果 Value(委托到 gen._translate_method_call)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._translate_method_call(pool, builder, mod, class_name, method_name,
|
||||
obj_ptr, cl, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# _kwarg_name_matches — 检查关键字参数名是否匹配函数参数名
|
||||
#
|
||||
# 函数参数名在 LLVM IR 中带 % 前缀(如 "%a"),关键字参数名无前缀(如 "a")
|
||||
# 跳过 % 前缀后逐字符比较
|
||||
# ============================================================
|
||||
def _kwarg_name_matches(kw_arg: str,
|
||||
param_name: str) -> int:
|
||||
"""检查关键字参数名 kw_arg 是否匹配参数名 param_name(跳过 % 前缀)(委托到 gen._kwarg_name_matches)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._kwarg_name_matches(kw_arg, param_name)
|
||||
return 0
|
||||
# ============================================================
|
||||
# _translate_struct_ctor_kw — 结构体构造函数(关键字参数)
|
||||
#
|
||||
# 支持两种语法:
|
||||
# Point(x=10, y=20) — 全关键字
|
||||
# Point(10, y=20) — 混合(位置 + 关键字)
|
||||
#
|
||||
# 位置参数按字段索引赋值,关键字参数按字段名查找赋值
|
||||
# ============================================================
|
||||
def _translate_struct_ctor_kw(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
struct_ty: llvmlite.LLVMType | t.CPtr,
|
||||
class_name: str,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
keywords: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
kw_count: t.CSizeT,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""结构体构造函数(关键字参数版本)(委托到 gen._translate_struct_ctor_kw)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._translate_struct_ctor_kw(pool, builder, mod, struct_ty, class_name,
|
||||
cargs, can, keywords, kw_count, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# _translate_call_with_kwargs — 带关键字参数的函数调用
|
||||
#
|
||||
# 支持两种语法:
|
||||
# add(b=4, a=3) — 全关键字乱序
|
||||
# greet("Hello", name="World") — 位置 + 关键字混合
|
||||
#
|
||||
# 策略: 遍历 found_func.Params 链表,对每个参数:
|
||||
# 1. 若位置参数仍有剩余(param_idx < can),取位置参数
|
||||
# 2. 否则按参数名匹配关键字参数
|
||||
# 3. 按参数顺序构建调用参数链表
|
||||
# ============================================================
|
||||
def _translate_call_with_kwargs(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
func_name: str,
|
||||
found_func: llvmlite.Function | t.CPtr,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
keywords: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
kw_count: t.CSizeT,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""带关键字参数的函数调用,按参数顺序构建调用链表(委托到 gen._translate_call_with_kwargs)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._translate_call_with_kwargs(pool, builder, mod, func_name, found_func,
|
||||
cargs, can, keywords, kw_count, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# _translate_t_type_cast - 翻译 t.XXX(value) 类型转换
|
||||
#
|
||||
# 当 func 是 t.XXX 形式且 XXX 是已知类型名(map_t_type 能映射)时,
|
||||
# 将 value 转换为目标类型:
|
||||
# - 指针 → 整数: ptrtoint(如 t.CUInt64T(ptr) → i64)
|
||||
# - 整数 → 指针: inttoptr(如 t.CPtr(int_val) → i8*)
|
||||
# - 整数 → 整数: trunc/zext(如 t.CInt8T(i32_val) → i8)
|
||||
# - 指针 → 指针: bitcast(如 t.CPtr(ptr_val) → i8*)
|
||||
# - 整数 → 浮点: sitofp(如 t.CDouble(i32_val) → double)
|
||||
# - 浮点 → 整数: fptosi(如 t.CInt(double_val) → i32)
|
||||
# - 浮点 → 浮点: fpext/fptrunc(如 t.CFloat(double_val) → float)
|
||||
# ============================================================
|
||||
def _translate_t_type_cast(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
val: llvmlite.Value | t.CPtr,
|
||||
target_ty: llvmlite.LLVMType | t.CPtr,
|
||||
target_name: str = None,
|
||||
src_node: ast.AST | t.CPtr = None,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""类型转换:根据参数类型和目标类型选择转换方式(委托到 gen._translate_t_type_cast)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._translate_t_type_cast(pool, builder, val, target_ty,
|
||||
target_name, src_node, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# 泛型实例化辅助:从 Subscript slice 提取类型实参名
|
||||
# ============================================================
|
||||
# _get_type_name_from_annotation 已移至 HandlesType.py(支持 BinOp/Attribute)
|
||||
# HandlesExprCall 通过 HandlesType._get_type_name_from_annotation 调用
|
||||
|
||||
def _extract_type_args_from_slice(pool: memhub.MemBuddy | t.CPtr,
|
||||
slice_node: ast.AST | t.CPtr) -> list[str] | t.CPtr:
|
||||
"""从 Subscript.slice 提取类型实参名列表(委托到 gen._extract_type_args_from_slice)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._extract_type_args_from_slice(pool, slice_node)
|
||||
return None
|
||||
# ============================================================
|
||||
# 泛型类构造调用辅助: list[str](pool, 8) → __new__ + __before_init__ + __init__
|
||||
#
|
||||
# 复用 translate_list_literal 的构造逻辑:
|
||||
# 1. alloca tmp(特化类临时空间,作为 __new__ 的 self)
|
||||
# 2. 翻译 cl.args 为参数指针数组
|
||||
# 3. call __new__(tmp, *args) → storage_ptr
|
||||
# 4. call __before_init__(storage_ptr)
|
||||
# 5. call __init__(storage_ptr, *args)
|
||||
# 6. return storage_ptr
|
||||
#
|
||||
# 必须独立于 translate_call 的普通函数路径:spec_name 是类名不是函数名,
|
||||
# 走裸名路径会被 _lookup_mod_sha1 的 star import 回退误导,用错误的 SHA1
|
||||
# 且缺少 __new__ 方法名后缀,导致链接报 undefined reference。
|
||||
# ============================================================
|
||||
def _infer_generic_ctor_type_arg(pool: memhub.MemBuddy | t.CPtr,
|
||||
arg_node: ast.AST | t.CPtr,
|
||||
class_name: str) -> str:
|
||||
"""从构造实参 AST 推断泛型类型实参名;无法推断时默认 "int"(与 TPC 一致)(委托到 gen._infer_generic_ctor_type_arg)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._infer_generic_ctor_type_arg(pool, arg_node, class_name)
|
||||
return "int"
|
||||
def _translate_generic_ctor_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
spec_name: str,
|
||||
cl: ast.Call | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""泛型类构造调用: list[str](pool, 8) → __new__ + __before_init__ + __init__(委托到 gen._translate_generic_ctor_call)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._translate_generic_ctor_call(pool, builder, mod, spec_name, cl, trans)
|
||||
return None
|
||||
@@ -1,291 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import sys
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.StubMerger as StubMerger
|
||||
|
||||
|
||||
import lib.core.Handles.ExprCallBase as ExprCallBase
|
||||
import lib.core.Handles.ExprCallCtor as ExprCallCtor
|
||||
import lib.core.Handles.ExprCallCall as ExprCallCall
|
||||
import lib.core.Handles.ExprCallTable as ExprCallTable
|
||||
import lib.core.Handles.ExprCallHandle as ExprCallHandle
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
|
||||
# ============================================================
|
||||
# ExprCallDeref - HandlesExprCall 拆分(阶段 E):ExprCallDeref
|
||||
#
|
||||
# 直接移动模式:委托函数迁至此模块,原 HandlesExprCall.vp 仅
|
||||
# 保留 _g_gen/常量/类;调用方经本模块前缀访问。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# c.Deref(ptr) — 解引用指针,按指针 pointee 类型读取
|
||||
#
|
||||
# 生成: %N = load <pointee_ty>, <pointee_ty>* %ptr
|
||||
# 返回 pointee 类型的值
|
||||
#
|
||||
# 注意: 必须按 ptr 的 pointee 类型决定读取宽度。
|
||||
# - i8* (str/bytes/字符遍历) → load i8
|
||||
# - i64* (t.CUInt64T, 块头部) → load i64(memhub 的 free list 链表读 8 字节头部)
|
||||
# 之前固定 load i8 导致 memhub 读块头部只读到低 8 位,
|
||||
# free list 的 next 指针被截断成 0x88 等垃圾值,alloc 崩溃。
|
||||
# ============================================================
|
||||
def translate_c_deref(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""c.Deref(ptr) → load 按 ptr 的 pointee 类型(委托到 gen.translate_c_deref)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_c_deref(pool, builder, mod, cl, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# c.DerefAs(ptr, val) — 解引用写入,*ptr = val
|
||||
#
|
||||
# 生成: %pc = bitcast i8* %ptr to <val_ty>*
|
||||
# store <val_ty> %val, <val_ty>* %pc
|
||||
# ============================================================
|
||||
def translate_c_derefas(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""c.DerefAs(ptr, val) → store val to ptr(bitcast 后 store)(委托到 gen.translate_c_derefas)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_c_derefas(pool, builder, mod, cl, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# c.Set(a, b) — 赋值语义 a = b(与 c.DerefAs 的指针语义不同)
|
||||
#
|
||||
# c.DerefAs(ptr, val) 是 *ptr = val(指针解引用写);
|
||||
# c.Set(a, b) 是 a = b(a 为左值),a 支持三种形态:
|
||||
# 1. c.Deref(ptr) → *ptr = b(zlib/vipermath 的 c.Set(c.Deref(p), v) 用法)
|
||||
# 2. Name 变量 → 变量赋值(含 global/nonlocal/局部)
|
||||
# 3. Attribute → 字段赋值(GEP + store)
|
||||
# ============================================================
|
||||
def translate_c_set(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""c.Set(a, b) → a = b(赋值语义,a 为左值)(委托到 gen.translate_c_set)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_c_set(pool, builder, mod, cl, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# c.Addr(var) — 取变量地址,返回 alloca 指针(不 load)
|
||||
#
|
||||
# 用于获取栈变量的可写地址,配合 c.DerefAs 使用
|
||||
# ============================================================
|
||||
def translate_c_addr(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""c.Addr(var) → 返回变量的 alloca 指针(不 load)(委托到 gen.translate_c_addr)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_c_addr(pool, builder, mod, cl, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# c.Load(a, b) — 指针间复制: *a = *b
|
||||
#
|
||||
# 加载 b 指向的值,存储到 a 指向的地址。
|
||||
# 生成: %pc_src = bitcast i8* %src to <ty>*
|
||||
# %loaded = load <ty>, <ty>* %pc_src
|
||||
# %pc_dst = bitcast i8* %dst to <ty>*
|
||||
# store <ty> %loaded, <ty>* %pc_dst
|
||||
# ============================================================
|
||||
def translate_c_load(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""c.Load(a, b) → *a = *b(加载 b 的值,存储到 a)(委托到 gen.translate_c_load)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_c_load(pool, builder, mod, cl, trans)
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
# c.Asm — 内联汇编支持
|
||||
#
|
||||
# 生成: %N = call <ret_ty> asm sideeffect "<asm>", "<constraints>"(<args>)
|
||||
# 或: call void asm sideeffect "<asm>", "<constraints>"(<args>)
|
||||
#
|
||||
# 操作数按出现顺序编号 $0, $1, ...(用户需按输出在前写 f-string)
|
||||
# ============================================================
|
||||
|
||||
ASM_MAX_OPERANDS: t.CDefine = 16
|
||||
ASM_TEXT_BUF_SIZE: t.CDefine = 2048
|
||||
ASM_CONST_BUF_SIZE: t.CDefine = 512
|
||||
ASM_ARGS_BUF_SIZE: t.CDefine = 512
|
||||
ASM_LINE_BUF_SIZE: t.CDefine = 4096
|
||||
# ============================================================
|
||||
# _asm_append_cstr — 将 C 字符串 src 追加到 dst 末尾
|
||||
# ============================================================
|
||||
def _asm_append_cstr(dst: str, dst_size: t.CSizeT,
|
||||
src: str):
|
||||
"""将 C 字符串 src 追加到 dst 末尾(委托到 gen._asm_append_cstr)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g._asm_append_cstr(dst, dst_size, src)
|
||||
# ============================================================
|
||||
# _asm_escape_for_ir — 将汇编文本转义为 LLVM IR 字符串内容
|
||||
#
|
||||
# \n → \0A, " → \22, \ → \5C
|
||||
# ============================================================
|
||||
def _asm_escape_for_ir(pool: memhub.MemBuddy | t.CPtr,
|
||||
src: str) -> str:
|
||||
"""转义汇编文本用于 LLVM IR 字符串字面量(委托到 gen._asm_escape_for_ir)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._asm_escape_for_ir(pool, src)
|
||||
return None
|
||||
# ============================================================
|
||||
# _resolve_register — 将 ASM_DESCR 属性名映射到约束字符串
|
||||
# ============================================================
|
||||
def _resolve_register(attr_name: str) -> str:
|
||||
"""将 t.ASM_DESCR.XXX 的属性名映射到约束字符串值(委托到 gen._resolve_register)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._resolve_register(attr_name)
|
||||
return ""
|
||||
# ============================================================
|
||||
# _resolve_asm_descr — 递归解析约束表达式
|
||||
#
|
||||
# 支持:
|
||||
# t.ASM_DESCR.XXX → _resolve_register(XXX)
|
||||
# expr | expr(BinOp BitOr) → 拼接
|
||||
# "string" (Constant) → 直接返回
|
||||
# ============================================================
|
||||
def _resolve_asm_descr(pool: memhub.MemBuddy | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> str:
|
||||
"""递归解析约束表达式,返回约束字符串(委托到 gen._resolve_asm_descr)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._resolve_asm_descr(pool, node)
|
||||
return ""
|
||||
# ============================================================
|
||||
# _asm_get_operand — 获取操作数数组中第 idx 个元素的指针
|
||||
# ============================================================
|
||||
def _asm_get_operand(base: HandlesExprCall.AsmOperand | t.CPtr,
|
||||
idx: int) -> HandlesExprCall.AsmOperand | t.CPtr:
|
||||
"""获取操作数数组中第 idx 个元素的指针(委托到 gen._asm_get_operand)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._asm_get_operand(base, idx)
|
||||
return None
|
||||
# ============================================================
|
||||
# _asm_is_c_call — 检查 Call 节点是否是 c.XXX 调用
|
||||
#
|
||||
# 返回 attr_name(如 "AsmInp"/"AsmOut"),不是则返回 None
|
||||
# ============================================================
|
||||
def _asm_is_c_call(node: ast.Call | t.CPtr) -> str:
|
||||
"""检查 Call 节点是否是 c.XXX 调用,返回属性名或 None(委托到 gen._asm_is_c_call)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._asm_is_c_call(node)
|
||||
return None
|
||||
# ============================================================
|
||||
# _asm_add_operand — 添加操作数到数组
|
||||
#
|
||||
# 返回 1 成功, 0 失败(数组已满)
|
||||
# ============================================================
|
||||
def _asm_add_operand(operands: HandlesExprCall.AsmOperand | t.CPtr,
|
||||
count: int,
|
||||
val: llvmlite.Value | t.CPtr,
|
||||
constraint: str,
|
||||
is_output: int) -> int:
|
||||
"""添加操作数到数组,返回新计数(失败返回原计数)(委托到 gen._asm_add_operand)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._asm_add_operand(operands, count, val, constraint, is_output)
|
||||
return 0
|
||||
# ============================================================
|
||||
# translate_c_asm — 翻译 c.Asm 内联汇编
|
||||
#
|
||||
# 语法:
|
||||
# c.Asm("nop", [t.ASM_DESCR.CLOBBER_MEMORY])
|
||||
# c.Asm(f"mov rax, {c.AsmInp(val, t.ASM_DESCR.REG_ANY)}", op=[...])
|
||||
# c.Asm(f"...", out=[c.AsmOut(var, t.ASM_DESCR.OUTPUT_REG)], op=[...])
|
||||
# ============================================================
|
||||
def translate_c_asm(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译 c.Asm 内联汇编,返回结果 Value(委托到 gen.translate_c_asm)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_c_asm(pool, builder, mod, cl, trans)
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
# c.LLVMIR — 内联 LLVM IR(无返回值,直接嵌入原始 IR 文本)
|
||||
#
|
||||
# 语法:
|
||||
# c.LLVMIR(f"add i32 {c.LInp(a)}, {c.LInp(b)}")
|
||||
# c.LLVMIR(f"{c.LOut(result)} = add i32 {c.LInp(a)}, {c.LInp(b)}")
|
||||
#
|
||||
# c.LInp(expr) - 输入操作数,替换为 expr 的 LLVM 值引用文本(SSA 名 "%x" 或常量 "42")
|
||||
# c.LOut(expr) - 输出操作数:为 expr 变量分配唯一 SSA 寄存器 %llvmirN,
|
||||
# 模板嵌入后自动追加 store <ty> %llvmirN, <ty>* %expr 写回变量
|
||||
#
|
||||
# 语义(2026-08-08 用户决策):不做指令解析,模板文本直接嵌入当前基本块,
|
||||
# 返回 None(无返回值)。ret_ty 第二参数已废弃(兼容忽略)。
|
||||
# ============================================================
|
||||
|
||||
LLVMIR_MAX_OPS: t.CDefine = 16
|
||||
LLVMIR_TEMPLATE_BUF: t.CDefine = 512
|
||||
# 注:LOut 唯一 SSA 寄存器名计数器已迁入 gen 字段(CallGenMixin.LLVMIRRegSeq),
|
||||
# 本模块不再持有(P4 簇 1+2)。
|
||||
|
||||
# ============================================================
|
||||
# translate_c_llvmir — 翻译 c.LLVMIR 内联 LLVM IR
|
||||
# ============================================================
|
||||
def translate_c_llvmir(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""c.LLVMIR 内联 LLVM IR:无返回值,直接嵌入原始 IR 文本(委托到 gen.translate_c_llvmir)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_c_llvmir(pool, builder, mod, cl, trans)
|
||||
return None
|
||||
@@ -1,287 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import sys
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.StubMerger as StubMerger
|
||||
|
||||
|
||||
import lib.core.Handles.ExprCallBase as ExprCallBase
|
||||
import lib.core.Handles.ExprCallDeref as ExprCallDeref
|
||||
import lib.core.Handles.ExprCallCtor as ExprCallCtor
|
||||
import lib.core.Handles.ExprCallCall as ExprCallCall
|
||||
import lib.core.Handles.ExprCallTable as ExprCallTable
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
|
||||
# ============================================================
|
||||
# ExprCallHandle - HandlesExprCall 拆分(阶段 E):ExprCallHandle
|
||||
#
|
||||
# 直接移动模式:委托函数迁至此模块,原 HandlesExprCall.vp 仅
|
||||
# 保留 _g_gen/常量/类;调用方经本模块前缀访问。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# NewExprCallHandle - 工厂函数
|
||||
# ============================================================
|
||||
def NewExprCallHandle(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> HandlesExprCall.ExprCallHandle | t.CPtr:
|
||||
"""新建 HandlesExprCall.ExprCallHandle 工厂(委托到 gen.NewExprCallHandle)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.NewExprCallHandle(pool, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# _make_vtable_ref_i8 / _emit_eh_guarded_call / _translate_isinstance
|
||||
# (追加91:CallGenMixin 拆分后顶层经委托调用 CallGenLeafKit 方法——
|
||||
# TPV self 调用仅支持 1 级父类,跨 Mixin 统一走 HandlesExprCall._g_gen 委托)
|
||||
# ============================================================
|
||||
def _make_vtable_ref_i8(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
class_name: str,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""构造类 vtable 地址引用(i8*)(委托到 gen._make_vtable_ref_i8)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._make_vtable_ref_i8(pool, builder, mod, class_name, trans)
|
||||
return None
|
||||
def _emit_eh_guarded_call(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
func: llvmlite.Function | t.CPtr,
|
||||
call_name: str,
|
||||
head: llvmlite.Value | t.CPtr,
|
||||
count: int,
|
||||
ret_ty: llvmlite.LLVMType | t.CPtr,
|
||||
is_variadic: int) -> llvmlite.Value | t.CPtr:
|
||||
"""带 try-except EH 检测的函数调用(委托到 gen._emit_eh_guarded_call)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._emit_eh_guarded_call(builder, pool, mod, trans, func, call_name, head, count, ret_ty, is_variadic)
|
||||
return None
|
||||
def _translate_isinstance(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
obj_node: ast.AST | t.CPtr,
|
||||
cls_node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译 isinstance()(委托到 gen._translate_isinstance)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._translate_isinstance(pool, builder, mod, obj_node, cls_node, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# _is_sha1_mangled_call / _is_list_builtin_method / _translate_fakeduck_call /
|
||||
# _translate_super_call(阶段 B:CallGenMixin 拆分后顶层经委托调用这些方法)
|
||||
# ============================================================
|
||||
def _is_sha1_mangled_call(call_name: str) -> int:
|
||||
"""判断 call_name 是否为跨模块 Viper 函数(委托到 gen._is_sha1_mangled_call)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._is_sha1_mangled_call(call_name)
|
||||
return 0
|
||||
def _is_list_builtin_method(class_name: str, method_name: str) -> int:
|
||||
"""判断(class_name, method_name) 是否是 list 泛型内置方法(委托到 gen._is_list_builtin_method)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._is_list_builtin_method(class_name, method_name)
|
||||
return 0
|
||||
def _translate_fakeduck_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cls_name: str,
|
||||
method_name: str,
|
||||
cl: ast.Call | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""FakeDuck: str 变量方法调用(委托到 gen._translate_fakeduck_call)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._translate_fakeduck_call(pool, builder, mod, cls_name, method_name, cl, trans)
|
||||
return None
|
||||
def _translate_super_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
method_name: str,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""super().method(args) → 父类方法静态调用(委托到 gen._translate_super_call)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._translate_super_call(pool, builder, mod, cl, method_name, trans)
|
||||
return None
|
||||
# ============================================================
|
||||
# translate_call 前置检测 helper(阶段 C:CallGenMixin 拆分后顶层经委托
|
||||
# 调用 CallGenDispatch 方法。每个返回 Value|CPtr,None = 未命中继续主路径)
|
||||
# ============================================================
|
||||
def _tc_h1_super_ctraits(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
func_name: str,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
hit_box: t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""super()/ctraits 编译期检测(委托到 gen._tc_h1_super_ctraits)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._tc_h1_super_ctraits(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, hit_box)
|
||||
return None
|
||||
def _tc_h2_c_special(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
func_name: str,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
hit_box: t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""c.Deref/Asm/LLVMIR 等特殊调用(委托到 gen._tc_h2_c_special)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._tc_h2_c_special(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, hit_box)
|
||||
return None
|
||||
def _tc_h3_stdarg_cast(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
func_name: str,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT) -> llvmlite.Value | t.CPtr:
|
||||
"""stdarg 糖 + str/int/bool 内置强转(委托到 gen._tc_h3_stdarg_cast)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._tc_h3_stdarg_cast(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can)
|
||||
return None
|
||||
def _tc_h4_type_casts(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
func_name: str,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT) -> llvmlite.Value | t.CPtr:
|
||||
"""t.XXX / typedef 类型转换(委托到 gen._tc_h4_type_casts)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._tc_h4_type_casts(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can)
|
||||
return None
|
||||
def _tc_h5_sizeof_len_isinst(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
func_name: str,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT) -> llvmlite.Value | t.CPtr:
|
||||
"""__sizeof__/len/isinstance 内置(委托到 gen._tc_h5_sizeof_len_isinst)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._tc_h5_sizeof_len_isinst(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can)
|
||||
return None
|
||||
def _tc_h6_method_dispatch(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
func_name: str,
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
can: t.CSizeT,
|
||||
hit_box: t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""静态类/方法调用/表达式接收者/self.field/list 内置(委托到 gen._tc_h6_method_dispatch)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._tc_h6_method_dispatch(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, hit_box)
|
||||
return None
|
||||
# ============================================================
|
||||
# FuncGen 跨 Mixin 委托(阶段 D:FuncGenMixin 拆 Base/Def 后顶层经
|
||||
# 此调用这些方法。参数与目标方法一致,去 self)
|
||||
# ============================================================
|
||||
def extract_func_attrs(pool: memhub.MemBuddy | t.CPtr,
|
||||
decorator_list: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
imported_modules: str) -> str:
|
||||
"""从 decorator_list 提取 c.Attribute 属性(委托到 gen.extract_func_attrs)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.extract_func_attrs(pool, decorator_list, imported_modules)
|
||||
return None
|
||||
def _mangle_name(trans: HT.Translator | t.CPtr, name: str) -> str:
|
||||
"""为任意名称添加 SHA1 前缀(委托到 gen._mangle_name)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._mangle_name(trans, name)
|
||||
return name
|
||||
def _mangle_func_name(trans: HT.Translator | t.CPtr, name: str,
|
||||
has_export: int) -> str:
|
||||
"""为函数名添加 SHA1 前缀(委托到 gen._mangle_func_name)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._mangle_func_name(trans, name, has_export)
|
||||
return name
|
||||
def _body_has_raise(fd: ast.FunctionDef | t.CPtr) -> int:
|
||||
"""函数体顶层是否含 raise(委托到 gen._body_has_raise)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._body_has_raise(fd)
|
||||
return 0
|
||||
def _prepare_chain_nonlocals(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr,
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""准备嵌套函数 nonlocals 链(委托到 gen._prepare_chain_nonlocals)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._prepare_chain_nonlocals(trans, node, pool, builder, mod, i8_ty, i8_ptr_ty)
|
||||
return 0
|
||||
@@ -1,206 +1,197 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import sys
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.StubMerger as StubMerger
|
||||
|
||||
|
||||
import lib.core.Handles.ExprCallBase as ExprCallBase
|
||||
import lib.core.Handles.ExprCallDeref as ExprCallDeref
|
||||
import lib.core.Handles.ExprCallCtor as ExprCallCtor
|
||||
import lib.core.Handles.ExprCallCall as ExprCallCall
|
||||
import lib.core.Handles.ExprCallHandle as ExprCallHandle
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
|
||||
# ============================================================
|
||||
# ExprCallTable - HandlesExprCall 拆分(阶段 E):ExprCallTable
|
||||
#
|
||||
# 直接移动模式:委托函数迁至此模块,原 HandlesExprCall.vp 仅
|
||||
# 保留 _g_gen/常量/类;调用方经本模块前缀访问。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# 初始化函数表
|
||||
# ============================================================
|
||||
def init_func_table(pool: memhub.MemBuddy | t.CPtr,
|
||||
max_count: int) -> HandlesExprCall.FuncEntry | t.CPtr:
|
||||
"""分配并清零函数表数组(委托到 gen.init_func_table)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.init_func_table(pool, max_count)
|
||||
return None
|
||||
# ============================================================
|
||||
# 查找函数
|
||||
# ============================================================
|
||||
def find_func_in_table(funcs: HandlesExprCall.FuncEntry | t.CPtr,
|
||||
func_count: int,
|
||||
name: str) -> llvmlite.Function | t.CPtr:
|
||||
"""在函数表中按名称查找,返回 Function 指针或 None(委托到 gen.find_func_in_table)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.find_func_in_table(funcs, func_count, name)
|
||||
return None
|
||||
# ============================================================
|
||||
# 添加函数到函数表
|
||||
# ============================================================
|
||||
def add_func_to_table(funcs: HandlesExprCall.FuncEntry | t.CPtr,
|
||||
func_count: int,
|
||||
name: str,
|
||||
func: llvmlite.Function | t.CPtr,
|
||||
max_count: int,
|
||||
defaults: t.CVoid | t.CPtr = None,
|
||||
default_count: int = 0,
|
||||
param_count: int = 0,
|
||||
pool: memhub.MemBuddy | t.CPtr = None) -> int:
|
||||
"""添加函数到函数表,返回 0 成功(委托到 gen.add_func_to_table)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.add_func_to_table(funcs, func_count, name, func, max_count,
|
||||
defaults, default_count, param_count, pool)
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# 全局函数注册表(跨模块函数查找)
|
||||
#
|
||||
# 所有模块翻译的函数都会注册到此表(通过 add_func_to_table 自动注册)。
|
||||
# 主要用途: vtable 初始化时查找跨模块继承方法的 Function 对象,
|
||||
# 以获取函数类型信息构造 bitcast 字符串。
|
||||
# ============================================================
|
||||
GLOBAL_FUNC_MAX: t.CDefine = 8192
|
||||
def _init_global_func_table() -> int:
|
||||
"""初始化全局函数表(用 stdlib.malloc 分配,生命周期=整个程序)(委托到 gen._init_global_func_table)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._init_global_func_table()
|
||||
return 0
|
||||
# _build_func_type_str — 从 Function 对象生成函数类型文本(stdlib 存储)
|
||||
#
|
||||
# 格式: ret_ty(param1_ty, param2_ty, ...),与 vtable bitcast 需要一致。
|
||||
# 用 stdlib.malloc 分配返回,跨文件永久存活(1b reset 不回收)。
|
||||
# 返回 None 表示失败。
|
||||
def _build_func_type_str(pool: memhub.MemBuddy | t.CPtr,
|
||||
func: llvmlite.Function | t.CPtr) -> str:
|
||||
"""生成函数类型文本(stdlib 分配)(委托到 gen._build_func_type_str)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._build_func_type_str(pool, func)
|
||||
return None
|
||||
def _register_global_func(name: str, func: llvmlite.Function | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr = None) -> int:
|
||||
"""注册函数到全局表(已存在则跳过),返回 0 成功(委托到 gen._register_global_func)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._register_global_func(name, func, pool)
|
||||
return 0
|
||||
def update_global_func_typestr(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str,
|
||||
func: llvmlite.Function | t.CPtr) -> int:
|
||||
"""更新全局函数表的 TypeStr(在函数参数全部添加完成后调用)(委托到 gen.update_global_func_typestr)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.update_global_func_typestr(pool, name, func)
|
||||
return 0
|
||||
def find_func_global(name: str) -> llvmlite.Function | t.CPtr:
|
||||
"""在全局函数表中按名称查找,返回 Function 指针或 None(委托到 gen.find_func_global)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.find_func_global(name)
|
||||
return None
|
||||
def find_func_entry_global(name: str) -> HandlesExprCall.FuncEntry | t.CPtr:
|
||||
"""在全局函数表中按名称查找,返回完整 HandlesExprCall.FuncEntry(含 TypeStr)或 None(委托到 gen.find_func_entry_global)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.find_func_entry_global(name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局默认参数注册表(跨模块默认参数填充)
|
||||
#
|
||||
# 独立于 _global_funcs,因为 _register_global_func 可能在
|
||||
# add_func_to_table 之前被调用(如 stub 注入),此时 defaults 还不可用。
|
||||
# ============================================================
|
||||
GLOBAL_DEFAULTS_MAX: t.CDefine = 4096
|
||||
def _init_global_defaults_table() -> int:
|
||||
"""初始化全局默认参数表(委托到 gen._init_global_defaults_table)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._init_global_defaults_table()
|
||||
return 0
|
||||
def _register_global_defaults(name: str,
|
||||
defaults: t.CVoid | t.CPtr,
|
||||
default_count: int,
|
||||
param_count: int) -> int:
|
||||
"""注册函数默认参数到全局表,返回 0 成功(委托到 gen._register_global_defaults)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._register_global_defaults(name, defaults, default_count, param_count)
|
||||
return 0
|
||||
def find_func_defaults(name: str) -> HandlesExprCall.FuncDefaultsEntry | t.CPtr:
|
||||
"""按函数名查找默认参数信息,返回 HandlesExprCall.FuncDefaultsEntry 或 None(委托到 gen.find_func_defaults)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.find_func_defaults(name)
|
||||
return None
|
||||
# _build_const_from_snapshot — 从常量快照重建常量 IR 值
|
||||
#
|
||||
# 用于跨模块默认参数填充:gd_entry.Defaults(pool 内 AST)可能已被 reset 回收,
|
||||
# 改用注册时提取的 stdlib 常量快照(ConstKinds/ConstInts/ConstStrs)重建常量 IR。
|
||||
# 返回 llvmlite.Value*,失败返回 None。
|
||||
def _build_const_from_snapshot(pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
gd_entry: HandlesExprCall.FuncDefaultsEntry | t.CPtr,
|
||||
di: int,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""从快照重建第 di 个默认值常量 IR(委托到 gen._build_const_from_snapshot)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._build_const_from_snapshot(pool, mod, gd_entry, di, trans, builder)
|
||||
return None
|
||||
def find_func_entry_in_table(funcs: HandlesExprCall.FuncEntry | t.CPtr,
|
||||
func_count: int,
|
||||
name: str) -> HandlesExprCall.FuncEntry | t.CPtr:
|
||||
"""在函数表中按名称查找,返回完整 HandlesExprCall.FuncEntry 或 None"""
|
||||
if name is None or funcs is None:
|
||||
return None
|
||||
entry_size: t.CSizeT = HandlesExprCall.FuncEntry.__sizeof__()
|
||||
i: int = 0
|
||||
while i < func_count:
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(funcs) + i * entry_size
|
||||
entry: HandlesExprCall.FuncEntry | t.CPtr = (HandlesExprCall.FuncEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
if entry.Name is not None:
|
||||
if string.strcmp(entry.Name, name) == 0:
|
||||
return entry
|
||||
i += 1
|
||||
return None
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.CallGenLeafKit as CallGenLeafKit
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import sys
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.StubMerger as StubMerger
|
||||
|
||||
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
|
||||
# ============================================================
|
||||
# ExprCallTable - HandlesExprCall 拆分(阶段 E):ExprCallTable
|
||||
#
|
||||
# 直接移动模式:委托函数迁至此模块,原 HandlesExprCall.vp 仅
|
||||
# 保留 _g_gen/常量/类;调用方经本模块前缀访问。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# 初始化函数表
|
||||
# ============================================================
|
||||
def init_func_table(pool: memhub.MemBuddy | t.CPtr,
|
||||
max_count: int) -> GenTypes.FuncEntry | t.CPtr:
|
||||
"""分配并清零函数表数组(委托到 gen.init_func_table)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenLeafKit.init_func_table(pool, max_count)
|
||||
return None
|
||||
# ============================================================
|
||||
# 查找函数
|
||||
# ============================================================
|
||||
def find_func_in_table(funcs: GenTypes.FuncEntry | t.CPtr,
|
||||
func_count: int,
|
||||
name: str) -> llvmlite.Function | t.CPtr:
|
||||
"""在函数表中按名称查找,返回 Function 指针或 None(委托到 gen.find_func_in_table)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenLeafKit.find_func_in_table(funcs, func_count, name)
|
||||
return None
|
||||
# ============================================================
|
||||
# 添加函数到函数表
|
||||
# ============================================================
|
||||
def add_func_to_table(funcs: GenTypes.FuncEntry | t.CPtr,
|
||||
func_count: int,
|
||||
name: str,
|
||||
func: llvmlite.Function | t.CPtr,
|
||||
max_count: int,
|
||||
defaults: t.CVoid | t.CPtr = None,
|
||||
default_count: int = 0,
|
||||
param_count: int = 0,
|
||||
pool: memhub.MemBuddy | t.CPtr = None) -> int:
|
||||
"""添加函数到函数表,返回 0 成功(委托到 gen.add_func_to_table)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenLeafKit.add_func_to_table(funcs, func_count, name, func, max_count,
|
||||
defaults, default_count, param_count, pool)
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# 全局函数注册表(跨模块函数查找)
|
||||
#
|
||||
# 所有模块翻译的函数都会注册到此表(通过 add_func_to_table 自动注册)。
|
||||
# 主要用途: vtable 初始化时查找跨模块继承方法的 Function 对象,
|
||||
# 以获取函数类型信息构造 bitcast 字符串。
|
||||
# ============================================================
|
||||
GLOBAL_FUNC_MAX: t.CDefine = 8192
|
||||
def _init_global_func_table() -> int:
|
||||
"""初始化全局函数表(用 stdlib.malloc 分配,生命周期=整个程序)(委托到 gen._init_global_func_table)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenLeafKit._init_global_func_table()
|
||||
return 0
|
||||
# _build_func_type_str — 从 Function 对象生成函数类型文本(stdlib 存储)
|
||||
#
|
||||
# 格式: ret_ty(param1_ty, param2_ty, ...),与 vtable bitcast 需要一致。
|
||||
# 用 stdlib.malloc 分配返回,跨文件永久存活(1b reset 不回收)。
|
||||
# 返回 None 表示失败。
|
||||
def _build_func_type_str(pool: memhub.MemBuddy | t.CPtr,
|
||||
func: llvmlite.Function | t.CPtr) -> str:
|
||||
"""生成函数类型文本(stdlib 分配)(委托到 gen._build_func_type_str)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenLeafKit._build_func_type_str(pool, func)
|
||||
return None
|
||||
def _register_global_func(name: str, func: llvmlite.Function | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr = None) -> int:
|
||||
"""注册函数到全局表(已存在则跳过),返回 0 成功(委托到 gen._register_global_func)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenLeafKit._register_global_func(name, func, pool)
|
||||
return 0
|
||||
def update_global_func_typestr(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str,
|
||||
func: llvmlite.Function | t.CPtr) -> int:
|
||||
"""更新全局函数表的 TypeStr(在函数参数全部添加完成后调用)(委托到 gen.update_global_func_typestr)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenLeafKit.update_global_func_typestr(pool, name, func)
|
||||
return 0
|
||||
def find_func_global(name: str) -> llvmlite.Function | t.CPtr:
|
||||
"""在全局函数表中按名称查找,返回 Function 指针或 None(委托到 gen.find_func_global)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenLeafKit.find_func_global(name)
|
||||
return None
|
||||
def find_func_entry_global(name: str) -> GenTypes.FuncEntry | t.CPtr:
|
||||
"""在全局函数表中按名称查找,返回完整 GenTypes.FuncEntry(含 TypeStr)或 None(委托到 gen.find_func_entry_global)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenLeafKit.find_func_entry_global(name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局默认参数注册表(跨模块默认参数填充)
|
||||
#
|
||||
# 独立于 _global_funcs,因为 _register_global_func 可能在
|
||||
# add_func_to_table 之前被调用(如 stub 注入),此时 defaults 还不可用。
|
||||
# ============================================================
|
||||
GLOBAL_DEFAULTS_MAX: t.CDefine = 4096
|
||||
def _init_global_defaults_table() -> int:
|
||||
"""初始化全局默认参数表(委托到 gen._init_global_defaults_table)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenLeafKit._init_global_defaults_table()
|
||||
return 0
|
||||
def _register_global_defaults(name: str,
|
||||
defaults: t.CVoid | t.CPtr,
|
||||
default_count: int,
|
||||
param_count: int) -> int:
|
||||
"""注册函数默认参数到全局表,返回 0 成功(委托到 gen._register_global_defaults)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenLeafKit._register_global_defaults(name, defaults, default_count, param_count)
|
||||
return 0
|
||||
def find_func_defaults(name: str) -> GenTypes.FuncDefaultsEntry | t.CPtr:
|
||||
"""按函数名查找默认参数信息,返回 GenTypes.FuncDefaultsEntry 或 None(委托到 gen.find_func_defaults)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenLeafKit.find_func_defaults(name)
|
||||
return None
|
||||
# _build_const_from_snapshot — 从常量快照重建常量 IR 值
|
||||
#
|
||||
# 用于跨模块默认参数填充:gd_entry.Defaults(pool 内 AST)可能已被 reset 回收,
|
||||
# 改用注册时提取的 stdlib 常量快照(ConstKinds/ConstInts/ConstStrs)重建常量 IR。
|
||||
# 返回 llvmlite.Value*,失败返回 None。
|
||||
def _build_const_from_snapshot(pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
gd_entry: GenTypes.FuncDefaultsEntry | t.CPtr,
|
||||
di: int,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""从快照重建第 di 个默认值常量 IR(委托到 gen._build_const_from_snapshot)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.CallGenLeafKit._build_const_from_snapshot(pool, mod, gd_entry, di, trans, builder)
|
||||
return None
|
||||
def find_func_entry_in_table(funcs: GenTypes.FuncEntry | t.CPtr,
|
||||
func_count: int,
|
||||
name: str) -> GenTypes.FuncEntry | t.CPtr:
|
||||
"""在函数表中按名称查找,返回完整 GenTypes.FuncEntry 或 None"""
|
||||
if name is None or funcs is None:
|
||||
return None
|
||||
entry_size: t.CSizeT = GenTypes.FuncEntry.__sizeof__()
|
||||
i: int = 0
|
||||
while i < func_count:
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(funcs) + i * entry_size
|
||||
entry: GenTypes.FuncEntry | t.CPtr = (GenTypes.FuncEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
if entry.Name is not None:
|
||||
if string.strcmp(entry.Name, name) == 0:
|
||||
return entry
|
||||
i += 1
|
||||
return None
|
||||
@@ -1,18 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ForHandleBase - HandlesFor 拆分(迁移完成,仅保留 _g_gen 单例)
|
||||
#
|
||||
# P6 机械化迁移:ForHandleBase 全部方法(_extract_tuple_names/
|
||||
# _seq_kind/_build_seq_loop)→ StmtGenCifMixin 方法。
|
||||
# main/BuildPipeline 仍注入 _g_gen,不可删。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
@@ -1,20 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ForHandleIter - HandlesFor 拆分(迁移完成,仅保留 _g_gen 单例)
|
||||
#
|
||||
# P6 机械化迁移:ForHandleIter 全部方法(_handle_ptr_iter/
|
||||
# _handle_array_iter/_handle_list_literal_iter/_handle_list_iter/
|
||||
# _handle_dict_iter/_handle_oop_iter/_handle_enumerate_iter/
|
||||
# _handle_zip_iter)→ StmtGenCifMixin 方法。
|
||||
# main/BuildPipeline 仍注入 _g_gen,不可删。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
@@ -1,234 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.ExprCallCall as ExprCallCall
|
||||
import lib.core.Handles.ExprCallCtor as ExprCallCtor
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesAnnAssign - AnnAssign 语句处理(迁移完成,保留跨 Mixin 委托壳)
|
||||
#
|
||||
# P6 机械化迁移:AnnAssignHandle 类 → AssignGenMixin.translate_annassign /
|
||||
# translate_annassign_prescan。分派中枢(StmtGenMixin/StmtGenDeclMixin)经
|
||||
# 本壳跨链调用(Viper @t.NoVTable 静态绑定下跨 Mixin self. 调用 mangle
|
||||
# 失败,须经模块级委托壳桥回 gen 单例)。迁移收尾后统一删除。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# is_cdefine_annotation - 检测注解是否为 t.CDefine(模块级函数)
|
||||
#
|
||||
# 支持两种形式:
|
||||
# 1. Attribute(Name('t'), 'CDefine')
|
||||
# 2. BinOp(... | Attribute(Name('t'), 'CDefine'))(联合注解)
|
||||
# ============================================================
|
||||
def is_cdefine_annotation(annot: ast.AST | t.CPtr) -> int:
|
||||
"""检测注解是否为 t.CDefine,返回 1 表示是,0 表示否(委托到 gen.is_cdefine_annotation)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_cdefine_annotation(annot)
|
||||
return 0
|
||||
|
||||
|
||||
def is_ctypedef_annotation(annot: ast.AST | t.CPtr) -> int:
|
||||
"""检测注解是否为 t.CTypedef,返回 1 表示是,0 表示否(委托到 gen._is_ctypedef_annotation)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._is_ctypedef_annotation(annot)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# extract_cdefine_int_value - 从 AnnAssign.value 提取整数常量(模块级函数)
|
||||
#
|
||||
# 支持的表达式形式:
|
||||
# 1. Constant(INT) — 如 0x0002, 42
|
||||
# 2. BinOp(BitOr/BitAnd) — 如 FOREGROUND_RED | FOREGROUND_GREEN
|
||||
# 3. Name — 引用已注册的 CDefine 常量
|
||||
# 4. Call — 如 t.CUnsignedLong(-11) → 取第一个参数
|
||||
# 5. UnaryOp(USub/UAdd/Invert) — 如 -11
|
||||
# ============================================================
|
||||
def extract_cdefine_int_value(val_node: ast.AST | t.CPtr) -> t.CInt64T:
|
||||
"""从值节点提取整数常量(支持 Constant/BinOp/Name/Call/UnaryOp,委托到 gen.extract_cdefine_int_value)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.extract_cdefine_int_value(val_node)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _register_cdefine_from_value - 注册 CDefine 常量(浮点/整数自动识别)
|
||||
#
|
||||
# 浮点字面量(如 vipermath 的 U_M_PI: t.CDefine = 3.14159...)走
|
||||
# register_cdefine_double,否则 translate_value 查表得 0 生成
|
||||
# ret i32 0(llc 报错 "value doesn't match function result type")。
|
||||
# ============================================================
|
||||
def _register_cdefine_from_value(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, val_node: ast.AST | t.CPtr) -> None:
|
||||
"""注册 CDefine 常量(浮点字面量 → register_cdefine_double,否则整数,委托到 gen._register_cdefine_from_value)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g._register_cdefine_from_value(pool, name, val_node)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 源文件重读恢复 CDefine 浮点值
|
||||
#
|
||||
# 背景:AST 节点的 float_val/str_val 字段可能被 pool 分配操作覆写
|
||||
# (MemBuddy 内存冲突),导致注册的浮点 CDefine 值错误(llc ret i32 0)。
|
||||
# 本函数直接读源文件找 "NAME: t.CDefine = value" 行,atof 解析 value——
|
||||
# 源文件文本不受 pool 影响,是最可靠的恢复路径。
|
||||
# 原模块级 _g_recover_found 全局已迁移为 gen 字段(RecoverFound)。
|
||||
# ============================================================
|
||||
|
||||
|
||||
def _recover_found() -> int:
|
||||
"""检查最近一次 _recover_cdefine_float 是否成功(委托到 gen._recover_found)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._recover_found()
|
||||
return 0
|
||||
|
||||
|
||||
def _recover_cdefine_float(name: str, out: t.CDouble | t.CPtr) -> int:
|
||||
"""从当前模块源文件恢复浮点 CDefine 值,写入 out[0],成功返回 1
|
||||
|
||||
用输出参数传递 double,避免 TPV 跨模块 double 返回值传递 bug。
|
||||
(委托到 gen._recover_cdefine_float)
|
||||
"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._recover_cdefine_float(name, out)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _annotation_contains_name - 递归检查注解中是否包含指定名称
|
||||
#
|
||||
# 支持 BinOp(BitOr) 递归,同时检查 Attribute.attr 和 Name.id。
|
||||
# ============================================================
|
||||
def _annotation_contains_name(annot: ast.AST | t.CPtr, name: str) -> int:
|
||||
"""递归检查注解中是否包含指定名称,返回 1=包含 / 0=不包含(委托到 gen._annotation_contains_name)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._annotation_contains_name(annot, name)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _is_ptr_element_annotation - 检查注解是否为 bytes|t.CPtr 或 str|t.CPtr
|
||||
#
|
||||
# 返回 1=是(下标按 8 字节步长, i8** 语义), 0=否(下标按 1 字节步长, i8* 语义)
|
||||
#
|
||||
# 规则:
|
||||
# bytes|t.CPtr / str|t.CPtr → i8**(8 字节步长)→ 返回 1
|
||||
# t.CChar|t.CPtr / t.CInt8T|t.CPtr → i8*(1 字节步长)→ 返回 0
|
||||
# 纯 bytes / str → i8*(1 字节步长)→ 返回 0
|
||||
#
|
||||
# 注: 注解中的 "|" 是"和"的意思(组合类型),非右值中的位或运算
|
||||
# ============================================================
|
||||
def _is_ptr_element_annotation(annot: ast.AST | t.CPtr) -> int:
|
||||
"""检查注解是否为 bytes|t.CPtr 或 str|t.CPtr 形式(委托到 gen._is_ptr_element_annotation)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._is_ptr_element_annotation(annot)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _infer_static_array_ty_from_literal - 单参 CArray + 列表字面量 → 静态数组
|
||||
#
|
||||
# 单参 t.CArray[elem_ty] 解析为 Ptr(elem_ty),但当 RHS 是列表字面量时,
|
||||
# 按 TPC 语义应推断为 [len x elem_ty](对齐 TPC ParseListAnnotation):
|
||||
# 避免误走动态 list 构造(_find_pool_var 兜底引用外部 @_mbuddy → 链接期
|
||||
# undefined)。PreScan 与 Handle 都调用(PreScan 预创建 alloca 的类型必须
|
||||
# 与 Handle 一致,否则 get_or_create_sym 复用旧 alloca 使推断失效)。
|
||||
# 真实实现已迁移至 gen._infer_static_array_ty_from_literal,本壳保留供
|
||||
# ClassGenDef(Gen 侧字段类型推断)等跨模块调用方使用。
|
||||
# ============================================================
|
||||
def _infer_static_array_ty_from_literal(pool: memhub.MemBuddy | t.CPtr,
|
||||
annot: ast.AST | t.CPtr,
|
||||
value: ast.AST | t.CPtr,
|
||||
resolved_ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""单参 CArray + 列表字面量 → Array(elem_ty, len);否则返回原类型(委托到 gen._infer_static_array_ty_from_literal)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._infer_static_array_ty_from_literal(pool, annot, value, resolved_ty)
|
||||
return resolved_ty
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _init_global_array_from_list — 从列表字面量初始化全局数组
|
||||
#
|
||||
# 为每个元素生成 GEP + store 指令,将值存入全局数组的对应位置。
|
||||
# 适用于模块级 t.CArray[elem_ty, count] = [v0, v1, ...] 的初始化。
|
||||
#
|
||||
# Args:
|
||||
# builder: IRBuilder
|
||||
# pool: 编译器内存池
|
||||
# mod: LLVMModule
|
||||
# array_alloca: 全局数组变量的 Value 引用(类型为 [N x elem_ty]*)
|
||||
# list_node: ast.List 节点
|
||||
# trans: Translator 对象
|
||||
#
|
||||
# Returns:
|
||||
# 0 成功,1 失败
|
||||
# ============================================================
|
||||
def _init_global_array_from_list(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
array_alloca: llvmlite.Value | t.CPtr,
|
||||
list_node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> int:
|
||||
"""从列表字面量初始化全局数组,为每个元素生成 GEP + store(委托到 gen._init_global_array_from_list)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._init_global_array_from_list(builder, pool, mod, array_alloca, list_node, trans)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# translate_annassign - AnnAssign 语句翻译(委托到 gen.translate_annassign)
|
||||
# ============================================================
|
||||
def translate_annassign(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 AnnAssign 语句,返回新增变量数(委托到 gen.translate_annassign)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_annassign(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# translate_annassign_prescan - AnnAssign 预扫描(委托到 gen.translate_annassign_prescan)
|
||||
# ============================================================
|
||||
def translate_annassign_prescan(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""预扫描 AnnAssign,提前创建 alloca 到 entry block 顶部(委托到 gen.translate_annassign_prescan)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_annassign_prescan(trans, node)
|
||||
return 0
|
||||
@@ -1,51 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.StubMergerStore as StubMergerStore
|
||||
import lib.core.Handles.ExprCallBase as ExprCallBase
|
||||
import lib.core.Handles.ExprCallCall as ExprCallCall
|
||||
import lib.core.Handles.ExprCallCtor as ExprCallCtor
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesAssign - Assign 语句处理(迁移完成,保留跨 Mixin 委托壳)
|
||||
#
|
||||
# P6 机械化迁移:AssignHandle 类 → AssignGenMixin.translate_assign
|
||||
# (lib.core.Gen.AssignGenMixin)。分派中枢(StmtGenMixin)经本壳跨链
|
||||
# 调用(Viper @t.NoVTable 静态绑定下跨 Mixin self. 调用 mangle 失败,
|
||||
# 须经模块级委托壳桥回 gen 单例)。迁移收尾后统一删除。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# translate_assign - Assign 语句翻译(委托到 gen.translate_assign)
|
||||
# ============================================================
|
||||
def translate_assign(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译赋值语句,返回新增变量数(委托到 gen.translate_assign)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_assign(trans, node)
|
||||
return 0
|
||||
@@ -1,34 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import memhub
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesAugAssign - 增强赋值语句处理(迁移完成,保留跨 Mixin 委托壳)
|
||||
#
|
||||
# P6 机械化迁移:AugAssignHandle 类 → AssignGenMixin.translate_augassign。
|
||||
# 分派中枢(StmtGenMixin)经本壳跨链调用(Viper @t.NoVTable 静态绑定下
|
||||
# 跨 Mixin self. 调用 mangle 失败,须经模块级委托壳桥回 gen 单例)。
|
||||
# 迁移收尾(编译器缺陷修复)后统一删除。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# translate_augassign - 增强赋值翻译(委托到 gen.translate_augassign)
|
||||
# ============================================================
|
||||
def translate_augassign(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译增强赋值语句,返回新增变量数(委托到 gen.translate_augassign)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_augassign(trans, node)
|
||||
return 0
|
||||
@@ -1,168 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import viperlib
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesBody - 语句分派(P6 对象化后的委托层)
|
||||
#
|
||||
# 全部模块级函数已迁移为 lib.core.Gen.StmtGenMixin 的方法,本模块
|
||||
# 保留同名模块级函数作为"一行委托":延迟 import Gen 取全局单例
|
||||
# (BuildPipeline/main 创建后 set_global_gen 注册),再调用 gen 的
|
||||
# 对应方法。签名与旧函数完全一致,调用方零改动。
|
||||
#
|
||||
# 所有语句类型通过 trans.XxxH.Handle(node) 分派到对应 Handle。
|
||||
# 对应 TransPyC BodyHandle.HandleBodyLlvm 的 isinstance 分派。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesStruct 模式)
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 语句翻译分派
|
||||
# ============================================================
|
||||
def translate_stmt(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译单条语句,返回新增的变量数(委托到 gen.translate_stmt)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_stmt(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译 Delete 语句: del obj.attr
|
||||
#
|
||||
# 支持 property deleter: 当目标 attr 是 @x.deleter 方法时,
|
||||
# 生成 call Class.attr$del(obj)。其余目标暂不生成代码。
|
||||
# ============================================================
|
||||
def translate_delete(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 del 语句,返回 0(委托到 gen.translate_delete)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_delete(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译 Global 语句: global x, y
|
||||
#
|
||||
# 将 names 中的变量名加入 _global_names 集合
|
||||
# ============================================================
|
||||
def translate_global(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 global 语句:记录 global 变量名(委托到 gen.translate_global)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_global(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译 Nonlocal 语句: nonlocal x, y
|
||||
#
|
||||
# 将 names 中的变量名加入 _nonlocal_names 集合
|
||||
# ============================================================
|
||||
def translate_nonlocal(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 nonlocal 语句:记录 nonlocal 变量名及其类型(委托到 gen.translate_nonlocal)
|
||||
|
||||
类型信息通过查找父作用域的 alloca 获取(用于 env 指针数组方案的类型恢复)。
|
||||
"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_nonlocal(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译表达式语句 Expr(value=Call(...))
|
||||
# ============================================================
|
||||
def translate_expr_stmt(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译表达式语句(printf 调用等)(委托到 gen.translate_expr_stmt)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_expr_stmt(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 预扫描:为局部变量提前创建 alloca
|
||||
# ============================================================
|
||||
def pre_scan_allocas(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""预扫描语句中的 AnnAssign,提前创建 alloca(委托到 gen.pre_scan_allocas)
|
||||
|
||||
返回新增的变量数
|
||||
"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.pre_scan_allocas(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 预扫描:Global/Nonlocal 声明(Python 作用域语义)
|
||||
#
|
||||
# Python 中 global/nonlocal 声明对整个函数作用域生效,与声明
|
||||
# 位置无关。必须在翻译任何赋值之前注册 global/nonlocal 名称,
|
||||
# 否则 global 声明前的赋值会错误创建局部变量遮蔽全局。
|
||||
# ============================================================
|
||||
def pre_scan_scope_decls(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""预扫描 Global/Nonlocal 声明,提前注册作用域名称(委托到 gen.pre_scan_scope_decls)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.pre_scan_scope_decls(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译 break 语句
|
||||
# ============================================================
|
||||
def translate_break(trans: HT.Translator | t.CPtr) -> int:
|
||||
"""翻译 break 语句:跳转到循环 end 块(委托到 gen.translate_break)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_break(trans)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译 continue 语句
|
||||
# ============================================================
|
||||
def translate_continue(trans: HT.Translator | t.CPtr) -> int:
|
||||
"""翻译 continue 语句:跳转到循环 cond/incr 块(委托到 gen.translate_continue)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_continue(trans)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 获取语句类型名(调试用)
|
||||
# ============================================================
|
||||
def get_stmt_kind_name(node: ast.AST | t.CPtr) -> str:
|
||||
"""获取语句类型名(委托到 gen.get_stmt_kind_name)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_stmt_kind_name(node)
|
||||
return None
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,166 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import llvmlite
|
||||
import stdio
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesEnum - 枚举类型注册和成员查找(P6 对象化后的委托层)
|
||||
#
|
||||
# 全部模块级函数已迁移为 lib.core.Gen.StmtGenMixin 的方法
|
||||
# (模块级全局 _enum_table/_enum_count → gen 实例字段
|
||||
# EnumTable/EnumCount),本模块保留同名模块级函数作为"一行委托":
|
||||
# 延迟 import Gen 取全局单例(BuildPipeline/main 创建后
|
||||
# set_global_gen 注册),再调用 gen 的对应方法。签名与旧函数
|
||||
# 完全一致,调用方零改动。
|
||||
#
|
||||
# EnumEntry/EnumMember 类型保留在本模块(gen 字段类型引用)。
|
||||
# 管理 t.CEnum 派生类的成员信息:
|
||||
# - 枚举名 → EnumEntry(基准类型 + 成员表)
|
||||
# - 成员名 → EnumMember(值、类型)
|
||||
#
|
||||
# 使用全局数组存储,线性查找(枚举数量通常很少)
|
||||
# ============================================================
|
||||
|
||||
ENUM_MAX: t.CDefine = 64
|
||||
ENUM_MEMBER_MAX: t.CDefine = 128
|
||||
|
||||
|
||||
# ============================================================
|
||||
# EnumMember - 枚举成员条目
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class EnumMember:
|
||||
Name: str # 成员名(字符串)
|
||||
Value: t.CInt64T # 成员的整数值
|
||||
Ty: llvmlite.LLVMType | t.CPtr # 成员的 LLVM 类型(用于混用类型场景)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# EnumEntry - 枚举类型条目
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class EnumEntry:
|
||||
Name: str # 枚举类名
|
||||
BaseTy: llvmlite.LLVMType | t.CPtr # 基准类型(所有成员类型中最大的)
|
||||
MemberCount: int # 成员数量
|
||||
Members: EnumMember | t.CPtr # 成员数组(ENUM_MEMBER_MAX 个槽位)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesStruct 模式)
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# init_enum_table — 初始化枚举注册表
|
||||
# ============================================================
|
||||
def init_enum_table(pool: memhub.MemBuddy | t.CPtr) -> int:
|
||||
"""初始化枚举注册表,返回 1 成功(委托到 gen.init_enum_table)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.init_enum_table(pool)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _get_enum_entry — 获取第 i 个 EnumEntry 槽位
|
||||
# ============================================================
|
||||
def _get_enum_entry(i: int) -> EnumEntry | t.CPtr:
|
||||
"""获取第 i 个枚举条目(委托到 gen._get_enum_entry)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._get_enum_entry(i)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _get_enum_member — 获取枚举中第 i 个 EnumMember 槽位
|
||||
# ============================================================
|
||||
def _get_enum_member(enum_entry: EnumEntry | t.CPtr, i: int) -> EnumMember | t.CPtr:
|
||||
"""获取枚举中第 i 个成员条目(委托到 gen._get_enum_member)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._get_enum_member(enum_entry, i)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# register_enum — 注册枚举类型
|
||||
#
|
||||
# 返回 EnumEntry 指针,可用于添加成员
|
||||
# ============================================================
|
||||
def register_enum(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str,
|
||||
base_ty: llvmlite.LLVMType | t.CPtr) -> EnumEntry | t.CPtr:
|
||||
"""注册枚举类型,返回 EnumEntry 指针(委托到 gen.register_enum)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.register_enum(pool, name, base_ty)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# add_enum_member — 向枚举添加成员
|
||||
# ============================================================
|
||||
def add_enum_member(pool: memhub.MemBuddy | t.CPtr,
|
||||
enum_entry: EnumEntry | t.CPtr,
|
||||
member_name: str,
|
||||
member_val: t.CInt64T,
|
||||
member_ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""向枚举添加成员,返回成员索引(-1 失败,委托到 gen.add_enum_member)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.add_enum_member(pool, enum_entry, member_name, member_val, member_ty)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# find_enum — 按枚举类名查找
|
||||
# ============================================================
|
||||
def find_enum(name: str) -> EnumEntry | t.CPtr:
|
||||
"""按枚举类名查找,返回 EnumEntry 或 None(委托到 gen.find_enum)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.find_enum(name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# lookup_enum_member — 按枚举类名和成员名查找
|
||||
# ============================================================
|
||||
def lookup_enum_member(enum_name: str,
|
||||
member_name: str) -> EnumMember | t.CPtr:
|
||||
"""按枚举类名和成员名查找,返回 EnumMember 或 None(委托到 gen.lookup_enum_member)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.lookup_enum_member(enum_name, member_name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# is_enum_class — 检查类名是否为已注册枚举
|
||||
# ============================================================
|
||||
def is_enum_class(name: str) -> int:
|
||||
"""检查类名是否为已注册枚举,返回 1=是 / 0=否(委托到 gen.is_enum_class)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_enum_class(name)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# get_enum_base_type — 按枚举类名获取基准类型
|
||||
# ============================================================
|
||||
def get_enum_base_type(enum_name: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""按枚举类名获取基准类型(委托到 gen.get_enum_base_type)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_enum_base_type(enum_name)
|
||||
return None
|
||||
+953
-951
File diff suppressed because it is too large.
Load diff
@@ -1,143 +1,137 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import sys
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.Handles.ExprCallCall as ExprCallCall
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 本地常量(阶段 E 拆分时随函数块误删,补回;子模块经 HandlesExprCall.常量 引用)
|
||||
# ============================================================
|
||||
_CEXPORT_MAX: t.CDefine = 256
|
||||
ASM_MAX_OPERANDS: t.CDefine = 16
|
||||
ASM_TEXT_BUF_SIZE: t.CDefine = 2048
|
||||
ASM_CONST_BUF_SIZE: t.CDefine = 512
|
||||
ASM_ARGS_BUF_SIZE: t.CDefine = 512
|
||||
ASM_LINE_BUF_SIZE: t.CDefine = 4096
|
||||
LLVMIR_MAX_OPS: t.CDefine = 16
|
||||
LLVMIR_TEMPLATE_BUF: t.CDefine = 512
|
||||
MAX_CLOSURE_NAMES: t.CDefine = 128
|
||||
MAX_FUNC_PTR_SIGS: t.CDefine = 64
|
||||
GLOBAL_FUNC_MAX: t.CDefine = 8192
|
||||
GLOBAL_DEFAULTS_MAX: t.CDefine = 4096
|
||||
|
||||
|
||||
|
||||
# ============================================================
|
||||
# AsmOperand - 内联汇编操作数条目
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class AsmOperand:
|
||||
"""内联汇编操作数条目"""
|
||||
Value: llvmlite.Value | t.CPtr # 输入值或输出 alloca
|
||||
Constraint: str # 约束字符串 (如 "r", "=r")
|
||||
IsOutput: int # 1=输出, 0=输入
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# ============================================================
|
||||
# FuncEntry 结构体(用于函数表)
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class FuncEntry:
|
||||
"""函数表条目"""
|
||||
Name: str
|
||||
Func: llvmlite.Function | t.CPtr
|
||||
Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr]),None=无默认值
|
||||
DefaultCount: int # 默认值数量
|
||||
ParamCount: int # 形参数量(不含 self)
|
||||
# TypeStr: 函数类型文本(stdlib 深拷贝,跨文件安全)
|
||||
# 1b 每文件 reset_to(mark1) 回收 pool 内 Function 对象后,
|
||||
# vtable 生成 find_func_global 读类型改用此文本,避免悬空。
|
||||
TypeStr: str
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class FuncDefaultsEntry:
|
||||
"""默认参数表条目"""
|
||||
Name: str
|
||||
Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr])(pool 内,可能被 reset)
|
||||
DefaultCount: int
|
||||
ParamCount: int # 形参数量(不含 self)
|
||||
# 常量快照(stdlib 分配,跨文件永久存活):
|
||||
# 注册时提取每个默认值 Constant 的值,跨模块调用时优先用快照重建常量 IR,
|
||||
# 避免读取已被 1b reset_to(mark1) 回收的 pool 内 AST。
|
||||
ConstKinds: t.CInt | t.CPtr # const_kind 数组(DefaultCount 个 i32)
|
||||
ConstInts: t.CInt64T | t.CPtr # int_val 数组(DefaultCount 个 i64)
|
||||
ConstStrs: t.CSizeT | t.CPtr # str_val 指针数组(DefaultCount 个 i8*)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ExprCallHandle - 函数调用处理器(Mixin 继承模式)
|
||||
#
|
||||
# HandleCall / HandlePrintfCall 提供 trans 接口
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class ExprCallHandle(HandlesBase.Mixin):
|
||||
"""函数调用处理器:继承 Mixin 获得 Trans 回指针"""
|
||||
|
||||
def __init__(self, trans: HT.Translator | t.CPtr):
|
||||
self.Trans = trans
|
||||
|
||||
# ============================================================
|
||||
# HandleCall - 翻译函数调用,返回 call 结果 Value
|
||||
# ============================================================
|
||||
def HandleCall(self, node: ast.AST | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译函数调用,从 self.Trans 获取共享状态"""
|
||||
return ExprCallCall.translate_call(
|
||||
self.Trans.Pool, self.Trans._cur_builder, self.Trans.Module,
|
||||
node,
|
||||
self.Trans._funcs, self.Trans._func_count, self.Trans)
|
||||
|
||||
# ============================================================
|
||||
# HandlePrintfCall - 翻译 printf 调用
|
||||
# ============================================================
|
||||
def HandlePrintfCall(self, cl: ast.Call | t.CPtr):
|
||||
"""翻译 printf 调用,从 self.Trans 获取共享状态"""
|
||||
ExprCallCall.translate_printf_call(
|
||||
self.Trans.Pool, self.Trans._cur_builder, self.Trans.Module,
|
||||
cl, self.Trans)
|
||||
|
||||
# ============================================================
|
||||
# HandlePrintCall - 翻译 print 调用
|
||||
# ============================================================
|
||||
def HandlePrintCall(self, cl: ast.Call | t.CPtr):
|
||||
"""翻译 print 调用(类型感知格式化 + 默认换行)"""
|
||||
ExprCallCall.translate_print_call(
|
||||
self.Trans.Pool, self.Trans._cur_builder, self.Trans.Module,
|
||||
cl, self.Trans)
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import sys
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 本地常量(阶段 E 拆分时随函数块误删,补回;子模块经 HandlesExprCall.常量 引用)
|
||||
# ============================================================
|
||||
_CEXPORT_MAX: t.CDefine = 256
|
||||
ASM_MAX_OPERANDS: t.CDefine = 16
|
||||
ASM_TEXT_BUF_SIZE: t.CDefine = 2048
|
||||
ASM_CONST_BUF_SIZE: t.CDefine = 512
|
||||
ASM_ARGS_BUF_SIZE: t.CDefine = 512
|
||||
ASM_LINE_BUF_SIZE: t.CDefine = 4096
|
||||
LLVMIR_MAX_OPS: t.CDefine = 16
|
||||
LLVMIR_TEMPLATE_BUF: t.CDefine = 512
|
||||
MAX_CLOSURE_NAMES: t.CDefine = 128
|
||||
MAX_FUNC_PTR_SIGS: t.CDefine = 64
|
||||
GLOBAL_FUNC_MAX: t.CDefine = 8192
|
||||
GLOBAL_DEFAULTS_MAX: t.CDefine = 4096
|
||||
|
||||
|
||||
|
||||
# ============================================================
|
||||
# AsmOperand - 内联汇编操作数条目
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class AsmOperand:
|
||||
"""内联汇编操作数条目"""
|
||||
Value: llvmlite.Value | t.CPtr # 输入值或输出 alloca
|
||||
Constraint: str # 约束字符串 (如 "r", "=r")
|
||||
IsOutput: int # 1=输出, 0=输入
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# ============================================================
|
||||
# FuncEntry 结构体(用于函数表)
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class FuncEntry:
|
||||
"""函数表条目"""
|
||||
Name: str
|
||||
Func: llvmlite.Function | t.CPtr
|
||||
Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr]),None=无默认值
|
||||
DefaultCount: int # 默认值数量
|
||||
ParamCount: int # 形参数量(不含 self)
|
||||
# TypeStr: 函数类型文本(stdlib 深拷贝,跨文件安全)
|
||||
# 1b 每文件 reset_to(mark1) 回收 pool 内 Function 对象后,
|
||||
# vtable 生成 find_func_global 读类型改用此文本,避免悬空。
|
||||
TypeStr: str
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class FuncDefaultsEntry:
|
||||
"""默认参数表条目"""
|
||||
Name: str
|
||||
Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr])(pool 内,可能被 reset)
|
||||
DefaultCount: int
|
||||
ParamCount: int # 形参数量(不含 self)
|
||||
# 常量快照(stdlib 分配,跨文件永久存活):
|
||||
# 注册时提取每个默认值 Constant 的值,跨模块调用时优先用快照重建常量 IR,
|
||||
# 避免读取已被 1b reset_to(mark1) 回收的 pool 内 AST。
|
||||
ConstKinds: t.CInt | t.CPtr # const_kind 数组(DefaultCount 个 i32)
|
||||
ConstInts: t.CInt64T | t.CPtr # int_val 数组(DefaultCount 个 i64)
|
||||
ConstStrs: t.CSizeT | t.CPtr # str_val 指针数组(DefaultCount 个 i8*)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ExprCallHandle - 函数调用处理器(Mixin 继承模式)
|
||||
#
|
||||
# HandleCall / HandlePrintfCall 提供 trans 接口
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class ExprCallHandle(HandlesBase.Mixin):
|
||||
"""函数调用处理器:继承 Mixin 获得 Trans 回指针"""
|
||||
|
||||
def __init__(self, trans: HT.Translator | t.CPtr):
|
||||
self.Trans = trans
|
||||
|
||||
# ============================================================
|
||||
# HandleCall - 翻译函数调用,返回 call 结果 Value
|
||||
# ============================================================
|
||||
def HandleCall(self, node: ast.AST | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译函数调用,从 self.Trans 获取共享状态"""
|
||||
return GenApi.translate_call(
|
||||
self.Trans.Pool, self.Trans._cur_builder, self.Trans.Module,
|
||||
node,
|
||||
self.Trans._funcs, self.Trans._func_count, self.Trans)
|
||||
|
||||
# ============================================================
|
||||
# HandlePrintfCall - 翻译 printf 调用
|
||||
# ============================================================
|
||||
def HandlePrintfCall(self, cl: ast.Call | t.CPtr):
|
||||
"""翻译 printf 调用,从 self.Trans 获取共享状态"""
|
||||
GenApi.translate_printf_call(
|
||||
self.Trans.Pool, self.Trans._cur_builder, self.Trans.Module,
|
||||
cl, self.Trans)
|
||||
|
||||
# ============================================================
|
||||
# HandlePrintCall - 翻译 print 调用
|
||||
# ============================================================
|
||||
def HandlePrintCall(self, cl: ast.Call | t.CPtr):
|
||||
"""翻译 print 调用(类型感知格式化 + 默认换行)"""
|
||||
GenApi.translate_print_call(
|
||||
self.Trans.Pool, self.Trans._cur_builder, self.Trans.Module,
|
||||
cl, self.Trans)
|
||||
@@ -1,116 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
# ============================================================
|
||||
# HandlesExprOps - 二元运算处理(P3 对象化后的委托层)
|
||||
#
|
||||
# 全部函数已迁移为 lib.core.Gen.ExprGenMixin 的方法,本模块保留
|
||||
# 同名模块级函数作为"一行委托":延迟 import Gen 取全局单例
|
||||
# (BuildPipeline/main 创建后 set_global_gen 注册),再调用 gen
|
||||
# 的对应方法。签名与旧函数完全一致,调用方零改动。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 委托函数:延迟 import Gen 取全局单例 → 调 gen 方法
|
||||
# (gen 未注册时正常流程不会发生;有返回值函数返回默认值)
|
||||
# ============================================================
|
||||
|
||||
|
||||
# BinOp 运算符 → dunder 方法名
|
||||
def _binop_to_dunder(op: int) -> str:
|
||||
"""将 BinOp 运算符映射到 dunder 方法名,无映射时返回 None(委托到 gen._binop_to_dunder)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._binop_to_dunder(op)
|
||||
return None
|
||||
|
||||
|
||||
# Compare 运算符 → dunder 方法名
|
||||
def _cmpop_to_dunder(op: int) -> str:
|
||||
"""将 Compare 运算符映射到 dunder 方法名,无映射时返回 None(委托到 gen._cmpop_to_dunder)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._cmpop_to_dunder(op)
|
||||
return None
|
||||
|
||||
|
||||
# UnaryOp 运算符 → dunder 方法名
|
||||
def _unaryop_to_dunder(op: int) -> str:
|
||||
"""将 UnaryOp 运算符映射到 dunder 方法名,无映射时返回 None(委托到 gen._unaryop_to_dunder)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._unaryop_to_dunder(op)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# try_operator_overload - 尝试运算符重载
|
||||
#
|
||||
# 检查 lhs 是否为结构体指针,并在该类(含继承链)中查找对应的
|
||||
# dunder 方法。找到则生成方法调用 lhs.__dunder__(rhs),返回
|
||||
# 调用结果;未找到返回 None,调用方回退到原生运算。
|
||||
# ============================================================
|
||||
def try_operator_overload(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
lhs: llvmlite.Value | t.CPtr,
|
||||
rhs: llvmlite.Value | t.CPtr,
|
||||
op: int,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
is_compare: int) -> llvmlite.Value | t.CPtr:
|
||||
"""尝试运算符重载:lhs 是结构体指针时调用 dunder 方法,否则返回 None(委托到 gen.try_operator_overload)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.try_operator_overload(pool, builder, mod, lhs, rhs, op, trans, is_compare)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# try_unary_operator_overload - 尝试一元运算符重载
|
||||
#
|
||||
# 检查 operand 是否为结构体指针,并在该类(含继承链)中查找对应的
|
||||
# dunder 方法(__neg__/__pos__/__invert__)。找到则生成方法调用
|
||||
# operand.__dunder__(),返回调用结果;未找到返回 None,调用方回退到原生运算。
|
||||
# ============================================================
|
||||
def try_unary_operator_overload(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
operand: llvmlite.Value | t.CPtr,
|
||||
op: int,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""尝试一元运算符重载:operand 是结构体指针时调用 dunder 方法,否则返回 None(委托到 gen.try_unary_operator_overload)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.try_unary_operator_overload(pool, builder, mod, operand, op, trans)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译二元运算(自动类型提升)
|
||||
# ============================================================
|
||||
def translate_binop(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译二元运算(自动类型提升)(委托到 gen.translate_binop)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_binop(pool, builder, mod, node, trans)
|
||||
return None
|
||||
@@ -1,55 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import memhub
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesFor - for 循环语句处理(迁移完成,保留跨 Mixin 委托壳)
|
||||
#
|
||||
# P6 机械化迁移:ForHandle/ForHandleBase/ForHandleIter 全部方法 →
|
||||
# StmtGenCifMixin.translate_for 及辅助方法(_handle_ptr_iter/
|
||||
# _handle_array_iter/_handle_list_literal_iter/_handle_list_iter/
|
||||
# _handle_dict_iter/_handle_oop_iter/_handle_enumerate_iter/
|
||||
# _handle_zip_iter/_extract_tuple_names/_seq_kind/_build_seq_loop)。
|
||||
# SEQ_KIND_* 常量保留:StmtGenCifMixin._seq_kind/_build_seq_loop 经
|
||||
# HandlesFor.SEQ_KIND_* 访问。
|
||||
# 分派中枢(StmtGenMixin)经本壳跨链调用(Viper @t.NoVTable 静态绑定下
|
||||
# 跨 Mixin self. 调用 mangle 失败,须经模块级委托壳桥回 gen 单例)。
|
||||
# 迁移收尾(编译器缺陷修复)后统一删除。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# StmtGenCifMixin 方法,避免函数体 import 包模块与类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 序列迭代源类型码(for x in ... / enumerate / zip 迭代源分类)
|
||||
# RANGE: range(start, stop, step)
|
||||
# STR: 字符串(常量或 str 变量)
|
||||
# LIST: list[T] 容器(按 __count__ + __data__ 迭代)
|
||||
# ============================================================
|
||||
SEQ_KIND_RANGE: t.CDefine = 1
|
||||
SEQ_KIND_STR: t.CDefine = 2
|
||||
SEQ_KIND_LIST: t.CDefine = 3
|
||||
|
||||
|
||||
# ============================================================
|
||||
# translate_for - for 循环语句翻译(委托到 gen.translate_for)
|
||||
# ============================================================
|
||||
def translate_for(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 for 循环语句(委托到 gen.translate_for)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_for(trans, node)
|
||||
return 0
|
||||
@@ -1,143 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesBody as HandlesBody
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesFunctions - 函数定义处理(P5-1 对象化后的委托层)
|
||||
#
|
||||
# P5-1 对象化重构(wiki/14-oo-refactor.md):
|
||||
# 全部函数已迁移为 lib.core.Gen.FuncGenMixin 的方法,本模块保留
|
||||
# 同名模块级函数作为"一行委托":延迟 import Gen 取全局单例
|
||||
# (BuildPipeline/main 创建后 set_global_gen 注册),再调用 gen
|
||||
# 的对应方法。签名与旧函数完全一致,调用方零改动。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像)
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# 作用域类型常量(本地副本,避免旧编译器跨模块 CDefine 查找 bug)
|
||||
SCOPE_FUNCTION: t.CDefine = 1
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 委托函数:延迟 import Gen 取全局单例 → 调 gen 方法
|
||||
# (gen 未注册时正常流程不会发生;有返回值函数返回默认值)
|
||||
# ============================================================
|
||||
|
||||
|
||||
def extract_func_attrs(pool: memhub.MemBuddy | t.CPtr,
|
||||
decorator_list: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
imported_modules: str) -> str:
|
||||
"""从 decorator_list 提取 c.Attribute 属性,返回 LLVM IR 属性字符串(委托到 gen.extract_func_attrs)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.extract_func_attrs(pool, decorator_list, imported_modules)
|
||||
return None
|
||||
|
||||
|
||||
def _get_attr_name_from_node(node: ast.AST | t.CPtr) -> str:
|
||||
"""从 AST 节点提取属性名(委托到 gen._get_attr_name_from_node)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._get_attr_name_from_node(node)
|
||||
return None
|
||||
|
||||
|
||||
def _append_llvm_attr(attrs_buf: str, attr_name: str) -> int:
|
||||
"""将属性名映射到 LLVM 属性名并追加到缓冲区(委托到 gen._append_llvm_attr)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._append_llvm_attr(attrs_buf, attr_name)
|
||||
return 0
|
||||
|
||||
|
||||
def _append_str(buf: str, s: str) -> None:
|
||||
"""将字符串追加到 buf 末尾(用 strlen+strcpy 模拟 strcat)(委托到 gen._append_str)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g._append_str(buf, s)
|
||||
|
||||
|
||||
def _mangle_name(trans: HT.Translator | t.CPtr, name: str) -> str:
|
||||
"""为任意名称添加 SHA1 前缀(不做 main/export 检查)(委托到 gen._mangle_name)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._mangle_name(trans, name)
|
||||
return None
|
||||
|
||||
|
||||
def _mangle_name_with_sha1(sha1: str, name: str) -> str:
|
||||
"""用指定 SHA1 为名称添加前缀(不做 main/export 检查)(委托到 gen._mangle_name_with_sha1)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._mangle_name_with_sha1(sha1, name)
|
||||
return None
|
||||
|
||||
|
||||
def _mangle_func_name(trans: HT.Translator | t.CPtr, name: str,
|
||||
has_export: int) -> str:
|
||||
"""为函数名添加 SHA1 前缀(检查 main/export)(委托到 gen._mangle_func_name)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._mangle_func_name(trans, name, has_export)
|
||||
return None
|
||||
|
||||
|
||||
def forward_declare_functions(trans: HT.Translator | t.CPtr,
|
||||
tree: ast.AST | t.CPtr) -> int:
|
||||
"""预扫描所有顶层 FunctionDef,创建前向声明(委托到 gen.forward_declare_functions)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.forward_declare_functions(trans, tree)
|
||||
return 0
|
||||
|
||||
|
||||
def translate_function_def(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译函数定义,返回新增的变量数(通常为 0,函数定义不增加当前作用域变量)(委托到 gen.translate_function_def)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_function_def(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
def translate_nested_function_def(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译嵌套函数定义:提升为顶层函数 + 创建闭包(委托到 gen.translate_nested_function_def)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_nested_function_def(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
def create_function(pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
name: str,
|
||||
args_node: ast.AST | t.CPtr,
|
||||
ret_ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Function | t.CPtr:
|
||||
"""创建 LLVM 函数并添加参数(委托到 gen.create_function)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.create_function(pool, mod, name, args_node, ret_ty)
|
||||
return None
|
||||
@@ -1,42 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import memhub
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesIf - if/elif/else 语句处理(迁移完成,保留跨 Mixin 委托壳)
|
||||
#
|
||||
# P6 机械化迁移:IfHandle 类 → StmtGenCifMixin.translate_if。
|
||||
# CIf 编译期求值(_is_cif_attr/_is_cif_call/_get_platform_macro_value/
|
||||
# _cif_name_value/_cif_attr_value/_cif_eval_node/_evaluate_cif_test 及
|
||||
# 模块级 _g_cif_eval_ok)已迁移为 StmtGenCifMixin 的方法/字段
|
||||
# (CifEvalOk)。
|
||||
# 分派中枢(StmtGenMixin)经本壳跨链调用(Viper @t.NoVTable 静态绑定下
|
||||
# 跨 Mixin self. 调用 mangle 失败,须经模块级委托壳桥回 gen 单例)。
|
||||
# 迁移收尾(编译器缺陷修复)后统一删除。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# StmtGenCifMixin 方法,避免函数体 import 包模块与类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# translate_if - if/elif/else 语句翻译(委托到 gen.translate_if)
|
||||
# ============================================================
|
||||
def translate_if(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 if/elif/else 语句(委托到 gen.translate_if)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_if(trans, node)
|
||||
return 0
|
||||
@@ -1,326 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import viperlib
|
||||
import stdio
|
||||
import sys
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesImports - 导入语句处理(P6-D 对象化后的委托层)
|
||||
#
|
||||
# 管理 _imported_modules 和 _from_imports 字符串
|
||||
# 注意:str = bytes = str = i8*
|
||||
#
|
||||
# P6-D 对象化重构(wiki/14-oo-refactor.md):
|
||||
# 全部模块级函数已迁移为 lib.core.Gen.ImportsGenMixin 的方法
|
||||
# (全局状态 _g_reexport_* 与 _g_current_file 迁入 gen 字段),本模块
|
||||
# 保留同名模块级函数作为"一行委托":延迟 import Gen 取全局单例
|
||||
# (BuildPipeline/main 创建后 set_global_gen 注册),再调用 gen 的
|
||||
# 对应方法。签名与旧函数完全一致,调用方零改动。
|
||||
# ImportsHandle 类与 NewImportsHandle 工厂已删除(P6 机械化迁移:
|
||||
# HandleImport/HandleImportFromModule/HandleImportFromNames → 本模块
|
||||
# 新增的 translate_import/translate_import_from_module/
|
||||
# translate_import_from_names 模块级委托壳,路由到 gen 方法)。
|
||||
# ============================================================
|
||||
|
||||
MAX_REEXPORT: t.CDefine = 512
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# P6-D 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# ImportsGenMixin 方法,避免函数体 import 包模块与 Generator
|
||||
# 类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 委托函数:延迟 import Gen 取全局单例 → 调 gen 方法
|
||||
# (gen 未注册时正常流程不会发生;有返回值函数返回默认值)
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 添加已导入模块名
|
||||
# ============================================================
|
||||
def add_imported_module(pool: memhub.MemBuddy | t.CPtr,
|
||||
imported_modules: str,
|
||||
name: str) -> str:
|
||||
"""记录已导入的模块名,返回新的 imported_modules 字符串指针(委托到 gen.add_imported_module)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.add_imported_module(pool, imported_modules, name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 检查模块是否已导入
|
||||
# ============================================================
|
||||
def is_module_imported(imported_modules: str, name: str) -> int:
|
||||
"""检查模块是否已导入(词边界精确匹配,避免子串误匹配,委托到 gen.is_module_imported)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_module_imported(imported_modules, name)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 添加 from-import 名称映射
|
||||
# ============================================================
|
||||
def add_from_import(pool: memhub.MemBuddy | t.CPtr,
|
||||
from_imports: str,
|
||||
local_name: str,
|
||||
module_name: str,
|
||||
original_name: str = None) -> str:
|
||||
"""添加 from-import 映射,返回新的 from_imports 字符串(委托到 gen.add_from_import)
|
||||
|
||||
格式:
|
||||
无别名: "local_name:module_name"
|
||||
有别名: "local_name:module_name:original_name"
|
||||
(original_name 为源模块中的真实函数名,用于跨模块 SHA1 修饰)
|
||||
"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.add_from_import(pool, from_imports, local_name, module_name, original_name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 查找 from-import 名称 → 返回原始函数名(别名场景)
|
||||
#
|
||||
# 对于 from X import Y as Z,返回 Y(源模块中的真实函数名)。
|
||||
# 无别名时返回 None(local_name 即为原始名)。
|
||||
# ============================================================
|
||||
def lookup_from_import_original(from_imports: str,
|
||||
local_name: str) -> str:
|
||||
"""查找 from-import 别名对应的原始函数名,返回 None=无别名或未找到(委托到 gen.lookup_from_import_original)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.lookup_from_import_original(from_imports, local_name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 查找 from-import 名称 → 返回模块名或 None
|
||||
#
|
||||
# allow_star_fallback: 是否允许 star import 回退(默认 1=允许)。
|
||||
# 当查询明确模块名(如 "BuildPipeline")时,应传 0 禁用回退,
|
||||
# 避免被 star import 模块名误导(如 from stdint import * 后
|
||||
# 查询 "BuildPipeline" 错误回退到 "stdint")。
|
||||
# ============================================================
|
||||
def lookup_from_import(from_imports: str, name: str,
|
||||
allow_star_fallback: int = 1) -> str:
|
||||
"""查找 from-import 名称,返回模块名或 None(委托到 gen.lookup_from_import)
|
||||
|
||||
支持 star import: 如果 from_imports 中有 "*:module" 条目,
|
||||
且未找到精确名称匹配,且 allow_star_fallback != 0,则返回 star import 的模块名。
|
||||
"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.lookup_from_import(from_imports, name, allow_star_fallback)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# register_reexport - 注册 re-export 映射
|
||||
#
|
||||
# 在 HandleImportFromNames 中调用:当处理 from .X import Y 时,
|
||||
# 记录当前模块(通过 ModuleSha1)re-export 了函数 Y,源模块为 X。
|
||||
#
|
||||
# 幂等:重复注册相同映射不会增加条目。
|
||||
# 内存用 stdlib.malloc 分配(全局存储器,跨 Phase 持久化)。
|
||||
# ============================================================
|
||||
def register_reexport(mod_sha1: str, func_name: str, source_module: str) -> int:
|
||||
"""注册 re-export 映射(幂等),返回 0 成功,-1 失败(委托到 gen.register_reexport)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.register_reexport(mod_sha1, func_name, source_module)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# lookup_reexport - 查找 re-export 映射
|
||||
#
|
||||
# 给定模块 SHA1 和函数名,返回源模块名(如 "ast.lexer")或 None。
|
||||
# 调用方通过 _lookup_module_sha1(source_module) 获取源模块的 SHA1。
|
||||
# ============================================================
|
||||
def lookup_reexport(mod_sha1: str, func_name: str) -> str:
|
||||
"""查找 re-export 映射,返回源模块名或 None(委托到 gen.lookup_reexport)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.lookup_reexport(mod_sha1, func_name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _resolve_relative_module - 解析相对导入为完整模块名
|
||||
#
|
||||
# 对于 from .X import Y(level=1, module="X")在包 pkg 中:
|
||||
# 解析为 "pkg.X"
|
||||
# 对于 from . import Y(level=1, module=None)在包 pkg 中:
|
||||
# 解析为 "pkg"
|
||||
# 对于 from ..X import Y(level=2, module="X")在包 pkg.sub 中:
|
||||
# 解析为 "pkg.X"(先从 pkg.sub 上溯一级到 pkg,再追加 .X)
|
||||
#
|
||||
# Args:
|
||||
# pool: 内存池
|
||||
# current_package: 当前文件所属包名(如 "llvmlite"),None 表示无包
|
||||
# level: 相对导入级别(0=绝对,1=., 2=..)
|
||||
# module: ImportFrom 的 module 字段(可能为 None)
|
||||
#
|
||||
# Returns:
|
||||
# 解析后的完整模块名;绝对导入(level<=0)直接返回 module;
|
||||
# 无法解析时返回 module(回退到原始值)
|
||||
# ============================================================
|
||||
def _resolve_relative_module(pool: memhub.MemBuddy | t.CPtr,
|
||||
current_package: str,
|
||||
level: t.CInt,
|
||||
module: str) -> str:
|
||||
"""解析相对导入为完整模块名(委托到 gen._resolve_relative_module)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._resolve_relative_module(pool, current_package, level, module)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# compute_package_from_relpath - 从相对路径计算包名
|
||||
#
|
||||
# 包名 = 文件所在目录路径,将 / 和 \ 替换为 .
|
||||
# 对于顶级文件(无目录分隔符),返回 None
|
||||
#
|
||||
# 示例:
|
||||
# "llvmlite/__init__.vp" → "llvmlite"
|
||||
# "llvmlite/__types.vp" → "llvmlite"
|
||||
# "ast/parser.vp" → "ast"
|
||||
# "ast.vp" → None(顶级文件)
|
||||
# ============================================================
|
||||
def compute_package_from_relpath(pool: memhub.MemBuddy | t.CPtr,
|
||||
rel_path: str) -> str:
|
||||
"""从相对路径计算包名(目录部分,分隔符替换为 .,委托到 gen.compute_package_from_relpath)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.compute_package_from_relpath(pool, rel_path)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# set_current_file - 设置当前编译的文件名
|
||||
#
|
||||
# 与 HandlesType.set_current_file 同步调用,写入 gen.CurrentFile
|
||||
# (委托到 gen.set_current_file)。
|
||||
# ============================================================
|
||||
def set_current_file(file_path: str) -> None:
|
||||
"""设置当前正在编译的文件名(与 HandlesType.set_current_file 同步调用,委托到 gen.set_current_file)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.set_current_file(file_path)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _report_import_error - 本地实现 Python 风格报错(避免循环依赖)
|
||||
#
|
||||
# 无法访问 HandlesType.fatal_error(HandlesType import 了本模块,
|
||||
# 若本模块再 import HandlesType 会形成循环依赖),这里用简化格式:
|
||||
# Traceback (most recent call last):
|
||||
# File "<当前文件>", line <N>
|
||||
# ImportError: <msg>
|
||||
# ============================================================
|
||||
def _report_import_error(node: ast.AST | t.CPtr, msg: str) -> None:
|
||||
"""以 Python 风格报错并退出(本地实现,避免循环依赖,委托到 gen._report_import_error)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g._report_import_error(node, msg)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _is_local_module_file - 当前文件同目录存在 {mod_name}.vp/.py
|
||||
#
|
||||
# 多文件项目(如 Test/G4/App 的 caller1.vp import g4node)的兄弟模块
|
||||
# 不在 includes 扫描存储器中(SHA1 在项目源文件列表),检查应豁免。
|
||||
# ============================================================
|
||||
def _is_local_module_file(mod_name: str) -> int:
|
||||
"""当前文件同目录存在 {mod_name}.vp/.py → 项目内兄弟模块(委托到 gen._is_local_module_file)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._is_local_module_file(mod_name)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _check_import_sha1 - 导入时校验模块 SHA1 是否已注册(fast-fail)
|
||||
#
|
||||
# 背景:若 includes 路径配置错误(如 project.json 指向不存在的
|
||||
# ./includes),includes 扫描结果为 0,模块不会注册 SHA1。此前
|
||||
# 错误延迟到实际调用 module.func() 时才报误导性的
|
||||
# "跨模块调用 'bd.alloc' 找不到模块 SHA1"。
|
||||
# 现在在 import 语句处立即检测并报错,快速定位配置问题。
|
||||
#
|
||||
# t/c 是内部库,不参与 includes 扫描,豁免检查。
|
||||
# ============================================================
|
||||
def _check_import_sha1(node: ast.AST | t.CPtr, mod_name: str) -> int:
|
||||
"""导入时校验模块 SHA1 是否已注册,未注册则立即报错退出(委托到 gen._check_import_sha1)
|
||||
|
||||
Args:
|
||||
node: Import/ImportFrom AST 节点(提供行号)
|
||||
mod_name: 导入的模块名(如 "memhub"、"w32.fileio")
|
||||
|
||||
Returns:
|
||||
1=检查通过;模块未注册时直接报错退出(不会返回 0)
|
||||
"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._check_import_sha1(node, mod_name)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# translate_import - 处理 import 语句(委托到 gen.translate_import)
|
||||
# ============================================================
|
||||
def translate_import(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""处理 import 语句,返回 0(委托到 gen.translate_import)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_import(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# translate_import_from_module - 处理 from X import Y 的模块部分
|
||||
# (委托到 gen.translate_import_from_module)
|
||||
# ============================================================
|
||||
def translate_import_from_module(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""处理 from X import Y 的模块部分(委托到 gen.translate_import_from_module)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_import_from_module(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# translate_import_from_names - 处理 from X import Y 的名称部分
|
||||
# (委托到 gen.translate_import_from_names)
|
||||
# ============================================================
|
||||
def translate_import_from_names(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""处理 from X import Y 的名称部分(委托到 gen.translate_import_from_names)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_import_from_names(trans, node)
|
||||
return 0
|
||||
@@ -1,172 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesBody as HandlesBody
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesMain - 模块级翻译入口 + wrapper main 创建
|
||||
#
|
||||
# 从 translator.py 拆分出来,负责:
|
||||
# 1. create_wrapper_main() - 无用户 main 时创建包装 main
|
||||
# 2. translate_children() - 遍历 AST 子节点并分派翻译
|
||||
#
|
||||
# trans 单参模式:所有共享状态从 trans 获取,无需 11 个参数
|
||||
# 注意: str = bytes = str = i8*
|
||||
#
|
||||
# P6-E 对象化重构:全部函数已迁移为 lib.core.Gen.TranslatorGenMixin
|
||||
# 的方法,本模块保留同名模块级函数作为"一行委托"(同 P2-P5 模式):
|
||||
# 延迟 import Gen 取全局单例,再调用 gen 的对应方法。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _register_cexport_from_funcdef - Phase 1a 预注册 CExport/State 函数
|
||||
#
|
||||
# 解决翻译顺序依赖问题:Phase 1b 按字母序翻译,后翻译的模块的
|
||||
# CExport 函数无法被先翻译的模块正确识别为裸名调用。
|
||||
# Phase 1a 预注册所有 CExport/State 函数名到全局表。
|
||||
# ============================================================
|
||||
def _register_cexport_from_funcdef(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""预注册 CExport/State 函数到全局表(仅注册,不生成 IR)(委托到 gen._register_cexport_from_funcdef)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._register_cexport_from_funcdef(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# translate_children - 遍历 AST 子节点并分派翻译
|
||||
#
|
||||
# 对应 TransPyC translator._translate_children()
|
||||
# 共享状态从 trans 获取,imported_modules/from_imports 更新到 trans
|
||||
# ============================================================
|
||||
def translate_children(trans: HT.Translator | t.CPtr,
|
||||
tree: ast.AST | t.CPtr) -> int:
|
||||
"""遍历 tree.children 并翻译每个子节点(委托到 gen.translate_children)
|
||||
|
||||
Args:
|
||||
trans: 翻译器(含所有共享状态)
|
||||
tree: AST 模块节点
|
||||
|
||||
Returns:
|
||||
t.CInt: 新增的变量数
|
||||
"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_children(trans, tree)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _prescan_funcdef_signatures - 1a 阶段预解析模块级函数签名
|
||||
#
|
||||
# 触发泛型类特化(如 numpy 的 _empty_like 签名 ndarray[t.CDouble]),
|
||||
# 使特化结构体在 mark1 前注册(Ty/Fields 不被 1b 的 mark/reset 回收),
|
||||
# 避免 Phase2 翻译 App 文件时访问悬空结构体(UAF)。
|
||||
# 仅解析类型触发特化,不验证结果(1b 全量翻译时重新解析)。
|
||||
# ============================================================
|
||||
def _prescan_funcdef_signatures(trans: HT.Translator | t.CPtr,
|
||||
fd: ast.FunctionDef | t.CPtr) -> None:
|
||||
"""预解析模块级函数签名的返回/参数类型,触发泛型类特化(委托到 gen._prescan_funcdef_signatures)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g._prescan_funcdef_signatures(trans, fd)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _build_array_initializer_text - 从 AST List 生成 LLVM IR 数组初始化器
|
||||
#
|
||||
# 生成格式: [N x elem_ty] [elem_ty val0, elem_ty val1, ...]
|
||||
# 用于模块级 t.CArray 列表字面量初始化(不依赖 builder,直接生成常量初始化器)
|
||||
# ============================================================
|
||||
def _build_array_initializer_text(pool: memhub.MemBuddy | t.CPtr,
|
||||
var_ty: llvmlite.LLVMType | t.CPtr,
|
||||
list_node: ast.List | t.CPtr) -> str:
|
||||
"""从 AST List 节点生成 LLVM IR 数组初始化器文本,None 失败(委托到 gen._build_array_initializer_text)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._build_array_initializer_text(pool, var_ty, list_node)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _build_string_ptr_initializer - 为字符串字面量初始化指针类型全局变量
|
||||
#
|
||||
# 创建内部字符串常量全局 @.str.{var_name} = private constant [len+1 x i8] c"...\00"
|
||||
# 返回 GEP 初始化器文本: getelementptr inbounds ([len+1 x i8], [len+1 x i8]* @.str.{var_name}, i32 0, i32 0)
|
||||
# 用于 b64_tab: t.CArray[t.CChar, None] = "ABC..." 等字符串初始化指针类型
|
||||
# ============================================================
|
||||
def _build_string_ptr_initializer(pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
var_name: str,
|
||||
str_val: str) -> str:
|
||||
"""为字符串字面量创建内部常量全局并返回 GEP 初始化器文本,None 失败(委托到 gen._build_string_ptr_initializer)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._build_string_ptr_initializer(pool, mod, var_name, str_val)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# handle_module_level_var - 模块级变量声明 → 创建 LLVM 全局变量
|
||||
#
|
||||
# 当用户已定义 main(无 wrapper main builder)时,模块级
|
||||
# AnnAssign/Assign 创建全局变量 @var_name 并注册到 SymTab 模块作用域
|
||||
# 支持整数、列表字面量、字符串字面量初始值
|
||||
# ============================================================
|
||||
def handle_module_level_var(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""处理模块级变量声明,创建全局变量(委托到 gen.handle_module_level_var)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.handle_module_level_var(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# create_wrapper_main - 创建包装 main 函数
|
||||
#
|
||||
# 当用户未定义 main 函数时调用。
|
||||
# 创建 main() -> i32 函数 → 设置 trans._cur_func/_cur_builder →
|
||||
# 预扫描 alloca → 翻译子节点 → ret 0
|
||||
# ============================================================
|
||||
def create_wrapper_main(trans: HT.Translator | t.CPtr,
|
||||
tree: ast.AST | t.CPtr,
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""创建包装 main 函数并翻译所有顶层语句(委托到 gen.create_wrapper_main)
|
||||
|
||||
Args:
|
||||
trans: 翻译器(含所有共享状态)
|
||||
tree: AST 模块节点
|
||||
i32_ty: i32 LLVMType
|
||||
|
||||
Returns:
|
||||
t.CInt: 新增的变量数
|
||||
"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.create_wrapper_main(trans, tree, i32_ty)
|
||||
return 0
|
||||
@@ -1,74 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesBody as HandlesBody
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesMatch - match 语句处理(P6 对象化后的委托层)
|
||||
#
|
||||
# P6 机械化迁移:MatchHandle 类 → lib.core.Gen.MatchGenMixin
|
||||
# (Handle → translate_match,方法体 self.Trans → trans 首参;
|
||||
# 类内辅助方法 + 模块级 _case_tail_unreachable 一并搬入成方法)。
|
||||
# 本模块保留同名模块级函数作为"一行委托":延迟 import Gen 取全局单例
|
||||
# (BuildPipeline/main 创建后 set_global_gen 注册),再调用 gen 的
|
||||
# 对应方法。签名与旧函数完全一致,调用方零改动。
|
||||
# 分派中枢(StmtGenMixin)经本壳跨链调用(Viper @t.NoVTable 静态绑定下
|
||||
# 跨 Mixin self. 调用 mangle 失败,须经模块级委托壳桥回 gen 单例)。
|
||||
# 迁移收尾(编译器缺陷修复)后统一删除。
|
||||
#
|
||||
# 逻辑移植自 TPC 的 HandlesMatch.py,用 Viper 语法重写。
|
||||
# 两条路径:
|
||||
# 1. REnum 路径:bitcast subject 到 i32* 读 __tag + switch 分派
|
||||
# 2. 非 REnum 路径:subject ptrtoint 到 i32 + switch 分派
|
||||
#
|
||||
# IR 模式(REnum):
|
||||
# %tag_ptr = bitcast <struct>* %subj to i32*
|
||||
# %tag = load i32, i32* %tag_ptr
|
||||
# switch i32 %tag, label %default [ i32 <tag1>, label %case1 ... ]
|
||||
# case1:
|
||||
# ... body ...
|
||||
# br label %end (若无 c.NoBreak)
|
||||
# end:
|
||||
# ============================================================
|
||||
|
||||
# match case 数量上限
|
||||
MAX_MATCH_CASES: t.CDefine = 32
|
||||
|
||||
# 作用域种类常量(与 HandlesVar 的 Scope.Kind 区分)
|
||||
SCOPE_MATCH: t.CDefine = 6
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# P6 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# MatchGenMixin 方法,避免函数体 import 包模块与 Generator
|
||||
# 类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# translate_match - match 语句翻译(委托到 gen.translate_match)
|
||||
# ============================================================
|
||||
def translate_match(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 match 语句,返回 0(委托到 gen.translate_match)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_match(trans, node)
|
||||
return 0
|
||||
@@ -1,126 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesNonlocal - nonlocal 变量访问(通过闭包 env)(P6 对象化后的委托层)
|
||||
#
|
||||
# 全部模块级函数已迁移为 lib.core.Gen.StmtGenMixin 的方法,本模块
|
||||
# 保留同名模块级函数作为"一行委托":延迟 import Gen 取全局单例
|
||||
# (BuildPipeline/main 创建后 set_global_gen 注册),再调用 gen 的
|
||||
# 对应方法。签名与旧函数完全一致,调用方零改动。
|
||||
#
|
||||
# 闭包 env 结构: {i8* ptr0, i8* ptr1, ...} (每个 nonlocal 变量一个 i8* 指针)
|
||||
# 指针指向父函数中变量的 alloca(原始存储位置),父与子共享同一存储,
|
||||
# 子函数修改对父函数可见(符合 Python nonlocal 语义)。
|
||||
#
|
||||
# 在提升的嵌套函数中:
|
||||
# 1. 函数签名: define i32 @__closure_{name}(i8* %env)
|
||||
# 2. 入口处: %env_alloca = alloca i8*; store i8* %env, i8** %env_alloca
|
||||
# 3. 访问 nonlocal var:
|
||||
# a. %env_ptr = load i8*, i8** %env_alloca
|
||||
# b. %addr = gep i8, i8* %env_ptr, i32 (index * 8)
|
||||
# c. %ptr_addr = bitcast i8* %addr to i8**
|
||||
# d. %var_ptr_raw = load i8*, i8** %ptr_addr
|
||||
# e. %var_ptr = bitcast i8* %var_ptr_raw to <var_ty>*
|
||||
# f. read: %val = load <var_ty>, <var_ty>* %var_ptr
|
||||
# write: store <var_ty> %new, <var_ty>* %var_ptr
|
||||
#
|
||||
# 变量类型通过 HT.get_nonlocal_type() 获取(注册 nonlocal 时记录)。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# StmtGenMixin 方法,避免函数体 import 包模块与类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _is_void_type — 判断是否为 Void 类型(非法用作变量类型)
|
||||
#
|
||||
# 由于某些路径(如 c.DerefAs 设置的 Pointee 字段访问异常)可能导致
|
||||
# 类型被设为 Void 而非 None,这里显式检测 Void 类型并视为无效,
|
||||
# 回退为 i32,避免生成 "bitcast ... to void*" / "load void, void*" 的非法 IR。
|
||||
# ============================================================
|
||||
def _is_void_type(ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""判断是否为 Void 类型,是则返回 1,否则 0(委托到 gen._is_void_type)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._is_void_type(ty)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 获取或创建 _env_ptr 变量(存储 env 参数的 alloca)
|
||||
# ============================================================
|
||||
def get_env_ptr_var(trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""获取或创建 _env_ptr 变量(存储闭包 env 指针)(委托到 gen.get_env_ptr_var)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_env_ptr_var(trans)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 从 env 加载原始变量指针(i8*)→ 调用方 bitcast 为具体类型
|
||||
#
|
||||
# env 存储指针数组(8 字节/槽),每个指针指向父函数的 alloca。
|
||||
# ============================================================
|
||||
def _load_raw_var_ptr(trans: HT.Translator | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""从闭包 env 加载 nonlocal 变量的原始指针(i8*)(委托到 gen._load_raw_var_ptr)
|
||||
|
||||
返回 i8* 类型的 Value,调用方需 bitcast 为具体类型指针后 load/store。
|
||||
"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._load_raw_var_ptr(trans, name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 加载 nonlocal 变量值 → 返回具体类型的 Value
|
||||
#
|
||||
# env 存储指向父函数 alloca 的指针,通过类型恢复 load 正确类型的值。
|
||||
# ============================================================
|
||||
def load_nonlocal_var(trans: HT.Translator | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""从闭包 env 加载 nonlocal 变量值(委托到 gen.load_nonlocal_var)
|
||||
|
||||
通过 HT.get_nonlocal_type 获取变量类型,bitcast 原始指针后 load。
|
||||
"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.load_nonlocal_var(trans, name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 获取 nonlocal 变量指针(用于 store)
|
||||
#
|
||||
# 返回具体类型指针(var_ty*),用于直接 store。
|
||||
# ============================================================
|
||||
def get_nonlocal_var_ptr(trans: HT.Translator | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""获取 nonlocal 变量的存储指针(var_ty*),用于 store 操作(委托到 gen.get_nonlocal_var_ptr)
|
||||
|
||||
返回的指针指向父函数的 alloca,store 操作对父函数可见。
|
||||
"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_nonlocal_var_ptr(trans, name)
|
||||
return None
|
||||
@@ -1,33 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesReturn - Return 语句处理(迁移完成,保留跨 Mixin 委托壳)
|
||||
#
|
||||
# P6 机械化迁移:ReturnHandle 类 → StmtGenCifMixin.translate_return。
|
||||
# 分派中枢(StmtGenMixin)经本壳跨类调用(Viper @t.NoVTable 静态绑定下
|
||||
# 跨 Mixin self. 调用 mangle 失败,须经模块级委托壳桥回 gen 单例)。
|
||||
# 迁移收尾(编译器缺陷修复)后统一删除。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# translate_return - Return 语句翻译(委托到 gen.translate_return)
|
||||
# ============================================================
|
||||
def translate_return(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 Return 语句,返回 0(委托到 gen.translate_return)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_return(trans, node)
|
||||
return 0
|
||||
@@ -1,544 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import llvmlite
|
||||
import stdio
|
||||
import ast
|
||||
import hashtable
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesStruct - 结构体类型注册和字段查找(P2-2 对象化后的委托层)
|
||||
#
|
||||
# 管理 class 定义的结构体类型信息:
|
||||
# - 类名 → LLVM StructType
|
||||
# - 字段名 → 字段索引和类型
|
||||
#
|
||||
# P2-2 对象化重构(wiki/14-oo-refactor.md):
|
||||
# 全部函数已迁移为 lib.core.Gen.StructGenMixin 的方法(全局状态迁入
|
||||
# gen 字段),本模块保留同名模块级函数作为"一行委托":延迟 import
|
||||
# Gen 取全局单例(BuildPipeline/main 创建后 set_global_gen 注册),
|
||||
# 再调用 gen 的对应方法。签名与旧函数完全一致,调用方零改动。
|
||||
#
|
||||
# FieldEntry/StructEntry 类型与常量保留在本模块(gen 字段类型引用)。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType 模式)
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
STRUCT_MAX: t.CDefine = 512
|
||||
# 字段槽位上限制(Generator 43 Mixin 展平 ~120 字段;2026-08-16 追加78:64
|
||||
# 截断导致第 9+ 父类字段丢失 → __init__ 写 self.DiagStmtCount "属性写入失败"。
|
||||
# 拆分重构使 Generator 父类数增至 43,FIELD_MAX 提至 256 防静默截断)
|
||||
FIELD_MAX: t.CDefine = 256
|
||||
FIELD_NAME_MAX: t.CDefine = 64
|
||||
# 多继承(MRO)支持:单类最大父类数 / MRO 链最大长度(Generator 43 父类;
|
||||
# PARENT_MAX=16 时 _collect_parents/set_parent_names 只收前 16 个 → 第 17+
|
||||
# 父类字段丢失 → __init__ 写 self.DiagStmtCount "属性写入失败" 根因)
|
||||
PARENT_MAX: t.CDefine = 64
|
||||
MRO_MAX: t.CDefine = 64
|
||||
|
||||
|
||||
# ============================================================
|
||||
# FieldEntry - 字段信息条目
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class FieldEntry:
|
||||
Name: str # 字段名(字符串)
|
||||
Index: int # 字段在结构体中的索引
|
||||
Ty: llvmlite.LLVMType | t.CPtr # 字段的 LLVM 类型
|
||||
DefaultVal: ast.AST | t.CPtr # 默认值 AST 节点(None=无默认值)
|
||||
AnnotClassName: str # 原始类型注解的类名(str 别名在结构体字段中触发编译器 bug,改用显式联合类型)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# StructEntry - 结构体注册条目
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class StructEntry:
|
||||
Name: str # 类名
|
||||
Ty: llvmlite.LLVMType | t.CPtr # LLVM StructType
|
||||
FieldCount: int # 字段数量
|
||||
Fields: FieldEntry | t.CPtr # 字段数组(FIELD_MAX 个槽位)
|
||||
IsUnion: int # 1=联合体 / 0=普通结构体
|
||||
IsOOP: int # 1=OOP结构体(有方法) / 0=纯内存结构体
|
||||
HasInit: int # 1=有__init__方法 / 0=无
|
||||
HasNew: int # 1=有__new__方法 / 0=无
|
||||
HasVTable: int # 1=有虚表 / 0=无虚表
|
||||
IsNoVTable: int # 1=明确标记 @t.NoVTable / 0=未标记
|
||||
ParentName: str # 父类名(None=无父类,多继承时为第一个父类,兼容旧调用)
|
||||
ParentNames: t.CSizeT | t.CPtr # 多继承父类名数组(每元素 str 指针,ParentCount 个;stdlib 深拷贝)
|
||||
ParentCount: t.CInt # 父类数量(0=无父类,1=单继承,>1=多继承)
|
||||
VTableMethodCount: int # 虚表中的方法数量
|
||||
VTableMethods: str # 虚表方法名数组(每个方法名 str,VTableMethodCount 个)
|
||||
ModuleSha1: str # 定义该类的模块 SHA1(None=无 SHA1)
|
||||
MethodsEmitted: int # 1=方法体已翻译 / 0=未译(Phase 1a mark_only 未译,Phase B 据此补译)
|
||||
SpecTriggerSha1: str # 泛型特化类的触发文件 SHA1(None=非特化类)。特化类 ModuleSha1=模板
|
||||
# sha1(方法名带模板前缀),作废重译时 reset_module_methods_emitted
|
||||
# 按触发文件 sha1 精确重置 MethodsEmitted,防特化方法体残留 1 不补译
|
||||
# → 链接 undefined symbol(list[ast.ClassDef|t.CPtr].* 根因)
|
||||
|
||||
|
||||
def set_stdlib_alloc(flag: int):
|
||||
"""设置 OOM 回收分配模式(委托到 gen.set_stdlib_alloc)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.set_stdlib_alloc(flag)
|
||||
|
||||
|
||||
def get_stdlib_alloc() -> int:
|
||||
"""读取 OOM 回收分配模式(委托到 gen.get_stdlib_alloc)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_stdlib_alloc()
|
||||
return 0
|
||||
|
||||
|
||||
def reset_visible_structs(pool: memhub.MemBuddy | t.CPtr, strict: int):
|
||||
"""重置可见性状态(每个文件翻译前调用,委托到 gen.reset_visible_structs)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.reset_visible_structs(pool, strict)
|
||||
|
||||
|
||||
def add_visible_struct(pool: memhub.MemBuddy | t.CPtr, name: str):
|
||||
"""添加可见结构体名(类定义时和 from-import 时调用,委托到 gen.add_visible_struct)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.add_visible_struct(pool, name)
|
||||
|
||||
|
||||
def is_struct_visible(name: str) -> int:
|
||||
"""检查结构体是否可见,返回 1=可见 / 0=不可见(委托到 gen.is_struct_visible)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_struct_visible(name)
|
||||
return 0
|
||||
|
||||
|
||||
def init_struct_table(pool: memhub.MemBuddy | t.CPtr) -> int:
|
||||
"""初始化结构体注册表,返回 1 成功(委托到 gen.init_struct_table)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.init_struct_table(pool)
|
||||
return 0
|
||||
|
||||
|
||||
def _get_struct_entry(i: int) -> StructEntry | t.CPtr:
|
||||
"""获取第 i 个结构体条目(委托到 gen._get_struct_entry)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._get_struct_entry(i)
|
||||
return None
|
||||
|
||||
|
||||
def _get_field_entry(struct_entry: StructEntry | t.CPtr, i: int) -> FieldEntry | t.CPtr:
|
||||
"""获取结构体中第 i 个字段条目(委托到 gen._get_field_entry)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._get_field_entry(struct_entry, i)
|
||||
return None
|
||||
|
||||
|
||||
def register_struct(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str,
|
||||
struct_ty: llvmlite.LLVMType | t.CPtr,
|
||||
sha1: str = None) -> StructEntry | t.CPtr:
|
||||
"""注册结构体类型,返回 StructEntry 指针(委托到 gen.register_struct)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.register_struct(pool, name, struct_ty, sha1)
|
||||
return None
|
||||
|
||||
|
||||
def set_struct_sha1(pool: memhub.MemBuddy | t.CPtr,
|
||||
class_name: str, sha1: str) -> int:
|
||||
"""设置结构体所属模块的 SHA1,返回 1=成功 / 0=失败(委托到 gen.set_struct_sha1)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.set_struct_sha1(pool, class_name, sha1)
|
||||
return 0
|
||||
|
||||
|
||||
def get_struct_sha1(class_name: str) -> str:
|
||||
"""获取结构体所属模块的 SHA1,返回 None=无 SHA1(委托到 gen.get_struct_sha1)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_struct_sha1(class_name)
|
||||
return None
|
||||
|
||||
|
||||
def add_field(pool: memhub.MemBuddy | t.CPtr,
|
||||
struct_entry: StructEntry | t.CPtr,
|
||||
field_name: str,
|
||||
field_ty: llvmlite.LLVMType | t.CPtr,
|
||||
default_val: ast.AST | t.CPtr = None,
|
||||
annot_class_name: str = None) -> int:
|
||||
"""向结构体添加字段,返回字段索引(-1 失败,委托到 gen.add_field)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.add_field(pool, struct_entry, field_name, field_ty,
|
||||
default_val, annot_class_name)
|
||||
return 0
|
||||
|
||||
|
||||
def get_struct_count() -> int:
|
||||
"""返回当前已注册的结构体数量(委托到 gen.get_struct_count)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_struct_count()
|
||||
return 0
|
||||
|
||||
|
||||
def reset_module_methods_emitted(sha1: str) -> int:
|
||||
"""回滚指定模块注册类的 MethodsEmitted 标志(Phase A _deps_pending 重试
|
||||
前调用,防 MethodsEmitted 跨遍残留导致类方法缺失——追加87,委托到 gen.reset_module_methods_emitted)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.reset_module_methods_emitted(sha1)
|
||||
return 0
|
||||
|
||||
|
||||
def find_struct(name: str) -> StructEntry | t.CPtr:
|
||||
"""按类名查找结构体,返回 StructEntry 或 None(委托到 gen.find_struct)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.find_struct(name)
|
||||
return None
|
||||
|
||||
|
||||
def find_struct_by_module(name: str, sha1: str) -> StructEntry | t.CPtr:
|
||||
"""按类名 + SHA1 查找结构体,返回 StructEntry 或 None(委托到 gen.find_struct_by_module)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.find_struct_by_module(name, sha1)
|
||||
return None
|
||||
|
||||
|
||||
def find_struct_by_type(struct_ty: llvmlite.LLVMType | t.CPtr) -> StructEntry | t.CPtr:
|
||||
"""按类型指针查找结构体(指针值比较),返回 StructEntry 或 None(委托到 gen.find_struct_by_type)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.find_struct_by_type(struct_ty)
|
||||
return None
|
||||
|
||||
|
||||
def lookup_field(struct_ty: llvmlite.LLVMType | t.CPtr,
|
||||
field_name: str) -> FieldEntry | t.CPtr:
|
||||
"""按结构体类型和字段名查找字段信息(委托到 gen.lookup_field)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.lookup_field(struct_ty, field_name)
|
||||
return None
|
||||
|
||||
|
||||
def lookup_field_by_class(class_name: str,
|
||||
field_name: str,
|
||||
sha1: str = None) -> FieldEntry | t.CPtr:
|
||||
"""按类名和字段名查找字段信息(委托到 gen.lookup_field_by_class)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.lookup_field_by_class(class_name, field_name, sha1)
|
||||
return None
|
||||
|
||||
|
||||
def get_struct_type(class_name: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""按类名获取结构体的 LLVM 类型(委托到 gen.get_struct_type)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_struct_type(class_name)
|
||||
return None
|
||||
|
||||
|
||||
def get_field_by_index(class_name: str,
|
||||
idx: int) -> FieldEntry | t.CPtr:
|
||||
"""按类名和字段索引获取字段信息(委托到 gen.get_field_by_index)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_field_by_index(class_name, idx)
|
||||
return None
|
||||
|
||||
|
||||
def struct_has_defaults(class_name: str) -> int:
|
||||
"""检查结构体是否有任何带默认值的字段,返回 1=有 / 0=无(委托到 gen.struct_has_defaults)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.struct_has_defaults(class_name)
|
||||
return 0
|
||||
|
||||
|
||||
def get_struct_type_from_value(val: llvmlite.Value | t.CPtr) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""从 Value 的类型推断结构体类型(委托到 gen.get_struct_type_from_value)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_struct_type_from_value(val)
|
||||
return None
|
||||
|
||||
|
||||
def mark_as_union(name: str) -> int:
|
||||
"""标记已注册的结构体为联合体,返回 1=成功 / 0=失败(委托到 gen.mark_as_union)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.mark_as_union(name)
|
||||
return 0
|
||||
|
||||
|
||||
def is_union_by_name(name: str) -> int:
|
||||
"""按类名检查是否为联合体,返回 1=是 / 0=否(委托到 gen.is_union_by_name)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_union_by_name(name)
|
||||
return 0
|
||||
|
||||
|
||||
def is_union_by_type(struct_ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""按类型指针检查是否为联合体,返回 1=是 / 0=否(委托到 gen.is_union_by_type)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_union_by_type(struct_ty)
|
||||
return 0
|
||||
|
||||
|
||||
def mark_as_oop(name: str) -> int:
|
||||
"""标记已注册的结构体为 OOP,返回 1=成功 / 0=失败(委托到 gen.mark_as_oop)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.mark_as_oop(name)
|
||||
return 0
|
||||
|
||||
|
||||
def is_oop_by_name(name: str) -> int:
|
||||
"""按类名检查是否为 OOP 结构体,返回 1=是 / 0=否(委托到 gen.is_oop_by_name)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_oop_by_name(name)
|
||||
return 0
|
||||
|
||||
|
||||
def mark_has_init(name: str) -> int:
|
||||
"""标记结构体拥有 __init__ 方法,返回 1=成功 / 0=失败(委托到 gen.mark_has_init)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.mark_has_init(name)
|
||||
return 0
|
||||
|
||||
|
||||
def has_init_by_name(name: str) -> int:
|
||||
"""按类名检查是否有 __init__ 方法,返回 1=有 / 0=无(委托到 gen.has_init_by_name)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.has_init_by_name(name)
|
||||
return 0
|
||||
|
||||
|
||||
def mark_has_new(name: str) -> int:
|
||||
"""标记结构体拥有 __new__ 方法,返回 1=成功 / 0=失败(委托到 gen.mark_has_new)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.mark_has_new(name)
|
||||
return 0
|
||||
|
||||
|
||||
def has_new_by_name(name: str) -> int:
|
||||
"""按类名检查是否有 __new__ 方法,返回 1=有 / 0=无(委托到 gen.has_new_by_name)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.has_new_by_name(name)
|
||||
return 0
|
||||
|
||||
|
||||
def get_class_name_by_type(pool: memhub.MemBuddy | t.CPtr,
|
||||
struct_ty: llvmlite.LLVMType | t.CPtr) -> str:
|
||||
"""按类型指针查找类名,返回类名字符串或 None(委托到 gen.get_class_name_by_type)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_class_name_by_type(pool, struct_ty)
|
||||
return None
|
||||
|
||||
|
||||
def _extract_struct_name(ty: llvmlite.LLVMType | t.CPtr) -> str:
|
||||
"""从 LLVMType 提取 Struct 变体的 Name 字段,返回 None 非 Struct(委托到 gen._extract_struct_name)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._extract_struct_name(ty)
|
||||
return None
|
||||
|
||||
|
||||
def mark_has_vtable(name: str) -> int:
|
||||
"""标记结构体拥有虚表,返回 1=成功 / 0=失败(委托到 gen.mark_has_vtable)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.mark_has_vtable(name)
|
||||
return 0
|
||||
|
||||
|
||||
def has_vtable_by_name(name: str) -> int:
|
||||
"""按类名检查是否有虚表,返回 1=有 / 0=无(委托到 gen.has_vtable_by_name)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.has_vtable_by_name(name)
|
||||
return 0
|
||||
|
||||
|
||||
def mark_novtable(name: str) -> int:
|
||||
"""标记结构体为 NoVTable,返回 1=成功 / 0=失败(委托到 gen.mark_novtable)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.mark_novtable(name)
|
||||
return 0
|
||||
|
||||
|
||||
def is_novtable_by_name(name: str) -> int:
|
||||
"""按类名检查是否为 NoVTable,返回 1=是 / 0=否(委托到 gen.is_novtable_by_name)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_novtable_by_name(name)
|
||||
return 0
|
||||
|
||||
|
||||
def set_parent_name(name: str, parent_name: str) -> int:
|
||||
"""设置结构体的父类名,返回 1=成功 / 0=失败(委托到 gen.set_parent_name)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.set_parent_name(name, parent_name)
|
||||
return 0
|
||||
|
||||
|
||||
def set_parent_names(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, names_ptr: t.CSizeT | t.CPtr,
|
||||
count: int) -> int:
|
||||
"""设置结构体的父类名数组(永久池深拷贝,委托到 gen.set_parent_names)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.set_parent_names(pool, name, names_ptr, count)
|
||||
return 0
|
||||
|
||||
|
||||
def get_parent_count(name: str) -> int:
|
||||
"""获取父类数量(0=无父类,1=单继承,>1=多继承,委托到 gen.get_parent_count)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_parent_count(name)
|
||||
return 0
|
||||
|
||||
|
||||
def get_parent_name_at(name: str, idx: int) -> str:
|
||||
"""获取第 idx 个父类名,越界返回 None(委托到 gen.get_parent_name_at)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_parent_name_at(name, idx)
|
||||
return None
|
||||
|
||||
|
||||
def get_mro_chain(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str) -> t.CSizeT | t.CPtr:
|
||||
"""MRO 线性化类名数组(深度优先 + 声明顺序 + 去重,含自身,委托到 gen.get_mro_chain)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_mro_chain(pool, name)
|
||||
return None
|
||||
|
||||
|
||||
def get_parent_name(name: str) -> str:
|
||||
"""获取结构体的父类名,返回 None=无父类(委托到 gen.get_parent_name)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_parent_name(name)
|
||||
return None
|
||||
|
||||
|
||||
def set_vtable_methods(name: str, methods: str, count: int) -> int:
|
||||
"""设置虚表方法名数组,返回 1=成功 / 0=失败(委托到 gen.set_vtable_methods)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.set_vtable_methods(name, methods, count)
|
||||
return 0
|
||||
|
||||
|
||||
def get_vtable_method_index(name: str, method_name: str) -> int:
|
||||
"""获取方法在虚表中的索引,返回 -1=未找到(委托到 gen.get_vtable_method_index)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_vtable_method_index(name, method_name)
|
||||
return 0
|
||||
|
||||
|
||||
def get_vtable_method_count(name: str) -> int:
|
||||
"""获取虚表方法数量(委托到 gen.get_vtable_method_count)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_vtable_method_count(name)
|
||||
return 0
|
||||
|
||||
|
||||
def get_vtable_method_name(name: str, idx: int) -> str:
|
||||
"""获取虚表中第 idx 个方法名,返回 None=越界(委托到 gen.get_vtable_method_name)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_vtable_method_name(name, idx)
|
||||
return None
|
||||
|
||||
|
||||
def get_field_count(name: str) -> int:
|
||||
"""获取结构体字段数量,返回 -1=未找到(委托到 gen.get_field_count)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_field_count(name)
|
||||
return 0
|
||||
|
||||
|
||||
def ensure_struct_def_in_module(pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
ty: llvmlite.LLVMType | t.CPtr):
|
||||
"""确保跨模块结构体的完整定义在当前模块中可用(委托到 gen.ensure_struct_def_in_module)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.ensure_struct_def_in_module(pool, mod, ty)
|
||||
|
||||
|
||||
def _ensure_field_types_in_module(pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
ty: llvmlite.LLVMType | t.CPtr):
|
||||
"""递归扫描类型树,确保值类型子结构体有完整定义(委托到 gen._ensure_field_types_in_module)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g._ensure_field_types_in_module(pool, mod, ty)
|
||||
|
||||
|
||||
def get_field_name_ptr(fe: FieldEntry | t.CPtr) -> str:
|
||||
"""获取 FieldEntry 的字段名,返回 None=未设置(委托到 gen.get_field_name_ptr)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_field_name_ptr(fe)
|
||||
return None
|
||||
|
||||
|
||||
def get_field_type_ptr(fe: FieldEntry | t.CPtr) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""获取 FieldEntry 的字段类型,返回 None=未设置(委托到 gen.get_field_type_ptr)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_field_type_ptr(fe)
|
||||
return None
|
||||
|
||||
|
||||
def get_field_default_ptr(fe: FieldEntry | t.CPtr) -> ast.AST | t.CPtr:
|
||||
"""获取 FieldEntry 的默认值 AST 节点,返回 None=无默认值(委托到 gen.get_field_default_ptr)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_field_default_ptr(fe)
|
||||
return None
|
||||
|
||||
|
||||
def get_field_annot_class_name(fe: FieldEntry | t.CPtr) -> str:
|
||||
"""获取 FieldEntry 的原始类型注解类名,返回 None=未设置(委托到 gen.get_field_annot_class_name)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_field_annot_class_name(fe)
|
||||
return None
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,598 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import sys
|
||||
import stdlib
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesType - 类型映射与解析(P2 对象化后的委托层)
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 常量(保留,供 TraceFrame 相关使用)
|
||||
# ============================================================
|
||||
TRACE_MAX: t.CDefine = 32
|
||||
MAX_CTYPEDEF_DEPTH: t.CDefine = 10
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class TraceFrame:
|
||||
file_name: str # 文件名
|
||||
lineno: int # 行号
|
||||
col_start: int # 列起始(1-based,0=不指定)
|
||||
col_end: int # 列结束(1-based,0=不指定)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像)
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 类编译期元数据(__provides__/__requires__/__require_must__)
|
||||
#
|
||||
# _fakeduck.vp 的 _str 用 __requires__ = ['__mbuddy__'] 声明 with 上下文
|
||||
# 依赖字段;with 提供者用 __provides__ 声明注入字段。这些是编译期
|
||||
# 元数据,不生成运行字段(FakeDuck 移植点 1)。
|
||||
# ============================================================
|
||||
CLASS_META_PROVIDES: t.CDefine = 1
|
||||
CLASS_META_REQUIRES: t.CDefine = 2
|
||||
CLASS_META_REQUIRE_MUST: t.CDefine = 3
|
||||
|
||||
|
||||
def register_class_meta(pool: memhub.MemBuddy | t.CPtr,
|
||||
kind: int, cls: str, field: str) -> int:
|
||||
"""注册类编译期元数据字段(委托到 gen.register_class_meta),0=成功"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.register_class_meta(pool, kind, cls, field)
|
||||
return 1
|
||||
|
||||
|
||||
def class_meta_count(kind: int, cls: str) -> int:
|
||||
"""返回某类某元数据类型的字段数(委托到 gen.class_meta_count)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.class_meta_count(kind, cls)
|
||||
return 0
|
||||
|
||||
|
||||
def class_meta_field_at(kind: int, cls: str, idx: int) -> str:
|
||||
"""返回某类某元数据类型的第 idx 个字段名(委托到 gen.class_meta_field_at)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.class_meta_field_at(kind, cls, idx)
|
||||
return None
|
||||
|
||||
|
||||
def _ensure_trace_init() -> int:
|
||||
"""确保调用栈已初始化(委托到 gen._ensure_trace_init)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._ensure_trace_init()
|
||||
return 0
|
||||
|
||||
|
||||
def _get_trace_frame(i: int) -> TraceFrame | t.CPtr:
|
||||
"""获取第 i 个 TraceFrame 槽位(委托到 gen._get_trace_frame)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._get_trace_frame(i)
|
||||
return None
|
||||
|
||||
|
||||
def push_trace(file_name: str, lineno: int, col_start: int = 0, col_end: int = 0):
|
||||
"""压入一个翻译上下文帧(委托到 gen.push_trace)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.push_trace(file_name, lineno, col_start, col_end)
|
||||
|
||||
|
||||
def pop_trace():
|
||||
"""弹出栈顶帧(委托到 gen.pop_trace)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.pop_trace()
|
||||
|
||||
|
||||
def clear_trace():
|
||||
"""清空调用栈(委托到 gen.clear_trace)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.clear_trace()
|
||||
|
||||
|
||||
def set_temp_dir(temp_dir: str) -> None:
|
||||
"""设置全局 temp_dir(委托到 gen.set_temp_dir)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.set_temp_dir(temp_dir)
|
||||
|
||||
|
||||
def get_temp_dir() -> str:
|
||||
"""获取全局 temp_dir(委托到 gen.get_temp_dir)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_temp_dir()
|
||||
return None
|
||||
|
||||
|
||||
def set_current_module_sha1(sha1: str) -> None:
|
||||
"""设置当前正在编译的模块 SHA1(委托到 gen.set_current_module_sha1)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.set_current_module_sha1(sha1)
|
||||
|
||||
|
||||
def _dbg_check_ast_floats(mb: memhub.MemBuddy | t.CPtr,
|
||||
tree: ast.AST | t.CPtr, tag: str):
|
||||
"""已移除调试插桩(占位保留签名,避免外部调用引用失败)"""
|
||||
pass
|
||||
|
||||
|
||||
def register_cdefine_constant(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, value: t.CInt64T) -> None:
|
||||
"""注册 CDefine 编译期常量到本地表(委托到 gen.register_cdefine_constant)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.register_cdefine_constant(pool, name, value)
|
||||
|
||||
|
||||
def register_cdefine_double(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, value: double) -> None:
|
||||
"""注册浮点 CDefine 编译期常量(委托到 gen.register_cdefine_double)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.register_cdefine_double(pool, name, value)
|
||||
|
||||
|
||||
def register_cdefine_string(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, value: str) -> None:
|
||||
"""注册字符串 CDefine 编译期常量(委托到 gen.register_cdefine_string)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.register_cdefine_string(pool, name, value)
|
||||
|
||||
|
||||
def lookup_cdefine_constant(name: str) -> t.CInt64T:
|
||||
"""查找 CDefine 编译期常量(委托到 gen.lookup_cdefine_constant)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.lookup_cdefine_constant(name)
|
||||
return 0
|
||||
|
||||
|
||||
def lookup_cdefine_double(name: str) -> double:
|
||||
"""查找 CDefine 编译期常量,返回 double 值(委托到 gen.lookup_cdefine_double)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.lookup_cdefine_double(name)
|
||||
return 0.0
|
||||
|
||||
|
||||
def lookup_cdefine_string(name: str) -> str:
|
||||
"""查找 CDefine 编译期字符串值(委托到 gen.lookup_cdefine_string)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.lookup_cdefine_string(name)
|
||||
return None
|
||||
|
||||
|
||||
def is_cdefine_str() -> int:
|
||||
"""检查最近一次 CDefine 查找命中的是否是字符串常量(委托到 gen.is_cdefine_str)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_cdefine_str()
|
||||
return 0
|
||||
|
||||
|
||||
def eval_ctraits_isptr(symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
name: str) -> int:
|
||||
"""ctraits.isptr(name) 编译期求值(委托到 gen._eval_ctraits_isptr)。
|
||||
|
||||
返回: 1=指针 0=非指针 -1=无法求值。
|
||||
"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._eval_ctraits_isptr(symtab, name)
|
||||
return -1
|
||||
|
||||
|
||||
def is_cdefine_double() -> int:
|
||||
"""检查最近一次 CDefine 查找命中的是否是浮点常量(委托到 gen.is_cdefine_double)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_cdefine_double()
|
||||
return 0
|
||||
|
||||
|
||||
def is_cdefine_found() -> int:
|
||||
"""检查上次 lookup_cdefine_constant 是否找到值(委托到 gen.is_cdefine_found)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_cdefine_found()
|
||||
return 0
|
||||
|
||||
|
||||
def set_cdefine_found(val: int) -> None:
|
||||
"""设置 cdefine_found 标志(委托到 gen.set_cdefine_found)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.set_cdefine_found(val)
|
||||
|
||||
|
||||
def clear_cdefine_constants() -> None:
|
||||
"""清空 CDefine 常量表(委托到 gen.clear_cdefine_constants)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.clear_cdefine_constants()
|
||||
|
||||
|
||||
def register_xmod_cdefine(name: str, value_str: str,
|
||||
is_double: int, is_str: int) -> None:
|
||||
"""注册跨模块 CDefine 查找结果到 perm_pool 全局缓存(委托到 gen.register_xmod_cdefine)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.register_xmod_cdefine(name, value_str, is_double, is_str)
|
||||
|
||||
|
||||
def lookup_xmod_cdefine(name: str) -> str:
|
||||
"""查找跨模块 CDefine 缓存(委托到 gen.lookup_xmod_cdefine)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.lookup_xmod_cdefine(name)
|
||||
return None
|
||||
|
||||
|
||||
def register_ctypedef(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, type_str: str) -> None:
|
||||
"""注册 CTypedef 到本地表(委托到 gen.register_ctypedef)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.register_ctypedef(pool, name, type_str)
|
||||
|
||||
|
||||
def lookup_ctypedef(name: str) -> str:
|
||||
"""查找 CTypedef,返回类型表达式字符串(委托到 gen.lookup_ctypedef)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.lookup_ctypedef(name)
|
||||
return None
|
||||
|
||||
|
||||
def is_ctypedef_found() -> int:
|
||||
"""检查上次 lookup_ctypedef 是否找到值(委托到 gen.is_ctypedef_found)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_ctypedef_found()
|
||||
return 0
|
||||
|
||||
|
||||
def clear_ctypedefs() -> None:
|
||||
"""清空 CTypedef 表(委托到 gen.clear_ctypedefs)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.clear_ctypedefs()
|
||||
|
||||
|
||||
def _ctypedef_push_visiting(pool: memhub.MemBuddy | t.CPtr, name: str) -> int:
|
||||
"""将 CTypedef 名加入正在解析列表(委托到 gen._ctypedef_push_visiting)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._ctypedef_push_visiting(pool, name)
|
||||
return 0
|
||||
|
||||
|
||||
def _ctypedef_pop_visiting() -> None:
|
||||
"""从正在解析列表弹出最后一个 CTypedef 名(委托到 gen._ctypedef_pop_visiting)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g._ctypedef_pop_visiting()
|
||||
|
||||
|
||||
def _is_ctypedef_annotation(annotation: ast.AST | t.CPtr) -> int:
|
||||
"""检测类型注解是否为 t.CTypedef(委托到 gen._is_ctypedef_annotation)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._is_ctypedef_annotation(annotation)
|
||||
return 0
|
||||
|
||||
|
||||
def ScanCTypedefDeclarations(pool: memhub.MemBuddy | t.CPtr,
|
||||
tree: ast.AST | t.CPtr) -> int:
|
||||
"""扫描 AST 顶层节点,注册所有 NAME: t.CTypedef = Type 声明(委托到 gen.ScanCTypedefDeclarations)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.ScanCTypedefDeclarations(pool, tree)
|
||||
return 0
|
||||
|
||||
|
||||
def RegisterCTypedefFromSource(pool: memhub.MemBuddy | t.CPtr,
|
||||
src: str) -> int:
|
||||
"""从源码文本逐行注册 CTypedef 声明(委托到 gen.register_ctypedef_from_source)
|
||||
|
||||
stdint.vp 崩溃根因修复:AST 字符串字段(attr/id)token 零拷贝指向
|
||||
src_buf,跨阶段内容不稳定(悬空),ScanCTypedefDeclarations 读 attr
|
||||
会 0xC0000005。改用文本匹配 "NAME: t.CTypedef = TYPE"。
|
||||
"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.register_ctypedef_from_source(pool, src)
|
||||
return 0
|
||||
|
||||
|
||||
def _eval_const_int_expr(node: ast.AST | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr = None,
|
||||
from_imports: str = None,
|
||||
imported_modules: str = None) -> int:
|
||||
"""递归计算常量整数表达式(委托到 gen._eval_const_int_expr)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._eval_const_int_expr(node, pool, from_imports, imported_modules)
|
||||
return 0
|
||||
|
||||
|
||||
def set_generic_context(tp_names: list[str] | t.CPtr,
|
||||
type_args: list[str] | t.CPtr):
|
||||
"""设置泛型特化上下文(委托到 gen.set_generic_context)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.set_generic_context(tp_names, type_args)
|
||||
|
||||
|
||||
def clear_generic_context():
|
||||
"""清除泛型特化上下文(委托到 gen.clear_generic_context)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.clear_generic_context()
|
||||
|
||||
|
||||
def resolve_generic_type_name(name: str) -> str:
|
||||
"""如果 name 是泛型类型参数,返回对应的具体类型名(委托到 gen.resolve_generic_type_name)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.resolve_generic_type_name(name)
|
||||
return name
|
||||
|
||||
|
||||
def _get_type_name_from_annotation(pool: memhub.MemBuddy | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> str:
|
||||
"""从类型注解节点提取类型名(委托到 gen._get_type_name_from_annotation)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._get_type_name_from_annotation(pool, node)
|
||||
return None
|
||||
|
||||
|
||||
def _parse_type_string(pool: memhub.MemBuddy | t.CPtr,
|
||||
type_str: str,
|
||||
ctx: t.CInt) -> ast.AST | t.CPtr:
|
||||
"""将类型名字符串解析为 AST 节点(委托到 gen._parse_type_string)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._parse_type_string(pool, type_str, ctx)
|
||||
return None
|
||||
|
||||
|
||||
def set_current_file(file_path: str):
|
||||
"""设置当前编译的文件名(委托到 gen.set_current_file)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.set_current_file(file_path)
|
||||
|
||||
|
||||
def get_current_file() -> str:
|
||||
"""获取当前编译的文件名(委托到 gen.get_current_file)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_current_file()
|
||||
return None
|
||||
|
||||
|
||||
def _read_source_line(file_path: str, lineno: int) -> str:
|
||||
"""从源文件读取第 lineno 行内容(委托到 gen._read_source_line)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._read_source_line(file_path, lineno)
|
||||
return None
|
||||
|
||||
|
||||
def read_source_line(file_path: str, lineno: int) -> str:
|
||||
"""公开包装:从源文件读取第 lineno 行内容(委托到 gen.read_source_line)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.read_source_line(file_path, lineno)
|
||||
return None
|
||||
|
||||
|
||||
def dump_parse_traceback(file_path: str):
|
||||
"""解析失败时以 Python 风格输出 traceback(委托到 gen.dump_parse_traceback)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.dump_parse_traceback(file_path)
|
||||
|
||||
|
||||
def fatal_error(node: ast.AST | t.CPtr, msg: str,
|
||||
err_type: str = "SyntaxError",
|
||||
col_start: int = 0, col_end: int = 0):
|
||||
"""以 Python 风格报错并退出(委托到 gen.fatal_error)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.fatal_error(node, msg, err_type, col_start, col_end)
|
||||
|
||||
|
||||
def fatal_type_error(node: ast.AST | t.CPtr, msg: str,
|
||||
col_start: int = 0, col_end: int = 0):
|
||||
"""以 Python 风格报错并退出(TypeError 版本,委托到 gen.fatal_type_error)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.fatal_type_error(node, msg, col_start, col_end)
|
||||
|
||||
|
||||
def try_extract_callable_ret(pool: memhub.MemBuddy | t.CPtr,
|
||||
annot: ast.AST | t.CPtr,
|
||||
imported_modules: str,
|
||||
from_imports: str,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""提取 t.Callable 注解的返回类型 LLVMType(委托到 gen.try_extract_callable_ret)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.try_extract_callable_ret(pool, annot, imported_modules, from_imports, trans)
|
||||
return None
|
||||
|
||||
|
||||
def map_t_type(pool: memhub.MemBuddy | t.CPtr,
|
||||
type_name: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""将 t.CXxx / c.CXxx 类型名映射到 LLVMType(委托到 gen.map_t_type)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.map_t_type(pool, type_name)
|
||||
return None
|
||||
|
||||
|
||||
def _is_t_attr(node: ast.AST | t.CPtr,
|
||||
attr_name: str,
|
||||
imported_modules: str) -> int:
|
||||
"""检测节点是否是 t.attr_name 形式(委托到 gen._is_t_attr)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._is_t_attr(node, attr_name, imported_modules)
|
||||
return 0
|
||||
|
||||
|
||||
def _is_cptr_marker(node: ast.AST | t.CPtr,
|
||||
imported_modules: str) -> int:
|
||||
"""检测节点是否为 CPtr 指针标记(委托到 gen._is_cptr_marker)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._is_cptr_marker(node, imported_modules)
|
||||
return 0
|
||||
|
||||
|
||||
def _is_cvoid_marker(node: ast.AST | t.CPtr,
|
||||
imported_modules: str) -> int:
|
||||
"""检测节点是否为 CVoid 指针标记(委托到 gen._is_cvoid_marker)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._is_cvoid_marker(node, imported_modules)
|
||||
return 0
|
||||
|
||||
|
||||
def annotation_to_str(annot: ast.AST | t.CPtr) -> str:
|
||||
"""将类型注解 AST 转换为可读字符串(委托到 gen.annotation_to_str)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.annotation_to_str(annot)
|
||||
return None
|
||||
|
||||
|
||||
def extract_class_name_from_annotation(node: ast.AST | t.CPtr,
|
||||
imported_modules: str,
|
||||
pool: memhub.MemBuddy | t.CPtr = None) -> str:
|
||||
"""从类型注解 AST 中提取类名(委托到 gen.extract_class_name_from_annotation)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.extract_class_name_from_annotation(node, imported_modules, pool)
|
||||
return None
|
||||
|
||||
|
||||
def _resolve_generic_subscript_ty(pool: memhub.MemBuddy | t.CPtr,
|
||||
sub: ast.Subscript | t.CPtr,
|
||||
gen_cls_name: str,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
imported_modules: str,
|
||||
from_imports: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""解析泛型类类型注解(委托到 gen._resolve_generic_subscript_ty)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._resolve_generic_subscript_ty(pool, sub, gen_cls_name, trans,
|
||||
imported_modules, from_imports)
|
||||
return None
|
||||
|
||||
|
||||
def resolve_annotation_type(pool: memhub.MemBuddy | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
imported_modules: str,
|
||||
from_imports: str,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""解析类型注解节点为 LLVMType(委托到 gen.resolve_annotation_type)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.resolve_annotation_type(pool, node, imported_modules, from_imports, trans)
|
||||
return None
|
||||
|
||||
|
||||
def has_decorator_marker(node: ast.AST | t.CPtr,
|
||||
marker_name: str) -> int:
|
||||
"""检测类型注解中是否包含指定的装饰器标记(委托到 gen.has_decorator_marker)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.has_decorator_marker(node, marker_name)
|
||||
return 0
|
||||
|
||||
|
||||
def is_pass_body(body: list[ast.AST | t.CPtr] | t.CPtr) -> int:
|
||||
"""检测函数体是否为 pass(委托到 gen.is_pass_body)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_pass_body(body)
|
||||
return 0
|
||||
|
||||
|
||||
def get_llvm_type_bits(ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""获取 LLVM 整数类型的位宽(委托到 gen.get_llvm_type_bits)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_llvm_type_bits(ty)
|
||||
return 0
|
||||
|
||||
|
||||
def infer_expr_type(pool: memhub.MemBuddy | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
param_types: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""推断表达式的 LLVM 类型(委托到 gen.infer_expr_type)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.infer_expr_type(pool, node, param_types)
|
||||
return None
|
||||
|
||||
|
||||
def infer_return_type(pool: memhub.MemBuddy | t.CPtr,
|
||||
body: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
param_types: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""扫描函数体中的 return 语句,推断返回类型(委托到 gen.infer_return_type)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.infer_return_type(pool, body, param_types)
|
||||
return None
|
||||
|
||||
|
||||
def build_param_types_str(pool: memhub.MemBuddy | t.CPtr,
|
||||
args_node: ast.AST | t.CPtr) -> str:
|
||||
"""构建参数类型编码字符串(委托到 gen.build_param_types_str)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.build_param_types_str(pool, args_node)
|
||||
return None
|
||||
|
||||
|
||||
def _strappend(dst: str, dst_size: t.CSizeT, src: str):
|
||||
"""将 src 追加到 dst 末尾(委托到 gen._strappend)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g._strappend(dst, dst_size, src)
|
||||
@@ -1,371 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesVar - 嵌套作用域符号表 + 变量管理(P6 对象化后的委托层)
|
||||
#
|
||||
# 使用 Scope 链(Parent 指针)管理嵌套作用域,
|
||||
# 每个作用域包含一个 VarEntry 数组(扁平化,已验证可工作)。
|
||||
#
|
||||
# 作用域类型:
|
||||
# SCOPE_MODULE — 模块级(根作用域)
|
||||
# SCOPE_FUNCTION — 函数级
|
||||
# SCOPE_BLOCK — 块级(if/for/while,当前未使用块作用域)
|
||||
#
|
||||
# P6 对象化重构(wiki/14-oo-refactor.md):
|
||||
# 全部模块级函数已迁移为 lib.core.Gen.VarGenMixin 的方法(方法化迁移,
|
||||
# 无全局状态),本模块保留同名模块级函数作为"一行委托":延迟 import
|
||||
# Gen 取全局单例(BuildPipeline/main 创建后 set_global_gen 注册),
|
||||
# 再调用 gen 的对应方法。签名与旧函数完全一致,调用方零改动。
|
||||
#
|
||||
# VarEntry/Scope/SymbolTable 类型与常量保留在本模块(gen 方法签名引用)。
|
||||
# ============================================================
|
||||
|
||||
# 作用域类型常量
|
||||
SCOPE_MODULE: t.CDefine = 0
|
||||
SCOPE_FUNCTION: t.CDefine = 1
|
||||
SCOPE_BLOCK: t.CDefine = 2
|
||||
|
||||
# 每个作用域最大变量数
|
||||
# 256 太小:NewAstTest main() 有 289 个局部变量,add_var 超限静默失败
|
||||
# 导致变量未注册,后续使用报"未定义名称"(与 Gen/VarGenMixin 保持一致)。
|
||||
MAX_VARS: t.CDefine = 1024
|
||||
|
||||
|
||||
# ============================================================
|
||||
# VarEntry - 变量表条目
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class VarEntry:
|
||||
"""变量表条目"""
|
||||
Name: str
|
||||
Alloca: llvmlite.Value | t.CPtr
|
||||
Used: t.CInt
|
||||
AnnotClassName: str # 原始类型注解的类名(str 别名在结构体字段中触发编译器 bug,改用显式联合类型)
|
||||
IsPtrElement: t.CInt # 标志: 1=注解为 bytes|t.CPtr 或 str|t.CPtr, 下标按 8 字节步长
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Scope - 作用域节点
|
||||
#
|
||||
# Parent 指向父作用域(None 表示根),
|
||||
# Vars 是 VarEntry 数组,VarCount 是当前变量数。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class Scope:
|
||||
"""作用域节点"""
|
||||
Parent: Scope | t.CPtr
|
||||
Vars: VarEntry | t.CPtr
|
||||
VarCount: t.CInt
|
||||
Kind: t.CInt
|
||||
|
||||
|
||||
# ============================================================
|
||||
# SymbolTable - 嵌套作用域符号表
|
||||
#
|
||||
# Root 是模块级根作用域,Current 是当前作用域。
|
||||
# enter_scope/exit_scope 管理作用域栈。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class SymbolTable:
|
||||
"""嵌套作用域符号表"""
|
||||
Pool: memhub.MemBuddy | t.CPtr
|
||||
Root: Scope | t.CPtr
|
||||
Current: Scope | t.CPtr
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# P6 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# VarGenMixin 方法,避免函数体 import 包模块与 Generator
|
||||
# 类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 委托函数:延迟 import Gen 取全局单例 → 调 gen 方法
|
||||
# (gen 未注册时正常流程不会发生;有返回值函数返回默认值)
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# init_vars — 分配并清零 VarEntry 数组
|
||||
# ============================================================
|
||||
def init_vars(pool: memhub.MemBuddy | t.CPtr) -> VarEntry | t.CPtr:
|
||||
"""分配并清零变量表数组(委托到 gen.init_vars)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.init_vars(pool)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# find_var — 在变量表中按名称查找
|
||||
# ============================================================
|
||||
def find_var(vars_ptr: VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""在变量表中按名称查找(委托到 gen.find_var)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.find_var(vars_ptr, var_count, name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# find_var_entry — 在变量表中按名称查找,返回 VarEntry(含 AnnotTy)
|
||||
# ============================================================
|
||||
def find_var_entry(vars_ptr: VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str) -> VarEntry | t.CPtr:
|
||||
"""在变量表中按名称查找,返回 VarEntry 或 None(委托到 gen.find_var_entry)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.find_var_entry(vars_ptr, var_count, name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# lookup_var_entry — 从当前作用域逐级向上查找变量,返回 VarEntry
|
||||
# ============================================================
|
||||
def lookup_var_entry(symtab: SymbolTable | t.CPtr,
|
||||
name: str) -> VarEntry | t.CPtr:
|
||||
"""从当前作用域逐级向上查找变量,返回 VarEntry 或 None(委托到 gen.lookup_var_entry)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.lookup_var_entry(symtab, name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# set_var_annot_class_name — 设置变量的原始类型注解类名
|
||||
#
|
||||
# 在函数参数定义后调用,存储原始类型注解的类名。
|
||||
# 方法调用检测时,当 alloca 类型是 Ptr(i8)(联合类型简化),
|
||||
# 通过 AnnotClassName 查找实际结构体类型。
|
||||
# ============================================================
|
||||
def set_var_annot_class_name(symtab: SymbolTable | t.CPtr,
|
||||
name: str,
|
||||
class_name: str) -> int:
|
||||
"""设置变量的原始类型注解类名,返回 0=成功 / 1=失败(委托到 gen.set_var_annot_class_name)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.set_var_annot_class_name(symtab, name, class_name)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# set_var_ptr_element — 标记变量为"指针到 str/bytes"类型
|
||||
#
|
||||
# 注解为 bytes|t.CPtr 或 str|t.CPtr 的变量,其 alloca 类型是 i8*,
|
||||
# 但下标访问应按 8 字节步长(i8** 语义),而非 1 字节步长(i8* 语义)。
|
||||
# 此标志在 HandlesAnnAssign 中根据注解形式设置。
|
||||
# ============================================================
|
||||
def set_var_ptr_element(symtab: SymbolTable | t.CPtr,
|
||||
name: str) -> int:
|
||||
"""标记变量为 ptr_element 类型,返回 0=成功 / 1=失败(委托到 gen.set_var_ptr_element)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.set_var_ptr_element(symtab, name)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# add_var — 添加变量到变量表
|
||||
# ============================================================
|
||||
def add_var(vars_ptr: VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str,
|
||||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""添加变量到变量表(委托到 gen.add_var)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.add_var(vars_ptr, var_count, name, alloca)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _alloca_at_entry - 在函数入口块生成 alloca(确保支配性)
|
||||
#
|
||||
# LLVM IR 要求指令支配所有使用点。如果 alloca 在条件分支内生成,
|
||||
# 但在其他分支使用,会违反支配性(Instruction does not dominate all uses)。
|
||||
# 标准做法:所有 alloca 在函数入口块生成。
|
||||
#
|
||||
# 临时切换 builder.CurBlock 到入口块,生成 alloca,然后恢复。
|
||||
# ============================================================
|
||||
def _alloca_at_entry(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""在函数入口块生成 alloca,返回 alloca 值(委托到 gen._alloca_at_entry)
|
||||
|
||||
使用 llvmlite.build_alloca_at_entry 在入口块终止指令之前插入 alloca,
|
||||
确保所有 alloca 在入口块,避免支配性违规。
|
||||
"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._alloca_at_entry(builder, ty)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# get_or_create_var — 查找或创建变量 alloca(旧版兼容)
|
||||
# ============================================================
|
||||
def get_or_create_var(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
vars_ptr: VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""查找或创建变量 alloca(委托到 gen.get_or_create_var)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_or_create_var(pool, builder, vars_ptr, var_count, name, ty)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _create_scope — 创建新作用域节点(内部辅助函数)
|
||||
# ============================================================
|
||||
def _create_scope(pool: memhub.MemBuddy | t.CPtr,
|
||||
parent: Scope | t.CPtr,
|
||||
kind: int) -> Scope | t.CPtr:
|
||||
"""创建并初始化作用域节点(委托到 gen._create_scope)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._create_scope(pool, parent, kind)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# init_symbol_table — 创建符号表(含模块级根作用域)
|
||||
# ============================================================
|
||||
def init_symbol_table(pool: memhub.MemBuddy | t.CPtr) -> SymbolTable | t.CPtr:
|
||||
"""创建并初始化符号表,包含模块级根作用域(委托到 gen.init_symbol_table)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.init_symbol_table(pool)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# enter_scope — 进入新作用域
|
||||
# ============================================================
|
||||
def enter_scope(symtab: SymbolTable | t.CPtr,
|
||||
kind: int) -> Scope | t.CPtr:
|
||||
"""进入新作用域,返回新创建的作用域(委托到 gen.enter_scope)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.enter_scope(symtab, kind)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# exit_scope — 退出当前作用域
|
||||
# ============================================================
|
||||
def exit_scope(symtab: SymbolTable | t.CPtr):
|
||||
"""退出当前作用域,恢复到父作用域(委托到 gen.exit_scope)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g.exit_scope(symtab)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# define_var — 在当前作用域定义变量
|
||||
# ============================================================
|
||||
def define_var(symtab: SymbolTable | t.CPtr,
|
||||
name: str,
|
||||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""在当前作用域定义变量,返回 0 成功(委托到 gen.define_var)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.define_var(symtab, name, alloca)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# define_module_var — 在模块作用域定义变量
|
||||
# ============================================================
|
||||
def define_module_var(symtab: SymbolTable | t.CPtr,
|
||||
name: str,
|
||||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""在模块作用域定义变量,返回 0 成功(委托到 gen.define_module_var)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.define_module_var(symtab, name, alloca)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# lookup_var — 从当前作用域逐级向上查找变量
|
||||
# ============================================================
|
||||
def lookup_var(symtab: SymbolTable | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""从当前作用域逐级向上查找变量,返回 alloca 或 None(委托到 gen.lookup_var)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.lookup_var(symtab, name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# lookup_current — 仅在当前作用域查找变量
|
||||
# ============================================================
|
||||
def lookup_current(symtab: SymbolTable | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""仅在当前作用域查找变量(委托到 gen.lookup_current)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.lookup_current(symtab, name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# lookup_module_var — 在模块作用域查找变量
|
||||
# ============================================================
|
||||
def lookup_module_var(symtab: SymbolTable | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""在模块作用域查找变量(委托到 gen.lookup_module_var)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.lookup_module_var(symtab, name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# is_module_scope - 判断当前是否在模块级作用域
|
||||
#
|
||||
# 用于区分模块级代码和函数内代码:
|
||||
# - 模块级代码:AnnAssign 应修改模块级变量(Python 语义)
|
||||
# - 函数内代码:无 global 声明时 AnnAssign 应创建局部变量(Python 语义)
|
||||
# ============================================================
|
||||
def is_module_scope(symtab: SymbolTable | t.CPtr) -> int:
|
||||
"""判断当前作用域是否为模块级作用域(Current == Root,委托到 gen.is_module_scope)
|
||||
|
||||
Returns: 1=模块级作用域, 0=函数内作用域
|
||||
"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_module_scope(symtab)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# get_or_create_sym — 查找或创建变量(在当前作用域)
|
||||
# ============================================================
|
||||
def get_or_create_sym(symtab: SymbolTable | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
name: str,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""查找或创建变量 alloca(在当前作用域,委托到 gen.get_or_create_sym)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_or_create_sym(symtab, pool, builder, name, ty)
|
||||
return None
|
||||
@@ -1,40 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import memhub
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Gen.Generator as Generator
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesWhile - while 循环语句处理(迁移完成,保留跨 Mixin 委托壳)
|
||||
#
|
||||
# P6 机械化迁移:WhileHandle 类 → StmtGenCifMixin.translate_while;
|
||||
# 模块级辅助 _IsConstTrue/_NodeHasBreak/_StmtHasBreak → StmtGenCifMixin
|
||||
# 方法(merge 可达性判定)。
|
||||
# 分派中枢(StmtGenMixin)经本壳跨链调用(Viper @t.NoVTable 静态绑定下
|
||||
# 跨 Mixin self. 调用 mangle 失败,须经模块级委托壳桥回 gen 单例)。
|
||||
# 迁移收尾(编译器缺陷修复)后统一删除。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# StmtGenCifMixin 方法,避免函数体 import 包模块与类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: Generator.Generator | t.CPtr = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# translate_while - while 循环语句翻译(委托到 gen.translate_while)
|
||||
# ============================================================
|
||||
def translate_while(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 while 循环语句(委托到 gen.translate_while)"""
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_while(trans, node)
|
||||
return 0
|
||||
@@ -1,23 +1,9 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
|
||||
# Handles 模块(绝对导入,Viper 兼容)
|
||||
# 参考 Python 版 TransPyC lib/core/Handles 的细粒度拆分
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesExprOps as HandlesExprOps
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesAssign as HandlesAssign
|
||||
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
|
||||
import lib.core.Handles.HandlesReturn as HandlesReturn
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.Handles.HandlesBody as HandlesBody
|
||||
import lib.core.Handles.HandlesIf as HandlesIf
|
||||
import lib.core.Handles.HandlesWhile as HandlesWhile
|
||||
import lib.core.Handles.HandlesFor as HandlesFor
|
||||
import lib.core.Handles.HandlesAugAssign as HandlesAugAssign
|
||||
import lib.core.Handles.HandlesMain as HandlesMain
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import t, c
|
||||
from stdint import *
|
||||
|
||||
# Handles 实体模块(去除委托层后保留:数据类/Translator/实体逻辑)
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.ExprCallTable as ExprCallTable
|
||||
+41
-46
@@ -1,46 +1,41 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import string
|
||||
import stdlib
|
||||
import memhub
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import w32.win32file
|
||||
import w32.win32base
|
||||
import ast
|
||||
import llvmlite
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.Gen.Generator as GenGenerator
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.BuildPipeline as BuildPipeline
|
||||
import lib.Projectrans.Config as Config
|
||||
import lib.StubGen.Converter as StubConverter
|
||||
import lib.core.StubMergerBuild as StubMergerBuild
|
||||
import lib.core.StubMergerCollect as StubMergerCollect
|
||||
import lib.core.StubMergerIR as StubMergerIR
|
||||
import lib.core.StubMergerStore as StubMergerStore
|
||||
import lib.core.Handles.ExprCallCtor as ExprCallCtor
|
||||
|
||||
# 全局 mbuddy 指针
|
||||
_mbuddy: memhub.MemBuddy | t.CPtr
|
||||
|
||||
# 源代码缓冲区大小(1MB)
|
||||
SRC_BUF_SIZE: t.CDefine = 1048576
|
||||
|
||||
# vpi 缓冲区大小(256KB)
|
||||
PYI_BUF_SIZE: t.CSizeT = 262144
|
||||
|
||||
# 拓扑排序相关常量
|
||||
MAX_CLASSES: t.CDefine = 512
|
||||
MAX_FILE_DEPS: t.CDefine = 256
|
||||
MAX_DEP_EDGES: t.CDefine = 16
|
||||
SHA1_LEN: t.CDefine = 17
|
||||
CLASS_NAME_LEN: t.CDefine = 64
|
||||
import t, c
|
||||
from stdint import *
|
||||
import string
|
||||
import stdlib
|
||||
import memhub
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import w32.win32file
|
||||
import w32.win32base
|
||||
import ast
|
||||
import llvmlite
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.Gen.Generator as GenGenerator
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.BuildPipeline as BuildPipeline
|
||||
import lib.Projectrans.Config as Config
|
||||
import lib.StubGen.Converter as StubConverter
|
||||
import lib.core.StubMergerBuild as StubMergerBuild
|
||||
import lib.core.StubMergerCollect as StubMergerCollect
|
||||
import lib.core.StubMergerIR as StubMergerIR
|
||||
import lib.core.StubMergerStore as StubMergerStore
|
||||
|
||||
# 全局 mbuddy 指针
|
||||
_mbuddy: memhub.MemBuddy | t.CPtr
|
||||
|
||||
# 源代码缓冲区大小(1MB)
|
||||
SRC_BUF_SIZE: t.CDefine = 1048576
|
||||
|
||||
# vpi 缓冲区大小(256KB)
|
||||
PYI_BUF_SIZE: t.CSizeT = 262144
|
||||
|
||||
# 拓扑排序相关常量
|
||||
MAX_CLASSES: t.CDefine = 512
|
||||
MAX_FILE_DEPS: t.CDefine = 256
|
||||
MAX_DEP_EDGES: t.CDefine = 16
|
||||
SHA1_LEN: t.CDefine = 17
|
||||
CLASS_NAME_LEN: t.CDefine = 64
|
||||
+969
-973
File diff suppressed because it is too large.
Load diff
+501
-505
File diff suppressed because it is too large.
Load diff
+412
-417
@@ -1,417 +1,412 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import string
|
||||
import stdlib
|
||||
import memhub
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import w32.win32file
|
||||
import w32.win32base
|
||||
import ast
|
||||
import llvmlite
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.Gen.Generator as GenGenerator
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.BuildPipeline as BuildPipeline
|
||||
import lib.Projectrans.Config as Config
|
||||
import lib.StubGen.Converter as StubConverter
|
||||
import lib.core.StubMergerBuild as StubMergerBuild
|
||||
import lib.core.StubMergerCollect as StubMergerCollect
|
||||
import lib.core.StubMergerIR as StubMergerIR
|
||||
import lib.core.StubMergerStore as StubMergerStore
|
||||
import lib.core.Handles.ExprCallCtor as ExprCallCtor
|
||||
|
||||
|
||||
import lib.core.Phase1Scan as Phase1Scan
|
||||
import lib.core.Phase1Main as Phase1Main
|
||||
import lib.core.Phase1 as Phase1
|
||||
|
||||
# ============================================================
|
||||
# Phase1Topo - Phase1 拆分(阶段 E):Phase1Topo
|
||||
#
|
||||
# 直接移动模式:函数迁至此模块,原 Phase1.vp 仅保留常量/_mbuddy;
|
||||
# 调用方经本模块前缀访问。全局符号经 Phase1._xxx 跨模块访问。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# _TopoSortFiles - 根据类继承关系对文件进行拓扑排序
|
||||
#
|
||||
# 算法(Kahn):
|
||||
# 1. 从扁平类信息数组构建"文件 SHA1 → 依赖文件 SHA1 集合"映射
|
||||
# 2. 计算每个文件的入度(依赖数量)
|
||||
# 3. 入度为 0 的文件先处理,处理后减少依赖它的文件入度
|
||||
# 4. 重复直到所有文件处理完成
|
||||
#
|
||||
# 注意:依赖方向是"父类所在文件 → 子类所在文件",
|
||||
# 即父类文件必须先处理。Kahn 用 DepCount 作为剩余依赖计数,
|
||||
# 依赖为 0 的先处理,初始化 InDegree = DepCount。
|
||||
#
|
||||
# Args:
|
||||
# mb: 内存池
|
||||
# result: IncludesScanner 扫描结果
|
||||
# reachable_set: 可达 SHA1 集合
|
||||
# reachable_count: 可达 SHA1 数量
|
||||
# use_reachable: 是否使用可达集合过滤
|
||||
# sha1_set: SHA1 集合
|
||||
# set_count: SHA1 集合数量
|
||||
# class_names_buf: 类名扁平数组
|
||||
# parent_names_buf: 父类名扁平数组
|
||||
# def_sha1s_buf: 定义 SHA1 扁平数组
|
||||
# class_count: 类数量
|
||||
# out_order: 输出拓扑顺序的文件索引数组(调用者分配,int 数组)
|
||||
# out_count: 输出文件数量
|
||||
#
|
||||
# Returns:
|
||||
# 0 成功,-1 失败
|
||||
# ============================================================
|
||||
def _TopoSortFiles(mb: memhub.MemBuddy | t.CPtr,
|
||||
result: IncludesScanner.ScanResult | t.CPtr,
|
||||
reachable_set: str, reachable_count: int,
|
||||
use_reachable: int,
|
||||
sha1_set: str, set_count: int,
|
||||
class_names_buf: bytes, parent_names_buf: bytes,
|
||||
def_sha1s_buf: bytes, class_count: int,
|
||||
out_order: t.CPtr, out_count: t.CPtr,
|
||||
temp_dir: str, td_len_ts: t.CSizeT) -> int:
|
||||
"""根据类继承关系对文件进行拓扑排序"""
|
||||
if result is None or out_order is None or out_count is None:
|
||||
return -1
|
||||
|
||||
entry_size: t.CSizeT = IncludesScanner.FileEntry.__sizeof__()
|
||||
|
||||
# 1. 分配扁平数组:文件 SHA1、依赖 SHA1 列表、依赖数量、入度、处理状态
|
||||
# 用扁平数组代替 FileDepEntry 结构体,避免 str 指针字段 NULL 崩溃
|
||||
file_sha1s_buf: bytes = mb.alloc(Phase1.MAX_FILE_DEPS * Phase1.SHA1_LEN)
|
||||
file_deps_buf: bytes = mb.alloc(Phase1.MAX_FILE_DEPS * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN)
|
||||
file_dep_counts: t.CPtr = mb.alloc(Phase1.MAX_FILE_DEPS * 4)
|
||||
file_indegrees: t.CPtr = mb.alloc(Phase1.MAX_FILE_DEPS * 4)
|
||||
file_processed: t.CPtr = mb.alloc(Phase1.MAX_FILE_DEPS * 4)
|
||||
|
||||
if file_sha1s_buf is None or file_deps_buf is None or file_dep_counts is None or file_indegrees is None or file_processed is None:
|
||||
if file_sha1s_buf is not None:
|
||||
mb.free(file_sha1s_buf)
|
||||
if file_deps_buf is not None:
|
||||
mb.free(file_deps_buf)
|
||||
if file_dep_counts is not None:
|
||||
mb.free(file_dep_counts)
|
||||
if file_indegrees is not None:
|
||||
mb.free(file_indegrees)
|
||||
if file_processed is not None:
|
||||
mb.free(file_processed)
|
||||
return -1
|
||||
|
||||
string.memset(file_sha1s_buf, 0, Phase1.MAX_FILE_DEPS * Phase1.SHA1_LEN)
|
||||
string.memset(file_deps_buf, 0, Phase1.MAX_FILE_DEPS * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN)
|
||||
string.memset(file_dep_counts, 0, Phase1.MAX_FILE_DEPS * 4)
|
||||
string.memset(file_indegrees, 0, Phase1.MAX_FILE_DEPS * 4)
|
||||
string.memset(file_processed, 0, Phase1.MAX_FILE_DEPS * 4)
|
||||
|
||||
file_count: int = 0
|
||||
# sha1→file_index 映射(简单线性查找,文件数不多)
|
||||
for i in range(result.Count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size
|
||||
entry: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
if entry is None or entry.Sha1 is None:
|
||||
continue
|
||||
|
||||
sha1_e: str = entry.Sha1
|
||||
in_set: int = 0
|
||||
if use_reachable != 0:
|
||||
in_set = StubMergerCollect._is_in_sha1_set(sha1_e, reachable_set, reachable_count)
|
||||
else:
|
||||
in_set = StubMergerCollect._is_in_sha1_set(sha1_e, sha1_set, set_count)
|
||||
if in_set == 0:
|
||||
continue
|
||||
|
||||
if file_count >= Phase1.MAX_FILE_DEPS:
|
||||
break
|
||||
|
||||
# 初始化扁平数组:文件 SHA1(偏移 = file_count * Phase1.SHA1_LEN)
|
||||
# DepCount/InDegree/Processed 已由 memset 清零
|
||||
sha1_dst: str = file_sha1s_buf + file_count * Phase1.SHA1_LEN
|
||||
string.strcpy(sha1_dst, sha1_e)
|
||||
|
||||
file_count += 1
|
||||
|
||||
# 2. 构建依赖边:对每个类,找到父类定义所在文件,建立 子文件→父文件 依赖
|
||||
for ci in range(class_count):
|
||||
# 读取父类名(偏移 = ci * Phase1.CLASS_NAME_LEN)
|
||||
parent_ptr: str = parent_names_buf + ci * Phase1.CLASS_NAME_LEN
|
||||
if parent_ptr[0] == '\0':
|
||||
continue
|
||||
|
||||
# 读取子类定义 SHA1(偏移 = ci * Phase1.SHA1_LEN)
|
||||
child_def_sha1: str = def_sha1s_buf + ci * Phase1.SHA1_LEN
|
||||
|
||||
# 查找父类定义所在文件的 SHA1
|
||||
parent_sha1: str = Phase1Scan._FindClassDefSha1(class_names_buf, def_sha1s_buf, class_count, parent_ptr)
|
||||
if parent_sha1 is None:
|
||||
continue # 父类不在 includes 中(如 Object、CEnum 等标记基类)
|
||||
|
||||
# 父类文件 SHA1 不能等于子类文件 SHA1(同文件内继承不需要依赖)
|
||||
if string.strcmp(parent_sha1, child_def_sha1) == 0:
|
||||
continue
|
||||
|
||||
# 找到子类文件对应的索引,添加父文件 SHA1 到依赖列表
|
||||
for fi in range(file_count):
|
||||
fsha1: str = file_sha1s_buf + fi * Phase1.SHA1_LEN
|
||||
if string.strcmp(fsha1, child_def_sha1) != 0:
|
||||
continue
|
||||
|
||||
# 读取当前依赖数量
|
||||
cnt_addr: t.CUInt64T = t.CUInt64T(file_dep_counts) + fi * 4
|
||||
cnt_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr, t.CPtr))
|
||||
if cnt_ptr is None:
|
||||
break
|
||||
cur_cnt: int = cnt_ptr[0]
|
||||
|
||||
# 检查依赖是否已添加(去重)
|
||||
already: int = 0
|
||||
for di in range(cur_cnt):
|
||||
dep_slot: str = file_deps_buf + fi * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + di * Phase1.SHA1_LEN
|
||||
if string.strcmp(dep_slot, parent_sha1) == 0:
|
||||
already = 1
|
||||
break
|
||||
if already != 0:
|
||||
break
|
||||
|
||||
if cur_cnt < Phase1.MAX_DEP_EDGES:
|
||||
dep_dst: str = file_deps_buf + fi * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + cur_cnt * Phase1.SHA1_LEN
|
||||
string.strcpy(dep_dst, parent_sha1)
|
||||
cnt_ptr[0] = cur_cnt + 1
|
||||
break
|
||||
|
||||
# 2.5 补充 import 依赖边:被 import 的模块先完整翻译。
|
||||
#
|
||||
# 仅按类继承建边不够:跨模块全局变量 stub(lexer.vp from-import
|
||||
# tokens.vp 的 _op_head)、跨模块 vtable TypeStr(astaux 继承 base 的
|
||||
# AST)、泛型模板(base.vp 用 list[...])都要求依赖模块先翻译,而它们
|
||||
# 之间可能无类继承关系。deps(_includes_deps_*)由 Phase 1a-pre 填充
|
||||
# (含容器按需注入的 _list/_dict)。
|
||||
#
|
||||
# 用 _BuildIncludesSha1Map 复制局部 sha1→模块名 数组(与
|
||||
# _BuildReachableSha1Set 的 BFS 一致),避免直接使用全局 store 返回值
|
||||
# 跨函数传参(bytes|t.CPtr 联合转 str 参数)的地址异常。
|
||||
sha1_arr_ts: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 17)
|
||||
mod_arr_ts: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 64)
|
||||
map_count_ts: int = 0
|
||||
if sha1_arr_ts is not None and mod_arr_ts is not None:
|
||||
map_count_ts = StubMergerIR._BuildIncludesSha1Map(
|
||||
temp_dir, td_len_ts, sha1_arr_ts, mod_arr_ts)
|
||||
for fi_imp in range(file_count):
|
||||
if map_count_ts <= 0:
|
||||
break
|
||||
fsha1_imp: str = file_sha1s_buf + fi_imp * Phase1.SHA1_LEN
|
||||
deps_imp: str = StubMergerStore.LookupIncludesDeps(fsha1_imp)
|
||||
if deps_imp is None:
|
||||
continue
|
||||
dl_imp: t.CSizeT = string.strlen(deps_imp)
|
||||
dpos_imp: t.CSizeT = 0
|
||||
while dpos_imp < dl_imp:
|
||||
dstart_imp: t.CSizeT = dpos_imp
|
||||
while dpos_imp < dl_imp and deps_imp[dpos_imp] != ' ':
|
||||
dpos_imp += 1
|
||||
dlen_imp: t.CSizeT = dpos_imp - dstart_imp
|
||||
if dpos_imp < dl_imp:
|
||||
dpos_imp += 1
|
||||
if dlen_imp == 0:
|
||||
continue
|
||||
dname_imp: bytes = stdlib.malloc(dlen_imp + 1)
|
||||
if dname_imp is None:
|
||||
continue
|
||||
string.strncpy(dname_imp, deps_imp + dstart_imp, dlen_imp)
|
||||
dname_imp[dlen_imp] = '\0'
|
||||
dsha1_imp: str = StubMergerIR._FindSha1ByModName(
|
||||
sha1_arr_ts, mod_arr_ts, map_count_ts, dname_imp)
|
||||
stdlib.free(dname_imp)
|
||||
if dsha1_imp is None:
|
||||
continue
|
||||
# 找依赖文件在列表中的索引(跳过自身)
|
||||
for fj_imp in range(file_count):
|
||||
if string.strcmp(file_sha1s_buf + fj_imp * Phase1.SHA1_LEN, dsha1_imp) != 0:
|
||||
continue
|
||||
if fj_imp == fi_imp:
|
||||
break
|
||||
# 去重 + 加边:fi_imp 依赖 fj_imp(InDegree[fi_imp]++)
|
||||
cnt_addr_imp: t.CUInt64T = t.CUInt64T(file_dep_counts) + fi_imp * 4
|
||||
cnt_ptr_imp: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr_imp, t.CPtr))
|
||||
if cnt_ptr_imp is None:
|
||||
break
|
||||
cur_cnt_imp: int = cnt_ptr_imp[0]
|
||||
already_imp: int = 0
|
||||
for di_imp in range(cur_cnt_imp):
|
||||
dep_slot_imp: str = file_deps_buf + fi_imp * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + di_imp * Phase1.SHA1_LEN
|
||||
if string.strcmp(dep_slot_imp, dsha1_imp) == 0:
|
||||
already_imp = 1
|
||||
break
|
||||
if already_imp == 0 and cur_cnt_imp < Phase1.MAX_DEP_EDGES:
|
||||
dep_dst_imp: str = file_deps_buf + fi_imp * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + cur_cnt_imp * Phase1.SHA1_LEN
|
||||
string.strcpy(dep_dst_imp, dsha1_imp)
|
||||
cnt_ptr_imp[0] = cur_cnt_imp + 1
|
||||
break
|
||||
|
||||
# 释放 import 边用的局部映射数组
|
||||
if sha1_arr_ts is not None:
|
||||
stdlib.free(sha1_arr_ts)
|
||||
if mod_arr_ts is not None:
|
||||
stdlib.free(mod_arr_ts)
|
||||
|
||||
# 3. Kahn 算法:InDegree = DepCount(依赖多少个父文件)
|
||||
# 依赖为 0 的先处理,处理后减少依赖它的文件入度
|
||||
for fi in range(file_count):
|
||||
cnt_addr3: t.CUInt64T = t.CUInt64T(file_dep_counts) + fi * 4
|
||||
cnt_ptr3: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr3, t.CPtr))
|
||||
ind_addr3: t.CUInt64T = t.CUInt64T(file_indegrees) + fi * 4
|
||||
ind_ptr3: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(ind_addr3, t.CPtr))
|
||||
if cnt_ptr3 is not None and ind_ptr3 is not None:
|
||||
ind_ptr3[0] = cnt_ptr3[0]
|
||||
|
||||
# 4. 拓扑排序输出
|
||||
out_idx: int = 0
|
||||
changed: int = 1
|
||||
while changed != 0:
|
||||
changed = 0
|
||||
for fi in range(file_count):
|
||||
# 检查处理状态
|
||||
proc_addr4: t.CUInt64T = t.CUInt64T(file_processed) + fi * 4
|
||||
proc_ptr4: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr4, t.CPtr))
|
||||
if proc_ptr4 is None or proc_ptr4[0] != 0:
|
||||
continue
|
||||
# 检查入度
|
||||
ind_addr4: t.CUInt64T = t.CUInt64T(file_indegrees) + fi * 4
|
||||
ind_ptr4: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(ind_addr4, t.CPtr))
|
||||
if ind_ptr4 is None or ind_ptr4[0] > 0:
|
||||
continue
|
||||
|
||||
# 入度为 0,可以处理
|
||||
# 找到对应的 result.Entries 索引
|
||||
target_sha1: str = file_sha1s_buf + fi * Phase1.SHA1_LEN
|
||||
for ri in range(result.Count):
|
||||
ea_r: t.CUInt64T = t.CUInt64T(result.Entries) + ri * entry_size
|
||||
ent_r: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea_r, t.CPtr))
|
||||
if ent_r is not None and ent_r.Sha1 is not None:
|
||||
if string.strcmp(ent_r.Sha1, target_sha1) == 0:
|
||||
# 写入输出索引数组
|
||||
out_idx_addr: t.CUInt64T = t.CUInt64T(out_order) + out_idx * 4
|
||||
out_int_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(out_idx_addr, t.CPtr))
|
||||
if out_int_ptr is not None:
|
||||
out_int_ptr[0] = ri
|
||||
out_idx += 1
|
||||
break
|
||||
|
||||
# 标记已处理
|
||||
proc_ptr4[0] = 1
|
||||
changed = 1
|
||||
|
||||
# 减少依赖该文件的其他文件的入度
|
||||
for fj in range(file_count):
|
||||
proc_addr5: t.CUInt64T = t.CUInt64T(file_processed) + fj * 4
|
||||
proc_ptr5: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr5, t.CPtr))
|
||||
if proc_ptr5 is None or proc_ptr5[0] != 0:
|
||||
continue
|
||||
# 读取 fj 的依赖数量
|
||||
cnt_addr5: t.CUInt64T = t.CUInt64T(file_dep_counts) + fj * 4
|
||||
cnt_ptr5: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr5, t.CPtr))
|
||||
if cnt_ptr5 is None:
|
||||
continue
|
||||
fj_dep_cnt: int = cnt_ptr5[0]
|
||||
for di in range(fj_dep_cnt):
|
||||
dep_slot5: str = file_deps_buf + fj * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + di * Phase1.SHA1_LEN
|
||||
if string.strcmp(dep_slot5, target_sha1) == 0:
|
||||
ind_addr5: t.CUInt64T = t.CUInt64T(file_indegrees) + fj * 4
|
||||
ind_ptr5: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(ind_addr5, t.CPtr))
|
||||
if ind_ptr5 is not None:
|
||||
ind_ptr5[0] = ind_ptr5[0] - 1
|
||||
break
|
||||
|
||||
# 处理循环依赖:环内优先输出"被依赖者"(被其余剩余文件依赖数量多者先)。
|
||||
#
|
||||
# 背景:容器按需注入(string 用 list 泛型 → 依赖 _list)与真实 import
|
||||
# (_list import string)形成伪环,Kahn 无法完全归零。若按扫描顺序追加,
|
||||
# 依赖者(astaux)会先于被依赖者(base)翻译 → 跨模块 vtable TypeStr
|
||||
# 未注册 → 误杀。被依赖者先翻译,其 stub/TypeStr/模板先就绪,依赖者
|
||||
# 翻译时可引用(函数/全局声明由 1a-pre 的 vpi 兜底)。
|
||||
if out_idx < file_count:
|
||||
rem_idx: t.CPtr = stdlib.malloc(4 * file_count)
|
||||
rem_depcnt: t.CPtr = stdlib.malloc(4 * file_count)
|
||||
rem_count: int = 0
|
||||
if rem_idx is not None and rem_depcnt is not None:
|
||||
for fi in range(file_count):
|
||||
proc_addr7: t.CUInt64T = t.CUInt64T(file_processed) + fi * 4
|
||||
proc_ptr7: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr7, t.CPtr))
|
||||
if proc_ptr7 is not None and proc_ptr7[0] == 0:
|
||||
rem_idx[rem_count] = fi
|
||||
rem_depcnt[rem_count] = 0
|
||||
rem_count += 1
|
||||
# 计算每个剩余文件的被依赖数(被其余剩余文件依赖)
|
||||
for i_a in range(rem_count):
|
||||
fi_a: int = rem_idx[i_a]
|
||||
target_sha1_a: str = file_sha1s_buf + fi_a * Phase1.SHA1_LEN
|
||||
for i_b in range(rem_count):
|
||||
fi_b: int = rem_idx[i_b]
|
||||
if fi_b == fi_a:
|
||||
continue
|
||||
cnt_addr_b: t.CUInt64T = t.CUInt64T(file_dep_counts) + fi_b * 4
|
||||
cnt_ptr_b: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr_b, t.CPtr))
|
||||
if cnt_ptr_b is None:
|
||||
continue
|
||||
cnt_b: int = cnt_ptr_b[0]
|
||||
for di_b in range(cnt_b):
|
||||
dep_slot_b: str = file_deps_buf + fi_b * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + di_b * Phase1.SHA1_LEN
|
||||
if string.strcmp(dep_slot_b, target_sha1_a) == 0:
|
||||
rem_depcnt[i_a] = rem_depcnt[i_a] + 1
|
||||
break
|
||||
# 冒泡降序(被依赖数多者在前)
|
||||
for i_a in range(rem_count):
|
||||
for j_a in range(rem_count - 1):
|
||||
if rem_depcnt[j_a] < rem_depcnt[j_a + 1]:
|
||||
tmp_i: int = rem_idx[j_a]
|
||||
rem_idx[j_a] = rem_idx[j_a + 1]
|
||||
rem_idx[j_a + 1] = tmp_i
|
||||
tmp_d: int = rem_depcnt[j_a]
|
||||
rem_depcnt[j_a] = rem_depcnt[j_a + 1]
|
||||
rem_depcnt[j_a + 1] = tmp_d
|
||||
# 按序输出剩余文件
|
||||
for i_a in range(rem_count):
|
||||
fi_a2: int = rem_idx[i_a]
|
||||
proc_addr8: t.CUInt64T = t.CUInt64T(file_processed) + fi_a2 * 4
|
||||
proc_ptr8: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr8, t.CPtr))
|
||||
if proc_ptr8 is None or proc_ptr8[0] != 0:
|
||||
continue
|
||||
target_sha1_2: str = file_sha1s_buf + fi_a2 * Phase1.SHA1_LEN
|
||||
for ri in range(result.Count):
|
||||
ea_r2: t.CUInt64T = t.CUInt64T(result.Entries) + ri * entry_size
|
||||
ent_r2: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea_r2, t.CPtr))
|
||||
if ent_r2 is not None and ent_r2.Sha1 is not None:
|
||||
if string.strcmp(ent_r2.Sha1, target_sha1_2) == 0:
|
||||
out_idx_addr2: t.CUInt64T = t.CUInt64T(out_order) + out_idx * 4
|
||||
out_int_ptr2: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(out_idx_addr2, t.CPtr))
|
||||
if out_int_ptr2 is not None:
|
||||
out_int_ptr2[0] = ri
|
||||
out_idx += 1
|
||||
break
|
||||
proc_ptr8[0] = 1
|
||||
stdlib.free(rem_idx)
|
||||
stdlib.free(rem_depcnt)
|
||||
|
||||
# 写入输出数量
|
||||
out_count_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(out_count, t.CPtr))
|
||||
if out_count_ptr is not None:
|
||||
out_count_ptr[0] = out_idx
|
||||
|
||||
# 释放扁平数组
|
||||
mb.free(file_sha1s_buf)
|
||||
mb.free(file_deps_buf)
|
||||
mb.free(file_dep_counts)
|
||||
mb.free(file_indegrees)
|
||||
mb.free(file_processed)
|
||||
|
||||
return 0
|
||||
import t, c
|
||||
from stdint import *
|
||||
import string
|
||||
import stdlib
|
||||
import memhub
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import w32.win32file
|
||||
import w32.win32base
|
||||
import ast
|
||||
import llvmlite
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.Gen.Generator as GenGenerator
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.BuildPipeline as BuildPipeline
|
||||
import lib.Projectrans.Config as Config
|
||||
import lib.StubGen.Converter as StubConverter
|
||||
import lib.core.StubMergerBuild as StubMergerBuild
|
||||
import lib.core.StubMergerCollect as StubMergerCollect
|
||||
import lib.core.StubMergerIR as StubMergerIR
|
||||
import lib.core.StubMergerStore as StubMergerStore
|
||||
|
||||
|
||||
import lib.core.Phase1Scan as Phase1Scan
|
||||
import lib.core.Phase1Main as Phase1Main
|
||||
import lib.core.Phase1 as Phase1
|
||||
|
||||
# ============================================================
|
||||
# Phase1Topo - Phase1 拆分(阶段 E):Phase1Topo
|
||||
#
|
||||
# 直接移动模式:函数迁至此模块,原 Phase1.vp 仅保留常量/_mbuddy;
|
||||
# 调用方经本模块前缀访问。全局符号经 Phase1._xxx 跨模块访问。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# _TopoSortFiles - 根据类继承关系对文件进行拓扑排序
|
||||
#
|
||||
# 算法(Kahn):
|
||||
# 1. 从扁平类信息数组构建"文件 SHA1 → 依赖文件 SHA1 集合"映射
|
||||
# 2. 计算每个文件的入度(依赖数量)
|
||||
# 3. 入度为 0 的文件先处理,处理后减少依赖它的文件入度
|
||||
# 4. 重复直到所有文件处理完成
|
||||
#
|
||||
# 注意:依赖方向是"父类所在文件 → 子类所在文件",
|
||||
# 即父类文件必须先处理。Kahn 用 DepCount 作为剩余依赖计数,
|
||||
# 依赖为 0 的先处理,初始化 InDegree = DepCount。
|
||||
#
|
||||
# Args:
|
||||
# mb: 内存池
|
||||
# result: IncludesScanner 扫描结果
|
||||
# reachable_set: 可达 SHA1 集合
|
||||
# reachable_count: 可达 SHA1 数量
|
||||
# use_reachable: 是否使用可达集合过滤
|
||||
# sha1_set: SHA1 集合
|
||||
# set_count: SHA1 集合数量
|
||||
# class_names_buf: 类名扁平数组
|
||||
# parent_names_buf: 父类名扁平数组
|
||||
# def_sha1s_buf: 定义 SHA1 扁平数组
|
||||
# class_count: 类数量
|
||||
# out_order: 输出拓扑顺序的文件索引数组(调用者分配,int 数组)
|
||||
# out_count: 输出文件数量
|
||||
#
|
||||
# Returns:
|
||||
# 0 成功,-1 失败
|
||||
# ============================================================
|
||||
def _TopoSortFiles(mb: memhub.MemBuddy | t.CPtr,
|
||||
result: IncludesScanner.ScanResult | t.CPtr,
|
||||
reachable_set: str, reachable_count: int,
|
||||
use_reachable: int,
|
||||
sha1_set: str, set_count: int,
|
||||
class_names_buf: bytes, parent_names_buf: bytes,
|
||||
def_sha1s_buf: bytes, class_count: int,
|
||||
out_order: t.CPtr, out_count: t.CPtr,
|
||||
temp_dir: str, td_len_ts: t.CSizeT) -> int:
|
||||
"""根据类继承关系对文件进行拓扑排序"""
|
||||
if result is None or out_order is None or out_count is None:
|
||||
return -1
|
||||
|
||||
entry_size: t.CSizeT = IncludesScanner.FileEntry.__sizeof__()
|
||||
|
||||
# 1. 分配扁平数组:文件 SHA1、依赖 SHA1 列表、依赖数量、入度、处理状态
|
||||
# 用扁平数组代替 FileDepEntry 结构体,避免 str 指针字段 NULL 崩溃
|
||||
file_sha1s_buf: bytes = mb.alloc(Phase1.MAX_FILE_DEPS * Phase1.SHA1_LEN)
|
||||
file_deps_buf: bytes = mb.alloc(Phase1.MAX_FILE_DEPS * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN)
|
||||
file_dep_counts: t.CPtr = mb.alloc(Phase1.MAX_FILE_DEPS * 4)
|
||||
file_indegrees: t.CPtr = mb.alloc(Phase1.MAX_FILE_DEPS * 4)
|
||||
file_processed: t.CPtr = mb.alloc(Phase1.MAX_FILE_DEPS * 4)
|
||||
|
||||
if file_sha1s_buf is None or file_deps_buf is None or file_dep_counts is None or file_indegrees is None or file_processed is None:
|
||||
if file_sha1s_buf is not None:
|
||||
mb.free(file_sha1s_buf)
|
||||
if file_deps_buf is not None:
|
||||
mb.free(file_deps_buf)
|
||||
if file_dep_counts is not None:
|
||||
mb.free(file_dep_counts)
|
||||
if file_indegrees is not None:
|
||||
mb.free(file_indegrees)
|
||||
if file_processed is not None:
|
||||
mb.free(file_processed)
|
||||
return -1
|
||||
|
||||
string.memset(file_sha1s_buf, 0, Phase1.MAX_FILE_DEPS * Phase1.SHA1_LEN)
|
||||
string.memset(file_deps_buf, 0, Phase1.MAX_FILE_DEPS * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN)
|
||||
string.memset(file_dep_counts, 0, Phase1.MAX_FILE_DEPS * 4)
|
||||
string.memset(file_indegrees, 0, Phase1.MAX_FILE_DEPS * 4)
|
||||
string.memset(file_processed, 0, Phase1.MAX_FILE_DEPS * 4)
|
||||
|
||||
file_count: int = 0
|
||||
# sha1→file_index 映射(简单线性查找,文件数不多)
|
||||
for i in range(result.Count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size
|
||||
entry: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
if entry is None or entry.Sha1 is None:
|
||||
continue
|
||||
|
||||
sha1_e: str = entry.Sha1
|
||||
in_set: int = 0
|
||||
if use_reachable != 0:
|
||||
in_set = StubMergerCollect._is_in_sha1_set(sha1_e, reachable_set, reachable_count)
|
||||
else:
|
||||
in_set = StubMergerCollect._is_in_sha1_set(sha1_e, sha1_set, set_count)
|
||||
if in_set == 0:
|
||||
continue
|
||||
|
||||
if file_count >= Phase1.MAX_FILE_DEPS:
|
||||
break
|
||||
|
||||
# 初始化扁平数组:文件 SHA1(偏移 = file_count * Phase1.SHA1_LEN)
|
||||
# DepCount/InDegree/Processed 已由 memset 清零
|
||||
sha1_dst: str = file_sha1s_buf + file_count * Phase1.SHA1_LEN
|
||||
string.strcpy(sha1_dst, sha1_e)
|
||||
|
||||
file_count += 1
|
||||
|
||||
# 2. 构建依赖边:对每个类,找到父类定义所在文件,建立 子文件→父文件 依赖
|
||||
for ci in range(class_count):
|
||||
# 读取父类名(偏移 = ci * Phase1.CLASS_NAME_LEN)
|
||||
parent_ptr: str = parent_names_buf + ci * Phase1.CLASS_NAME_LEN
|
||||
if parent_ptr[0] == '\0':
|
||||
continue
|
||||
|
||||
# 读取子类定义 SHA1(偏移 = ci * Phase1.SHA1_LEN)
|
||||
child_def_sha1: str = def_sha1s_buf + ci * Phase1.SHA1_LEN
|
||||
|
||||
# 查找父类定义所在文件的 SHA1
|
||||
parent_sha1: str = Phase1Scan._FindClassDefSha1(class_names_buf, def_sha1s_buf, class_count, parent_ptr)
|
||||
if parent_sha1 is None:
|
||||
continue # 父类不在 includes 中(如 Object、CEnum 等标记基类)
|
||||
|
||||
# 父类文件 SHA1 不能等于子类文件 SHA1(同文件内继承不需要依赖)
|
||||
if string.strcmp(parent_sha1, child_def_sha1) == 0:
|
||||
continue
|
||||
|
||||
# 找到子类文件对应的索引,添加父文件 SHA1 到依赖列表
|
||||
for fi in range(file_count):
|
||||
fsha1: str = file_sha1s_buf + fi * Phase1.SHA1_LEN
|
||||
if string.strcmp(fsha1, child_def_sha1) != 0:
|
||||
continue
|
||||
|
||||
# 读取当前依赖数量
|
||||
cnt_addr: t.CUInt64T = t.CUInt64T(file_dep_counts) + fi * 4
|
||||
cnt_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr, t.CPtr))
|
||||
if cnt_ptr is None:
|
||||
break
|
||||
cur_cnt: int = cnt_ptr[0]
|
||||
|
||||
# 检查依赖是否已添加(去重)
|
||||
already: int = 0
|
||||
for di in range(cur_cnt):
|
||||
dep_slot: str = file_deps_buf + fi * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + di * Phase1.SHA1_LEN
|
||||
if string.strcmp(dep_slot, parent_sha1) == 0:
|
||||
already = 1
|
||||
break
|
||||
if already != 0:
|
||||
break
|
||||
|
||||
if cur_cnt < Phase1.MAX_DEP_EDGES:
|
||||
dep_dst: str = file_deps_buf + fi * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + cur_cnt * Phase1.SHA1_LEN
|
||||
string.strcpy(dep_dst, parent_sha1)
|
||||
cnt_ptr[0] = cur_cnt + 1
|
||||
break
|
||||
|
||||
# 2.5 补充 import 依赖边:被 import 的模块先完整翻译。
|
||||
#
|
||||
# 仅按类继承建边不够:跨模块全局变量 stub(lexer.vp from-import
|
||||
# tokens.vp 的 _op_head)、跨模块 vtable TypeStr(astaux 继承 base 的
|
||||
# AST)、泛型模板(base.vp 用 list[...])都要求依赖模块先翻译,而它们
|
||||
# 之间可能无类继承关系。deps(_includes_deps_*)由 Phase 1a-pre 填充
|
||||
# (含容器按需注入的 _list/_dict)。
|
||||
#
|
||||
# 用 _BuildIncludesSha1Map 复制局部 sha1→模块名 数组(与
|
||||
# _BuildReachableSha1Set 的 BFS 一致),避免直接使用全局 store 返回值
|
||||
# 跨函数传参(bytes|t.CPtr 联合转 str 参数)的地址异常。
|
||||
sha1_arr_ts: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 17)
|
||||
mod_arr_ts: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 64)
|
||||
map_count_ts: int = 0
|
||||
if sha1_arr_ts is not None and mod_arr_ts is not None:
|
||||
map_count_ts = StubMergerIR._BuildIncludesSha1Map(
|
||||
temp_dir, td_len_ts, sha1_arr_ts, mod_arr_ts)
|
||||
for fi_imp in range(file_count):
|
||||
if map_count_ts <= 0:
|
||||
break
|
||||
fsha1_imp: str = file_sha1s_buf + fi_imp * Phase1.SHA1_LEN
|
||||
deps_imp: str = StubMergerStore.LookupIncludesDeps(fsha1_imp)
|
||||
if deps_imp is None:
|
||||
continue
|
||||
dl_imp: t.CSizeT = string.strlen(deps_imp)
|
||||
dpos_imp: t.CSizeT = 0
|
||||
while dpos_imp < dl_imp:
|
||||
dstart_imp: t.CSizeT = dpos_imp
|
||||
while dpos_imp < dl_imp and deps_imp[dpos_imp] != ' ':
|
||||
dpos_imp += 1
|
||||
dlen_imp: t.CSizeT = dpos_imp - dstart_imp
|
||||
if dpos_imp < dl_imp:
|
||||
dpos_imp += 1
|
||||
if dlen_imp == 0:
|
||||
continue
|
||||
dname_imp: bytes = stdlib.malloc(dlen_imp + 1)
|
||||
if dname_imp is None:
|
||||
continue
|
||||
string.strncpy(dname_imp, deps_imp + dstart_imp, dlen_imp)
|
||||
dname_imp[dlen_imp] = '\0'
|
||||
dsha1_imp: str = StubMergerIR._FindSha1ByModName(
|
||||
sha1_arr_ts, mod_arr_ts, map_count_ts, dname_imp)
|
||||
stdlib.free(dname_imp)
|
||||
if dsha1_imp is None:
|
||||
continue
|
||||
# 找依赖文件在列表中的索引(跳过自身)
|
||||
for fj_imp in range(file_count):
|
||||
if string.strcmp(file_sha1s_buf + fj_imp * Phase1.SHA1_LEN, dsha1_imp) != 0:
|
||||
continue
|
||||
if fj_imp == fi_imp:
|
||||
break
|
||||
# 去重 + 加边:fi_imp 依赖 fj_imp(InDegree[fi_imp]++)
|
||||
cnt_addr_imp: t.CUInt64T = t.CUInt64T(file_dep_counts) + fi_imp * 4
|
||||
cnt_ptr_imp: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr_imp, t.CPtr))
|
||||
if cnt_ptr_imp is None:
|
||||
break
|
||||
cur_cnt_imp: int = cnt_ptr_imp[0]
|
||||
already_imp: int = 0
|
||||
for di_imp in range(cur_cnt_imp):
|
||||
dep_slot_imp: str = file_deps_buf + fi_imp * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + di_imp * Phase1.SHA1_LEN
|
||||
if string.strcmp(dep_slot_imp, dsha1_imp) == 0:
|
||||
already_imp = 1
|
||||
break
|
||||
if already_imp == 0 and cur_cnt_imp < Phase1.MAX_DEP_EDGES:
|
||||
dep_dst_imp: str = file_deps_buf + fi_imp * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + cur_cnt_imp * Phase1.SHA1_LEN
|
||||
string.strcpy(dep_dst_imp, dsha1_imp)
|
||||
cnt_ptr_imp[0] = cur_cnt_imp + 1
|
||||
break
|
||||
|
||||
# 释放 import 边用的局部映射数组
|
||||
if sha1_arr_ts is not None:
|
||||
stdlib.free(sha1_arr_ts)
|
||||
if mod_arr_ts is not None:
|
||||
stdlib.free(mod_arr_ts)
|
||||
|
||||
# 3. Kahn 算法:InDegree = DepCount(依赖多少个父文件)
|
||||
# 依赖为 0 的先处理,处理后减少依赖它的文件入度
|
||||
for fi in range(file_count):
|
||||
cnt_addr3: t.CUInt64T = t.CUInt64T(file_dep_counts) + fi * 4
|
||||
cnt_ptr3: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr3, t.CPtr))
|
||||
ind_addr3: t.CUInt64T = t.CUInt64T(file_indegrees) + fi * 4
|
||||
ind_ptr3: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(ind_addr3, t.CPtr))
|
||||
if cnt_ptr3 is not None and ind_ptr3 is not None:
|
||||
ind_ptr3[0] = cnt_ptr3[0]
|
||||
|
||||
# 4. 拓扑排序输出
|
||||
out_idx: int = 0
|
||||
changed: int = 1
|
||||
while changed != 0:
|
||||
changed = 0
|
||||
for fi in range(file_count):
|
||||
# 检查处理状态
|
||||
proc_addr4: t.CUInt64T = t.CUInt64T(file_processed) + fi * 4
|
||||
proc_ptr4: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr4, t.CPtr))
|
||||
if proc_ptr4 is None or proc_ptr4[0] != 0:
|
||||
continue
|
||||
# 检查入度
|
||||
ind_addr4: t.CUInt64T = t.CUInt64T(file_indegrees) + fi * 4
|
||||
ind_ptr4: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(ind_addr4, t.CPtr))
|
||||
if ind_ptr4 is None or ind_ptr4[0] > 0:
|
||||
continue
|
||||
|
||||
# 入度为 0,可以处理
|
||||
# 找到对应的 result.Entries 索引
|
||||
target_sha1: str = file_sha1s_buf + fi * Phase1.SHA1_LEN
|
||||
for ri in range(result.Count):
|
||||
ea_r: t.CUInt64T = t.CUInt64T(result.Entries) + ri * entry_size
|
||||
ent_r: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea_r, t.CPtr))
|
||||
if ent_r is not None and ent_r.Sha1 is not None:
|
||||
if string.strcmp(ent_r.Sha1, target_sha1) == 0:
|
||||
# 写入输出索引数组
|
||||
out_idx_addr: t.CUInt64T = t.CUInt64T(out_order) + out_idx * 4
|
||||
out_int_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(out_idx_addr, t.CPtr))
|
||||
if out_int_ptr is not None:
|
||||
out_int_ptr[0] = ri
|
||||
out_idx += 1
|
||||
break
|
||||
|
||||
# 标记已处理
|
||||
proc_ptr4[0] = 1
|
||||
changed = 1
|
||||
|
||||
# 减少依赖该文件的其他文件的入度
|
||||
for fj in range(file_count):
|
||||
proc_addr5: t.CUInt64T = t.CUInt64T(file_processed) + fj * 4
|
||||
proc_ptr5: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr5, t.CPtr))
|
||||
if proc_ptr5 is None or proc_ptr5[0] != 0:
|
||||
continue
|
||||
# 读取 fj 的依赖数量
|
||||
cnt_addr5: t.CUInt64T = t.CUInt64T(file_dep_counts) + fj * 4
|
||||
cnt_ptr5: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr5, t.CPtr))
|
||||
if cnt_ptr5 is None:
|
||||
continue
|
||||
fj_dep_cnt: int = cnt_ptr5[0]
|
||||
for di in range(fj_dep_cnt):
|
||||
dep_slot5: str = file_deps_buf + fj * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + di * Phase1.SHA1_LEN
|
||||
if string.strcmp(dep_slot5, target_sha1) == 0:
|
||||
ind_addr5: t.CUInt64T = t.CUInt64T(file_indegrees) + fj * 4
|
||||
ind_ptr5: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(ind_addr5, t.CPtr))
|
||||
if ind_ptr5 is not None:
|
||||
ind_ptr5[0] = ind_ptr5[0] - 1
|
||||
break
|
||||
|
||||
# 处理循环依赖:环内优先输出"被依赖者"(被其余剩余文件依赖数量多者先)。
|
||||
#
|
||||
# 背景:容器按需注入(string 用 list 泛型 → 依赖 _list)与真实 import
|
||||
# (_list import string)形成伪环,Kahn 无法完全归零。若按扫描顺序追加,
|
||||
# 依赖者(astaux)会先于被依赖者(base)翻译 → 跨模块 vtable TypeStr
|
||||
# 未注册 → 误杀。被依赖者先翻译,其 stub/TypeStr/模板先就绪,依赖者
|
||||
# 翻译时可引用(函数/全局声明由 1a-pre 的 vpi 兜底)。
|
||||
if out_idx < file_count:
|
||||
rem_idx: t.CPtr = stdlib.malloc(4 * file_count)
|
||||
rem_depcnt: t.CPtr = stdlib.malloc(4 * file_count)
|
||||
rem_count: int = 0
|
||||
if rem_idx is not None and rem_depcnt is not None:
|
||||
for fi in range(file_count):
|
||||
proc_addr7: t.CUInt64T = t.CUInt64T(file_processed) + fi * 4
|
||||
proc_ptr7: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr7, t.CPtr))
|
||||
if proc_ptr7 is not None and proc_ptr7[0] == 0:
|
||||
rem_idx[rem_count] = fi
|
||||
rem_depcnt[rem_count] = 0
|
||||
rem_count += 1
|
||||
# 计算每个剩余文件的被依赖数(被其余剩余文件依赖)
|
||||
for i_a in range(rem_count):
|
||||
fi_a: int = rem_idx[i_a]
|
||||
target_sha1_a: str = file_sha1s_buf + fi_a * Phase1.SHA1_LEN
|
||||
for i_b in range(rem_count):
|
||||
fi_b: int = rem_idx[i_b]
|
||||
if fi_b == fi_a:
|
||||
continue
|
||||
cnt_addr_b: t.CUInt64T = t.CUInt64T(file_dep_counts) + fi_b * 4
|
||||
cnt_ptr_b: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr_b, t.CPtr))
|
||||
if cnt_ptr_b is None:
|
||||
continue
|
||||
cnt_b: int = cnt_ptr_b[0]
|
||||
for di_b in range(cnt_b):
|
||||
dep_slot_b: str = file_deps_buf + fi_b * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + di_b * Phase1.SHA1_LEN
|
||||
if string.strcmp(dep_slot_b, target_sha1_a) == 0:
|
||||
rem_depcnt[i_a] = rem_depcnt[i_a] + 1
|
||||
break
|
||||
# 冒泡降序(被依赖数多者在前)
|
||||
for i_a in range(rem_count):
|
||||
for j_a in range(rem_count - 1):
|
||||
if rem_depcnt[j_a] < rem_depcnt[j_a + 1]:
|
||||
tmp_i: int = rem_idx[j_a]
|
||||
rem_idx[j_a] = rem_idx[j_a + 1]
|
||||
rem_idx[j_a + 1] = tmp_i
|
||||
tmp_d: int = rem_depcnt[j_a]
|
||||
rem_depcnt[j_a] = rem_depcnt[j_a + 1]
|
||||
rem_depcnt[j_a + 1] = tmp_d
|
||||
# 按序输出剩余文件
|
||||
for i_a in range(rem_count):
|
||||
fi_a2: int = rem_idx[i_a]
|
||||
proc_addr8: t.CUInt64T = t.CUInt64T(file_processed) + fi_a2 * 4
|
||||
proc_ptr8: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr8, t.CPtr))
|
||||
if proc_ptr8 is None or proc_ptr8[0] != 0:
|
||||
continue
|
||||
target_sha1_2: str = file_sha1s_buf + fi_a2 * Phase1.SHA1_LEN
|
||||
for ri in range(result.Count):
|
||||
ea_r2: t.CUInt64T = t.CUInt64T(result.Entries) + ri * entry_size
|
||||
ent_r2: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea_r2, t.CPtr))
|
||||
if ent_r2 is not None and ent_r2.Sha1 is not None:
|
||||
if string.strcmp(ent_r2.Sha1, target_sha1_2) == 0:
|
||||
out_idx_addr2: t.CUInt64T = t.CUInt64T(out_order) + out_idx * 4
|
||||
out_int_ptr2: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(out_idx_addr2, t.CPtr))
|
||||
if out_int_ptr2 is not None:
|
||||
out_int_ptr2[0] = ri
|
||||
out_idx += 1
|
||||
break
|
||||
proc_ptr8[0] = 1
|
||||
stdlib.free(rem_idx)
|
||||
stdlib.free(rem_depcnt)
|
||||
|
||||
# 写入输出数量
|
||||
out_count_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(out_count, t.CPtr))
|
||||
if out_count_ptr is not None:
|
||||
out_count_ptr[0] = out_idx
|
||||
|
||||
# 释放扁平数组
|
||||
mb.free(file_sha1s_buf)
|
||||
mb.free(file_deps_buf)
|
||||
mb.free(file_dep_counts)
|
||||
mb.free(file_indegrees)
|
||||
mb.free(file_processed)
|
||||
|
||||
return 0
|
||||
+1285
-1289
File diff suppressed because it is too large.
Load diff
+78
-80
@@ -1,80 +1,78 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import llvmlite
|
||||
import w32.win32file as win32file
|
||||
import w32.win32base as win32base
|
||||
import w32.fileio as fileio
|
||||
import viperlib
|
||||
import sys
|
||||
import ast
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import lib.core.BuildPipeline as BuildPipeline
|
||||
import lib.StubGen.VpiReader as VpiReader
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import lib.Projectrans.Config as Config
|
||||
|
||||
|
||||
# ============================================================
|
||||
# StubMerger - stub 声明合并模块
|
||||
#
|
||||
# 从 temp 目录加载所有 .stub.ll 文件,将声明内容合并到主 IR。
|
||||
# 这是 Phase2 的核心功能:翻译主文件时,将所有依赖的 stub
|
||||
# 声明合并到主 IR 前面,使链接器能解析跨模块符号引用。
|
||||
#
|
||||
# 合并策略:
|
||||
# 1. 扫描 temp 目录,收集所有 {sha1}.stub.ll 文件
|
||||
# 2. 读取每个 stub 文件内容
|
||||
# 3. 过滤去重(避免重复声明)
|
||||
# 4. 将声明插入到主 IR 的 target triple 之后
|
||||
# ============================================================
|
||||
|
||||
# 全局 mbuddy 指针
|
||||
_mbuddy: memhub.MemBuddy | t.CPtr
|
||||
|
||||
# 最大 includes SHA1 数(用于过滤)
|
||||
MAX_INCLUDES_SHA1: t.CDefine = 1024
|
||||
# stub 读取缓冲区大小
|
||||
STUB_READ_BUF_SIZE: t.CDefine = 1048576
|
||||
# 最大 includes 条目数
|
||||
MAX_INCLUDES: t.CDefine = 1024
|
||||
# 可达性分析 worklist/processed 缓冲区大小(8192 不够:递归扫描 source_dir
|
||||
# 后 worklist 含全部 App 文件 imports 的拼接 + BFS 依赖展开,追加82 溢出)
|
||||
REACH_WORKLIST_BUF: t.CDefine = 65536
|
||||
|
||||
# 全局 SHA1 映射存储器(内存中,不依赖 _sha1_map.txt 文件)
|
||||
# Phase1 扫描完成后填充,供所有函数使用
|
||||
_sha1_store_arr: bytes # SHA1 数组(每个 17 字节,MAX_INCLUDES 个)
|
||||
_sha1_store_mod: bytes # 模块名数组(每个 64 字节,MAX_INCLUDES 个)
|
||||
_sha1_store_rel: bytes # 相对路径数组(每个 256 字节,MAX_INCLUDES 个)
|
||||
_sha1_store_incdir: bytes # 所属 includes 根目录数组(每个 512 字节,MAX_INCLUDES 个,多 includes 支持)
|
||||
_sha1_store_count: int # 条目数
|
||||
|
||||
# includes 依赖内存存储(不依赖 deps.txt 过程文件)
|
||||
# Phase B+ 前用 declare_only 翻译所有 includes 文件,提取 _imported_modules 存入此处
|
||||
# _BuildReachableSha1Set 从此处读取依赖,不读 deps.txt
|
||||
_includes_deps_sha1: bytes # SHA1 数组(每个 17 字节,MAX_INCLUDES 个)
|
||||
_includes_deps_str: bytes # 依赖字符串数组(每个 512 字节,MAX_INCLUDES 个)
|
||||
_includes_deps_count: int # 条目数
|
||||
|
||||
# BuildCombinedIR 全目录扫描缓存:Phase B 对每个源文件调用一次 BuildCombinedIR,
|
||||
# 每次 _collect_stub_sha1s 递归扫描 temp_dir 全部切片子目录(O(N×S) 目录枚举,
|
||||
# 90 文件 × 全目录是 Phase B 慢的根因之一)。按 temp_dir 缓存扫描结果,
|
||||
# 首次扫描后复用,temp_dir 变化时自动重建。
|
||||
_stub_scan_cache_dir: str # 缓存对应的 temp_dir(None=未初始化)
|
||||
_stub_scan_cache_arr: str # 扫描结果数组(每 17 字节一个 SHA1,MAX_INCLUDES_SHA1 个)
|
||||
_stub_scan_cache_count: int # 收集数量
|
||||
|
||||
# 单条依赖字符串最大长度
|
||||
MAX_DEPS_STR_LEN: t.CDefine = 512
|
||||
|
||||
# rel_path 最大长度
|
||||
MAX_REL_PATH_LEN: t.CDefine = 256
|
||||
# includes 根目录最大长度(绝对路径,多 includes 支持)
|
||||
MAX_INC_DIR_LEN: t.CDefine = 512
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import llvmlite
|
||||
import w32.win32file as win32file
|
||||
import w32.win32base as win32base
|
||||
import w32.fileio as fileio
|
||||
import viperlib
|
||||
import sys
|
||||
import ast
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import lib.core.BuildPipeline as BuildPipeline
|
||||
import lib.StubGen.VpiReader as VpiReader
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import lib.Projectrans.Config as Config
|
||||
|
||||
|
||||
# ============================================================
|
||||
# StubMerger - stub 声明合并模块
|
||||
#
|
||||
# 从 temp 目录加载所有 .stub.ll 文件,将声明内容合并到主 IR。
|
||||
# 这是 Phase2 的核心功能:翻译主文件时,将所有依赖的 stub
|
||||
# 声明合并到主 IR 前面,使链接器能解析跨模块符号引用。
|
||||
#
|
||||
# 合并策略:
|
||||
# 1. 扫描 temp 目录,收集所有 {sha1}.stub.ll 文件
|
||||
# 2. 读取每个 stub 文件内容
|
||||
# 3. 过滤去重(避免重复声明)
|
||||
# 4. 将声明插入到主 IR 的 target triple 之后
|
||||
# ============================================================
|
||||
|
||||
# 全局 mbuddy 指针
|
||||
_mbuddy: memhub.MemBuddy | t.CPtr
|
||||
|
||||
# 最大 includes SHA1 数(用于过滤)
|
||||
MAX_INCLUDES_SHA1: t.CDefine = 1024
|
||||
# stub 读取缓冲区大小
|
||||
STUB_READ_BUF_SIZE: t.CDefine = 1048576
|
||||
# 最大 includes 条目数
|
||||
MAX_INCLUDES: t.CDefine = 1024
|
||||
# 可达性分析 worklist/processed 缓冲区大小(8192 不够:递归扫描 source_dir
|
||||
# 后 worklist 含全部 App 文件 imports 的拼接 + BFS 依赖展开,追加82 溢出)
|
||||
REACH_WORKLIST_BUF: t.CDefine = 65536
|
||||
|
||||
# 全局 SHA1 映射存储器(内存中,不依赖 _sha1_map.txt 文件)
|
||||
# Phase1 扫描完成后填充,供所有函数使用
|
||||
_sha1_store_arr: bytes # SHA1 数组(每个 17 字节,MAX_INCLUDES 个)
|
||||
_sha1_store_mod: bytes # 模块名数组(每个 64 字节,MAX_INCLUDES 个)
|
||||
_sha1_store_rel: bytes # 相对路径数组(每个 256 字节,MAX_INCLUDES 个)
|
||||
_sha1_store_incdir: bytes # 所属 includes 根目录数组(每个 512 字节,MAX_INCLUDES 个,多 includes 支持)
|
||||
_sha1_store_count: int # 条目数
|
||||
|
||||
# includes 依赖内存存储(不依赖 deps.txt 过程文件)
|
||||
# Phase B+ 前用 declare_only 翻译所有 includes 文件,提取 _imported_modules 存入此处
|
||||
# _BuildReachableSha1Set 从此处读取依赖,不读 deps.txt
|
||||
_includes_deps_sha1: bytes # SHA1 数组(每个 17 字节,MAX_INCLUDES 个)
|
||||
_includes_deps_str: bytes # 依赖字符串数组(每个 512 字节,MAX_INCLUDES 个)
|
||||
_includes_deps_count: int # 条目数
|
||||
|
||||
# BuildCombinedIR 全目录扫描缓存:Phase B 对每个源文件调用一次 BuildCombinedIR,
|
||||
# 每次 _collect_stub_sha1s 递归扫描 temp_dir 全部切片子目录(O(N×S) 目录枚举,
|
||||
# 90 文件 × 全目录是 Phase B 慢的根因之一)。按 temp_dir 缓存扫描结果,
|
||||
# 首次扫描后复用,temp_dir 变化时自动重建。
|
||||
_stub_scan_cache_dir: str # 缓存对应的 temp_dir(None=未初始化)
|
||||
_stub_scan_cache_arr: str # 扫描结果数组(每 17 字节一个 SHA1,MAX_INCLUDES_SHA1 个)
|
||||
_stub_scan_cache_count: int # 收集数量
|
||||
|
||||
# 单条依赖字符串最大长度
|
||||
MAX_DEPS_STR_LEN: t.CDefine = 512
|
||||
|
||||
# rel_path 最大长度
|
||||
MAX_REL_PATH_LEN: t.CDefine = 256
|
||||
# includes 根目录最大长度(绝对路径,多 includes 支持)
|
||||
MAX_INC_DIR_LEN: t.CDefine = 512
|
||||
+1229
-1230
File diff suppressed because it is too large.
Load diff
+284
-286
@@ -1,286 +1,284 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import llvmlite
|
||||
import w32.win32file as win32file
|
||||
import w32.win32base as win32base
|
||||
import w32.fileio as fileio
|
||||
import viperlib
|
||||
import sys
|
||||
import ast
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import lib.core.BuildPipeline as BuildPipeline
|
||||
import lib.StubGen.VpiReader as VpiReader
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import lib.Projectrans.Config as Config
|
||||
|
||||
|
||||
import lib.core.StubMergerStore as StubMergerStore
|
||||
import lib.core.StubMergerTopo as StubMergerTopo
|
||||
import lib.core.StubMergerIR as StubMergerIR
|
||||
import lib.core.StubMergerBuild as StubMergerBuild
|
||||
import lib.core.StubMerger as StubMerger
|
||||
|
||||
# ============================================================
|
||||
# StubMergerCollect - StubMerger 拆分(阶段 E):StubMergerCollect
|
||||
#
|
||||
# 直接移动模式:函数实现迁至此模块,原 StubMerger.vp 仅保留
|
||||
# 常量/全局变量;调用方经本模块前缀访问。全局变量跨模块经
|
||||
# StubMerger._xxx 访问(main.vp 先例)。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# _sliced_path - 构建切片路径(stdlib.malloc 分配,调用者负责 free)
|
||||
#
|
||||
# 根据 Config.Sha1SliceLevel 将文件分散到 SHA1 前缀子目录:
|
||||
# level=0 → {temp_dir}/{sha1}.{ext}
|
||||
# level=1 → {temp_dir}/b7/{sha1}.{ext}
|
||||
# level=2 → {temp_dir}/b7/90/{sha1}.{ext}
|
||||
#
|
||||
# 自动调用 BuildPipeline.ensure_dir 创建子目录(level>0 时)。
|
||||
#
|
||||
# Args:
|
||||
# temp_dir: 基础目录
|
||||
# td_len: temp_dir 长度(避免重复 strlen)
|
||||
# sha1: SHA1 字符串
|
||||
# ext: 文件扩展名(如 "stub.ll")
|
||||
#
|
||||
# Returns:
|
||||
# 完整路径(stdlib.malloc 分配,需 stdlib.free),None 失败
|
||||
# ============================================================
|
||||
def _sliced_path(temp_dir: str, td_len: t.CSizeT, sha1: str, ext: str) -> str:
|
||||
"""构建切片路径(stdlib.malloc 分配,调用者负责 free)
|
||||
|
||||
level>0 时自动调用 ensure_dir 创建子目录。
|
||||
"""
|
||||
if temp_dir is None or sha1 is None or ext is None:
|
||||
return None
|
||||
sha1_len: t.CSizeT = string.strlen(sha1)
|
||||
ext_len: t.CSizeT = string.strlen(ext)
|
||||
|
||||
# 子目录前缀:复用 Config.slice_subdir(SHA1 切片唯一权威实现,mbuddy 分配无需 free)
|
||||
subdir_buf: str = Config.slice_subdir(sha1, Config.Sha1SliceLevel)
|
||||
sub_len: t.CSizeT = 0
|
||||
if subdir_buf is not None:
|
||||
sub_len = string.strlen(subdir_buf)
|
||||
|
||||
# 确保子目录存在: {temp_dir}/{subdir}
|
||||
# 不创建目录会导致 fileio.File(MODE.W) 静默失败(file.closed==True),
|
||||
# 进而 BuildCombinedIR 读不到文件返回 0("BuildCombinedIR 失败")。
|
||||
dir_path_len: t.CSizeT = td_len + sub_len + 2
|
||||
dir_path: bytes = stdlib.malloc(dir_path_len)
|
||||
if dir_path is not None:
|
||||
viperlib.snprintf(dir_path, dir_path_len, "%s/%s", temp_dir, subdir_buf)
|
||||
BuildPipeline.ensure_dir(dir_path)
|
||||
stdlib.free(dir_path)
|
||||
|
||||
# 构建完整路径
|
||||
path: str = None
|
||||
path_len: t.CSizeT = 0
|
||||
if sub_len > 0:
|
||||
path_len = td_len + sub_len + sha1_len + ext_len + 4
|
||||
path = stdlib.malloc(path_len)
|
||||
if path is not None:
|
||||
viperlib.snprintf(path, path_len, "%s/%s/%s.%s", temp_dir, subdir_buf, sha1, ext)
|
||||
else:
|
||||
path_len = td_len + sha1_len + ext_len + 3
|
||||
path = stdlib.malloc(path_len)
|
||||
if path is not None:
|
||||
viperlib.snprintf(path, path_len, "%s/%s.%s", temp_dir, sha1, ext)
|
||||
|
||||
return path
|
||||
# ============================================================
|
||||
# _collect_stub_sha1s - 递归扫描子目录,收集 .stub.ll 文件的 SHA1
|
||||
#
|
||||
# 根据 level 递归扫描子目录:
|
||||
# level=0 → 扫描 {base_dir}/*.stub.ll,从文件名提取 SHA1
|
||||
# level>0 → 扫描 {base_dir}/* 的子目录,对每个子目录递归调用
|
||||
#
|
||||
# Args:
|
||||
# base_dir: 当前扫描目录
|
||||
# bd_len: base_dir 长度
|
||||
# level: 剩余递归层数
|
||||
# out_arr: 输出数组(每个 SHA1 17 字节 = 16字符 + null)
|
||||
# out_count: 当前已收集数量
|
||||
# max_count: 最大数量
|
||||
#
|
||||
# Returns:
|
||||
# 收集后的总数量
|
||||
# ============================================================
|
||||
def _collect_stub_sha1s(base_dir: str, bd_len: t.CSizeT, level: int,
|
||||
out_arr: str, out_count: int, max_count: int) -> int:
|
||||
"""递归扫描子目录,收集 .stub.ll 文件的 SHA1"""
|
||||
if base_dir is None or out_arr is None:
|
||||
return out_count
|
||||
if out_count >= max_count:
|
||||
return out_count
|
||||
|
||||
find_data: win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(win32file.WIN32_FIND_DATAA.__sizeof__())
|
||||
if find_data is None:
|
||||
return out_count
|
||||
string.memset(find_data, 0, win32file.WIN32_FIND_DATAA.__sizeof__())
|
||||
|
||||
if level <= 0:
|
||||
# 扫描 {base_dir}/*.stub.ll
|
||||
pattern: bytes = stdlib.malloc(bd_len + 16)
|
||||
if pattern is None:
|
||||
stdlib.free(find_data)
|
||||
return out_count
|
||||
viperlib.snprintf(pattern, bd_len + 16, "%s/*.stub.ll", base_dir)
|
||||
handle: win32base.HANDLE = win32file.FindFirstFileA(pattern, find_data)
|
||||
stdlib.free(pattern)
|
||||
if handle != win32base.INVALID_HANDLE_VALUE:
|
||||
while 1:
|
||||
if out_count >= max_count:
|
||||
break
|
||||
fname: str = find_data.cFileName
|
||||
if fname is not None:
|
||||
if fname[0] != '\0':
|
||||
# 从文件名提取 SHA1(前 16 字符)
|
||||
string.strncpy(out_arr + out_count * 17, fname, 16)
|
||||
out_arr[out_count * 17 + 16] = '\0'
|
||||
out_count += 1
|
||||
if win32file.FindNextFileA(handle, find_data) == 0:
|
||||
break
|
||||
win32file.FindClose(handle)
|
||||
else:
|
||||
# 扫描 {base_dir}/* 的子目录
|
||||
pattern = stdlib.malloc(bd_len + 4)
|
||||
if pattern is None:
|
||||
stdlib.free(find_data)
|
||||
return out_count
|
||||
viperlib.snprintf(pattern, bd_len + 4, "%s/*", base_dir)
|
||||
handle = win32file.FindFirstFileA(pattern, find_data)
|
||||
stdlib.free(pattern)
|
||||
if handle != win32base.INVALID_HANDLE_VALUE:
|
||||
while 1:
|
||||
# 检查是否是目录(FILE_ATTRIBUTE_DIRECTORY = 0x10 = 16)
|
||||
attrs: t.CUInt32T = find_data.dwFileAttributes
|
||||
if(attrs & 16) != 0:
|
||||
fname = find_data.cFileName
|
||||
if fname is not None:
|
||||
# 跳过 "." 和 ".."
|
||||
is_dot: int = 0
|
||||
if fname[0] == '.':
|
||||
if fname[1] == '\0':
|
||||
is_dot = 1
|
||||
elif fname[1] == '.' and fname[2] == '\0':
|
||||
is_dot = 1
|
||||
if is_dot == 0:
|
||||
# 构建子目录路径并递归扫描
|
||||
sub_dir: str = Utils.JoinPath(base_dir, fname)
|
||||
if sub_dir is not None:
|
||||
sub_dir_len: t.CSizeT = string.strlen(sub_dir)
|
||||
out_count = _collect_stub_sha1s(sub_dir, sub_dir_len, level - 1, out_arr, out_count, max_count)
|
||||
stdlib.free(sub_dir)
|
||||
if win32file.FindNextFileA(handle, find_data) == 0:
|
||||
break
|
||||
win32file.FindClose(handle)
|
||||
|
||||
stdlib.free(find_data)
|
||||
return out_count
|
||||
# ============================================================
|
||||
# _load_includes_sha1_set - 从全局内存存储器收集 includes 的 SHA1
|
||||
#
|
||||
# 数据来源是 PopulateSha1MapStore 填充的全局存储器(不读取 _sha1_map.txt)。
|
||||
# 用于过滤 stub 文件,避免加载 TransPyV 自身源文件(lib/*)的 stub 导致链接失败。
|
||||
# ============================================================
|
||||
def _load_includes_sha1_set(pool: memhub.MemBuddy | t.CPtr,
|
||||
temp_dir: str,
|
||||
sha1_set: str) -> int:
|
||||
"""从全局内存存储器将 includes 的 SHA1 写入 sha1_set
|
||||
|
||||
pool/temp_dir 参数保留以兼容现有调用者,但不再使用。
|
||||
数据来源是 PopulateSha1MapStore 填充的全局存储器。
|
||||
sha1_set 大小为 MAX_INCLUDES_SHA1 * 17(每个 SHA1 16字符+null)
|
||||
返回找到的 includes SHA1 数量,-1 表示错误"""
|
||||
if sha1_set is None:
|
||||
return -1
|
||||
if StubMerger._sha1_store_arr is None:
|
||||
return -1
|
||||
count: int = 0
|
||||
for i in range(StubMerger._sha1_store_count):
|
||||
if count >= MAX_INCLUDES_SHA1:
|
||||
break
|
||||
idx: t.CSizeT = t.CSizeT(i) * 17
|
||||
string.strcpy(sha1_set + t.CSizeT(count) * 17, StubMerger._sha1_store_arr + idx)
|
||||
count += 1
|
||||
return count
|
||||
# ============================================================
|
||||
# _is_in_sha1_set - 检查 SHA1 是否在集合中
|
||||
# ============================================================
|
||||
def _is_in_sha1_set(sha1: str, sha1_set: str, set_count: int) -> int:
|
||||
"""检查 sha1 是否在集合中"""
|
||||
if sha1 is None or sha1_set is None:
|
||||
return 0
|
||||
for i in range(set_count):
|
||||
if string.strcmp(sha1_set + i * 17, sha1) == 0:
|
||||
return 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# WriteIncludesSha1Map - 将 includes 扫描结果写入 _sha1_map.txt(人类可读输出)
|
||||
#
|
||||
# _sha1_map.txt 仅作为人类可读的调试输出,程序内部不读取此文件。
|
||||
# 机器分析使用 PopulateSha1MapStore 填充的全局内存存储器。
|
||||
#
|
||||
# Args:
|
||||
# mb: 内存池
|
||||
# temp_dir: 临时目录(_sha1_map.txt 写入位置)
|
||||
# scan_result: IncludesScanner 扫描结果
|
||||
#
|
||||
# Returns:
|
||||
# 0 成功,非 0 失败
|
||||
# ============================================================
|
||||
def WriteIncludesSha1Map(mb: memhub.MemBuddy | t.CPtr, temp_dir: str,
|
||||
scan_result: IncludesScanner.ScanResult | t.CPtr,
|
||||
filter_set: str,
|
||||
filter_count: int) -> int:
|
||||
"""将 includes 扫描结果写入 _sha1_map.txt(人类可读输出,程序内部使用内存存储器)
|
||||
|
||||
若 filter_set 不为 None 且 filter_count > 0,只写入 filter_set 中的条目。
|
||||
"""
|
||||
if temp_dir is None or scan_result is None:
|
||||
return 1
|
||||
|
||||
# 构造路径 temp_dir/_sha1_map.txt
|
||||
dir_len: t.CSizeT = string.strlen(temp_dir)
|
||||
map_path: bytes = stdlib.malloc(dir_len + 32)
|
||||
if map_path is None:
|
||||
return 1
|
||||
viperlib.snprintf(map_path, dir_len + 32, "%s/_sha1_map.txt", temp_dir)
|
||||
|
||||
# 打开文件写入(CREATE_ALWAYS)
|
||||
f: fileio.File | t.CPtr = fileio.File(map_path, fileio.MODE.W)
|
||||
if f.closed:
|
||||
return 1
|
||||
|
||||
# 写入每个 include 条目: {sha1}:includes/{rel_path}\n
|
||||
entry_size_w: t.CSizeT = IncludesScanner.FileEntry.__sizeof__()
|
||||
line_buf: bytes = stdlib.malloc(512)
|
||||
if line_buf is None:
|
||||
f.close()
|
||||
return 1
|
||||
|
||||
written_count: int = 0
|
||||
for i in range(scan_result.Count):
|
||||
ea_w: t.CUInt64T = t.CUInt64T(scan_result.Entries) + i * entry_size_w
|
||||
ent_w: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea_w, t.CPtr))
|
||||
if ent_w is None or ent_w.Sha1 is None or ent_w.RelPath is None:
|
||||
continue
|
||||
# 若提供过滤集合,只写入集合中的条目
|
||||
if filter_set is not None and filter_count > 0:
|
||||
if _is_in_sha1_set(ent_w.Sha1, filter_set, filter_count) == 0:
|
||||
continue
|
||||
viperlib.snprintf(line_buf, 512, "%s:includes/%s\n", ent_w.Sha1, ent_w.RelPath)
|
||||
line_len_w: t.CSizeT = string.strlen(line_buf)
|
||||
f.write(line_buf, line_len_w)
|
||||
written_count += 1
|
||||
|
||||
f.close()
|
||||
return 0
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import llvmlite
|
||||
import w32.win32file as win32file
|
||||
import w32.win32base as win32base
|
||||
import w32.fileio as fileio
|
||||
import viperlib
|
||||
import sys
|
||||
import ast
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import lib.core.BuildPipeline as BuildPipeline
|
||||
import lib.StubGen.VpiReader as VpiReader
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import lib.Projectrans.Config as Config
|
||||
|
||||
|
||||
import lib.core.StubMergerStore as StubMergerStore
|
||||
import lib.core.StubMergerTopo as StubMergerTopo
|
||||
import lib.core.StubMergerIR as StubMergerIR
|
||||
import lib.core.StubMergerBuild as StubMergerBuild
|
||||
import lib.core.StubMerger as StubMerger
|
||||
|
||||
# ============================================================
|
||||
# StubMergerCollect - StubMerger 拆分(阶段 E):StubMergerCollect
|
||||
#
|
||||
# 直接移动模式:函数实现迁至此模块,原 StubMerger.vp 仅保留
|
||||
# 常量/全局变量;调用方经本模块前缀访问。全局变量跨模块经
|
||||
# StubMerger._xxx 访问(main.vp 先例)。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# _sliced_path - 构建切片路径(stdlib.malloc 分配,调用者负责 free)
|
||||
#
|
||||
# 根据 Config.Sha1SliceLevel 将文件分散到 SHA1 前缀子目录:
|
||||
# level=0 → {temp_dir}/{sha1}.{ext}
|
||||
# level=1 → {temp_dir}/b7/{sha1}.{ext}
|
||||
# level=2 → {temp_dir}/b7/90/{sha1}.{ext}
|
||||
#
|
||||
# 自动调用 BuildPipeline.ensure_dir 创建子目录(level>0 时)。
|
||||
#
|
||||
# Args:
|
||||
# temp_dir: 基础目录
|
||||
# td_len: temp_dir 长度(避免重复 strlen)
|
||||
# sha1: SHA1 字符串
|
||||
# ext: 文件扩展名(如 "stub.ll")
|
||||
#
|
||||
# Returns:
|
||||
# 完整路径(stdlib.malloc 分配,需 stdlib.free),None 失败
|
||||
# ============================================================
|
||||
def _sliced_path(temp_dir: str, td_len: t.CSizeT, sha1: str, ext: str) -> str:
|
||||
"""构建切片路径(stdlib.malloc 分配,调用者负责 free)
|
||||
|
||||
level>0 时自动调用 ensure_dir 创建子目录。
|
||||
"""
|
||||
if temp_dir is None or sha1 is None or ext is None:
|
||||
return None
|
||||
sha1_len: t.CSizeT = string.strlen(sha1)
|
||||
ext_len: t.CSizeT = string.strlen(ext)
|
||||
|
||||
# 子目录前缀:复用 Config.slice_subdir(SHA1 切片唯一权威实现,mbuddy 分配无需 free)
|
||||
subdir_buf: str = Config.slice_subdir(sha1, Config.Sha1SliceLevel)
|
||||
sub_len: t.CSizeT = 0
|
||||
if subdir_buf is not None:
|
||||
sub_len = string.strlen(subdir_buf)
|
||||
|
||||
# 确保子目录存在: {temp_dir}/{subdir}
|
||||
# 不创建目录会导致 fileio.File(MODE.W) 静默失败(file.closed==True),
|
||||
# 进而 BuildCombinedIR 读不到文件返回 0("BuildCombinedIR 失败")。
|
||||
dir_path_len: t.CSizeT = td_len + sub_len + 2
|
||||
dir_path: bytes = stdlib.malloc(dir_path_len)
|
||||
if dir_path is not None:
|
||||
viperlib.snprintf(dir_path, dir_path_len, "%s/%s", temp_dir, subdir_buf)
|
||||
BuildPipeline.ensure_dir(dir_path)
|
||||
stdlib.free(dir_path)
|
||||
|
||||
# 构建完整路径
|
||||
path: str = None
|
||||
path_len: t.CSizeT = 0
|
||||
if sub_len > 0:
|
||||
path_len = td_len + sub_len + sha1_len + ext_len + 4
|
||||
path = stdlib.malloc(path_len)
|
||||
if path is not None:
|
||||
viperlib.snprintf(path, path_len, "%s/%s/%s.%s", temp_dir, subdir_buf, sha1, ext)
|
||||
else:
|
||||
path_len = td_len + sha1_len + ext_len + 3
|
||||
path = stdlib.malloc(path_len)
|
||||
if path is not None:
|
||||
viperlib.snprintf(path, path_len, "%s/%s.%s", temp_dir, sha1, ext)
|
||||
|
||||
return path
|
||||
# ============================================================
|
||||
# _collect_stub_sha1s - 递归扫描子目录,收集 .stub.ll 文件的 SHA1
|
||||
#
|
||||
# 根据 level 递归扫描子目录:
|
||||
# level=0 → 扫描 {base_dir}/*.stub.ll,从文件名提取 SHA1
|
||||
# level>0 → 扫描 {base_dir}/* 的子目录,对每个子目录递归调用
|
||||
#
|
||||
# Args:
|
||||
# base_dir: 当前扫描目录
|
||||
# bd_len: base_dir 长度
|
||||
# level: 剩余递归层数
|
||||
# out_arr: 输出数组(每个 SHA1 17 字节 = 16字符 + null)
|
||||
# out_count: 当前已收集数量
|
||||
# max_count: 最大数量
|
||||
#
|
||||
# Returns:
|
||||
# 收集后的总数量
|
||||
# ============================================================
|
||||
def _collect_stub_sha1s(base_dir: str, bd_len: t.CSizeT, level: int,
|
||||
out_arr: str, out_count: int, max_count: int) -> int:
|
||||
"""递归扫描子目录,收集 .stub.ll 文件的 SHA1"""
|
||||
if base_dir is None or out_arr is None:
|
||||
return out_count
|
||||
if out_count >= max_count:
|
||||
return out_count
|
||||
|
||||
find_data: win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(win32file.WIN32_FIND_DATAA.__sizeof__())
|
||||
if find_data is None:
|
||||
return out_count
|
||||
string.memset(find_data, 0, win32file.WIN32_FIND_DATAA.__sizeof__())
|
||||
|
||||
if level <= 0:
|
||||
# 扫描 {base_dir}/*.stub.ll
|
||||
pattern: bytes = stdlib.malloc(bd_len + 16)
|
||||
if pattern is None:
|
||||
stdlib.free(find_data)
|
||||
return out_count
|
||||
viperlib.snprintf(pattern, bd_len + 16, "%s/*.stub.ll", base_dir)
|
||||
handle: win32base.HANDLE = win32file.FindFirstFileA(pattern, find_data)
|
||||
stdlib.free(pattern)
|
||||
if handle != win32base.INVALID_HANDLE_VALUE:
|
||||
while 1:
|
||||
if out_count >= max_count:
|
||||
break
|
||||
fname: str = find_data.cFileName
|
||||
if fname is not None:
|
||||
if fname[0] != '\0':
|
||||
# 从文件名提取 SHA1(前 16 字符)
|
||||
string.strncpy(out_arr + out_count * 17, fname, 16)
|
||||
out_arr[out_count * 17 + 16] = '\0'
|
||||
out_count += 1
|
||||
if win32file.FindNextFileA(handle, find_data) == 0:
|
||||
break
|
||||
win32file.FindClose(handle)
|
||||
else:
|
||||
# 扫描 {base_dir}/* 的子目录
|
||||
pattern = stdlib.malloc(bd_len + 4)
|
||||
if pattern is None:
|
||||
stdlib.free(find_data)
|
||||
return out_count
|
||||
viperlib.snprintf(pattern, bd_len + 4, "%s/*", base_dir)
|
||||
handle = win32file.FindFirstFileA(pattern, find_data)
|
||||
stdlib.free(pattern)
|
||||
if handle != win32base.INVALID_HANDLE_VALUE:
|
||||
while 1:
|
||||
# 检查是否是目录(FILE_ATTRIBUTE_DIRECTORY = 0x10 = 16)
|
||||
attrs: t.CUInt32T = find_data.dwFileAttributes
|
||||
if(attrs & 16) != 0:
|
||||
fname = find_data.cFileName
|
||||
if fname is not None:
|
||||
# 跳过 "." 和 ".."
|
||||
is_dot: int = 0
|
||||
if fname[0] == '.':
|
||||
if fname[1] == '\0':
|
||||
is_dot = 1
|
||||
elif fname[1] == '.' and fname[2] == '\0':
|
||||
is_dot = 1
|
||||
if is_dot == 0:
|
||||
# 构建子目录路径并递归扫描
|
||||
sub_dir: str = Utils.JoinPath(base_dir, fname)
|
||||
if sub_dir is not None:
|
||||
sub_dir_len: t.CSizeT = string.strlen(sub_dir)
|
||||
out_count = _collect_stub_sha1s(sub_dir, sub_dir_len, level - 1, out_arr, out_count, max_count)
|
||||
stdlib.free(sub_dir)
|
||||
if win32file.FindNextFileA(handle, find_data) == 0:
|
||||
break
|
||||
win32file.FindClose(handle)
|
||||
|
||||
stdlib.free(find_data)
|
||||
return out_count
|
||||
# ============================================================
|
||||
# _load_includes_sha1_set - 从全局内存存储器收集 includes 的 SHA1
|
||||
#
|
||||
# 数据来源是 PopulateSha1MapStore 填充的全局存储器(不读取 _sha1_map.txt)。
|
||||
# 用于过滤 stub 文件,避免加载 TransPyV 自身源文件(lib/*)的 stub 导致链接失败。
|
||||
# ============================================================
|
||||
def _load_includes_sha1_set(pool: memhub.MemBuddy | t.CPtr,
|
||||
temp_dir: str,
|
||||
sha1_set: str) -> int:
|
||||
"""从全局内存存储器将 includes 的 SHA1 写入 sha1_set
|
||||
|
||||
pool/temp_dir 参数保留以兼容现有调用者,但不再使用。
|
||||
数据来源是 PopulateSha1MapStore 填充的全局存储器。
|
||||
sha1_set 大小为 MAX_INCLUDES_SHA1 * 17(每个 SHA1 16字符+null)
|
||||
返回找到的 includes SHA1 数量,-1 表示错误"""
|
||||
if sha1_set is None:
|
||||
return -1
|
||||
if StubMerger._sha1_store_arr is None:
|
||||
return -1
|
||||
count: int = 0
|
||||
for i in range(StubMerger._sha1_store_count):
|
||||
if count >= MAX_INCLUDES_SHA1:
|
||||
break
|
||||
idx: t.CSizeT = t.CSizeT(i) * 17
|
||||
string.strcpy(sha1_set + t.CSizeT(count) * 17, StubMerger._sha1_store_arr + idx)
|
||||
count += 1
|
||||
return count
|
||||
# ============================================================
|
||||
# _is_in_sha1_set - 检查 SHA1 是否在集合中
|
||||
# ============================================================
|
||||
def _is_in_sha1_set(sha1: str, sha1_set: str, set_count: int) -> int:
|
||||
"""检查 sha1 是否在集合中"""
|
||||
if sha1 is None or sha1_set is None:
|
||||
return 0
|
||||
for i in range(set_count):
|
||||
if string.strcmp(sha1_set + i * 17, sha1) == 0:
|
||||
return 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# WriteIncludesSha1Map - 将 includes 扫描结果写入 _sha1_map.txt(人类可读输出)
|
||||
#
|
||||
# _sha1_map.txt 仅作为人类可读的调试输出,程序内部不读取此文件。
|
||||
# 机器分析使用 PopulateSha1MapStore 填充的全局内存存储器。
|
||||
#
|
||||
# Args:
|
||||
# mb: 内存池
|
||||
# temp_dir: 临时目录(_sha1_map.txt 写入位置)
|
||||
# scan_result: IncludesScanner 扫描结果
|
||||
#
|
||||
# Returns:
|
||||
# 0 成功,非 0 失败
|
||||
# ============================================================
|
||||
def WriteIncludesSha1Map(mb: memhub.MemBuddy | t.CPtr, temp_dir: str,
|
||||
scan_result: IncludesScanner.ScanResult | t.CPtr,
|
||||
filter_set: str,
|
||||
filter_count: int) -> int:
|
||||
"""将 includes 扫描结果写入 _sha1_map.txt(人类可读输出,程序内部使用内存存储器)
|
||||
|
||||
若 filter_set 不为 None 且 filter_count > 0,只写入 filter_set 中的条目。
|
||||
"""
|
||||
if temp_dir is None or scan_result is None:
|
||||
return 1
|
||||
|
||||
# 构造路径 temp_dir/_sha1_map.txt
|
||||
dir_len: t.CSizeT = string.strlen(temp_dir)
|
||||
map_path: bytes = stdlib.malloc(dir_len + 32)
|
||||
if map_path is None:
|
||||
return 1
|
||||
viperlib.snprintf(map_path, dir_len + 32, "%s/_sha1_map.txt", temp_dir)
|
||||
|
||||
# 打开文件写入(CREATE_ALWAYS)
|
||||
f: fileio.File | t.CPtr = fileio.File(map_path, fileio.MODE.W)
|
||||
if f.closed:
|
||||
return 1
|
||||
|
||||
# 写入每个 include 条目: {sha1}:includes/{rel_path}\n
|
||||
entry_size_w: t.CSizeT = IncludesScanner.FileEntry.__sizeof__()
|
||||
line_buf: bytes = stdlib.malloc(512)
|
||||
if line_buf is None:
|
||||
f.close()
|
||||
return 1
|
||||
|
||||
written_count: int = 0
|
||||
for i in range(scan_result.Count):
|
||||
ea_w: t.CUInt64T = t.CUInt64T(scan_result.Entries) + i * entry_size_w
|
||||
ent_w: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea_w, t.CPtr))
|
||||
if ent_w is None or ent_w.Sha1 is None or ent_w.RelPath is None:
|
||||
continue
|
||||
# 若提供过滤集合,只写入集合中的条目
|
||||
if filter_set is not None and filter_count > 0:
|
||||
if _is_in_sha1_set(ent_w.Sha1, filter_set, filter_count) == 0:
|
||||
continue
|
||||
viperlib.snprintf(line_buf, 512, "%s:includes/%s\n", ent_w.Sha1, ent_w.RelPath)
|
||||
line_len_w: t.CSizeT = string.strlen(line_buf)
|
||||
f.write(line_buf, line_len_w)
|
||||
written_count += 1
|
||||
|
||||
f.close()
|
||||
return 0
|
||||
+415
-416
@@ -1,416 +1,415 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import llvmlite
|
||||
import w32.win32file as win32file
|
||||
import w32.win32base as win32base
|
||||
import w32.fileio as fileio
|
||||
import viperlib
|
||||
import sys
|
||||
import ast
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import lib.core.BuildPipeline as BuildPipeline
|
||||
import lib.StubGen.VpiReader as VpiReader
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import lib.Projectrans.Config as Config
|
||||
|
||||
|
||||
import lib.core.StubMergerCollect as StubMergerCollect
|
||||
import lib.core.StubMergerStore as StubMergerStore
|
||||
import lib.core.StubMergerTopo as StubMergerTopo
|
||||
import lib.core.StubMergerBuild as StubMergerBuild
|
||||
import lib.core.StubMerger as StubMerger
|
||||
|
||||
# ============================================================
|
||||
# StubMergerIR - StubMerger 拆分(阶段 E):StubMergerIR
|
||||
#
|
||||
# 直接移动模式:函数实现迁至此模块,原 StubMerger.vp 仅保留
|
||||
# 常量/全局变量;调用方经本模块前缀访问。全局变量跨模块经
|
||||
# StubMerger._xxx 访问(main.vp 先例)。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# IsDeclOnlyModule - 判断模块是否为纯声明文件
|
||||
#
|
||||
# 读取 {temp_dir}/{sha1}.text.ll,扫描是否含 "define " 行:
|
||||
# 返回 1 = 纯声明(无函数体,如 stdio.vp 全 pass),无需 .obj
|
||||
# 返回 0 = 实现文件(含 define 函数体)
|
||||
# 返回 -1 = text.ll 不存在/无法判断
|
||||
#
|
||||
# 与 Phase B+(Phase2.vp 编译缺失 includes 时)的内联判断逻辑一致,
|
||||
# 供 Phase C 链接时区分"声明文件无需 .obj"与"实现文件缺失"。
|
||||
# ============================================================
|
||||
def IsDeclOnlyModule(temp_dir: str, td_len: t.CSizeT, sha1: str) -> int:
|
||||
"""判断模块是否为纯声明文件(text.ll 无 define 行)"""
|
||||
if temp_dir is None or sha1 is None:
|
||||
return -1
|
||||
tpath: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1, "text.ll")
|
||||
if tpath is None:
|
||||
return -1
|
||||
tf_d: fileio.File | t.CPtr = fileio.File(tpath, fileio.MODE.R)
|
||||
stdlib.free(tpath)
|
||||
if tf_d.closed:
|
||||
return -1
|
||||
tbuf_d: bytes = stdlib.malloc(STUB_READ_BUF_SIZE)
|
||||
tbr_d: t.CInt64T = 0
|
||||
if tbuf_d is not None:
|
||||
tbr_d = tf_d.read_all(tbuf_d, STUB_READ_BUF_SIZE)
|
||||
tf_d.close()
|
||||
if tbuf_d is None:
|
||||
return -1
|
||||
if tbr_d <= 0:
|
||||
# 空 text.ll:无函数体,纯声明
|
||||
stdlib.free(tbuf_d)
|
||||
return 1
|
||||
if tbr_d < STUB_READ_BUF_SIZE:
|
||||
tbuf_d[tbr_d] = '\0'
|
||||
else:
|
||||
tbuf_d[STUB_READ_BUF_SIZE - 1] = '\0'
|
||||
# 逐行扫描:找 "define " 行即为实现文件
|
||||
tpos_d: t.CSizeT = 0
|
||||
while tpos_d < tbr_d:
|
||||
tls_d: t.CSizeT = tpos_d
|
||||
while tpos_d < tbr_d:
|
||||
if tbuf_d[tpos_d] == '\n':
|
||||
break
|
||||
tpos_d += 1
|
||||
tll_d: t.CSizeT = tpos_d - tls_d
|
||||
if tpos_d < tbr_d:
|
||||
tpos_d += 1
|
||||
if tll_d >= 7 and string.strncmp(tbuf_d + tls_d, "define ", 7) == 0:
|
||||
stdlib.free(tbuf_d)
|
||||
return 0
|
||||
stdlib.free(tbuf_d)
|
||||
return 1
|
||||
# ============================================================
|
||||
# _IsFuncDeclaredOrDefined - 检查 out_buf 中是否已有函数的 declare/define
|
||||
#
|
||||
# 逐字节strncmp搜索 func_sig(如 @"sha1.func"(/ @printf( ),每次
|
||||
# 找到匹配后检查行首是否以 "declare " 或 "define " 开头,跳过 call 语句。
|
||||
# 避免 strstr 子串匹配误匹配 call ... @"func"(...) 中的 @"func"( 子串。
|
||||
#
|
||||
# Args:
|
||||
# out_buf: 已有的 IR 文本缓冲区
|
||||
# func_sig: 函数签名片段,如 @"sha1.func"(/ @printf(
|
||||
#
|
||||
# Returns:
|
||||
# 1=已存在 declare/define, 0=不存在
|
||||
# ============================================================
|
||||
def _IsFuncDeclaredOrDefined(out_buf: bytes, func_sig: str) -> int:
|
||||
"""检查 out_buf 中是否已有函数的 declare 或 define 行"""
|
||||
if out_buf is None or func_sig is None:
|
||||
return 0
|
||||
sig_len: t.CSizeT = string.strlen(func_sig)
|
||||
out_len: t.CSizeT = string.strlen(out_buf)
|
||||
if sig_len == 0 or out_len == 0 or sig_len > out_len:
|
||||
return 0
|
||||
pos: t.CSizeT = 0
|
||||
while pos + sig_len <= out_len:
|
||||
if string.strncmp(out_buf + pos, func_sig, sig_len) == 0:
|
||||
ls: t.CSizeT = pos
|
||||
while ls > 0 and out_buf[ls - 1] != '\n':
|
||||
ls -= 1
|
||||
if string.strncmp(out_buf + ls, "declare ", 8) == 0:
|
||||
return 1
|
||||
if string.strncmp(out_buf + ls, "define ", 7) == 0:
|
||||
return 1
|
||||
pos += 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# _CommentOutDeclareInBuf - 将 out_buf 中匹配 func_sig 的 declare 行注释掉
|
||||
#
|
||||
# 用于解决 declare/define 冲突:当本地 text.ll 包含 define 而依赖
|
||||
# text.ll 已生成了同函数的 declare 时,将 declare 行首字符改为 ';'
|
||||
# 使其成为注释,然后追加 define 行。
|
||||
# ============================================================
|
||||
def _CommentOutDeclareInBuf(out_buf: bytes, func_sig: str) -> int:
|
||||
"""在 out_buf 中搜索 declare 行(包含 func_sig),将其注释掉"""
|
||||
if out_buf is None or func_sig is None:
|
||||
return 0
|
||||
sig_len: t.CSizeT = string.strlen(func_sig)
|
||||
out_len: t.CSizeT = string.strlen(out_buf)
|
||||
if sig_len == 0 or out_len == 0 or sig_len > out_len:
|
||||
return 0
|
||||
pos: t.CSizeT = 0
|
||||
while pos + sig_len <= out_len:
|
||||
if string.strncmp(out_buf + pos, func_sig, sig_len) == 0:
|
||||
ls: t.CSizeT = pos
|
||||
while ls > 0 and out_buf[ls - 1] != '\n':
|
||||
ls -= 1
|
||||
if string.strncmp(out_buf + ls, "declare ", 8) == 0:
|
||||
out_buf[ls] = ';'
|
||||
return 1
|
||||
pos += 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# _CommentOutGlobalInBuf - 将 out_buf 中匹配全局变量名的行注释掉
|
||||
#
|
||||
# 解决 stub/text 全局变量重复定义问题:stub 中可能是 external 声明
|
||||
# 或完整定义,以 text 中的定义为准,将 stub 中的同名行注释掉。
|
||||
# ============================================================
|
||||
def _CommentOutGlobalInBuf(out_buf: bytes, global_name: str) -> int:
|
||||
"""在 out_buf 中搜索全局变量定义行(以 global_name 开头),将行首改为 ';'
|
||||
|
||||
注释掉**所有**匹配行(而非仅第一个):跨模块同名裸全局(如 main.vp 与
|
||||
argparse.vp 都声明 StubMerger._mbuddy)时,本地 stub external + 依赖 stub external +
|
||||
依赖 text 定义会同时存在。只注释第一个会导致依赖 text 的定义残留 →
|
||||
合成 IR 重复定义 → llc "redefinition of global '@StubMerger._mbuddy'"(ArgparseTest
|
||||
回归根因)。"以 text 中定义为准"的语义:后追加者注释掉全部旧行,最终
|
||||
只保留最后一个定义。
|
||||
"""
|
||||
if out_buf is None or global_name is None:
|
||||
return 0
|
||||
name_len: t.CSizeT = string.strlen(global_name)
|
||||
out_len: t.CSizeT = string.strlen(out_buf)
|
||||
if name_len == 0 or out_len == 0 or name_len > out_len:
|
||||
return 0
|
||||
pos: t.CSizeT = 0
|
||||
commented: int = 0
|
||||
while pos + name_len <= out_len:
|
||||
if string.strncmp(out_buf + pos, global_name, name_len) == 0:
|
||||
# 确认是行首(前一个是换行或 pos==0)
|
||||
if pos == 0 or out_buf[pos - 1] == '\n':
|
||||
out_buf[pos] = ';'
|
||||
commented = 1
|
||||
pos += 1
|
||||
return commented
|
||||
def _HasGlobalInBuf(out_buf: bytes, global_name: str) -> int:
|
||||
"""检测 out_buf 中是否已有同名全局变量行(行首匹配,未注释)
|
||||
|
||||
用于跳过重复追加依赖全局强定义:stub 注入已提供 external 声明,
|
||||
依赖 text.ll 的强定义只需在定义模块存在一份,复制进每个依赖方
|
||||
会导致 ld.lld duplicate symbol(如 _op_head、MemBuddy.vtable)。
|
||||
"""
|
||||
if out_buf is None or global_name is None:
|
||||
return 0
|
||||
name_len: t.CSizeT = string.strlen(global_name)
|
||||
out_len: t.CSizeT = string.strlen(out_buf)
|
||||
if name_len == 0 or out_len == 0 or name_len > out_len:
|
||||
return 0
|
||||
pos: t.CSizeT = 0
|
||||
while pos + name_len <= out_len:
|
||||
if string.strncmp(out_buf + pos, global_name, name_len) == 0:
|
||||
# 确认是行首(前一个是换行或 pos==0)
|
||||
if pos == 0 or out_buf[pos - 1] == '\n':
|
||||
return 1
|
||||
pos += 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# _CommentOutOpaqueTypeInBuf - 将 out_buf 中匹配类型名的 opaque 声明行注释掉
|
||||
#
|
||||
# 解决跨模块类型定义冲突:本地 stub 可能包含自动生成的 opaque 声明
|
||||
#(如 %"sha1.Widget" = type opaque),而依赖 stub 包含完整定义
|
||||
#(如 %"sha1.Widget" = type { i8*, i32 })。去重时需要将 opaque 声明
|
||||
# 注释掉,让完整定义被追加,否则 LLC 报错 "Cannot allocate unsized type"。
|
||||
# ============================================================
|
||||
def _CommentOutOpaqueTypeInBuf(out_buf: bytes, type_name_prefix: str) -> int:
|
||||
"""在 out_buf 中搜索 type_name_prefix 对应的 opaque 声明行,将行首改为 ';'
|
||||
|
||||
type_name_prefix 格式: '%"sha1.ClassName"'(不含 '=' 和后续内容)
|
||||
返回 1=已注释, 0=未找到
|
||||
"""
|
||||
if out_buf is None or type_name_prefix is None:
|
||||
return 0
|
||||
prefix_len: t.CSizeT = string.strlen(type_name_prefix)
|
||||
out_len: t.CSizeT = string.strlen(out_buf)
|
||||
if prefix_len == 0 or out_len == 0 or prefix_len > out_len:
|
||||
return 0
|
||||
pos: t.CSizeT = 0
|
||||
while pos + prefix_len <= out_len:
|
||||
if string.strncmp(out_buf + pos, type_name_prefix, prefix_len) == 0:
|
||||
# 确认是行首(前一个是换行或 pos==0)
|
||||
if pos == 0 or out_buf[pos - 1] == '\n':
|
||||
# 检查后面是否是 " = type opaque"
|
||||
p: t.CSizeT = pos + prefix_len
|
||||
# 跳过空格
|
||||
while p < out_len and out_buf[p] == ' ':
|
||||
p += 1
|
||||
if p < out_len and out_buf[p] == '=':
|
||||
p += 1
|
||||
while p < out_len and out_buf[p] == ' ':
|
||||
p += 1
|
||||
if p + 11 <= out_len:
|
||||
if string.strncmp(out_buf + p, "type opaque", 11) == 0:
|
||||
# 找到 opaque 声明,将行首改为 ';'
|
||||
out_buf[pos] = ';'
|
||||
return 1
|
||||
pos += 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# _is_submodule_of_imported - 检查模块名是否是已导入包的子模块
|
||||
#
|
||||
# deps.txt 只记录直接导入的模块名(如 "ast"),但包的 __init__.vp
|
||||
# 内部 from .lexer import Lexer 会让 IR 引用 ast.lexer 子模块类型。
|
||||
# 当模块名包含 '.' 时,检查其顶层包名是否在 deps_buf 中。
|
||||
#
|
||||
# 例如:
|
||||
# deps_buf = "ast stdio string"
|
||||
# mod_name = "ast.lexer" → 顶层包 "ast" 在 deps_buf 中 → 返回 1
|
||||
# mod_name = "ast.token" → 顶层包 "ast" 在 deps_buf 中 → 返回 1
|
||||
# mod_name = "foo.bar" → 顶层包 "foo" 不在 deps_buf 中 → 返回 0
|
||||
# ============================================================
|
||||
def _is_submodule_of_imported(deps_buf: str, mod_name: str) -> int:
|
||||
"""检查 mod_name 是否是 deps_buf 中已导入包的子模块"""
|
||||
if deps_buf is None or mod_name is None:
|
||||
return 0
|
||||
# 查找第一个 '.',提取顶层包名
|
||||
dot_pos: str = string.strchr(mod_name, 46) # '.' = 46
|
||||
if dot_pos is None:
|
||||
return 0
|
||||
pkg_len: t.CSizeT = t.CSizeT(t.CUInt64T(dot_pos) - t.CUInt64T(mod_name))
|
||||
if pkg_len == 0 or pkg_len >= 256:
|
||||
return 0
|
||||
# 构造顶层包名(截断到 '.' 之前)
|
||||
# 直接在 mod_name 上临时截断检查,避免分配
|
||||
saved_ch: t.CChar = mod_name[pkg_len]
|
||||
mod_name[pkg_len] = '\0'
|
||||
result: int = HandlesImports.is_module_imported(deps_buf, mod_name)
|
||||
mod_name[pkg_len] = saved_ch
|
||||
return result
|
||||
# ============================================================
|
||||
# _HasFullTypeDefinition - 检查 out_buf 中是否已有完整类型定义(非 opaque)
|
||||
#
|
||||
# type_name_prefix 格式: '%"sha1.ClassName"'(不含 '=')
|
||||
# 完整定义: %"name" = type { ... } 或 %"name" = type < { ... } >
|
||||
# 返回 1=已有完整定义, 0=无完整定义
|
||||
# ============================================================
|
||||
def _HasFullTypeDefinition(out_buf: bytes, type_name_prefix: str) -> int:
|
||||
"""检查 out_buf 中是否已有 type_name_prefix 的完整定义"""
|
||||
if out_buf is None or type_name_prefix is None:
|
||||
return 0
|
||||
prefix_len: t.CSizeT = string.strlen(type_name_prefix)
|
||||
out_len: t.CSizeT = string.strlen(out_buf)
|
||||
if prefix_len == 0 or out_len == 0 or prefix_len > out_len:
|
||||
return 0
|
||||
pos: t.CSizeT = 0
|
||||
while pos + prefix_len <= out_len:
|
||||
if string.strncmp(out_buf + pos, type_name_prefix, prefix_len) == 0:
|
||||
# 确认是行首(前一个是换行或 pos==0),且未被注释(行首不是 ';')
|
||||
is_line_start: int = 0
|
||||
if pos == 0:
|
||||
is_line_start = 1
|
||||
elif out_buf[pos - 1] == '\n':
|
||||
is_line_start = 1
|
||||
if is_line_start == 1:
|
||||
# 检查后面是否是 " = type {" 或 " = type <"
|
||||
p: t.CSizeT = pos + prefix_len
|
||||
while p < out_len and out_buf[p] == ' ':
|
||||
p += 1
|
||||
if p < out_len and out_buf[p] == '=':
|
||||
p += 1
|
||||
while p < out_len and out_buf[p] == ' ':
|
||||
p += 1
|
||||
if p + 5 < out_len:
|
||||
if string.strncmp(out_buf + p, "type ", 5) == 0:
|
||||
p += 5
|
||||
if p < out_len:
|
||||
if out_buf[p] == '{' or out_buf[p] == '<':
|
||||
return 1
|
||||
pos += 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# _BuildIncludesSha1Map - 从全局内存存储器构建 sha1 → module_name 映射
|
||||
#
|
||||
# 数据来源是 PopulateSha1MapStore 填充的全局存储器(不读取 _sha1_map.txt)。
|
||||
# 返回两个数组(sha1_list 和 mod_list),长度存储在 count 中。
|
||||
# 所有内存由 stdlib.malloc 分配,调用者负责释放。
|
||||
# ============================================================
|
||||
def _BuildIncludesSha1Map(temp_dir: str, td_len: t.CSizeT,
|
||||
sha1_list: str,
|
||||
mod_list: str) -> int:
|
||||
"""从全局内存存储器复制 sha1→module_name 映射到调用者数组
|
||||
|
||||
temp_dir/td_len 参数保留以兼容现有调用者,但不再使用。
|
||||
数据来源是 PopulateSha1MapStore 填充的全局存储器。
|
||||
"""
|
||||
if sha1_list is None or mod_list is None:
|
||||
return 0
|
||||
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None:
|
||||
return 0
|
||||
count: int = 0
|
||||
for i in range(StubMerger._sha1_store_count):
|
||||
if count >= MAX_INCLUDES:
|
||||
break
|
||||
idx: t.CSizeT = t.CSizeT(i) * 17
|
||||
idx2: t.CSizeT = t.CSizeT(i) * 64
|
||||
string.strcpy(sha1_list + t.CSizeT(count) * 17, StubMerger._sha1_store_arr + idx)
|
||||
string.strcpy(mod_list + t.CSizeT(count) * 64, StubMerger._sha1_store_mod + idx2)
|
||||
count += 1
|
||||
return count
|
||||
# ============================================================
|
||||
# _FindSha1ByModName - 从模块名查找 SHA1(精确匹配)
|
||||
#
|
||||
# 在 sha1_arr/mod_arr 映射中查找模块名对应的 SHA1。
|
||||
# 用于依赖图分析:模块名 → SHA1。
|
||||
#
|
||||
# Args:
|
||||
# sha1_arr: SHA1 数组(每个 17 字节)
|
||||
# mod_arr: 模块名数组(每个 64 字节)
|
||||
# count: 映射条目数
|
||||
# mod_name: 要查找的模块名
|
||||
#
|
||||
# Returns:
|
||||
# SHA1 字符串指针(指向 sha1_arr 内部,无需释放),未找到返回 None
|
||||
# ============================================================
|
||||
def _FindSha1ByModName(sha1_arr: str, mod_arr: str,
|
||||
count: int, mod_name: str) -> str:
|
||||
"""从模块名查找 SHA1(精确匹配 + 包名回退)
|
||||
|
||||
精确匹配失败时,尝试 "{mod_name}.__init__" 回退,
|
||||
支持 import ast(包)→ ast.__init__ 的 SHA1 查找。
|
||||
"""
|
||||
if sha1_arr is None or mod_arr is None or mod_name is None:
|
||||
return None
|
||||
if count <= 0:
|
||||
return None
|
||||
# 第一遍:精确匹配
|
||||
for i in range(count):
|
||||
idx: t.CSizeT = t.CSizeT(i) * 64
|
||||
if string.strcmp(mod_arr + idx, mod_name) == 0:
|
||||
sidx: t.CSizeT = t.CSizeT(i) * 17
|
||||
return sha1_arr + sidx
|
||||
# 第二遍:包名回退("ast" → "ast.__init__")
|
||||
nm_len: t.CSizeT = string.strlen(mod_name)
|
||||
init_buf: bytes = stdlib.malloc(nm_len + 12)
|
||||
if init_buf is not None:
|
||||
viperlib.snprintf(init_buf, nm_len + 12, "%s.__init__", mod_name)
|
||||
for i in range(count):
|
||||
idx2: t.CSizeT = t.CSizeT(i) * 64
|
||||
if string.strcmp(mod_arr + idx2, init_buf) == 0:
|
||||
sidx2: t.CSizeT = t.CSizeT(i) * 17
|
||||
stdlib.free(init_buf)
|
||||
return sha1_arr + sidx2
|
||||
stdlib.free(init_buf)
|
||||
return None
|
||||
# ============================================================
|
||||
# _AddSha1ToSet - 将 SHA1 加入集合(去重)
|
||||
#
|
||||
# 检查 SHA1 是否已在集合中,若不在则加入。返回新的 count。
|
||||
#
|
||||
# Args:
|
||||
# set_buf: SHA1 集合缓冲区(每个 17 字节)
|
||||
# count: 当前集合中的 SHA1 数量
|
||||
# sha1: 要加入的 SHA1
|
||||
#
|
||||
# Returns:
|
||||
# 新的 count(如果已存在则不变)
|
||||
# ============================================================
|
||||
def _AddSha1ToSet(set_buf: str, count: int, sha1: str) -> int:
|
||||
"""将 SHA1 加入集合,返回新 count"""
|
||||
if set_buf is None or sha1 is None:
|
||||
return count
|
||||
for i in range(count):
|
||||
idx: t.CSizeT = t.CSizeT(i) * 17
|
||||
if string.strcmp(set_buf + idx, sha1) == 0:
|
||||
return count
|
||||
if count < MAX_INCLUDES_SHA1:
|
||||
idx: t.CSizeT = t.CSizeT(count) * 17
|
||||
string.strcpy(set_buf + idx, sha1)
|
||||
return count + 1
|
||||
return count
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import llvmlite
|
||||
import w32.win32file as win32file
|
||||
import w32.win32base as win32base
|
||||
import w32.fileio as fileio
|
||||
import viperlib
|
||||
import sys
|
||||
import ast
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import lib.core.BuildPipeline as BuildPipeline
|
||||
import lib.StubGen.VpiReader as VpiReader
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import lib.Projectrans.Config as Config
|
||||
|
||||
|
||||
import lib.core.StubMergerCollect as StubMergerCollect
|
||||
import lib.core.StubMergerStore as StubMergerStore
|
||||
import lib.core.StubMergerTopo as StubMergerTopo
|
||||
import lib.core.StubMergerBuild as StubMergerBuild
|
||||
import lib.core.StubMerger as StubMerger
|
||||
|
||||
# ============================================================
|
||||
# StubMergerIR - StubMerger 拆分(阶段 E):StubMergerIR
|
||||
#
|
||||
# 直接移动模式:函数实现迁至此模块,原 StubMerger.vp 仅保留
|
||||
# 常量/全局变量;调用方经本模块前缀访问。全局变量跨模块经
|
||||
# StubMerger._xxx 访问(main.vp 先例)。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# IsDeclOnlyModule - 判断模块是否为纯声明文件
|
||||
#
|
||||
# 读取 {temp_dir}/{sha1}.text.ll,扫描是否含 "define " 行:
|
||||
# 返回 1 = 纯声明(无函数体,如 stdio.vp 全 pass),无需 .obj
|
||||
# 返回 0 = 实现文件(含 define 函数体)
|
||||
# 返回 -1 = text.ll 不存在/无法判断
|
||||
#
|
||||
# 与 Phase B+(Phase2.vp 编译缺失 includes 时)的内联判断逻辑一致,
|
||||
# 供 Phase C 链接时区分"声明文件无需 .obj"与"实现文件缺失"。
|
||||
# ============================================================
|
||||
def IsDeclOnlyModule(temp_dir: str, td_len: t.CSizeT, sha1: str) -> int:
|
||||
"""判断模块是否为纯声明文件(text.ll 无 define 行)"""
|
||||
if temp_dir is None or sha1 is None:
|
||||
return -1
|
||||
tpath: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1, "text.ll")
|
||||
if tpath is None:
|
||||
return -1
|
||||
tf_d: fileio.File | t.CPtr = fileio.File(tpath, fileio.MODE.R)
|
||||
stdlib.free(tpath)
|
||||
if tf_d.closed:
|
||||
return -1
|
||||
tbuf_d: bytes = stdlib.malloc(STUB_READ_BUF_SIZE)
|
||||
tbr_d: t.CInt64T = 0
|
||||
if tbuf_d is not None:
|
||||
tbr_d = tf_d.read_all(tbuf_d, STUB_READ_BUF_SIZE)
|
||||
tf_d.close()
|
||||
if tbuf_d is None:
|
||||
return -1
|
||||
if tbr_d <= 0:
|
||||
# 空 text.ll:无函数体,纯声明
|
||||
stdlib.free(tbuf_d)
|
||||
return 1
|
||||
if tbr_d < STUB_READ_BUF_SIZE:
|
||||
tbuf_d[tbr_d] = '\0'
|
||||
else:
|
||||
tbuf_d[STUB_READ_BUF_SIZE - 1] = '\0'
|
||||
# 逐行扫描:找 "define " 行即为实现文件
|
||||
tpos_d: t.CSizeT = 0
|
||||
while tpos_d < tbr_d:
|
||||
tls_d: t.CSizeT = tpos_d
|
||||
while tpos_d < tbr_d:
|
||||
if tbuf_d[tpos_d] == '\n':
|
||||
break
|
||||
tpos_d += 1
|
||||
tll_d: t.CSizeT = tpos_d - tls_d
|
||||
if tpos_d < tbr_d:
|
||||
tpos_d += 1
|
||||
if tll_d >= 7 and string.strncmp(tbuf_d + tls_d, "define ", 7) == 0:
|
||||
stdlib.free(tbuf_d)
|
||||
return 0
|
||||
stdlib.free(tbuf_d)
|
||||
return 1
|
||||
# ============================================================
|
||||
# _IsFuncDeclaredOrDefined - 检查 out_buf 中是否已有函数的 declare/define
|
||||
#
|
||||
# 逐字节strncmp搜索 func_sig(如 @"sha1.func"(/ @printf( ),每次
|
||||
# 找到匹配后检查行首是否以 "declare " 或 "define " 开头,跳过 call 语句。
|
||||
# 避免 strstr 子串匹配误匹配 call ... @"func"(...) 中的 @"func"( 子串。
|
||||
#
|
||||
# Args:
|
||||
# out_buf: 已有的 IR 文本缓冲区
|
||||
# func_sig: 函数签名片段,如 @"sha1.func"(/ @printf(
|
||||
#
|
||||
# Returns:
|
||||
# 1=已存在 declare/define, 0=不存在
|
||||
# ============================================================
|
||||
def _IsFuncDeclaredOrDefined(out_buf: bytes, func_sig: str) -> int:
|
||||
"""检查 out_buf 中是否已有函数的 declare 或 define 行"""
|
||||
if out_buf is None or func_sig is None:
|
||||
return 0
|
||||
sig_len: t.CSizeT = string.strlen(func_sig)
|
||||
out_len: t.CSizeT = string.strlen(out_buf)
|
||||
if sig_len == 0 or out_len == 0 or sig_len > out_len:
|
||||
return 0
|
||||
pos: t.CSizeT = 0
|
||||
while pos + sig_len <= out_len:
|
||||
if string.strncmp(out_buf + pos, func_sig, sig_len) == 0:
|
||||
ls: t.CSizeT = pos
|
||||
while ls > 0 and out_buf[ls - 1] != '\n':
|
||||
ls -= 1
|
||||
if string.strncmp(out_buf + ls, "declare ", 8) == 0:
|
||||
return 1
|
||||
if string.strncmp(out_buf + ls, "define ", 7) == 0:
|
||||
return 1
|
||||
pos += 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# _CommentOutDeclareInBuf - 将 out_buf 中匹配 func_sig 的 declare 行注释掉
|
||||
#
|
||||
# 用于解决 declare/define 冲突:当本地 text.ll 包含 define 而依赖
|
||||
# text.ll 已生成了同函数的 declare 时,将 declare 行首字符改为 ';'
|
||||
# 使其成为注释,然后追加 define 行。
|
||||
# ============================================================
|
||||
def _CommentOutDeclareInBuf(out_buf: bytes, func_sig: str) -> int:
|
||||
"""在 out_buf 中搜索 declare 行(包含 func_sig),将其注释掉"""
|
||||
if out_buf is None or func_sig is None:
|
||||
return 0
|
||||
sig_len: t.CSizeT = string.strlen(func_sig)
|
||||
out_len: t.CSizeT = string.strlen(out_buf)
|
||||
if sig_len == 0 or out_len == 0 or sig_len > out_len:
|
||||
return 0
|
||||
pos: t.CSizeT = 0
|
||||
while pos + sig_len <= out_len:
|
||||
if string.strncmp(out_buf + pos, func_sig, sig_len) == 0:
|
||||
ls: t.CSizeT = pos
|
||||
while ls > 0 and out_buf[ls - 1] != '\n':
|
||||
ls -= 1
|
||||
if string.strncmp(out_buf + ls, "declare ", 8) == 0:
|
||||
out_buf[ls] = ';'
|
||||
return 1
|
||||
pos += 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# _CommentOutGlobalInBuf - 将 out_buf 中匹配全局变量名的行注释掉
|
||||
#
|
||||
# 解决 stub/text 全局变量重复定义问题:stub 中可能是 external 声明
|
||||
# 或完整定义,以 text 中的定义为准,将 stub 中的同名行注释掉。
|
||||
# ============================================================
|
||||
def _CommentOutGlobalInBuf(out_buf: bytes, global_name: str) -> int:
|
||||
"""在 out_buf 中搜索全局变量定义行(以 global_name 开头),将行首改为 ';'
|
||||
|
||||
注释掉**所有**匹配行(而非仅第一个):跨模块同名裸全局(如 main.vp 与
|
||||
argparse.vp 都声明 StubMerger._mbuddy)时,本地 stub external + 依赖 stub external +
|
||||
依赖 text 定义会同时存在。只注释第一个会导致依赖 text 的定义残留 →
|
||||
合成 IR 重复定义 → llc "redefinition of global '@StubMerger._mbuddy'"(ArgparseTest
|
||||
回归根因)。"以 text 中定义为准"的语义:后追加者注释掉全部旧行,最终
|
||||
只保留最后一个定义。
|
||||
"""
|
||||
if out_buf is None or global_name is None:
|
||||
return 0
|
||||
name_len: t.CSizeT = string.strlen(global_name)
|
||||
out_len: t.CSizeT = string.strlen(out_buf)
|
||||
if name_len == 0 or out_len == 0 or name_len > out_len:
|
||||
return 0
|
||||
pos: t.CSizeT = 0
|
||||
commented: int = 0
|
||||
while pos + name_len <= out_len:
|
||||
if string.strncmp(out_buf + pos, global_name, name_len) == 0:
|
||||
# 确认是行首(前一个是换行或 pos==0)
|
||||
if pos == 0 or out_buf[pos - 1] == '\n':
|
||||
out_buf[pos] = ';'
|
||||
commented = 1
|
||||
pos += 1
|
||||
return commented
|
||||
def _HasGlobalInBuf(out_buf: bytes, global_name: str) -> int:
|
||||
"""检测 out_buf 中是否已有同名全局变量行(行首匹配,未注释)
|
||||
|
||||
用于跳过重复追加依赖全局强定义:stub 注入已提供 external 声明,
|
||||
依赖 text.ll 的强定义只需在定义模块存在一份,复制进每个依赖方
|
||||
会导致 ld.lld duplicate symbol(如 _op_head、MemBuddy.vtable)。
|
||||
"""
|
||||
if out_buf is None or global_name is None:
|
||||
return 0
|
||||
name_len: t.CSizeT = string.strlen(global_name)
|
||||
out_len: t.CSizeT = string.strlen(out_buf)
|
||||
if name_len == 0 or out_len == 0 or name_len > out_len:
|
||||
return 0
|
||||
pos: t.CSizeT = 0
|
||||
while pos + name_len <= out_len:
|
||||
if string.strncmp(out_buf + pos, global_name, name_len) == 0:
|
||||
# 确认是行首(前一个是换行或 pos==0)
|
||||
if pos == 0 or out_buf[pos - 1] == '\n':
|
||||
return 1
|
||||
pos += 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# _CommentOutOpaqueTypeInBuf - 将 out_buf 中匹配类型名的 opaque 声明行注释掉
|
||||
#
|
||||
# 解决跨模块类型定义冲突:本地 stub 可能包含自动生成的 opaque 声明
|
||||
#(如 %"sha1.Widget" = type opaque),而依赖 stub 包含完整定义
|
||||
#(如 %"sha1.Widget" = type { i8*, i32 })。去重时需要将 opaque 声明
|
||||
# 注释掉,让完整定义被追加,否则 LLC 报错 "Cannot allocate unsized type"。
|
||||
# ============================================================
|
||||
def _CommentOutOpaqueTypeInBuf(out_buf: bytes, type_name_prefix: str) -> int:
|
||||
"""在 out_buf 中搜索 type_name_prefix 对应的 opaque 声明行,将行首改为 ';'
|
||||
|
||||
type_name_prefix 格式: '%"sha1.ClassName"'(不含 '=' 和后续内容)
|
||||
返回 1=已注释, 0=未找到
|
||||
"""
|
||||
if out_buf is None or type_name_prefix is None:
|
||||
return 0
|
||||
prefix_len: t.CSizeT = string.strlen(type_name_prefix)
|
||||
out_len: t.CSizeT = string.strlen(out_buf)
|
||||
if prefix_len == 0 or out_len == 0 or prefix_len > out_len:
|
||||
return 0
|
||||
pos: t.CSizeT = 0
|
||||
while pos + prefix_len <= out_len:
|
||||
if string.strncmp(out_buf + pos, type_name_prefix, prefix_len) == 0:
|
||||
# 确认是行首(前一个是换行或 pos==0)
|
||||
if pos == 0 or out_buf[pos - 1] == '\n':
|
||||
# 检查后面是否是 " = type opaque"
|
||||
p: t.CSizeT = pos + prefix_len
|
||||
# 跳过空格
|
||||
while p < out_len and out_buf[p] == ' ':
|
||||
p += 1
|
||||
if p < out_len and out_buf[p] == '=':
|
||||
p += 1
|
||||
while p < out_len and out_buf[p] == ' ':
|
||||
p += 1
|
||||
if p + 11 <= out_len:
|
||||
if string.strncmp(out_buf + p, "type opaque", 11) == 0:
|
||||
# 找到 opaque 声明,将行首改为 ';'
|
||||
out_buf[pos] = ';'
|
||||
return 1
|
||||
pos += 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# _is_submodule_of_imported - 检查模块名是否是已导入包的子模块
|
||||
#
|
||||
# deps.txt 只记录直接导入的模块名(如 "ast"),但包的 __init__.vp
|
||||
# 内部 from .lexer import Lexer 会让 IR 引用 ast.lexer 子模块类型。
|
||||
# 当模块名包含 '.' 时,检查其顶层包名是否在 deps_buf 中。
|
||||
#
|
||||
# 例如:
|
||||
# deps_buf = "ast stdio string"
|
||||
# mod_name = "ast.lexer" → 顶层包 "ast" 在 deps_buf 中 → 返回 1
|
||||
# mod_name = "ast.token" → 顶层包 "ast" 在 deps_buf 中 → 返回 1
|
||||
# mod_name = "foo.bar" → 顶层包 "foo" 不在 deps_buf 中 → 返回 0
|
||||
# ============================================================
|
||||
def _is_submodule_of_imported(deps_buf: str, mod_name: str) -> int:
|
||||
"""检查 mod_name 是否是 deps_buf 中已导入包的子模块"""
|
||||
if deps_buf is None or mod_name is None:
|
||||
return 0
|
||||
# 查找第一个 '.',提取顶层包名
|
||||
dot_pos: str = string.strchr(mod_name, 46) # '.' = 46
|
||||
if dot_pos is None:
|
||||
return 0
|
||||
pkg_len: t.CSizeT = t.CSizeT(t.CUInt64T(dot_pos) - t.CUInt64T(mod_name))
|
||||
if pkg_len == 0 or pkg_len >= 256:
|
||||
return 0
|
||||
# 构造顶层包名(截断到 '.' 之前)
|
||||
# 直接在 mod_name 上临时截断检查,避免分配
|
||||
saved_ch: t.CChar = mod_name[pkg_len]
|
||||
mod_name[pkg_len] = '\0'
|
||||
result: int = GenApi.is_module_imported(deps_buf, mod_name)
|
||||
mod_name[pkg_len] = saved_ch
|
||||
return result
|
||||
# ============================================================
|
||||
# _HasFullTypeDefinition - 检查 out_buf 中是否已有完整类型定义(非 opaque)
|
||||
#
|
||||
# type_name_prefix 格式: '%"sha1.ClassName"'(不含 '=')
|
||||
# 完整定义: %"name" = type { ... } 或 %"name" = type < { ... } >
|
||||
# 返回 1=已有完整定义, 0=无完整定义
|
||||
# ============================================================
|
||||
def _HasFullTypeDefinition(out_buf: bytes, type_name_prefix: str) -> int:
|
||||
"""检查 out_buf 中是否已有 type_name_prefix 的完整定义"""
|
||||
if out_buf is None or type_name_prefix is None:
|
||||
return 0
|
||||
prefix_len: t.CSizeT = string.strlen(type_name_prefix)
|
||||
out_len: t.CSizeT = string.strlen(out_buf)
|
||||
if prefix_len == 0 or out_len == 0 or prefix_len > out_len:
|
||||
return 0
|
||||
pos: t.CSizeT = 0
|
||||
while pos + prefix_len <= out_len:
|
||||
if string.strncmp(out_buf + pos, type_name_prefix, prefix_len) == 0:
|
||||
# 确认是行首(前一个是换行或 pos==0),且未被注释(行首不是 ';')
|
||||
is_line_start: int = 0
|
||||
if pos == 0:
|
||||
is_line_start = 1
|
||||
elif out_buf[pos - 1] == '\n':
|
||||
is_line_start = 1
|
||||
if is_line_start == 1:
|
||||
# 检查后面是否是 " = type {" 或 " = type <"
|
||||
p: t.CSizeT = pos + prefix_len
|
||||
while p < out_len and out_buf[p] == ' ':
|
||||
p += 1
|
||||
if p < out_len and out_buf[p] == '=':
|
||||
p += 1
|
||||
while p < out_len and out_buf[p] == ' ':
|
||||
p += 1
|
||||
if p + 5 < out_len:
|
||||
if string.strncmp(out_buf + p, "type ", 5) == 0:
|
||||
p += 5
|
||||
if p < out_len:
|
||||
if out_buf[p] == '{' or out_buf[p] == '<':
|
||||
return 1
|
||||
pos += 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# _BuildIncludesSha1Map - 从全局内存存储器构建 sha1 → module_name 映射
|
||||
#
|
||||
# 数据来源是 PopulateSha1MapStore 填充的全局存储器(不读取 _sha1_map.txt)。
|
||||
# 返回两个数组(sha1_list 和 mod_list),长度存储在 count 中。
|
||||
# 所有内存由 stdlib.malloc 分配,调用者负责释放。
|
||||
# ============================================================
|
||||
def _BuildIncludesSha1Map(temp_dir: str, td_len: t.CSizeT,
|
||||
sha1_list: str,
|
||||
mod_list: str) -> int:
|
||||
"""从全局内存存储器复制 sha1→module_name 映射到调用者数组
|
||||
|
||||
temp_dir/td_len 参数保留以兼容现有调用者,但不再使用。
|
||||
数据来源是 PopulateSha1MapStore 填充的全局存储器。
|
||||
"""
|
||||
if sha1_list is None or mod_list is None:
|
||||
return 0
|
||||
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None:
|
||||
return 0
|
||||
count: int = 0
|
||||
for i in range(StubMerger._sha1_store_count):
|
||||
if count >= MAX_INCLUDES:
|
||||
break
|
||||
idx: t.CSizeT = t.CSizeT(i) * 17
|
||||
idx2: t.CSizeT = t.CSizeT(i) * 64
|
||||
string.strcpy(sha1_list + t.CSizeT(count) * 17, StubMerger._sha1_store_arr + idx)
|
||||
string.strcpy(mod_list + t.CSizeT(count) * 64, StubMerger._sha1_store_mod + idx2)
|
||||
count += 1
|
||||
return count
|
||||
# ============================================================
|
||||
# _FindSha1ByModName - 从模块名查找 SHA1(精确匹配)
|
||||
#
|
||||
# 在 sha1_arr/mod_arr 映射中查找模块名对应的 SHA1。
|
||||
# 用于依赖图分析:模块名 → SHA1。
|
||||
#
|
||||
# Args:
|
||||
# sha1_arr: SHA1 数组(每个 17 字节)
|
||||
# mod_arr: 模块名数组(每个 64 字节)
|
||||
# count: 映射条目数
|
||||
# mod_name: 要查找的模块名
|
||||
#
|
||||
# Returns:
|
||||
# SHA1 字符串指针(指向 sha1_arr 内部,无需释放),未找到返回 None
|
||||
# ============================================================
|
||||
def _FindSha1ByModName(sha1_arr: str, mod_arr: str,
|
||||
count: int, mod_name: str) -> str:
|
||||
"""从模块名查找 SHA1(精确匹配 + 包名回退)
|
||||
|
||||
精确匹配失败时,尝试 "{mod_name}.__init__" 回退,
|
||||
支持 import ast(包)→ ast.__init__ 的 SHA1 查找。
|
||||
"""
|
||||
if sha1_arr is None or mod_arr is None or mod_name is None:
|
||||
return None
|
||||
if count <= 0:
|
||||
return None
|
||||
# 第一遍:精确匹配
|
||||
for i in range(count):
|
||||
idx: t.CSizeT = t.CSizeT(i) * 64
|
||||
if string.strcmp(mod_arr + idx, mod_name) == 0:
|
||||
sidx: t.CSizeT = t.CSizeT(i) * 17
|
||||
return sha1_arr + sidx
|
||||
# 第二遍:包名回退("ast" → "ast.__init__")
|
||||
nm_len: t.CSizeT = string.strlen(mod_name)
|
||||
init_buf: bytes = stdlib.malloc(nm_len + 12)
|
||||
if init_buf is not None:
|
||||
viperlib.snprintf(init_buf, nm_len + 12, "%s.__init__", mod_name)
|
||||
for i in range(count):
|
||||
idx2: t.CSizeT = t.CSizeT(i) * 64
|
||||
if string.strcmp(mod_arr + idx2, init_buf) == 0:
|
||||
sidx2: t.CSizeT = t.CSizeT(i) * 17
|
||||
stdlib.free(init_buf)
|
||||
return sha1_arr + sidx2
|
||||
stdlib.free(init_buf)
|
||||
return None
|
||||
# ============================================================
|
||||
# _AddSha1ToSet - 将 SHA1 加入集合(去重)
|
||||
#
|
||||
# 检查 SHA1 是否已在集合中,若不在则加入。返回新的 count。
|
||||
#
|
||||
# Args:
|
||||
# set_buf: SHA1 集合缓冲区(每个 17 字节)
|
||||
# count: 当前集合中的 SHA1 数量
|
||||
# sha1: 要加入的 SHA1
|
||||
#
|
||||
# Returns:
|
||||
# 新的 count(如果已存在则不变)
|
||||
# ============================================================
|
||||
def _AddSha1ToSet(set_buf: str, count: int, sha1: str) -> int:
|
||||
"""将 SHA1 加入集合,返回新 count"""
|
||||
if set_buf is None or sha1 is None:
|
||||
return count
|
||||
for i in range(count):
|
||||
idx: t.CSizeT = t.CSizeT(i) * 17
|
||||
if string.strcmp(set_buf + idx, sha1) == 0:
|
||||
return count
|
||||
if count < MAX_INCLUDES_SHA1:
|
||||
idx: t.CSizeT = t.CSizeT(count) * 17
|
||||
string.strcpy(set_buf + idx, sha1)
|
||||
return count + 1
|
||||
return count
|
||||
+407
-409
@@ -1,409 +1,407 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import llvmlite
|
||||
import w32.win32file as win32file
|
||||
import w32.win32base as win32base
|
||||
import w32.fileio as fileio
|
||||
import viperlib
|
||||
import sys
|
||||
import ast
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import lib.core.BuildPipeline as BuildPipeline
|
||||
import lib.StubGen.VpiReader as VpiReader
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import lib.Projectrans.Config as Config
|
||||
|
||||
|
||||
import lib.core.StubMergerCollect as StubMergerCollect
|
||||
import lib.core.StubMergerTopo as StubMergerTopo
|
||||
import lib.core.StubMergerIR as StubMergerIR
|
||||
import lib.core.StubMergerBuild as StubMergerBuild
|
||||
import lib.core.StubMerger as StubMerger
|
||||
|
||||
# ============================================================
|
||||
# StubMergerStore - StubMerger 拆分(阶段 E):StubMergerStore
|
||||
#
|
||||
# 直接移动模式:函数实现迁至此模块,原 StubMerger.vp 仅保留
|
||||
# 常量/全局变量;调用方经本模块前缀访问。全局变量跨模块经
|
||||
# StubMerger._xxx 访问(main.vp 先例)。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# PopulateSha1MapStore - 从扫描结果填充全局 SHA1 映射存储器
|
||||
#
|
||||
# 遍历 ScanResult.Entries,为每个条目构建 sha1→module_name 映射。
|
||||
# 模块名通过 _PathToModuleName(includes/rel_path) 计算。
|
||||
# 内存用 stdlib.malloc 分配(全局存储器,不随 mbuddy 释放)。
|
||||
#
|
||||
# Args:
|
||||
# scan_result: IncludesScanner 扫描结果
|
||||
#
|
||||
# Returns:
|
||||
# 填充的条目数,-1 表示失败
|
||||
# ============================================================
|
||||
def PopulateSha1MapStore(scan_result: IncludesScanner.ScanResult | t.CPtr) -> int:
|
||||
"""从扫描结果填充全局 SHA1 映射存储器
|
||||
|
||||
遍历 ScanResult.Entries,为每个条目构建 sha1→module_name 映射。
|
||||
模块名通过 _PathToModuleName(includes/rel_path) 计算。
|
||||
内存用 stdlib.malloc 分配(全局存储器,不随 mbuddy 释放)。
|
||||
"""
|
||||
if scan_result is None:
|
||||
return -1
|
||||
# 释放旧存储器
|
||||
if StubMerger._sha1_store_arr is not None:
|
||||
stdlib.free(StubMerger._sha1_store_arr)
|
||||
if StubMerger._sha1_store_mod is not None:
|
||||
stdlib.free(StubMerger._sha1_store_mod)
|
||||
if StubMerger._sha1_store_rel is not None:
|
||||
stdlib.free(StubMerger._sha1_store_rel)
|
||||
if StubMerger._sha1_store_incdir is not None:
|
||||
stdlib.free(StubMerger._sha1_store_incdir)
|
||||
StubMerger._sha1_store_arr = stdlib.malloc(MAX_INCLUDES * 17)
|
||||
StubMerger._sha1_store_mod = stdlib.malloc(MAX_INCLUDES * 64)
|
||||
StubMerger._sha1_store_rel = stdlib.malloc(MAX_INCLUDES * MAX_REL_PATH_LEN)
|
||||
StubMerger._sha1_store_incdir = stdlib.malloc(MAX_INCLUDES * MAX_INC_DIR_LEN)
|
||||
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None:
|
||||
return -1
|
||||
string.memset(StubMerger._sha1_store_arr, 0, MAX_INCLUDES * 17)
|
||||
string.memset(StubMerger._sha1_store_mod, 0, MAX_INCLUDES * 64)
|
||||
string.memset(StubMerger._sha1_store_rel, 0, MAX_INCLUDES * MAX_REL_PATH_LEN)
|
||||
string.memset(StubMerger._sha1_store_incdir, 0, MAX_INCLUDES * MAX_INC_DIR_LEN)
|
||||
StubMerger._sha1_store_count = 0
|
||||
p_bad: int = 0
|
||||
entry_size_p: t.CSizeT = IncludesScanner.FileEntry.__sizeof__()
|
||||
for i in range(scan_result.Count):
|
||||
if StubMerger._sha1_store_count >= MAX_INCLUDES:
|
||||
VLogger.error("includes SHA1 存储超上限,终止", "StubMerger")
|
||||
ea: t.CUInt64T = t.CUInt64T(scan_result.Entries) + i * entry_size_p
|
||||
ent: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea, t.CPtr))
|
||||
if ent is None or ent.Sha1 is None or ent.RelPath is None:
|
||||
p_bad += 1
|
||||
continue
|
||||
# 构建完整路径 includes/{RelPath}(_PathToModuleName 需要)
|
||||
rp_len: t.CSizeT = string.strlen(ent.RelPath)
|
||||
full_path_buf: bytes = stdlib.malloc(rp_len + 10)
|
||||
if full_path_buf is None:
|
||||
p_bad += 1
|
||||
continue
|
||||
viperlib.snprintf(full_path_buf, rp_len + 10, "includes/%s", ent.RelPath)
|
||||
mod_name: str = Utils.PathToModuleName(full_path_buf, 1)
|
||||
stdlib.free(full_path_buf)
|
||||
if mod_name is not None:
|
||||
idx: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * 17
|
||||
string.strcpy(StubMerger._sha1_store_arr + idx, ent.Sha1)
|
||||
idx2: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * 64
|
||||
mn_len: t.CSizeT = string.strlen(mod_name)
|
||||
if mn_len < 64:
|
||||
string.strcpy(StubMerger._sha1_store_mod + idx2, mod_name)
|
||||
else:
|
||||
string.strncpy(StubMerger._sha1_store_mod + idx2, mod_name, 63)
|
||||
StubMerger._sha1_store_mod[idx2 + 63] = '\0'
|
||||
stdlib.free(mod_name)
|
||||
# 保存 rel_path(供 Phase2 3.5 编译缺失 includes 使用)
|
||||
idx3: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_REL_PATH_LEN
|
||||
if rp_len < MAX_REL_PATH_LEN:
|
||||
string.strcpy(StubMerger._sha1_store_rel + idx3, ent.RelPath)
|
||||
else:
|
||||
string.strncpy(StubMerger._sha1_store_rel + idx3, ent.RelPath, MAX_REL_PATH_LEN - 1)
|
||||
StubMerger._sha1_store_rel[idx3 + MAX_REL_PATH_LEN - 1] = '\0'
|
||||
# 保存所属 includes 根目录(Phase2 预注册/按需编译拼路径用)
|
||||
idx_inc: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_INC_DIR_LEN
|
||||
if ent.IncDir is not None:
|
||||
icd_len: t.CSizeT = string.strlen(ent.IncDir)
|
||||
if icd_len < MAX_INC_DIR_LEN:
|
||||
string.strcpy(StubMerger._sha1_store_incdir + idx_inc, ent.IncDir)
|
||||
else:
|
||||
string.strncpy(StubMerger._sha1_store_incdir + idx_inc, ent.IncDir, MAX_INC_DIR_LEN - 1)
|
||||
StubMerger._sha1_store_incdir[idx_inc + MAX_INC_DIR_LEN - 1] = '\0'
|
||||
StubMerger._sha1_store_count += 1
|
||||
if p_bad > 0:
|
||||
fb_pbad: str = VLogger.fmt_buf()
|
||||
if fb_pbad is not None:
|
||||
viperlib.snprintf(fb_pbad, 1024, "includes SHA1 存储有 %d 个条目失败", p_bad)
|
||||
VLogger.error(fb_pbad, "StubMerger")
|
||||
return StubMerger._sha1_store_count
|
||||
# ============================================================
|
||||
# AppendToSha1MapStore - 追加条目到全局 SHA1 映射存储器
|
||||
#
|
||||
# Phase1 调用 PopulateSha1MapStore 填充 includes 文件,
|
||||
# Phase2 扫描 App 源文件后调用此函数追加 App 模块条目,
|
||||
# 确保编译 App 自身时跨模块 CDefine 查找能命中 App 模块
|
||||
# (如 StubMerger.MAX_INCLUDES 在编译 Phase2 时通过
|
||||
# _build_source_path_from_sha1 查找 StubMerger 的源路径)。
|
||||
#
|
||||
# 若存储器未初始化(PopulateSha1MapStore 未调用),自动初始化。
|
||||
# 若 SHA1 已存在(去重),跳过。
|
||||
#
|
||||
# Args:
|
||||
# sha1: SHA1 字符串(16 字符 + null)
|
||||
# rel_path: 相对路径(如 "lib/core/StubMerger.vp",
|
||||
# 不含 includes/ 前缀,与 _sha1_map.txt 格式一致)
|
||||
#
|
||||
# Returns:
|
||||
# 0 成功(含去重跳过),1 失败
|
||||
# ============================================================
|
||||
def AppendToSha1MapStore(sha1: str, rel_path: str) -> int:
|
||||
"""追加条目到全局 SHA1 映射存储器(Phase2 用)"""
|
||||
if sha1 is None or rel_path is None:
|
||||
return 1
|
||||
# 存储器未初始化:自动初始化(Phase2 可能先于 Phase1 调用)
|
||||
if StubMerger._sha1_store_arr is None:
|
||||
StubMerger._sha1_store_arr = stdlib.malloc(MAX_INCLUDES * 17)
|
||||
StubMerger._sha1_store_mod = stdlib.malloc(MAX_INCLUDES * 64)
|
||||
StubMerger._sha1_store_rel = stdlib.malloc(MAX_INCLUDES * MAX_REL_PATH_LEN)
|
||||
StubMerger._sha1_store_incdir = stdlib.malloc(MAX_INCLUDES * MAX_INC_DIR_LEN)
|
||||
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None:
|
||||
return 1
|
||||
string.memset(StubMerger._sha1_store_arr, 0, MAX_INCLUDES * 17)
|
||||
string.memset(StubMerger._sha1_store_mod, 0, MAX_INCLUDES * 64)
|
||||
string.memset(StubMerger._sha1_store_rel, 0, MAX_INCLUDES * MAX_REL_PATH_LEN)
|
||||
string.memset(StubMerger._sha1_store_incdir, 0, MAX_INCLUDES * MAX_INC_DIR_LEN)
|
||||
StubMerger._sha1_store_count = 0
|
||||
if StubMerger._sha1_store_count >= MAX_INCLUDES:
|
||||
return 1
|
||||
# 去重:若 SHA1 已存在则跳过
|
||||
for i in range(StubMerger._sha1_store_count):
|
||||
sidx_d: t.CSizeT = t.CSizeT(i) * 17
|
||||
if string.strcmp(StubMerger._sha1_store_arr + sidx_d, sha1) == 0:
|
||||
return 0
|
||||
# 模块名:rel_path "lib/core/StubMerger.vp" → "lib.core.StubMerger"
|
||||
full_path_buf: bytes = stdlib.malloc(string.strlen(rel_path) + 10)
|
||||
if full_path_buf is None:
|
||||
return 1
|
||||
viperlib.snprintf(full_path_buf, string.strlen(rel_path) + 10, "includes/%s", rel_path)
|
||||
mod_name: str = Utils.PathToModuleName(full_path_buf, 1)
|
||||
stdlib.free(full_path_buf)
|
||||
if mod_name is None:
|
||||
return 1
|
||||
# 写入 SHA1
|
||||
idx_a: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * 17
|
||||
string.strcpy(StubMerger._sha1_store_arr + idx_a, sha1)
|
||||
# 写入模块名
|
||||
idx_m: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * 64
|
||||
mn_len: t.CSizeT = string.strlen(mod_name)
|
||||
if mn_len < 64:
|
||||
string.strcpy(StubMerger._sha1_store_mod + idx_m, mod_name)
|
||||
else:
|
||||
string.strncpy(StubMerger._sha1_store_mod + idx_m, mod_name, 63)
|
||||
StubMerger._sha1_store_mod[idx_m + 63] = '\0'
|
||||
stdlib.free(mod_name)
|
||||
# 写入相对路径
|
||||
idx_r: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_REL_PATH_LEN
|
||||
rp_len: t.CSizeT = string.strlen(rel_path)
|
||||
if rp_len < MAX_REL_PATH_LEN:
|
||||
string.strcpy(StubMerger._sha1_store_rel + idx_r, rel_path)
|
||||
else:
|
||||
string.strncpy(StubMerger._sha1_store_rel + idx_r, rel_path, MAX_REL_PATH_LEN - 1)
|
||||
StubMerger._sha1_store_rel[idx_r + MAX_REL_PATH_LEN - 1] = '\0'
|
||||
# App 源文件不属于任何 includes 目录:IncDir 留空(Phase2 回退 includes_dir 参数)
|
||||
idx_inc_a: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_INC_DIR_LEN
|
||||
StubMerger._sha1_store_incdir[idx_inc_a] = '\0'
|
||||
StubMerger._sha1_store_count += 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# GetSha1StoreCount - 获取全局存储器条目数
|
||||
# ============================================================
|
||||
def GetSha1StoreCount() -> int:
|
||||
"""返回全局 SHA1 存储器的条目数"""
|
||||
return StubMerger._sha1_store_count
|
||||
# ============================================================
|
||||
# LookupSha1ByModName - 从模块名查找 SHA1(直接查全局存储器)
|
||||
#
|
||||
# 精确匹配失败时,尝试 "{mod_name}.__init__" 回退,
|
||||
# 支持 import ast(包)→ ast.__init__ 的 SHA1 查找。
|
||||
#
|
||||
# Returns:
|
||||
# SHA1 字符串指针(指向全局存储器内部,无需释放),None 未找到
|
||||
# ============================================================
|
||||
def LookupSha1ByModName(mod_name: str) -> str:
|
||||
"""从模块名查找 SHA1(精确匹配 + 包名回退),委托通用实现 _FindSha1ByModName"""
|
||||
return StubMergerIR._FindSha1ByModName(StubMerger._sha1_store_arr, StubMerger._sha1_store_mod, StubMerger._sha1_store_count, mod_name)
|
||||
# ============================================================
|
||||
# LookupSha1ByModNameSuffix - 后缀匹配查找模块 SHA1
|
||||
#
|
||||
# 用于 from .X import Y 的相对导入:impf.module 是 ".X"(带前导点),
|
||||
# 去掉前导点后为 "X",SHA1 映射表中键是 "pkg.X",需要后缀匹配。
|
||||
# 包含三种匹配方式:精确、后缀、反向后缀。
|
||||
#
|
||||
# Returns:
|
||||
# SHA1 字符串指针(指向全局存储器内部,无需释放),None 未找到
|
||||
# ============================================================
|
||||
def LookupSha1ByModNameSuffix(mod_suffix: str) -> str:
|
||||
"""后缀匹配查找模块 SHA1"""
|
||||
if mod_suffix is None:
|
||||
return None
|
||||
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None:
|
||||
return None
|
||||
if StubMerger._sha1_store_count <= 0:
|
||||
return None
|
||||
suffix_len_sf: t.CSizeT = string.strlen(mod_suffix)
|
||||
if suffix_len_sf == 0:
|
||||
return None
|
||||
i_sf: int
|
||||
for i_sf in range(StubMerger._sha1_store_count):
|
||||
idx_sf: t.CSizeT = t.CSizeT(i_sf) * 64
|
||||
mod_name_sf: str = StubMerger._sha1_store_mod + idx_sf
|
||||
mod_len_sf: t.CSizeT = string.strlen(mod_name_sf)
|
||||
if mod_len_sf == 0:
|
||||
continue
|
||||
# 精确匹配
|
||||
if mod_len_sf == suffix_len_sf:
|
||||
if string.strcmp(mod_name_sf, mod_suffix) == 0:
|
||||
sidx_sf: t.CSizeT = t.CSizeT(i_sf) * 17
|
||||
return StubMerger._sha1_store_arr + sidx_sf
|
||||
# 后缀匹配:mod_name 以 "." + mod_suffix 结尾
|
||||
if mod_len_sf > suffix_len_sf:
|
||||
if mod_name_sf[mod_len_sf - suffix_len_sf - 1] == '.':
|
||||
cmp_start_sf: str = mod_name_sf + mod_len_sf - suffix_len_sf
|
||||
if string.strcmp(cmp_start_sf, mod_suffix) == 0:
|
||||
sidx2_sf: t.CSizeT = t.CSizeT(i_sf) * 17
|
||||
return StubMerger._sha1_store_arr + sidx2_sf
|
||||
# 反向后缀匹配:mod_suffix 以 "." + mod_name 结尾
|
||||
if suffix_len_sf > mod_len_sf:
|
||||
if mod_suffix[suffix_len_sf - mod_len_sf - 1] == '.':
|
||||
cmp_start_rev_sf: str = mod_suffix + suffix_len_sf - mod_len_sf
|
||||
if string.strcmp(cmp_start_rev_sf, mod_name_sf) == 0:
|
||||
sidx_rev_sf: t.CSizeT = t.CSizeT(i_sf) * 17
|
||||
return StubMerger._sha1_store_arr + sidx_rev_sf
|
||||
return None
|
||||
# ============================================================
|
||||
# PopulateIncludesDeps - 将 includes 文件的依赖存入内存
|
||||
#
|
||||
# Phase B+ 前用 declare_only 翻译 includes 文件,提取 _imported_modules
|
||||
# 后调用此函数存入内存。_BuildReachableSha1Set 从内存读取,不读 deps.txt。
|
||||
#
|
||||
# Args:
|
||||
# sha1: includes 文件的 SHA1(16字符)
|
||||
# deps_str: 依赖模块名字符串(空格分隔,如 "t c stdint string")
|
||||
#
|
||||
# Returns:
|
||||
# 0 成功,非 0 失败
|
||||
# ============================================================
|
||||
def PopulateIncludesDeps(sha1: str, deps_str: str) -> int:
|
||||
"""将 includes 文件的依赖存入内存"""
|
||||
if sha1 is None:
|
||||
return 1
|
||||
# 延迟初始化
|
||||
if StubMerger._includes_deps_sha1 is None:
|
||||
StubMerger._includes_deps_sha1 = stdlib.malloc(MAX_INCLUDES * 17)
|
||||
StubMerger._includes_deps_str = stdlib.malloc(MAX_INCLUDES * MAX_DEPS_STR_LEN)
|
||||
if StubMerger._includes_deps_sha1 is None or StubMerger._includes_deps_str is None:
|
||||
return 1
|
||||
string.memset(StubMerger._includes_deps_sha1, 0, MAX_INCLUDES * 17)
|
||||
string.memset(StubMerger._includes_deps_str, 0, MAX_INCLUDES * MAX_DEPS_STR_LEN)
|
||||
StubMerger._includes_deps_count = 0
|
||||
if StubMerger._includes_deps_count >= MAX_INCLUDES:
|
||||
return 1
|
||||
# 去重:若 SHA1 已存在则跳过
|
||||
for i in range(StubMerger._includes_deps_count):
|
||||
sidx: t.CSizeT = t.CSizeT(i) * 17
|
||||
if string.strcmp(StubMerger._includes_deps_sha1 + sidx, sha1) == 0:
|
||||
return 0
|
||||
# 写入 SHA1
|
||||
idx: t.CSizeT = t.CSizeT(StubMerger._includes_deps_count) * 17
|
||||
string.strcpy(StubMerger._includes_deps_sha1 + idx, sha1)
|
||||
# 写入依赖字符串
|
||||
idx2: t.CSizeT = t.CSizeT(StubMerger._includes_deps_count) * MAX_DEPS_STR_LEN
|
||||
if deps_str is not None:
|
||||
dl: t.CSizeT = string.strlen(deps_str)
|
||||
if dl < MAX_DEPS_STR_LEN:
|
||||
string.strcpy(StubMerger._includes_deps_str + idx2, deps_str)
|
||||
else:
|
||||
string.strncpy(StubMerger._includes_deps_str + idx2, deps_str, MAX_DEPS_STR_LEN - 1)
|
||||
else:
|
||||
StubMerger._includes_deps_str[idx2] = '\0'
|
||||
StubMerger._includes_deps_count = StubMerger._includes_deps_count + 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# LookupIncludesDeps - 从内存查找 includes 文件的依赖
|
||||
#
|
||||
# Args:
|
||||
# sha1: includes 文件的 SHA1(16字符)
|
||||
#
|
||||
# Returns:
|
||||
# 依赖模块名字符串指针(空格分隔),None 表示未找到
|
||||
# ============================================================
|
||||
def LookupIncludesDeps(sha1: str) -> str:
|
||||
"""从内存查找 includes 文件的依赖"""
|
||||
if sha1 is None or StubMerger._includes_deps_sha1 is None:
|
||||
return None
|
||||
if StubMerger._includes_deps_count <= 0:
|
||||
return None
|
||||
for i in range(StubMerger._includes_deps_count):
|
||||
sidx: t.CSizeT = t.CSizeT(i) * 17
|
||||
if string.strcmp(StubMerger._includes_deps_sha1 + sidx, sha1) == 0:
|
||||
idx2: t.CSizeT = t.CSizeT(i) * MAX_DEPS_STR_LEN
|
||||
return StubMerger._includes_deps_str + idx2
|
||||
return None
|
||||
def GetSha1StoreArrPtr() -> bytes | t.CPtr:
|
||||
"""返回 SHA1 数组指针(每个条目 17 字节)"""
|
||||
return StubMerger._sha1_store_arr
|
||||
def GetSha1StoreModArrPtr() -> bytes | t.CPtr:
|
||||
"""返回模块名数组指针(每个条目 64 字节)"""
|
||||
return StubMerger._sha1_store_mod
|
||||
def GetSha1StoreRelArrPtr() -> bytes | t.CPtr:
|
||||
"""返回相对路径数组指针(每个条目 MAX_REL_PATH_LEN 字节)"""
|
||||
return StubMerger._sha1_store_rel
|
||||
def GetSha1StoreIncdirArrPtr() -> bytes | t.CPtr:
|
||||
"""返回所属 includes 根目录数组指针(每个条目 MAX_INC_DIR_LEN 字节,空串表示不属于任何 includes 目录)"""
|
||||
return StubMerger._sha1_store_incdir
|
||||
# ============================================================
|
||||
# GetSha1StoreArr - 获取全局存储器数组指针(直接遍历用)
|
||||
#
|
||||
# 返回 sha1_arr、mod_arr、rel_arr 三个数组的指针和条目数。
|
||||
# 调用者直接遍历数组:sha1_arr[i*17]、mod_arr[i*64]、rel_arr[i*MAX_REL_PATH_LEN]
|
||||
# 内存归全局存储器所有,调用者不要 free
|
||||
# ============================================================
|
||||
def GetSha1StoreArr(out_sha1_arr: t.CPtr, out_mod_arr: t.CPtr, out_rel_arr: t.CPtr) -> int:
|
||||
"""获取全局存储器数组指针
|
||||
|
||||
out_sha1_arr/out_mod_arr/out_rel_arr 是调用者提供的 t.CPtr 指针,
|
||||
函数将存储器数组指针写入这些位置。
|
||||
返回条目数,-1 失败
|
||||
"""
|
||||
if out_sha1_arr is None or out_mod_arr is None or out_rel_arr is None:
|
||||
return -1
|
||||
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None:
|
||||
return -1
|
||||
sp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_sha1_arr, t.CPtr))
|
||||
if sp is not None:
|
||||
sp[0] = StubMerger._sha1_store_arr
|
||||
mp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_mod_arr, t.CPtr))
|
||||
if mp is not None:
|
||||
mp[0] = StubMerger._sha1_store_mod
|
||||
rp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_rel_arr, t.CPtr))
|
||||
if rp is not None:
|
||||
rp[0] = StubMerger._sha1_store_rel
|
||||
return StubMerger._sha1_store_count
|
||||
# ============================================================
|
||||
# LookupSha1RelPath - 通过 SHA1 查找相对路径
|
||||
#
|
||||
# 遍历全局存储器,返回 sha1 对应的相对路径指针(只读,不要 free)。
|
||||
# 用于错误提示:将 sha1 转换为人类可读的文件路径。
|
||||
#
|
||||
# Args:
|
||||
# sha1: SHA1 字符串(16 字符)
|
||||
#
|
||||
# Returns:
|
||||
# 相对路径字符串指针(只读),None=未找到
|
||||
# ============================================================
|
||||
def LookupSha1RelPath(sha1: str) -> str:
|
||||
"""通过 SHA1 查找相对路径,返回只读指针,None=未找到"""
|
||||
if sha1 is None:
|
||||
return None
|
||||
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_rel is None:
|
||||
return None
|
||||
for i in range(StubMerger._sha1_store_count):
|
||||
sidx: t.CSizeT = t.CSizeT(i) * 17
|
||||
if string.strcmp(StubMerger._sha1_store_arr + sidx, sha1) == 0:
|
||||
ridx: t.CSizeT = t.CSizeT(i) * MAX_REL_PATH_LEN
|
||||
return StubMerger._sha1_store_rel + ridx
|
||||
return None
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import llvmlite
|
||||
import w32.win32file as win32file
|
||||
import w32.win32base as win32base
|
||||
import w32.fileio as fileio
|
||||
import viperlib
|
||||
import sys
|
||||
import ast
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import lib.core.BuildPipeline as BuildPipeline
|
||||
import lib.StubGen.VpiReader as VpiReader
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import lib.Projectrans.Config as Config
|
||||
|
||||
|
||||
import lib.core.StubMergerCollect as StubMergerCollect
|
||||
import lib.core.StubMergerTopo as StubMergerTopo
|
||||
import lib.core.StubMergerIR as StubMergerIR
|
||||
import lib.core.StubMergerBuild as StubMergerBuild
|
||||
import lib.core.StubMerger as StubMerger
|
||||
|
||||
# ============================================================
|
||||
# StubMergerStore - StubMerger 拆分(阶段 E):StubMergerStore
|
||||
#
|
||||
# 直接移动模式:函数实现迁至此模块,原 StubMerger.vp 仅保留
|
||||
# 常量/全局变量;调用方经本模块前缀访问。全局变量跨模块经
|
||||
# StubMerger._xxx 访问(main.vp 先例)。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# PopulateSha1MapStore - 从扫描结果填充全局 SHA1 映射存储器
|
||||
#
|
||||
# 遍历 ScanResult.Entries,为每个条目构建 sha1→module_name 映射。
|
||||
# 模块名通过 _PathToModuleName(includes/rel_path) 计算。
|
||||
# 内存用 stdlib.malloc 分配(全局存储器,不随 mbuddy 释放)。
|
||||
#
|
||||
# Args:
|
||||
# scan_result: IncludesScanner 扫描结果
|
||||
#
|
||||
# Returns:
|
||||
# 填充的条目数,-1 表示失败
|
||||
# ============================================================
|
||||
def PopulateSha1MapStore(scan_result: IncludesScanner.ScanResult | t.CPtr) -> int:
|
||||
"""从扫描结果填充全局 SHA1 映射存储器
|
||||
|
||||
遍历 ScanResult.Entries,为每个条目构建 sha1→module_name 映射。
|
||||
模块名通过 _PathToModuleName(includes/rel_path) 计算。
|
||||
内存用 stdlib.malloc 分配(全局存储器,不随 mbuddy 释放)。
|
||||
"""
|
||||
if scan_result is None:
|
||||
return -1
|
||||
# 释放旧存储器
|
||||
if StubMerger._sha1_store_arr is not None:
|
||||
stdlib.free(StubMerger._sha1_store_arr)
|
||||
if StubMerger._sha1_store_mod is not None:
|
||||
stdlib.free(StubMerger._sha1_store_mod)
|
||||
if StubMerger._sha1_store_rel is not None:
|
||||
stdlib.free(StubMerger._sha1_store_rel)
|
||||
if StubMerger._sha1_store_incdir is not None:
|
||||
stdlib.free(StubMerger._sha1_store_incdir)
|
||||
StubMerger._sha1_store_arr = stdlib.malloc(MAX_INCLUDES * 17)
|
||||
StubMerger._sha1_store_mod = stdlib.malloc(MAX_INCLUDES * 64)
|
||||
StubMerger._sha1_store_rel = stdlib.malloc(MAX_INCLUDES * MAX_REL_PATH_LEN)
|
||||
StubMerger._sha1_store_incdir = stdlib.malloc(MAX_INCLUDES * MAX_INC_DIR_LEN)
|
||||
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None:
|
||||
return -1
|
||||
string.memset(StubMerger._sha1_store_arr, 0, MAX_INCLUDES * 17)
|
||||
string.memset(StubMerger._sha1_store_mod, 0, MAX_INCLUDES * 64)
|
||||
string.memset(StubMerger._sha1_store_rel, 0, MAX_INCLUDES * MAX_REL_PATH_LEN)
|
||||
string.memset(StubMerger._sha1_store_incdir, 0, MAX_INCLUDES * MAX_INC_DIR_LEN)
|
||||
StubMerger._sha1_store_count = 0
|
||||
p_bad: int = 0
|
||||
entry_size_p: t.CSizeT = IncludesScanner.FileEntry.__sizeof__()
|
||||
for i in range(scan_result.Count):
|
||||
if StubMerger._sha1_store_count >= MAX_INCLUDES:
|
||||
VLogger.error("includes SHA1 存储超上限,终止", "StubMerger")
|
||||
ea: t.CUInt64T = t.CUInt64T(scan_result.Entries) + i * entry_size_p
|
||||
ent: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea, t.CPtr))
|
||||
if ent is None or ent.Sha1 is None or ent.RelPath is None:
|
||||
p_bad += 1
|
||||
continue
|
||||
# 构建完整路径 includes/{RelPath}(_PathToModuleName 需要)
|
||||
rp_len: t.CSizeT = string.strlen(ent.RelPath)
|
||||
full_path_buf: bytes = stdlib.malloc(rp_len + 10)
|
||||
if full_path_buf is None:
|
||||
p_bad += 1
|
||||
continue
|
||||
viperlib.snprintf(full_path_buf, rp_len + 10, "includes/%s", ent.RelPath)
|
||||
mod_name: str = Utils.PathToModuleName(full_path_buf, 1)
|
||||
stdlib.free(full_path_buf)
|
||||
if mod_name is not None:
|
||||
idx: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * 17
|
||||
string.strcpy(StubMerger._sha1_store_arr + idx, ent.Sha1)
|
||||
idx2: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * 64
|
||||
mn_len: t.CSizeT = string.strlen(mod_name)
|
||||
if mn_len < 64:
|
||||
string.strcpy(StubMerger._sha1_store_mod + idx2, mod_name)
|
||||
else:
|
||||
string.strncpy(StubMerger._sha1_store_mod + idx2, mod_name, 63)
|
||||
StubMerger._sha1_store_mod[idx2 + 63] = '\0'
|
||||
stdlib.free(mod_name)
|
||||
# 保存 rel_path(供 Phase2 3.5 编译缺失 includes 使用)
|
||||
idx3: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_REL_PATH_LEN
|
||||
if rp_len < MAX_REL_PATH_LEN:
|
||||
string.strcpy(StubMerger._sha1_store_rel + idx3, ent.RelPath)
|
||||
else:
|
||||
string.strncpy(StubMerger._sha1_store_rel + idx3, ent.RelPath, MAX_REL_PATH_LEN - 1)
|
||||
StubMerger._sha1_store_rel[idx3 + MAX_REL_PATH_LEN - 1] = '\0'
|
||||
# 保存所属 includes 根目录(Phase2 预注册/按需编译拼路径用)
|
||||
idx_inc: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_INC_DIR_LEN
|
||||
if ent.IncDir is not None:
|
||||
icd_len: t.CSizeT = string.strlen(ent.IncDir)
|
||||
if icd_len < MAX_INC_DIR_LEN:
|
||||
string.strcpy(StubMerger._sha1_store_incdir + idx_inc, ent.IncDir)
|
||||
else:
|
||||
string.strncpy(StubMerger._sha1_store_incdir + idx_inc, ent.IncDir, MAX_INC_DIR_LEN - 1)
|
||||
StubMerger._sha1_store_incdir[idx_inc + MAX_INC_DIR_LEN - 1] = '\0'
|
||||
StubMerger._sha1_store_count += 1
|
||||
if p_bad > 0:
|
||||
fb_pbad: str = VLogger.fmt_buf()
|
||||
if fb_pbad is not None:
|
||||
viperlib.snprintf(fb_pbad, 1024, "includes SHA1 存储有 %d 个条目失败", p_bad)
|
||||
VLogger.error(fb_pbad, "StubMerger")
|
||||
return StubMerger._sha1_store_count
|
||||
# ============================================================
|
||||
# AppendToSha1MapStore - 追加条目到全局 SHA1 映射存储器
|
||||
#
|
||||
# Phase1 调用 PopulateSha1MapStore 填充 includes 文件,
|
||||
# Phase2 扫描 App 源文件后调用此函数追加 App 模块条目,
|
||||
# 确保编译 App 自身时跨模块 CDefine 查找能命中 App 模块
|
||||
# (如 StubMerger.MAX_INCLUDES 在编译 Phase2 时通过
|
||||
# _build_source_path_from_sha1 查找 StubMerger 的源路径)。
|
||||
#
|
||||
# 若存储器未初始化(PopulateSha1MapStore 未调用),自动初始化。
|
||||
# 若 SHA1 已存在(去重),跳过。
|
||||
#
|
||||
# Args:
|
||||
# sha1: SHA1 字符串(16 字符 + null)
|
||||
# rel_path: 相对路径(如 "lib/core/StubMerger.vp",
|
||||
# 不含 includes/ 前缀,与 _sha1_map.txt 格式一致)
|
||||
#
|
||||
# Returns:
|
||||
# 0 成功(含去重跳过),1 失败
|
||||
# ============================================================
|
||||
def AppendToSha1MapStore(sha1: str, rel_path: str) -> int:
|
||||
"""追加条目到全局 SHA1 映射存储器(Phase2 用)"""
|
||||
if sha1 is None or rel_path is None:
|
||||
return 1
|
||||
# 存储器未初始化:自动初始化(Phase2 可能先于 Phase1 调用)
|
||||
if StubMerger._sha1_store_arr is None:
|
||||
StubMerger._sha1_store_arr = stdlib.malloc(MAX_INCLUDES * 17)
|
||||
StubMerger._sha1_store_mod = stdlib.malloc(MAX_INCLUDES * 64)
|
||||
StubMerger._sha1_store_rel = stdlib.malloc(MAX_INCLUDES * MAX_REL_PATH_LEN)
|
||||
StubMerger._sha1_store_incdir = stdlib.malloc(MAX_INCLUDES * MAX_INC_DIR_LEN)
|
||||
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None:
|
||||
return 1
|
||||
string.memset(StubMerger._sha1_store_arr, 0, MAX_INCLUDES * 17)
|
||||
string.memset(StubMerger._sha1_store_mod, 0, MAX_INCLUDES * 64)
|
||||
string.memset(StubMerger._sha1_store_rel, 0, MAX_INCLUDES * MAX_REL_PATH_LEN)
|
||||
string.memset(StubMerger._sha1_store_incdir, 0, MAX_INCLUDES * MAX_INC_DIR_LEN)
|
||||
StubMerger._sha1_store_count = 0
|
||||
if StubMerger._sha1_store_count >= MAX_INCLUDES:
|
||||
return 1
|
||||
# 去重:若 SHA1 已存在则跳过
|
||||
for i in range(StubMerger._sha1_store_count):
|
||||
sidx_d: t.CSizeT = t.CSizeT(i) * 17
|
||||
if string.strcmp(StubMerger._sha1_store_arr + sidx_d, sha1) == 0:
|
||||
return 0
|
||||
# 模块名:rel_path "lib/core/StubMerger.vp" → "lib.core.StubMerger"
|
||||
full_path_buf: bytes = stdlib.malloc(string.strlen(rel_path) + 10)
|
||||
if full_path_buf is None:
|
||||
return 1
|
||||
viperlib.snprintf(full_path_buf, string.strlen(rel_path) + 10, "includes/%s", rel_path)
|
||||
mod_name: str = Utils.PathToModuleName(full_path_buf, 1)
|
||||
stdlib.free(full_path_buf)
|
||||
if mod_name is None:
|
||||
return 1
|
||||
# 写入 SHA1
|
||||
idx_a: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * 17
|
||||
string.strcpy(StubMerger._sha1_store_arr + idx_a, sha1)
|
||||
# 写入模块名
|
||||
idx_m: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * 64
|
||||
mn_len: t.CSizeT = string.strlen(mod_name)
|
||||
if mn_len < 64:
|
||||
string.strcpy(StubMerger._sha1_store_mod + idx_m, mod_name)
|
||||
else:
|
||||
string.strncpy(StubMerger._sha1_store_mod + idx_m, mod_name, 63)
|
||||
StubMerger._sha1_store_mod[idx_m + 63] = '\0'
|
||||
stdlib.free(mod_name)
|
||||
# 写入相对路径
|
||||
idx_r: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_REL_PATH_LEN
|
||||
rp_len: t.CSizeT = string.strlen(rel_path)
|
||||
if rp_len < MAX_REL_PATH_LEN:
|
||||
string.strcpy(StubMerger._sha1_store_rel + idx_r, rel_path)
|
||||
else:
|
||||
string.strncpy(StubMerger._sha1_store_rel + idx_r, rel_path, MAX_REL_PATH_LEN - 1)
|
||||
StubMerger._sha1_store_rel[idx_r + MAX_REL_PATH_LEN - 1] = '\0'
|
||||
# App 源文件不属于任何 includes 目录:IncDir 留空(Phase2 回退 includes_dir 参数)
|
||||
idx_inc_a: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_INC_DIR_LEN
|
||||
StubMerger._sha1_store_incdir[idx_inc_a] = '\0'
|
||||
StubMerger._sha1_store_count += 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# GetSha1StoreCount - 获取全局存储器条目数
|
||||
# ============================================================
|
||||
def GetSha1StoreCount() -> int:
|
||||
"""返回全局 SHA1 存储器的条目数"""
|
||||
return StubMerger._sha1_store_count
|
||||
# ============================================================
|
||||
# LookupSha1ByModName - 从模块名查找 SHA1(直接查全局存储器)
|
||||
#
|
||||
# 精确匹配失败时,尝试 "{mod_name}.__init__" 回退,
|
||||
# 支持 import ast(包)→ ast.__init__ 的 SHA1 查找。
|
||||
#
|
||||
# Returns:
|
||||
# SHA1 字符串指针(指向全局存储器内部,无需释放),None 未找到
|
||||
# ============================================================
|
||||
def LookupSha1ByModName(mod_name: str) -> str:
|
||||
"""从模块名查找 SHA1(精确匹配 + 包名回退),委托通用实现 _FindSha1ByModName"""
|
||||
return StubMergerIR._FindSha1ByModName(StubMerger._sha1_store_arr, StubMerger._sha1_store_mod, StubMerger._sha1_store_count, mod_name)
|
||||
# ============================================================
|
||||
# LookupSha1ByModNameSuffix - 后缀匹配查找模块 SHA1
|
||||
#
|
||||
# 用于 from .X import Y 的相对导入:impf.module 是 ".X"(带前导点),
|
||||
# 去掉前导点后为 "X",SHA1 映射表中键是 "pkg.X",需要后缀匹配。
|
||||
# 包含三种匹配方式:精确、后缀、反向后缀。
|
||||
#
|
||||
# Returns:
|
||||
# SHA1 字符串指针(指向全局存储器内部,无需释放),None 未找到
|
||||
# ============================================================
|
||||
def LookupSha1ByModNameSuffix(mod_suffix: str) -> str:
|
||||
"""后缀匹配查找模块 SHA1"""
|
||||
if mod_suffix is None:
|
||||
return None
|
||||
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None:
|
||||
return None
|
||||
if StubMerger._sha1_store_count <= 0:
|
||||
return None
|
||||
suffix_len_sf: t.CSizeT = string.strlen(mod_suffix)
|
||||
if suffix_len_sf == 0:
|
||||
return None
|
||||
i_sf: int
|
||||
for i_sf in range(StubMerger._sha1_store_count):
|
||||
idx_sf: t.CSizeT = t.CSizeT(i_sf) * 64
|
||||
mod_name_sf: str = StubMerger._sha1_store_mod + idx_sf
|
||||
mod_len_sf: t.CSizeT = string.strlen(mod_name_sf)
|
||||
if mod_len_sf == 0:
|
||||
continue
|
||||
# 精确匹配
|
||||
if mod_len_sf == suffix_len_sf:
|
||||
if string.strcmp(mod_name_sf, mod_suffix) == 0:
|
||||
sidx_sf: t.CSizeT = t.CSizeT(i_sf) * 17
|
||||
return StubMerger._sha1_store_arr + sidx_sf
|
||||
# 后缀匹配:mod_name 以 "." + mod_suffix 结尾
|
||||
if mod_len_sf > suffix_len_sf:
|
||||
if mod_name_sf[mod_len_sf - suffix_len_sf - 1] == '.':
|
||||
cmp_start_sf: str = mod_name_sf + mod_len_sf - suffix_len_sf
|
||||
if string.strcmp(cmp_start_sf, mod_suffix) == 0:
|
||||
sidx2_sf: t.CSizeT = t.CSizeT(i_sf) * 17
|
||||
return StubMerger._sha1_store_arr + sidx2_sf
|
||||
# 反向后缀匹配:mod_suffix 以 "." + mod_name 结尾
|
||||
if suffix_len_sf > mod_len_sf:
|
||||
if mod_suffix[suffix_len_sf - mod_len_sf - 1] == '.':
|
||||
cmp_start_rev_sf: str = mod_suffix + suffix_len_sf - mod_len_sf
|
||||
if string.strcmp(cmp_start_rev_sf, mod_name_sf) == 0:
|
||||
sidx_rev_sf: t.CSizeT = t.CSizeT(i_sf) * 17
|
||||
return StubMerger._sha1_store_arr + sidx_rev_sf
|
||||
return None
|
||||
# ============================================================
|
||||
# PopulateIncludesDeps - 将 includes 文件的依赖存入内存
|
||||
#
|
||||
# Phase B+ 前用 declare_only 翻译 includes 文件,提取 _imported_modules
|
||||
# 后调用此函数存入内存。_BuildReachableSha1Set 从内存读取,不读 deps.txt。
|
||||
#
|
||||
# Args:
|
||||
# sha1: includes 文件的 SHA1(16字符)
|
||||
# deps_str: 依赖模块名字符串(空格分隔,如 "t c stdint string")
|
||||
#
|
||||
# Returns:
|
||||
# 0 成功,非 0 失败
|
||||
# ============================================================
|
||||
def PopulateIncludesDeps(sha1: str, deps_str: str) -> int:
|
||||
"""将 includes 文件的依赖存入内存"""
|
||||
if sha1 is None:
|
||||
return 1
|
||||
# 延迟初始化
|
||||
if StubMerger._includes_deps_sha1 is None:
|
||||
StubMerger._includes_deps_sha1 = stdlib.malloc(MAX_INCLUDES * 17)
|
||||
StubMerger._includes_deps_str = stdlib.malloc(MAX_INCLUDES * MAX_DEPS_STR_LEN)
|
||||
if StubMerger._includes_deps_sha1 is None or StubMerger._includes_deps_str is None:
|
||||
return 1
|
||||
string.memset(StubMerger._includes_deps_sha1, 0, MAX_INCLUDES * 17)
|
||||
string.memset(StubMerger._includes_deps_str, 0, MAX_INCLUDES * MAX_DEPS_STR_LEN)
|
||||
StubMerger._includes_deps_count = 0
|
||||
if StubMerger._includes_deps_count >= MAX_INCLUDES:
|
||||
return 1
|
||||
# 去重:若 SHA1 已存在则跳过
|
||||
for i in range(StubMerger._includes_deps_count):
|
||||
sidx: t.CSizeT = t.CSizeT(i) * 17
|
||||
if string.strcmp(StubMerger._includes_deps_sha1 + sidx, sha1) == 0:
|
||||
return 0
|
||||
# 写入 SHA1
|
||||
idx: t.CSizeT = t.CSizeT(StubMerger._includes_deps_count) * 17
|
||||
string.strcpy(StubMerger._includes_deps_sha1 + idx, sha1)
|
||||
# 写入依赖字符串
|
||||
idx2: t.CSizeT = t.CSizeT(StubMerger._includes_deps_count) * MAX_DEPS_STR_LEN
|
||||
if deps_str is not None:
|
||||
dl: t.CSizeT = string.strlen(deps_str)
|
||||
if dl < MAX_DEPS_STR_LEN:
|
||||
string.strcpy(StubMerger._includes_deps_str + idx2, deps_str)
|
||||
else:
|
||||
string.strncpy(StubMerger._includes_deps_str + idx2, deps_str, MAX_DEPS_STR_LEN - 1)
|
||||
else:
|
||||
StubMerger._includes_deps_str[idx2] = '\0'
|
||||
StubMerger._includes_deps_count = StubMerger._includes_deps_count + 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# LookupIncludesDeps - 从内存查找 includes 文件的依赖
|
||||
#
|
||||
# Args:
|
||||
# sha1: includes 文件的 SHA1(16字符)
|
||||
#
|
||||
# Returns:
|
||||
# 依赖模块名字符串指针(空格分隔),None 表示未找到
|
||||
# ============================================================
|
||||
def LookupIncludesDeps(sha1: str) -> str:
|
||||
"""从内存查找 includes 文件的依赖"""
|
||||
if sha1 is None or StubMerger._includes_deps_sha1 is None:
|
||||
return None
|
||||
if StubMerger._includes_deps_count <= 0:
|
||||
return None
|
||||
for i in range(StubMerger._includes_deps_count):
|
||||
sidx: t.CSizeT = t.CSizeT(i) * 17
|
||||
if string.strcmp(StubMerger._includes_deps_sha1 + sidx, sha1) == 0:
|
||||
idx2: t.CSizeT = t.CSizeT(i) * MAX_DEPS_STR_LEN
|
||||
return StubMerger._includes_deps_str + idx2
|
||||
return None
|
||||
def GetSha1StoreArrPtr() -> bytes | t.CPtr:
|
||||
"""返回 SHA1 数组指针(每个条目 17 字节)"""
|
||||
return StubMerger._sha1_store_arr
|
||||
def GetSha1StoreModArrPtr() -> bytes | t.CPtr:
|
||||
"""返回模块名数组指针(每个条目 64 字节)"""
|
||||
return StubMerger._sha1_store_mod
|
||||
def GetSha1StoreRelArrPtr() -> bytes | t.CPtr:
|
||||
"""返回相对路径数组指针(每个条目 MAX_REL_PATH_LEN 字节)"""
|
||||
return StubMerger._sha1_store_rel
|
||||
def GetSha1StoreIncdirArrPtr() -> bytes | t.CPtr:
|
||||
"""返回所属 includes 根目录数组指针(每个条目 MAX_INC_DIR_LEN 字节,空串表示不属于任何 includes 目录)"""
|
||||
return StubMerger._sha1_store_incdir
|
||||
# ============================================================
|
||||
# GetSha1StoreArr - 获取全局存储器数组指针(直接遍历用)
|
||||
#
|
||||
# 返回 sha1_arr、mod_arr、rel_arr 三个数组的指针和条目数。
|
||||
# 调用者直接遍历数组:sha1_arr[i*17]、mod_arr[i*64]、rel_arr[i*MAX_REL_PATH_LEN]
|
||||
# 内存归全局存储器所有,调用者不要 free
|
||||
# ============================================================
|
||||
def GetSha1StoreArr(out_sha1_arr: t.CPtr, out_mod_arr: t.CPtr, out_rel_arr: t.CPtr) -> int:
|
||||
"""获取全局存储器数组指针
|
||||
|
||||
out_sha1_arr/out_mod_arr/out_rel_arr 是调用者提供的 t.CPtr 指针,
|
||||
函数将存储器数组指针写入这些位置。
|
||||
返回条目数,-1 失败
|
||||
"""
|
||||
if out_sha1_arr is None or out_mod_arr is None or out_rel_arr is None:
|
||||
return -1
|
||||
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None:
|
||||
return -1
|
||||
sp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_sha1_arr, t.CPtr))
|
||||
if sp is not None:
|
||||
sp[0] = StubMerger._sha1_store_arr
|
||||
mp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_mod_arr, t.CPtr))
|
||||
if mp is not None:
|
||||
mp[0] = StubMerger._sha1_store_mod
|
||||
rp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_rel_arr, t.CPtr))
|
||||
if rp is not None:
|
||||
rp[0] = StubMerger._sha1_store_rel
|
||||
return StubMerger._sha1_store_count
|
||||
# ============================================================
|
||||
# LookupSha1RelPath - 通过 SHA1 查找相对路径
|
||||
#
|
||||
# 遍历全局存储器,返回 sha1 对应的相对路径指针(只读,不要 free)。
|
||||
# 用于错误提示:将 sha1 转换为人类可读的文件路径。
|
||||
#
|
||||
# Args:
|
||||
# sha1: SHA1 字符串(16 字符)
|
||||
#
|
||||
# Returns:
|
||||
# 相对路径字符串指针(只读),None=未找到
|
||||
# ============================================================
|
||||
def LookupSha1RelPath(sha1: str) -> str:
|
||||
"""通过 SHA1 查找相对路径,返回只读指针,None=未找到"""
|
||||
if sha1 is None:
|
||||
return None
|
||||
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_rel is None:
|
||||
return None
|
||||
for i in range(StubMerger._sha1_store_count):
|
||||
sidx: t.CSizeT = t.CSizeT(i) * 17
|
||||
if string.strcmp(StubMerger._sha1_store_arr + sidx, sha1) == 0:
|
||||
ridx: t.CSizeT = t.CSizeT(i) * MAX_REL_PATH_LEN
|
||||
return StubMerger._sha1_store_rel + ridx
|
||||
return None
|
||||
+166
-168
@@ -1,168 +1,166 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import llvmlite
|
||||
import w32.win32file as win32file
|
||||
import w32.win32base as win32base
|
||||
import w32.fileio as fileio
|
||||
import viperlib
|
||||
import sys
|
||||
import ast
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import lib.core.BuildPipeline as BuildPipeline
|
||||
import lib.StubGen.VpiReader as VpiReader
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import lib.Projectrans.Config as Config
|
||||
|
||||
|
||||
import lib.core.StubMergerCollect as StubMergerCollect
|
||||
import lib.core.StubMergerStore as StubMergerStore
|
||||
import lib.core.StubMergerIR as StubMergerIR
|
||||
import lib.core.StubMergerBuild as StubMergerBuild
|
||||
import lib.core.StubMerger as StubMerger
|
||||
|
||||
# ============================================================
|
||||
# StubMergerTopo - StubMerger 拆分(阶段 E):StubMergerTopo
|
||||
#
|
||||
# 直接移动模式:函数实现迁至此模块,原 StubMerger.vp 仅保留
|
||||
# 常量/全局变量;调用方经本模块前缀访问。全局变量跨模块经
|
||||
# StubMerger._xxx 访问(main.vp 先例)。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# BuildTopoSortedIndices - 对可达 includes 逆拓扑排序(被依赖者先)
|
||||
#
|
||||
# 背景:跨模块 vtable 生成要求被依赖模块先完整翻译(如 astaux.vp 继承
|
||||
# base.vp 的 AST,vtable 槽位需 AST.accept 的 TypeStr 已注册到全局表)。
|
||||
# Phase B+ 原先按 store 扫描顺序编译,依赖顺序不保证 → fail-fast 暴露。
|
||||
#
|
||||
# 算法:Kahn 逆拓扑。边 m→d 表示 m 依赖 d(d 在 m 的 deps 中)。
|
||||
# indegree[m] = m 在可达集合内的直接依赖数;
|
||||
# 入度为 0(不依赖任何可达模块)者先输出,输出后对依赖它的模块
|
||||
# 减入度,入度归 0 者入队。结果即"被依赖者先编译"。
|
||||
# reachable_count <= 0 时对全部 store 排序(与既有全量编译行为一致)。
|
||||
#
|
||||
# Args:
|
||||
# store_count / store_sha1_arr / store_mod_arr: store 元数据
|
||||
# reachable_set / reachable_count: 可达集合(_BuildReachableSha1Set 输出)
|
||||
# sorted_idx: 输出数组(store_count+1 个 8 字节槽),前 N 个为拓扑序 store 索引
|
||||
#
|
||||
# Returns:
|
||||
# 拓扑序条数;有环时剩余条目按 store 顺序补齐(避免漏编译)
|
||||
# ============================================================
|
||||
def BuildTopoSortedIndices(store_count: int, store_sha1_arr: bytes,
|
||||
store_mod_arr: bytes, reachable_set: bytes,
|
||||
reachable_count: int,
|
||||
sorted_idx: t.CSizeT | t.CPtr) -> int:
|
||||
"""对可达 includes 逆拓扑排序(被依赖者先),store 索引写入 sorted_idx"""
|
||||
if store_count <= 0 or store_sha1_arr is None or store_mod_arr is None or sorted_idx is None:
|
||||
return 0
|
||||
indegree: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(stdlib.malloc(8 * (store_count + 1)))
|
||||
queue: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(stdlib.malloc(8 * (store_count + 1)))
|
||||
rel_idx: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(stdlib.malloc(8 * (store_count + 1)))
|
||||
if indegree is None or queue is None or rel_idx is None:
|
||||
if indegree is not None:
|
||||
stdlib.free(indegree)
|
||||
if queue is not None:
|
||||
stdlib.free(queue)
|
||||
if rel_idx is not None:
|
||||
stdlib.free(rel_idx)
|
||||
return 0
|
||||
# 收集可达 store 索引(reachable_count<=0 时全量,对齐既有全量编译行为)
|
||||
rel_count: int = 0
|
||||
i_t: int
|
||||
if reachable_set is None or reachable_count <= 0:
|
||||
for i_t in range(store_count):
|
||||
rel_idx[rel_count] = i_t
|
||||
rel_count += 1
|
||||
else:
|
||||
for i_t in range(store_count):
|
||||
if StubMergerCollect._is_in_sha1_set(store_sha1_arr + t.CSizeT(i_t) * 17, reachable_set, reachable_count) != 0:
|
||||
rel_idx[rel_count] = i_t
|
||||
rel_count += 1
|
||||
# 计算入度:m 在可达集合内的直接依赖数
|
||||
i_r: int
|
||||
for i_r in range(rel_count):
|
||||
si: int = rel_idx[i_r]
|
||||
deps_si: str = StubMergerStore.LookupIncludesDeps(store_sha1_arr + t.CSizeT(si) * 17)
|
||||
if deps_si is None:
|
||||
continue
|
||||
dl_si: t.CSizeT = string.strlen(deps_si)
|
||||
dpos: t.CSizeT = 0
|
||||
while dpos < dl_si:
|
||||
dstart: t.CSizeT = dpos
|
||||
while dpos < dl_si and deps_si[dpos] != ' ':
|
||||
dpos += 1
|
||||
dlen: t.CSizeT = dpos - dstart
|
||||
if dpos < dl_si:
|
||||
dpos += 1
|
||||
if dlen == 0:
|
||||
continue
|
||||
dname_buf: bytes = stdlib.malloc(dlen + 1)
|
||||
if dname_buf is None:
|
||||
continue
|
||||
string.strncpy(dname_buf, deps_si + dstart, dlen)
|
||||
dname_buf[dlen] = '\0'
|
||||
dsha1: str = StubMergerIR._FindSha1ByModName(store_sha1_arr, store_mod_arr, store_count, dname_buf)
|
||||
stdlib.free(dname_buf)
|
||||
if dsha1 is not None and StubMergerCollect._is_in_sha1_set(dsha1, reachable_set, reachable_count) != 0:
|
||||
indegree[si] = indegree[si] + 1
|
||||
# Kahn:入度为 0(不依赖任何可达模块)者先出 → 最先编译
|
||||
q_head: int = 0
|
||||
q_tail: int = 0
|
||||
for i_r in range(rel_count):
|
||||
si2: int = rel_idx[i_r]
|
||||
if indegree[si2] == 0:
|
||||
queue[q_tail] = si2
|
||||
q_tail += 1
|
||||
out_count: int = 0
|
||||
while q_head < q_tail:
|
||||
m: int = queue[q_head]
|
||||
q_head += 1
|
||||
sorted_idx[out_count] = m
|
||||
out_count += 1
|
||||
# 对依赖 m 的可达模块减入度
|
||||
mod_m: str = store_mod_arr + t.CSizeT(m) * 64
|
||||
mod_m_len: t.CSizeT = string.strlen(mod_m)
|
||||
for i_r in range(rel_count):
|
||||
si3: int = rel_idx[i_r]
|
||||
if indegree[si3] == 0:
|
||||
continue
|
||||
deps_si3: str = StubMergerStore.LookupIncludesDeps(store_sha1_arr + t.CSizeT(si3) * 17)
|
||||
if deps_si3 is None:
|
||||
continue
|
||||
dl_si3: t.CSizeT = string.strlen(deps_si3)
|
||||
dpos3: t.CSizeT = 0
|
||||
found_dep: int = 0
|
||||
while dpos3 < dl_si3 and found_dep == 0:
|
||||
dstart3: t.CSizeT = dpos3
|
||||
while dpos3 < dl_si3 and deps_si3[dpos3] != ' ':
|
||||
dpos3 += 1
|
||||
dlen3: t.CSizeT = dpos3 - dstart3
|
||||
if dpos3 < dl_si3:
|
||||
dpos3 += 1
|
||||
if dlen3 == 0:
|
||||
continue
|
||||
if dlen3 == mod_m_len and string.strncmp(deps_si3 + dstart3, mod_m, mod_m_len) == 0:
|
||||
found_dep = 1
|
||||
if found_dep == 1:
|
||||
indegree[si3] = indegree[si3] - 1
|
||||
if indegree[si3] == 0:
|
||||
queue[q_tail] = si3
|
||||
q_tail += 1
|
||||
# 有环时剩余条目按 store 顺序补齐(避免漏编译)
|
||||
for i_r in range(rel_count):
|
||||
si4: int = rel_idx[i_r]
|
||||
if indegree[si4] > 0:
|
||||
sorted_idx[out_count] = si4
|
||||
out_count += 1
|
||||
stdlib.free(indegree)
|
||||
stdlib.free(queue)
|
||||
stdlib.free(rel_idx)
|
||||
return out_count
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import llvmlite
|
||||
import w32.win32file as win32file
|
||||
import w32.win32base as win32base
|
||||
import w32.fileio as fileio
|
||||
import viperlib
|
||||
import sys
|
||||
import ast
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import lib.core.BuildPipeline as BuildPipeline
|
||||
import lib.StubGen.VpiReader as VpiReader
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import lib.Projectrans.Config as Config
|
||||
|
||||
|
||||
import lib.core.StubMergerCollect as StubMergerCollect
|
||||
import lib.core.StubMergerStore as StubMergerStore
|
||||
import lib.core.StubMergerIR as StubMergerIR
|
||||
import lib.core.StubMergerBuild as StubMergerBuild
|
||||
import lib.core.StubMerger as StubMerger
|
||||
|
||||
# ============================================================
|
||||
# StubMergerTopo - StubMerger 拆分(阶段 E):StubMergerTopo
|
||||
#
|
||||
# 直接移动模式:函数实现迁至此模块,原 StubMerger.vp 仅保留
|
||||
# 常量/全局变量;调用方经本模块前缀访问。全局变量跨模块经
|
||||
# StubMerger._xxx 访问(main.vp 先例)。
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# BuildTopoSortedIndices - 对可达 includes 逆拓扑排序(被依赖者先)
|
||||
#
|
||||
# 背景:跨模块 vtable 生成要求被依赖模块先完整翻译(如 astaux.vp 继承
|
||||
# base.vp 的 AST,vtable 槽位需 AST.accept 的 TypeStr 已注册到全局表)。
|
||||
# Phase B+ 原先按 store 扫描顺序编译,依赖顺序不保证 → fail-fast 暴露。
|
||||
#
|
||||
# 算法:Kahn 逆拓扑。边 m→d 表示 m 依赖 d(d 在 m 的 deps 中)。
|
||||
# indegree[m] = m 在可达集合内的直接依赖数;
|
||||
# 入度为 0(不依赖任何可达模块)者先输出,输出后对依赖它的模块
|
||||
# 减入度,入度归 0 者入队。结果即"被依赖者先编译"。
|
||||
# reachable_count <= 0 时对全部 store 排序(与既有全量编译行为一致)。
|
||||
#
|
||||
# Args:
|
||||
# store_count / store_sha1_arr / store_mod_arr: store 元数据
|
||||
# reachable_set / reachable_count: 可达集合(_BuildReachableSha1Set 输出)
|
||||
# sorted_idx: 输出数组(store_count+1 个 8 字节槽),前 N 个为拓扑序 store 索引
|
||||
#
|
||||
# Returns:
|
||||
# 拓扑序条数;有环时剩余条目按 store 顺序补齐(避免漏编译)
|
||||
# ============================================================
|
||||
def BuildTopoSortedIndices(store_count: int, store_sha1_arr: bytes,
|
||||
store_mod_arr: bytes, reachable_set: bytes,
|
||||
reachable_count: int,
|
||||
sorted_idx: t.CSizeT | t.CPtr) -> int:
|
||||
"""对可达 includes 逆拓扑排序(被依赖者先),store 索引写入 sorted_idx"""
|
||||
if store_count <= 0 or store_sha1_arr is None or store_mod_arr is None or sorted_idx is None:
|
||||
return 0
|
||||
indegree: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(stdlib.malloc(8 * (store_count + 1)))
|
||||
queue: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(stdlib.malloc(8 * (store_count + 1)))
|
||||
rel_idx: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(stdlib.malloc(8 * (store_count + 1)))
|
||||
if indegree is None or queue is None or rel_idx is None:
|
||||
if indegree is not None:
|
||||
stdlib.free(indegree)
|
||||
if queue is not None:
|
||||
stdlib.free(queue)
|
||||
if rel_idx is not None:
|
||||
stdlib.free(rel_idx)
|
||||
return 0
|
||||
# 收集可达 store 索引(reachable_count<=0 时全量,对齐既有全量编译行为)
|
||||
rel_count: int = 0
|
||||
i_t: int
|
||||
if reachable_set is None or reachable_count <= 0:
|
||||
for i_t in range(store_count):
|
||||
rel_idx[rel_count] = i_t
|
||||
rel_count += 1
|
||||
else:
|
||||
for i_t in range(store_count):
|
||||
if StubMergerCollect._is_in_sha1_set(store_sha1_arr + t.CSizeT(i_t) * 17, reachable_set, reachable_count) != 0:
|
||||
rel_idx[rel_count] = i_t
|
||||
rel_count += 1
|
||||
# 计算入度:m 在可达集合内的直接依赖数
|
||||
i_r: int
|
||||
for i_r in range(rel_count):
|
||||
si: int = rel_idx[i_r]
|
||||
deps_si: str = StubMergerStore.LookupIncludesDeps(store_sha1_arr + t.CSizeT(si) * 17)
|
||||
if deps_si is None:
|
||||
continue
|
||||
dl_si: t.CSizeT = string.strlen(deps_si)
|
||||
dpos: t.CSizeT = 0
|
||||
while dpos < dl_si:
|
||||
dstart: t.CSizeT = dpos
|
||||
while dpos < dl_si and deps_si[dpos] != ' ':
|
||||
dpos += 1
|
||||
dlen: t.CSizeT = dpos - dstart
|
||||
if dpos < dl_si:
|
||||
dpos += 1
|
||||
if dlen == 0:
|
||||
continue
|
||||
dname_buf: bytes = stdlib.malloc(dlen + 1)
|
||||
if dname_buf is None:
|
||||
continue
|
||||
string.strncpy(dname_buf, deps_si + dstart, dlen)
|
||||
dname_buf[dlen] = '\0'
|
||||
dsha1: str = StubMergerIR._FindSha1ByModName(store_sha1_arr, store_mod_arr, store_count, dname_buf)
|
||||
stdlib.free(dname_buf)
|
||||
if dsha1 is not None and StubMergerCollect._is_in_sha1_set(dsha1, reachable_set, reachable_count) != 0:
|
||||
indegree[si] = indegree[si] + 1
|
||||
# Kahn:入度为 0(不依赖任何可达模块)者先出 → 最先编译
|
||||
q_head: int = 0
|
||||
q_tail: int = 0
|
||||
for i_r in range(rel_count):
|
||||
si2: int = rel_idx[i_r]
|
||||
if indegree[si2] == 0:
|
||||
queue[q_tail] = si2
|
||||
q_tail += 1
|
||||
out_count: int = 0
|
||||
while q_head < q_tail:
|
||||
m: int = queue[q_head]
|
||||
q_head += 1
|
||||
sorted_idx[out_count] = m
|
||||
out_count += 1
|
||||
# 对依赖 m 的可达模块减入度
|
||||
mod_m: str = store_mod_arr + t.CSizeT(m) * 64
|
||||
mod_m_len: t.CSizeT = string.strlen(mod_m)
|
||||
for i_r in range(rel_count):
|
||||
si3: int = rel_idx[i_r]
|
||||
if indegree[si3] == 0:
|
||||
continue
|
||||
deps_si3: str = StubMergerStore.LookupIncludesDeps(store_sha1_arr + t.CSizeT(si3) * 17)
|
||||
if deps_si3 is None:
|
||||
continue
|
||||
dl_si3: t.CSizeT = string.strlen(deps_si3)
|
||||
dpos3: t.CSizeT = 0
|
||||
found_dep: int = 0
|
||||
while dpos3 < dl_si3 and found_dep == 0:
|
||||
dstart3: t.CSizeT = dpos3
|
||||
while dpos3 < dl_si3 and deps_si3[dpos3] != ' ':
|
||||
dpos3 += 1
|
||||
dlen3: t.CSizeT = dpos3 - dstart3
|
||||
if dpos3 < dl_si3:
|
||||
dpos3 += 1
|
||||
if dlen3 == 0:
|
||||
continue
|
||||
if dlen3 == mod_m_len and string.strncmp(deps_si3 + dstart3, mod_m, mod_m_len) == 0:
|
||||
found_dep = 1
|
||||
if found_dep == 1:
|
||||
indegree[si3] = indegree[si3] - 1
|
||||
if indegree[si3] == 0:
|
||||
queue[q_tail] = si3
|
||||
q_tail += 1
|
||||
# 有环时剩余条目按 store 顺序补齐(避免漏编译)
|
||||
for i_r in range(rel_count):
|
||||
si4: int = rel_idx[i_r]
|
||||
if indegree[si4] > 0:
|
||||
sorted_idx[out_count] = si4
|
||||
out_count += 1
|
||||
stdlib.free(indegree)
|
||||
stdlib.free(queue)
|
||||
stdlib.free(rel_idx)
|
||||
return out_count
|
||||
+673
-712
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user