直接移动+改调用方:~100 个委托函数按功能移至 6 个子模块,主文件 保留 _g_gen/set_global_gen/顶层常量/4 个类(AsmOperand、FuncEntry、 FuncDefaultsEntry、ExprCallHandle——CallGenLeafKit/HandlesTranslator 仍以 HandlesExprCall.类名 引用)。 - 子模块函数体内 _g_gen/常量/类裸引用 → HandlesExprCall.xxx 跨模块访问 - 28 个调用方 HandlesExprCall.func( → 子模块前缀并补 import - 全 App 语法/引用/import 验证通过
247 lines
13 KiB
Plaintext
247 lines
13 KiB
Plaintext
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
|