feat(compiler): __sizeof__ 支持实例接收者与泛型类引用(self/obj 实际类型 + Stack[T] 特化)
This commit is contained in:
1 parent
51d0ef2c18
commit
ba6beb439c
1 file changed
+56
-14
@@ -4901,9 +4901,13 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
elif sz_vk == ast.ASTKind.Attribute:
|
||||
sz_inner_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(sz_at.value)
|
||||
sz_cls_name = sz_inner_at.attr
|
||||
# 最终解析出的结构体类型:类型名命中 → 泛型特化(Stack[T])→ 实例接收者类型(self/obj)
|
||||
sz_resolved_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
sz_resolved_name: str = sz_cls_name
|
||||
if sz_cls_name is not None:
|
||||
# 泛型类型参数 T 替换: T.__sizeof__() → int.__sizeof__()
|
||||
sz_cls_name = HandlesType.resolve_generic_type_name(sz_cls_name)
|
||||
sz_resolved_name = sz_cls_name
|
||||
# 去除模块前缀: Viper 解析器将 t.CInt 解析为 Name(id="t.CInt")
|
||||
# 而非 Attribute(value=Name("t"), attr="CInt"),需要手动提取最后的类名分量
|
||||
# "t.CInt" → "CInt", "w32.win32file.WIN32_FIND_DATAA" → "WIN32_FIND_DATAA"
|
||||
@@ -4952,22 +4956,60 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
# ConstInt 的 name 参数是 IR 文本表示,ValuePrint 输出时使用 Name 而非 IntVal
|
||||
# 硬编码 "0" 会导致 IR 输出 i64 0 而非实际值
|
||||
return llvmlite.const_int64(pool, sz_builtin)
|
||||
sz_struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(
|
||||
sz_cls_name)
|
||||
if sz_struct_ty is not None:
|
||||
sz_val: int = HandlesClassDef._get_type_size(sz_struct_ty)
|
||||
if sz_val > 0:
|
||||
return llvmlite.const_int64(pool, sz_val)
|
||||
# 类型已注册但大小为 0(opaque struct 或字段链表未填充):Python 风格报错终止
|
||||
HandlesType.fatal_error(
|
||||
sz_at, f"类型 '{sz_cls_name}' 已注册但大小为 0(字段链表未填充),无法计算大小",
|
||||
"TypeError")
|
||||
# 类型未注册:Python 风格报错终止,不静默返回 0(会导致 malloc(0)/alloc(0) 堆溢出)。
|
||||
# 注意:__sizeof__ 的接收者若是变量名(如 self.__sizeof__()),sz_cls_name 是
|
||||
# 字面变量名("self")而非类型名,此报错即由此类误用触发(见 G5/GenericTest2)。
|
||||
sz_resolved_ty = HandlesStruct.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 | t.CPtr = (ast.Subscript | t.CPtr)(sz_at.value)
|
||||
if sub_sz.value is not None and sub_sz.value.kind() == ast.ASTKind.Name:
|
||||
gen_nm_sz: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub_sz.value)
|
||||
if gen_nm_sz.id is not None:
|
||||
gen_args_sz: list[str] | t.CPtr = _extract_type_args_from_slice(pool, sub_sz.slice)
|
||||
if gen_args_sz is not None and gen_args_sz.__len__() > 0:
|
||||
gargs_resolved: list[str] | t.CPtr = list[str](pool, 8)
|
||||
if gargs_resolved is not None:
|
||||
gai_sz: t.CSizeT = gen_args_sz.__len__()
|
||||
gai2_sz: t.CSizeT = 0
|
||||
for gai2_sz in range(gai_sz):
|
||||
gres_sz: str = HandlesType.resolve_generic_type_name(
|
||||
gen_args_sz.get(gai2_sz))
|
||||
gargs_resolved.append(gres_sz)
|
||||
spec_sz: str = HandlesClassDef._specialize_generic_class(
|
||||
trans, gen_nm_sz.id, gargs_resolved)
|
||||
if spec_sz is not None:
|
||||
sz_resolved_name = spec_sz
|
||||
sz_resolved_ty = HandlesStruct.get_struct_type(spec_sz)
|
||||
# 回退 2: 实例接收者 self.__sizeof__() / obj.__sizeof__() — 用接收者值的实际类型
|
||||
# (GenericTest2 Stack.size_of 依赖此路径;self 在方法内是 Ptr(Stack[int]))
|
||||
if sz_resolved_ty is None:
|
||||
inst_sz_val: llvmlite.Value | t.CPtr = HandlesExpr.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 _:
|
||||
pass
|
||||
case llvmlite.LLVMType.Struct(_, _, _):
|
||||
sz_resolved_ty = inst_sz_val.Ty
|
||||
case _:
|
||||
pass
|
||||
if sz_resolved_ty is not None:
|
||||
sz_val: int = HandlesClassDef._get_type_size(sz_resolved_ty)
|
||||
if sz_val > 0:
|
||||
return llvmlite.const_int64(pool, sz_val)
|
||||
# 类型已注册但大小为 0(opaque struct 或字段链表未填充):Python 风格报错终止
|
||||
HandlesType.fatal_error(
|
||||
sz_at, f"类型 '{sz_cls_name}' 未在结构体表中注册,无法计算大小",
|
||||
sz_at, f"类型 '{sz_resolved_name}' 已注册但大小为 0(字段链表未填充),无法计算大小",
|
||||
"TypeError")
|
||||
# 类型未注册:Python 风格报错终止,不静默返回 0(会导致 malloc(0)/alloc(0) 堆溢出)
|
||||
if sz_resolved_name is None:
|
||||
sz_resolved_name = "(unknown)"
|
||||
HandlesType.fatal_error(
|
||||
sz_at, f"类型 '{sz_resolved_name}' 未在结构体表中注册,无法计算大小",
|
||||
"TypeError")
|
||||
|
||||
# 检测 obj.__len__() — 返回 list 对象的 __count__ 字段(偏移 8,i64)
|
||||
# __len__ 是 list[T] 的内置方法,list 是泛型类不注册 struct
|
||||
|
||||
Reference in new issue
Block a user