- @t.NoVTable class X → novirtual class X
- t.CDefine = N → define N
- rawptr[X]、X | t.CPtr → X*
- t.CPtr → rawptr(裸指针标记)
- t.Callable[...] → callable[...]
- 去掉 if/elif 条件的行续反斜杠(改单行写法)
- w32.win32file.X → win32file.X(已 import as)
- core/__init__.vp 去掉未使用的 import t, c / from stdint import *
涉及:CompilerFactory、IncludesScanner、Repl、core/__init__、
Gen/Call/{CallGenBase,CallGenCBuiltin,CallGenCall,CallGenDispatch,CallGenLeafKit}、
Gen/Class/ClassGenGeneric。
1819 lines
147 KiB
Plaintext
1819 lines
147 KiB
Plaintext
import lib.core.Gen.GenTypes as GenTypes
|
||
import lib.core.Gen.Generator as Generator
|
||
import lib.core.Gen.Expr.ExprGenCls as ExprGenCls
|
||
import lib.core.Gen.Expr.ExprGenName as ExprGenName
|
||
import t, c
|
||
from stdint import *
|
||
import ast
|
||
import llvmlite
|
||
import memhub
|
||
import string
|
||
import stdlib
|
||
import sys
|
||
import viperlib
|
||
import w32.fileio as fileio
|
||
import lib.core.VLogger as VLogger
|
||
import lib.core.Gen.Translator as HT
|
||
import lib.core.Gen.Type.TypeSpec as TSpec
|
||
import lib.Stub.StubMerger as StubMerger
|
||
import lib.core.CompilerFactory as CompilerFactory
|
||
from . import CallGenBase
|
||
import lib.core.Gen.GenApi as GenApi
|
||
|
||
|
||
# ============================================================
|
||
# CallGenDispatch - CallGenMixin 拆分(阶段 C):translate_call 检测段
|
||
# ============================================================
|
||
novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||
"""translate_call 前置检测 helper(继承 Base)"""
|
||
|
||
def _tc_h1_super_ctraits(self, pool: memhub.MemBuddy*,
|
||
builder: llvmlite.IRBuilder*,
|
||
mod: llvmlite.LLVMModule*,
|
||
cl: ast.Call*,
|
||
funcs_ptr: t.CPtr,
|
||
func_count: int,
|
||
trans: HT.Translator*,
|
||
func_name: str,
|
||
cargs: list[ast.AST*]*,
|
||
can: sizet,
|
||
hit_box: t.CPtr = None) -> llvmlite.Value*:
|
||
"""super()/ctraits 编译期检测(未命中返回 None)
|
||
|
||
hit_box: 命中标志字节([0]=1 表示被本 helper 拦截处理)。
|
||
super().method() 命中后 _translate_super_call 对 void 方法(如
|
||
__init__)经 build_call 返回 None 属预期(void call 无 SSA 值),
|
||
必须用 hit_box 与"未命中"区分,否则 translate_call 会误判继续
|
||
主路径 → 把内层 Call(super) 当裸名调用报"super 未定义"。
|
||
"""
|
||
# super() 语义(2026-08-10):super().method(args) → 静态调用父类方法
|
||
# 形态: Call(func=Attribute(value=Call(func=Name('super')), attr=method))
|
||
# 必须在 Attribute 分派前拦截——否则 value 的 Call(super) 被 translate_value
|
||
# 当作普通函数调用报错,且走普通属性调用会命中自身/虚分派而非父类实现。
|
||
if func_name is not None and cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||
sup_at: ast.Attribute* = ast.Attribute*(cl.func)
|
||
if sup_at.value is not None and sup_at.value.kind() == ast.ASTKind.Call:
|
||
sup_cl: ast.Call* = ast.Call*(sup_at.value)
|
||
if sup_cl.func is not None and sup_cl.func.kind() == ast.ASTKind.Name:
|
||
sup_nm: ast.Name* = ast.Name*(sup_cl.func)
|
||
if sup_nm.id is not None and string.strcmp(sup_nm.id, "super") == 0:
|
||
if hit_box is not None:
|
||
hit_box[0] = 1
|
||
return self.Gen.CallGenCall._translate_super_call(pool, builder, mod, cl, func_name, trans)
|
||
|
||
# ctraits 宏库编译期谓词:ctraits.isptr(x) 不生成运行时调用,
|
||
# 直接按变量存储类型返回编译期常量(CIf 求值失败回退或非 CIf 上下文时兜底,
|
||
# 避免生成跨模块调用 ctraits.isptr 触发"模块未注册 SHA1"误导性报错)
|
||
if func_name is not None and cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||
ct_at: ast.Attribute* = ast.Attribute*(cl.func)
|
||
if ct_at.value is not None and ct_at.value.kind() == ast.ASTKind.Name:
|
||
ct_nm: ast.Name* = ast.Name*(ct_at.value)
|
||
if ct_nm.id is not None and string.strcmp(ct_nm.id, "ctraits") == 0 and string.strcmp(func_name, "isptr") == 0:
|
||
ct_args: list[ast.AST*]* = cl.args
|
||
if ct_args is not None and len(ct_args) >= 1:
|
||
ct_arg0: ast.AST* = ct_args.get(0)
|
||
if ct_arg0 is not None and ct_arg0.kind() == ast.ASTKind.Name:
|
||
ct_nm0: ast.Name* = ast.Name*(ct_arg0)
|
||
if ct_nm0.id is not None and trans is not None:
|
||
ct_r: int = self.Gen.StmtGenCif._eval_ctraits_isptr(trans.SymTab, ct_nm0.id)
|
||
if ct_r > 0:
|
||
return llvmlite.const_int32(pool, 1)
|
||
return llvmlite.const_int32(pool, 0)
|
||
return None
|
||
|
||
def _tc_h2_c_special(self, pool: memhub.MemBuddy*,
|
||
builder: llvmlite.IRBuilder*,
|
||
mod: llvmlite.LLVMModule*,
|
||
cl: ast.Call*,
|
||
funcs_ptr: t.CPtr,
|
||
func_count: int,
|
||
trans: HT.Translator*,
|
||
func_name: str,
|
||
cargs: list[ast.AST*]*,
|
||
can: sizet,
|
||
hit_box: t.CPtr = None) -> llvmlite.Value*:
|
||
"""c.Deref/Asm/LLVMIR 等特殊调用(未命中返回 None)
|
||
|
||
hit_box: 命中标记(t.CPtr,[0]=1 表示已识别为 c.* 特殊调用)。
|
||
仅对 c.Asm/c.LLVMIR 等返回 None(void,无返回值)的调用置位——
|
||
translate_c_asm/translate_c_llvmir 成功处理 void 时返回 None,
|
||
若不加 hit_box 会被 translate_call 误判为"未命中"继续走外部函数路径。
|
||
"""
|
||
# __asm__(...) / __llvmir__(...) 语法糖:裸名调用等价 c.Asm(...) / c.LLVMIR(...)
|
||
# (无 c. 前缀,无需 import c)。必须在 c.* Attribute 分支之前拦截:
|
||
# 裸名 cl.func 是 Name 而非 Attribute。
|
||
if func_name is not None and cl.func is not None and cl.func.kind() == ast.ASTKind.Name:
|
||
bare_nm: ast.Name* = ast.Name*(cl.func)
|
||
if bare_nm.id is not None and string.strcmp(bare_nm.id, "__asm__") == 0:
|
||
# 无输出(void)时 translate_c_asm 返回 None:置命中标记,
|
||
# 避免 translate_call 误判未命中继续走外部函数路径。
|
||
if hit_box is not None:
|
||
hit_box[0] = 1
|
||
return self.Gen.CallGenCBuiltin.translate_c_asm(pool, builder, mod, cl, trans)
|
||
if bare_nm.id is not None and string.strcmp(bare_nm.id, "__llvmir__") == 0:
|
||
# c.LLVMIR 总是无返回值(返回 None):置命中标记
|
||
if hit_box is not None:
|
||
hit_box[0] = 1
|
||
return self.Gen.CallGenCBuiltin.translate_c_llvmir(pool, builder, mod, cl, trans)
|
||
if bare_nm.id is not None and (string.strcmp(bare_nm.id, "irinp") == 0 or string.strcmp(bare_nm.id, "irout") == 0):
|
||
# irinp/irout 独立调用时返回 0(仅在 __llvmir__ 的 f-string 内有意义)
|
||
return llvmlite.ConstInt(pool, llvmlite.Int32(pool), 0, "0")
|
||
|
||
# 检测 c.Deref / c.DerefAs / c.Addr 等特殊调用(内联 IR,不生成 call)
|
||
# 及 coro.* 协程库拦截(coro.coro_run 内联翻译,TPV-M1)
|
||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||
at_node: ast.Attribute* = ast.Attribute*(cl.func)
|
||
if at_node.value is not None and at_node.value.kind() == ast.ASTKind.Name:
|
||
mod_nm: ast.Name* = ast.Name*(at_node.value)
|
||
is_coro_mod: int = 0
|
||
if mod_nm.id is not None and string.strcmp(mod_nm.id, "coro") == 0:
|
||
is_coro_mod = 1
|
||
if mod_nm.id is not None and (string.strcmp(mod_nm.id, "c") == 0 or is_coro_mod != 0):
|
||
if string.strcmp(func_name, "Deref") == 0:
|
||
return self.Gen.CallGenCBuiltin.translate_c_deref(pool, builder, mod, cl, trans)
|
||
elif string.strcmp(func_name, "DerefAs") == 0:
|
||
return self.Gen.CallGenCBuiltin.translate_c_derefas(pool, builder, mod, cl, trans)
|
||
elif string.strcmp(func_name, "Addr") == 0:
|
||
return self.Gen.CallGenCBuiltin.translate_c_addr(pool, builder, mod, cl, trans)
|
||
elif string.strcmp(func_name, "Set") == 0:
|
||
# c.Set(a, b) = a = b(赋值语义,非指针解引用)。
|
||
# 若当普通函数调用会生成 @Set 引用导致链接失败(undefined reference to `Set')。
|
||
return self.Gen.CallGenCBuiltin.translate_c_set(pool, builder, mod, cl, trans)
|
||
elif string.strcmp(func_name, "Load") == 0:
|
||
return self.Gen.CallGenCBuiltin.translate_c_load(pool, builder, mod, cl, trans)
|
||
elif string.strcmp(func_name, "Asm") == 0:
|
||
# c.Asm 无输出(void)时 translate_c_asm 返回 None:
|
||
# 置命中标记,避免 translate_call 误判未命中继续走外部函数
|
||
if hit_box is not None:
|
||
hit_box[0] = 1
|
||
return self.Gen.CallGenCBuiltin.translate_c_asm(pool, builder, mod, cl, trans)
|
||
elif string.strcmp(func_name, "LLVMIR") == 0:
|
||
# c.LLVMIR 总是无返回值(返回 None):置命中标记
|
||
if hit_box is not None:
|
||
hit_box[0] = 1
|
||
return self.Gen.CallGenCBuiltin.translate_c_llvmir(pool, builder, mod, cl, trans)
|
||
elif string.strcmp(func_name, "LInp") == 0 or string.strcmp(func_name, "LOut") == 0:
|
||
# c.LInp/c.LOut 独立调用时返回 0(仅在 c.LLVMIR 的 f-string 内有意义)
|
||
return llvmlite.ConstInt(pool, llvmlite.Int32(pool), 0, "0")
|
||
elif string.strcmp(func_name, "CIf") == 0:
|
||
# 运行时 c.CIf(expr)(编译期求值失败回退):expr 与 0 比较得到 i1
|
||
# 对齐 TPC HandlesExprCall.py L2434-2444
|
||
cif_args: list[ast.AST*]* = cl.args
|
||
if cif_args is not None and len(cif_args) >= 1:
|
||
cif_arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cif_args.get(0), funcs_ptr, func_count, trans)
|
||
if cif_arg_val is not None:
|
||
cif_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(cif_arg_val.Ty)
|
||
if cif_bits == 1:
|
||
return cif_arg_val
|
||
if self.Gen.ExprGenBase.is_ptr_type(cif_arg_val.Ty) != 0:
|
||
cif_null: llvmlite.Value* = llvmlite.ConstNull(pool, cif_arg_val.Ty, "null")
|
||
return llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cif_arg_val, cif_null)
|
||
cif_zero: llvmlite.Value* = llvmlite.const_int32(pool, 0)
|
||
return llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cif_arg_val, cif_zero)
|
||
return llvmlite.ConstInt(pool, llvmlite.Int1(pool), 0, "0")
|
||
elif string.strcmp(func_name, "CIfdef") == 0 or string.strcmp(func_name, "CIfndef") == 0:
|
||
# 运行时 c.CIfdef/c.CIfndef(编译期求值失败回退):恒真
|
||
# 对齐 TPC HandlesExprCall.py L2445-2446
|
||
return llvmlite.ConstInt(pool, llvmlite.Int1(pool), 1, "1")
|
||
elif is_coro_mod != 0 and string.strcmp(func_name, "coro_run") == 0:
|
||
# coro.coro_run(帧):内联翻译(resume 循环到 done,返回帧 ret 槽)
|
||
# 对齐 TPC HandlesAsyncFunctions._HandleCoroRunLlvm
|
||
# 注意:coro.* 系列 translate_coro_* 签名统一是
|
||
# (builder, pool, mod, cl, trans),与本文件其它 c.* 分支的
|
||
# (pool, builder, ...) 顺序不同,勿混用。
|
||
return self.Gen.AsyncGen.translate_coro_run(builder, pool, mod, cl, trans)
|
||
elif is_coro_mod != 0 and string.strcmp(func_name, "coro_destroy") == 0:
|
||
# coro.coro_destroy(帧):帧回池(M7 free-list)
|
||
return self.Gen.AsyncGen.translate_coro_destroy(builder, pool, mod, cl, trans)
|
||
elif is_coro_mod != 0 and string.strcmp(func_name, "coro_exception") == 0:
|
||
# coro.coro_exception(帧):返回帧 exc 槽(M4)
|
||
return self.Gen.AsyncGen.translate_coro_exception(builder, pool, mod, cl, trans)
|
||
elif is_coro_mod != 0 and string.strcmp(func_name, "coro_exception_msg") == 0:
|
||
# coro.coro_exception_msg(帧):返回帧 msg 槽(M7)
|
||
return self.Gen.AsyncGen.translate_coro_exception_msg(builder, pool, mod, cl, trans)
|
||
elif is_coro_mod != 0 and string.strcmp(func_name, "coro_gather") == 0:
|
||
# coro.coro_gather(帧...):并发推进全部协程(M4)
|
||
return self.Gen.AsyncGen.translate_coro_gather(builder, pool, mod, cl, trans)
|
||
return None
|
||
|
||
def _tc_h3_stdarg_cast(self, pool: memhub.MemBuddy*,
|
||
builder: llvmlite.IRBuilder*,
|
||
mod: llvmlite.LLVMModule*,
|
||
cl: ast.Call*,
|
||
funcs_ptr: t.CPtr,
|
||
func_count: int,
|
||
trans: HT.Translator*,
|
||
func_name: str,
|
||
cargs: list[ast.AST*]*,
|
||
can: sizet) -> llvmlite.Value*:
|
||
"""stdarg 糖 + str/int/bool 内置强转(未命中返回 None)"""
|
||
# stdarg 糖函数处理: va_arg / arg / va_start / va_end
|
||
# 这些函数在 stdarg.vp 中声明为 pass 体,由编译器在翻译期处理:
|
||
# va_arg(ap, type) → %N = va_arg <ap_ty> <ap>, <type> (LLVM 指令)
|
||
# va_arg(ap) → 同上,类型从赋值上下文推断(默认 i32)
|
||
# arg(type) → 同上,使用当前函数的隐式 va_list (trans._va_list_ptr)
|
||
# va_start(ap, _) → call void @llvm.va_start(i8* %ap) (LLVM intrinsic)
|
||
# va_end(ap) → call void @llvm.va_end(i8* %ap) (LLVM intrinsic)
|
||
# ============================================================
|
||
if func_name is not None and trans is not None:
|
||
if string.strcmp(func_name, "va_arg") == 0:
|
||
return self.Gen.CallGenVa._translate_va_arg_sugar(pool, builder, mod, cl, cargs, can,
|
||
funcs_ptr, func_count, trans)
|
||
elif string.strcmp(func_name, "arg") == 0:
|
||
return self.Gen.CallGenVa._translate_arg_sugar(pool, builder, mod, cl, cargs, can,
|
||
funcs_ptr, func_count, trans)
|
||
elif string.strcmp(func_name, "va_start") == 0:
|
||
return self.Gen.CallGenVa._translate_va_start_sugar(pool, builder, mod, cargs, can,
|
||
funcs_ptr, func_count, trans)
|
||
elif string.strcmp(func_name, "va_end") == 0:
|
||
return self.Gen.CallGenVa._translate_va_end_sugar(pool, builder, mod, cargs, can,
|
||
funcs_ptr, func_count, trans)
|
||
|
||
# 内置强转函数: str(x)/bytes(x) → i8*, int(x) → i32
|
||
# 等价于 (str)(x) / (int32)(x)
|
||
# 单参数:str(val) → bitcast val to i8*
|
||
# int(val) → trunc/sext val to i32
|
||
# 泛型类型参数: 类特化/泛型函数上下文中的 T(x) 先解析 T 为具体类型名
|
||
# (如 "int")再按内建强转处理(Box[int].__init__ 的 self.value = T(v)、
|
||
# combine[T1,T2] 的 T1(b) 依赖此路径)
|
||
if func_name is not None and can == 1:
|
||
cast_fn_name: str = self.Gen.TypeGenBase.resolve_generic_type_name(func_name)
|
||
if string.strcmp(cast_fn_name, "str") == 0 or string.strcmp(cast_fn_name, "bytes") == 0:
|
||
# str(x) / bytes(x) → i8* (bitcast)
|
||
cast_arg: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), funcs_ptr, func_count, trans)
|
||
if cast_arg is not None:
|
||
i8_ptr_ty_builtin: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||
return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, cast_arg, i8_ptr_ty_builtin)
|
||
return None
|
||
elif string.strcmp(cast_fn_name, "int") == 0:
|
||
# int(x) → i32
|
||
cast_arg_int: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), funcs_ptr, func_count, trans)
|
||
if cast_arg_int is not None:
|
||
i32_ty_builtin: llvmlite.LLVMType* = llvmlite.Int32(pool)
|
||
return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, cast_arg_int, i32_ty_builtin)
|
||
return None
|
||
elif string.strcmp(cast_fn_name, "bool") == 0:
|
||
# bool(x) → i1(严格 != 0 归一化)
|
||
# 整数: icmp ne x, 0 → i1
|
||
# 浮点: fcmp one x, 0.0 → i1
|
||
# 指针: icmp ne x, null → i1
|
||
cast_arg_bool: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), funcs_ptr, func_count, trans)
|
||
if cast_arg_bool is not None:
|
||
arg_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(cast_arg_bool.Ty)
|
||
arg_fbits: int = self.Gen.ExprGenBase.get_llvm_float_bits(cast_arg_bool.Ty)
|
||
# 整数: icmp ne x, 0
|
||
if arg_bits != 0:
|
||
zero_int: llvmlite.Value* = llvmlite.const_int(pool, arg_bits, 0)
|
||
if zero_int is not None:
|
||
return llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cast_arg_bool, zero_int)
|
||
return None
|
||
# 浮点: fcmp one x, 0.0
|
||
if arg_fbits != 0:
|
||
zero_ty: llvmlite.LLVMType* = cast_arg_bool.Ty
|
||
zero_flt: llvmlite.Value* = llvmlite.ConstFloat(pool, zero_ty, 0.0)
|
||
if zero_flt is not None:
|
||
return llvmlite.build_fcmp(builder, llvmlite.FCMP_ONE, cast_arg_bool, zero_flt)
|
||
return None
|
||
# 指针: icmp ne x, null
|
||
ptr_null: llvmlite.Value* = llvmlite.ConstNull(pool, cast_arg_bool.Ty, "null")
|
||
if ptr_null is not None:
|
||
return llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cast_arg_bool, ptr_null)
|
||
return None
|
||
return None
|
||
return None
|
||
|
||
def _tc_h4_type_casts(self, pool: memhub.MemBuddy*,
|
||
builder: llvmlite.IRBuilder*,
|
||
mod: llvmlite.LLVMModule*,
|
||
cl: ast.Call*,
|
||
funcs_ptr: t.CPtr,
|
||
func_count: int,
|
||
trans: HT.Translator*,
|
||
func_name: str,
|
||
cargs: list[ast.AST*]*,
|
||
can: sizet) -> llvmlite.Value*:
|
||
"""t.XXX / typedef 类型转换(未命中返回 None)"""
|
||
# 检测 t.XXX 类型转换: uint64(ptr), t.CPtr(val), int(val) 等
|
||
# 当 func 是 t.XXX 形式且 XXX 是已知类型名时,当作类型转换处理(而非函数调用)
|
||
# 支持:
|
||
# 单参数: int(val) → 目标类型 = map_t_type(func_name)
|
||
# 双参数: int(val, t.CPtr) → 目标类型 = Ptr(map_t_type(func_name))
|
||
# t 是内部库,一旦确认为类型转换,绝不跌落到跨模块调用 FATAL 路径
|
||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||
tc_at: ast.Attribute* = ast.Attribute*(cl.func)
|
||
if tc_at.value is not None and tc_at.value.kind() == ast.ASTKind.Name:
|
||
tc_mod_nm: ast.Name* = ast.Name*(tc_at.value)
|
||
if tc_mod_nm.id is not None and string.strcmp(tc_mod_nm.id, "t") == 0:
|
||
# t.CType 特殊形式:t.CType(value, TypeName, t.CPtr) →
|
||
# 把 value 转为 TypeName|t.CPtr(TypeName* 指针)。TypeName
|
||
# 是类型名(Name/Attribute),不是值表达式——此前被当普通
|
||
# 参数翻译 → NameError: 未定义名称 'memory_block'
|
||
# (VKernel mm.vp merge_blocks 根因)。CType 不是 map_t_type
|
||
# 的具名类型,须在此显式处理,否则跌落到跨模块 FATAL。
|
||
if string.strcmp(func_name, "CType") == 0 and can >= 2:
|
||
cty_node: ast.AST* = cargs.get(1)
|
||
ctype_target: llvmlite.LLVMType* = None
|
||
if cty_node is not None:
|
||
cti_imp: str = None
|
||
cti_fi: str = None
|
||
if trans is not None:
|
||
cti_imp = trans._imported_modules
|
||
cti_fi = trans._from_imports
|
||
ctype_target = self.Gen.TypeGenResolve.resolve_annotation_type(pool, cty_node, cti_imp, cti_fi, trans, 0)
|
||
if ctype_target is not None:
|
||
if can == 3:
|
||
cty_arg3: ast.AST* = cargs.get(2)
|
||
cty_is_cptr: int = 0
|
||
if cty_arg3 is not None:
|
||
# 形式 1: t.CPtr(Attribute)
|
||
if cty_arg3.kind() == ast.ASTKind.Attribute:
|
||
cty_at3: ast.Attribute* = ast.Attribute*(cty_arg3)
|
||
if cty_at3.attr is not None and string.strcmp(cty_at3.attr, "CPtr") == 0:
|
||
if cty_at3.value is not None and cty_at3.value.kind() == ast.ASTKind.Name:
|
||
cty_nm3: ast.Name* = ast.Name*(cty_at3.value)
|
||
if cty_nm3.id is not None and string.strcmp(cty_nm3.id, "t") == 0:
|
||
cty_is_cptr = 1
|
||
# 形式 2: 裸名 CPtr
|
||
elif cty_arg3.kind() == ast.ASTKind.Name:
|
||
cty_bn3: ast.Name* = ast.Name*(cty_arg3)
|
||
if cty_bn3.id is not None and string.strcmp(cty_bn3.id, "CPtr") == 0:
|
||
cty_is_cptr = 1
|
||
if cty_is_cptr != 0:
|
||
# CVoid* → i8*(LLVM 中 void* 表示为 i8*)
|
||
match ctype_target:
|
||
case llvmlite.LLVMType.Void():
|
||
ctype_target = llvmlite.Int8(pool)
|
||
case _:
|
||
pass
|
||
ctype_target = llvmlite.Ptr(pool, ctype_target)
|
||
cty_arg0: ast.AST* = cargs.get(0)
|
||
if cty_arg0 is not None:
|
||
cty_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cty_arg0, funcs_ptr, func_count, trans)
|
||
if cty_val is not None:
|
||
return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, cty_val, ctype_target, cty_arg0, trans)
|
||
# t.CType 语法已确认:即使类型解析失败也不跌落到跨模块 FATAL
|
||
return None
|
||
# CConst const 标记:CConst(val, t.CPtr) → Ptr(i8)(const void*)。
|
||
# CConst 不是 map_t_type 具名类型——t.CConst|char|t.CPtr 注解 =
|
||
# const char*(i8*),显式调用 t.CConst(addr, t.CPtr) 把整数地址转
|
||
# const 指针。此前 map_t_type 失败 → 跌落跨模块函数调用 → 生成
|
||
# call @CConst(裸名,无 obj 定义)→ ld.lld undefined symbol:
|
||
# CConst(elf.vp L650 t.CConst(uint64(strtab_ptr)+sym.st_name,
|
||
# t.CPtr) 根因)。单参 CConst(x) 仅 const 限定,LLVM 类型不变,
|
||
# 直接返回原值。
|
||
if string.strcmp(func_name, "CConst") == 0:
|
||
if can >= 2:
|
||
cconst_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||
cconst_arg: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), funcs_ptr, func_count, trans)
|
||
if cconst_arg is not None:
|
||
return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, cconst_arg, cconst_ptr_ty, cargs.get(0), trans)
|
||
elif can == 1:
|
||
return self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), funcs_ptr, func_count, trans)
|
||
return None
|
||
target_ty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.map_t_type(pool, func_name)
|
||
if target_ty is not None:
|
||
tc_effective_can: sizet = can
|
||
# 双参数形式: int(val, t.CPtr) → Ptr(target_ty)
|
||
# 注意: void* 在 LLVM 中非法,CVoid* 应表示为 i8*
|
||
if can == 2:
|
||
tc_arg2_node: ast.AST* = cargs.get(1)
|
||
tc_arg2_is_cptr: int = 0
|
||
if tc_arg2_node is not None:
|
||
# 形式 1: t.CPtr(Attribute 形式)
|
||
if tc_arg2_node.kind() == ast.ASTKind.Attribute:
|
||
tc_arg2_at: ast.Attribute* = ast.Attribute*(tc_arg2_node)
|
||
if tc_arg2_at.attr is not None and string.strcmp(tc_arg2_at.attr, "CPtr") == 0:
|
||
if tc_arg2_at.value is not None and tc_arg2_at.value.kind() == ast.ASTKind.Name:
|
||
tc_arg2_nm: ast.Name* = ast.Name*(tc_arg2_at.value)
|
||
if tc_arg2_nm.id is not None and string.strcmp(tc_arg2_nm.id, "t") == 0:
|
||
tc_arg2_is_cptr = 1
|
||
# 形式 2: 裸名 CPtr(from t import CPtr 后直接使用,如 t.CXXX(x, CPtr))
|
||
elif tc_arg2_node.kind() == ast.ASTKind.Name:
|
||
tc_arg2_bn: ast.Name* = ast.Name*(tc_arg2_node)
|
||
if tc_arg2_bn.id is not None and string.strcmp(tc_arg2_bn.id, "CPtr") == 0:
|
||
tc_arg2_is_cptr = 1
|
||
if tc_arg2_is_cptr != 0:
|
||
# CVoid* → i8*(LLVM 中 void* 表示为 i8*)
|
||
match target_ty:
|
||
case llvmlite.LLVMType.Void():
|
||
target_ty = llvmlite.Int8(pool)
|
||
case _:
|
||
pass
|
||
target_ty = llvmlite.Ptr(pool, target_ty)
|
||
tc_effective_can = 1
|
||
if tc_effective_can == 1:
|
||
tc_arg_node: ast.AST* = cargs.get(0)
|
||
if tc_arg_node is not None:
|
||
# 第 8 参 target_ty 必须下传:否则常量在
|
||
# translate_constant 里按「是否超出 i32 范围」选位宽,
|
||
# `uint64(0xFFFFFFFFFFFFFFFF)`(词法回绕为 -1)被
|
||
# 物化成 i32 -1 再 zext → 0x00000000FFFFFFFF(N1)。
|
||
tc_arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, tc_arg_node, None, 0, trans, target_ty)
|
||
if tc_arg_val is not None:
|
||
return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, tc_arg_val, target_ty, tc_arg_node, trans)
|
||
# t.XXX 类型转换已确认但不满足参数条件:返回 None,不跌落到跨模块 FATAL
|
||
return None
|
||
|
||
# 模块限定 typedef 转换: posix.mode_t(mode), w32.win32base.HANDLE(v) 等
|
||
# func = Attribute(value=Name(模块), attr=typedef名),此前被误当跨模块函数调用
|
||
# → "跨模块函数 'sha1.mode_t' 返回类型无法精确获取"(SysLibTest os/_posix.vp
|
||
# L130 posix.mode_t(mode) 根因)。typedef 名做类型转换(与裸名 BYTEPTR(x)
|
||
# 对齐);非 typedef 名继续走模块函数调用。
|
||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||
mt_at: ast.Attribute* = ast.Attribute*(cl.func)
|
||
if mt_at.value is not None and mt_at.value.kind() == ast.ASTKind.Name:
|
||
mt_mod_nm: ast.Name* = ast.Name*(mt_at.value)
|
||
if mt_mod_nm.id is not None and string.strcmp(mt_mod_nm.id, "t") != 0 and string.strcmp(mt_mod_nm.id, "c") != 0:
|
||
mod_td_ty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.map_t_type(pool, func_name)
|
||
if mod_td_ty is None:
|
||
mod_td_str: str = self.Gen.TypeGenCType.lookup_ctypedef(func_name)
|
||
if mod_td_str is not None and self.Gen.TypeGenCType.is_ctypedef_found() != 0:
|
||
mod_td_ast: ast.AST* = self.Gen.TypeGenResolve._parse_type_string(pool, mod_td_str, 0)
|
||
if mod_td_ast is not None:
|
||
mod_imp_td: str = None
|
||
mod_fi_td: str = None
|
||
if trans is not None:
|
||
mod_imp_td = trans._imported_modules
|
||
mod_fi_td = trans._from_imports
|
||
mod_td_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, mod_td_ast, mod_imp_td, mod_fi_td, trans, 0)
|
||
if mod_td_ty is not None and can == 1:
|
||
mt_arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), funcs_ptr, func_count, trans, mod_td_ty)
|
||
if mt_arg_val is not None:
|
||
return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, mt_arg_val, mod_td_ty, cargs.get(0), trans)
|
||
|
||
# 裸名 typedef 调用: BYTEPTR(ptr1), HANDLE(val), CHARPTR(str) 等
|
||
# 用户通过 `from stdint import *` 导入 typedef 后,可直接用裸名做类型转换
|
||
# 统一口径:所有 CTypedef 名与 t/c 库原始类型的 call 都具备强转功能
|
||
# (BYTEPTR/HANDLE/size_t 等库 typedef + CInt/CBool 等 t/c 核心原语)。
|
||
# 泛型类型参数转换: 泛型上下文(类特化/泛型函数)中 T(x) → 先解析 T 为具体
|
||
# 类型名(如 "int")再走 resolve_typedef_or_map(Box[int].__init__ 的
|
||
# self.value = T(v)、combine[T1,T2] 的 T1(b) 依赖此路径)
|
||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Name:
|
||
bare_fn_name: str = self.Gen.TypeGenBase.resolve_generic_type_name(func_name)
|
||
bare_ty: llvmlite.LLVMType* = None
|
||
# 泛型上下文解析出的内建名(如 T→"double"/"float"):map_t_type 只认 t.CDouble,
|
||
# 且 float 必须映射 t.CFloat(f32)而非 f64(与注解语义一致)
|
||
if string.strcmp(bare_fn_name, "double") == 0:
|
||
bare_ty = llvmlite.Double(pool)
|
||
elif string.strcmp(bare_fn_name, "float") == 0:
|
||
bare_ty = llvmlite.Float(pool)
|
||
else:
|
||
# 统一口径:CTypedef 动态表优先(BYTEPTR 等库 typedef 强转),
|
||
# miss 回退 map_t_type(t/c 核心原语强转,阶段2 收敛后 map_t_type
|
||
# 不再含 stdint 别名,故必须走动态表)。
|
||
bare_imp_c: str = None
|
||
bare_fi_c: str = None
|
||
if trans is not None:
|
||
bare_imp_c = trans._imported_modules
|
||
bare_fi_c = trans._from_imports
|
||
bare_ty = self.Gen.TypeGenResolve.resolve_typedef_or_map(pool, bare_fn_name, bare_imp_c, bare_fi_c)
|
||
# 泛型上下文替换出的类型名(如 T→"int")map_t_type 不识别(只认无前缀名),
|
||
# 回退用 resolve_annotation_type 解析(支持 t.CXxx / 结构体类名 / 别名等)。
|
||
# GenericTest4 Box[int].__init__ 的 self.value = T(v) 依赖此路径。
|
||
if bare_ty is None and string.strcmp(bare_fn_name, func_name) != 0:
|
||
gp_ast: ast.AST* = self.Gen.TypeGenResolve._parse_type_string(pool, bare_fn_name, 0)
|
||
if gp_ast is not None:
|
||
imp_gp: str = None
|
||
fi_gp: str = None
|
||
if trans is not None:
|
||
imp_gp = trans._imported_modules
|
||
fi_gp = trans._from_imports
|
||
bare_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, gp_ast, imp_gp, fi_gp, trans, 0)
|
||
# 泛型类型参数双参数形式: T(val, t.CPtr) → Ptr(T)
|
||
# (与 int(val, t.CPtr) → Ptr(i32) 对齐;vector.vp get() 的
|
||
# typed_ptr = T(offset, t.CPtr) 依赖此路径,否则双参数不进
|
||
# can==1 单参数分支 → 跌落到"裸名调用未定义"误报)
|
||
if bare_ty is not None and can == 2:
|
||
bare_arg2_node: ast.AST* = cargs.get(1)
|
||
bare_arg2_is_cptr: int = 0
|
||
if bare_arg2_node is not None:
|
||
# 形式 1: t.CPtr(Attribute 形式)
|
||
if bare_arg2_node.kind() == ast.ASTKind.Attribute:
|
||
bare_arg2_at: ast.Attribute* = ast.Attribute*(bare_arg2_node)
|
||
if bare_arg2_at.attr is not None and string.strcmp(bare_arg2_at.attr, "CPtr") == 0:
|
||
if bare_arg2_at.value is not None and bare_arg2_at.value.kind() == ast.ASTKind.Name:
|
||
bare_arg2_nm: ast.Name* = ast.Name*(bare_arg2_at.value)
|
||
if bare_arg2_nm.id is not None and string.strcmp(bare_arg2_nm.id, "t") == 0:
|
||
bare_arg2_is_cptr = 1
|
||
# 形式 2: 裸名 CPtr(from t import CPtr 后直接使用)
|
||
elif bare_arg2_node.kind() == ast.ASTKind.Name:
|
||
bare_arg2_bn: ast.Name* = ast.Name*(bare_arg2_node)
|
||
if bare_arg2_bn.id is not None and string.strcmp(bare_arg2_bn.id, "CPtr") == 0:
|
||
bare_arg2_is_cptr = 1
|
||
if bare_arg2_is_cptr != 0:
|
||
# CVoid* → i8*(LLVM 中 void* 表示为 i8*)
|
||
match bare_ty:
|
||
case llvmlite.LLVMType.Void():
|
||
bare_ty = llvmlite.Int8(pool)
|
||
case _:
|
||
pass
|
||
bare_ty = llvmlite.Ptr(pool, bare_ty)
|
||
bare_arg_node: ast.AST* = cargs.get(0)
|
||
if bare_arg_node is not None:
|
||
bare_arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, bare_arg_node, None, 0, trans, bare_ty)
|
||
if bare_arg_val is not None:
|
||
return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, bare_arg_val, bare_ty, bare_arg_node, trans)
|
||
if bare_ty is not None and can == 1:
|
||
bare_arg_node: ast.AST* = cargs.get(0)
|
||
if bare_arg_node is not None:
|
||
# 第 8 参 target_ty 下传:裸名 typedef 强转(如 uint64(x))的
|
||
# 目标位宽必须参与常量物化(N1)。
|
||
bare_arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, bare_arg_node, None, 0, trans, bare_ty)
|
||
if bare_arg_val is not None:
|
||
return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, bare_arg_val, bare_ty, bare_arg_node, trans)
|
||
|
||
return None
|
||
|
||
def _tc_h5_sizeof_len_isinst(self, pool: memhub.MemBuddy*,
|
||
builder: llvmlite.IRBuilder*,
|
||
mod: llvmlite.LLVMModule*,
|
||
cl: ast.Call*,
|
||
funcs_ptr: t.CPtr,
|
||
func_count: int,
|
||
trans: HT.Translator*,
|
||
func_name: str,
|
||
cargs: list[ast.AST*]*,
|
||
can: sizet) -> llvmlite.Value*:
|
||
"""__sizeof__/len/isinstance 内置(未命中返回 None)"""
|
||
# 检测 ClassName.__sizeof__() — 返回结构体大小常量(i64)
|
||
# __sizeof__ 是内置方法,不走跨模块调用路径
|
||
# 支持: Argument.__sizeof__() 和 w32.win32file.WIN32_FIND_DATAA.__sizeof__()
|
||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||
sz_at: ast.Attribute* = ast.Attribute*(cl.func)
|
||
if sz_at.attr is not None and string.strcmp(sz_at.attr, "__sizeof__") == 0:
|
||
if sz_at.value is not None and can == 0:
|
||
sz_cls_name: str = None
|
||
sz_vk: int = sz_at.value.kind()
|
||
if sz_vk == ast.ASTKind.Name:
|
||
sz_cls_nm2: ast.Name* = ast.Name*(sz_at.value)
|
||
sz_cls_name = sz_cls_nm2.id
|
||
elif sz_vk == ast.ASTKind.Attribute:
|
||
sz_inner_at: ast.Attribute* = ast.Attribute*(sz_at.value)
|
||
sz_cls_name = sz_inner_at.attr
|
||
# 保留完整模块路径(w32.win32base.SECURITY_ATTRIBUTES):
|
||
# 仅取 attr 会在后续 get_struct_type 裸名全局匹配时误命中
|
||
# 跨模块同名类(SECURITY_ATTRIBUTES FieldCount=0 根因)。
|
||
if sz_inner_at.value is not None and sz_inner_at.attr is not None:
|
||
if sz_inner_at.value.kind() == ast.ASTKind.Name:
|
||
sz_inner_nm: ast.Name* = ast.Name*(sz_inner_at.value)
|
||
if sz_inner_nm.id is not None:
|
||
sz_full_len: sizet = string.strlen(sz_inner_nm.id) + 1 + string.strlen(sz_inner_at.attr) + 1
|
||
sz_full_buf: str = pool.alloc(sz_full_len)
|
||
if sz_full_buf is not None:
|
||
sz_full_buf[0] = '\0'
|
||
string.strcat(sz_full_buf, sz_inner_nm.id)
|
||
string.strcat(sz_full_buf, ".")
|
||
string.strcat(sz_full_buf, sz_inner_at.attr)
|
||
sz_cls_name = sz_full_buf
|
||
elif sz_inner_at.value.kind() == ast.ASTKind.Attribute:
|
||
sz_mod_path: str = self.Gen.ExprGenAttr._attr_module_path_str(pool, sz_inner_at.value)
|
||
if sz_mod_path is not None:
|
||
sz_full_len2: sizet = string.strlen(sz_mod_path) + 1 + string.strlen(sz_inner_at.attr) + 1
|
||
sz_full_buf2: str = pool.alloc(sz_full_len2)
|
||
if sz_full_buf2 is not None:
|
||
sz_full_buf2[0] = '\0'
|
||
string.strcat(sz_full_buf2, sz_mod_path)
|
||
string.strcat(sz_full_buf2, ".")
|
||
string.strcat(sz_full_buf2, sz_inner_at.attr)
|
||
sz_cls_name = sz_full_buf2
|
||
# 最终解析出的结构体类型:类型名命中 → 泛型特化(Stack[T])→ 实例接收者类型(self/obj)
|
||
sz_resolved_ty: llvmlite.LLVMType* = None
|
||
sz_resolved_name: str = sz_cls_name
|
||
if sz_cls_name is not None:
|
||
# 泛型类型参数 T 替换: T.__sizeof__() → int.__sizeof__()
|
||
sz_orig: str = sz_cls_name
|
||
sz_cls_name = self.Gen.TypeGenBase.resolve_generic_type_name(sz_cls_name)
|
||
# 兜底:TypeGenBase 上下文为空时(模板 tp_names 跨 phase 失效),
|
||
# 直接用 trans 的泛型映射替换 T(list[int] 单态化 _list.vp
|
||
# T.__sizeof__ 根因)。
|
||
if string.strcmp(sz_cls_name, sz_orig) == 0 and trans is not None and trans.GenericTypeParamNames is not None and trans.GenericTypeArgs is not None:
|
||
gp_n: sizet = len(trans.GenericTypeParamNames)
|
||
gp_i: sizet
|
||
for gp_i in range(gp_n):
|
||
gpn: str = trans.GenericTypeParamNames.get(gp_i)
|
||
if gpn is not None and string.strcmp(sz_orig, gpn) == 0:
|
||
gta: str = trans.GenericTypeArgs.get(gp_i)
|
||
if gta is not None:
|
||
sz_cls_name = gta
|
||
break
|
||
sz_resolved_name = sz_cls_name
|
||
# 指针包装类型检查必须在 dot-strip 之前:类型实参可能带 sha1
|
||
# 前缀内嵌点号(rawptr[7565e081d88517ac.AST]、f4679...AST|t.CPtr),
|
||
# strrchr('.') 会把括号内 ".AST"/".CPtr" 剥掉 → "AST]"/"CPtr",
|
||
# 前缀/联合判断永远失配 → 落回把接收者 Name(T) 当实例翻译 →
|
||
# NameError: 未定义名称 'T'(SlotsBugTest rawptr[list[rawptr[AST]]] 根因)。
|
||
# 联合类型(X | t.CPtr)与新一代指针包装 rawptr[X] 均按指针大小 8。
|
||
if string.strstr(sz_cls_name, "|") is not None:
|
||
return llvmlite.const_int64(pool, 8)
|
||
if string.strncmp(sz_cls_name, "rawptr[", 7) == 0:
|
||
return llvmlite.const_int64(pool, 8)
|
||
# 归一后的指针唯一规范形 `T*`(TypeGenResolve._norm_type_arg_name
|
||
# 的指针书写归一:rawptr[T] ≡ t.CPtr[T] ≡ T|t.CPtr ≡ T*)
|
||
# ⇒ **尾随** '*' 一律按指针大小 8(多级 `**` 同为 8)。
|
||
# 判据必须是"尾随",不能用 strrchr:接收者是
|
||
# `list[{sha}.AST*]`(元素为指针的容器)时串内也含 '*',
|
||
# strrchr 会把它误判成指针并返回 8(容器大小 ≠ 8)。
|
||
# 缺本判据时 `T.__sizeof__()` 的实参串 `{sha}.AST*` 既不命中
|
||
# '|' 也不命中 'rawptr[',落回把接收者 Name(T) 当实例翻译 →
|
||
# NameError: 未定义名称 'T'(现场 Test/AstTest/App/main.vp:21
|
||
# 特化 list[ast.AST|t.CPtr] → includes/_list.vp:36)。
|
||
_sz_len_s: sizet = string.strlen(sz_cls_name)
|
||
while _sz_len_s > 0 and sz_cls_name[_sz_len_s - 1] == ' ':
|
||
_sz_len_s -= 1
|
||
if _sz_len_s > 0 and sz_cls_name[_sz_len_s - 1] == '*':
|
||
return llvmlite.const_int64(pool, 8)
|
||
# 保存完整名(含模块前缀)供模块归属精确匹配:去前缀后
|
||
# get_struct_type 裸名全局匹配会误命中跨模块同名类
|
||
# (w32.win32base.SECURITY_ATTRIBUTES 根因)。
|
||
sz_full_name: str = sz_cls_name
|
||
# 去除模块前缀: Viper 解析器将 int 解析为 Name(id="int")
|
||
# 而非 Attribute(value=Name("t"), attr="CInt"),需要手动提取最后的类名分量
|
||
# "int" → "CInt", "w32.win32file.WIN32_FIND_DATAA" → "WIN32_FIND_DATAA"
|
||
dot_pos: str = string.strrchr(sz_cls_name, '.')
|
||
if dot_pos is not None:
|
||
sz_cls_name = dot_pos + 1
|
||
# [阶段3] 统一尺寸口径:库 typedef(BYTE/DWORD 等)先经正常
|
||
# 库分析解析(resolve_typedef_or_map → 位宽/8),miss 才走
|
||
# 下方硬编码尺寸表(t/c 核心原语)。
|
||
# 必须传入 trans 的 from_imports/imported_modules:本模块 typedef
|
||
# 值可能引用 from-import 别名(MyWord: t.CTypedef = MyInt,
|
||
# MyInt 来自 from t import CInt as MyInt),不传则别名链解析失败
|
||
# → get_type_size_bytes 返回 0 → 落到"回退 2"把 Name 当值翻译
|
||
# → NameError: 未定义名称 'MyWord'(T8 根因)。
|
||
dyn_sz_c: int = self.Gen.TypeGenResolve.get_type_size_bytes(pool, sz_cls_name,
|
||
trans._imported_modules if trans is not None else None,
|
||
trans._from_imports if trans is not None else None)
|
||
if dyn_sz_c > 0:
|
||
return llvmlite.const_int64(pool, dyn_sz_c)
|
||
# 内置类型 sizeof(int=4, str/bytes=8 指针, double=8 等)
|
||
sz_builtin: int = -1
|
||
if string.strcmp(sz_cls_name, "int") == 0: sz_builtin = 4
|
||
elif string.strcmp(sz_cls_name, "str") == 0: sz_builtin = 8
|
||
elif string.strcmp(sz_cls_name, "bytes") == 0: sz_builtin = 8
|
||
elif string.strcmp(sz_cls_name, "CInt") == 0: sz_builtin = 4
|
||
elif string.strcmp(sz_cls_name, "CInt8T") == 0: sz_builtin = 1
|
||
elif string.strcmp(sz_cls_name, "CInt16T") == 0: sz_builtin = 2
|
||
elif string.strcmp(sz_cls_name, "CInt32T") == 0: sz_builtin = 4
|
||
elif string.strcmp(sz_cls_name, "CInt64T") == 0: sz_builtin = 8
|
||
elif string.strcmp(sz_cls_name, "CChar") == 0: sz_builtin = 1
|
||
elif string.strcmp(sz_cls_name, "CDouble") == 0: sz_builtin = 8
|
||
elif string.strcmp(sz_cls_name, "CFloat") == 0: sz_builtin = 4
|
||
elif string.strcmp(sz_cls_name, "CPtr") == 0: sz_builtin = 8
|
||
elif string.strcmp(sz_cls_name, "CSizeT") == 0: sz_builtin = 8
|
||
elif string.strcmp(sz_cls_name, "CBool") == 0: sz_builtin = 1
|
||
elif string.strcmp(sz_cls_name, "bool") == 0: sz_builtin = 1
|
||
# 泛型 T 解析出的裸内建名(resolve_generic_type_name 返回
|
||
# _infer_generic_ctor_type_arg 的输出,如 T→"double"/"float"):
|
||
# 缺省会让 sz_builtin=-1 → 落到"回退 2"把 Name(T) 当值翻译 →
|
||
# NameError(VectorGenericTest Vector[double].__init__ 回归根因)
|
||
elif string.strcmp(sz_cls_name, "double") == 0: sz_builtin = 8
|
||
elif string.strcmp(sz_cls_name, "float") == 0: sz_builtin = 4
|
||
elif string.strcmp(sz_cls_name, "char") == 0: sz_builtin = 1
|
||
if sz_builtin >= 0:
|
||
# 注意: 必须用 const_int64 而非 ConstInt(...,"0")
|
||
# ConstInt 的 name 参数是 IR 文本表示,ValuePrint 输出时使用 Name 而非 IntVal
|
||
# 硬编码 "0" 会导致 IR 输出 i64 0 而非实际值
|
||
return llvmlite.const_int64(pool, sz_builtin)
|
||
sz_resolved_ty = None
|
||
# 模块限定类(w32.win32base.SECURITY_ATTRIBUTES):模块归属
|
||
# 精确匹配定义侧结构体,防裸名全局匹配误命中跨模块同名类
|
||
# (SECURITY_ATTRIBUTES 注册于 e710 但期望 a335 根因)。
|
||
if sz_full_name is not None:
|
||
szf_dot: str = string.strrchr(sz_full_name, '.')
|
||
if szf_dot is not None:
|
||
szf_mod_len: sizet = sizet(uint64(szf_dot) - uint64(sz_full_name))
|
||
szf_mod: str = pool.alloc(szf_mod_len + 1)
|
||
if szf_mod is not None:
|
||
string.strncpy(szf_mod, sz_full_name, szf_mod_len)
|
||
szf_mod[szf_mod_len] = '\0'
|
||
# t/c 内置库豁免(int 等已由内建/尺寸表处理)
|
||
if string.strcmp(szf_mod, "t") != 0 and string.strcmp(szf_mod, "c") != 0:
|
||
szf_sha1: str = self.Gen.StructGen._resolve_module_sha1(szf_mod, trans._from_imports if trans is not None else None)
|
||
if szf_sha1 is not None:
|
||
szf_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(sz_cls_name, szf_sha1)
|
||
if szf_entry is not None and szf_entry.Ty is not None:
|
||
sz_resolved_ty = szf_entry.Ty
|
||
if sz_resolved_ty is None:
|
||
sz_resolved_ty = self.Gen.StructGen.get_struct_type(sz_cls_name)
|
||
# 回退 1: 泛型类引用接收者 Stack[T].__sizeof__() — Subscript → 特化后计算大小
|
||
# (GenericTest2 Stack.type_size 依赖此路径)
|
||
if sz_resolved_ty is None and trans is not None and sz_vk == ast.ASTKind.Subscript:
|
||
sub_sz: ast.Subscript* = ast.Subscript*(sz_at.value)
|
||
if sub_sz.value is not None and sub_sz.value.kind() == ast.ASTKind.Name:
|
||
gen_nm_sz: ast.Name* = ast.Name*(sub_sz.value)
|
||
if gen_nm_sz.id is not None:
|
||
gen_args_sz: list[str]* = self.Gen.CallGenCtor._extract_type_args_from_slice(pool, sub_sz.slice, trans._from_imports)
|
||
if gen_args_sz is not None and len(gen_args_sz) > 0:
|
||
gargs_resolved: list[str]* = list[str](pool, 8)
|
||
if gargs_resolved is not None:
|
||
gai_sz: sizet = len(gen_args_sz)
|
||
gai2_sz: sizet = 0
|
||
for gai2_sz in range(gai_sz):
|
||
gres_sz: str = self.Gen.TypeGenBase.resolve_generic_type_name(gen_args_sz.get(gai2_sz))
|
||
gargs_resolved.append(gres_sz)
|
||
spec_sz: str = self.Gen.ClassGenGeneric._specialize_generic_class(trans, gen_nm_sz.id, gargs_resolved)
|
||
if spec_sz is not None:
|
||
sz_resolved_name = spec_sz
|
||
sz_resolved_ty = self.Gen.StructGen.get_struct_type(spec_sz)
|
||
# 回退 2: 实例接收者 self.__sizeof__() / obj.__sizeof__() — 用接收者值的实际类型
|
||
# (GenericTest2 Stack.size_of 依赖此路径;self 在方法内是 Ptr(Stack[int]))
|
||
# 数组变量接收者 bl_count.__sizeof__()(t.CArray[T, N] 变量)→ alloca
|
||
# 指针 Ptr([N x T]),算 N*elem_size(TPC _HandleSizeofLlvm 数组分支;
|
||
# zhuff.vp memset(bl_count, 0, bl_count.__sizeof__()) 依赖)
|
||
if sz_resolved_ty is None:
|
||
inst_sz_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sz_at.value, None, 0, trans)
|
||
if inst_sz_val is not None and inst_sz_val.Ty is not None:
|
||
match inst_sz_val.Ty:
|
||
case llvmlite.LLVMType.Ptr(inst_inner_sz):
|
||
match inst_inner_sz:
|
||
case llvmlite.LLVMType.Struct(_, _, _):
|
||
sz_resolved_ty = inst_inner_sz
|
||
case llvmlite.LLVMType.Array(_, _):
|
||
sz_resolved_ty = inst_inner_sz
|
||
case _:
|
||
pass
|
||
case llvmlite.LLVMType.Struct(_, _, _):
|
||
sz_resolved_ty = inst_sz_val.Ty
|
||
case llvmlite.LLVMType.Array(_, _):
|
||
# 全局数组变量(模块级 t.CArray[T,N])translate_value
|
||
# 返回数组值 [N x T](非指针);局部数组返回 alloca
|
||
# 指针 Ptr([N x T]) 走上方 Ptr(Array) 分支。
|
||
# pyzlib_error_msg.__sizeof__() 依赖(全局字符缓冲)。
|
||
sz_resolved_ty = inst_sz_val.Ty
|
||
case _:
|
||
pass
|
||
if sz_resolved_ty is not None:
|
||
sz_val: int = self.Gen.ClassGenEnum._get_type_size(sz_resolved_ty)
|
||
if sz_val > 0:
|
||
return llvmlite.const_int64(pool, sz_val)
|
||
# 类型已注册但大小为 0(opaque struct 或字段链表未填充):Python 风格报错终止
|
||
self.Gen.TypeGenErr.fatal_error(sz_at, f"类型 '{sz_resolved_name}' 已注册但大小为 0(字段链表未填充),无法计算大小", "TypeError")
|
||
# 类型未注册:Python 风格报错终止,不静默返回 0(会导致 malloc(0)/alloc(0) 堆溢出)
|
||
if sz_resolved_name is None:
|
||
sz_resolved_name = "(unknown)"
|
||
self.Gen.TypeGenErr.fatal_error(sz_at, f"类型 '{sz_resolved_name}' 未在结构体表中注册,无法计算大小", "TypeError")
|
||
|
||
# 检测 len(obj) — 返回 list 对象的 __count__ 字段(偏移 8,i64)
|
||
# __len__ 是 list[T] 的内置方法,list 是泛型类不注册 struct
|
||
# 注意: 必须用 translate_value 而非 translate_name_value,因为 len_at.value
|
||
# 可能是 Attribute 节点(如 md_ags.args),translate_name_value 只处理 Name 节点,
|
||
# 对 Attribute 会错误返回 i32 0,导致 GEP base 不是指针(base of getelementptr must be a pointer)
|
||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||
len_at: ast.Attribute* = ast.Attribute*(cl.func)
|
||
if len_at.attr is not None and string.strcmp(len_at.attr, "__len__") == 0:
|
||
if len_at.value is not None and can == 0:
|
||
obj_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, len_at.value, funcs_ptr, func_count, trans)
|
||
if obj_val is not None and obj_val.Ty is not None:
|
||
# 防御性类型检查: obj_val 必须是指针类型才能做 GEP
|
||
# 如果 translate_value 返回 i32 (如 CDefine 常量被误解析、
|
||
# 模块属性前向引用回退为 i32),GEP base 会是 i32 而非指针,
|
||
# 导致 llc 报错 "base of getelementptr must be a pointer"
|
||
if self.Gen.ExprGenBase.is_ptr_type(obj_val.Ty) == 0:
|
||
# 类型推断失败(非指针/结构体):fail-fast,绝不返回 0 掩盖错误
|
||
self.Gen.TypeGenErr.fatal_error(len_at.value, "len() 参数类型推断失败(非指针/结构体)", "TypeError")
|
||
i64_ty_len: llvmlite.LLVMType* = llvmlite.Int64(pool)
|
||
# 注意: 必须用 const_int64 而非 ConstInt(...,"0")
|
||
# ConstInt 的 name 参数 "0" 会被当作 IR 文本值输出 i64 0
|
||
# 导致 GEP 索引为 0(访问 __data__)而非 1(访问 __count__)
|
||
idx_one: llvmlite.Value* = llvmlite.const_int64(pool, 1)
|
||
count_ptr: llvmlite.Value* = llvmlite.build_gep(builder, i64_ty_len, obj_val, idx_one)
|
||
if count_ptr is not None:
|
||
return llvmlite.build_load(builder, i64_ty_len, count_ptr)
|
||
|
||
# 检测 len() 内置函数调用 — 结构体对象走 __len__ 方法,字符串走 strlen
|
||
# len(s) 对 str 类型调用 strlen,返回 i64
|
||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Name:
|
||
if func_name is not None and string.strcmp(func_name, "len") == 0:
|
||
if can == 1:
|
||
len_arg_node: ast.AST* = cargs.get(0)
|
||
if len_arg_node is not None:
|
||
len_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, len_arg_node, None, 0, trans)
|
||
if len_val is not None:
|
||
# len(数组):t.CArray[T, N] → 常量 N(对齐 TPC
|
||
# _HandleLenLlvm 的 ArrayType.count 分支)。数组变量
|
||
# translate_value 可能返回 Ptr([N x T])(alloca 指针)
|
||
# 或 [N x T] 值,两种都识别;否则会误走 strlen 把
|
||
# 数组首元素当字符串读 → 垃圾长度。
|
||
len_is_arr: int = 0
|
||
len_arr_n: int = 0
|
||
if len_val.Ty is not None:
|
||
if self.Gen.ExprGenBase.is_ptr_type(len_val.Ty) != 0:
|
||
len_ap: llvmlite.LLVMType* = len_val.Ty.Pointee
|
||
if len_ap is not None:
|
||
match len_ap:
|
||
case llvmlite.LLVMType.Array(_, len_arr_cnt):
|
||
len_is_arr = 1
|
||
len_arr_n = len_arr_cnt
|
||
case _:
|
||
pass
|
||
else:
|
||
match len_val.Ty:
|
||
case llvmlite.LLVMType.Array(_, len_arr_cnt):
|
||
len_is_arr = 1
|
||
len_arr_n = len_arr_cnt
|
||
case _:
|
||
pass
|
||
if len_is_arr != 0:
|
||
return llvmlite.const_int64(pool, len_arr_n)
|
||
# len(对象):有 __len__ 就调用,没有就编译期报错
|
||
# (用户要求 2026-08-15,不再静默 strlen 读对象首字段):
|
||
# - list 泛型内置容器:__len__ 由 list 内置分支内联
|
||
# (读 __count__,偏移 1),不生成方法函数
|
||
# (_is_list_builtin_method,通用判断非特判)
|
||
# - 普通类:调用 {Class}.__len__ 函数
|
||
# - 都没有:fatal_error
|
||
# str(Ptr(Int8))保持 strlen(内建语义)。
|
||
len_struct_ty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(len_val)
|
||
if len_struct_ty is not None:
|
||
len_cls_nm: str = self.Gen.StructGen.get_class_name_by_type(pool, len_struct_ty)
|
||
if len_cls_nm is None:
|
||
self.Gen.TypeGenErr.fatal_error(len_arg_node, "len() 参数类型推断失败(结构体类名未知)", "TypeError")
|
||
# list 内置 __len__:读 __count__(GEP 偏移 1,i64)
|
||
# 判据优先取接收者实际类型(_is_list_builtin_receiver)
|
||
# 目标类型已由 can==1(len 的实参存在)确定为表达式节点
|
||
# ⇒ 在此显式窄化:形参是 ast.Call*(仅用于 fail-fast
|
||
# 定位节点),而 len_arg_node 声明为基类 ast.AST*;
|
||
# 基类指针传派生类形参属向下转型,严格指针规则下禁止。
|
||
len_arg_cl: ast.Call* = ast.Call*(len_arg_node)
|
||
if self.Gen.CallGenProp._is_list_builtin_receiver(pool, len_val, len_cls_nm, "__len__", len_arg_cl) != 0:
|
||
i64_ty_lb: llvmlite.LLVMType* = llvmlite.Int64(pool)
|
||
idx_one_lb: llvmlite.Value* = llvmlite.const_int64(pool, 1)
|
||
cnt_ptr_lb: llvmlite.Value* = llvmlite.build_gep(builder, i64_ty_lb, len_val, idx_one_lb)
|
||
if cnt_ptr_lb is not None:
|
||
return llvmlite.build_load(builder, i64_ty_lb, cnt_ptr_lb)
|
||
len_lookup: str = pool.alloc(128)
|
||
if len_lookup is not None:
|
||
viperlib.snprintf(len_lookup, 128, "%s.__len__", len_cls_nm)
|
||
len_fn2: llvmlite.Function* = self.find_func_in_module(mod, len_lookup)
|
||
if len_fn2 is not None:
|
||
len_ret_ty2: llvmlite.LLVMType* = llvmlite.function_get_ret_ty(len_fn2)
|
||
len_fn_name2: str = llvmlite.function_get_name(len_fn2)
|
||
if len_ret_ty2 is not None and len_fn_name2 is not None:
|
||
# self 参数类型对齐(按方法首个形参 bitcast)
|
||
len_self_arg2: llvmlite.Value* = len_val
|
||
len_first_param2: llvmlite.Param* = llvmlite.function_get_param_head(len_fn2)
|
||
if len_first_param2 is not None:
|
||
len_self_ty2: llvmlite.LLVMType* = llvmlite.param_get_ty(len_first_param2)
|
||
if len_self_ty2 is not None and len_val.Ty is not None:
|
||
len_self_arg2 = llvmlite.build_bitcast(builder, len_val, len_self_ty2)
|
||
len_self_arg2.Next = None
|
||
return llvmlite.build_call(builder, len_fn_name2, len_self_arg2, 1, len_ret_ty2, 0)
|
||
# len_fn2 未命中(跨模块方法):如 ndarray[t.CDouble].__len__
|
||
# 定义在 numpy——泛型特化方法无 stub declare,find_func_in_module
|
||
# 后缀匹配查不到。用结构体所属模块 sha1 构造
|
||
# {sha1}.{cls}.__len__ 精确调用名(对齐 _translate_method_call
|
||
# 跨模块调用名构造),返回类型从 text.ll/vpi 精确解析,
|
||
# _ensure_method_declare 建 declare 后调用。
|
||
len_cls_sha1_x: str = self.Gen.StructGen.get_struct_sha1(len_cls_nm)
|
||
if len_cls_sha1_x is not None:
|
||
# 缓冲区需容纳 "{sha1}.{cls}.__len__":
|
||
# 2 个点 + "__len__"(7) + NUL = 10;+8 会截断
|
||
# 末两位 → 符号变 ".__len" 链接 undefined
|
||
# (NumpyTest test_len 链接错误根因)
|
||
len_ml_x: sizet = string.strlen(len_cls_sha1_x) + string.strlen(len_cls_nm) + 10
|
||
len_mangled_x: str = pool.alloc(len_ml_x)
|
||
if len_mangled_x is not None:
|
||
viperlib.snprintf(len_mangled_x, len_ml_x, "%s.%s.__len__", len_cls_sha1_x, len_cls_nm)
|
||
len_ret_x: llvmlite.LLVMType* = self._LookupMethodRetTyFromTextLL(pool, len_cls_sha1_x, len_cls_nm, "__len__")
|
||
if len_ret_x is None:
|
||
len_ret_x = self._lookup_method_ret_ty_via_vpi(pool, len_cls_sha1_x, len_cls_nm, "__len__")
|
||
if len_ret_x is not None:
|
||
# self 参数按对象实际类型 Ptr(len_struct_ty)(与定义侧
|
||
# 同名类型链接匹配);len_val 已是 load 后的对象指针。
|
||
# Value 链直接作 param_head(同跨模块调用模式)。
|
||
len_self_x: llvmlite.Value* = len_val
|
||
len_self_x.Next = None
|
||
self._ensure_method_declare(pool, mod, len_mangled_x, len_ret_x, len_self_x, 1)
|
||
return llvmlite.build_call(builder, len_mangled_x, len_self_x, 1, len_ret_x, 0)
|
||
# fail-fast:类没有 __len__(用户要求编译期报错)
|
||
# 报文措辞与 TPC HandlesExprBuiltin._FailFastLenUnsupported 逐字对齐
|
||
self.Gen.TypeGenErr.fatal_error(len_arg_node, f"len() 参数类型 '{len_cls_nm}' 没有 __len__ 方法。len() 只支持定长数组/数组指针(t.CArray[T, N])、i8*(str/bytes)或带 __len__ 的结构体;非 i8 裸指针/标量指针没有长度语义:字符串请用 str/bytes,需要元素个数请自行记录长度,或改用 t.CPtr[元素] 并显式维护元素计数", "TypeError")
|
||
# 非结构体:str(Ptr(Int8))走 strlen;其它类型 fail-fast
|
||
len_arg_ty: llvmlite.LLVMType* = llvmlite.value_get_ty(len_val)
|
||
len_is_str: int = 0
|
||
if len_arg_ty is not None and self.Gen.ExprGenBase.is_ptr_type(len_arg_ty) != 0:
|
||
match len_arg_ty:
|
||
case llvmlite.LLVMType.Ptr(len_pt_ty):
|
||
if len_pt_ty is not None:
|
||
match len_pt_ty:
|
||
case llvmlite.LLVMType.Int(len_pt_bits):
|
||
if len_pt_bits == 8:
|
||
len_is_str = 1
|
||
case _:
|
||
pass
|
||
case _:
|
||
pass
|
||
if len_is_str != 0:
|
||
# 确保 strlen 在模块中有声明
|
||
strlen_fn: llvmlite.Function* = self.find_func_in_module(mod, "strlen")
|
||
if strlen_fn is None:
|
||
i64_ty_ln: llvmlite.LLVMType* = llvmlite.Int64(pool)
|
||
i8_ptr_ty_ln: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||
strlen_fn = llvmlite.create_declare(pool, mod, "strlen", i64_ty_ln)
|
||
if strlen_fn is not None:
|
||
llvmlite.add_param(pool, strlen_fn, i8_ptr_ty_ln, "s")
|
||
# 参数类型转换为 i8*
|
||
i8_ptr_ty_ln2: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||
len_coerced: llvmlite.Value* = len_val
|
||
if self.Gen.ExprGenBase.is_ptr_type(len_arg_ty) != 0:
|
||
len_coerced = llvmlite.build_bitcast(builder, len_val, i8_ptr_ty_ln2)
|
||
# 构建单参数链表并调用 strlen
|
||
len_coerced.Next = None
|
||
i64_ty_ln2: llvmlite.LLVMType* = llvmlite.Int64(pool)
|
||
return llvmlite.build_call(builder, "strlen", len_coerced, 1, i64_ty_ln2, 0)
|
||
# fail-fast:非字符串/数组/对象,无法求长度
|
||
# 报文措辞与 TPC HandlesExprBuiltin._FailFastLenUnsupported 逐字对齐
|
||
self.Gen.TypeGenErr.fatal_error(len_arg_node, "len() 参数类型不支持(非字符串/数组/对象)。len() 只支持定长数组/数组指针(t.CArray[T, N])、i8*(str/bytes)或带 __len__ 的结构体;非 i8 裸指针/标量指针没有长度语义:字符串请用 str/bytes,需要元素个数请自行记录长度,或改用 t.CPtr[元素] 并显式维护元素计数", "TypeError")
|
||
|
||
# 检测 isinstance() 内置函数调用 — 运行时 vtable 子类集合比较
|
||
# isinstance(obj, Cls):obj 头部 vtable 指针 ∈ {Cls 及全部子类 vtable};
|
||
# NoVTable 目标类回退编译时静态判断(详见 _translate_isinstance)。
|
||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Name:
|
||
if func_name is not None and string.strcmp(func_name, "isinstance") == 0:
|
||
if can >= 2:
|
||
is_res: llvmlite.Value* = self.Gen.CallGenLeafKit._translate_isinstance(pool, builder, mod, cargs.get(0), cargs.get(1), trans)
|
||
if is_res is not None:
|
||
return is_res
|
||
|
||
return None
|
||
|
||
def _tc_h6_method_dispatch(self, pool: memhub.MemBuddy*,
|
||
builder: llvmlite.IRBuilder*,
|
||
mod: llvmlite.LLVMModule*,
|
||
cl: ast.Call*,
|
||
funcs_ptr: t.CPtr,
|
||
func_count: int,
|
||
trans: HT.Translator*,
|
||
func_name: str,
|
||
cargs: list[ast.AST*]*,
|
||
can: sizet,
|
||
hit_box: t.CPtr = None) -> llvmlite.Value*:
|
||
"""静态类/方法调用/表达式接收者/self.field/list 内置(未命中返回 None)
|
||
|
||
hit_box: 命中标记(t.CPtr,[0]=1 表示已识别为方法调用路径)。
|
||
编译器生成方法(如 __before_init__/__init__)恒返回 void,
|
||
_translate_method_call 处理后返回 None(无返回值)——若不标记,
|
||
translate_call 会误判"未命中"继续走跨模块函数路径(把对象名
|
||
当模块名查 SHA1 → "跨模块调用 'buf.__before_init__' 找不到模块 SHA1")。
|
||
"""
|
||
# REnum.kind() 编译期转 __tag 读取(字段偏移 0;类型取 __tag 的字段声明类型):
|
||
# REnum 无 kind 方法(源码无、编译器不生成),此前 .kind() 被方法查找
|
||
# 兜底误绑到 ast.AST.kind(this 偏移,语义错误)。此处直接翻译为
|
||
# bitcast obj 到 __tag* + load —— 零函数调用,返回变体 tag。
|
||
# REnum 判据四条并列(缺一即整条分支被跳过 ⇒ .kind() 掉进通用调用路径、
|
||
# 返回类型落空 ⇒ 报「指针隐式转整数」):
|
||
# ① 变体表 _is_renum_class_name ② struct 带 __tag:_is_renum_by_entry
|
||
# ③ pointee 结构体带 __tag(类型版,不需要类名)
|
||
# ④ 接收者 `X.field` 时按 X 的注解 + 字段声明类型反推 pointee 类名
|
||
# ③④ 的存在理由:变体表是 per-Generator 实例字段(ClassGenEnum:811-816:
|
||
# InitClassGen 每个 Generator 重置),跨模块 stub 路径又明确跳过 REnum 注册
|
||
# (VpiReader:2637-2643);且字段访问可能把类型整体退化掉。
|
||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||
rk_at: ast.Attribute* = ast.Attribute*(cl.func)
|
||
if rk_at is not None and rk_at.attr is not None and string.strcmp(rk_at.attr, "kind") == 0:
|
||
rk_obj: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, rk_at.value, None, 0, trans)
|
||
if rk_obj is not None and rk_obj.Ty is not None:
|
||
rk_ty: llvmlite.LLVMType* = rk_obj.Ty
|
||
rk_load: int = 0
|
||
rk_cls: str = None
|
||
rk_pointee: llvmlite.LLVMType* = None
|
||
# rk_is_rn:是否已判定为 REnum。与 rk_cls 解耦——判据不再只依赖类名/变体表。
|
||
rk_is_rn: int = 0
|
||
# rk_tag_ty:kind() 的返回类型真源 = __tag 的**字段声明类型**
|
||
# (FieldEntry.Ty)。默认先放 i32 只为"取不到字段条目"时的等效值
|
||
# ——__tag 全仓只有一处写入(ClassGenEnum:1009
|
||
# add_field(entry, "__tag", Int32)),故取不到时 i32 必等价;
|
||
# 取到则以字段声明类型为准,将来 __tag 换宽度不会静默失配。
|
||
rk_tag_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
|
||
if self.Gen.ExprGenBase.is_ptr_type(rk_ty) != 0:
|
||
rk_pointee = rk_ty.Pointee
|
||
# 联合简化双指针(Ptr(Ptr(Struct)))→ 解一层 + load
|
||
if rk_pointee is not None and self.Gen.ExprGenBase.is_ptr_type(rk_pointee) != 0:
|
||
rk_pointee = rk_pointee.Pointee
|
||
rk_load = 1
|
||
rk_cls = self.Gen.StructGen.get_class_name_by_type(pool, rk_pointee)
|
||
# 判据三条并列(此前只认变体表这一条):
|
||
# 1) 变体表命中:_is_renum_class_name
|
||
# 2) struct 带 __tag:_is_renum_by_entry(表缺失时的既有判据,
|
||
# 与 CallGenMixin:426-427 同口径)
|
||
# 3) 类名反查不到(跨模块 struct 未命名/名称退化)但 pointee 结构体
|
||
# 带 __tag ⇒ 必是 REnum(_is_renum_by_entry 的类型版,不需要类名)
|
||
# 背景:变体表是 per-Generator 实例字段(ClassGenEnum:811-816 注释:
|
||
# InitClassGen 每个 Generator 重置),跨模块 stub 路径又明确跳过
|
||
# REnum 注册(VpiReader:2637-2643)⇒「表里没有 LLVMType」是常态。
|
||
# 只认表会让整条 kind() 分支被跳过 ⇒ .kind() 掉进通用调用路径、返回
|
||
# 类型落空(实况:CallGenLib.vp:355 `vk_a: int = val.Ty.kind()` 报
|
||
# 「指针隐式转整数已禁止」)。
|
||
if rk_cls is not None:
|
||
if self.Gen.ClassGenEnum._is_renum_class_name(rk_cls) != 0 or self.Gen.ClassGenEnum._is_renum_by_entry(rk_cls) != 0:
|
||
rk_is_rn = 1
|
||
else:
|
||
rk_cls = None
|
||
# ③:类名反查不到也不要紧——直接看 pointee 结构体带不带 __tag。
|
||
# 顺带把 __tag 的字段声明类型记为 kind() 返回类型真源(第 2 层)。
|
||
rk_tag_fe: GenTypes.FieldEntry* = None
|
||
if rk_pointee is not None:
|
||
rk_tag_fe = self.Gen.StructGen.lookup_field(rk_pointee, "__tag")
|
||
if rk_is_rn == 0 and rk_tag_fe is not None:
|
||
rk_is_rn = 1
|
||
if rk_tag_fe is not None and rk_tag_fe.Ty is not None:
|
||
rk_tag_ty = rk_tag_fe.Ty
|
||
# 注解兜底:联合简化/退化后运行时类型丢失(如
|
||
# resolved: llvmlite.LLVMType* 存 i8*,pointee 非
|
||
# 结构体),用变量注解类名识别 REnum 类(kind() 语义:
|
||
# 读 __tag,bitcast 对象到 i32* + load)。
|
||
if rk_is_rn == 0 and rk_at.value is not None and rk_at.value.kind() == ast.ASTKind.Name and trans is not None:
|
||
rk_nm: ast.Name* = ast.Name*(rk_at.value)
|
||
if rk_nm.id is not None:
|
||
rk_ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, rk_nm.id)
|
||
rk_annot_raw: str = self.Gen.VarGen.var_annot_class_name(rk_ve)
|
||
if rk_annot_raw is not None:
|
||
# 截断联合/泛型后缀(" | t.CPtr" / "[...]")
|
||
rk_ae: sizet = 0
|
||
while rk_annot_raw[rk_ae] != '\0' and rk_annot_raw[rk_ae] != ' ' and rk_annot_raw[rk_ae] != '|' and rk_annot_raw[rk_ae] != '[':
|
||
rk_ae += 1
|
||
rk_ab: str = pool.alloc(rk_ae + 1)
|
||
if rk_ab is not None:
|
||
string.strncpy(rk_ab, rk_annot_raw, rk_ae)
|
||
rk_ab[rk_ae] = '\0'
|
||
# 去模块前缀("llvmlite.LLVMType" → "LLVMType")
|
||
rk_ad: str = string.strrchr(rk_ab, '.')
|
||
if rk_ad is not None and rk_ad[1] != '\0':
|
||
rk_cls = rk_ad + 1
|
||
else:
|
||
rk_cls = rk_ab
|
||
# 判据同上(表 或 struct 带 __tag),不再只认变体表
|
||
if self.Gen.ClassGenEnum._is_renum_class_name(rk_cls) != 0 or self.Gen.ClassGenEnum._is_renum_by_entry(rk_cls) != 0:
|
||
rk_is_rn = 1
|
||
# 第 2 层:按类名取 struct 的 __tag 声明类型
|
||
rk_st_b: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(rk_cls)
|
||
if rk_st_b is not None:
|
||
rk_fe_b: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(rk_st_b, "__tag")
|
||
if rk_fe_b is not None and rk_fe_b.Ty is not None:
|
||
rk_tag_ty = rk_fe_b.Ty
|
||
else:
|
||
rk_cls = None
|
||
# 第 4 层兜底:接收者是 `X.field` 形状时,运行时类型可能整体退化
|
||
# (rk_ty 不是"指向 REnum 结构体"的指针 ⇒ 上面三条判据都拿不到
|
||
# struct,只能用**声明**信息判):X 的注解类名 → struct → 该字段的
|
||
# 声明类型 → 解一层(字段访问取地址形态为 Ptr(Ptr(T)),故必要时再解
|
||
# 一层)→ pointee 类名 → 再走 表/__tag 判据。
|
||
# CallGenLib.vp:355 `vk_a: int = val.Ty.kind()` 正是此形态:
|
||
# Value.Ty 声明为 `rawptr[LLVMType]`(__values.vp:22)。
|
||
if rk_is_rn == 0 and rk_at.value is not None and rk_at.value.kind() == ast.ASTKind.Attribute and trans is not None:
|
||
rk_bat: ast.Attribute* = ast.Attribute*(rk_at.value)
|
||
if rk_bat is not None and rk_bat.attr is not None and rk_bat.value is not None and rk_bat.value.kind() == ast.ASTKind.Name:
|
||
rk_bnm: ast.Name* = ast.Name*(rk_bat.value)
|
||
if rk_bnm.id is not None:
|
||
rk_bve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, rk_bnm.id)
|
||
rk_bannot: str = self.Gen.VarGen.var_annot_class_name(rk_bve)
|
||
if rk_bannot is not None:
|
||
rk_blen: sizet = 0
|
||
while rk_bannot[rk_blen] != '\0' and rk_bannot[rk_blen] != ' ' and rk_bannot[rk_blen] != '|' and rk_bannot[rk_blen] != '[':
|
||
rk_blen += 1
|
||
rk_bbuf: str = pool.alloc(rk_blen + 1)
|
||
if rk_bbuf is not None:
|
||
string.strncpy(rk_bbuf, rk_bannot, rk_blen)
|
||
rk_bbuf[rk_blen] = '\0'
|
||
# 去模块前缀("llvmlite.Value" → "Value")
|
||
rk_bdot: str = string.strrchr(rk_bbuf, '.')
|
||
rk_bcls: str = rk_bbuf
|
||
if rk_bdot is not None and rk_bdot[1] != '\0':
|
||
rk_bcls = rk_bdot + 1
|
||
rk_bst: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(rk_bcls)
|
||
if rk_bst is not None:
|
||
rk_bfe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(rk_bst, rk_bat.attr)
|
||
if rk_bfe is not None and rk_bfe.Ty is not None:
|
||
rk_fpt: llvmlite.LLVMType* = rk_bfe.Ty
|
||
if self.Gen.ExprGenBase.is_ptr_type(rk_fpt) != 0:
|
||
rk_fpt = rk_fpt.Pointee
|
||
if rk_fpt is not None and self.Gen.ExprGenBase.is_ptr_type(rk_fpt) != 0:
|
||
rk_fpt = rk_fpt.Pointee
|
||
if rk_fpt is not None:
|
||
rk_fcls: str = self.Gen.StructGen.get_class_name_by_type(pool, rk_fpt)
|
||
if rk_fcls is not None:
|
||
if self.Gen.ClassGenEnum._is_renum_class_name(rk_fcls) != 0 or self.Gen.ClassGenEnum._is_renum_by_entry(rk_fcls) != 0:
|
||
rk_is_rn = 1
|
||
rk_cls = rk_fcls
|
||
rk_ffe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(rk_fpt, "__tag")
|
||
if rk_ffe is not None:
|
||
if rk_is_rn == 0:
|
||
rk_is_rn = 1
|
||
if rk_ffe.Ty is not None:
|
||
rk_tag_ty = rk_ffe.Ty
|
||
if rk_is_rn != 0:
|
||
rk_val: llvmlite.Value* = rk_obj
|
||
if rk_load != 0:
|
||
# build_load(builder, ty, ptr):ty 是**载入值**的类型
|
||
# (生成 `load <ty>, <ptr.Ty> <ptr>`,返回值 Ty = ty)。
|
||
# rk_ty 是 Ptr(Ptr(X)),要取内层指针 ⇒ ty 必须是 rk_ty.Pointee;
|
||
# 传 rk_ty 会生成 `load <ptr>, <ptr> %p` 且返回值 Ty 仍是指针。
|
||
rk_val = llvmlite.build_load(builder, rk_ty.Pointee, rk_obj)
|
||
if rk_val is None:
|
||
# fail-fast:已判定为 REnum(判据命中),双指针解一层 load 却拿不到
|
||
# 值——绝不静默跳过:跳过会让 .kind() 掉进通用调用路径、返回类型落空,
|
||
# 报错点漂到几百行外的赋值处(如 CallGenLib.vp:355)。
|
||
self.Gen.TypeGenErr.fatal_error(cl,
|
||
f"REnum.kind() 翻译失败:接收者已判定为 REnum(变体表/__tag 判据命中),"
|
||
f"但接收者指针解一层 load 失败(rk_load={rk_load})", "TypeError")
|
||
if hit_box is not None:
|
||
hit_box[0] = 1
|
||
# 第 2 层:按 __tag 的**字段声明类型**取址并 load,不再硬编码 i32。
|
||
# 宽度口径交给赋值侧的隐式转换规则(coerce_to_type):整型↔整型
|
||
# (低向高无损 / 高向低可安全降级)自动提升降级,规则不覆盖的组合
|
||
# (如 tag 为浮点/指针)才由该规则 fail-fast。
|
||
rk_tag_p: llvmlite.LLVMType* = llvmlite.Ptr(pool, rk_tag_ty)
|
||
rk_cast: llvmlite.Value* = llvmlite.build_bitcast(builder, rk_val, rk_tag_p)
|
||
# 第一参数是**载入值**类型 rk_tag_ty(不是指针 rk_tag_p):
|
||
# 传 rk_tag_p 会生成 `load i32*, i32* %p`,返回值 Ty = i32*,
|
||
# 到赋值侧 coerce_to_type 就报「指针隐式转整数已禁止」
|
||
# (CallGenLib.vp:355 `vk_a: int = val.Ty.kind()` 根因)。
|
||
# 对照 MatchGenMixin.vp:327 读 __tag 的正确写法。
|
||
return llvmlite.build_load(builder, rk_tag_ty, rk_cast)
|
||
# 检测类名静态/类方法调用: ClassName.method(args)
|
||
# 当 cl.func 是 Attribute、value 是已注册结构体类名(非普通变量)时,
|
||
# 且方法带 @staticmethod/@classmethod 元数据,走静态调用路径
|
||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||
st_at: ast.Attribute* = ast.Attribute*(cl.func)
|
||
if st_at is not None and st_at.value is not None and trans is not None:
|
||
if st_at.value.kind() == ast.ASTKind.Name:
|
||
st_nm: ast.Name* = ast.Name*(st_at.value)
|
||
if st_nm.id is not None:
|
||
st_var: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, st_nm.id)
|
||
if st_var is None and self.Gen.StructGen.get_struct_type(st_nm.id) is not None and self.Gen.ImportsGen.is_module_imported(trans._imported_modules, st_nm.id) == 0:
|
||
# REnum 变体构造优先于静态/类方法调用:
|
||
if self.Gen.ClassGenEnum._is_renum_class_name(st_nm.id) != 0:
|
||
rc_tag_sc: int = self.Gen.ClassGenEnum._lookup_renum_variant_in_class(st_nm.id, func_name)
|
||
if rc_tag_sc >= 0:
|
||
return self.Gen.CallGenCtor._translate_renum_construct(pool, builder, mod, st_nm.id, func_name, rc_tag_sc, cargs, can, trans, cl.IsVolatile)
|
||
st_res: llvmlite.Value* = self.Gen.CallGenProp._translate_static_class_call(pool, builder, mod, st_nm.id, func_name, cl, trans)
|
||
if st_res is not None:
|
||
return st_res
|
||
# 实例方法经类名调用 ClassName.method(obj, args) → obj.method(args)(Python 语义,首参是 self 对象);但 st_nm.id == func_name(类名==方法名,如 CompilerFactory.CompilerFactory(...))是构造调用而非实例方法调用——本分支会误把模块限定类构造当 ClassName.method(obj,args) 且首实参当 self 传,导致返回类型查 "X.X" 永远落空 fail-fast。故跳过本分支,落到 translate_call 尾部的 ctor 检测
|
||
if can >= 1 and cargs is not None and string.strcmp(st_nm.id, func_name) != 0:
|
||
im_self: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), None, 0, trans)
|
||
if im_self is not None:
|
||
im_rem: sizet* = None
|
||
if can >= 2:
|
||
im_rem = pool.alloc(sizet(can - 1) * 8)
|
||
if im_rem is not None:
|
||
ri_im: sizet
|
||
for ri_im in range(can - 1):
|
||
im_rv: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(ri_im + 1), None, 0, trans)
|
||
if im_rv is not None:
|
||
im_rem[ri_im] = sizet(im_rv)
|
||
im_res: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, st_nm.id, func_name, im_self, im_rem, can - 1, trans)
|
||
if im_res is not None:
|
||
return im_res
|
||
elif st_at.value.kind() == ast.ASTKind.Attribute:
|
||
# 模块限定静态调用: module.ClassName.static_method(args)
|
||
# cl.func = Attribute(value=Attribute(value=Name(module),
|
||
# attr=ClassName), attr=method_name)
|
||
# 此前未检测 → 走通用路径把 method_name 当裸函数解析,
|
||
# 生成 call i32 @from_long(无类名/SHA1 前缀)→ 链接
|
||
# undefined reference(CPythonTest PyLongObj.from_long 根因)
|
||
st_at2: ast.Attribute* = ast.Attribute*(st_at.value)
|
||
if st_at2 is not None and st_at2.attr is not None and st_at2.value is not None:
|
||
if st_at2.value.kind() == ast.ASTKind.Name:
|
||
# ClassName 是已注册结构体类名时尝试静态/类方法
|
||
if self.Gen.StructGen.get_struct_type(st_at2.attr) is not None:
|
||
st_res2: llvmlite.Value* = self.Gen.CallGenProp._translate_static_class_call(pool, builder, mod, st_at2.attr, func_name, cl, trans)
|
||
if st_res2 is not None:
|
||
return st_res2
|
||
|
||
# [M4·REPL 专用分支] 会话变量接收者的方法调用:`obj.m(args)` 的 obj 是**会话
|
||
# 变量**时,其值在 ctx 槽里、不在 SymTab ⇒ 上面的 lookup_var 分支恒不命中
|
||
# (本次之前:整个分派都靠 SymTab,跨片段的 `p.get()` 直接落空)。此处按
|
||
# 会话表判定:命中即取接收者(PTR 条目取槽内指针值;STRUCT 条目取**槽地址**
|
||
# = 对象自身地址,正是 self 需要的形态),再用接收者类型的类名走同一条
|
||
# `_translate_method_call`(符号 <sha1>.<类>.<方法>、返回类型经 text.ll/vpi)。
|
||
# 守卫 trans.ReplCtx is not None ⇒ 非 REPL 编译路径一行不经过(逐字不变)。
|
||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute and trans is not None and trans.ReplCtx is not None and pool is not None:
|
||
rp_at: ast.Attribute* = ast.Attribute*(cl.func)
|
||
if rp_at is not None and rp_at.value is not None and rp_at.attr is not None:
|
||
if rp_at.value.kind() == ast.ASTKind.Name:
|
||
rp_nm: ast.Name* = ast.Name*(rp_at.value)
|
||
if rp_nm.id is not None:
|
||
rp_ent: rawptr[GenTypes.ReplVarEntry] = self.Gen.VarGen.repl_find_entry(trans.ReplCtx, rp_nm.id)
|
||
if rp_ent is not None:
|
||
rp_val: llvmlite.Value* = None
|
||
if rp_ent.TyTag == GenTypes.REPL_TY_STRUCT:
|
||
# 结构体值内联在槽里:槽地址即对象地址(self)
|
||
rp_val = self.Gen.VarGen.repl_try_addr(trans, rp_nm.id, cl)
|
||
else:
|
||
rp_val = self.Gen.VarGen.repl_try_read(trans, rp_nm.id, cl)
|
||
rp_cls: str = None
|
||
if rp_val is not None and rp_val.Ty is not None:
|
||
rp_sty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(rp_val)
|
||
if rp_sty is not None:
|
||
rp_cls = self.Gen.StructGen.get_class_name_by_type(pool, rp_sty)
|
||
if rp_cls is not None:
|
||
rp_obj: llvmlite.Value* = rp_val
|
||
if self.Gen.ExprGenBase.is_ptr_type(rp_val.Ty) != 0 and rp_val.Ty.Pointee != 0 and self.Gen.ExprGenBase.is_ptr_type(rp_val.Ty.Pointee) != 0:
|
||
rp_obj = llvmlite.build_load(builder, rp_val.Ty, rp_val)
|
||
if rp_obj is not None:
|
||
if hit_box is not None:
|
||
hit_box[0] = 1
|
||
return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, rp_cls, rp_at.attr, rp_obj, cl, trans)
|
||
# 会话变量命中但接收者不是结构体类(如 int/str/其它指针):
|
||
# 不拦截、不置 hit,交给下方既有分支(list 内置/FakeDuck 等)
|
||
|
||
# 检测方法调用: obj.method(args)
|
||
# 当 cl.func 是 Attribute 且 obj 是已注册的结构体变量时,翻译为方法调用
|
||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||
method_at: ast.Attribute* = ast.Attribute*(cl.func)
|
||
if method_at is not None and method_at.value is not None:
|
||
# 链式方法调用: a.b().c() —— value 是内层 Call(如 gfx.vp 的
|
||
# eye.Sub(target).Norm())。此前未处理 → 外层 .Norm() 的 value
|
||
# 非 Name 跳过方法分支 → 通用路径把 eye.Sub 当属性解析 →
|
||
# "属性写入失败: .Sub"。先翻译内层调用得接收者,再方法调用。
|
||
if method_at.value.kind() == ast.ASTKind.Call and trans is not None:
|
||
recv_val_c: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, method_at.value, None, 0, trans)
|
||
if recv_val_c is not None and recv_val_c.Ty is not None:
|
||
recv_ty_c: llvmlite.LLVMType* = recv_val_c.Ty
|
||
if self.Gen.ExprGenBase.is_ptr_type(recv_ty_c) != 0:
|
||
recv_ty_c = recv_ty_c.Pointee
|
||
# 堆对象(@t.Object)双指针 → 再解一层取 struct
|
||
if self.Gen.ExprGenBase.is_ptr_type(recv_ty_c) != 0:
|
||
recv_ty_c = recv_ty_c.Pointee
|
||
recv_cls_c: str = self.Gen.StructGen.get_class_name_by_type(pool, recv_ty_c)
|
||
if recv_cls_c is not None:
|
||
if self.Gen.CallGenProp._is_list_builtin_receiver(pool, recv_val_c, recv_cls_c, method_at.attr, cl) == 0:
|
||
obj_ptr_c: llvmlite.Value* = recv_val_c
|
||
if self.Gen.ExprGenBase.is_ptr_type(recv_val_c.Ty) != 0 and recv_val_c.Ty.Pointee != 0 and self.Gen.ExprGenBase.is_ptr_type(recv_val_c.Ty.Pointee) != 0:
|
||
obj_ptr_c = llvmlite.build_load(builder, recv_val_c.Ty, recv_val_c)
|
||
if obj_ptr_c is not None:
|
||
if hit_box is not None:
|
||
hit_box[0] = 1
|
||
return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, recv_cls_c, method_at.attr, obj_ptr_c, cl, trans)
|
||
if method_at.value.kind() == ast.ASTKind.Name and trans is not None:
|
||
method_obj_nm: ast.Name* = ast.Name*(method_at.value)
|
||
if method_obj_nm.id is not None:
|
||
# nonlocal 对象:提升函数内从 env 读对象指针(load_nonlocal_var),
|
||
# 不能 lookup_var 跨函数命中父函数 alloca(SSA 编号错乱 →
|
||
# llc "use of undefined value")。entry.get() 等方法调用的
|
||
# 基座对象经此路径解析(closure 隐式捕获场景)。
|
||
# 用 get_struct_type_from_value 递归解 Ptr,兼容
|
||
# Ptr(Struct)(load_nonlocal_var 已 load)与
|
||
# Ptr(Ptr(Struct))(联合简化未解引用)两种形态。
|
||
if GenApi.is_nonlocal_name(trans, method_obj_nm.id) != 0:
|
||
nl_obj: llvmlite.Value* = self.Gen.StmtGenDecl.load_nonlocal_var(trans, method_obj_nm.id)
|
||
if nl_obj is not None and nl_obj.Ty is not None:
|
||
nl_deref: llvmlite.Value* = self.Gen.ExprGenBase._deref_if_ptr_ptr(builder, nl_obj)
|
||
if nl_deref is None:
|
||
nl_deref = nl_obj
|
||
nl_struct: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(nl_deref)
|
||
if nl_struct is not None:
|
||
nl_cls: str = self.Gen.StructGen.get_class_name_by_type(pool, nl_struct)
|
||
if nl_cls is not None:
|
||
if self.Gen.CallGenProp._is_list_builtin_receiver(pool, nl_deref, nl_cls, func_name, cl) == 0:
|
||
if hit_box is not None:
|
||
hit_box[0] = 1
|
||
return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, nl_cls, func_name, nl_deref, cl, trans)
|
||
# 非 local 对象但分派未成功:绝不回退 lookup_var
|
||
# (其 Alloca 是父函数存储,跨函数引用 → SSA 错乱),
|
||
# 返回 None 让上层 fast-fail 暴露类型解析问题。
|
||
return None
|
||
# 查找对象变量
|
||
obj_var: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, method_obj_nm.id)
|
||
if obj_var is not None and obj_var.Ty is not None:
|
||
# list 泛型容器注解先行识别(早期拦截,供下方各 class 分支共用):rawptr[list[rawptr[AST]]] 的 LLVM 形态为 Ptr(Ptr(Struct('list[sha.AST]'))),而 list 特化 struct 不注册为普通类,get_class_name_by_type 或返回 None、或后缀误命中内层元素类 ⇒ 下方两个 Ptr 分支的 list 内置拦截落空/错判。此处再兜底剥一次最外层 rawptr,内层以 'list' 开头且方法属 list 内置集合时置位 is_list_annot_builtin,交给本方法尾部 list 内置分支(内联 GEP)翻译
|
||
var_entry: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, method_obj_nm.id)
|
||
is_list_annot_builtin: int = 0
|
||
la_buf: str = self.Gen.VarGen.var_annot_class_name(var_entry)
|
||
if la_buf is not None:
|
||
la_tail: str = la_buf
|
||
if string.strncmp(la_buf, "rawptr[", 7) == 0:
|
||
la_tail = la_buf + 7
|
||
if string.strncmp(la_tail, "list", 4) == 0:
|
||
if self.Gen.CallGenProp._is_list_builtin_receiver(pool, obj_var, la_tail, func_name, cl) != 0:
|
||
is_list_annot_builtin = 1
|
||
match obj_var.Ty:
|
||
case llvmlite.LLVMType.Ptr(obj_struct_ty):
|
||
class_nm: str = self.Gen.StructGen.get_class_name_by_type(pool, obj_struct_ty)
|
||
if class_nm is not None:
|
||
# list 泛型内置容器方法(append/get/set/pop/clear/__iter__/
|
||
# __len__/__getitem__/__setitem__)由下方 list 内置分支
|
||
# (L5848 起)内联 GEP 处理,不注册方法函数;若走
|
||
# _translate_method_call 会查 append 返回类型(函数/text.ll/
|
||
# vpi stub 均未命中)→ fail-fast。检测到 list 方法时
|
||
# 跳过 method_call,落到内置分支(NewAstTest body.append 根因)。
|
||
# 注解兜底(is_list_annot_builtin=1)同跳过:class_nm
|
||
# 可能被类型名后缀匹配错解为内层元素类,非 'list' 前缀
|
||
# 拦截会漏放 → 走 method_call/MRO fatal。
|
||
if self.Gen.CallGenProp._is_list_builtin_receiver(pool, obj_var, class_nm, func_name, cl) == 0 and is_list_annot_builtin == 0:
|
||
if hit_box is not None:
|
||
hit_box[0] = 1
|
||
return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, class_nm, func_name, obj_var, cl, trans)
|
||
# 指针变量: alloca 类型是 Ptr(Ptr(Struct))
|
||
# load 获取实际指针 Ptr(Struct) 后再查找
|
||
match obj_struct_ty:
|
||
case llvmlite.LLVMType.Ptr(inner_struct_ty):
|
||
inner_nm: str = self.Gen.StructGen.get_class_name_by_type(pool, inner_struct_ty)
|
||
if inner_nm is not None:
|
||
# list 内置方法同样跳过(同 Ptr(Struct) 分支);
|
||
# 注解兜底(is_list_annot_builtin=1)同跳过:
|
||
# inner_nm 也可能被后缀匹配错解为内层元素类。
|
||
if self.Gen.CallGenProp._is_list_builtin_receiver(pool, obj_var, inner_nm, func_name, cl) == 0 and is_list_annot_builtin == 0:
|
||
obj_ptr: llvmlite.Value* = llvmlite.build_load(builder, obj_struct_ty, obj_var)
|
||
if obj_ptr is not None:
|
||
if hit_box is not None:
|
||
hit_box[0] = 1
|
||
return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, inner_nm, func_name,obj_ptr, cl, trans)
|
||
# FakeDuck: str/bytes 变量(Ptr(i8),AnnotClassName 为空)
|
||
# 方法调用 → 扩展类 _Type/_str(a.type_id() / a.upper())。
|
||
# 前置拦截:常规结构体方法分支全落空时,尝试扩展类方法
|
||
# (find_func_in_module 未命中返回 None,不影响正常路径)。
|
||
# list 容器注解命中(is_list_annot_builtin=1)时跳过 FakeDuck:
|
||
# 接收者非 str/bytes,此调用必须由尾部 list 内置分支翻译。
|
||
if is_list_annot_builtin == 0:
|
||
fd_name_res: llvmlite.Value* = self.Gen.CallGenFd._translate_fakeduck_call(pool, builder, mod, None, func_name, cl, trans)
|
||
if fd_name_res is not None:
|
||
return fd_name_res
|
||
# AnnotClassName 回退:联合类型简化为 Ptr(i8) 时,
|
||
# 通过原始类型注解的类名查找结构体(var_entry 已在上方
|
||
# list 注解识别处查得,同一变量表项)。
|
||
# list 容器注解命中(is_list_annot_builtin=1)时跳过本回退:
|
||
# 本回退的"剥模块前缀"会按内层元素 '.'(如
|
||
# list[rawptr[sha.AST]])把类名错切为 'AST]]' 垃圾 → 下方
|
||
# _is_list_builtin_method 前缀匹配不中 → 误走 FakeDuck/sha1
|
||
# 方法构造 → _translate_method_call MRO fatal。list 调用由
|
||
# 尾部 list 内置分支统一翻译。
|
||
annot_val: str = self.Gen.VarGen.var_annot_class_name(var_entry)
|
||
if annot_val is not None and is_list_annot_builtin == 0:
|
||
# 解析模块限定名 "memhub.MemBuddy" → mod_nm="memhub", cls_nm="MemBuddy"
|
||
dot_ptr: str = string.strrchr(annot_val, '.')
|
||
cls_nm2: str = annot_val
|
||
mod_nm2: str = None
|
||
if dot_ptr is not None:
|
||
cls_nm2 = dot_ptr + 1
|
||
total_len_av: sizet = string.strlen(annot_val)
|
||
cls_len_av: sizet = string.strlen(cls_nm2)
|
||
mod_len2: sizet = total_len_av - cls_len_av - 1
|
||
mod_nm2 = pool.alloc(mod_len2 + 1)
|
||
if mod_nm2 is not None:
|
||
string.strncpy(mod_nm2, annot_val, mod_len2)
|
||
mod_nm2[mod_len2] = '\0'
|
||
# 检查结构体是否已注册
|
||
if self.Gen.StructGen.get_struct_type(cls_nm2) is not None:
|
||
# list 内置方法跳过 method_call(同 Ptr(Struct) 分支),
|
||
# 落到下方 list 内置分支
|
||
if self.Gen.CallGenProp._is_list_builtin_receiver(pool, obj_var, cls_nm2, func_name, cl) == 0:
|
||
# 结构体已注册:load obj_ptr 走方法调用
|
||
i8_ptr_ty2: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||
obj_ptr2: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty2, obj_var)
|
||
if obj_ptr2 is not None:
|
||
if hit_box is not None:
|
||
hit_box[0] = 1
|
||
return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, cls_nm2, func_name,obj_ptr2, cl, trans)
|
||
else:
|
||
# list 内置方法跳过(结构体未注册路径同样不能
|
||
# 构造 {sha1}.{cls}.append 调用名——list 方法无此函数)
|
||
if self.Gen.CallGenProp._is_list_builtin_receiver(pool, obj_var, cls_nm2, func_name, cl) == 0:
|
||
# FakeDuck: str 变量方法调用 → 扩展类 _Type/_str
|
||
# a.type_id() / a.upper() / " ".isspace() 等
|
||
# AnnotClassName=="str" 且对象是 char* 时触发,
|
||
# self 用影子结构体 {a}__meta__(或临时影子)。
|
||
fd_res: llvmlite.Value* = self.Gen.CallGenFd._translate_fakeduck_call(pool, builder, mod, cls_nm2, func_name, cl, trans)
|
||
if fd_res is not None:
|
||
return fd_res
|
||
# 结构体未注册(跨模块依赖未翻译):
|
||
# 用模块名查 SHA1 构造方法调用名
|
||
sha1_fc: str = None
|
||
if mod_nm2 is not None:
|
||
sha1_fc = self._lookup_module_sha1(mod_nm2)
|
||
if sha1_fc is not None:
|
||
# 构造 "{sha1}.{cls_nm2}.{func_name}" 调用名
|
||
mlen3: sizet = string.strlen(sha1_fc) + string.strlen(cls_nm2) + string.strlen(func_name) + 3
|
||
mangled3: str = pool.alloc(mlen3)
|
||
if mangled3 is not None:
|
||
viperlib.snprintf(mangled3, mlen3, "%s.%s.%s", sha1_fc, cls_nm2, func_name)
|
||
# load obj_ptr (self)
|
||
i8_ptr_ty3: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||
obj_ptr3: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty3, obj_var)
|
||
if obj_ptr3 is not None:
|
||
# 构建参数链表: obj_ptr3 (self) → 其他参数
|
||
llvmlite.value_set_next(obj_ptr3, None)
|
||
head3: llvmlite.Value* = obj_ptr3
|
||
tail3: llvmlite.Value* = obj_ptr3
|
||
for ai3 in range(can):
|
||
arg3: ast.AST* = cargs.get(ai3)
|
||
if arg3 is not None:
|
||
arg_val3: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg3, None, 0, trans)
|
||
if arg_val3 is not None:
|
||
llvmlite.value_set_next(arg_val3, None)
|
||
llvmlite.value_set_next(tail3, arg_val3)
|
||
tail3 = arg_val3
|
||
total3: int = 1 + can
|
||
ret_ty3: llvmlite.LLVMType* = self._special_method_ret_ty(pool, cls_nm2, func_name)
|
||
if ret_ty3 is None:
|
||
ret_ty3 = self._LookupMethodRetTyFromTextLL(pool, sha1_fc, cls_nm2, func_name)
|
||
if ret_ty3 is None:
|
||
# 精确查找:vpi stub 返回注解缓存(方法定义处,不硬编码白名单)
|
||
ret_ty3 = self._lookup_method_ret_ty_via_vpi(pool, sha1_fc, cls_nm2, func_name)
|
||
if ret_ty3 is None:
|
||
# 本分支仅在"注解类结构体未注册"时到达(L6932 else):
|
||
# 类未注册 → 无法沿 MRO 解析 Mixin 方法定义模块。
|
||
# 例如 g 注解 Generator.Generator,但 _register_cdefine_from_value
|
||
# 定义在 AssignGenMixin.vp——其 text.ll 的 define 名是
|
||
# {AssignGenMixin_sha1}.AssignGenMixin.xxx,查
|
||
# {Generator_sha1}.Generator.xxx 永远落空(追加80d 根因;
|
||
# sha1_fc 存在 + text.ll 存在仍查不到,固定 256KB 截断
|
||
# 只是次要因素)。本遍保持默认类型,不在此 fail-fast。
|
||
# 依赖未就绪:保持默认 i32(build_call(Void)
|
||
# 返回 None 破坏表达式翻译)
|
||
ret_ty3 = llvmlite.Int32(pool)
|
||
# 先按 vpi 定义侧形参 coerce 实参(宽度对齐),再建 declare
|
||
head3 = self.Gen.CallGenLib._coerce_args_to_def_params(pool, builder, mangled3, head3, total3, cargs, 1, trans)
|
||
self._ensure_method_declare(pool, mod, mangled3, ret_ty3, head3, total3)
|
||
return llvmlite.build_call(builder, mangled3, head3, total3, ret_ty3, 0)
|
||
else:
|
||
# 编译器生成特殊方法放行(__before_init__/__init__ 等):
|
||
# 结构体未注册 + 模块 SHA1 均不可查(Phase A 依赖未就绪)时,
|
||
# 方法返回类型由编译器确定性定义(_special_method_ret_ty),
|
||
# 不依赖结构体注册即可精确解析。走 _translate_method_call 处理
|
||
# (内部含 _special_method_ret_ty + mc_entry/类型名 SHA1 提取),
|
||
# 绝不掉出返回 None 让 translate_call 把对象名当模块名
|
||
# 报"跨模块调用 'buf.__before_init__' 找不到模块 SHA1"
|
||
# (memhub.alloc_buf buf.__before_init__() 根因)。
|
||
sp_ty4: llvmlite.LLVMType* = self._special_method_ret_ty(pool, cls_nm2, func_name)
|
||
if sp_ty4 is not None:
|
||
i8_ptr_ty4: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||
obj_ptr4: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty4, obj_var)
|
||
if obj_ptr4 is not None:
|
||
if hit_box is not None:
|
||
hit_box[0] = 1
|
||
return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, cls_nm2, func_name, obj_ptr4, cl, trans)
|
||
|
||
# ============================================================
|
||
# 检测表达式接收者方法调用: (expr).method(args)
|
||
#
|
||
# 当 method_at.value 是 BinOp/Subscript/Call 等非 Name/Attribute 表达式时
|
||
# (如 (a + b).dot(c)、(v1 + v2) * 3.0),先 translate_value 求值接收者,
|
||
# 再从值的 LLVM 类型(Ptr(Struct))解析类名,走方法调用路径。
|
||
# ============================================================
|
||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||
expr_method_at: ast.Attribute* = ast.Attribute*(cl.func)
|
||
if expr_method_at is not None and expr_method_at.value is not None and trans is not None:
|
||
evk: int = expr_method_at.value.kind()
|
||
# Attribute 接收者区分两种形态:
|
||
# 1. 模块限定路径(os._win32.exists / w32.fileio.fn)——根名是已导入
|
||
# 模块或 t/c,留给下方跨模块限定路径处理
|
||
# 2. 字段链表达式接收者(self.writer.write_bits / self.pool.alloc)
|
||
# ——根名是对象(self/局部变量),必须走本方法调用路径;
|
||
# 否则被模块限定路径误判 xmod_path="self.writer" → "找不到模块
|
||
# SHA1"(zdeflate.vp write_fixed_block 根因)
|
||
is_mod_path_expr: int = 0
|
||
if evk == ast.ASTKind.Attribute:
|
||
expr_root: ast.AST* = expr_method_at.value
|
||
while expr_root is not None and expr_root.kind() == ast.ASTKind.Attribute:
|
||
expr_root = ast.Attribute*(expr_root).value
|
||
if expr_root is not None and expr_root.kind() == ast.ASTKind.Name:
|
||
expr_root_nm: str = ast.Name*(expr_root).id
|
||
if expr_root_nm is not None:
|
||
if string.strcmp(expr_root_nm, "t") == 0 or string.strcmp(expr_root_nm, "c") == 0:
|
||
is_mod_path_expr = 1
|
||
elif trans._imported_modules is not None:
|
||
if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, expr_root_nm) != 0:
|
||
is_mod_path_expr = 1
|
||
if evk != ast.ASTKind.Name and is_mod_path_expr == 0:
|
||
# 翻译接收者表达式(求值结果应为 Ptr(Struct))
|
||
expr_obj: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, expr_method_at.value, funcs_ptr, func_count, trans)
|
||
if expr_obj is not None and expr_obj.Ty is not None:
|
||
expr_cls_nm: str = None
|
||
# 递归解 Ptr:识别 X|t.CPtr 联合简化的 Ptr(Ptr(Struct))
|
||
# (如 (a*2.0 - b) 中 __mul__ 返回 Vec3**),否则方法
|
||
# 调用被当裸函数 @dot 解析 → 链接 undefined symbol
|
||
expr_struct_ty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(expr_obj)
|
||
if expr_struct_ty is not None:
|
||
expr_cls_nm = self.Gen.StructGen.get_class_name_by_type(pool, expr_struct_ty)
|
||
# 回退:LLVM 类型为 Ptr(i8)(方法返回 X|t.CPtr 无类型信息)时,
|
||
# 从接收者表达式结构推断类名(链式调用 c2.scale(2.0).move(...)
|
||
# 的 scale 返回 Ptr(i8),经 infer_expr_class → vpi 返回注解)
|
||
# 跨 Mixin 不能 self 调用 ExprGenMixin 方法,经全局单例
|
||
if expr_cls_nm is None:
|
||
expr_cls_nm = self.Gen.ExprGenCls.infer_expr_class(pool, mod, expr_method_at.value, trans)
|
||
if expr_cls_nm is not None:
|
||
# 值类型接收者(内嵌 struct 字段,如 zdeflate s.writer 值字段):
|
||
# 方法调用 self 必须传字段地址(GEP)而非 load 出的结构体值,
|
||
# 否则结构体值(40B)塞进 zbit_writer* 参数 → ABI 错配 →
|
||
# 被调方把值当 this 指针解引用 → GEP 0x18 崩溃
|
||
# (s.writer.write_zlib_header 运行时 access-violation 根因;
|
||
# 本路径 evk=Attribute 先于 self.field.method() 分支命中)。
|
||
expr_is_ptr: int = 0
|
||
match expr_obj.Ty:
|
||
case llvmlite.LLVMType.Ptr(expr_ptr_inner):
|
||
expr_is_ptr = 1
|
||
case _:
|
||
expr_is_ptr = 0
|
||
if expr_is_ptr == 0:
|
||
expr_addr: llvmlite.Value* = self.Gen.ExprGenAttr.get_attribute_ptr(builder, pool, mod, expr_method_at.value, trans)
|
||
if expr_addr is not None:
|
||
expr_obj = expr_addr
|
||
if hit_box is not None:
|
||
hit_box[0] = 1
|
||
return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, expr_cls_nm, func_name, expr_obj, cl, trans)
|
||
# FakeDuck: 表达式接收者解析失败且对象是 char* 时
|
||
# (如 " ".isspace()),尝试扩展类 _Type/_str 方法
|
||
# (self 用临时影子,对齐 TPC L2858-2873)
|
||
fd_expr_res: llvmlite.Value* = self.Gen.CallGenFd._translate_fakeduck_call(pool, builder, mod, None, func_name, cl, trans)
|
||
if fd_expr_res is not None:
|
||
return fd_expr_res
|
||
|
||
# ============================================================
|
||
# 检测 self.field.method() 调用
|
||
#
|
||
# 当 method_at.value 是 Attribute(字段访问,如 self.__pool__)时,
|
||
# 翻译字段值获取对象指针,然后走方法调用路径。
|
||
#
|
||
# 路径1: 从字段值的 LLVM 类型获取类名(字段类型为 Ptr(Struct("MemManager")))
|
||
# 路径2: 从字段的 AnnotClassName 回退查找(字段类型被简化为 Ptr(i8) 时)
|
||
# ============================================================
|
||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||
attr_method_at: ast.Attribute* = ast.Attribute*(cl.func)
|
||
if attr_method_at is not None and attr_method_at.value is not None:
|
||
if attr_method_at.value.kind() == ast.ASTKind.Attribute and trans is not None:
|
||
inner_attr: ast.Attribute* = ast.Attribute*(attr_method_at.value)
|
||
if inner_attr is not None and inner_attr.attr is not None:
|
||
# 翻译 self.__pool__ 获取字段值(已 load 的对象指针)
|
||
field_obj: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, attr_method_at.value, funcs_ptr, func_count, trans)
|
||
if field_obj is not None and field_obj.Ty is not None:
|
||
field_cls_nm: str = None
|
||
# 路径1: 从字段值的 LLVM 类型获取类名
|
||
match field_obj.Ty:
|
||
case llvmlite.LLVMType.Ptr(field_struct_ty):
|
||
field_cls_nm = self.Gen.StructGen.get_class_name_by_type(pool, field_struct_ty)
|
||
# 路径2: 从字段注解类名回退查找
|
||
if field_cls_nm is None:
|
||
if inner_attr.value is not None and inner_attr.value.kind() == ast.ASTKind.Name:
|
||
inner_name_node: ast.Name* = ast.Name*(inner_attr.value)
|
||
if inner_name_node is not None and inner_name_node.id is not None:
|
||
inner_var: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, inner_name_node.id)
|
||
if inner_var is not None and inner_var.Ty is not None:
|
||
match inner_var.Ty:
|
||
case llvmlite.LLVMType.Ptr(field_owner_struct_ty):
|
||
field_info: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(field_owner_struct_ty, inner_attr.attr)
|
||
if field_info is not None:
|
||
field_annot: str = self.Gen.StructGen.get_field_annot_class_name(field_info)
|
||
if field_annot is not None:
|
||
dot_p: str = string.strrchr(field_annot, 46)
|
||
if dot_p is not None:
|
||
field_cls_nm = dot_p + 1
|
||
else:
|
||
field_cls_nm = field_annot
|
||
if field_cls_nm is not None:
|
||
# 值类型字段(内嵌 struct,如 zdeflate_stream.writer: zbit_writer)
|
||
# 方法调用 self 必须传字段地址(GEP),而非 load 出的结构体值:
|
||
# 传值给 stub 声明/define 的 zbit_writer* 参数 → ABI 错配,
|
||
# 被调方把结构体值前 8 字节当 this 指针解引用 → GEP 0x18 崩溃
|
||
# (zdeflate s.writer.write_zlib_header 运行时 access-violation 根因)。
|
||
is_val_field: int = 0
|
||
match field_obj.Ty:
|
||
case llvmlite.LLVMType.Ptr(field_ptr_inner):
|
||
is_val_field = 0
|
||
case _:
|
||
is_val_field = 1
|
||
if is_val_field != 0:
|
||
field_addr: llvmlite.Value* = self.Gen.ExprGenAttr.get_attribute_ptr(builder, pool, mod, attr_method_at.value, trans)
|
||
if field_addr is not None:
|
||
field_obj = field_addr
|
||
if hit_box is not None:
|
||
hit_box[0] = 1
|
||
return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, field_cls_nm, func_name, field_obj, cl, trans)
|
||
|
||
# ============================================================
|
||
# 检测 list 内置方法调用: lst.get(i), lst.set(i,v), lst.pop(), lst.clear(), lst.__iter__()
|
||
# list[T] 是泛型类不注册 struct,方法调用处理器(上方)无法处理,
|
||
# 需要在此特殊处理。
|
||
# list 结构布局 (6 字段 × 8 字节):
|
||
# __data__(0) __count__(8) __capacity__(16) __pool__(24) __elem_size__(32) __iter_index__(40)
|
||
# ============================================================
|
||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||
lm_at: ast.Attribute* = ast.Attribute*(cl.func)
|
||
if lm_at is not None and lm_at.attr is not None and lm_at.value is not None:
|
||
lm_name: str = lm_at.attr
|
||
# 判断是否是 list 方法名
|
||
lm_is_list: int = 0
|
||
if string.strcmp(lm_name, "get") == 0: lm_is_list = 1
|
||
elif string.strcmp(lm_name, "__getitem__") == 0: lm_is_list = 1
|
||
elif string.strcmp(lm_name, "set") == 0: lm_is_list = 1
|
||
elif string.strcmp(lm_name, "__setitem__") == 0: lm_is_list = 1
|
||
elif string.strcmp(lm_name, "pop") == 0: lm_is_list = 1
|
||
elif string.strcmp(lm_name, "clear") == 0: lm_is_list = 1
|
||
elif string.strcmp(lm_name, "__iter__") == 0: lm_is_list = 1
|
||
elif string.strcmp(lm_name, "append") == 0: lm_is_list = 1
|
||
|
||
if lm_is_list == 1 and trans is not None:
|
||
# 翻译 list 对象
|
||
lm_obj: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, lm_at.value, funcs_ptr, func_count, trans)
|
||
if lm_obj is not None:
|
||
# 防御性类型检查: lm_obj 必须是指针类型才能做 GEP
|
||
# translate_value 对某些 Attribute 节点(如 ast.Arguments 的属性)
|
||
# 可能返回 i32 0 (非指针),直接 GEP 会导致
|
||
# "base of getelementptr must be a pointer" 错误
|
||
if lm_obj.Ty is None or self.Gen.ExprGenBase.is_ptr_type(lm_obj.Ty) == 0:
|
||
# translate_value 类型推断失败(目标对象非指针):
|
||
# fail-fast,绝不 VLogger.critical 后 return None 静默吞掉
|
||
self.Gen.TypeGenErr.fatal_error(lm_at.value, f"list 方法 '{lm_name}' 目标对象非指针", "TypeError")
|
||
# list 对象类型确认(额外搜索路径):list 内置分支仅按方法名
|
||
# 判断(get/set/__getitem__ 等非 list 专有),须确认对象确实
|
||
# 是 list——从对象结构体名匹配 "list"。明确非 list(如 dict /
|
||
# 普通类未注册场景)跳过本分支,避免按 list 布局 GEP 生成
|
||
# 错误 IR(dict 的 get 被当 list.get 按 __data__/__elem_size__
|
||
# 偏移读写垃圾)。
|
||
lm_conf_ty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(lm_obj)
|
||
lm_conf_nm: str = None
|
||
if lm_conf_ty is not None:
|
||
lm_conf_nm = llvmlite.get_struct_name(lm_conf_ty)
|
||
# [S4] 容器基名**精确**比较:此处读的是 LLVM 注册名,含模块 sha1
|
||
# 前缀(如 "e94ef9e139461915.list[ast.ASTptr]");SpecTypeNameBaseIs
|
||
# 会去前缀、截断泛型实参后精确比 "list"(原 strstr 子串会误命中
|
||
# playlist 之类的类名)。
|
||
if lm_conf_nm is not None and TSpec.SpecTypeNameBaseIs(lm_conf_nm, "list") == 0:
|
||
return None
|
||
# list 内置分支命中标记:void 方法(set/clear)成功处理后返回
|
||
# None,必须置位 hit_box 区分"已识别为 list 方法路径",否则
|
||
# translate_call 误判未命中继续走跨模块函数路径,把对象名当
|
||
# 模块名查 SHA1 → "跨模块调用 'nums.set' 找不到模块 SHA1"
|
||
# (ListTest main.vp nums.set(1,99) 根因;对齐 _translate_method_call
|
||
# 调用点的 hit_box 置位模式)。
|
||
if hit_box is not None:
|
||
hit_box[0] = 1
|
||
i64_ty: llvmlite.LLVMType* = llvmlite.Int64(pool)
|
||
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
|
||
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
|
||
# 元素类型 T:从 list 特化类型名解析(list[int]→i32、
|
||
# list[str]→i8*、未知/指针元素→i8*)。此前 get/set/pop
|
||
# 固定 i8*(8 字节)读写:set 的 8 字节 store 覆盖相邻元素
|
||
# (inttoptr 值,如 set(1,99) 把 data[8..11] 的 30 清 0),
|
||
# pop 读回 0 → ListTest "pop FAILED expect 30" 根因。
|
||
# subscript 路径(list_getitem_inline 调用方)已用
|
||
# _list_elem_type_from_name 修正,方法调用路径漏改。
|
||
lm_esty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(lm_obj)
|
||
lm_ename: str = None
|
||
if lm_esty is not None:
|
||
lm_ename = llvmlite.get_struct_name(lm_esty)
|
||
lm_elem_ty: llvmlite.LLVMType* = None
|
||
if lm_ename is not None:
|
||
lm_elem_ty = self.Gen.ExprGenName._list_elem_type_from_name(pool, lm_ename)
|
||
if lm_elem_ty is None:
|
||
lm_elem_ty = i8_ptr_ty
|
||
|
||
# get / __getitem__: 返回 index 处的元素
|
||
if string.strcmp(lm_name, "get") == 0 or string.strcmp(lm_name, "__getitem__") == 0:
|
||
if can >= 1:
|
||
# 加载 __data__ (偏移 0)
|
||
g_idx0: llvmlite.Value* = llvmlite.const_int64(pool, 0)
|
||
g_dpp: llvmlite.Value* = llvmlite.build_gep(builder, i64_ty, lm_obj, g_idx0)
|
||
g_data: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty, g_dpp)
|
||
# 加载 __elem_size__ (偏移 32, index 4)
|
||
g_idx4: llvmlite.Value* = llvmlite.const_int64(pool, 4)
|
||
g_epp: llvmlite.Value* = llvmlite.build_gep(builder, i64_ty, lm_obj, g_idx4)
|
||
g_esize: llvmlite.Value* = llvmlite.build_load(builder, i64_ty, g_epp)
|
||
# 翻译 index
|
||
g_idx_node: ast.AST* = cargs.get(0)
|
||
g_idx_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, g_idx_node, None, 0, trans)
|
||
if g_data is not None and g_esize is not None and g_idx_val is not None:
|
||
g_idx_i64: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, g_idx_val, i64_ty, g_idx_node)
|
||
g_offset: llvmlite.Value* = llvmlite.build_mul(builder, g_idx_i64, g_esize)
|
||
g_addr: llvmlite.Value* = llvmlite.build_gep(builder, i8_ty, g_data, g_offset)
|
||
if g_addr is not None:
|
||
g_ep: llvmlite.Value* = llvmlite.build_bitcast(builder, g_addr, llvmlite.Ptr(pool, lm_elem_ty))
|
||
if g_ep is not None:
|
||
return llvmlite.build_load(builder, lm_elem_ty, g_ep)
|
||
|
||
# set / __setitem__: 设置 index 处的元素
|
||
elif string.strcmp(lm_name, "set") == 0 or string.strcmp(lm_name, "__setitem__") == 0:
|
||
if can >= 2:
|
||
s_idx0: llvmlite.Value* = llvmlite.const_int64(pool, 0)
|
||
s_dpp: llvmlite.Value* = llvmlite.build_gep(builder, i64_ty, lm_obj, s_idx0)
|
||
s_data: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty, s_dpp)
|
||
s_idx4: llvmlite.Value* = llvmlite.const_int64(pool, 4)
|
||
s_epp: llvmlite.Value* = llvmlite.build_gep(builder, i64_ty, lm_obj, s_idx4)
|
||
s_esize: llvmlite.Value* = llvmlite.build_load(builder, i64_ty, s_epp)
|
||
s_idx_node: ast.AST* = cargs.get(0)
|
||
s_val_node: ast.AST* = cargs.get(1)
|
||
s_idx_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, s_idx_node, None, 0, trans)
|
||
s_val_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, s_val_node, None, 0, trans)
|
||
if s_data is not None and s_esize is not None and s_idx_val is not None and s_val_val is not None:
|
||
s_idx_i64: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, s_idx_val, i64_ty, s_idx_node)
|
||
s_offset: llvmlite.Value* = llvmlite.build_mul(builder, s_idx_i64, s_esize)
|
||
s_addr: llvmlite.Value* = llvmlite.build_gep(builder, i8_ty, s_data, s_offset)
|
||
if s_addr is not None:
|
||
s_val_elem: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, s_val_val, lm_elem_ty, s_val_node)
|
||
s_ep: llvmlite.Value* = llvmlite.build_bitcast(builder, s_addr, llvmlite.Ptr(pool, lm_elem_ty))
|
||
if s_ep is not None:
|
||
llvmlite.build_store(builder, s_val_elem, s_ep)
|
||
return None
|
||
|
||
# pop: 返回最后一个元素,count--
|
||
elif string.strcmp(lm_name, "pop") == 0:
|
||
p_idx1: llvmlite.Value* = llvmlite.const_int64(pool, 1)
|
||
p_cpp: llvmlite.Value* = llvmlite.build_gep(builder, i64_ty, lm_obj, p_idx1)
|
||
p_count: llvmlite.Value* = llvmlite.build_load(builder, i64_ty, p_cpp)
|
||
p_nc: llvmlite.Value* = llvmlite.build_sub(builder, p_count, llvmlite.const_int64(pool, 1))
|
||
llvmlite.build_store(builder, p_nc, p_cpp)
|
||
p_idx0: llvmlite.Value* = llvmlite.const_int64(pool, 0)
|
||
p_dpp: llvmlite.Value* = llvmlite.build_gep(builder, i64_ty, lm_obj, p_idx0)
|
||
p_data: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty, p_dpp)
|
||
p_idx4: llvmlite.Value* = llvmlite.const_int64(pool, 4)
|
||
p_epp: llvmlite.Value* = llvmlite.build_gep(builder, i64_ty, lm_obj, p_idx4)
|
||
p_esize: llvmlite.Value* = llvmlite.build_load(builder, i64_ty, p_epp)
|
||
if p_data is not None and p_esize is not None and p_nc is not None:
|
||
p_offset: llvmlite.Value* = llvmlite.build_mul(builder, p_nc, p_esize)
|
||
p_addr: llvmlite.Value* = llvmlite.build_gep(builder, i8_ty, p_data, p_offset)
|
||
if p_addr is not None:
|
||
p_ep: llvmlite.Value* = llvmlite.build_bitcast(builder, p_addr, llvmlite.Ptr(pool, lm_elem_ty))
|
||
if p_ep is not None:
|
||
return llvmlite.build_load(builder, lm_elem_ty, p_ep)
|
||
|
||
# clear: count = 0
|
||
elif string.strcmp(lm_name, "clear") == 0:
|
||
c_idx1: llvmlite.Value* = llvmlite.const_int64(pool, 1)
|
||
c_cpp: llvmlite.Value* = llvmlite.build_gep(builder, i64_ty, lm_obj, c_idx1)
|
||
llvmlite.build_store(builder, llvmlite.const_int64(pool, 0), c_cpp)
|
||
return None
|
||
|
||
# __iter__: iter_index = 0, return self
|
||
elif string.strcmp(lm_name, "__iter__") == 0:
|
||
it_idx5: llvmlite.Value* = llvmlite.const_int64(pool, 5)
|
||
it_ipp: llvmlite.Value* = llvmlite.build_gep(builder, i64_ty, lm_obj, it_idx5)
|
||
llvmlite.build_store(builder, llvmlite.const_int64(pool, 0), it_ipp)
|
||
return lm_obj
|
||
|
||
# append: 直接调用 list.append(self, item)
|
||
# append 需要容量检查和内存重分配,逻辑复杂,直接调用 _list.py 中的实现
|
||
elif string.strcmp(lm_name, "append") == 0:
|
||
if can >= 1:
|
||
ap_sha1: str = self._lookup_module_sha1("_list")
|
||
if ap_sha1 is None:
|
||
# 依赖模块未编译(_list 未预加入编译链):fail-fast,
|
||
# 绝不静默跳过 append(元素永远不会被加入列表)
|
||
self.Gen.TypeGenErr.fatal_error(cl, "list.append: 找不到 _list 模块 SHA1(依赖模块未编译)", "InternalCompilerError")
|
||
if ap_sha1 is not None:
|
||
# 特化类名提取:list.append 的符号名是
|
||
# {sha1}.list[AST|CPtr].append(带类型参数特化名),
|
||
# 而非 {sha1}.list.append。lm_obj 类型即特化结构体
|
||
# Ptr(list[AST|CPtr]),从类型解析特化类名拼接调用名,
|
||
# 否则 ld.lld undefined symbol(定义端是特化名)。
|
||
ap_spec_nm: str = None
|
||
ap_struct_ty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(lm_obj)
|
||
if ap_struct_ty is not None:
|
||
ap_spec_nm = self.Gen.StructGen.get_class_name_by_type(pool, ap_struct_ty)
|
||
if ap_spec_nm is None:
|
||
ap_spec_nm = "list"
|
||
# 触发泛型特化翻译(幂等,MethodsEmitted 防重入):
|
||
# list[AST|CPtr].append 的 define 方法体在特化类翻译时
|
||
# 生成。仅构造调用名不触发特化会导致定义缺失
|
||
# (ld.lld undefined symbol: list[AST|CPtr].append)。
|
||
if trans is not None and ap_spec_nm is not None:
|
||
lbkt_ap: str = string.strchr(ap_spec_nm, '[')
|
||
if lbkt_ap is not None:
|
||
rbkt_ap: str = string.strrchr(ap_spec_nm, ']')
|
||
if rbkt_ap is not None and rbkt_ap > lbkt_ap:
|
||
base_len_ap: sizet = sizet(uint64(lbkt_ap) - uint64(ap_spec_nm))
|
||
arg_len_ap: sizet = sizet(uint64(rbkt_ap) - uint64(lbkt_ap) - 1)
|
||
if base_len_ap > 0 and arg_len_ap > 0:
|
||
base_buf_ap: str = pool.alloc(base_len_ap + 1)
|
||
arg_buf_ap: str = pool.alloc(arg_len_ap + 1)
|
||
if base_buf_ap is not None and arg_buf_ap is not None:
|
||
string.strncpy(base_buf_ap, ap_spec_nm, base_len_ap)
|
||
base_buf_ap[base_len_ap] = '\0'
|
||
string.strncpy(arg_buf_ap, lbkt_ap + 1, arg_len_ap)
|
||
arg_buf_ap[arg_len_ap] = '\0'
|
||
args_ap: list[str]* = list[str](pool, 8)
|
||
if args_ap is not None:
|
||
# 逗号分隔多类型实参(list[X] / dict[K, V])
|
||
cur_ap: str = arg_buf_ap
|
||
while cur_ap is not None:
|
||
comma_ap: str = string.strchr(cur_ap, ',')
|
||
if comma_ap is None:
|
||
args_ap.append(cur_ap)
|
||
break
|
||
seg_len_ap: sizet = sizet(uint64(comma_ap) - uint64(cur_ap))
|
||
seg_buf_ap: str = pool.alloc(seg_len_ap + 1)
|
||
if seg_buf_ap is not None:
|
||
string.strncpy(seg_buf_ap, cur_ap, seg_len_ap)
|
||
seg_buf_ap[seg_len_ap] = '\0'
|
||
args_ap.append(seg_buf_ap)
|
||
cur_ap = comma_ap + 1
|
||
self.Gen.ClassGenGeneric._specialize_generic_class(trans, base_buf_ap, args_ap)
|
||
# 调用名 "{sha1}.{spec}.append":
|
||
# sha1(16) + '.'(1) + spec + '.append'(7) + NUL(1) = spec + 25。
|
||
# 此前 +8 少 1 字节,snprintf 截断末尾 'd' →
|
||
# undefined symbol: ...list[AST|CPtr].appen(缺 d)。
|
||
ap_mlen: sizet = string.strlen(ap_sha1) + string.strlen(ap_spec_nm) + 26
|
||
ap_mangled: str = pool.alloc(ap_mlen)
|
||
if ap_mangled is not None:
|
||
viperlib.snprintf(ap_mangled, ap_mlen, "%s.%s.append", ap_sha1, ap_spec_nm)
|
||
ap_item_node: ast.AST* = cargs.get(0)
|
||
ap_item_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, ap_item_node, None, 0, trans)
|
||
if ap_item_val is not None:
|
||
llvmlite.value_set_next(lm_obj, None)
|
||
llvmlite.value_set_next(ap_item_val, None)
|
||
llvmlite.value_set_next(lm_obj, ap_item_val)
|
||
ap_ret_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
|
||
self._ensure_method_declare(pool, mod, ap_mangled, ap_ret_ty, lm_obj, 2)
|
||
return llvmlite.build_call(builder, ap_mangled, lm_obj, 2, ap_ret_ty, 0)
|
||
|
||
return None |