fix(tpc): list 联合类型方法分派保护 + str 压平条件收紧 + external global 裸名兼容
- HandlesAssign: 变量已有同 base 声明类型时不再覆盖 var_struct_class(sha1 前缀特化名覆盖裸名,导致 dbody.get 查表 miss 后 fallback 到 list[int].get,i32 返回值被截断成垃圾指针崩溃——TPC 侧根治) - HandlesExprCall: IdentifiedStructType 真值判断改 is None(opaque 时 bool() 触发 __len__ assert) - HandlesFunctions/HandlesImports: IsStr 压平条件加 PtrCount<=1,str|t.CPtr(i8**) 不压平;external global 正则兼容裸名格式
This commit is contained in:
1 parent
3b0a73db5e
commit
50ca560563
4 files changed
+80
-28
No files matched your search
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user