Files
ViperC/App/lib/core/Handles/HandlesExprCall.vp
T
TermiNexus 0e4f00baf4 refactor(gen): P4 CallGenMixin - HandlesExprCall 86 函数迁移 + 委托层
HandlesExprCall(7043 行, 本仓库最大文件)全部模块级函数迁移为
CallGenMixin 方法(含 translate_call 1408 行整体迁移),全局表
(cexport/LLVMIR 序号/temp_dir/闭包/funcptr/全局函数表/默认参数表)
迁入 gen 字段;旧函数保留为 _g_gen 单例委托,4 类保留。Generator
多继承追加 CallGenMixin(现为 5 Mixin 组合)。

修复 P4 迁移引入的两处缺陷:
1. HandlesTranslator 引用已删除的 HandlesExprCall._g_temp_dir → None
   导致跨模块 .vpi 注入全局失效(json 翻译崩溃),改用
   HandlesType.get_temp_dir()
2. Generator 50 字段突破 FIELD_MAX=48 硬上限导致字段截断丢失,
   字段槽位上限提升至 64(HandlesStruct/StructGenMixin/HandlesClassDef)
2026-08-10 03:31:10 +08:00

1767 lines
89 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
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
#
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
# P4 委托函数用本地 _g_gen(cast 成 Generator 类型)调
# CallGenMixin 方法,避免函数体 import 包模块与类/模块名歧义。
# ============================================================
_g_gen: t.CVoid | t.CPtr = None
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
global _g_gen
_g_gen = 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(_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(_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(_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(_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(_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(_g_gen, t.CPtr))
if g is not None:
return g._lookup_sha1_from_modname_raw(pool, mod_name_raw)
return None
# ============================================================
# HandlesExprCall - 函数调用表达式处理(Mixin 继承模式)
#
# 工具函数和 FuncEntry 保留为模块级,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(_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(_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(_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(_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(_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
# ============================================================
# 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(_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(_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(_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(_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(_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
# ============================================================
# AsmOperand - 内联汇编操作数条目
# ============================================================
@t.NoVTable
class AsmOperand:
"""内联汇编操作数条目"""
Value: llvmlite.Value | t.CPtr # 输入值或输出 alloca
Constraint: str # 约束字符串 (如 "r", "=r")
IsOutput: int # 1=输出, 0=输入
# ============================================================
# _asm_append_cstr — 将 C 字符串 src 追加到 dst 末尾
# ============================================================
def _asm_append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT,
src: t.CChar | t.CPtr):
"""将 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(_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: t.CChar | t.CPtr) -> t.CChar | t.CPtr:
"""转义汇编文本用于 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(_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(_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(_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: AsmOperand | t.CPtr,
idx: int) -> 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(_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(_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: 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(_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(_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(_g_gen, t.CPtr))
if g is not None:
return g.translate_c_llvmir(pool, builder, mod, cl, trans)
return None
# ============================================================
# _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(_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(_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(_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) -> 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(_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)
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(_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(_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 →
# "t.CChar | t.CPtr")在 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(_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(_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(_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 缓存)。
# ============================================================
# text.ll 读取缓冲区大小
_TEXT_LL_READ_BUF_SIZE: t.CDefine = 262144
# ============================================================
# 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(_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(_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) -> 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(_g_gen, t.CPtr))
if g is not None:
return g._LookupMethodRetTyFromTextLL(pool, class_sha1, class_name, method_name)
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(_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(_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(_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(_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(_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(_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(_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: t.CChar | t.CPtr) -> 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(_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(_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(_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(_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(_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) -> 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(_g_gen, t.CPtr))
if g is not None:
return g._infer_generic_ctor_type_arg(pool, arg_node)
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(_g_gen, t.CPtr))
if g is not None:
return g._translate_generic_ctor_call(pool, builder, mod, spec_name, cl, trans)
return None
# ============================================================
# 翻译函数调用 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(_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) -> 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(_g_gen, t.CPtr))
if g is not None:
return g.translate_closure_call(pool, builder, mod, closure_alloca, cargs, can)
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(_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(_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(_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(_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(_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(_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(_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(_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(_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(_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(_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(_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(_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(_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(_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(_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(_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) -> 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(_g_gen, t.CPtr))
if g is not None:
return g._check_and_promote_variadic_call(pool, builder, mod, call_name, head, can)
return 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: t.CChar | t.CPtr
# ============================================================
# 初始化函数表
# ============================================================
def init_func_table(pool: memhub.MemBuddy | t.CPtr,
max_count: int) -> 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(_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: 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(_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: 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(_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(_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) -> t.CChar | t.CPtr:
"""生成函数类型文本(stdlib 分配)(委托到 gen._build_func_type_str)"""
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._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(_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(_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(_g_gen, t.CPtr))
if g is not None:
return g.find_func_global(name)
return None
def find_func_entry_global(name: str) -> FuncEntry | t.CPtr:
"""在全局函数表中按名称查找,返回完整 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(_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
@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*)
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(_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(_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) -> FuncDefaultsEntry | t.CPtr:
"""按函数名查找默认参数信息,返回 FuncDefaultsEntry 或 None(委托到 gen.find_func_defaults)"""
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.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: 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(_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: FuncEntry | t.CPtr,
func_count: int,
name: str) -> FuncEntry | t.CPtr:
"""在函数表中按名称查找,返回完整 FuncEntry 或 None"""
if name is None or funcs is None:
return None
entry_size: t.CSizeT = FuncEntry.__sizeof__()
i: int = 0
while i < func_count:
entry_addr: t.CUInt64T = t.CUInt64T(funcs) + i * entry_size
entry: FuncEntry | t.CPtr = (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
# ============================================================
# 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 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 获取共享状态"""
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 调用(类型感知格式化 + 默认换行)"""
translate_print_call(
self.Trans.Pool, self.Trans._cur_builder, self.Trans.Module,
cl, self.Trans)
# ============================================================
# NewExprCallHandle - 工厂函数
# ============================================================
def NewExprCallHandle(pool: memhub.MemBuddy | t.CPtr,
trans: HT.Translator | t.CPtr) -> ExprCallHandle | t.CPtr:
"""新建 ExprCallHandle 工厂(委托到 gen.NewExprCallHandle)"""
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.NewExprCallHandle(pool, trans)
return None