Files
TransPyC/lib/includes/t.py
2026-07-18 19:25:40 +08:00

1163 lines
40 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 类型定义模块
from __future__ import annotations
import sys
import types
from typing import Any, ClassVar, Optional, TypeVar, Generic, TypeAlias
from lib.constants.config import mode as _ConfigMode
from lib.core.VLogger import get_logger as _vlog
# =============================================================================
# 类型映射常量
# =============================================================================
# 标记基类注册表(由 @_marker_base 装饰器自动注册,或手动添加)
_MARKER_BASES: set[str] = set()
def _marker_base(cls: type) -> type:
"""将类名注册为标记基类,供 HandlesClassDef 检测使用"""
_MARKER_BASES.add(cls.__name__)
return cls
# 平台相关类型的默认 Size可由 configure_platform 修改)
_LONG_SIZE = 64
_UNSIGNED_LONG_SIZE = 64
_WCHAR_T_SIZE = 32
_SIZE_T_SIZE = 64
_INTPTR_T_SIZE = 64
_UINTPTR_T_SIZE = 64
_PTRDIFF_T_SIZE = 64
def configure_platform(triple: Optional[str] = None) -> None:
"""根据目标三元组配置平台相关类型的大小
Args:
triple: LLVM 目标三元组字符串,如 'x86_64-pc-windows-gnu'
"""
global _LONG_SIZE, _UNSIGNED_LONG_SIZE, _WCHAR_T_SIZE
global _SIZE_T_SIZE, _INTPTR_T_SIZE, _UINTPTR_T_SIZE, _PTRDIFF_T_SIZE
if not triple:
return
triple_lower: str = triple.lower()
is_windows: bool = any(k in triple_lower for k in ('windows', 'win32', 'mingw', 'msvc', 'cygwin'))
is_32bit: bool = any(k in triple_lower for k in ('i386', 'i686'))
if is_windows:
_LONG_SIZE = 32 # Windows LLP64: long = 32 位
_UNSIGNED_LONG_SIZE = 32
_WCHAR_T_SIZE = 16 # Windows: wchar_t = 16 位
if is_32bit:
_SIZE_T_SIZE = 32
_INTPTR_T_SIZE = 32
_UINTPTR_T_SIZE = 32
_PTRDIFF_T_SIZE = 32
# =============================================================================
# CType 基类
# =============================================================================
class CType:
"""C 类型基类"""
PREFIX: ClassVar[str] = 'prefix'
BASE: ClassVar[str] = 'base'
POINTER: ClassVar[str] = 'ptr'
ARRAY: ClassVar[str] = 'array'
NAMED: ClassVar[str] = 'named'
STORAGE_CLASS: ClassVar[str] = 'storage_class'
TYPE_QUALIFIER: ClassVar[str] = 'type_qualifier'
position: ClassVar[frozenset[str]] = frozenset({BASE}) # 类属性,支持联合类型如 BASE | SPECIAL
def __init__(self, value: Any = None, *types: Any) -> None:
self.value: Any = value
self.types: tuple[Any, ...] = types
self.Name: str = ''
self.IsBasicType: bool = False
self.IsPointer: bool = False
self.IsSigned: Optional[bool] = None
self.Size: Optional[int] = None
def GetPositions(self) -> frozenset[str]:
"""获取 position 的 frozenset 形式"""
return self.position
@classmethod
def HasPosition(cls, pos: str) -> bool:
"""检查是否包含指定的位置"""
return pos in cls.position
@classmethod
def IsNamed(cls) -> bool:
"""检查是否是命名类型struct/union/enum/typedef 等)"""
return cls.NAMED in cls.position
@classmethod
def IsStorageClass(cls) -> bool:
"""检查是否是存储类修饰符"""
return cls.STORAGE_CLASS in cls.position
@classmethod
def IsTypeQualifier(cls) -> bool:
"""检查是否是类型限定符"""
return cls.TYPE_QUALIFIER in cls.position
@classmethod
def IsBasicType(cls) -> bool:
"""检查是否是基本类型"""
return cls.BASE in cls.position
@classmethod
def IsPrefix(cls) -> bool:
"""检查是否是前缀类型"""
return cls.PREFIX in cls.position
def rfind(self, s: str) -> None:
"""注解"""
pass
def get_position(self) -> frozenset[str]:
"""获取类型在声明中的位置"""
return self.position
def __merge__(self, types: Any) -> Any:
return types
def __or__(self, other: Any) -> list[Any]:
return [self, other]
def __set_default__(self, **kwargs: Any) -> CTypeDefault:
"""设置默认值/初始值,用于 static/global 变量的初始化
Args:
**kwargs: 成员名称和值的键值对
Returns:
包含默认值信息的 CTypeDefault 对象
"""
return CTypeDefault(self, **kwargs)
def GetFullType(self, VarName: str = '', ArraySizeStr: str = '') -> str:
"""获取完整的类型声明字符串
Args:
VarName: 变量名
ArraySizeStr: 数组大小字符串
Returns:
完整的类型声明字符串
"""
ptr_str: str = '*' if self.IsPointer else ''
if VarName:
return f'{self.Name}{ptr_str} {VarName}{ArraySizeStr}'
return f'{self.Name}{ptr_str}'
def __repr__(self) -> str:
ptr_str: str = '*' if self.IsPointer else ''
return f'CType({self.Name}{ptr_str}, IsBasicType={self.IsBasicType})'
class CChar(CType):
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = 8
class CInt(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = 32
class CShort(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = 16
class CLong(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = _LONG_SIZE
class CLongLong(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = 64
class CFloat(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: Optional[bool] = None
self.Size: int = 32
class CDouble(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: Optional[bool] = None
self.Size: int = 64
class CFloat8T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: Optional[bool] = None
self.Size: int = 8
class CFloat16T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: Optional[bool] = None
self.Size: int = 16
class CFloat32T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: Optional[bool] = None
self.Size: int = 32
class CFloat64T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: Optional[bool] = None
self.Size: int = 64
class CFloat128T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: Optional[bool] = None
self.Size: int = 128
class CVoid(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: Optional[bool] = None
self.Size: int = 0
class CUnsigned(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 32
class CUnsignedChar(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 8
class CUnsignedInt(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 32
class CUnsignedShort(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 16
class CUnsignedLong(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = _UNSIGNED_LONG_SIZE
class CUnsignedLongLong(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 64
class CSignedChar(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = 8
@_marker_base
class CStruct(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE, CType.NAMED})
def __init__(self, value: Any = None, name: Optional[str] = None) -> None:
self.name: Optional[str] = name
super().__init__(value)
@_marker_base
class CUnion(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE, CType.NAMED})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
@_marker_base
class CEnum(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE, CType.NAMED})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
Enum = CEnum
@_marker_base
class REnum(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE, CType.NAMED})
tag: int = 0 # 无用,只是个标记
def __init__(self, value: Any = None) -> None:
super().__init__(value)
'''
class Object(CType):
"""Python 对象类型,用于支持类方法外联函数"""
position = frozenset({CType.BASE, CType.NAMED})
def __init__(self, value=None):
super().__init__(value)
def __call__(self, cls):
return cls
'''
def Object() -> None:
pass
def CVTable() -> None:
pass
def NoVTable() -> None:
"""标记类为非多态继承基类:被子类继承时字段直接展平嵌入,不生成 vtable避免 vtable 开销。
区别于 @t.CVTable启用多态 vtable。对应 C++ 的非多态继承struct A : B {} 无 virtual"""
pass
def TLS() -> None:
"""标记函数为 TLS 初始化函数,首次调用时执行,后续调用跳过。
编译器自动生成全局标志变量和一次性执行检查代码。
"""
pass
# Object 和 CVTable 是普通函数Exception 是 Python 内建类型Enum 是 CEnum 的别名
# 这些名称无法通过 @_marker_base 装饰器自动注册,需手动添加到 _MARKER_BASES
# TLS 是函数装饰器标记,由编译器在函数处理阶段识别
_MARKER_BASES.update({'Object', 'CVTable', 'Exception', 'Enum'})
CTypedef: TypeAlias = TypeAlias
class _CTypedef(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX, CType.NAMED})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
class CAuto(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
class CRegister(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX, CType.STORAGE_CLASS})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
class CStatic(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX, CType.STORAGE_CLASS})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
class CExtern(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX, CType.STORAGE_CLASS})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
class CConst(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX, CType.TYPE_QUALIFIER})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
class CInline(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX, CType.STORAGE_CLASS})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
class CExport(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX, CType.STORAGE_CLASS})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
class CVolatile(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX, CType.TYPE_QUALIFIER})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
class CSizeT(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = _SIZE_T_SIZE
class CInt8T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = 8
class CInt16T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = 16
class CInt32T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = 32
class CInt64T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = 64
class CUInt8T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 8
class CUInt16T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 16
class CUInt32T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 32
class CUInt64T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 64
class CIntPtrT(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = _INTPTR_T_SIZE
class CUIntPtrT(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = _UINTPTR_T_SIZE
class CPtrDiffT(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = _PTRDIFF_T_SIZE
class CWCharT(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = _WCHAR_T_SIZE
class CChar8T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 8
class CChar16T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 16
class CChar32T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 32
class CBool(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 8
T = TypeVar("T")
class CPtr(CType, Generic[T]):
position: ClassVar[frozenset[str]] = frozenset({CType.POINTER})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
class CNeedPtr(CPtr):
"""函数签名注解:自动取地址(仅对非指针值)。
用作参数类型时,编译器在调用处自动将非指针值取地址为指针。
若参数已经是指针,则不做操作。"""
position: ClassVar[frozenset[str]] = frozenset({CType.POINTER})
auto_addr_mode: ClassVar[str] = 'need'
def __init__(self, value: Any = None) -> None:
super().__init__(value)
class CAutoPtr(CPtr):
"""函数签名注解:无条件取地址。
用作参数类型时,编译器在调用处无条件将值取地址为指针,
即使值本身已经是指针也会再取一层地址。"""
position: ClassVar[frozenset[str]] = frozenset({CType.POINTER})
auto_addr_mode: ClassVar[str] = 'always'
def __init__(self, value: Any = None) -> None:
super().__init__(value)
class CTypeDefault(CType):
"""用于存储 C 类型默认值/初始化的包装类
当使用 t.CStatic.__set_default__(open=mouse_open, ...) 时创建
"""
def __init__(self, BaseType: Any, **kwargs: Any) -> None:
super().__init__()
self.BaseType: Any = BaseType
self.defaults: dict[str, Any] = kwargs
self.position: frozenset[str] = BaseType.position if hasattr(BaseType, 'position') else CType.BASE
def __repr__(self) -> str:
return f'CTypeDefault({self.BaseType}, {self.defaults})'
class CArrayPtr(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.POINTER})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
class CArray(CType):
"""栈上固定数组类型注解。
用法: names: t.CArray[VOIDPTR, 32] # void*[32]
data: t.CArray[t.CInt, 64] # int[64]
第一个参数为元素类型,第二个参数为数组大小(整数或常量名)。"""
position: ClassVar[frozenset[str]] = frozenset({CType.ARRAY})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
def __class_getitem__(cls, item: Any) -> type:
return cls
class CDefine(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
class CPass(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
class State(CType):
"""状态标记,用于仅声明不定义,等价于 CExport | CExtern"""
position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX, CType.STORAGE_CLASS})
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 t.State() 调用"""
return ['t.State']
class Postdefinition:
def __init__(self, c: Any) -> None:
pass
class Bit:
def __init__(self, i: Any) -> None:
pass
class BigEndian(CType):
"""大端序Big-Endian字节序标记类
用于标记结构体成员应使用大端序存储。
在小端序平台如x86上读取时会自动进行字节交换。
用法示例:
class MyStruct:
a: t.CInt | t.BigEndian # 大端序存储的整数
"""
IsSigned: ClassVar[bool] = True
Size: ClassVar[int] = 32
Align: ClassVar[int] = 32
class LittleEndian(CType):
"""小端序Little-Endian字节序标记类
用于标记结构体成员应使用小端序存储。
在小端序平台如x86上读取时不需要进行字节交换。
用法示例:
class MyStruct:
b: t.CInt | t.LittleEndian # 小端序存储的整数
"""
IsSigned: ClassVar[bool] = True
Size: ClassVar[int] = 32
Align: ClassVar[int] = 32
class ASM_DESCR:
"""内嵌 ASM 破坏描述符类
定义了所有可能的破坏描述符和约束字符,用于 GCC 内嵌汇编
"""
# 操作数修饰符
MODIFIER_OUTPUT = '=' # 输出操作数
MODIFIER_READWRITE = '+' # 读写操作数
MODIFIER_INPUT = '' # 输入操作数(默认)
MODIFIER_GLOBAL = '&' # 全局操作数
# 寄存器约束32位命名
REG_ANY = 'r' # 任何通用寄存器
REG_EAX = 'a' # EAX/RAX 寄存器
REG_EBX = 'b' # EBX/RBX 寄存器
REG_ECX = 'c' # ECX/RCX 寄存器
REG_EDX = 'd' # EDX/RDX 寄存器
REG_ESI = 'S' # ESI/RSI 寄存器
REG_EDI = 'D' # EDI/RDI 寄存器
REG_STACK = 'q' # 任何通用寄存器EAX, EBX, ECX, EDX
REG_FLOAT = 'f' # 浮点寄存器
REG_MMX = 'y' # MMX 寄存器
REG_XMM = 'x' # XMM 寄存器
# 寄存器约束64位命名GCC约束字符与32位相同
REG_RAX = 'a' # RAX 寄存器
REG_RBX = 'b' # RBX 寄存器
REG_RCX = 'c' # RCX 寄存器
REG_RDX = 'd' # RDX 寄存器
REG_RSI = 'S' # RSI 寄存器
REG_RDI = 'D' # RDI 寄存器
REG_R8 = 'r' # R8 寄存器需通过r约束+显式指定)
REG_R9 = 'r' # R9 寄存器
REG_R10 = 'r' # R10 寄存器
REG_R11 = 'r' # R11 寄存器
REG_R12 = 'r' # R12 寄存器
REG_R13 = 'r' # R13 寄存器
REG_R14 = 'r' # R14 寄存器
REG_R15 = 'r' # R15 寄存器
REG_RBP = 'r' # RBP 寄存器
REG_RSP = 'r' # RSP 寄存器
# 内存约束
MEMORY = 'm' # 内存操作数
# 立即数约束
IMMEDIATE = 'i' # 立即数
IMMEDIATE_CONST = 'n' # 常量立即数
# 综合约束
ANY = 'g' # 任何通用寄存器、内存或立即数
MEMORY_OR_REG = 'o' # 内存或寄存器
# 破坏描述符clobber list
CLOBBER_EAX = 'eax' # 破坏 EAX/RAX 寄存器
CLOBBER_EBX = 'ebx' # 破坏 EBX/RBX 寄存器
CLOBBER_ECX = 'ecx' # 破坏 ECX/RCX 寄存器
CLOBBER_EDX = 'edx' # 破坏 EDX/RDX 寄存器
CLOBBER_ESI = 'esi' # 破坏 ESI/RSI 寄存器
CLOBBER_EDI = 'edi' # 破坏 EDI/RDI 寄存器
CLOBBER_EBP = 'ebp' # 破坏 EBP/RBP 寄存器
CLOBBER_ESP = 'esp' # 破坏 ESP/RSP 寄存器
CLOBBER_AL = 'al' # 破坏 AL 寄存器EAX/RAX 低8位
CLOBBER_AH = 'ah' # 破坏 AH 寄存器EAX/RAX 高8位
CLOBBER_BL = 'bl' # 破坏 BL 寄存器EBX/RBX 低8位
CLOBBER_BH = 'bh' # 破坏 BH 寄存器EBX/RBX 高8位
CLOBBER_CL = 'cl' # 破坏 CL 寄存器ECX/RCX 低8位
CLOBBER_CH = 'ch' # 破坏 CH 寄存器ECX/RCX 高8位
CLOBBER_DL = 'dl' # 破坏 DL 寄存器EDX/RDX 低8位
CLOBBER_DH = 'dh' # 破坏 DH 寄存器EDX/RDX 高8位
CLOBBER_CC = 'cc' # 破坏条件代码寄存器(标志寄存器)
CLOBBER_MEMORY = 'memory' # 破坏内存(表示汇编代码修改了内存)
# 16 位寄存器破坏描述符
CLOBBER_AX = 'ax' # 破坏 AX 寄存器
CLOBBER_BX = 'bx' # 破坏 BX 寄存器
CLOBBER_CX = 'cx' # 破坏 CX 寄存器
CLOBBER_DX = 'dx' # 破坏 DX 寄存器
CLOBBER_SI = 'si' # 破坏 SI 寄存器
CLOBBER_DI = 'di' # 破坏 DI 寄存器
CLOBBER_BP = 'bp' # 破坏 BP 寄存器
# 64位寄存器破坏描述符
CLOBBER_RAX = 'rax' # 破坏 RAX 寄存器
CLOBBER_RBX = 'rbx' # 破坏 RBX 寄存器
CLOBBER_RCX = 'rcx' # 破坏 RCX 寄存器
CLOBBER_RDX = 'rdx' # 破坏 RDX 寄存器
CLOBBER_RSI = 'rsi' # 破坏 RSI 寄存器
CLOBBER_RDI = 'rdi' # 破坏 RDI 寄存器
CLOBBER_RBP = 'rbp' # 破坏 RBP 寄存器
CLOBBER_RSP = 'rsp' # 破坏 RSP 寄存器
CLOBBER_R8 = 'r8' # 破坏 R8 寄存器
CLOBBER_R9 = 'r9' # 破坏 R9 寄存器
CLOBBER_R10 = 'r10' # 破坏 R10 寄存器
CLOBBER_R11 = 'r11' # 破坏 R11 寄存器
CLOBBER_R12 = 'r12' # 破坏 R12 寄存器
CLOBBER_R13 = 'r13' # 破坏 R13 寄存器
CLOBBER_R14 = 'r14' # 破坏 R14 寄存器
CLOBBER_R15 = 'r15' # 破坏 R15 寄存器
# 预定义的组合约束32位命名
OUTPUT_REG = '=r' # 输出操作数,使用任何通用寄存器
OUTPUT_MEM = '=m' # 输出操作数,使用内存
OUTPUT_EAX = '=a' # 输出操作数,使用 EAX/RAX 寄存器
OUTPUT_EBX = '=b' # 输出操作数,使用 EBX/RBX 寄存器
OUTPUT_ECX = '=c' # 输出操作数,使用 ECX/RCX 寄存器
OUTPUT_EDX = '=d' # 输出操作数,使用 EDX/RDX 寄存器
OUTPUT_ESI = '=S' # 输出操作数,使用 ESI/RSI 寄存器
OUTPUT_EDI = '=D' # 输出操作数,使用 EDI/RDI 寄存器
# 预定义的组合约束64位命名
OUTPUT_RAX = '=a' # 输出操作数,使用 RAX 寄存器
OUTPUT_RBX = '=b' # 输出操作数,使用 RBX 寄存器
OUTPUT_RCX = '=c' # 输出操作数,使用 RCX 寄存器
OUTPUT_RDX = '=d' # 输出操作数,使用 RDX 寄存器
OUTPUT_RSI = '=S' # 输出操作数,使用 RSI 寄存器
OUTPUT_RDI = '=D' # 输出操作数,使用 RDI 寄存器
INPUT_REG = 'r' # 输入操作数,使用任何通用寄存器
INPUT_MEM = 'm' # 输入操作数,使用内存
INPUT_EAX = 'a' # 输入操作数,使用 EAX/RAX 寄存器
INPUT_EBX = 'b' # 输入操作数,使用 EBX/RBX 寄存器
INPUT_ECX = 'c' # 输入操作数,使用 ECX/RCX 寄存器
INPUT_EDX = 'd' # 输入操作数,使用 EDX/RDX 寄存器
INPUT_ESI = 'S' # 输入操作数,使用 ESI/RSI 寄存器
INPUT_EDI = 'D' # 输入操作数,使用 EDI/RDI 寄存器
INPUT_IMM = 'i' # 输入操作数,使用立即数
INPUT_ANY = 'g' # 输入操作数,使用任何通用寄存器、内存或立即数
# 输入约束64位命名
INPUT_RAX = 'a' # 输入操作数,使用 RAX 寄存器
INPUT_RBX = 'b' # 输入操作数,使用 RBX 寄存器
INPUT_RCX = 'c' # 输入操作数,使用 RCX 寄存器
INPUT_RDX = 'd' # 输入操作数,使用 RDX 寄存器
INPUT_RSI = 'S' # 输入操作数,使用 RSI 寄存器
INPUT_RDI = 'D' # 输入操作数,使用 RDI 寄存器
# 所有单独约束字符列表
ALL_CONSTRAINTS = [
# 操作数修饰符
MODIFIER_OUTPUT, MODIFIER_READWRITE, MODIFIER_INPUT, MODIFIER_GLOBAL,
# 寄存器约束
REG_ANY, REG_EAX, REG_EBX, REG_ECX, REG_EDX, REG_ESI, REG_EDI,
REG_STACK, REG_FLOAT, REG_MMX, REG_XMM,
# 内存约束
MEMORY,
# 立即数约束
IMMEDIATE, IMMEDIATE_CONST,
# 综合约束
ANY, MEMORY_OR_REG
]
# 所有破坏描述符列表
ALL_CLOBBERS = [
CLOBBER_EAX, CLOBBER_EBX, CLOBBER_ECX, CLOBBER_EDX,
CLOBBER_ESI, CLOBBER_EDI, CLOBBER_EBP, CLOBBER_ESP,
CLOBBER_CC, CLOBBER_MEMORY,
CLOBBER_RAX, CLOBBER_RBX, CLOBBER_RCX, CLOBBER_RDX,
CLOBBER_RSI, CLOBBER_RDI, CLOBBER_RBP, CLOBBER_RSP,
CLOBBER_R8, CLOBBER_R9, CLOBBER_R10, CLOBBER_R11,
CLOBBER_R12, CLOBBER_R13, CLOBBER_R14, CLOBBER_R15
]
# 所有描述符列表
ALL = ALL_CONSTRAINTS + ALL_CLOBBERS
# 定义 ASM_LIST包含所有可能的汇编约束字符
ASM_LIST: list[str] = ASM_DESCR.ALL
class attr:
"""C 语言 __attribute__ 属性操作类型"""
@staticmethod
def noreturn() -> str:
return "noreturn"
@staticmethod
def format(printf: Any, arg1: Any, arg2: Any) -> str:
return f"format({printf}, {arg1}, {arg2})"
@staticmethod
def section(name: str) -> str:
return f'section("{name}")'
@staticmethod
def aligned(bytes: int) -> str:
return f"aligned({bytes})"
@staticmethod
def packed() -> str:
return "packed"
@staticmethod
def unused() -> str:
return "unused"
@staticmethod
def used() -> str:
return "used"
@staticmethod
def weak() -> str:
return "weak"
@staticmethod
def alias(name: str) -> str:
return f'alias("{name}")'
@staticmethod
def visibility(type: str) -> str:
return f'visibility("{type}")'
@staticmethod
def constructor() -> str:
return "constructor"
@staticmethod
def destructor() -> str:
return "destructor"
@staticmethod
def always_inline() -> str:
return "always_inline"
@staticmethod
def noinline() -> str:
return "noinline"
@staticmethod
def pure() -> str:
return "pure"
@staticmethod
def const() -> str:
return "const"
@staticmethod
def malloc() -> str:
return "malloc"
@staticmethod
def alloc_size(n: int) -> str:
return f"alloc_size({n})"
@staticmethod
def warn_unused_result() -> str:
return "warn_unused_result"
@staticmethod
def deprecated(msg: Optional[str] = None) -> str:
if msg:
return f'deprecated("{msg}")'
return "deprecated"
@staticmethod
def fallthrough() -> str:
return "fallthrough"
@staticmethod
def likely() -> str:
return "likely"
@staticmethod
def unlikely() -> str:
return "unlikely"
@staticmethod
def hot() -> str:
return "hot"
@staticmethod
def cold() -> str:
return "cold"
@staticmethod
def interrupt() -> str:
return "interrupt"
@staticmethod
def naked() -> str:
return "naked"
@staticmethod
def sentinel(n: int = 0) -> str:
return f"sentinel({n})"
@staticmethod
def nonnull(*args: Any) -> str:
if args:
return f"nonnull({', '.join(map(str, args))})"
return "nonnull"
@staticmethod
def returns_nonnull() -> str:
return "returns_nonnull"
@staticmethod
def access(mode: Any, *args: Any) -> str:
return f"access({mode}, {', '.join(map(str, args))})"
@staticmethod
def cleanup(func: str) -> str:
return f'cleanup({func})'
@staticmethod
def transparent_union() -> str:
return "transparent_union"
@staticmethod
def mode(mode_name: str) -> str:
return f"mode({mode_name})"
@staticmethod
def vector_size(bytes: int) -> str:
return f"vector_size({bytes})"
@staticmethod
def target(string: str) -> str:
return f'target("{string}")'
@staticmethod
def optimize(level: str) -> str:
return f'optimize("{level}")'
@staticmethod
def no_instrument_function() -> str:
return "no_instrument_function"
@staticmethod
def no_sanitize(type: str) -> str:
return f"no_sanitize({type})"
@staticmethod
def no_stack_protector() -> str:
return "no_stack_protector"
@staticmethod
def stack_protector() -> str:
return "stack_protector"
@staticmethod
def error(msg: str) -> str:
return f'error("{msg}")'
@staticmethod
def warning(msg: str) -> str:
return f'warning("{msg}")'
class llvm:
"""LLVM 函数属性描述符
用于在返回类型注解中指定 LLVM 函数属性。
例如: def foo() -> t.CInt | t.attr.llvm.nobuiltin | t.attr.llvm.nounwind:
"""
# 以下空类仅作为类型注解占位符使用,由 HandlesFunctions._GetAttrLLVMName
# 从 AST 直接提取属性名node.attr不依赖 CName 属性。
class nobuiltin: pass
class nounwind: pass
class noredzone: pass
class willreturn: pass
class mustprogress: pass
class optnone: pass
class noinline: pass
class alwaysinline: pass
class readnone: pass
class readonly: pass
class writeonly: pass
class inaccessiblememonly: pass
class inaccessiblemem_or_argmemonly: pass
class CTypeRegistry:
"""基于 CType 元属性的类型注册表,替代手动映射表
利用 CType 子类的 position/IsSigned/Size 元属性自动推导:
- LLVM IR 类型字符串 (如 'i32', 'double', 'i8*')
- C 类型名称 (如 'int', 'unsigned char', 'long long')
- Python CType 类引用 (如 t.CInt32T)
"""
_name_to_class: ClassVar[Optional[dict[str, type]]] = None
@classmethod
def _build(cls) -> None:
if cls._name_to_class is not None:
return
mod: Optional[types.ModuleType] = sys.modules.get(__name__)
if mod is None:
return
cls._name_to_class = {}
for name, obj in vars(mod).items():
if not isinstance(obj, type) or not issubclass(obj, CType) or obj is CType:
continue
if obj in (CTypeDefault, BigEndian, LittleEndian):
continue
try:
inst: Any = obj()
except Exception:
continue
pos: frozenset[str] = getattr(obj, 'position', frozenset())
if CType.PREFIX in pos and CType.BASE not in pos:
continue
if CType.POINTER in pos and CType.BASE not in pos:
cls._name_to_class[name] = obj
continue
# 注册基本类型(有 Size和命名基本类型CStruct/CUnion/CEnum/REnum
# 不再依赖 CName 属性,依据 position/Size 推断。
if getattr(inst, 'Size', None) is not None or CType.NAMED in pos:
cls._name_to_class[name] = obj
@classmethod
def GetClassByName(cls, name: str) -> Optional[type]:
"""根据 Python 类名获取 CType 类 (如 'CInt32T' -> t.CInt32T)"""
cls._build()
return cls._name_to_class.get(name)
@staticmethod
def CTypeToLLVM(ctype_class: Optional[type]) -> str:
"""从 CType 类的元属性推导 LLVM IR 类型字符串
规则:
- position 含 POINTER 且不含 BASE → 'i8*'
- position 含 PREFIX 且不含 BASE → '' (修饰符,无LLVM类型)
- Size == 0 且 IsSigned is None → 'void'
- IsSigned is None 且 Size > 0 → 浮点: half/float/double/fp128
- IsSigned is True/False 且 Size > 0 → 整数: i{Size}
"""
if ctype_class is None:
return 'i8*'
pos: frozenset[str] = getattr(ctype_class, 'position', frozenset())
if CType.POINTER in pos and CType.BASE not in pos:
return 'i8*'
if CType.PREFIX in pos and CType.BASE not in pos:
return ''
try:
inst: Any = ctype_class()
except Exception:
return 'i8*'
size: Optional[int] = getattr(inst, 'Size', None)
is_signed: Optional[bool] = getattr(inst, 'IsSigned', None)
if size is None or size == 0:
if is_signed is None:
return 'void'
return 'i8*'
if is_signed is None:
float_map: dict[int, str] = {8: 'half', 16: 'half', 32: 'float', 64: 'double', 128: 'fp128'}
return float_map.get(size, f'f{size}')
return f'i{size}'
_llvm_to_ctype_cache: ClassVar[Optional[dict[str, type]]] = None
@classmethod
def LLVMToCType(cls, llvm_str: str) -> Optional[type]:
if cls._llvm_to_ctype_cache is None:
cls._build()
cls._llvm_to_ctype_cache = {}
for name, ctype_cls in cls._name_to_class.items():
pos: frozenset[str] = getattr(ctype_cls, 'position', frozenset())
if CType.PREFIX in pos and CType.BASE not in pos:
continue
llvm_key: str = cls.CTypeToLLVM(ctype_cls)
if llvm_key and llvm_key not in cls._llvm_to_ctype_cache:
cls._llvm_to_ctype_cache[llvm_key] = ctype_cls
return cls._llvm_to_ctype_cache.get(llvm_str)
@classmethod
def NameToLLVM(cls, name: str) -> Optional[str]:
"""根据 Python 类型名推导 LLVM IR 类型 (如 'CFloat64T' -> 'double')
修饰符类型 (CConst, CStatic 等) 返回空字符串。
指针类型 (CPtr) 返回 'i8*'
未知类型返回 None。
"""
cls._build()
mod: Optional[types.ModuleType] = sys.modules.get(__name__)
if mod and hasattr(mod, name):
obj: Any = getattr(mod, name)
if isinstance(obj, type) and issubclass(obj, CType):
return cls.CTypeToLLVM(obj)
return None
@classmethod
def ResolveName(cls, name: str) -> Optional[tuple[type, int]]:
"""解析类型名到 (CType类, 指针层级)
支持的格式:
- Python 类名: 'CInt32T' -> (t.CInt32T, 0)
- C 基本类型名/Python 内置名: 'int' -> (t.CInt, 0), 'bool' -> (t.CBool, 0)
注意stdint.h 类型名int8_t/uint8_t/size_t/intptr_t 等)和
Win32 大写别名INT8/UINT8/BYTE/DWORD/FLOAT8 等)由 stdint.py
通过 t.CTypedef 提供,用户 `from stdint import *` 后即可使用。
指针必须使用 t.CPtr[T] 显式表达(如 t.CPtr[t.CInt]
本方法不再做 PTR 后缀的隐式类型推断,以避免违反类型自由原则。
"""
cls._build()
direct: Optional[type] = cls._name_to_class.get(name)
if direct is not None:
pos: frozenset[str] = getattr(direct, 'position', frozenset())
ptr_level: int = 1 if CType.POINTER in pos and CType.BASE not in pos else 0
return (direct, ptr_level)
# C 基本类型名 / Python 内置类型名 → Python 类名硬编码表。
# 仅保留语言内置名称stdint.h 类型名由 stdint.py 的 typedef 提供。
_CNAME_ALIAS: dict[str, str] = {
# Python 内置类型名
'bool': 'CBool', 'int': 'CInt', 'float': 'CFloat',
# C 基本类型名
'char': 'CChar', 'short': 'CShort', 'long': 'CLong',
'long long': 'CLongLong', 'double': 'CDouble', 'void': 'CVoid',
'unsigned': 'CUnsigned', 'signed': 'CInt', 'signed int': 'CInt',
'signed char': 'CSignedChar',
'unsigned char': 'CUnsignedChar', 'unsigned int': 'CUnsignedInt',
'unsigned short': 'CUnsignedShort', 'unsigned long': 'CUnsignedLong',
'unsigned long long': 'CUnsignedLongLong',
}
cname_alias: Optional[str] = _CNAME_ALIAS.get(name)
if cname_alias is not None:
alias_cls: Optional[type] = cls._name_to_class.get(cname_alias)
if alias_cls is not None:
return (alias_cls, 0)
return None