chore: 改名同步 TransPyV -> ViperC(源码/配置内的纯替换)

This commit is contained in:
TermiNexus committed 2026-10-12 15:06:47 +08:00
1 parent ccd7434c5a
commit fb365a1707
12 files changed
+9369 -9369

No files matched your search

+1 -1
View File
@@ -27,7 +27,7 @@ _tls_index: ulong = 0
def _init_tls(): def _init_tls():
"""Initialize TLS index (executes once; subsequent calls are skipped).""" """Initialize TLS index (executes once; subsequent calls are skipped)."""
global _tls_index global _tls_index
# Double guard: TPV now implements @t.TLS (a per-function one-shot guard setting __tls_init_done), but this re-check is kept for compatibility with older TPV.exe builds. # Double guard: VPC now implements @t.TLS (a per-function one-shot guard setting __tls_init_done), but this re-check is kept for compatibility with older VPC.exe builds.
# _tls_index starts at 0 (TlsAlloc never returns 0 on success). # _tls_index starts at 0 (TlsAlloc never returns 0 on success).
if _tls_index == 0: if _tls_index == 0:
_tls_index = TlsAlloc() _tls_index = TlsAlloc()
+1 -1
View File
@@ -40,5 +40,5 @@ def coro_gather(a: Coroutine) -> int:
def coro_exception_msg(c: Coroutine) -> rawptr: def coro_exception_msg(c: Coroutine) -> rawptr:
# M7 placeholder: the compiler inlines coro.coro_exception_msg(frame) into a frame msg-slot read. # M7 placeholder: the compiler inlines coro.coro_exception_msg(frame) into a frame msg-slot read.
# Note: TPV (Viper) does not support bare null; use t.CPtr(0) to build a null pointer (compatible with both compilers). # Note: VPC (Viper) does not support bare null; use t.CPtr(0) to build a null pointer (compatible with both compilers).
return None return None
+1 -1
View File
@@ -15,7 +15,7 @@
# all FLTK objects are opaque pointers; methods map to cfltk's Fl_<Class>_<action>. # all FLTK objects are opaque pointers; methods map to cfltk's Fl_<Class>_<action>.
# * The full C API is directly available via `from fltk._cfl import *` etc. # * The full C API is directly available via `from fltk._cfl import *` etc.
# * Callback support: a Viper module-level function can be passed to FLTK directly as an Fl_Callback-- # * Callback support: a Viper module-level function can be passed to FLTK directly as an Fl_Callback--
# TPV auto-bitcasts the function name into a function pointer (e.g. CreateThread passes a function). # VPC auto-bitcasts the function name into a function pointer (e.g. CreateThread passes a function).
# Callback signature convention: def cb(w: bytes, data: bytes): ... (w=widget pointer, data=user data) # Callback signature convention: def cb(w: bytes, data: bytes): ... (w=widget pointer, data=user data)
# def on_click(w: bytes, data: bytes): # def on_click(w: bytes, data: bytes):
# Fl_Widget_set_label(w, "Clicked!") # Fl_Widget_set_label(w, "Clicked!")
+17 -17
View File
@@ -4,10 +4,10 @@
**逐名逐签名同形**:内部模型(类型/值/函数/基本块/构建器/模块)与公开 API 完全一致, **逐名逐签名同形**:内部模型(类型/值/函数/基本块/构建器/模块)与公开 API 完全一致,
唯一区别是"打印"阶段输出 MLIR 文本而不是 LLVM IR 文本。 唯一区别是"打印"阶段输出 MLIR 文本而不是 LLVM IR 文本。
目的:让 TransPyV 侧只需把 `llvmlite.` 前缀重命名为 `mlirlite.` 即可编译, 目的:让 ViperC 侧只需把 `llvmlite.` 前缀重命名为 `mlirlite.` 即可编译,
从而在不改内部模型、不改 builders 的前提下切换到 MLIR 后端。 从而在不改内部模型、不改 builders 的前提下切换到 MLIR 后端。
> 实际切换方式(2026-09):不动 TransPyV 侧任何 `llvmlite.` 调用点,也不动 > 实际切换方式(2026-09):不动 ViperC 侧任何 `llvmlite.` 调用点,也不动
> `includes/llvmlite/**`——工程文件 `project.vpj` 的 `options.target = "mlir"` 会让 > `includes/llvmlite/**`——工程文件 `project.vpj` 的 `options.target = "mlir"` 会让
> 模块名 `llvmlite` 在名称→SHA1 解析处改写为 `mlirlite`(唯一改动点是 > 模块名 `llvmlite` 在名称→SHA1 解析处改写为 `mlirlite`(唯一改动点是
> `StubMergerIR._FindSha1ByModName`)。开关、回退与缓存标签要求见 > `StubMergerIR._FindSha1ByModName`)。开关、回退与缓存标签要求见
@@ -61,7 +61,7 @@ builders 未改,而它们内嵌的类型一律来自 `IRBuilder._type_str` →
同时保留 LLVM 语法分支(`i8*`、`[N x x]`、`{…}`)以兼容手工构造的中间文本; 同时保留 LLVM 语法分支(`i8*`、`[N x x]`、`{…}`)以兼容手工构造的中间文本;
- 结构体类型在中间文本里就已是完整内联形态(匿名 `!llvm.struct<(…)>`、 - 结构体类型在中间文本里就已是完整内联形态(匿名 `!llvm.struct<(…)>`、
具名 `!llvm.struct<"name", (…)>`,见 §2.10),因此**不需要**在中间文本里 具名 `!llvm.struct<"name", (…)>`,见 §2.10),因此**不需要**在中间文本里
出现 `%"name"` 这种"只有名字"的形态;若出现(手工构造 / TPV 注入), 出现 `%"name"` 这种"只有名字"的形态;若出现(手工构造 / VPC 注入),
`MlirTypeText` 按**模块打印期发布的登记表**回查完整定义后展开为具名内联形态, `MlirTypeText` 按**模块打印期发布的登记表**回查完整定义后展开为具名内联形态,
查不到 / 仍是 opaque ⇒ 响亮报错; 查不到 / 仍是 opaque ⇒ 响亮报错;
- `_mlir_read_type` 的类型读取按 `[] {} () <>` 统一做括号平衡, - `_mlir_read_type` 的类型读取按 `[] {} () <>` 统一做括号平衡,
@@ -215,10 +215,10 @@ region 内元素 MLIR 类型并行取自**全局类型树**(`Struct` 字段链
**⚠ 五条由 mlir-opt 22.1.8 实测确立的硬约束(违反即解析/校验失败)** **⚠ 五条由 mlir-opt 22.1.8 实测确立的硬约束(违反即解析/校验失败)**
1. **符号名判据与 LLVM 不同**:MLIR 裸标识符**首字符必须是字母或 `_`**,且 1. **符号名判据与 LLVM 不同**:MLIR 裸标识符**首字符必须是字母或 `_`**,且
**不允许 `-`**(LLVM 允许)。⇒ TPV 的 `{sha1}.{name}`(sha1 以数字开头)与 **不允许 `-`**(LLVM 允许)。⇒ VPC 的 `{sha1}.{name}`(sha1 以数字开头)与
`@.str`(以 `.` 开头)**一律需要 `@"…"` 引号形式**。判据见 `@.str`(以 `.` 开头)**一律需要 `@"…"` 引号形式**。判据见
`__function.vp:_ll_name_needs_quote`,输出统一走 `_MlirSymRefAppend`。 `__function.vp:_ll_name_needs_quote`,输出统一走 `_MlirSymRefAppend`。
2. **字符串属性长度必须等于 i8 数组长度**:TPV 的字符串常量类型含尾随 NUL 2. **字符串属性长度必须等于 i8 数组长度**:VPC 的字符串常量类型含尾随 NUL
(`[N+1 x i8]`)⇒ 属性里**必须保留 `\00`**。**绝不能**为了对齐长度去剥掉 (`[N+1 x i8]`)⇒ 属性里**必须保留 `\00`**。**绝不能**为了对齐长度去剥掉
类型里的 NUL —— 那会丢掉 C 字符串终止符、破坏 ABI。 类型里的 NUL —— 那会丢掉 C 字符串终止符、破坏 ABI。
3. **`dense<[…] : !llvm.array<…>>` 非法**(`dense` 只接受 builtin shaped 类型 3. **`dense<[…] : !llvm.array<…>>` 非法**(`dense` 只接受 builtin shaped 类型
@@ -268,7 +268,7 @@ module {
- 对齐值只接受**常量十进制 + 2 的幂**:非常量(SSA)/非幂/超范围(> 2^30)一律 `MlirFail` - 对齐值只接受**常量十进制 + 2 的幂**:非常量(SSA)/非幂/超范围(> 2^30)一律 `MlirFail`
—— mlir-opt 自身不校验幂次(实测 `{alignment = 3 : i64}` exit 0),故由本层把关。 —— mlir-opt 自身不校验幂次(实测 `{alignment = 3 : i64}` exit 0),故由本层把关。
### 2.8 内联汇编(`build_inline_asm` / TPV 注入文本) ### 2.8 内联汇编(`build_inline_asm` / VPC 注入文本)
两条来源的中间文本 opcode 都是 `call`,由 `_MlirCall` 转交 `_MlirAsm`: 两条来源的中间文本 opcode 都是 `call`,由 `_MlirCall` 转交 `_MlirAsm`:
@@ -284,14 +284,14 @@ module {
`asm_dialect = inteldialect` 报 `expected … enum values … [att, intel]`)。 `asm_dialect = inteldialect` 报 `expected … enum values … [att, intel]`)。
- **输入操作数在 MLIR 里是逗号分隔的裸操作数、不带括号**(LLVM 词法的 `"…"(%v)` - **输入操作数在 MLIR 里是逗号分隔的裸操作数、不带括号**(LLVM 词法的 `"…"(%v)`
实测报 `expected ':'`);操作数类型串位于 `: (<操作数类型…>) -> <返回类型|()>`。 实测报 `expected ':'`);操作数类型串位于 `: (<操作数类型…>) -> <返回类型|()>`。
- 汇编/约束串按引号串整体透传:TPV 的 `\22`/`\5C`/`\0A` 转义对 MLIR 词法同样合法(实测 exit 0)。 - 汇编/约束串按引号串整体透传:VPC 的 `\22`/`\5C`/`\0A` 转义对 MLIR 词法同样合法(实测 exit 0)。
- 只认 `sideeffect` / `inteldialect` 两个关键字;其它记号(含 LLVM 的 - 只认 `sideeffect` / `inteldialect` 两个关键字;其它记号(含 LLVM 的
`attdialect`/`alignstack`/`unwind`)、缺约束串、实参不成对、有返回值却无结果名 `attdialect`/`alignstack`/`unwind`)、缺约束串、实参不成对、有返回值却无结果名
⇒ `MlirFail` 响亮报错。 ⇒ `MlirFail` 响亮报错。
(`attdialect`/`alignstack` 在 1024 份真实 `.ll` 语料中 **0 命中** ⇒ **不列入支持计划**, (`attdialect`/`alignstack` 在 1024 份真实 `.ll` 语料中 **0 命中** ⇒ **不列入支持计划**,
此处的 `MlirFail` 只是兜底,不是待补齐缺口。) 此处的 `MlirFail` 只是兜底,不是待补齐缺口。)
**多结果内联汇编 + `extractvalue`**(本轮补齐;TPV 全量产物 4163 份 `.ll` 的 **多结果内联汇编 + `extractvalue`**(本轮补齐;VPC 全量产物 4163 份 `.ll` 的
"指令位置"扫描中 `extractvalue` **70 处**,且是**唯一**未支持却真实使用的 opcode) "指令位置"扫描中 `extractvalue` **70 处**,且是**唯一**未支持却真实使用的 opcode)
真实形态(`Test/DefaultArgTest/output/*.ll` 等,多结果内联汇编是 `extractvalue` 真实形态(`Test/DefaultArgTest/output/*.ll` 等,多结果内联汇编是 `extractvalue`
@@ -323,7 +323,7 @@ module {
- 实测(mlir-opt / mlir-translate 22.1.8):`%v[0]` / `%v[1, 0]` / 具名结构体 - 实测(mlir-opt / mlir-translate 22.1.8):`%v[0]` / `%v[1, 0]` / 具名结构体
`!llvm.struct<"n", (i32, i32)>` / 数组 `!llvm.array<2 x i32>` 作聚合类型均 exit 0; `!llvm.struct<"n", (i32, i32)>` / 数组 `!llvm.array<2 x i32>` 作聚合类型均 exit 0;
降级得 `call { i32, i32 } asm sideeffect "…", "=r,r"()` + 降级得 `call { i32, i32 } asm sideeffect "…", "=r,r"()` +
`extractvalue { i32, i32 } %1, 0` / `, 1`(与 TPV 产物逐字同形)。 `extractvalue { i32, i32 } %1, 0` / `, 1`(与 VPC 产物逐字同形)。
- `insertvalue` / `invoke` / `landingpad` / `resume` / `freeze` / `fence` / - `insertvalue` / `invoke` / `landingpad` / `resume` / `freeze` / `fence` /
`shufflevector` / `insertelement` / `extractelement` / `callbr` 在 4163 份真实产物中 `shufflevector` / `insertelement` / `extractelement` / `callbr` 在 4163 份真实产物中
**全部 0 命中** ⇒ **不实现**,仍走"未知指令 opcode"响亮报错。 **全部 0 命中** ⇒ **不实现**,仍走"未知指令 opcode"响亮报错。
@@ -405,11 +405,11 @@ module {
### 2.10 具名结构体(`%"name" = type {…}`) ### 2.10 具名结构体(`%"name" = type {…}`)
**背景(实测语料)**:TPV 对每个类都调 `module_add_named_type`(18 处调用点: **背景(实测语料)**:VPC 对每个类都调 `module_add_named_type`(18 处调用点:
`ClassGenDef.vp:522`、`ClassGenEnum.vp:720/1000`、`StructGenMixin.vp:1802`、 `ClassGenDef.vp:522`、`ClassGenEnum.vp:720/1000`、`StructGenMixin.vp:1802`、
`AsyncGenMixin.vp:733`、`VpiReader.vp:2705/4059` 等),llvmlite 侧由 `AsyncGenMixin.vp:733`、`VpiReader.vp:2705/4059` 等),llvmlite 侧由
`PrintStructDefinition` 输出 `%"sha1.Cls" = type {…}` 定义行 `PrintStructDefinition` 输出 `%"sha1.Cls" = type {…}` 定义行
(`.tpv_build/**/*.ll` 里 `^%"[^"]+" = type` 命中 78319 行 / 1815 文件)。 (`__vpcbuild__/**/*.ll` 里 `^%"[^"]+" = type` 命中 78319 行 / 1815 文件)。
**MLIR 侧两条硬约束(实测 mlir-opt 22.1.8)**: **MLIR 侧两条硬约束(实测 mlir-opt 22.1.8)**:
@@ -476,7 +476,7 @@ mlir-opt 报 `identified type already used with a different body`。故凡具名
| 名字为空 / 字段链成环(> 4096) | `命名结构体名字为空` / `命名结构体字段过多或字段链成环` | | 名字为空 / 字段链成环(> 4096) | `命名结构体名字为空` / `命名结构体字段过多或字段链成环` |
| 中间文本 `%"name"` 未登记(含"表未发布"的独立 `FunctionPrint`) | `命名结构体类型文本未在模块中登记完整定义(MLIR 不允许无体前向声明…)` | | 中间文本 `%"name"` 未登记(含"表未发布"的独立 `FunctionPrint`) | `命名结构体类型文本未在模块中登记完整定义(MLIR 不允许无体前向声明…)` |
**opaque 风险查证(结论:按值使用处不会出现 opaque)**:TPV 的 opaque 只由 **opaque 风险查证(结论:按值使用处不会出现 opaque)**:VPC 的 opaque 只由
`_scan_type_for_cross_module_refs`(`Ptr(Struct(name))` 分支)与 REPL 专用的 `_scan_type_for_cross_module_refs`(`Ptr(Struct(name))` 分支)与 REPL 专用的
`_repl_opaque_class_ty` 产生,两者都服务于**指针**引用;按值位置(C ABI 值形参) `_repl_opaque_class_ty` 产生,两者都服务于**指针**引用;按值位置(C ABI 值形参)
另有显式判据 `_AggregateParamTy`:命中注册表且非 opaque 才按值、否则**降级 i64**; 另有显式判据 `_AggregateParamTy`:命中注册表且非 opaque 才按值、否则**降级 i64**;
@@ -568,7 +568,7 @@ packed"的组合,无需(也无处)为其单独报错。登记表每槽 16
- **Debug Info**(`module_add_di_node` / `module_add_named_metadata` / - **Debug Info**(`module_add_di_node` / `module_add_named_metadata` /
`function_set_dbg` / `builder_set_(clear_)debug_location`、`DINode` / `function_set_dbg` / `builder_set_(clear_)debug_location`、`DINode` /
`DINamedMeta`、`LLVMModule.DIMeta*`/`DINamed*`、`Function.DbgRef`、 `DINamedMeta`、`LLVMModule.DIMeta*`/`DINamed*`、`Function.DbgRef`、
`IRBuilder.DbgLoc`):为保持与 llvmlite **逐名同形**(并让 TransPyV 的 `IRBuilder.DbgLoc`):为保持与 llvmlite **逐名同形**(并让 ViperC 的
`DebugInfoGen` 在 `llvmlite.`→`mlirlite.` 改名后可编译),本库**完整保留这些名字 `DebugInfoGen` 在 `llvmlite.`→`mlirlite.` 改名后可编译),本库**完整保留这些名字
与模型字段/布局**(`LLVMModule` 144B、`Function` 88B、`IRBuilder` 40B, 与模型字段/布局**(`LLVMModule` 144B、`Function` 88B、`IRBuilder` 40B,
与 llvmlite 同布局);但 MLIR 语法没有 `!N = …` 元数据与 `, !dbg !N` 后缀, 与 llvmlite 同布局);但 MLIR 语法没有 `!N = …` 元数据与 `, !dbg !N` 后缀,
@@ -617,7 +617,7 @@ packed"的组合,无需(也无处)为其单独报错。登记表每槽 16
`()`。详见 §2.5 的硬约束 4/5。 `()`。详见 §2.5 的硬约束 4/5。
4. ~~`c"hello\00"` → `"hello"`:按设计规范**去掉尾随 `\00`**~~ —— 4. ~~`c"hello\00"` → `"hello"`:按设计规范**去掉尾随 `\00`**~~ ——
**与实测冲突,已按实测推翻**:MLIR 要求字符串属性长度**等于** i8 数组长度, **与实测冲突,已按实测推翻**:MLIR 要求字符串属性长度**等于** i8 数组长度,
而 TPV 的类型含尾随 NUL(`[N+1 x i8]`)⇒ 属性里**必须保留 `\00`** 而 VPC 的类型含尾随 NUL(`[N+1 x i8]`)⇒ 属性里**必须保留 `\00`**
(`_MlirCStringToMlir` 只剥 `c` 前缀,见 §2.5 硬约束 2)。 (`_MlirCStringToMlir` 只剥 `c` 前缀,见 §2.5 硬约束 2)。
5. `Func(Void, …)` 的类型文本渲染为 `!llvm.func<none (…)>`(由 `Void → none` 规则 5. `Func(Void, …)` 的类型文本渲染为 `!llvm.func<none (…)>`(由 `Void → none` 规则
组合而来);函数签名位置的 void 返回值则是**省略** `-> ty`(不影响)。 组合而来);函数签名位置的 void 返回值则是**省略** `-> ty`(不影响)。
@@ -644,9 +644,9 @@ packed"的组合,无需(也无处)为其单独报错。登记表每槽 16
10. `_mlir_read_type` 按 `[] {} () <>` 做**字符级**括号平衡来读 `!llvm.struct<…>`; 10. `_mlir_read_type` 按 `[] {} () <>` 做**字符级**括号平衡来读 `!llvm.struct<…>`;
具名结构的名字是**带引号字符串**,含 `[`/`]`(泛型特化名如 具名结构的名字是**带引号字符串**,含 `[`/`]`(泛型特化名如
`100000000000000a.GSList[100000000000000b.BasicBlock]`)时不影响平衡(成对出现)。 `100000000000000a.GSList[100000000000000b.BasicBlock]`)时不影响平衡(成对出现)。
实测语料(全仓 1462 个 `.ll`/`.vpi`,26476 个唯一具名类型):TPV 名字**全部成对**、 实测语料(全仓 1462 个 `.ll`/`.vpi`,26476 个唯一具名类型):VPC 名字**全部成对**、
无空格、无 `"`/`\`;仅 19 个非 TPV 名(手工 IR 里的 `<<.1` / `>>.10` 类移位临时名) 无空格、无 `"`/`\`;仅 19 个非 VPC 名(手工 IR 里的 `<<.1` / `>>.10` 类移位临时名)
含不配对 `<>` —— 它们不经 mlirlite(本库是**生成器**,只打印 TPV 模型)。 含不配对 `<>` —— 它们不经 mlirlite(本库是**生成器**,只打印 VPC 模型)。
MLIR 侧对这些名字的承载已实测:`!llvm.struct<">>.1", (i32)>` exit 0, MLIR 侧对这些名字的承载已实测:`!llvm.struct<">>.1", (i32)>` exit 0,
降级得 `%">>.1" = type { i32 }`。 降级得 `%">>.1" = type { i32 }`。
+1928 -1928
View File
File diff suppressed because it is too large. Load diff
+3934 -3934
View File
File diff suppressed because it is too large. Load diff
+462 -462
View File
@@ -1,462 +1,462 @@
from stdint import * from stdint import *
import memhub import memhub
import string import string
import viperlib import viperlib
# ============================================================ # ============================================================
# mlirlite -- an MLIR (llvm dialect) text emission library, isomorphic to llvmlite name for name # mlirlite -- an MLIR (llvm dialect) text emission library, isomorphic to llvmlite name for name
# #
# Design principles: # Design principles:
# * The internal model (LLVMType/Value/Function/BasicBlock/IRBuilder/Module...) is # * The internal model (LLVMType/Value/Function/BasicBlock/IRBuilder/Module...) is
# **isomorphic to includes/llvmlite name for name and signature for signature**, so on the TPV side it suffices to rename # **isomorphic to includes/llvmlite name for name and signature for signature**, so on the VPC side it suffices to rename
# `llvmlite.` to `mlirlite.` in order to compile; # `llvmlite.` to `mlirlite.` in order to compile;
# * The difference lies only in the "printing" stage: TypePrint / ValuePrint / FunctionPrint / # * The difference lies only in the "printing" stage: TypePrint / ValuePrint / FunctionPrint /
# LLVMModulePrint emit MLIR text, while the builders still generate the intermediate instruction text as before; # LLVMModulePrint emit MLIR text, while the builders still generate the intermediate instruction text as before;
# * Names keep the LLVMxxx form (isomorphism first). See README.md for semantic differences. # * Names keep the LLVMxxx form (isomorphism first). See README.md for semantic differences.
# ============================================================ # ============================================================
# Import submodules # Import submodules
from .__types import ( from .__types import (
LLVMType, ParamNode, LLVMTypeCore, LLVMType, ParamNode, LLVMTypeCore,
Int1, Int8, Int16, Int32, Int64, Ptr, Func, Void, Array, Struct, Int1, Int8, Int16, Int32, Int64, Ptr, Func, Void, Array, Struct,
Half, Float, Double, FP128, Label, Half, Float, Double, FP128, Label,
new_param_node, param_list_append, new_param_node, param_list_append,
paramnode_get_ty, paramnode_get_next, paramnode_set_ty, paramnode_set_next, paramnode_get_ty, paramnode_get_next, paramnode_set_ty, paramnode_set_next,
TypePrint, PrintStructDefinition, get_struct_name, TypePrint, PrintStructDefinition, get_struct_name,
get_struct_fields, get_struct_fcount, DeepCopyType, get_struct_fields, get_struct_fcount, DeepCopyType,
) )
from .__values import ( from .__values import (
Value, new_value, ConstInt, ConstNull, ConstZero, ConstFloat, SSAValue, ValuePrint, Value, new_value, ConstInt, ConstNull, ConstZero, ConstFloat, SSAValue, ValuePrint,
value_get_ty, value_get_next, value_get_ty, value_get_next,
value_set_ty, value_set_next, value_set_name, value_set_isconst, value_set_ty, value_set_next, value_set_name, value_set_isconst,
) )
from .__function import ( from .__function import (
Line, BasicBlock, Param, Function, Line, BasicBlock, Param, Function,
new_line, new_basic_block, new_param, new_function, new_line, new_basic_block, new_param, new_function,
function_add_param, function_add_block, function_add_param, function_add_block,
block_append_line, block_append_text, block_append_line, block_append_text,
function_set_attrs, param_set_attrs, function_set_attrs, param_set_attrs,
function_set_attr_group, function_set_attr_group,
function_set_dbg, function_set_dbg,
function_get_name, function_get_name_len, function_get_ret_ty, function_get_params, function_get_name, function_get_name_len, function_get_ret_ty, function_get_params,
function_get_param_head, function_get_next, function_is_declared, function_get_param_head, function_get_next, function_is_declared,
param_get_name, param_get_ty, param_get_next, param_get_name, param_get_ty, param_get_next,
FunctionPrint, G_PeepEnable, FunctionPrint, G_PeepEnable,
DebugSetEnabled, DebugIsEnabled, DebugNoteFunc, DebugClearFunc, DebugSetEnabled, DebugIsEnabled, DebugNoteFunc, DebugClearFunc,
DebugNoteLine, DebugResetFunc, DebugTakeText, DebugNoteLine, DebugResetFunc, DebugTakeText,
) )
from .__module import ( from .__module import (
LLVMModule, GlobalVariable, NamedTypeNode, DINode, DINamedMeta, LLVMModule, GlobalVariable, NamedTypeNode, DINode, DINamedMeta,
new_module, new_global_variable, new_module, new_global_variable,
module_add_function, module_add_global, module_add_named_type, module_add_function, module_add_global, module_add_named_type,
module_set_named_type_packed, module_set_named_type_packed,
module_set_target, module_set_datalayout, module_set_target, module_set_datalayout,
module_add_di_node, module_add_named_metadata, module_add_di_node, module_add_named_metadata,
global_set_constant, global_set_linkage, global_set_unnamed_addr, global_set_section, global_set_constant, global_set_linkage, global_set_unnamed_addr, global_set_section,
LLVMModulePrint, OUTPUT_FULL, OUTPUT_STUB, OUTPUT_TEXT, LLVMModulePrint, OUTPUT_FULL, OUTPUT_STUB, OUTPUT_TEXT,
module_ensure_opaque_for_type, module_ensure_opaque_for_type,
) )
from .__builder import ( from .__builder import (
IRBuilder, new_builder, position_at_end, IRBuilder, new_builder, position_at_end,
builder_cur_block_is_terminated, builder_cur_block_is_terminated,
builder_set_debug_location, builder_clear_debug_location, builder_set_debug_location, builder_clear_debug_location,
build_alloca, build_alloca_aligned, build_alloca_at_entry, build_load, build_store, build_alloca, build_alloca_aligned, build_alloca_at_entry, build_load, build_store,
build_store_at_entry, build_store_at_entry,
build_add, build_sub, build_mul, build_sdiv, build_udiv, build_srem, build_urem, build_add, build_sub, build_mul, build_sdiv, build_udiv, build_srem, build_urem,
build_and, build_or, build_xor, build_shl, build_lshr, build_ashr, build_and, build_or, build_xor, build_shl, build_lshr, build_ashr,
build_fadd, build_fsub, build_fmul, build_fdiv, build_frem, build_fneg, build_fadd, build_fsub, build_fmul, build_fdiv, build_frem, build_fneg,
build_icmp, build_fcmp, build_icmp, build_fcmp,
build_br, build_cond_br, build_ret, build_ret_void, build_br, build_cond_br, build_ret, build_ret_void,
build_call, build_call_indirect, build_bitcast, build_sext, build_trunc, build_zext, build_call, build_call_indirect, build_bitcast, build_sext, build_trunc, build_zext,
build_ptrtoint, build_inttoptr, build_ptrtoint, build_inttoptr,
build_fpext, build_fptrunc, build_fp2si, build_si2fp, build_fp2ui, build_ui2fp, build_fpext, build_fptrunc, build_fp2si, build_si2fp, build_fp2ui, build_ui2fp,
build_gep, build_gep_array, build_gep_struct, build_gep, build_gep_array, build_gep_struct,
build_phi, build_switch, build_select, build_unreachable, build_phi, build_switch, build_select, build_unreachable,
build_atomicrmw, build_cmpxchg, build_inline_asm, build_va_arg, build_atomicrmw, build_cmpxchg, build_inline_asm, build_va_arg,
PhiIncoming, new_phi_incoming, SwitchCase, new_switch_case, PhiIncoming, new_phi_incoming, SwitchCase, new_switch_case,
ICMP_EQ, ICMP_NE, ICMP_SGT, ICMP_SGE, ICMP_SLT, ICMP_SLE, ICMP_EQ, ICMP_NE, ICMP_SGT, ICMP_SGE, ICMP_SLT, ICMP_SLE,
ICMP_UGT, ICMP_UGE, ICMP_ULT, ICMP_ULE, ICMP_UGT, ICMP_UGE, ICMP_ULT, ICMP_ULE,
FCMP_FALSE, FCMP_OEQ, FCMP_OGT, FCMP_OGE, FCMP_OLT, FCMP_OLE, FCMP_FALSE, FCMP_OEQ, FCMP_OGT, FCMP_OGE, FCMP_OLT, FCMP_OLE,
FCMP_ONE, FCMP_ORD, FCMP_UNO, FCMP_UEQ, FCMP_UGT, FCMP_UGE, FCMP_ONE, FCMP_ORD, FCMP_UNO, FCMP_UEQ, FCMP_UGT, FCMP_UGE,
FCMP_ULT, FCMP_ULE, FCMP_UNE, FCMP_TRUE, FCMP_ULT, FCMP_ULE, FCMP_UNE, FCMP_TRUE,
ATOMIC_XCHG, ATOMIC_ADD, ATOMIC_SUB, ATOMIC_AND, ATOMIC_NAND, ATOMIC_XCHG, ATOMIC_ADD, ATOMIC_SUB, ATOMIC_AND, ATOMIC_NAND,
ATOMIC_OR, ATOMIC_XOR, ATOMIC_MAX, ATOMIC_MIN, ATOMIC_UMAX, ATOMIC_UMIN, ATOMIC_OR, ATOMIC_XOR, ATOMIC_MAX, ATOMIC_MIN, ATOMIC_UMAX, ATOMIC_UMIN,
ATOMIC_ORDER_NOTATOMIC, ATOMIC_ORDER_UNORDERED, ATOMIC_ORDER_MONOTONIC, ATOMIC_ORDER_NOTATOMIC, ATOMIC_ORDER_UNORDERED, ATOMIC_ORDER_MONOTONIC,
ATOMIC_ORDER_ACQUIRE, ATOMIC_ORDER_RELEASE, ATOMIC_ORDER_ACQ_REL, ATOMIC_ORDER_ACQUIRE, ATOMIC_ORDER_RELEASE, ATOMIC_ORDER_ACQ_REL,
ATOMIC_ORDER_SEQ_CST, ATOMIC_ORDER_SEQ_CST,
) )
from .__verify import ( from .__verify import (
VerifyResult, NameEntry, VerifyResult, NameEntry,
verify_function, verify_module, verify_function, verify_module,
VERIFY_OK, VERIFY_ERR_NO_TERMINATOR, VERIFY_ERR_DUPLICATE_DEF, VERIFY_OK, VERIFY_ERR_NO_TERMINATOR, VERIFY_ERR_DUPLICATE_DEF,
VERIFY_ERR_UNDEFINED_USE, VERIFY_ERR_PHI_NOT_FIRST, VERIFY_ERR_UNDEFINED_USE, VERIFY_ERR_PHI_NOT_FIRST,
_new_verify_result, _new_verify_result,
) )
# ============================================================ # ============================================================
# Convenience factory: string copy # Convenience factory: string copy
# ============================================================ # ============================================================
def _str_dup(pool: memhub.MemBuddy*, src: str) -> str: def _str_dup(pool: memhub.MemBuddy*, src: str) -> str:
"""Allocate from pool and copy a C string.""" """Allocate from pool and copy a C string."""
if src is None: return None if src is None: return None
slen: sizet = string.strlen(src) slen: sizet = string.strlen(src)
buf: str = pool.alloc(slen + 1) buf: str = pool.alloc(slen + 1)
if buf is None: return None if buf is None: return None
string.strcpy(buf, src) string.strcpy(buf, src)
return buf return buf
# ============================================================ # ============================================================
# Convenience factory: create a named basic block # Convenience factory: create a named basic block
# ============================================================ # ============================================================
def create_block(pool: memhub.MemBuddy*, func: Function*, def create_block(pool: memhub.MemBuddy*, func: Function*,
name: str) -> BasicBlock*: name: str) -> BasicBlock*:
"""Create a basic block and add it to the function.""" """Create a basic block and add it to the function."""
# Block-name/param conflict guard: block label "entry:" is value %entry, so a param %entry # Block-name/param conflict guard: block label "entry:" is value %entry, so a param %entry
# collides; on collision append .1/.2/... (strip a leading % from Param.Name before comparing). # collides; on collision append .1/.2/... (strip a leading % from Param.Name before comparing).
use_name: str = name use_name: str = name
if func is not None and func.Params is not None and name is not None \ if func is not None and func.Params is not None and name is not None \
and name[0] != '\0': and name[0] != '\0':
cb_len: sizet = string.strlen(name) + 16 cb_len: sizet = string.strlen(name) + 16
cb_buf: str = pool.alloc(cb_len) cb_buf: str = pool.alloc(cb_len)
if cb_buf is not None: if cb_buf is not None:
cb_k: int = 1 cb_k: int = 1
cb_collide: int = 1 cb_collide: int = 1
while cb_collide != 0: while cb_collide != 0:
cb_collide = 0 cb_collide = 0
cb_p: Param* = function_get_param_head(func) cb_p: Param* = function_get_param_head(func)
while cb_p is not None: while cb_p is not None:
cb_pnm: str = param_get_name(cb_p) cb_pnm: str = param_get_name(cb_p)
if cb_pnm is not None: if cb_pnm is not None:
cb_pv: str = cb_pnm cb_pv: str = cb_pnm
if cb_pv[0] == '%': if cb_pv[0] == '%':
cb_pv = cb_pv + 1 cb_pv = cb_pv + 1
if string.strcmp(cb_pv, use_name) == 0: if string.strcmp(cb_pv, use_name) == 0:
cb_collide = 1 cb_collide = 1
break break
cb_p = param_get_next(cb_p) cb_p = param_get_next(cb_p)
if cb_collide != 0: if cb_collide != 0:
viperlib.snprintf(cb_buf, cb_len, "%s.%d", name, cb_k) viperlib.snprintf(cb_buf, cb_len, "%s.%d", name, cb_k)
use_name = cb_buf use_name = cb_buf
cb_k += 1 cb_k += 1
name_dup: str = _str_dup(pool, use_name) name_dup: str = _str_dup(pool, use_name)
blk: BasicBlock* = new_basic_block(pool, name_dup) blk: BasicBlock* = new_basic_block(pool, name_dup)
if blk is not None: if blk is not None:
function_add_block(func, blk) function_add_block(func, blk)
return blk return blk
# ============================================================ # ============================================================
# Convenience factory: create an integer constant value # Convenience factory: create an integer constant value
# ============================================================ # ============================================================
def const_int(pool: memhub.MemBuddy*, bits: int, def const_int(pool: memhub.MemBuddy*, bits: int,
val: int64) -> Value*: val: int64) -> Value*:
"""Create an integer constant value (auto-creates type + name text). """Create an integer constant value (auto-creates type + name text).
bits: bit width (1/8/16/32/64); val: integer value. bits: bit width (1/8/16/32/64); val: integer value.
""" """
# create type # create type
ty: LLVMType* = pool.alloc(LLVMType.__sizeof__()) ty: LLVMType* = pool.alloc(LLVMType.__sizeof__())
if ty is None: return None if ty is None: return None
string.memset(ty, 0, LLVMType.__sizeof__()) string.memset(ty, 0, LLVMType.__sizeof__())
*ty = *LLVMType.Int(bits) *ty = *LLVMType.Int(bits)
# create name text # create name text
name: str = pool.alloc(32) name: str = pool.alloc(32)
if name is None: return None if name is None: return None
# LLVM i64 literals exclude INT64_MIN: represent it as the unsigned bit pattern # LLVM i64 literals exclude INT64_MIN: represent it as the unsigned bit pattern
# 9223372036854775808 (accepted by LLVM), else opt rejects "-9223372036854775808". # 9223372036854775808 (accepted by LLVM), else opt rejects "-9223372036854775808".
if bits == 64 and val == -9223372036854775807 - 1: if bits == 64 and val == -9223372036854775807 - 1:
viperlib.snprintf(name, 32, "9223372036854775808") viperlib.snprintf(name, 32, "9223372036854775808")
else: else:
viperlib.snprintf(name, 32, "%lld", val) viperlib.snprintf(name, 32, "%lld", val)
return ConstInt(pool, ty, val, name) return ConstInt(pool, ty, val, name)
def const_int32(pool: memhub.MemBuddy*, val: int64) -> Value*: def const_int32(pool: memhub.MemBuddy*, val: int64) -> Value*:
"""Convenience: create an i32 integer constant.""" """Convenience: create an i32 integer constant."""
return const_int(pool, 32, val) return const_int(pool, 32, val)
def const_int64(pool: memhub.MemBuddy*, val: int64) -> Value*: def const_int64(pool: memhub.MemBuddy*, val: int64) -> Value*:
"""Convenience: create an i64 integer constant.""" """Convenience: create an i64 integer constant."""
return const_int(pool, 64, val) return const_int(pool, 64, val)
# ============================================================ # ============================================================
# Convenience factory: create a function and add it to the module # Convenience factory: create a function and add it to the module
# ============================================================ # ============================================================
def create_function(pool: memhub.MemBuddy*, mod: LLVMModule*, def create_function(pool: memhub.MemBuddy*, mod: LLVMModule*,
name: str, ret_ty: LLVMType*) -> Function*: name: str, ret_ty: LLVMType*) -> Function*:
"""Create a function and add it to the module.""" """Create a function and add it to the module."""
name_dup: str = _str_dup(pool, name) name_dup: str = _str_dup(pool, name)
func: Function* = new_function(pool, name_dup, ret_ty) func: Function* = new_function(pool, name_dup, ret_ty)
if func is not None: if func is not None:
module_add_function(mod, func) module_add_function(mod, func)
return func return func
def add_param(pool: memhub.MemBuddy*, func: Function*, def add_param(pool: memhub.MemBuddy*, func: Function*,
ty: LLVMType*, name: str) -> Param*: ty: LLVMType*, name: str) -> Param*:
"""Create a parameter and add it to the function.""" """Create a parameter and add it to the function."""
name_dup: str = _str_dup(pool, name) name_dup: str = _str_dup(pool, name)
param: Param* = new_param(pool, ty, name_dup) param: Param* = new_param(pool, ty, name_dup)
if param is not None: if param is not None:
function_add_param(func, param) function_add_param(func, param)
return param return param
# ============================================================ # ============================================================
# Convenience factory: create a function declaration (declare) # Convenience factory: create a function declaration (declare)
# ============================================================ # ============================================================
def create_declare(pool: memhub.MemBuddy*, mod: LLVMModule*, def create_declare(pool: memhub.MemBuddy*, mod: LLVMModule*,
name: str, ret_ty: LLVMType*) -> Function*: name: str, ret_ty: LLVMType*) -> Function*:
"""Create a function declaration (declare, no body) and add it to the module. """Create a function declaration (declare, no body) and add it to the module.
Unlike create_function, it emits only: declare <ret_ty> @<name>(<params>) Unlike create_function, it emits only: declare <ret_ty> @<name>(<params>)
""" """
name_dup: str = _str_dup(pool, name) name_dup: str = _str_dup(pool, name)
func: Function* = new_function(pool, name_dup, ret_ty) func: Function* = new_function(pool, name_dup, ret_ty)
if func is not None: if func is not None:
func.IsDeclared = 1 func.IsDeclared = 1
module_add_function(mod, func) module_add_function(mod, func)
return func return func
# ============================================================ # ============================================================
# Convenience factory: create a string-constant global variable # Convenience factory: create a string-constant global variable
# #
# The initializer is stored in gv.Initializer as llvmlite-shaped LLVM syntax text (c"contents\00"); # The initializer is stored in gv.Initializer as llvmlite-shaped LLVM syntax text (c"contents\00");
# the MLIR render stage (__module.vp/_MlirGlobalInit) converts it to the attribute form "contents". # the MLIR render stage (__module.vp/_MlirGlobalInit) converts it to the attribute form "contents".
# ============================================================ # ============================================================
def create_global_string(pool: memhub.MemBuddy*, mod: LLVMModule*, def create_global_string(pool: memhub.MemBuddy*, mod: LLVMModule*,
name: str, text: str) -> GlobalVariable*: name: str, text: str) -> GlobalVariable*:
"""Create a string-constant global variable and add it to the module. """Create a string-constant global variable and add it to the module.
name: global name (e.g. ".str"); text: C string without trailing NUL (added automatically). name: global name (e.g. ".str"); text: C string without trailing NUL (added automatically).
Returns: GlobalVariable pointer of type [len+1 x i8]. Returns: GlobalVariable pointer of type [len+1 x i8].
""" """
if text is None: return None if text is None: return None
slen: sizet = string.strlen(text) slen: sizet = string.strlen(text)
# 显式收窄:LLVMType.Array 的 Count 是 int(i32),而 slen 是 sizet(u64); # 显式收窄:LLVMType.Array 的 Count 是 int(i32),而 slen 是 sizet(u64);
# 这里按显式转换(非隐式窄化)取 i32(字符串长度远超 2^31 不现实)。 # 这里按显式转换(非隐式窄化)取 i32(字符串长度远超 2^31 不现实)。
count: int = int(slen + 1) # includes the trailing NUL count: int = int(slen + 1) # includes the trailing NUL
# create i8 type # create i8 type
i8_ty: LLVMType* = pool.alloc(LLVMType.__sizeof__()) i8_ty: LLVMType* = pool.alloc(LLVMType.__sizeof__())
if i8_ty is None: return None if i8_ty is None: return None
string.memset(i8_ty, 0, LLVMType.__sizeof__()) string.memset(i8_ty, 0, LLVMType.__sizeof__())
*i8_ty = *LLVMType.Int(8) *i8_ty = *LLVMType.Int(8)
# create [count x i8] array type # create [count x i8] array type
arr_ty: LLVMType* = pool.alloc(LLVMType.__sizeof__()) arr_ty: LLVMType* = pool.alloc(LLVMType.__sizeof__())
if arr_ty is None: return None if arr_ty is None: return None
string.memset(arr_ty, 0, LLVMType.__sizeof__()) string.memset(arr_ty, 0, LLVMType.__sizeof__())
*arr_ty = *LLVMType.Array(i8_ty, count) *arr_ty = *LLVMType.Array(i8_ty, count)
# create global variable # create global variable
name_dup: str = _str_dup(pool, name) name_dup: str = _str_dup(pool, name)
gv: GlobalVariable* = new_global_variable(pool, name_dup, arr_ty) gv: GlobalVariable* = new_global_variable(pool, name_dup, arr_ty)
if gv is None: return None if gv is None: return None
# set attributes: private + unnamed_addr + constant # set attributes: private + unnamed_addr + constant
global_set_linkage(gv, "private") global_set_linkage(gv, "private")
global_set_unnamed_addr(gv, 1) global_set_unnamed_addr(gv, 1)
global_set_constant(gv, 1) global_set_constant(gv, 1)
# Build initializer text c"contents\00": LLVM IR string literal c"<chars>" with " \ and # Build initializer text c"contents\00": LLVM IR string literal c"<chars>" with " \ and
# non-printables escaped as \xx; buffer sized for worst case (4 bytes/char) + c"..." + \00 + " # non-printables escaped as \xx; buffer sized for worst case (4 bytes/char) + c"..." + \00 + "
init_buf: str = pool.alloc(slen * 4 + 8) init_buf: str = pool.alloc(slen * 4 + 8)
if init_buf is None: return None if init_buf is None: return None
pos: sizet = 0 pos: sizet = 0
init_buf[pos] = 'c' init_buf[pos] = 'c'
pos += 1 pos += 1
init_buf[pos] = '"' init_buf[pos] = '"'
pos += 1 pos += 1
for i in range(int(slen)): for i in range(int(slen)):
ch: uint8 = text[i] ch: uint8 = text[i]
if ch == 0x22 or ch == 0x5C or ch < 0x20 or ch >= 0x7F: if ch == 0x22 or ch == 0x5C or ch < 0x20 or ch >= 0x7F:
# escape: " -> \22, \ -> \5c, non-printable -> \xx # escape: " -> \22, \ -> \5c, non-printable -> \xx
init_buf[pos] = '\\' init_buf[pos] = '\\'
pos += 1 pos += 1
hi: int = (ch >> 4) & 0x0F hi: int = (ch >> 4) & 0x0F
lo: int = ch & 0x0F lo: int = ch & 0x0F
if hi < 10: if hi < 10:
init_buf[pos] = char(0x30 + hi) init_buf[pos] = char(0x30 + hi)
else: else:
init_buf[pos] = char(0x61 + hi - 10) init_buf[pos] = char(0x61 + hi - 10)
pos += 1 pos += 1
if lo < 10: if lo < 10:
init_buf[pos] = char(0x30 + lo) init_buf[pos] = char(0x30 + lo)
else: else:
init_buf[pos] = char(0x61 + lo - 10) init_buf[pos] = char(0x61 + lo - 10)
pos += 1 pos += 1
else: else:
init_buf[pos] = ch init_buf[pos] = ch
pos += 1 pos += 1
# trailing NUL byte # trailing NUL byte
init_buf[pos] = '\\' init_buf[pos] = '\\'
pos += 1 pos += 1
init_buf[pos] = '0' init_buf[pos] = '0'
pos += 1 pos += 1
init_buf[pos] = '0' init_buf[pos] = '0'
pos += 1 pos += 1
init_buf[pos] = '"' init_buf[pos] = '"'
pos += 1 pos += 1
init_buf[pos] = '\0' init_buf[pos] = '\0'
gv.Initializer = init_buf gv.Initializer = init_buf
module_add_global(mod, gv) module_add_global(mod, gv)
return gv return gv
# ============================================================ # ============================================================
# Convenience factory: create an integer global with an initializer # Convenience factory: create an integer global with an initializer
# ============================================================ # ============================================================
def create_global_int(pool: memhub.MemBuddy*, mod: LLVMModule*, def create_global_int(pool: memhub.MemBuddy*, mod: LLVMModule*,
name: str, bits: int, val: int64) -> GlobalVariable*: name: str, bits: int, val: int64) -> GlobalVariable*:
"""Create an integer global variable and add it to the module. """Create an integer global variable and add it to the module.
MLIR output: llvm.mlir.global @<name>(<val> : i<bits>) : i<bits> MLIR output: llvm.mlir.global @<name>(<val> : i<bits>) : i<bits>
""" """
# create integer type # create integer type
ty: LLVMType* = pool.alloc(LLVMType.__sizeof__()) ty: LLVMType* = pool.alloc(LLVMType.__sizeof__())
if ty is None: return None if ty is None: return None
string.memset(ty, 0, LLVMType.__sizeof__()) string.memset(ty, 0, LLVMType.__sizeof__())
*ty = *LLVMType.Int(bits) *ty = *LLVMType.Int(bits)
name_dup: str = _str_dup(pool, name) name_dup: str = _str_dup(pool, name)
gv: GlobalVariable* = new_global_variable(pool, name_dup, ty) gv: GlobalVariable* = new_global_variable(pool, name_dup, ty)
if gv is None: return None if gv is None: return None
# build initializer text "42" (the type is printed separately by the global render stage) # build initializer text "42" (the type is printed separately by the global render stage)
init_buf: str = pool.alloc(48) init_buf: str = pool.alloc(48)
if init_buf is None: return None if init_buf is None: return None
viperlib.snprintf(init_buf, 48, "%lld", val) viperlib.snprintf(init_buf, 48, "%lld", val)
gv.Initializer = init_buf gv.Initializer = init_buf
module_add_global(mod, gv) module_add_global(mod, gv)
return gv return gv
# ============================================================ # ============================================================
# LLVMModuleCore: module/function/value creation core; wraps pool to avoid passing it repeatedly # LLVMModuleCore: module/function/value creation core; wraps pool to avoid passing it repeatedly
# #
# Usage: # Usage:
# mcore: rawptr[LLVMModuleCore] = LLVMModuleCore(pool) # mcore: rawptr[LLVMModuleCore] = LLVMModuleCore(pool)
# mod: rawptr[LLVMModule] = mcore.NewModule("test") # mod: rawptr[LLVMModule] = mcore.NewModule("test")
# func: rawptr[Function] = mcore.CreateFunction(mod, "add", ty_i32) # func: rawptr[Function] = mcore.CreateFunction(mod, "add", ty_i32)
# val: rawptr[Value] = mcore.ConstInt32(42) # val: rawptr[Value] = mcore.ConstInt32(42)
# ============================================================ # ============================================================
novirtual class LLVMModuleCore: novirtual class LLVMModuleCore:
"""Module/function/value creation core; wraps pool so callers need not pass it.""" """Module/function/value creation core; wraps pool so callers need not pass it."""
Pool: memhub.MemBuddy* Pool: memhub.MemBuddy*
def __init__(self, pool: memhub.MemBuddy*): def __init__(self, pool: memhub.MemBuddy*):
self.Pool = pool self.Pool = pool
# ---- module operations ---- # ---- module operations ----
def NewModule(self, name: str) -> LLVMModule*: def NewModule(self, name: str) -> LLVMModule*:
return new_module(self.Pool, name) return new_module(self.Pool, name)
def CreateFunction(self, mod: LLVMModule*, name: str, def CreateFunction(self, mod: LLVMModule*, name: str,
ret_ty: LLVMType*) -> Function*: ret_ty: LLVMType*) -> Function*:
return create_function(self.Pool, mod, name, ret_ty) return create_function(self.Pool, mod, name, ret_ty)
def CreateDeclare(self, mod: LLVMModule*, name: str, def CreateDeclare(self, mod: LLVMModule*, name: str,
ret_ty: LLVMType*) -> Function*: ret_ty: LLVMType*) -> Function*:
"""Create a function declaration (declare, no body).""" """Create a function declaration (declare, no body)."""
return create_declare(self.Pool, mod, name, ret_ty) return create_declare(self.Pool, mod, name, ret_ty)
def AddParam(self, func: Function*, ty: LLVMType*, def AddParam(self, func: Function*, ty: LLVMType*,
name: str) -> Param*: name: str) -> Param*:
return add_param(self.Pool, func, ty, name) return add_param(self.Pool, func, ty, name)
def FunctionSetAttrs(self, func: Function*, attrs: str): def FunctionSetAttrs(self, func: Function*, attrs: str):
"""Set the function-level attribute text.""" """Set the function-level attribute text."""
function_set_attrs(func, attrs) function_set_attrs(func, attrs)
def ParamSetAttrs(self, param: Param*, attrs: str): def ParamSetAttrs(self, param: Param*, attrs: str):
"""Set the parameter attribute text.""" """Set the parameter attribute text."""
param_set_attrs(param, attrs) param_set_attrs(param, attrs)
def CreateBlock(self, func: Function*, def CreateBlock(self, func: Function*,
name: str) -> BasicBlock*: name: str) -> BasicBlock*:
return create_block(self.Pool, func, name) return create_block(self.Pool, func, name)
def NewBuilder(self, func: Function*) -> IRBuilder*: def NewBuilder(self, func: Function*) -> IRBuilder*:
return new_builder(self.Pool, func) return new_builder(self.Pool, func)
# ---- globals ---- # ---- globals ----
def NewGlobal(self, mod: LLVMModule*, name: str, def NewGlobal(self, mod: LLVMModule*, name: str,
ty: LLVMType*) -> GlobalVariable*: ty: LLVMType*) -> GlobalVariable*:
"""Create a global variable and add it to the module.""" """Create a global variable and add it to the module."""
name_dup: str = _str_dup(self.Pool, name) name_dup: str = _str_dup(self.Pool, name)
gv: GlobalVariable* = new_global_variable(self.Pool, name_dup, ty) gv: GlobalVariable* = new_global_variable(self.Pool, name_dup, ty)
if gv is not None: if gv is not None:
module_add_global(mod, gv) module_add_global(mod, gv)
return gv return gv
def CreateGlobalString(self, mod: LLVMModule*, name: str, def CreateGlobalString(self, mod: LLVMModule*, name: str,
text: str) -> GlobalVariable*: text: str) -> GlobalVariable*:
"""Create a string-constant global variable.""" """Create a string-constant global variable."""
return create_global_string(self.Pool, mod, name, text) return create_global_string(self.Pool, mod, name, text)
def CreateGlobalInt(self, mod: LLVMModule*, name: str, def CreateGlobalInt(self, mod: LLVMModule*, name: str,
bits: int, val: int64) -> GlobalVariable*: bits: int, val: int64) -> GlobalVariable*:
"""Create an integer global with an initializer.""" """Create an integer global with an initializer."""
return create_global_int(self.Pool, mod, name, bits, val) return create_global_int(self.Pool, mod, name, bits, val)
def GlobalSetConstant(self, gv: GlobalVariable*, is_const: int): def GlobalSetConstant(self, gv: GlobalVariable*, is_const: int):
global_set_constant(gv, is_const) global_set_constant(gv, is_const)
def GlobalSetLinkage(self, gv: GlobalVariable*, linkage: str): def GlobalSetLinkage(self, gv: GlobalVariable*, linkage: str):
global_set_linkage(gv, linkage) global_set_linkage(gv, linkage)
def GlobalSetUnnamedAddr(self, gv: GlobalVariable*, level: int): def GlobalSetUnnamedAddr(self, gv: GlobalVariable*, level: int):
global_set_unnamed_addr(gv, level) global_set_unnamed_addr(gv, level)
def GlobalSetSection(self, gv: GlobalVariable*, section: str): def GlobalSetSection(self, gv: GlobalVariable*, section: str):
global_set_section(gv, section) global_set_section(gv, section)
# ---- value creation ---- # ---- value creation ----
def ConstInt(self, bits: int, val: int64) -> Value*: def ConstInt(self, bits: int, val: int64) -> Value*:
return const_int(self.Pool, bits, val) return const_int(self.Pool, bits, val)
def ConstInt32(self, val: int64) -> Value*: def ConstInt32(self, val: int64) -> Value*:
return const_int32(self.Pool, val) return const_int32(self.Pool, val)
def ConstInt64(self, val: int64) -> Value*: def ConstInt64(self, val: int64) -> Value*:
return const_int64(self.Pool, val) return const_int64(self.Pool, val)
def ConstFloat(self, ty: LLVMType*, val: double) -> Value*: def ConstFloat(self, ty: LLVMType*, val: double) -> Value*:
return ConstFloat(self.Pool, ty, val) return ConstFloat(self.Pool, ty, val)
def SSAValue(self, ty: LLVMType*, name: str) -> Value*: def SSAValue(self, ty: LLVMType*, name: str) -> Value*:
return SSAValue(self.Pool, ty, name) return SSAValue(self.Pool, ty, name)
def ConstNull(self, ty: LLVMType*, name: str) -> Value*: def ConstNull(self, ty: LLVMType*, name: str) -> Value*:
return ConstNull(self.Pool, ty, name) return ConstNull(self.Pool, ty, name)
# ---- printing ---- # ---- printing ----
def PrintValue(self, buf: str, size: sizet, val: Value*): def PrintValue(self, buf: str, size: sizet, val: Value*):
ValuePrint(buf, size, val, self.Pool) ValuePrint(buf, size, val, self.Pool)
def PrintFunction(self, buf: str, size: sizet, func: Function*): def PrintFunction(self, buf: str, size: sizet, func: Function*):
FunctionPrint(buf, size, func, self.Pool) FunctionPrint(buf, size, func, self.Pool)
def PrintModule(self, buf: str, size: sizet, mod: LLVMModule*): def PrintModule(self, buf: str, size: sizet, mod: LLVMModule*):
LLVMModulePrint(buf, size, mod, self.Pool, OUTPUT_FULL) LLVMModulePrint(buf, size, mod, self.Pool, OUTPUT_FULL)
# ---- SSA verification ---- # ---- SSA verification ----
def NewVerifyResult(self, buf_size: sizet) -> VerifyResult*: def NewVerifyResult(self, buf_size: sizet) -> VerifyResult*:
"""Create a verify-result object (buf_size = error message buffer size).""" """Create a verify-result object (buf_size = error message buffer size)."""
return _new_verify_result(self.Pool, buf_size) return _new_verify_result(self.Pool, buf_size)
def VerifyFunction(self, func: Function*, def VerifyFunction(self, func: Function*,
result: VerifyResult*) -> int: result: VerifyResult*) -> int:
"""Verify SSA correctness of one function; returns error count (0 = pass).""" """Verify SSA correctness of one function; returns error count (0 = pass)."""
return verify_function(self.Pool, func, result) return verify_function(self.Pool, func, result)
def VerifyModule(self, mod: LLVMModule*, def VerifyModule(self, mod: LLVMModule*,
result: VerifyResult*) -> int: result: VerifyResult*) -> int:
"""Verify SSA correctness of all functions in the module; returns error count (0 = pass).""" """Verify SSA correctness of all functions in the module; returns error count (0 = pass)."""
return verify_module(self.Pool, mod, result) return verify_module(self.Pool, mod, result)
+1639 -1639
View File
File diff suppressed because it is too large. Load diff
+1383 -1383
View File
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -183,7 +183,7 @@ movups [{asminp(out, ASM_DESCR.REG_ANY)}], xmm0""",
def simd_add_array(a: double*, b: double*, out: double*, n: sizet): def simd_add_array(a: double*, b: double*, out: double*, n: sizet):
"""AVX2 batch: out[i:i+4] = a[i:i+4] + b[i:i+4], i=0,4,8,... """AVX2 batch: out[i:i+4] = a[i:i+4] + b[i:i+4], i=0,4,8,...
×8 double-buffering (32 doubles/iteration): 16 loads in flight (a: ymm0-7, b: ymm8-15), then 8 independent add->store chains; tail falls back to the single-vector loop (floor(n/4) vectors). ×8 double-buffering (32 doubles/iteration): 16 loads in flight (a: ymm0-7, b: ymm8-15), then 8 independent add->store chains; tail falls back to the single-vector loop (floor(n/4) vectors).
Note: ymm0-15 clobber requires TPV __asm__ support (CallGenCBuiltin ASM_MAX_CLOBBERS=32).""" Note: ymm0-15 clobber requires VPC __asm__ support (CallGenCBuiltin ASM_MAX_CLOBBERS=32)."""
__asm__(f"""mov rcx, {asminp(n, ASM_DESCR.REG_ANY)} __asm__(f"""mov rcx, {asminp(n, ASM_DESCR.REG_ANY)}
shr rcx, 2 shr rcx, 2
mov r8, {asminp(a, ASM_DESCR.REG_ANY)} mov r8, {asminp(a, ASM_DESCR.REG_ANY)}
+1 -1
View File
@@ -119,6 +119,6 @@ extern def FreeConsole() -> BOOL
extern def SetConsoleWindowInfo(hConsoleOutput: HANDLE, bAbsolute: BOOL, lpConsoleWindow: SMALL_RECT*) -> BOOL extern def SetConsoleWindowInfo(hConsoleOutput: HANDLE, bAbsolute: BOOL, lpConsoleWindow: SMALL_RECT*) -> BOOL
extern def ScrollConsoleScreenBufferA(hConsoleOutput: HANDLE, lpScrollRectangle: SMALL_RECT*, lpClipRectangle: SMALL_RECT*, dwDestinationOrigin: COORD, lpFill: CHAR_INFO*) -> BOOL extern def ScrollConsoleScreenBufferA(hConsoleOutput: HANDLE, lpScrollRectangle: SMALL_RECT*, lpClipRectangle: SMALL_RECT*, dwDestinationOrigin: COORD, lpFill: CHAR_INFO*) -> BOOL
# SetConsoleCtrlHandler registration/removal (consoleapi.h / kernel32.dll): pass the routine name directly, bitcast by TPV (function pointers declared as rawptr). # SetConsoleCtrlHandler registration/removal (consoleapi.h / kernel32.dll): pass the routine name directly, bitcast by VPC (function pointers declared as rawptr).
# Returns 0 on failure (see GetLastError); Add=FALSE removes the registered routine. # Returns 0 on failure (see GetLastError); Add=FALSE removes the registered routine.
extern def SetConsoleCtrlHandler(HandlerRoutine: rawptr, Add: BOOL) -> BOOL extern def SetConsoleCtrlHandler(HandlerRoutine: rawptr, Add: BOOL) -> BOOL
+1 -1
View File
@@ -118,7 +118,7 @@ extern def SymGetModuleBase64(hProcess: HANDLE, AddrBase: ULONGLONG) -> ULONGLON
# PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, # PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
# PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, # PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
# PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); # PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
# The three callbacks follow the "function pointers passed as rawptr" convention: pass the function name (ReadProcessMemory / SymFunctionTableAccess64 / SymGetModuleBase64), bitcast by TPV. # The three callbacks follow the "function pointers passed as rawptr" convention: pass the function name (ReadProcessMemory / SymFunctionTableAccess64 / SymGetModuleBase64), bitcast by VPC.
# TranslateAddress is None (0): x64 needs no address-translation routine. # TranslateAddress is None (0): x64 needs no address-translation routine.
extern def StackWalk64(MachineType: DWORD, hProcess: HANDLE, hThread: HANDLE, extern def StackWalk64(MachineType: DWORD, hProcess: HANDLE, hThread: HANDLE,
StackFrame: STACKFRAME64*, ContextRecord: VOIDPTR, StackFrame: STACKFRAME64*, ContextRecord: VOIDPTR,