# 02 - 类型系统 Viper 的类型系统通过 `t` 模块提供,所有类型注解继承 `t.CType` 。大都以 `t.C{TypeName:PascalCase}`为类型,类型注解是 Viper 的核心机制,决定了变量的内存布局、大小和对齐方式。 ## 基本类型 ### 整数类型 | Viper 类型 | C 等价 | 大小(位) | 有符号 | |------------|--------|-----------|--------| | `t.CChar` | `char` | 8 | 是 | | `t.CShort` | `short` | 16 | 是 | | `t.CInt` | `int` | 32 | 是 | | `t.CLong` | `long` | 64 | 是 | | `t.CUnsignedChar` | `unsigned char` | 8 | 否 | | `t.CUnsignedShort` | `unsigned short` | 16 | 否 | | `t.CUnsigned` / `t.CUnsignedInt` | `unsigned int` | 32 | 否 | | `t.CUnsignedLong` | `unsigned long` | 64 | 否 | | `t.CSignedChar` | `signed char` | 8 | 是 | 值得注意的是,t.CUnsigned 一般不单独使用,而是配合其它有符号类型,替换表示无符号,比如 `t.CUnsigned | t.CInt`,由于为了便于使用一些常用类型,则将其组合为常用的 `t.CUnsignedInt` 等。 ### 固定宽度整数类型 | Viper 类型 | C 等价 | 大小(位) | 有符号 | |------------|--------|-----------|--------| | `t.CInt8T` | `int8_t` | 8 | 是 | | `t.CInt16T` | `int16_t` | 16 | 是 | | `t.CInt32T` | `int32_t` | 32 | 是 | | `t.CInt64T` | `int64_t` | 64 | 是 | | `t.CUInt8T` | `uint8_t` | 8 | 否 | | `t.CUInt16T` | `uint16_t` | 16 | 否 | | `t.CUInt32T` | `uint32_t` | 32 | 否 | | `t.CUInt64T` | `uint64_t` | 64 | 否 | ### 最小宽度整数类型 | Viper 类型 | C 等价 | 大小(位) | 有符号 | |------------|--------|-----------|--------| | `t.CIntLeast8T` | `int_least8_t` | ≥8 | 是 | | `t.CIntLeast16T` | `int_least16_t` | ≥16 | 是 | | `t.CIntLeast32T` | `int_least32_t` | ≥32 | 是 | | `t.CIntLeast64T` | `int_least64_t` | ≥64 | 是 | | `t.CUIntLeast8T` | `uint_least8_t` | ≥8 | 否 | | `t.CUIntLeast16T` | `uint_least16_t` | ≥16 | 否 | | `t.CUIntLeast32T` | `uint_least32_t` | ≥32 | 否 | | `t.CUIntLeast64T` | `uint_least64_t` | ≥64 | 否 | ### 最快最小宽度整数类型 | Viper 类型 | C 等价 | 大小(位) | 有符号 | |------------|--------|-----------|--------| | `t.CIntFast8T` | `int_fast8_t` | ≥8 | 是 | | `t.CIntFast16T` | `int_fast16_t` | ≥16 | 是 | | `t.CIntFast32T` | `int_fast32_t` | ≥32 | 是 | | `t.CIntFast64T` | `int_fast64_t` | ≥64 | 是 | | `t.CUIntFast8T` | `uint_fast8_t` | ≥8 | 否 | | `t.CUIntFast16T` | `uint_fast16_t` | ≥16 | 否 | | `t.CUIntFast32T` | `uint_fast32_t` | ≥32 | 否 | | `t.CUIntFast64T` | `uint_fast64_t` | ≥64 | 否 | ### 最大宽度整数类型 | Viper 类型 | C 等价 | 大小(位) | 有符号 | |------------|--------|-----------|--------| | `t.CIntMaxT` | `intmax_t` | ≥64 | 是 | | `t.CUIntMaxT` | `uintmax_t` | ≥64 | 否 | ### stdint 短名别名 通过 `import stdint` 引入,这些短名是上述类型的 `t.CTypedef` 别名,便于在系统编程场景中快速使用。允许直接使用 `from stdint import *` 来直接使用。 #### 基本类型短名 | 短名 | 等价展开 | 说明 | |------|---------|------| | `stdint.INT` | `t.CInt` | - | | `stdint.UINT` | `t.CUnsignedInt` | - | | `stdint.BOOL` | `t.CInt` | 1 为真,0 为假 | | `stdint.SHORT` | `t.CShort` | - | | `stdint.USHORT` | `t.CUnsignedShort` | - | | `stdint.LONG` | `t.CLong` | - | | `stdint.ULONG` | `t.CUnsignedLong` | - | | `stdint.LONGLONG` | `t.CLong \| t.CLong` | - | | `stdint.ULONGLONG` | `t.CUnsignedLong \| t.CLong` | - | | `stdint.FLOAT` | `t.CFloat` | - | | `stdint.DOUBLE` | `t.CDouble` | - | #### 固定宽度短名 | 短名 | 等价展开 | |------|---------| | `stdint.INT8` | `t.CInt8T` | | `stdint.INT16` | `t.CInt16T` | | `stdint.INT32` | `t.CInt32T` | | `stdint.INT64` | `t.CInt64T` | | `stdint.UINT8` | `t.CUInt8T` | | `stdint.UINT16` | `t.CUInt16T` | | `stdint.UINT32` | `t.CUInt32T` | | `stdint.UINT64` | `t.CUInt64T` | #### 字节与字短名 | 短名 | 等价展开 | 说明 | |------|---------|------| | `stdint.BYTE` | `t.CUnsignedChar` | 8 位无符号 | | `stdint.WORD` | `t.CUInt16T` | 16 位无符号 | | `stdint.DWORD` | `t.CUInt32T` | 32 位无符号 | | `stdint.QWORD` | `t.CUInt64T` | 64 位无符号 | #### 字符类型短名 | 短名 | 等价展开 | 说明 | |------|---------|------| | `stdint.TCHAR` | `t.CChar` | - | | `stdint.CHARLIST` | `str \| t.CPtr` / `list[str, None]` | - | | `stdint.WCHAR` | `stdint.WORD` | UTF-16 代码单元 | | `stdint.CHAR8` | `t.CChar8T` | - | | `stdint.CHAR16` | `t.CChar16T` | - | | `stdint.CHAR32` | `t.CChar32T` | - | #### 指针短名 | 短名 | 等价展开 | |------|---------| | `stdint.INTPTR` | `t.CInt \| t.CPtr` | | `stdint.UINTPTR` | `t.CUnsignedInt \| t.CPtr` | | `stdint.BYTEPTR` | `stdint.BYTE \| t.CPtr` | | `stdint.SHORTPTR` | `t.CShort \| t.CPtr` | | `stdint.USHORTPTR` | `t.CUnsignedShort \| t.CPtr` | | `stdint.WCHARPTR` | `stdint.WORD \| t.CPtr` | | `stdint.VOIDPTR` | `t.CVoid \| t.CPtr` | | `stdint.INT8PTR` | `t.CInt8T \| t.CPtr` | | `stdint.INT16PTR` | `t.CInt16T \| t.CPtr` | | `stdint.INT32PTR` | `t.CInt32T \| t.CPtr` | | `stdint.INT64PTR` | `t.CInt64T \| t.CPtr` | | `stdint.UINT8PTR` | `t.CUInt8T \| t.CPtr` | | `stdint.UINT16PTR` | `t.CUInt16T \| t.CPtr` | | `stdint.UINT32PTR` | `t.CUInt32T \| t.CPtr` | | `stdint.UINT64PTR` | `t.CUInt64T \| t.CPtr` | | `stdint.CHAR8PTR` | `t.CChar8T \| t.CPtr` | | `stdint.CHAR16PTR` | `t.CChar16T \| t.CPtr` | | `stdint.CHAR32PTR` | `t.CChar32T \| t.CPtr` | #### 平台特定短名 | 短名 | 等价展开 | 说明 | |------|---------|------| | `stdint.FSIZE_t` | `stdint.DWORD` | 文件大小 | | `stdint.LBA_t` | `stdint.DWORD` | 逻辑块地址 | ### 平台相关类型 | Viper 类型 | C 等价 | 大小(位) | 有符号 | |------------|--------|-----------|--------| | `t.CSizeT` | `size_t` | 64 | 否 | | `t.CIntPtrT` | `intptr_t` | 64 | 是 | | `t.CUIntPtrT` | `uintptr_t` | 64 | 否 | | `t.CPtrDiffT` | `ptrdiff_t` | 64 | 是 | ### stdint 短名别名 Viper 在 `stdint` 模块中提供了更简短的类型别名,通过 `t.CTypedef` 映射到对应的完整类型。使用时需 `import stdint`。 #### 固定宽度整数短名 | 短名 | 等价 Viper 类型 | C 等价 | |------|----------------|--------| | `INT8` | `t.CInt8T` | `int8_t` | | `INT16` | `t.CInt16T` | `int16_t` | | `INT32` | `t.CInt32T` | `int32_t` | | `INT64` | `t.CInt64T` | `int64_t` | | `UINT8` | `t.CUInt8T` | `uint8_t` | | `UINT16` | `t.CUInt16T` | `uint16_t` | | `UINT32` | `t.CUInt32T` | `uint32_t` | | `UINT64` | `t.CUInt64T` | `uint64_t` | #### 固定宽度指针短名 | 短名 | 等价 Viper 类型 | C 等价 | |------|----------------|--------| | `INT8PTR` | `t.CInt8T \| t.CPtr` | `int8_t*` | | `INT16PTR` | `t.CInt16T \| t.CPtr` | `int16_t*` | | `INT32PTR` | `t.CInt32T \| t.CPtr` | `int32_t*` | | `INT64PTR` | `t.CInt64T \| t.CPtr` | `int64_t*` | | `UINT8PTR` | `t.CUInt8T \| t.CPtr` | `uint8_t*` | | `UINT16PTR` | `t.CUInt16T \| t.CPtr` | `uint16_t*` | | `UINT32PTR` | `t.CUInt32T \| t.CPtr` | `uint32_t*` | | `UINT64PTR` | `t.CUInt64T \| t.CPtr` | `uint64_t*` | #### 字符类型短名 | 短名 | 等价 Viper 类型 | C 等价 | |------|----------------|--------| | `CHAR8` | `t.CChar8T` | `char8_t` | | `CHAR16` | `t.CChar16T` | `char16_t` | | `CHAR32` | `t.CChar32T` | `char32_t` | | `CHAR8PTR` | `t.CChar8T \| t.CPtr` | `char8_t*` | | `CHAR16PTR` | `t.CChar16T \| t.CPtr` | `char16_t*` | | `CHAR32PTR` | `t.CChar32T \| t.CPtr` | `char32_t*` | #### 基本类型短名 | 短名 | 等价 Viper 类型 | C 等价 | |------|----------------|--------| | `INT` | `t.CInt` | `int` | | `UINT` | `t.CUnsignedInt` | `unsigned int` | | `BOOL` | `t.CInt` | `int`(0/1) | | `SHORT` | `t.CShort` | `short` | | `USHORT` | `t.CUnsignedShort` | `unsigned short` | | `LONG` | `t.CLong` | `long` | | `ULONG` | `t.CUnsignedLong` | `unsigned long` | | `LONGLONG` | `t.CLong \| t.CLong` | `long long` | | `ULONGLONG` | `t.CUnsignedLong \| t.CLong` | `unsigned long long` | | `FLOAT` | `t.CFloat` | `float` | | `DOUBLE` | `t.CDouble` | `double` | #### 平台 / Windows 风格短名 | 短名 | 等价 Viper 类型 | C 等价 | |------|----------------|--------| | `BYTE` | `t.CUnsignedChar` | `unsigned char`(8位) | | `BYTEPTR` | `BYTE \| t.CPtr` | `unsigned char*` | | `WORD` | `t.CUInt16T` | `uint16_t`(16位) | | `DWORD` | `t.CUInt32T` | `uint32_t`(32位) | | `QWORD` | `t.CUInt64T` | `uint64_t`(64位) | | `INTPTR` | `t.CInt \| t.CPtr` | `int*` | | `UINTPTR` | `t.CUnsignedInt \| t.CPtr` | `unsigned int*` | | `SHORTPTR` | `t.CShort \| t.CPtr` | `short*` | | `USHORTPTR` | `t.CUnsignedShort \| t.CPtr` | `unsigned short*` | | `VOIDPTR` | `t.CVoid \| t.CPtr` | `void*` | | `TCHAR` | `t.CChar` | `char` | | `WCHAR` | `WORD` | `uint16_t`(UTF-16) | | `WCHARPTR` | `WORD \| t.CPtr` | `uint16_t*`(UTF-16) | | `CHARLIST` | `str \| t.CPtr` | `char*` | | `FSIZE_t` | `DWORD` | `uint32_t` | | `LBA_t` | `DWORD` | `uint32_t` | ### 浮点类型 | Viper 类型 | C 等价 | 大小(位) | |------------|--------|-----------| | `t.CFloat` | `float` | 32 | | `t.CDouble` | `double` | 64 | ### 其他基本类型 | Viper 类型 | C 等价 | 说明 | |------------|--------|------| | `t.CVoid` | `void` | 空类型 | | `t.CBool` | `bool` | 布尔类型(8位) | | `t.CWCharT` | `wchar_t` | 宽字符(32位) | | `t.CChar8T` | `char8_t` | UTF-8 字符(8位,无符号) | | `t.CChar16T` | `char16_t` | UTF-16 字符(16位,无符号) | | `t.CChar32T` | `char32_t` | UTF-32 字符(32位,无符号) | ### Python 便捷映射类型 | Python 类型| Viper 类型 | Viper 值 | |--------|--------|------| |`int`|`t.CInt`|-| |`float`|`t.CFloat`|-| |`str`|`t.CChar \| t.CPtr`|-| |`bool`|`t.CBool`|-| |`True`|`t.CBool`|`1`| |`False`|`t.CBool`|`0`| |`None`|`NULL`|`t.CIntPtr(0)`| 对于 t.py 和 c.py 的引用,必须使用 import,不能使用 from ... import ...,也不能使用 as,因为这两者都是直接以字符串识别的。 ## 类型组合 Viper 使用 Python 的 `|` 来组合类型修饰符(TypeUnion),其仅在左值注解中有效,其它位置均为位或语义(至少重载前是这样的),这是 Viper 最重要的语法特性之一。 ### 指针类型 使用 `t.CPtr` 表示指针,通过 `|` 与基本类型组合: ```python x: t.CInt | t.CPtr # int* — 指向 int 的指针 p: t.CVoid | t.CPtr # void* — 通用指针 s: t.CChar | t.CPtr # char* — 字符串指针 pp: t.CInt | t.CPtr | t.CPtr # int** — 指向指针的指针 ``` 等价 C 代码: ```c int* x; void* p; char* s; int** pp; ``` 同时,指针也可以用 `Ptr[T]` 的方法表示,但在 Viper 中不太推荐,虽然说这样做一直是类似工程的常见用法,但是如果此处 `T` 是一个多态,同时我们想要复用 Python 的高亮插件,插件无法识别 `Ptr[T]` 的属性取值,但是对于 `T | Ptr` 可以。 ```python x: t.CPtr[t.CInt] p: t.CPtr[t.CVoid] s: t.CPtr[t.CChar] pp: t.CPtr[t.CPtr[t.CInt]] pp2: t.CInt | t.CPtr[t.CPtr] # 同时也可以这么表示 ``` 等价 C 代码: ```c int* x; void* p; char* s: int** pp; int** pp2; ``` ### 类型限定符组合 ```python x: t.CConst | t.CInt # const int p: t.CConst | t.CChar | t.CPtr # const char* ``` ### 存储类组合 ```python x: t.CStatic | t.CInt # static int f: t.CExtern | t.CInt # extern int(声明其存在于外部) ``` ### 函数返回类型组合 ```python def foo() -> t.CInt | t.CExport: # 导出函数,返回 int return 0 def bar() -> t.CVoid | t.CExtern: # 外部函数声明 pass ``` ### `t.State` 声明性标记 `t.State` 是**声明性标记类型**,表示"仅声明不定义"(语义等价于 `t.CExport | t.CExtern`)。主要用于 FFI 外部函数声明:函数体为 `pass`,编译器只生成函数原型(declare),不生成定义(define),由链接器在外部库中解析符号。 ```python def CreateFileA(lpFileName: LPCSTR, dwDesiredAccess: ULONG, dwShareMode: ULONG, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwCreationDisposition: ULONG, dwFlagsAndAttributes: ULONG, hTemplateFile: HANDLE) -> HANDLE | t.State: pass ``` 等价 C 声明: ```c HANDLE CreateFileA(LPCSTR, ULONG, ULONG, SECURITY_ATTRIBUTES*, ULONG, ULONG, HANDLE); ``` `t.State` 是 Viper FFI 机制的核心,无需任何特殊语法,仅靠返回类型注解即可声明外部函数。详见 [08-c-operations.md 的 FFI 章节](08-c-operations.md#ffi-外部函数声明) 和 [includes/w32](../includes/w32) 的 Win32 绑定。 ## 数组类型 使用 Python 的 `list[ElementType, Size]` 语法表示固定大小数组(通常的,这用于栈上和 BSS 段上): ```python buf: list[t.CChar, 64] # char buf[64] ids: list[t.CInt, 10] # int ids[10] matrix: list[t.CFloat, 16] # float matrix[16] entries: list[idt_entry, 256] # struct idt_entry entries[256] s: list[t.CChar, None] # 自推长度 char s[]; ``` 等价 C 代码: ```c char buf[64]; int ids[10]; float matrix[16]; struct idt_entry entries[256]; ``` ### 数组指针和函数指针 ```python lp: list[t.CInt, 12] | t.CPtr vp: t.Callable[[t.CInt, t.CInt], t.CInt] = x # 其中 t.Callable = typing.Callable,可以直接使用。 ``` ## 结构体类型 使用 `class` 定义结构体,成员通过类型注解声明: ```python class point: x: t.CInt y: t.CInt ``` 等价 C 代码: ```c struct point { int x; int y; }; ``` ### 带指针成员的结构体 ```python class node: value: t.CInt next: node | t.CPtr # struct node* next ``` ### 匿名结构体成员(❌) > WARNING: **警告:** 由于 Viper 在声明结构体,枚举等处不需要关键字,因此 `t.Anonymouse` 是不需要使用的。此关键字不再维护,强行使用可能导致未定义行为。 继承 `t.Anonymous` 的类作为匿名成员嵌入: ```python class header(t.Anonymous): magic: t.CUInt32T version: t.CUInt32T class packet: header # 匿名嵌入,可直接访问 packet.magic length: t.CUInt32T ``` ### 字节序标记 > WARNING: **警告:** 此关键字是实验性的。未经充分测试,不当使用可能导致未定义行为。 使用 `t.BigEndian` 或 `t.LittleEndian` 标记成员的字节序: ```python class network_packet: length: t.CUInt16T | t.BigEndian # 大端序存储 type: t.CUInt8T # 默认小端序 ``` ## 联合体类型 继承 `t.CUnion` 定义联合体: ```python class value(t.CUnion): ival: t.CInt fval: t.CFloat pval: t.CVoid | t.CPtr ``` 等价 C 代码: ```c union value { int ival; float fval; void* pval; }; ``` ## 枚举类型 继承 `t.CEnum` 定义枚举: ```python class color(t.CEnum): RED: t.CEnum = 0 GREEN: t.CEnum = 1 BLUE: t.CEnum = 2 ``` 等价 C 代码: ```c enum color { RED = 0, GREEN = 1, BLUE = 2 }; ``` 枚举成员可直接使用名称: ```python c: t.CInt = color.RED ``` ### REnum(标签联合体) `t.CEnum` 是普通枚举(整数常量集合),`t.REnum` 是**标签联合体**(tagged union / Rust enum 风格)。每个变体可携带不同的 payload,通过 `match` 模式匹配分派。适用于少变体、无通用字段、match 分派的场景(如类型系统、IR 表示)。 ```python class LLVMType(t.REnum): class Int: Bits: t.CInt class Void: pass match ty: case LLVMType.Int: snprintf(buf, size, "i%d", ty.Bits) case LLVMType.Void: string.strcpy(buf, "void") ``` REnum 的详细用法、与 CEnum/胖节点 AST 的对比见 [05-classes.md 的 REnum 章节](05-classes.md#renum标签联合体)。 ## Typedef 使用 `t.CTypedef` 创建类型别名: ```python irq_handler_t: t.CTypedef | t.Callable[[], t.CInt] # typedef int (*irq_handler_t)(); ``` 或通过注解赋值: ```python MyStruct: t.CTypedef = original_struct # typedef struct original_struct MyStruct; ``` 更推荐通过后者的形式,前者编译器不一定能够识别到注解是对 t.CTypedef 的,还是后面的注解的,而且容易触发未定义行为。 ## 泛型类型(PEP 695 语法) Viper 支持 PEP 695 泛型语法 `class Name[T]:`,定义类型参数化的类。类型参数 `T` 在类体内可作为占位类型使用,实例化时用 `Name[ConcreteType]` 特化。 ```python @t.NoVTable class GSList[T]: Head: T | t.CPtr Tail: T | t.CPtr Count: t.CSizeT lst: GSList[GNode] | t.CPtr = GSList[GNode]() ``` 泛型类还支持**递归泛型继承**(如 `class GNode(GSListNode[GNode])`),实现强类型自引用结构,无需 `void*` + 转型。这是 C/C++/Rust 均无法如此简洁表达的能力。 泛型类的完整用法、递归继承、实例化示例见 [05-classes.md 的泛型类章节](05-classes.md#泛型类pep-695-语法)。 ## 强制类型转换 在 Viper 中的强制类型转换有些不同,强制类型转换有两种方案,都是基于 `t.CType` 的用法,符合 Python 本意。 对于原先就继承自 `t.CType` 的类型来说,可以直接使用 call 的方法进行类型转换,比如 ```python x: t.CChar | t.CPtr = "Hello" t.CVoid(x, t.CPtr) ``` 其中用法为 `t.CType(x, ...)`,此处...可以是其它的 `t.CType` 或将要提到的 `Typedef`,将其视为组合类型对 `x` 进行强制转换。 额外补充一句,对于比较,四则运算,可以不使用强制类型转换,而是依靠隐式类型转换,但如果是严谨数学计算,推荐还是强制类型转换避免判断出错。 此外,若将一个不同类型的右值赋值到左值,则会隐式将右值转换为左值的类型。 如果你不喜欢 `t.CVoid(x, t.CPtr)` 的方法,认为这将 `void` 和 `ptr` 分开,不便于理解,那么还有一个方法,即将二者打包为一个 Typedef,即: ```python VOIDPTR: t.CTypedef = t.CVoid | t.CPtr ``` 则如果你想,你可以直接通过 call 的方式进行强转,比如: ```python y: VOIDPTR = VOIDPTR(x) ``` ## 宏定义常量 使用 `t.CDefine` 定义编译时常量。`t.CDefine` 不是数据类型,而是编译时元指令——标记为 `t.CDefine` 的常量在 LLVM IR 中不生成任何全局变量,而是在引用处直接内联展开。详见 [01-overview.md 中 t.CDefine 深度解析](01-overview.md#tcdefine-深度解析)。 ```python MAX_SIZE: t.CDefine = 1024 PAGE_SIZE: t.CDefine = 4096 FA_READ: t.CDefine = 0x01 ``` 语义上等价于 C 的 `#define`: ```c #define MAX_SIZE 1024 #define PAGE_SIZE 4096 #define FA_READ 0x01 ``` 宏定义支持表达式: ```python CPU_FEATURE_FPU: t.CDefine = (1 << 0) CPU_FEATURE_APIC: t.CDefine = (1 << 6) ``` 宏定义也可与类型组合使用: ```python CODE_SEG: t.CDefine | t.CUInt16T = 0x08 ``` ## 位域 使用 `t.Bit(n)` 定义位域成员: ```python class flags: a: t.CUInt32T | t.Bit[1] # 此处,如果存入 2,二进制是 10,会被截断为 0 b: t.CUInt32T | t.Bit[3] c: t.CUInt32T | t.Bit[4] ``` ## LLVM IR 类型简写 Viper 提供了 LLVM IR 级别的类型简写: ```python i1 # 1位整数 i8 # 8位有符号整数 i16 # 16位有符号整数 i32 # 32位有符号整数 i64 # 64位有符号整数 u1 # 1位无符号整数 u8 # 8位无符号整数 u16 # 16位无符号整数 u32 # 32位无符号整数 u64 # 64位无符号整数 ``` 仍然通过 `t.x` 的方式调用,比如 `t.i1` 等。 ## `__attribute__` 属性 通过 `t.attr` 命名空间访问 GCC `__attribute__` 属性: ```python t.attr.packed() # __attribute__((packed)) t.attr.aligned(16) # __attribute__((aligned(16))) t.attr.section(".text.startup") # __attribute__((section(".text.startup"))) t.attr.always_inline() # __attribute__((always_inline)) t.attr.noinline() # __attribute__((noinline)) t.attr.noreturn() # __attribute__((noreturn)) t.attr.weak() # __attribute__((weak)) t.attr.unused() # __attribute__((unused)) t.attr.constructor() # __attribute__((constructor)) t.attr.destructor() # __attribute__((destructor)) t.attr.deprecated("use X") # __attribute__((deprecated("use X"))) ``` ### LLVM 函数属性 通过 `t.attr.llvm` 命名空间指定 LLVM 函数属性: ```python t.attr.llvm.nobuiltin t.attr.llvm.nounwind t.attr.llvm.noredzone t.attr.llvm.willreturn t.attr.llvm.mustprogress t.attr.llvm.optnone t.attr.llvm.noinline t.attr.llvm.alwaysinline t.attr.llvm.readnone t.attr.llvm.readonly t.attr.llvm.writeonly t.attr.llvm.inaccessiblememonly t.attr.llvm.inaccessiblemem_or_argmemonly ``` 在函数返回类型注解中使用: ```python def foo() -> t.CInt | t.attr.llvm.nobuiltin | t.attr.llvm.nounwind: return 0 ```