修复了一些错误
This commit is contained in:
1 parent
6af2dea917
commit
2cc816ac13
16 files changed
+1155
-230
No files matched your search
@@ -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
|
||||
|
||||
Reference in new issue
Block a user