修复了一些错误

This commit is contained in:
TermiNexus committed 2026-09-18 20:00:59 +08:00
1 parent 6af2dea917
commit 2cc816ac13
16 files changed
+1155 -230

No files matched your search

+134 -19
View File
@@ -8,7 +8,9 @@ import copy
import traceback
import llvmlite.ir as ir
from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta
from lib.core.SymbolUtils import IsTModule, FindStructNameInAnnotation, AnnotationContainsName
from lib.core.SymbolUtils import (
IsTModule, FindStructNameInAnnotationWithContext, AnnotationContainsName,
IsPtrSubscriptNode, DesugarPtrSubscriptToUnion)
from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode
from lib.includes import t
@@ -520,7 +522,8 @@ class FunctionHandle(BaseHandle):
if not isinstance(ReturnTypeInfo, CTypeInfo):
ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CVoid()
if (ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState) or ReturnTypeInfo.PtrCount >= 2:
if ((ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState)
or (ReturnTypeInfo.PtrCount >= 2 and ReturnTypeInfo.BaseType is None)):
def _FindNonVoidCTypeInfo(node: ast.AST) -> Any:
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
results: list[Any] = []
@@ -557,7 +560,10 @@ class FunctionHandle(BaseHandle):
is_str_type: bool = False
if isinstance(Node.returns, ast.Name) and Node.returns.id in ('str', 'bytes'):
is_str_type = True
ReturnTypeInfo = CTypeInfo.FromNode(Node.returns, self.Trans.SymbolTable)
# 走 ResolveAnnotationType 而非 CTypeInfo.FromNode:指针下标
# 返回注解(rawptr[T] / t.CPtr[T])需走 TypeMerge 通用解析,
# 否则内层跨模块类解析不出 → CVoid/1(i8*)。
ReturnTypeInfo = self.ResolveAnnotationType(Node.returns)
if ReturnTypeInfo and ReturnTypeInfo.IsDefine:
inferred: Any = self._infer_return_type_from_body(Node, Gen, ClassName)
if inferred:
@@ -637,9 +643,15 @@ class FunctionHandle(BaseHandle):
ReturnTypeInfo.PtrCount = 1 if inferred[1] else 0
IsPtr = ReturnTypeInfo.IsPtr if ReturnTypeInfo else False
ReturnType: ir.Type = Gen._ctype_to_llvm(ReturnTypeInfo)
if isinstance(ReturnType, ir.PointerType) and isinstance(ReturnType.pointee, ir.PointerType):
if isinstance(ReturnType.pointee.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)):
ReturnType = ir.PointerType(ReturnType.pointee.pointee)
# 此处原有 "Ptr(Ptr(Struct)) → Ptr(Struct)" 的压层(历史遗留):会把已解析的
# 多层指针返回类型(`-> rawptr[rawptr[X]]` / `-> X | t.CPtr | t.CPtr`)
# 与泛型特化方法返回(`list[X**]` 的 get/pop/__getitem__/__next__)少算一层,
# 与同函数的形参(`append(item: T)` 保留 `X**`)、声明端
# DeclarationGenerator._get_type_str 的 BinOp 分支(同样不压层,见
# '_is_bare_class_ref_annotation' 为假时逐层外包)以及 _EmitFunctionLlvm
# 的定义体路径全部不一致。违反"多层指针已解析时照原样保留层数"。
# 实测(36 用例 A/B)删除后仅 `list[X**]` 的 4 个方法 declare 由 `X*` 变
# `X**`,与 append/set 的形参一致;stub 逐字节不变。
if isinstance(ReturnType, ir.IntType) and ReturnType.width == 8:
if RawFuncName == '__str__':
ReturnType = ir.PointerType(ir.IntType(8))
@@ -681,7 +693,12 @@ class FunctionHandle(BaseHandle):
if Arg.annotation:
try:
ParamTypeInfo: Any
ParamTypeInfo = self.ResolveAnnotationType(Arg.annotation)
# 走 ResolveParamAnnotation(= ResolveAnnotationType + 泛型模板
# 识别):参数注解中的泛型容器(list[X] / rawptr[list[X]])与
# 指针下标(rawptr[X])需走 TypeMerge 通用解析,否则
# TypeAnnotationResolver 解析不出 → VoidType → 报
# "无法识别的参数类型注解"。
ParamTypeInfo = self.ResolveParamAnnotation(Arg.annotation)
if ParamTypeInfo is None:
ParamTypeInfo = CTypeInfo()
ParamTypeInfo.BaseType = t.CInt()
@@ -820,20 +837,113 @@ class FunctionHandle(BaseHandle):
def _make_replacement_node(self, replacement: str) -> ast.AST:
"""将 type_map 中的替换字符串转换为 AST 节点。
mangled 名称如 'sha1.ASTptr' 需要还原为 AST | t.CPtr 结构,
mangled 名称如 '<sha1>.AST*' 需要还原为 AST | t.CPtr 结构,
否则类型解析会丢失 PtrCount 信息。
含点号的名称(如 'sha1.AST')需解析为 ast.Attribute 链。
含点号的名称(如 '<sha1>.AST')需解析为 ast.Attribute 链。
下标形态('rawptr[ast.AST]' / 'list[AST]' 等)必须整体解析为 Subscript:
_make_name_node 只按 '.' 切分会把 'rawptr[ast.AST]' 拆成
Name('rawptr[ast') + Attribute('AST]'),两段都不是有效类型名 →
参数/返回注解解析为空 → VoidType → "无法识别的参数类型注解"。
指针下标(rawptr[T] / t.CPtr[T])再折叠为等价的 `T | t.CPtr`,与源码
联合写法同解析路径(对齐 TPV TypeGenResolve._parse_type_string 的 '['
分支 + ClassGenGeneric._clone_annotation 的 T 替换)。
内层为已混淆名(数字开头,如 'rawptr[7565e081d88517ac.AST]')时
ast.parse 无法解析(数字开头的令牌),改用手工拆 base/slice(同 TPV
TypeGenResolve._parse_type_string 的数字开头手工拆分分支)。
尾部 '*'(泛型实参 '<sha1>.Node*' / '<sha1>.Node**',来自 rawptr[T] /
t.CPtr 的逐层 mangling)逐层还原为 `Node | t.CPtr [| t.CPtr]` → 对应
层数指针;只剥一层会把 'Node*' 当结构体名建出 phantom opaque
(item 类型与特化名 '<sha1>.Node**' 的语义不一致)。
尾部 'ptr'(旧规则 mangling,如 'Nodeptr' / 'ast.ASTptr')保留兼容:
.vpi/stub 缓存里仍是旧名时按同样方式还原。
"""
StarCount: int = len(replacement) - len(replacement.rstrip('*'))
if StarCount > 0:
BaseName: str = replacement[:len(replacement) - StarCount]
base_node: ast.AST
if BaseName in ('i8', 'void', 'void*'):
# i8*(void*)在源码侧写作 t.CPtr;再叠加 StarCount-1 层
base_node = ast.Attribute(
value=ast.Name(id='t', ctx=ast.Load()), attr='CPtr', ctx=ast.Load())
StarCount -= 1
else:
base_node = self._make_name_node(BaseName)
node: ast.AST = base_node
for _ in range(StarCount):
node = ast.BinOp(
left=node,
op=ast.BitOr(),
right=ast.Attribute(
value=ast.Name(id='t', ctx=ast.Load()),
attr='CPtr', ctx=ast.Load()),
)
return node
if replacement.endswith('ptr'):
# 提取基础名称: 'sha1.ASTptr' -> 'sha1.AST'
base: str = replacement[:-3]
return ast.BinOp(
left=self._make_name_node(base),
op=ast.BitOr(),
right=ast.Attribute(value=ast.Name(id='t', ctx=ast.Load()), attr='CPtr', ctx=ast.Load())
)
# 提取基础名称:'sha1.ASTptr' → 'sha1.AST';'Nodeptrptr' → 'Node'(2 层)
base: str = replacement
levels: int = 0
while base.endswith('ptr') and len(base) > 3:
base = base[:-3]
levels += 1
node: ast.AST = self._make_name_node(base)
for _ in range(levels):
node = ast.BinOp(
left=node,
op=ast.BitOr(),
right=ast.Attribute(
value=ast.Name(id='t', ctx=ast.Load()),
attr='CPtr', ctx=ast.Load()),
)
return node
if '[' in replacement:
SubNode: ast.AST | None = None
try:
SubNode = ast.parse(replacement, mode='eval').body
except Exception:
SubNode = None
if not isinstance(SubNode, ast.Subscript):
SubNode = self._parse_subscript_manually(replacement)
if isinstance(SubNode, ast.Subscript):
if IsPtrSubscriptNode(SubNode, self.Trans.SymbolTable):
return DesugarPtrSubscriptToUnion(SubNode, self.Trans.SymbolTable)
return SubNode
return self._make_name_node(replacement)
def _parse_subscript_manually(self, replacement: str) -> ast.AST | None:
"""手工拆分单实参下标字符串(ast.parse 因数字开头标识符失败时使用)。
处理 `<base>[<inner>]`(整体以 ']' 结尾、单实参、无逗号;内层可为嵌套
单实参下标):'rawptr[7565e081d88517ac.AST]' → Subscript(Name('rawptr'),
Attribute(Name('7565e081d88517ac'), 'AST'));
'rawptr[rawptr[7565e081d88517ac.AST]]' → 外层 Subscript 的 slice 递归
拆出内层 Subscript(嵌套 rawptr 需两层指针)。带逗号等复杂形态返回
None(交调用方按普通名称处理),不做字符串猜测。
"""
open_idx: int = replacement.find('[')
if open_idx <= 0 or not replacement.endswith(']'):
return None
inner: str = replacement[open_idx + 1:-1]
if not inner or ',' in inner:
return None
base_name: str = replacement[:open_idx].strip()
inner_name: str = inner.strip()
if not base_name or not inner_name:
return None
slice_node: ast.AST | None
if '[' in inner_name or inner_name.endswith('*'):
# 嵌套单实参下标 / 指针层数内层(如 rawptr[rawptr[<sha1>.CLS]]、
# <sha1>.list[<sha1>.X*]):递归按同一还原规则拆解
slice_node = self._make_replacement_node(inner_name)
else:
try:
slice_node = ast.parse(inner_name, mode='eval').body
except Exception:
slice_node = self._make_name_node(inner_name)
if slice_node is None:
return None
return ast.Subscript(
value=self._make_name_node(base_name), slice=slice_node, ctx=ast.Load())
@staticmethod
def _make_name_node(name: str) -> ast.AST:
"""将可能含点号的名称转换为 ast.Name 或 ast.Attribute 链。
@@ -1323,7 +1433,8 @@ class FunctionHandle(BaseHandle):
if not isinstance(ReturnTypeInfo, CTypeInfo):
ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CVoid()
if (ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState) or ReturnTypeInfo.PtrCount >= 2:
if ((ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState)
or (ReturnTypeInfo.PtrCount >= 2 and ReturnTypeInfo.BaseType is None)):
def _FindNonVoidCTypeInfo(node):
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
results = []
@@ -1359,7 +1470,10 @@ class FunctionHandle(BaseHandle):
is_str_type = False
if isinstance(Node.returns, ast.Name) and Node.returns.id in ('str', 'bytes'):
is_str_type = True
ReturnTypeInfo = CTypeInfo.FromNode(Node.returns, self.Trans.SymbolTable)
# 与 _GetFunctionSignatureLlvm 同口径:指针下标返回注解
# (rawptr[T] / t.CPtr[T])走 ResolveAnnotationType 的
# TypeMerge 通用解析,避免内层跨模块类退化为 i8*。
ReturnTypeInfo = self.ResolveAnnotationType(Node.returns)
if ReturnTypeInfo and ReturnTypeInfo.IsDefine:
inferred = self._infer_return_type_from_body(Node, Gen, ClassName)
if inferred:
@@ -1807,7 +1921,8 @@ class FunctionHandle(BaseHandle):
if not (_existing_ps == 'rawptr' or '.rawptr' in _existing_ps
or _existing_ps.startswith('rawptr[')):
continue
found_struct: str | None = FindStructNameInAnnotation(arg.annotation, Gen.structs)
found_struct: str | None = FindStructNameInAnnotationWithContext(
arg.annotation, self.Trans, Gen)
if found_struct:
Gen.var_struct_class[param_name] = found_struct
# 普通类注解形参(非 BinOp 联合):rawptr[X] / t.CPtr[X] / X / t.X