Files
ViperC/App/lib/core/Handles/ExprCallBase.vp
T
TermiNexus 2cb974ae5a refactor(handles): HandlesExprCall 拆 6 组(Base/Deref/Ctor/Call/Table/Handle,2041→241 行)
直接移动+改调用方:~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 验证通过
2026-08-17 08:10:55 +08:00

247 lines
13 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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