Files
TransPyC/CPython/t.py
2026-06-16 16:09:42 +08:00

1283 lines
39 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.
# 类型定义模块
import re
import types
from typing import TypeVar, Generic, TypeAlias
# =============================================================================
# 类型映射常量
# =============================================================================
# 类型映射常量(由 _build_type_maps() 在模块末尾自动生成)
_BASIC_TYPES_MAP = {}
_T_TYPE_PATTERNS = []
def _build_type_maps():
global _BASIC_TYPES_MAP, _T_TYPE_PATTERNS
for _name in dir():
_obj = eval(_name)
if isinstance(_obj, type) and issubclass(_obj, CType) and _obj is not CType:
try:
_inst = _obj()
_cname = getattr(_inst, 'CName', '')
if _cname and _obj.IsBasicType():
_BASIC_TYPES_MAP[_cname] = _cname
_T_TYPE_PATTERNS.append((_name, _cname))
except Exception:
pass
# =============================================================================
# CType 基类
# =============================================================================
class CType:
"""C 类型基类"""
PREFIX = 'prefix'
BASE = 'base'
POINTER = 'ptr'
ARRAY = 'array'
NAMED = 'named'
STORAGE_CLASS = 'storage_class'
TYPE_QUALIFIER = 'type_qualifier'
position = frozenset({BASE}) # 类属性,支持联合类型如 BASE | SPECIAL
def __init__(self, value=None, *types):
self.value = value
self.types = types
self.Name = ''
self.IsBasicType = False
self.IsPointer = False
self.IsSigned = None
self.Size = None
if not hasattr(self, 'CName'):
self.CName = ''
def GetPositions(self) -> frozenset:
"""获取 position 的 frozenset 形式"""
return self.position
@classmethod
def HasPosition(cls, pos) -> 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):
"""注解"""
pass
def get_position(self):
"""获取类型在声明中的位置"""
return self.position
def GetCAame(self):
"""获取 C 类型名称"""
return self.CName
def __merge__(self, types):
return types
def __or__(self, other):
return [self, other]
def __set_default__(self, **kwargs):
"""设置默认值/初始值,用于 static/global 变量的初始化
Args:
**kwargs: 成员名称和值的键值对
Returns:
包含默认值信息的 CTypeDefault 对象
"""
return CTypeDefault(self, **kwargs)
@classmethod
def FromAnnotation(cls, AnnotationStr, TypeName=''):
"""从类型注解字符串解析类型信息
Args:
AnnotationStr: 类型注解的字符串表示ast.dump结果
TypeName: 类型名称(可选)
Returns:
CType 实例
"""
ctype = cls()
# 检查是否是基本类型
if TypeName in _BASIC_TYPES_MAP:
ctype.IsBasicType = True
ctype.Name = _BASIC_TYPES_MAP[TypeName]
else:
for pattern, c_name in _T_TYPE_PATTERNS:
if pattern in AnnotationStr:
ctype.IsBasicType = True
ctype.Name = c_name
break
# 检查是否包含指针
if 'CPtr' in AnnotationStr:
ctype.IsPointer = True
return ctype
@classmethod
def FromTypeName(cls, TypeName):
"""从类型名称创建 CType
Args:
TypeName: 类型名称
Returns:
CType 实例
"""
ctype = cls()
if TypeName in _BASIC_TYPES_MAP:
ctype.IsBasicType = True
ctype.Name = _BASIC_TYPES_MAP[TypeName]
return ctype
def GetFullType(self, VarName='', ArraySizeStr=''):
"""获取完整的类型声明字符串
Args:
VarName: 变量名
ArraySizeStr: 数组大小字符串
Returns:
完整的类型声明字符串
"""
ptr_str = '*' if self.IsPointer else ''
if VarName:
return f'{self.Name}{ptr_str} {VarName}{ArraySizeStr}'
return f'{self.Name}{ptr_str}'
def __repr__(self):
ptr_str = '*' if self.IsPointer else ''
return f'CType({self.Name}{ptr_str}, IsBasicType={self.IsBasicType})'
class CChar(CType):
def __init__(self, value=None):
self.CName = 'char'
super().__init__(value)
self.IsSigned = True
self.Size = 8
class CInt(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'int'
super().__init__(value)
self.IsSigned = True
self.Size = 32
class CShort(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'short'
super().__init__(value)
self.IsSigned = True
self.Size = 16
class CLong(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'long'
super().__init__(value)
self.IsSigned = True
self.Size = 64
class CFloat(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'float'
super().__init__(value)
self.IsSigned = None
self.Size = 32
class CDouble(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'double'
super().__init__(value)
self.IsSigned = None
self.Size = 64
class CFloat8T(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'float8_t'
super().__init__(value)
self.IsSigned = None
self.Size = 8
class CFloat16T(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'float16_t'
super().__init__(value)
self.IsSigned = None
self.Size = 16
class CFloat32T(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'float32_t'
super().__init__(value)
self.IsSigned = None
self.Size = 32
class CFloat64T(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'float64_t'
super().__init__(value)
self.IsSigned = None
self.Size = 64
class CFloat128T(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'float128_t'
super().__init__(value)
self.IsSigned = None
self.Size = 128
class CVoid(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'void'
super().__init__(value)
self.IsSigned = None
self.Size = 0
class CUnsigned(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'unsigned'
super().__init__(value)
self.IsSigned = False
self.Size = 32
class CUnsignedChar(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'unsigned char'
super().__init__(value)
self.IsSigned = False
self.Size = 8
class CUnsignedInt(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'unsigned int'
super().__init__(value)
self.IsSigned = False
self.Size = 32
class CUnsignedShort(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'unsigned short'
super().__init__(value)
self.IsSigned = False
self.Size = 16
class CUnsignedLong(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'unsigned long'
super().__init__(value)
self.IsSigned = False
self.Size = 64
class CSignedChar(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'signed char'
super().__init__(value)
self.IsSigned = True
self.Size = 8
class CStruct(CType):
position = frozenset({CType.BASE, CType.NAMED})
def __init__(self, value=None, name=None):
self.CName = f'struct {name}' if name else 'struct'
super().__init__(value)
class CUnion(CType):
position = frozenset({CType.BASE, CType.NAMED})
def __init__(self, value=None):
self.CName = 'union'
super().__init__(value)
class CEnum(CType):
position = frozenset({CType.BASE, CType.NAMED})
def __init__(self, value=None):
self.CName = 'enum'
super().__init__(value)
self.b = 1
Enum = CEnum # 别名,允许使用 t.Enum
'''
class Object(CType):
"""Python 对象类型,用于支持类方法外联函数"""
position = frozenset({CType.BASE, CType.NAMED})
def __init__(self, value=None):
self.CName = 'struct'
super().__init__(value)
def __call__(self, cls):
return cls
'''
def Object():
pass
def CVTable():
pass
CTypedef = TypeAlias
class _CTypedef(CType):
position = frozenset({CType.PREFIX, CType.NAMED})
def __init__(self, value=None):
self.CName = 'typedef'
super().__init__(value)
class CAuto(CType):
position = frozenset({CType.PREFIX})
def __init__(self, value=None):
self.CName = 'auto'
super().__init__(value)
class CRegister(CType):
position = frozenset({CType.PREFIX, CType.STORAGE_CLASS})
def __init__(self, value=None):
self.CName = 'register'
super().__init__(value)
class CStatic(CType):
position = frozenset({CType.PREFIX, CType.STORAGE_CLASS})
def __init__(self, value=None):
self.CName = 'static'
super().__init__(value)
class CExtern(CType):
position = frozenset({CType.PREFIX, CType.STORAGE_CLASS})
def __init__(self, value=None):
self.CName = 'extern'
super().__init__(value)
class CConst(CType):
position = frozenset({CType.PREFIX, CType.TYPE_QUALIFIER})
def __init__(self, value=None):
self.CName = 'const'
super().__init__(value)
class CInline(CType):
position = frozenset({CType.PREFIX, CType.STORAGE_CLASS})
def __init__(self, value=None):
self.CName = 'inline'
super().__init__(value)
class CExport(CType):
position = frozenset({CType.PREFIX, CType.STORAGE_CLASS})
def __init__(self, value=None):
self.CName = 'export'
super().__init__(value)
class CVolatile(CType):
position = frozenset({CType.PREFIX, CType.TYPE_QUALIFIER})
def __init__(self, value=None):
self.CName = 'volatile'
super().__init__(value)
class CSizeT(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'size_t'
super().__init__(value)
self.IsSigned = False
self.Size = 64
class CInt8T(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'int8_t'
super().__init__(value)
self.IsSigned = True
self.Size = 8
class CInt16T(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'int16_t'
super().__init__(value)
self.IsSigned = True
self.Size = 16
class CInt32T(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'int32_t'
super().__init__(value)
self.IsSigned = True
self.Size = 32
class CInt64T(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'int64_t'
super().__init__(value)
self.IsSigned = True
self.Size = 64
class CUInt8T(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'uint8_t'
super().__init__(value)
self.IsSigned = False
self.Size = 8
class CUInt16T(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'uint16_t'
super().__init__(value)
self.IsSigned = False
self.Size = 16
class CUInt32T(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'uint32_t'
super().__init__(value)
self.IsSigned = False
self.Size = 32
class CUInt64T(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'uint64_t'
super().__init__(value)
self.IsSigned = False
self.Size = 64
class CIntPtrT(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'intptr_t'
super().__init__(value)
self.IsSigned = True
self.Size = 64
class CUIntPtrT(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'uintptr_t'
super().__init__(value)
self.IsSigned = False
self.Size = 64
class CPtrDiffT(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'ptrdiff_t'
super().__init__(value)
self.IsSigned = True
self.Size = 64
class CWCharT(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'wchar_t'
super().__init__(value)
self.IsSigned = True
self.Size = 32
class CChar8T(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'char8_t'
super().__init__(value)
self.IsSigned = False
self.Size = 8
class CChar16T(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'char16_t'
super().__init__(value)
self.IsSigned = False
self.Size = 16
class CChar32T(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'char32_t'
super().__init__(value)
self.IsSigned = False
self.Size = 32
class CBool(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = 'bool'
super().__init__(value)
self.IsSigned = False
self.Size = 8
class CComplex(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = '_Complex'
super().__init__(value)
class CImaginary(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = '_Imaginary'
super().__init__(value)
T = TypeVar("T")
Callable = Generic[T]
class CPtr(CType, Generic[T]):
position = frozenset({CType.POINTER})
def __init__(self, value=None):
self.CName = '*'
super().__init__(value)
class CTypeDefault(CType):
"""用于存储 C 类型默认值/初始化的包装类
当使用 t.CStatic.__set_default__(open=mouse_open, ...) 时创建
"""
def __init__(self, BaseType, **kwargs):
super().__init__()
self.BaseType = BaseType
self.defaults = kwargs
self.CName = BaseType.CName if hasattr(BaseType, 'CName') else ''
self.position = BaseType.position if hasattr(BaseType, 'position') else CType.BASE
def __repr__(self):
return f'CTypeDefault({self.BaseType}, {self.defaults})'
class CArrayPtr(CType):
position = frozenset({CType.POINTER})
def __init__(self, value=None):
self.CName = '(*)' # 特殊标记表示数组指针
super().__init__(value)
class CDefine(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = '#define'
super().__init__(value)
class CPass(CType):
position = frozenset({CType.BASE})
def __init__(self, value=None):
self.CName = ''
super().__init__(value)
class State(CType):
"""状态标记,用于仅声明不定义,等价于 CExport | CExtern"""
position = frozenset({CType.PREFIX})
@staticmethod
def HandleCall(translator, args, keywords):
"""处理 t.State() 调用"""
return ['t.State']
class Anonymous:
def __init__():
pass
class Postdefinition:
def __init__(self, c):
pass
class Bit:
def __init__(self, i):
pass
class BigEndian(CType):
"""大端序Big-Endian字节序标记类
用于标记结构体成员应使用大端序存储。
在小端序平台如x86上读取时会自动进行字节交换。
用法示例:
class MyStruct:
a: t.CInt | t.BigEndian # 大端序存储的整数
"""
IsSigned = True
Size = 4
Align = 4
class LittleEndian(CType):
"""小端序Little-Endian字节序标记类
用于标记结构体成员应使用小端序存储。
在小端序平台如x86上读取时不需要进行字节交换。
用法示例:
class MyStruct:
b: t.CInt | t.LittleEndian # 小端序存储的整数
"""
IsSigned = True
Size = 4
Align = 4
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 = ASM_DESCR.ALL
class attr:
"""C 语言 __attribute__ 属性操作类型"""
@staticmethod
def noreturn():
return "noreturn"
@staticmethod
def format(printf, arg1, arg2):
return f"format({printf}, {arg1}, {arg2})"
@staticmethod
def section(name):
return f'section("{name}")'
@staticmethod
def aligned(bytes):
return f"aligned({bytes})"
@staticmethod
def packed():
return "packed"
@staticmethod
def unused():
return "unused"
@staticmethod
def used():
return "used"
@staticmethod
def weak():
return "weak"
@staticmethod
def alias(name):
return f'alias("{name}")'
@staticmethod
def visibility(type):
return f'visibility("{type}")'
@staticmethod
def constructor():
return "constructor"
@staticmethod
def destructor():
return "destructor"
@staticmethod
def always_inline():
return "always_inline"
@staticmethod
def noinline():
return "noinline"
@staticmethod
def pure():
return "pure"
@staticmethod
def const():
return "const"
@staticmethod
def malloc():
return "malloc"
@staticmethod
def alloc_size(n):
return f"alloc_size({n})"
@staticmethod
def warn_unused_result():
return "warn_unused_result"
@staticmethod
def deprecated(msg=None):
if msg:
return f'deprecated("{msg}")'
return "deprecated"
@staticmethod
def fallthrough():
return "fallthrough"
@staticmethod
def likely():
return "likely"
@staticmethod
def unlikely():
return "unlikely"
@staticmethod
def hot():
return "hot"
@staticmethod
def cold():
return "cold"
@staticmethod
def interrupt():
return "interrupt"
@staticmethod
def naked():
return "naked"
@staticmethod
def sentinel(n=0):
return f"sentinel({n})"
@staticmethod
def nonnull(*args):
if args:
return f"nonnull({', '.join(map(str, args))})"
return "nonnull"
@staticmethod
def returns_nonnull():
return "returns_nonnull"
@staticmethod
def access(mode, *args):
return f"access({mode}, {', '.join(map(str, args))})"
@staticmethod
def cleanup(func):
return f'cleanup({func})'
@staticmethod
def transparent_union():
return "transparent_union"
@staticmethod
def mode(mode_name):
return f"mode({mode_name})"
@staticmethod
def vector_size(bytes):
return f"vector_size({bytes})"
@staticmethod
def target(string):
return f'target("{string}")'
@staticmethod
def optimize(level):
return f'optimize("{level}")'
@staticmethod
def no_instrument_function():
return "no_instrument_function"
@staticmethod
def no_sanitize(type):
return f"no_sanitize({type})"
@staticmethod
def no_stack_protector():
return "no_stack_protector"
@staticmethod
def stack_protector():
return "stack_protector"
@staticmethod
def error(msg):
return f'error("{msg}")'
@staticmethod
def warning(msg):
return f'warning("{msg}")'
class llvm:
"""LLVM 函数属性描述符
用于在返回类型注解中指定 LLVM 函数属性。
例如: def foo() -> t.CInt | t.attr.llvm.nobuiltin | t.attr.llvm.nounwind:
"""
class nobuiltin:
CName = '#attr.llvm.nobuiltin'
class nounwind:
CName = '#attr.llvm.nounwind'
class noredzone:
CName = '#attr.llvm.noredzone'
class willreturn:
CName = '#attr.llvm.willreturn'
class mustprogress:
CName = '#attr.llvm.mustprogress'
class optnone:
CName = '#attr.llvm.optnone'
class noinline:
CName = '#attr.llvm.noinline'
class alwaysinline:
CName = '#attr.llvm.alwaysinline'
class readnone:
CName = '#attr.llvm.readnone'
class readonly:
CName = '#attr.llvm.readonly'
class writeonly:
CName = '#attr.llvm.writeonly'
class inaccessiblememonly:
CName = '#attr.llvm.inaccessiblememonly'
class inaccessiblemem_or_argmemonly:
CName = '#attr.llvm.inaccessiblemem_or_argmemonly'
def NewCType(size, signed):
ct = CType()
ct.Size = size
ct.IsSigned = signed
return ct
i1 = NewCType(1, True)
i8 = NewCType(8, True)
i16 = NewCType(16, True)
i32 = NewCType(32, True)
i64 = NewCType(64, True)
u1 = NewCType(1, False)
u8 = NewCType(8, False)
u16 = NewCType(16, False)
u32 = NewCType(32, False)
u64 = NewCType(64, False)
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 = None
_cname_to_class = None
@classmethod
def _build(cls):
if cls._name_to_class is not None:
return
import sys
mod = sys.modules.get(__name__)
if mod is None:
return
cls._name_to_class = {}
cls._cname_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 = obj()
except Exception:
continue
pos = 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
if getattr(inst, 'Size', None) is not None or getattr(inst, 'CName', ''):
cls._name_to_class[name] = obj
cname = getattr(inst, 'CName', '')
if cname and cname not in cls._cname_to_class:
cls._cname_to_class[cname] = obj
@classmethod
def GetClassByName(cls, name: str):
"""根据 Python 类名获取 CType 类 (如 'CInt32T' -> t.CInt32T)"""
cls._build()
return cls._name_to_class.get(name)
@classmethod
def GetClassByCName(cls, cname: str):
"""根据 C 类型名获取 CType 类 (如 'int32_t' -> t.CInt32T)"""
cls._build()
return cls._cname_to_class.get(cname)
@staticmethod
def CTypeToLLVM(ctype_class) -> 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 = 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 = ctype_class()
except Exception:
return 'i8*'
size = getattr(inst, 'Size', None)
is_signed = 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 = {8: 'half', 16: 'half', 32: 'float', 64: 'double', 128: 'fp128'}
return float_map.get(size, f'f{size}')
return f'i{size}'
@staticmethod
def CTypeToCName(ctype_class) -> str:
"""从 CType 类推导 C 类型名称 (用于 printf 格式化等)
规则:
- IsSigned is None 且 Size > 0 → 浮点: float/double/long double
- IsSigned is True → 有符号整数: char/short/int/long long
- IsSigned is False → 无符号整数: unsigned char/unsigned short/unsigned int/unsigned long long
"""
if ctype_class is None:
return ''
try:
inst = ctype_class()
except Exception:
return ''
size = getattr(inst, 'Size', None)
is_signed = getattr(inst, 'IsSigned', None)
if size is None:
return ''
if is_signed is None and size > 0:
float_cname = {32: 'float', 64: 'double', 128: 'long double'}
return float_cname.get(size, 'double')
int_cname_signed = {8: 'char', 16: 'short', 32: 'int', 64: 'long long'}
int_cname_unsigned = {8: 'unsigned char', 16: 'unsigned short', 32: 'unsigned int', 64: 'unsigned long long'}
if is_signed:
return int_cname_signed.get(size, 'int')
else:
return int_cname_unsigned.get(size, 'unsigned int')
@classmethod
def NameToLLVM(cls, name: str) -> str:
"""根据 Python 类型名推导 LLVM IR 类型 (如 'CFloat64T' -> 'double')
修饰符类型 (CConst, CStatic 等) 返回空字符串。
指针类型 (CPtr) 返回 'i8*'
未知类型返回 None。
"""
cls._build()
import sys
mod = sys.modules.get(__name__)
if mod and hasattr(mod, name):
obj = getattr(mod, name)
if isinstance(obj, type) and issubclass(obj, CType):
return cls.CTypeToLLVM(obj)
return None
@classmethod
def NameToCName(cls, name: str) -> str:
"""根据 Python 类型名推导 C 类型名 (如 'CInt32T' -> 'int')"""
ctype_class = cls.GetClassByName(name)
if ctype_class is not None:
return cls.CTypeToCName(ctype_class)
return None
@classmethod
def CNameToClass(cls, cname: str):
"""根据 C 类型名获取 CType 类 (如 'int32_t' -> t.CInt32T, 'unsigned char' -> t.CUnsignedChar)"""
cls._build()
return cls._cname_to_class.get(cname)
@classmethod
def ResolveName(cls, name: str):
"""解析类型名到 (CType类, 指针层级)
支持的格式:
- Python 类名: 'CInt32T' -> (t.CInt32T, 0)
- C 类型名: 'int32_t' -> (t.CInt32T, 0)
- stdint 大写别名: 'INT32' -> (t.CInt32T, 0)
- 指针别名: 'INT32PTR' -> (t.CInt32T, 1)
- 大写别名: 'BYTE' -> (t.CUnsignedChar, 0), 'DWORD' -> (t.CUInt32T, 0)
- 浮点别名: 'FLOAT64' -> (t.CFloat64T, 0)
- void指针: 'VOIDPTR' -> (t.CVoid, 1)
"""
cls._build()
direct = cls._name_to_class.get(name)
if direct is not None:
pos = getattr(direct, 'position', frozenset())
ptr_level = 1 if CType.POINTER in pos and CType.BASE not in pos else 0
return (direct, ptr_level)
cnameres = cls._cname_to_class.get(name)
if cnameres is not None:
return (cnameres, 0)
if name.endswith('PTR'):
base_name = name[:-3]
base_result = cls.ResolveName(base_name)
if base_result is not None:
return (base_result[0], base_result[1] + 1)
if name.startswith('FLOAT') and name[5:].isdigit():
bits = int(name[5:])
float_name = f'CFloat{bits}T'
float_cls = cls._name_to_class.get(float_name)
if float_cls is not None:
return (float_cls, 0)
_UPPER_ALIAS = {
'BYTE': 'CUInt8T', 'INT8': 'CInt8T', 'UINT8': 'CUInt8T',
'WORD': 'CUInt16T', 'INT16': 'CInt16T', 'UINT16': 'CUInt16T',
'DWORD': 'CUInt32T', 'INT32': 'CInt32T', 'UINT32': 'CUInt32T',
'UINT': 'CUnsignedInt', 'INT': 'CInt',
'QWORD': 'CUInt64T', 'INT64': 'CInt64T', 'UINT64': 'CUInt64T',
'INTPTR': 'CIntPtrT', 'UINTPTR': 'CUIntPtrT',
'SIZE_T': 'CSizeT', 'SSIZE_T': 'CPtrDiffT', 'PTRDIFF_T': 'CPtrDiffT',
'VOID': 'CVoid',
}
alias = _UPPER_ALIAS.get(name)
if alias:
alias_cls = cls._name_to_class.get(alias)
if alias_cls is not None:
return (alias_cls, 0)
return None
_build_type_maps()