diff --git a/lib/core/Handles/HandlesAssign.py b/lib/core/Handles/HandlesAssign.py index 96953cc..b2aa216 100644 --- a/lib/core/Handles/HandlesAssign.py +++ b/lib/core/Handles/HandlesAssign.py @@ -186,8 +186,19 @@ class AssignHandle(BaseHandle): CN: str = found[0] ST: ir.Type = found[1] found_class = CN - Gen.var_struct_class[VarName] = CN - Gen._var_to_heap_ptr[VarName] = Value + # 同类特化覆盖保护:简单赋值(如 dbody = dbody2)会经 + # find_struct_by_pointee 拿到带 sha1 前缀的 IR 特化名 + # (list[f467...ASTptr]),覆盖声明注解解析出的裸名 + # (list[ast.ASTptr])→ 方法调用(dbody.get)按该名查 + # SymbolTable/functions 时 miss → fallback 到 list[int].get + # → i32 返回值被 zext+inttoptr 当指针 → 崩溃。因此变量已有 + # 同 base 的声明类型时不覆盖(保留声明名,方法解析走声明名)。 + _prev_cls: str | None = Gen.var_struct_class.get(VarName) + if _prev_cls and '[' in _prev_cls and '[' in CN and _prev_cls.split('[')[0] == CN.split('[')[0]: + pass + else: + Gen.var_struct_class[VarName] = CN + Gen._var_to_heap_ptr[VarName] = Value if found_class is None and isinstance(Value.type.pointee, ir.IdentifiedStructType): pointee_name: str = Value.type.pointee.name pointee_short: str = Gen._extract_short_name(pointee_name) @@ -201,8 +212,14 @@ class AssignHandle(BaseHandle): found_class = CN best_elem_count = elem_count if found_class: - Gen.var_struct_class[VarName] = found_class - Gen._var_to_heap_ptr[VarName] = Value + # 同类特化覆盖保护(见上方 L189 注释):短名匹配的 + # sha1 前缀变体不覆盖声明注解类型 + _prev_cls2: str | None = Gen.var_struct_class.get(VarName) + if _prev_cls2 and '[' in _prev_cls2 and '[' in found_class and _prev_cls2.split('[')[0] == found_class.split('[')[0]: + pass + else: + Gen.var_struct_class[VarName] = found_class + Gen._var_to_heap_ptr[VarName] = Value # 泛型类特化触发:返回类型是泛型类特化(如 list[str])但结构体尚未创建, # 或虽然找到了结构体但它是 opaque(来自 stub 声明,尚未发射方法体) _fd_struct_opaque: bool = False @@ -246,8 +263,14 @@ class AssignHandle(BaseHandle): gc_base, gc_type_args, Gen, type_names=gc_type_names) if gc_spec and gc_spec in Gen.structs: found_class = gc_spec - Gen.var_struct_class[VarName] = gc_spec - Gen._var_to_heap_ptr[VarName] = Value + # 同类特化覆盖保护(见上方 L189 注释): + # gc_spec 与声明注解类型同 base 时不覆盖 + _prev_cls3: str | None = Gen.var_struct_class.get(VarName) + if _prev_cls3 and '[' in _prev_cls3 and '[' in gc_spec and _prev_cls3.split('[')[0] == gc_spec.split('[')[0]: + pass + else: + Gen.var_struct_class[VarName] = gc_spec + Gen._var_to_heap_ptr[VarName] = Value else: if VarName in ('mctx', 's1ctx', 's2ctx', 's5ctx'): pass diff --git a/lib/core/Handles/HandlesExprCall.py b/lib/core/Handles/HandlesExprCall.py index 5aa6726..93c8741 100644 --- a/lib/core/Handles/HandlesExprCall.py +++ b/lib/core/Handles/HandlesExprCall.py @@ -2472,10 +2472,13 @@ class ExprCallHandle(BaseHandle): if len(ClassName) > 17 and ClassName[16] == '.': lookup_cls = ClassName[17:] st = Gen.structs.get(ClassName) - if (not st or not isinstance(st, ir.IdentifiedStructType) or st.elements is None) \ + # 注意:不能用 `not st` 做真值判断——IdentifiedStructType 定义 __len__, + # opaque(elements is None)时 bool(st) 触发 __len__ 的 assert(AssertionError)。 + # 必须用 `st is None` 身份比较。 + if (st is None or not isinstance(st, ir.IdentifiedStructType) or st.elements is None) \ and lookup_cls != ClassName: st = Gen.structs.get(lookup_cls) - if not st or not isinstance(st, ir.IdentifiedStructType) or st.elements is None: + if st is None or not isinstance(st, ir.IdentifiedStructType) or st.elements is None: return None members: list = Gen.class_members.get(lookup_cls, []) has_vtable: bool = (ClassName in Gen.class_vtable @@ -2556,8 +2559,10 @@ class ExprCallHandle(BaseHandle): # 组合类 MRO 中位于调用类之前(如 Combined(BaseA, BaseB),BaseB 内 # self.helper() 调 BaseA.helper)。此时 BaseB.this 指向组合类中 # BaseB 字段区起点,BaseA 区在它前面,this 前移 sizeof(定义类 struct)。 - anc_st: Any = Gen.structs.get(method_anc) or Gen.structs.get(anc_lookup) - if not anc_st or not isinstance(anc_st, ir.IdentifiedStructType) or anc_st.elements is None: + anc_st: Any = Gen.structs.get(method_anc) + if anc_st is None: + anc_st = Gen.structs.get(anc_lookup) + if anc_st is None or not isinstance(anc_st, ir.IdentifiedStructType) or anc_st.elements is None: return ObjVal sibling_delta: int = -Gen._get_struct_size(anc_st) if sibling_delta >= 0: diff --git a/lib/core/Handles/HandlesFunctions.py b/lib/core/Handles/HandlesFunctions.py index d7bfc96..4ab4e56 100644 --- a/lib/core/Handles/HandlesFunctions.py +++ b/lib/core/Handles/HandlesFunctions.py @@ -571,7 +571,9 @@ class FunctionHandle(BaseHandle): if ReturnTypeInfo is None: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CVoid() - if is_str_type or ReturnTypeInfo.IsStr: + # 仅指针层数 <=1 才算裸 str/bytes(i8*)。 + # `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),不能压平。 + if is_str_type or (ReturnTypeInfo.IsStr and ReturnTypeInfo.PtrCount <= 1): ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.PtrCount = 1 @@ -655,7 +657,9 @@ class FunctionHandle(BaseHandle): if CReturnTypes: for i, ReturnTypeNode in enumerate(CReturnTypes): ReturnTypeInfo = CTypeInfo.FromNode(ReturnTypeNode, self.Trans.SymbolTable) - if ReturnTypeInfo and ReturnTypeInfo.IsStr: + # 仅指针层数 <=1 才算裸 str/bytes(i8*)。 + # `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),不能压平。 + if ReturnTypeInfo and ReturnTypeInfo.IsStr and ReturnTypeInfo.PtrCount <= 1: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.PtrCount = 1 @@ -678,7 +682,10 @@ class FunctionHandle(BaseHandle): if ParamTypeInfo and getattr(ParamTypeInfo, 'IsCpythonObject', False) and not IsPtr: IsPtr = True ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1) - if ParamTypeInfo.IsStr or (isinstance(Arg.annotation, ast.Name) and Arg.annotation.id in ('str', 'bytes')): + # 仅当指针层数 <=1 时才压平为 i8*(裸 str/bytes)。 + # `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组), + # 不能压平,否则形参类型错误导致 _adjust_args 多 load 一层崩溃。 + if (ParamTypeInfo.IsStr and ParamTypeInfo.PtrCount <= 1) or (isinstance(Arg.annotation, ast.Name) and Arg.annotation.id in ('str', 'bytes')): ParamTypeInfo = CTypeInfo() ParamTypeInfo.BaseType = t.CChar() ParamTypeInfo.PtrCount = 1 @@ -1285,7 +1292,10 @@ class FunctionHandle(BaseHandle): else: try: rt_info = CTypeInfo.FromNode(Node.returns, self.Trans.SymbolTable) - if rt_info and rt_info.IsStr: + # 仅指针层数 <=1 才算裸 str/bytes(i8*)。 + # `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组), + # 不能压平,否则返回类型错误。 + if rt_info and rt_info.IsStr and rt_info.PtrCount <= 1: is_str_return = True except Exception as _e: if _config_mode == "strict": @@ -1353,7 +1363,9 @@ class FunctionHandle(BaseHandle): if ReturnTypeInfo is None: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CVoid() - if is_str_type or ReturnTypeInfo.IsStr: + # 仅指针层数 <=1 才算裸 str/bytes(i8*)。 + # `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),不能压平。 + if is_str_type or (ReturnTypeInfo.IsStr and ReturnTypeInfo.PtrCount <= 1): ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.PtrCount = 1 @@ -1438,7 +1450,10 @@ class FunctionHandle(BaseHandle): if ParamTypeInfo and getattr(ParamTypeInfo, 'IsCpythonObject', False) and not IsPtr: IsPtr = True ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1) - if ParamTypeInfo.IsStr or (isinstance(Arg.annotation, ast.Name) and Arg.annotation.id in ('str', 'bytes')): + # 仅当指针层数 <=1 时才压平为 i8*(裸 str/bytes)。 + # `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组), + # 不能压平,否则形参类型错误导致 _adjust_args 多 load 一层崩溃。 + if (ParamTypeInfo.IsStr and ParamTypeInfo.PtrCount <= 1) or (isinstance(Arg.annotation, ast.Name) and Arg.annotation.id in ('str', 'bytes')): ParamTypeInfo = CTypeInfo() ParamTypeInfo.BaseType = t.CChar() ParamTypeInfo.PtrCount = 1 @@ -1494,7 +1509,9 @@ class FunctionHandle(BaseHandle): CReturnLlvmTypes = [] for i, ReturnTypeNode in enumerate(CReturnTypes): ReturnTypeInfo = CTypeInfo.FromNode(ReturnTypeNode, self.Trans.SymbolTable) - if ReturnTypeInfo and ReturnTypeInfo.IsStr: + # 仅指针层数 <=1 才算裸 str/bytes(i8*)。 + # `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),不能压平。 + if ReturnTypeInfo and ReturnTypeInfo.IsStr and ReturnTypeInfo.PtrCount <= 1: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.PtrCount = 1 diff --git a/lib/core/Handles/HandlesImports.py b/lib/core/Handles/HandlesImports.py index 126941b..8930ed7 100644 --- a/lib/core/Handles/HandlesImports.py +++ b/lib/core/Handles/HandlesImports.py @@ -1210,7 +1210,9 @@ class ImportHandle(BaseHandle): if Node.returns: try: ReturnTypeInfo = self.ResolveAnnotationType(Node.returns) - if ReturnTypeInfo and ReturnTypeInfo.IsStr: + # 仅指针层数 <=1 才算裸 str/bytes(i8*)。 + # `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),不能压平。 + if ReturnTypeInfo and ReturnTypeInfo.IsStr and ReturnTypeInfo.PtrCount <= 1: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.PtrCount = 1 @@ -1309,7 +1311,10 @@ class ImportHandle(BaseHandle): if i == 0 and is_method and Arg.arg == 'self' and class_is_cpython: ParamIsPtr = True ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1) - if ParamTypeInfo.IsStr: + # 仅当指针层数 <=1 时才压平为 i8*(裸 str/bytes)。 + # `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组), + # 不能压平,否则形参类型错误导致 _adjust_args 多 load 一层崩溃。 + if (ParamTypeInfo.IsStr and ParamTypeInfo.PtrCount <= 1) or (isinstance(Arg.annotation, ast.Name) and Arg.annotation.id in ('str', 'bytes')): ParamTypeInfo = CTypeInfo() ParamTypeInfo.BaseType = t.CChar() ParamTypeInfo.PtrCount = 1 @@ -2695,16 +2700,18 @@ class ImportHandle(BaseHandle): _vlog().warning(f"处理导入失败: {_e}", "Exception") continue - # 全局变量声明:@sha1.name = external global TYPE(stub.ll 写入, - # 原加载器只解析 struct/declare、忽略全局变量 → TPC 编译 TPV 时 - # 跨模块全局变量(如 StubMerger._sha1_store_count)从未嵌入 - # Gen.module.globals → _lookup_module_global 恒 None → return - # 静默跳过 ret / 跨模块赋值丢失。此处嵌入 external 声明, - # 名称格式与定义一致(@{sha1}.{name},temp/*.text.ll 确认)。 - _gv_match = re.match(r'@("?)([a-f0-9]{16}\.[\w.\[\]]+)\1\s*=\s*external\s+global\s+(\S.*)', stripped) + # 全局变量声明:@name = external global TYPE(stub.ll 实际写入格式, + # 跨模块全局变量为裸名,如 @_sha1_store_arr;原正则只匹配 + # @sha1.name 前缀格式,实际从未命中 → TPC 编译 TPV 时跨模块 + # 全局变量(如 StubMerger._sha1_store_count)从未嵌入 + # Gen.module.globals → _lookup_module_global 恒 None → store/load + # 全部丢失 → memset(null) 崩溃。此处兼容裸名 + sha1 前缀两种格式, + # 名称与定义一致(temp/*.text.ll 均为裸名)。 + _gv_match = re.match(r'@("?)(?:([a-f0-9]{16})\.)?([\w.\[\]]+)\1\s*=\s*external\s+global\s+(\S.*)', stripped) if _gv_match: - _gv_name: str = _gv_match.group(2) - _gv_type_str: str = _gv_match.group(3).strip() + _gv_name: str = _gv_match.group(3) + _gv_sha1: str | None = _gv_match.group(2) + _gv_type_str: str = _gv_match.group(4).strip() # 去掉尾部修饰(zeroinitializer / , align N),只保留类型 _gv_type_str = re.sub(r'\s+zeroinitializer.*$', '', _gv_type_str) _gv_type_str = re.sub(r'\s*,\s*align\s+\d+.*$', '', _gv_type_str)