diff --git a/App/lib/core/Handles/HandlesExprCall.vp b/App/lib/core/Handles/HandlesExprCall.vp index 6b4d685..a984b4d 100644 --- a/App/lib/core/Handles/HandlesExprCall.vp +++ b/App/lib/core/Handles/HandlesExprCall.vp @@ -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