Files
ViperC/App/lib/core/Gen/CallGenCtor.vp
T
TermiNexus 89995dffde refactor(gen): 去除 Handles 委托层——链式化 + GenTypes/GenApi 迁移
- Gen 内部 1742 处 HandlesX.func() 改 self.Gen.Y.method() 链式调用
- 数据类/常量迁移 GenTypes.vp(10 类 + CLASS_META_*/META_*/SEQ_KIND_*/FIELD_MAX 等)
- 管线/保留文件经 GenApi.vp 模块级入口(48 函数带类型注解,从 Gen 方法签名自动生成)
- 删除 26 个纯委托 Handles 文件,仅留 5 个实体文件(Base/Translator/Expr/ExprCall/ExprCallTable)
- 修复字段分裂:TypeGenErr CurrentFile/TraceCount 链式化;CallGenBase TempDir/Cexport 真源化
2026-08-21 06:32:40 +08:00

981 lines
54 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import lib.core.Gen.GenTypes as GenTypes
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.StubMerger as StubMerger
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.CallGenBase as CallGenBase
import lib.core.Handles.ExprCallTable as ExprCallTable
# ============================================================
# CallGenCtor - CallGenMixin 拆分(阶段 B):结构体构造 / 枚举构造 / 泛型构造 / 类型转换
#
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class CallGenCtor(CallGenBase.CallGenBase):
"""结构体构造 / 枚举构造 / 泛型构造 / 类型转换"""
# ============================================================
# _apply_struct_defaults — 应用结构体字段的默认值
#
# 在 zeroinitializer 之后、显式参数之前调用
# 遍历所有字段,对有默认值的字段翻译并 store
# 显式参数(位置/关键字)后续会覆盖默认值
# ============================================================
def _apply_struct_defaults(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
struct_ty: llvmlite.LLVMType | t.CPtr,
class_name: str,
tmp: llvmlite.Value | t.CPtr,
trans: HT.Translator | t.CPtr):
"""应用结构体字段的默认值"""
# 用类型指针定位 entry,规避跨模块同名 find_struct 找错
entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct_by_type(struct_ty)
if entry is None:
# fast-fail: 结构体类型未注册,静默 return 会导致字段未初始化
VLogger.error(
f"结构体类型未注册,无法应用默认值: {class_name}",
"HandlesExprCall")
return
for fi in range(entry.FieldCount):
fe: GenTypes.FieldEntry | t.CPtr = self.Gen.StructGen._get_field_entry(
entry, fi)
if fe is None:
# fast-fail: 字段索引越界(entry.FieldCount 与实际不一致)
VLogger.error(
f"字段索引越界,无法获取字段 entry: {class_name}",
"HandlesExprCall")
continue
if fe.DefaultVal is None:
continue # 合理跳过:无默认值的字段
# 静态数组字段 + 列表字面量默认值 → 整体置零 + 逐元素 GEP+store
# (与 _generate_before_init 一致;translate_value 会把列表字面量
# 误译成动态 list 对象指针,coerce 到 [N x elem] 会失败)。
# Mixin 静态绑定:跨 Mixin 方法必须走 HandlesAnnAssign 模块级委托。
if fe.Ty is not None and self.Gen.ExprGenBase.is_array_type(fe.Ty) != 0 \
and fe.DefaultVal.kind() == ast.ASTKind.List:
field_ptr_arr2: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, struct_ty, fe.Ty, tmp, fe.Index)
if field_ptr_arr2 is not None:
zero_arr2: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, fe.Ty)
if zero_arr2 is not None:
llvmlite.build_store(builder, zero_arr2, field_ptr_arr2)
self.Gen.AssignGen._init_global_array_from_list(
builder, pool, mod, field_ptr_arr2, fe.DefaultVal, trans)
continue
default_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, fe.DefaultVal, None, 0, trans)
if default_val is None:
# fast-fail: 默认值翻译失败(如引用了未定义符号)
VLogger.error(
f"字段默认值翻译失败: {class_name}",
"HandlesExprCall")
continue
field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, struct_ty, fe.Ty, tmp, fe.Index)
if field_ptr is None:
# fast-fail: GEP 失败(struct_ty 与 fe.Ty 不匹配)
VLogger.error(
f"字段 GEP 失败,类型不匹配: {class_name}",
"HandlesExprCall")
continue
default_val = self.Gen.ExprGenBase.coerce_to_type(builder, default_val, fe.Ty, fe.DefaultVal)
llvmlite.build_store(builder, default_val, field_ptr)
# ============================================================
# _translate_struct_ctor — 结构体构造函数 Point(10, 20)
#
# 生成:
# %tmp = alloca {i32, i32}
# store {i32, i32} zeroinitializer, {i32, i32}* %tmp
# %f0 = getelementptr {i32, i32}, {i32, i32}* %tmp, i32 0, i32 0
# store i32 10, i32* %f0
# %f1 = getelementptr {i32, i32}, {i32, i32}* %tmp, i32 0, i32 1
# store i32 20, i32* %f1
# %result = load {i32, i32}, {i32, i32}* %tmp
# ============================================================
# ============================================================
def _translate_struct_ctor(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
struct_ty: llvmlite.LLVMType | t.CPtr,
class_name: str,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""结构体构造函数:按字段顺序 store 参数值,返回结构体值
OOP 结构体:alloca → call __before_init__(ptr) → call __init__(ptr, args) 或 store 参数 → load
普通结构体:alloca → zero + defaults → store 参数 → load
"""
# 创建临时 alloca
# 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间)
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, struct_ty)
tmp: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, struct_ty)
if tmp is None:
return llvmlite.ConstZero(pool, struct_ty)
# 诊断节点:取第一个构造实参(有行号),供 _call_method_on_ptr 的
# fatal_error 显示构造调用行号(本函数无 cl 参数,实参节点最接近调用点)
diag_node_ct: ast.AST | t.CPtr = None
if cargs is not None and len(cargs) > 0:
diag_node_ct = cargs.get(0)
# 检查是否为 OOP 结构体(用类型指针定位 entry,规避跨模块同名 find_struct 找错)
ctor_entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct_by_type(struct_ty)
is_oop: int = 0
if ctor_entry is not None:
is_oop = ctor_entry.IsOOP
# 跨模块 OOP 类推断:IsOOP 可能未设置(Phase1 缓存跳过 _translate_oop_methods)
# 方案1: 检查当前模块是否有 ClassName.__init__ 的声明(stub 注入)
# 方案2: 检查全局默认参数表是否有 ClassName.__init__ 的条目(翻译时填充,更可靠)
if is_oop == 0 and class_name is not None:
init_lookup_name: str = pool.alloc(128)
if init_lookup_name is not None:
viperlib.snprintf(init_lookup_name, 128, "%s.__init__", class_name)
# 方案1: 检查当前模块的函数声明
init_found_func: llvmlite.Function | t.CPtr = self.find_func_in_module(mod, init_lookup_name)
if init_found_func is not None:
is_oop = 1
if ctor_entry is not None:
ctor_entry.IsOOP = 1
ctor_entry.HasInit = 1
else:
# 方案2: 检查全局默认参数表(翻译时填充,不依赖 stub 注入)
init_defaults_entry: FuncDefaultsEntry | t.CPtr = self.Gen.CallGenLeafKit.find_func_defaults(init_lookup_name)
if init_defaults_entry is not None:
is_oop = 1
if ctor_entry is not None:
ctor_entry.IsOOP = 1
ctor_entry.HasInit = 1
if is_oop != 0:
# 存储指针:默认用 alloca,如果有 __new__ 则用 __new__ 返回的指针
storage_ptr: llvmlite.Value | t.CPtr = tmp
# 如果有 __new__,调用 __new__(tmp, args...) 获取实际存储指针
# __new__ 签名与 __init__ 一样(self + args),返回 Ptr(struct_ty)
has_new_flag: int = 0
if ctor_entry is not None:
has_new_flag = ctor_entry.HasNew
# 注意: __new__ 是可选的,不推断 HasNew(仅 __init__ 是 OOP 类标准方法)
if has_new_flag != 0:
new_arg_vals: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
if new_arg_vals is not None:
string.memset(new_arg_vals, 0, 8 * 32)
new_arg_count: int = 0
for nai in range(can):
new_arg_node: ast.AST | t.CPtr = cargs.get(nai)
if new_arg_node is None:
continue
new_av: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, new_arg_node, None, 0, trans)
if new_av is not None:
if new_arg_count < 32:
new_arg_vals[new_arg_count] = t.CSizeT(new_av)
new_arg_count += 1
new_ptr: llvmlite.Value | t.CPtr = self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, class_name,
"__new__", tmp, new_arg_vals, new_arg_count, trans, diag_node_ct)
if new_ptr is not None:
storage_ptr = new_ptr
# __new__ 只保证返回"实例存储指针",声明类型通常是
# `-> t.CPtr`(i8*),与类的真实类型 Ptr(struct_ty) 不一致。
# 若直接使用,构造结果变量类型退化为 Ptr(i8),无注解变量的
# obj.method(如 parser.add_argument)get_class_name_by_type
# 查不到类名,误报"跨模块调用 'parser.add_argument' 找不到模块 SHA1"。
# bitcast 只改类型层视图,运行时零开销(指针位不变)。
if new_ptr.Ty is not None:
nw_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty)
if t.CUInt64T(new_ptr.Ty) != t.CUInt64T(nw_ty):
nw_bc: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, new_ptr, nw_ty)
if nw_bc is not None:
storage_ptr = nw_bc
# OOP 结构体:调用 __before_init__ 进行零值填充和默认值赋值
self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name,
"__before_init__", storage_ptr, None, 0, trans, diag_node_ct)
# 如果有 __init__,调用 __init__(ptr, args...)
# 注意: 仅依据 ctor_entry.HasInit 判断,不强制推断
# (JsonValue 等类有 __new__ 但无 __init__,强制推断会导致 undefined reference)
has_init_flag: int = 0
if ctor_entry is not None:
has_init_flag = ctor_entry.HasInit
if has_init_flag != 0:
# 翻译构造函数参数
arg_vals: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
if arg_vals is not None:
string.memset(arg_vals, 0, 8 * 32)
real_arg_count: int = 0
for ai in range(can):
arg_node: ast.AST | t.CPtr = cargs.get(ai)
if arg_node is None:
continue
av: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, arg_node, None, 0, trans)
if av is not None:
if real_arg_count < 32:
arg_vals[real_arg_count] = t.CSizeT(av)
real_arg_count += 1
self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name,
"__init__", storage_ptr, arg_vals, real_arg_count, trans, diag_node_ct)
elif has_new_flag == 0:
# 无 __init__ 且无 __new__:逐字段 store 参数值
# (有 __new__ 时参数已由 __new__ 消费,不应存入字段)
for ai in range(can):
arg: ast.AST | t.CPtr = cargs.get(ai)
if arg is None:
continue
arg_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, arg, None, 0, trans)
if arg_val is None:
# fast-fail: 参数翻译失败
VLogger.error(
f"构造函数参数翻译失败: {class_name}",
"HandlesExprCall")
continue
fe: GenTypes.FieldEntry | t.CPtr = None
if ctor_entry is not None:
# OOP 结构体字段表第 0 个字段是 __vtable__(vtable 指针占位),
# 构造参数按"用户字段顺序"存储:必须跳过 __vtable__ 字段,
# 否则参数会覆盖 vtable 槽(对象头读到垃圾指针,
# isinstance 的 icmp 全部不匹配 + 方法分派错乱)。
# 原实现直接 _get_field_entry(ctor_entry, ai) 取到 __vtable__
# → GEP Index 0 → 覆盖 vtable(Dog("dog") 场景崩溃漂移根因)。
target_idx: int = 0
for fi in range(ctor_entry.FieldCount):
cand_fe: GenTypes.FieldEntry | t.CPtr = self.Gen.StructGen._get_field_entry(
ctor_entry, fi)
if cand_fe is None:
continue
cand_name: str = self.Gen.StructGen.get_field_name_ptr(cand_fe)
if cand_name is not None and string.strcmp(cand_name, "__vtable__") == 0:
continue
if target_idx == ai:
fe = cand_fe
break
target_idx += 1
else:
fe = self.Gen.StructGen.get_field_by_index(class_name, ai)
if fe is None:
# fast-fail: 字段索引越界(用户传了多余参数)
VLogger.error(
f"构造函数参数过多,字段索引越界: {class_name}",
"HandlesExprCall")
continue
field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, struct_ty, fe.Ty, storage_ptr, fe.Index)
if field_ptr is None:
# fast-fail: GEP 失败(struct_ty 与 fe.Ty 不匹配)
VLogger.error(
f"构造函数字段 GEP 失败: {class_name}",
"HandlesExprCall")
continue
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, fe.Ty, arg)
llvmlite.build_store(builder, arg_val, field_ptr)
# 返回指针(而非结构体值),赋值时由 coerce_to_type 按目标类型决定是否 load
return storage_ptr
# 普通结构体:先 store zeroinitializer 清零(确保未赋值字段为零)
zero: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, struct_ty)
llvmlite.build_store(builder, zero, tmp)
# 应用默认值(显式参数会覆盖默认值)
self._apply_struct_defaults(pool, builder, mod, struct_ty, class_name, tmp, trans)
# 逐字段 store 参数值(覆盖默认值)
for ai in range(can):
arg: ast.AST | t.CPtr = cargs.get(ai)
if arg is None:
continue
arg_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, arg, None, 0, trans)
if arg_val is None:
# fast-fail: 参数翻译失败
VLogger.error(
f"构造函数参数翻译失败: {class_name}",
"HandlesExprCall")
continue
# 获取字段信息(用 ctor_entry 规避跨模块同名 find_struct 找错)
fe: GenTypes.FieldEntry | t.CPtr = None
if ctor_entry is not None:
fe = self.Gen.StructGen._get_field_entry(ctor_entry, ai)
else:
fe = self.Gen.StructGen.get_field_by_index(class_name, ai)
if fe is None:
# fast-fail: 字段索引越界(用户传了多余参数)
VLogger.error(
f"构造函数参数过多,字段索引越界: {class_name}",
"HandlesExprCall")
continue
# GEP 到字段 ai
field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, struct_ty, fe.Ty, tmp, fe.Index)
if field_ptr is None:
# fast-fail: GEP 失败(struct_ty 与 fe.Ty 不匹配)
VLogger.error(
f"构造函数字段 GEP 失败: {class_name}",
"HandlesExprCall")
continue
# 类型转换并 store
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, fe.Ty, arg)
llvmlite.build_store(builder, arg_val, field_ptr)
# 返回指针(而非结构体值),赋值时由 coerce_to_type 按目标类型决定是否 load
return tmp
# ============================================================
# _translate_renum_construct — REnum 变体构造函数
#
# 语法: ClassName.VariantName(args...)
# 如 LLVMType.Int(1) → 构造 LLVMType 的 Int 变体,__tag=0,_p1=1
#
# 生成 IR:
# %tmp = alloca {i32, i32, ...} ; REnum 类型
# store zeroinitializer, %tmp ; 清零
# %tag_ptr = gep %tmp, 0, 0 ; __tag 字段
# store i32 <tag_value>, %tag_ptr ; 写入 tag
# %p1_ptr = gep %tmp, 0, 1 ; _p1 字段
# store <coerced_arg0>, %p1_ptr ; 写入 payload[0]
# ... (更多 payload 字段)
# return %tmp ; 返回指针
#
# 对应 TPC 的 _HandleREnumConstructLlvm
# ============================================================
# ============================================================
def _translate_renum_construct(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
class_name: str,
variant_name: str,
tag_value: int,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""构造 REnum 变体实例,返回指向 alloca 的指针
class_name: REnum 类名(如 "LLVMType")
variant_name: 变体名(如 "Int")
tag_value: 变体的 tag 值(变体在类中的索引)
cargs: 参数 AST 列表
can: 参数数量
"""
if pool is None or builder is None or class_name is None:
return None
# 查找 REnum 结构体类型(用 find_struct_by_module 规避跨模块同名)
renum_entry: GenTypes.StructEntry | t.CPtr = None
if trans is not None:
renum_entry = self.Gen.StructGen.find_struct_by_module(class_name, trans.ModuleSha1)
if renum_entry is None:
renum_entry = self.Gen.StructGen.find_struct(class_name)
if renum_entry is None:
fb_re: str = VLogger.fmt_buf()
if fb_re is not None:
viperlib.snprintf(fb_re, 1024, "REnum construct: type %s not registered", class_name)
VLogger.error(fb_re, "RENUM")
return None
renum_ty: llvmlite.LLVMType | t.CPtr = renum_entry.Ty
if renum_ty is None:
return None
# alloca REnum 类型
# 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间)
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, renum_ty)
tmp: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, renum_ty)
if tmp is None:
return llvmlite.ConstZero(pool, renum_ty)
# 清零(确保未赋值的 payload 位置为零)
zero: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, renum_ty)
llvmlite.build_store(builder, zero, tmp)
# 写入 __tag 字段(索引 0)
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
tag_name_buf: str = pool.alloc(32)
if tag_name_buf is not None:
viperlib.snprintf(tag_name_buf, 32, "%d", tag_value)
tag_const: llvmlite.Value | t.CPtr = llvmlite.ConstInt(
pool, i32_ty, tag_value,
tag_name_buf if tag_name_buf is not None else "0")
tag_field: GenTypes.FieldEntry | t.CPtr = self.Gen.StructGen._get_field_entry(renum_entry, 0)
tag_field_ty: llvmlite.LLVMType | t.CPtr = i32_ty
if tag_field is not None and tag_field.Ty is not None:
tag_field_ty = tag_field.Ty
tag_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, renum_ty, tag_field_ty, tmp, 0)
if tag_ptr is not None:
llvmlite.build_store(builder, tag_const, tag_ptr)
# 写入 payload 字段(索引 1, 2, ... 对应 _p1, _p2, ...)
# 参数按位置顺序填充 payload,跳过 __tag(索引 0)
for ai in range(can):
arg: ast.AST | t.CPtr = cargs.get(ai)
if arg is None:
continue
arg_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, arg, None, 0, trans)
if arg_val is None:
continue
# payload 字段索引 = ai + 1(跳过 __tag)
payload_idx: int = ai + 1
if payload_idx >= renum_entry.FieldCount:
break
pfe: GenTypes.FieldEntry | t.CPtr = self.Gen.StructGen._get_field_entry(
renum_entry, payload_idx)
if pfe is None:
continue
payload_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, renum_ty, pfe.Ty, tmp, payload_idx)
if payload_ptr is None:
continue
# 类型转换并 store(payload 位置可能是 i32 或 i64,按字段类型 coerce)
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, pfe.Ty, arg)
llvmlite.build_store(builder, arg_val, payload_ptr)
# 返回指针(与 _translate_struct_ctor 一致,赋值时由 coerce_to_type 决定是否 load)
return tmp
# ============================================================
# _translate_struct_ctor_kw — 结构体构造函数(关键字参数)
#
# 支持两种语法:
# Point(x=10, y=20) — 全关键字
# Point(10, y=20) — 混合(位置 + 关键字)
#
# 位置参数按字段索引赋值,关键字参数按字段名查找赋值
# ============================================================
# ============================================================
def _translate_struct_ctor_kw(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
struct_ty: llvmlite.LLVMType | t.CPtr,
class_name: str,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
keywords: list[ast.AST | t.CPtr] | t.CPtr,
kw_count: t.CSizeT,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""结构体构造函数(关键字参数版本)"""
# 创建临时 alloca
# 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间)
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, struct_ty)
tmp: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, struct_ty)
if tmp is None:
return llvmlite.ConstZero(pool, struct_ty)
# 诊断节点:取第一个构造实参(有行号),供 _call_method_on_ptr 的
# fatal_error 显示构造调用行号(本函数无 cl 参数,实参节点最接近调用点)
diag_node_ct: ast.AST | t.CPtr = None
if cargs is not None and len(cargs) > 0:
diag_node_ct = cargs.get(0)
# OOP 结构体:调用 __before_init__ 进行零值填充和默认值赋值
# 用 find_struct_by_type 规避跨模块同名 find_struct 找错
kw_entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct_by_type(struct_ty)
is_oop: int = 0
if kw_entry is not None:
is_oop = kw_entry.IsOOP
# 跨模块 OOP 类推断:IsOOP 可能未设置(Phase1 缓存跳过 _translate_oop_methods)
# 方案1: 检查当前模块是否有 ClassName.__init__ 的声明(stub 注入)
# 方案2: 检查全局默认参数表是否有 ClassName.__init__ 的条目(翻译时填充,更可靠)
if is_oop == 0 and class_name is not None:
kw_init_lookup: str = pool.alloc(128)
if kw_init_lookup is not None:
viperlib.snprintf(kw_init_lookup, 128, "%s.__init__", class_name)
# 方案1: 检查当前模块的函数声明
kw_init_found: llvmlite.Function | t.CPtr = self.find_func_in_module(mod, kw_init_lookup)
if kw_init_found is not None:
is_oop = 1
if kw_entry is not None:
kw_entry.IsOOP = 1
kw_entry.HasInit = 1
else:
# 方案2: 检查全局默认参数表(翻译时填充,不依赖 stub 注入)
kw_init_defaults: FuncDefaultsEntry | t.CPtr = self.Gen.CallGenLeafKit.find_func_defaults(kw_init_lookup)
if kw_init_defaults is not None:
is_oop = 1
if kw_entry is not None:
kw_entry.IsOOP = 1
kw_entry.HasInit = 1
if is_oop != 0:
self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name,
"__before_init__", tmp, None, 0, trans)
else:
# 普通结构体:store zeroinitializer + 应用默认值
zero: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, struct_ty)
llvmlite.build_store(builder, zero, tmp)
self._apply_struct_defaults(pool, builder, mod, struct_ty, class_name, tmp, trans)
# OOP 结构体且有 __init__:调用 __init__ 而非逐字段 store
# 关键字构造调用此前总是逐字段 store,导致 __init__ 方法体不执行
# (如 self._args = mb.alloc(...) 不执行 → self._args 为 NULL → add_argument 崩溃)
has_init_flag: int = 0
has_new_flag: int = 0
if kw_entry is not None:
has_init_flag = kw_entry.HasInit
has_new_flag = kw_entry.HasNew
# 跨模块 OOP 类: HasInit 可能未设置(_translate_oop_methods 未被调用)
# 但 IsOOP=1 说明类有方法,推断 HasInit=1(__init__ 在目标模块中存在)
# 注意: __new__ 是可选的,不推断 HasNew(仅 __init__ 是 OOP 类标准方法)
if is_oop != 0 and has_init_flag == 0:
has_init_flag = 1
if is_oop != 0 and has_init_flag != 0:
# 有 __init__:构建参数数组并调用 __init__
storage_ptr: llvmlite.Value | t.CPtr = tmp
# 如果有 __new__,调用 __new__ 获取实际存储指针
if has_new_flag != 0:
new_arg_vals: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
if new_arg_vals is not None:
string.memset(new_arg_vals, 0, 8 * 32)
new_arg_count: int = 0
for nai in range(can):
new_arg_node: ast.AST | t.CPtr = cargs.get(nai)
if new_arg_node is None:
continue
new_av: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, new_arg_node, None, 0, trans)
if new_av is not None:
if new_arg_count < 32:
new_arg_vals[new_arg_count] = t.CSizeT(new_av)
new_arg_count += 1
# 关键字参数也传递给 __new__
for nki in range(kw_count):
nkw: ast.Keyword | t.CPtr = (ast.Keyword | t.CPtr)(keywords.get(nki))
if nkw is None or nkw.value is None:
continue
nkw_av: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, nkw.value, None, 0, trans)
if nkw_av is not None:
if new_arg_count < 32:
new_arg_vals[new_arg_count] = t.CSizeT(nkw_av)
new_arg_count += 1
new_ptr: llvmlite.Value | t.CPtr = self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, class_name,
"__new__", tmp, new_arg_vals, new_arg_count, trans, diag_node_ct)
if new_ptr is not None:
storage_ptr = new_ptr
# __new__ 只保证返回"实例存储指针",声明类型通常是
# `-> t.CPtr`(i8*),与类的真实类型 Ptr(struct_ty) 不一致。
# 若直接使用,构造结果变量类型退化为 Ptr(i8),无注解变量的
# obj.method(如 parser.add_argument)get_class_name_by_type
# 查不到类名,误报"跨模块调用 'parser.add_argument' 找不到模块 SHA1"。
# bitcast 只改类型层视图,运行时零开销(指针位不变)。
if new_ptr.Ty is not None:
nw_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty)
if t.CUInt64T(new_ptr.Ty) != t.CUInt64T(nw_ty):
nw_bc: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, new_ptr, nw_ty)
if nw_bc is not None:
storage_ptr = nw_bc
# 构建 __init__ 参数数组:位置参数按顺序 + 关键字参数追加
init_arg_vals: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
if init_arg_vals is not None:
string.memset(init_arg_vals, 0, 8 * 32)
init_arg_count: int = 0
# 位置参数
for ai_init in range(can):
arg_node_init: ast.AST | t.CPtr = cargs.get(ai_init)
if arg_node_init is None:
continue
av_init: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, arg_node_init, None, 0, trans)
if av_init is not None:
if init_arg_count < 32:
init_arg_vals[init_arg_count] = t.CSizeT(av_init)
init_arg_count += 1
# 关键字参数(追加到末尾,按出现顺序)
for ki_init in range(kw_count):
kw_init: ast.Keyword | t.CPtr = (ast.Keyword | t.CPtr)(keywords.get(ki_init))
if kw_init is None or kw_init.value is None:
continue
kw_av_init: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, kw_init.value, None, 0, trans)
if kw_av_init is not None:
if init_arg_count < 32:
init_arg_vals[init_arg_count] = t.CSizeT(kw_av_init)
init_arg_count += 1
# 调用 __init__(storage_ptr, *args)
self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name,
"__init__", storage_ptr, init_arg_vals, init_arg_count, trans, diag_node_ct)
# 返回指针
return storage_ptr
# 无 __init__(或非 OOP):逐字段 store 参数值
# 先处理位置参数(按字段索引,覆盖默认值)
for ai in range(can):
arg: ast.AST | t.CPtr = cargs.get(ai)
if arg is None:
continue
arg_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, arg, None, 0, trans)
if arg_val is None:
continue
fe: GenTypes.FieldEntry | t.CPtr = None
if kw_entry is not None:
fe = self.Gen.StructGen._get_field_entry(kw_entry, ai)
else:
fe = self.Gen.StructGen.get_field_by_index(class_name, ai)
if fe is None:
# 位置参数越界(字段表无对应项):fail-fast,绝不静默跳过
self.Gen.TypeGenErr.fatal_error(
arg, f"结构体 '{class_name}' 位置参数越界(无对应字段)", "TypeError")
continue
field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, struct_ty, fe.Ty, tmp, fe.Index)
if field_ptr is None:
continue
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, fe.Ty, arg)
llvmlite.build_store(builder, arg_val, field_ptr)
# 处理关键字参数(按字段名查找)
# SHA1 从 kw_entry 获取(规避跨模块同名 find_struct 找错)
kw_sha1: str = None
if kw_entry is not None:
kw_sha1 = kw_entry.ModuleSha1
for ki in range(kw_count):
kw: ast.Keyword | t.CPtr = (ast.Keyword | t.CPtr)(keywords.get(ki))
if kw is None or kw.arg is None or kw.value is None:
continue
fe: GenTypes.FieldEntry | t.CPtr = self.Gen.StructGen.lookup_field_by_class(
class_name, kw.arg, kw_sha1)
if fe is None:
# 关键字字段不存在:fail-fast(AttributeError),绝不静默跳过
self.Gen.TypeGenErr.fatal_error(
kw, f"结构体 '{class_name}' 无字段 '{kw.arg}'", "AttributeError")
continue
kw_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, kw.value, None, 0, trans)
if kw_val is None:
continue
field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, struct_ty, fe.Ty, tmp, fe.Index)
if field_ptr is None:
continue
kw_val = self.Gen.ExprGenBase.coerce_to_type(builder, kw_val, fe.Ty, kw.value)
llvmlite.build_store(builder, kw_val, field_ptr)
# 返回指针(而非结构体值),赋值时由 coerce_to_type 按目标类型决定是否 load
return tmp
# ============================================================
# _translate_t_type_cast - 翻译 t.XXX(value) 类型转换
#
# 当 func 是 t.XXX 形式且 XXX 是已知类型名(map_t_type 能映射)时,
# 将 value 转换为目标类型:
# - 指针 → 整数: ptrtoint (如 t.CUInt64T(ptr) → i64)
# - 整数 → 指针: inttoptr (如 t.CPtr(int_val) → i8*)
# - 整数 → 整数: trunc/zext (如 t.CInt8T(i32_val) → i8)
# - 指针 → 指针: bitcast (如 t.CPtr(ptr_val) → i8*)
# - 整数 → 浮点: sitofp (如 t.CDouble(i32_val) → double)
# - 浮点 → 整数: fptosi (如 t.CInt(double_val) → i32)
# - 浮点 → 浮点: fpext/fptrunc (如 t.CFloat(double_val) → float)
# ============================================================
# ============================================================
def _translate_t_type_cast(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
val: llvmlite.Value | t.CPtr,
target_ty: llvmlite.LLVMType | t.CPtr,
target_name: str = None,
src_node: ast.AST | t.CPtr = None,
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""类型转换:根据参数类型和目标类型选择转换方式
整数 → 整数拓宽时(对齐 TPC _HandleTypeCastLlvm L1723-1737):
源 i1(bool)→ zext
目标类型无符号(target_name 命中 CUIntXXT 等)→ zext
源表达式无符号(t.CUIntXXT(x) 强转 / 无符号注解变量)→ zext
否则 → sext(有符号整数拓宽保持数值,如 i8 -50 → 0xFFFFFFCE)
"""
if val is None or target_ty is None:
return None
val_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(val.Ty)
target_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(target_ty)
val_fbits: int = self.Gen.ExprGenBase.get_llvm_float_bits(val.Ty)
target_fbits: int = self.Gen.ExprGenBase.get_llvm_float_bits(target_ty)
# 整数 → 整数: trunc/zext/sext
if val_bits != 0 and target_bits != 0:
if val_bits == target_bits:
return val
elif val_bits < target_bits:
if val_bits == 1:
# i1 是布尔值(来自 icmp/fcmp),无符号语义,必须 zext
return llvmlite.build_zext(builder, val, target_ty)
# 目标类型名已知且为有符号 → 按源符号性 sext/zext(对齐 TPC L1723-1737);
# 目标名未知(int()/联合类型强转等)保持默认 zext(旧行为)
need_sext: int = 0
if target_name is not None and self.Gen.ExprGenOps._type_name_unsigned(target_name) == 0:
if src_node is None or self.Gen.ExprGenOps._node_type_unsigned(pool, src_node, trans) == 0:
need_sext = 1
if need_sext != 0:
return llvmlite.build_sext(builder, val, target_ty)
return llvmlite.build_zext(builder, val, target_ty)
else:
return llvmlite.build_trunc(builder, val, target_ty)
# 整数 → 浮点: sitofp
if val_bits != 0 and target_fbits != 0:
return llvmlite.build_si2fp(builder, val, target_ty)
# 浮点 → 整数: fptosi
if val_fbits != 0 and target_bits != 0:
return llvmlite.build_fp2si(builder, val, target_ty)
# 浮点 → 浮点: fpext/fptrunc
if val_fbits != 0 and target_fbits != 0:
if val_fbits == target_fbits:
return val
elif val_fbits < target_fbits:
return llvmlite.build_fpext(builder, val, target_ty)
else:
return llvmlite.build_fptrunc(builder, val, target_ty)
# 指针 → 整数: ptrtoint
if val_bits == 0 and val_fbits == 0 and target_bits != 0:
return llvmlite.build_ptrtoint(builder, val, target_ty)
# 整数 → 指针: inttoptr(必须排除浮点 target,浮点 target_bits 也是 0)
if val_bits != 0 and target_bits == 0 and target_fbits == 0:
return llvmlite.build_inttoptr(builder, val, target_ty)
# 指针 → 指针: bitcast
return llvmlite.build_bitcast(builder, val, target_ty)
# ============================================================
# 泛型实例化辅助:从 Subscript slice 提取类型实参名
# ============================================================
# _get_type_name_from_annotation 已移至 HandlesType.py(支持 BinOp/Attribute)
# HandlesExprCall 通过 HandlesType._get_type_name_from_annotation 调用
# ============================================================
# 泛型实例化辅助:从 Subscript slice 提取类型实参名
# ============================================================
# _get_type_name_from_annotation 已移至 HandlesType.py(支持 BinOp/Attribute)
# HandlesExprCall 通过 HandlesType._get_type_name_from_annotation 调用
def _extract_type_args_from_slice(self, pool: memhub.MemBuddy | t.CPtr,
slice_node: ast.AST | t.CPtr) -> list[str] | t.CPtr:
"""从 Subscript.slice 提取类型实参名列表
list[int] -> ["int"]
dict[str, int] -> ["str", "int"]
list[AST | t.CPtr] -> ["AST|t.CPtr"]
"""
if slice_node is None or pool is None:
return None
# elem_size=8:str 是 i8* 指针(8 字节),若用 4 则双元素时 append 写 8 字节
# 但步长按 4 计算,第 2 个元素覆盖第 1 个元素高 4 字节 → get 读出垃圾指针崩溃
result: list[str] | t.CPtr = list[str](pool, 8)
k: int = slice_node.kind()
if k == ast.ASTKind.Tuple:
tp: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(slice_node)
elts: list[ast.AST | t.CPtr] | t.CPtr = tp.elts
if elts is not None:
n: t.CSizeT = len(elts)
i: t.CSizeT
for i in range(n):
elt: ast.AST | t.CPtr = elts.get(i)
tn: str = self.Gen.TypeGenResolve._get_type_name_from_annotation(pool, elt)
if tn is not None:
result.append(tn)
else:
tn: str = self.Gen.TypeGenResolve._get_type_name_from_annotation(pool, slice_node)
if tn is not None:
result.append(tn)
return result
# ============================================================
# 泛型类构造调用辅助: list[str](pool, 8) → __new__ + __before_init__ + __init__
#
# 复用 translate_list_literal 的构造逻辑:
# 1. alloca tmp(特化类临时空间,作为 __new__ 的 self)
# 2. 翻译 cl.args 为参数指针数组
# 3. call __new__(tmp, *args) → storage_ptr
# 4. call __before_init__(storage_ptr)
# 5. call __init__(storage_ptr, *args)
# 6. return storage_ptr
#
# 必须独立于 translate_call 的普通函数路径:spec_name 是类名不是函数名,
# 走裸名路径会被 _lookup_mod_sha1 的 star import 回退误导,用错误的 SHA1
# 且缺少 __new__ 方法名后缀,导致链接报 undefined reference。
# ============================================================
# ============================================================
def _infer_generic_ctor_type_arg(self, pool: memhub.MemBuddy | t.CPtr,
arg_node: ast.AST | t.CPtr,
class_name: str) -> str:
"""从构造实参 AST 推断泛型类型实参名;无法推断时 fail-fast(绝不默认 "int")
裸名泛型类构造(Box(42) → Box[int])需要从实参推断类型实参。
对应 TPC _HandleGenericClassNewLlvm 的推断逻辑(常量/类型转换调用)。
注意:本函数仅做 AST 静态推断,不发射 IR(避免重复翻译实参)。
"""
if pool is None or arg_node is None:
self.Gen.TypeGenErr.fatal_error(
None,
f"无法从实参推断泛型类 '{class_name}' 的类型实参,请显式标注如 {class_name}[类型](...)",
"TypeError")
return "int"
k: int = arg_node.kind()
# 常量: 42→int, 3.14→double, "abc"→str
if k == ast.ASTKind.Constant:
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(arg_node)
if cn.const_kind == ast.CONST_FLOAT:
return "double"
if cn.const_kind == ast.CONST_STR:
return "str"
return "int"
# 类型转换调用: int(...)/float(...)/t.CInt(...)/t.CDouble(...)
if k == ast.ASTKind.Call:
cl_f: ast.Call | t.CPtr = (ast.Call | t.CPtr)(arg_node)
if cl_f.func is not None:
if cl_f.func.kind() == ast.ASTKind.Name:
fn_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cl_f.func)
if fn_nm.id is not None:
# 与下方 Attribute 分支的 strstr 匹配一致:from t import CInt
# 后 `CInt(0)` 的 func 是 Name("CInt"),仅精确匹配 int/float
# 会漏判 → fail-fast 误杀(VectorGenericTest 隐式泛型推断)。
if string.strcmp(fn_nm.id, "float") == 0 or string.strcmp(fn_nm.id, "double") == 0 \
or string.strstr(fn_nm.id, "Float") is not None or string.strstr(fn_nm.id, "Double") is not None:
return "double"
if string.strcmp(fn_nm.id, "int") == 0 \
or string.strstr(fn_nm.id, "Int") is not None or string.strstr(fn_nm.id, "UInt") is not None \
or string.strstr(fn_nm.id, "Char") is not None or string.strstr(fn_nm.id, "Short") is not None \
or string.strstr(fn_nm.id, "Long") is not None:
return "int"
elif cl_f.func.kind() == ast.ASTKind.Attribute:
fn_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl_f.func)
if fn_at.attr is not None:
if string.strstr(fn_at.attr, "Float") is not None or string.strstr(fn_at.attr, "Double") is not None:
return "double"
if string.strstr(fn_at.attr, "Int") is not None or string.strstr(fn_at.attr, "UInt") is not None or string.strstr(fn_at.attr, "Char") is not None or string.strstr(fn_at.attr, "Short") is not None or string.strstr(fn_at.attr, "Long") is not None:
return "int"
# 类型转换调用(Call)但函数名无法识别:明确的类型意图却无法解析,
# fail-fast(区别于普通变量 Name——那是非 T 参数,默认 int 被过滤)。
self.Gen.TypeGenErr.fatal_error(
arg_node,
f"无法从实参推断泛型类 '{class_name}' 的类型实参,请显式标注如 {class_name}[类型](...)",
"TypeError")
return "int"
# 非类型转换节点(普通变量 Name/Attribute 等,如 Vector(pool, 8, ...)
# 的 pool 参数):不是 T 类型提示,返回默认 "int"(调用方"过滤纯 int"
# 逻辑将其排除,只保留 float/str 等区分性提示)。
return "int"
def _translate_generic_ctor_call(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
spec_name: str,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""泛型类构造调用: list[str](pool, 8) → __new__ + __before_init__ + __init__"""
if pool is None or builder is None or mod is None or spec_name is None or cl is None:
return None
# 查找 struct entry 获取类型
struct_entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct(spec_name)
if struct_entry is None:
self.Gen.TypeGenErr.fatal_error(cl, "泛型类构造调用: 特化类未注册")
return None
struct_ty: llvmlite.LLVMType | t.CPtr = struct_entry.Ty
if struct_ty is None:
return None
# 确保结构体定义在当前模块中可用(供 alloca 分配空间)
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, struct_ty)
# alloca tmp(self 指针)
tmp: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, struct_ty)
if tmp is None:
return None
# 翻译 cl.args 为参数指针数组(extra_args[i] = Value 指针)
cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args
can: t.CSizeT = 0
if cargs is not None:
can = len(cargs)
extra_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
if extra_args is None:
return None
string.memset(extra_args, 0, 8 * 32)
ai: t.CSizeT = 0
while ai < can:
if ai >= 32:
# 定长 8*32 槽:超过 32 个实参继续写会越界污染 pool 相邻块,fail-fast
self.Gen.TypeGenErr.fatal_error(
cl, "泛型构造实参超过 32 个上限", "TypeError")
break
arg_node: ast.AST | t.CPtr = cargs.get(ai)
if arg_node is not None:
arg_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, arg_node, None, 0, trans)
if arg_val is not None:
extra_args[ai] = t.CSizeT(arg_val)
ai += 1
# 存储指针:默认用 alloca,如果有 __new__ 则用 __new__ 返回的指针
# __new__ 是可选的,仅当泛型类模板定义了 __new__ 方法时才调用
# (与 _translate_struct_ctor 保持一致,避免为无 __new__ 的类生成过度声明)
storage_ptr: llvmlite.Value | t.CPtr = tmp
has_new_flag: int = 0
if struct_entry is not None:
has_new_flag = struct_entry.HasNew
if has_new_flag != 0:
new_ptr: llvmlite.Value | t.CPtr = self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, spec_name, "__new__", tmp, extra_args, can, trans)
if new_ptr is not None:
storage_ptr = new_ptr
# __new__ 只保证返回"实例存储指针",声明类型通常是
# `-> t.CPtr`(i8*),与类的真实类型 Ptr(struct_ty) 不一致。
# 若直接使用,构造结果变量类型退化为 Ptr(i8),无注解变量的
# obj.method(如 parser.add_argument)get_class_name_by_type
# 查不到类名,误报"跨模块调用 'parser.add_argument' 找不到模块 SHA1"。
# bitcast 只改类型层视图,运行时零开销(指针位不变)。
if new_ptr.Ty is not None:
nw_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty)
if t.CUInt64T(new_ptr.Ty) != t.CUInt64T(nw_ty):
nw_bc: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, new_ptr, nw_ty)
if nw_bc is not None:
storage_ptr = nw_bc
# call __before_init__(storage_ptr)(TransPyV 自动生成,零值填充)
self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, spec_name, "__before_init__", storage_ptr, None, 0, trans)
# call __init__(storage_ptr, *args)
self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, spec_name, "__init__", storage_ptr, extra_args, can, trans)
return storage_ptr