# 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
```
