直接移动+改调用方:~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 验证通过
387 lines
18 KiB
Plaintext
387 lines
18 KiB
Plaintext
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.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
|
||
# 兜底: 创建外部全局 @_mbuddy 引用(i8** 类型)
|
||
# 仅用于函数内动态 list 字面量,@_mbuddy 由入口模块定义并初始化
|
||
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)
|
||
# 创建外部全局 @_mbuddy(external linkage,无初始值)
|
||
gv_ext: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, "_mbuddy", i8_ptr_ty_fb)
|
||
if gv_ext is not None:
|
||
gv_ext.Linkage = "external"
|
||
llvmlite.module_add_global(trans.Module, gv_ext)
|
||
# 创建 Value 引用(@_mbuddy, 类型为 i8**)
|
||
i8_ptr_ptr_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty_fb)
|
||
ref_name_fb: str = pool.alloc(16)
|
||
if ref_name_fb is not None:
|
||
string.strcpy(ref_name_fb, "@_mbuddy")
|
||
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
|
||
|
||
return storage_ptr |