refactor(backend): 单端 MLIR —— 发射器全树改名 mlirlite 并删除 --backend 开关

- App/Test 的 .vp 中 llvmlite 全部改名为 mlirlite(import、限定名、类型注解、注释)

- 删除后端开关:Config.set_backend/is_mlir_backend/alias_module_name、BackendTarget/BackendIsMlir、CLI --backend、options.backend/options.target 读取,以及 IncludesScanner/StubMergerIR 的模块别名调用

- BuildPipeline 的 mlir-opt -> mlir-translate 降级管线去掉开关门,改为恒执行

- backend_dir_suffix 改名 mlir_dir_suffix 并恒返回 _mlir:TempDir/OutputDir/includes 缓存继续落在 *_mlir,避免复用旧 LLVM 后端的 .ll/obj

- project.vpj 删除已失效的 options.target
This commit is contained in:
TermiNexus committed 2026-10-03 19:26:24 +08:00
1 parent 1dcd29db9c
commit 7b3e814524
70 files changed
+5670 -5746

No files matched your search

+48 -50
View File
@@ -53,7 +53,7 @@ _phase2_cmd_path: str = None
# bat 文件是否已写入 header(@echo off),首次写入时置 1
_phase2_bat_init: int = 0
# MLIR 后端(Config.is_mlir_backend())降级步骤:mlirlite 发射的是 MLIR 文本,
# MLIR 降级步骤(单端固定,无后端开关):mlirlite 发射的是 MLIR 文本,
# 而 opt/llc 只接受 LLVM IR,故在两者之前插入:
# mlir-opt <in> -o <in>.mlir.opt (语法/语义校验)
# mlir-translate --mlir-to-llvmir <in>.mlir.opt -o <in>.ll.local (降级回 LLVM IR)
@@ -270,8 +270,8 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy*, file_path: str,
return None
# --traceback: when this file is includes/traceback.vp, inject the startup
# Install() ctor into its IR (before the caller dumps stub/text.ll). The
# injector lives in the Gen layer, which already depends on llvmlite, so
# BuildPipeline gains no cross-module llvmlite symbol dependency.
# injector lives in the Gen layer, which already depends on mlirlite, so
# BuildPipeline gains no cross-module mlirlite symbol dependency.
if _traceback_mode != 0 and _tb_basename_is_traceback(file_path) != 0:
HandlesTranslator.InjectTracebackInstallCtor(tr)
return tr
@@ -426,37 +426,36 @@ def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: s
# 用直接地址寻址,ASan 全局 redzone 重定位后引用错位会读到垃圾指针。
compile_input: str = ir_path
# ---- MLIR 后端降级:mlir-opt(校验)→ mlir-translate(降级回 LLVM IR)----
# ---- MLIR 降级(单端固定,无开关):mlir-opt(校验)→ mlir-translate ----
# 必须在 ASan opt 与 llc 之前,并把 compile_input 替换为 <...>.ll.local。
if Config.is_mlir_backend() != 0:
ll_local_path: str = _ir_sibling_path(ir_path, ".ll.local")
mlir_opt_out: str = _ir_sibling_path(ir_path, ".mlir.opt")
if ll_local_path is None or mlir_opt_out is None:
ll_local_path: str = _ir_sibling_path(ir_path, ".ll.local")
mlir_opt_out: str = _ir_sibling_path(ir_path, ".mlir.opt")
if ll_local_path is None or mlir_opt_out is None:
return 1
mo_len: sizet = len(MLIR_OPT_CMD) + len(ir_path) + len(mlir_opt_out) + 16
cmd_mo: str = _mbuddy.alloc(mo_len)
if cmd_mo is None:
return 1
viperlib.snprintf(cmd_mo, mo_len, "%s %s -o %s", MLIR_OPT_CMD, ir_path, mlir_opt_out)
mt_len: sizet = len(MLIR_TRANSLATE_CMD) + len(mlir_opt_out) + len(ll_local_path) + 40
cmd_mt: str = _mbuddy.alloc(mt_len)
if cmd_mt is None:
return 1
viperlib.snprintf(cmd_mt, mt_len, "%s --mlir-to-llvmir %s -o %s", MLIR_TRANSLATE_CMD, mlir_opt_out, ll_local_path)
if _phase2_cmd_path is not None:
# 只写命令(须排在下面的 ASan/llc 命令之前)
_phase2_write_cmd(cmd_mo)
_phase2_write_cmd(cmd_mt)
else:
mo_rc: int = _run_cmd_wait(cmd_mo)
if mo_rc != 0:
VLogger.error(f"mlir-opt 失败 (module={module_name}, exit={mo_rc}, cmd={cmd_mo})", "MLIR")
return 1
mo_len: sizet = len(MLIR_OPT_CMD) + len(ir_path) + len(mlir_opt_out) + 16
cmd_mo: str = _mbuddy.alloc(mo_len)
if cmd_mo is None:
mt_rc: int = _run_cmd_wait(cmd_mt)
if mt_rc != 0:
VLogger.error(f"mlir-translate 失败 (module={module_name}, exit={mt_rc}, cmd={cmd_mt})", "MLIR")
return 1
viperlib.snprintf(cmd_mo, mo_len, "%s %s -o %s", MLIR_OPT_CMD, ir_path, mlir_opt_out)
mt_len: sizet = len(MLIR_TRANSLATE_CMD) + len(mlir_opt_out) + len(ll_local_path) + 40
cmd_mt: str = _mbuddy.alloc(mt_len)
if cmd_mt is None:
return 1
viperlib.snprintf(cmd_mt, mt_len, "%s --mlir-to-llvmir %s -o %s", MLIR_TRANSLATE_CMD, mlir_opt_out, ll_local_path)
if _phase2_cmd_path is not None:
# 只写命令(须排在下面的 ASan/llc 命令之前)
_phase2_write_cmd(cmd_mo)
_phase2_write_cmd(cmd_mt)
else:
mo_rc: int = _run_cmd_wait(cmd_mo)
if mo_rc != 0:
VLogger.error(f"mlir-opt 失败 (module={module_name}, exit={mo_rc}, cmd={cmd_mo})", "MLIR")
return 1
mt_rc: int = _run_cmd_wait(cmd_mt)
if mt_rc != 0:
VLogger.error(f"mlir-translate 失败 (module={module_name}, exit={mt_rc}, cmd={cmd_mt})", "MLIR")
return 1
compile_input = ll_local_path
compile_input = ll_local_path
# --phase2command 模式:不执行 opt/llc,把 opt(ASan)+ llc 命令写入 bat
if _phase2_cmd_path is not None:
@@ -577,25 +576,24 @@ def init_llc_task(task: LlcTask | t.CPtr, ir_path: str, output_dir: str,
# compile_ll_to_obj 的 compile_input 同口径(否则 opt 生成了插桩产物
# 却被 llc 忽略,App 侧 obj 里 0 处 __asan,内存排查半盲)
compile_input: str = ir_path
# MLIR 后端降级:worker 先跑 mlir-opt(校验)→ mlir-translate(降级回 LLVM IR),
# 之后的 ASan OptCmd / LlcCmd 输入必须是 <...>.ll.local。
if Config.is_mlir_backend() != 0:
ll_local_path: str = _ir_sibling_path(ir_path, ".ll.local")
mlir_opt_out: str = _ir_sibling_path(ir_path, ".mlir.opt")
if ll_local_path is None or mlir_opt_out is None:
return 1
mo_len: sizet = len(MLIR_OPT_CMD) + len(ir_path) + len(mlir_opt_out) + 16
task.MlirOptCmd = stdlib.malloc(mo_len)
if task.MlirOptCmd is None:
return 1
viperlib.snprintf(task.MlirOptCmd, mo_len, "%s %s -o %s", MLIR_OPT_CMD, ir_path, mlir_opt_out)
mt_len: sizet = len(MLIR_TRANSLATE_CMD) + len(mlir_opt_out) + len(ll_local_path) + 40
task.MlirTranslateCmd = stdlib.malloc(mt_len)
if task.MlirTranslateCmd is None:
return 1
viperlib.snprintf(task.MlirTranslateCmd, mt_len, "%s --mlir-to-llvmir %s -o %s",
MLIR_TRANSLATE_CMD, mlir_opt_out, ll_local_path)
compile_input = ll_local_path
# MLIR 降级(单端固定,无开关):worker 先跑 mlir-opt(校验)→ mlir-translate
# (降级回 LLVM IR),之后的 ASan OptCmd / LlcCmd 输入必须是 <...>.ll.local。
ll_local_path: str = _ir_sibling_path(ir_path, ".ll.local")
mlir_opt_out: str = _ir_sibling_path(ir_path, ".mlir.opt")
if ll_local_path is None or mlir_opt_out is None:
return 1
mo_len: sizet = len(MLIR_OPT_CMD) + len(ir_path) + len(mlir_opt_out) + 16
task.MlirOptCmd = stdlib.malloc(mo_len)
if task.MlirOptCmd is None:
return 1
viperlib.snprintf(task.MlirOptCmd, mo_len, "%s %s -o %s", MLIR_OPT_CMD, ir_path, mlir_opt_out)
mt_len: sizet = len(MLIR_TRANSLATE_CMD) + len(mlir_opt_out) + len(ll_local_path) + 40
task.MlirTranslateCmd = stdlib.malloc(mt_len)
if task.MlirTranslateCmd is None:
return 1
viperlib.snprintf(task.MlirTranslateCmd, mt_len, "%s --mlir-to-llvmir %s -o %s",
MLIR_TRANSLATE_CMD, mlir_opt_out, ll_local_path)
compile_input = ll_local_path
# ASan 模式:opt 插桩命令(worker 先跑 MLIR 降级/opt 再跑 llc,故 LlcCmd 的输入
# 必须指向 asan_path;失败即置 Result)
if _asan_mode != 0:
+7 -7
View File
@@ -7,7 +7,7 @@ import viperlib
import w32.fileio as fileio
import w32.win32base
import ast
import llvmlite
import mlirlite
import lib.core.VLogger as VLogger
import lib.core.Gen.Translator as HandlesTranslator
import lib.core.IncludesScanner as IncludesScanner
@@ -522,7 +522,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str,
# ============================================================
# Phase 1a-pre-generic-all: mark1 前全量预注册 includes 泛型模板
#
# 非可达泛型文件(_list/_dict/linkedlist/llvmlite 等)的模板若在 Phase2(mark2 之后)才注册会被 reset 回收 → list[int]/dict[...] 特化失败。
# 非可达泛型文件(_list/_dict/linkedlist/mlirlite 等)的模板若在 Phase2(mark2 之后)才注册会被 reset 回收 → list[int]/dict[...] 特化失败。
# 故对全部 includes 轻量预注册,使模板表与节点都落在 mark1 之前(_PreRegisterAllGenericTemplates 内有 generic marker 文本预筛,不 parse 全部 AST,OOM 风险可控)。
full_scan_g: rawptr[IncludesScanner.ScanResult] = IncludesScanner.scan_includes(mb, includes_dir)
if full_scan_g is not None:
@@ -1087,8 +1087,8 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str,
# --traceback: inject the startup Install() ctor when translating traceback.vp
# (its stub/text.ll below are what Phase2 reuses to build the .obj). The
# injector lives in the Gen layer (already depends on llvmlite), so this
# module gains no cross-module llvmlite symbol dependency.
# injector lives in the Gen layer (already depends on mlirlite), so this
# module gains no cross-module mlirlite symbol dependency.
if BuildPipeline._traceback_mode != 0 and BuildPipeline._tb_basename_is_traceback(file_path) != 0:
HandlesTranslator.InjectTracebackInstallCtor(tr)
@@ -1113,7 +1113,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str,
stdlib.free(tr._nonlocal_names)
failed += 1
continue
tr.dump_ir(stub_buf, PHASE1_IR_SIZE, llvmlite.OUTPUT_STUB)
tr.dump_ir(stub_buf, PHASE1_IR_SIZE, mlirlite.OUTPUT_STUB)
stub_len: sizet = string.strlen(stub_buf)
# save stub.ll
@@ -1137,7 +1137,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str,
stdlib.free(tr._nonlocal_names)
failed += 1
continue
tr.dump_ir(text_buf, PHASE1_IR_SIZE, llvmlite.OUTPUT_TEXT)
tr.dump_ir(text_buf, PHASE1_IR_SIZE, mlirlite.OUTPUT_TEXT)
text_len: sizet = string.strlen(text_buf)
# save text.ll
@@ -1158,7 +1158,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str,
full_buf_p1: bytes = stdlib.malloc(PHASE1_FULL_SIZE)
if full_buf_p1 is None:
VLogger.error("full.ll 缓冲区分配失败", "Phase1")
tr.dump_ir(full_buf_p1, PHASE1_FULL_SIZE, llvmlite.OUTPUT_FULL)
tr.dump_ir(full_buf_p1, PHASE1_FULL_SIZE, mlirlite.OUTPUT_FULL)
full_len_p1: sizet = string.strlen(full_buf_p1)
full_path_p1: str = StubMergerCollect._sliced_path(temp_dir, dir_len_p1, sha1, "full.ll")
if full_path_p1 is not None:
+1 -1
View File
@@ -9,7 +9,7 @@ import w32.fileio as fileio
import w32.win32file
import w32.win32base
import ast
import llvmlite
import mlirlite
import lib.core.VLogger as VLogger
import lib.core.Gen.Translator as HandlesTranslator
import lib.core.IncludesScanner as IncludesScanner
+1 -1
View File
@@ -8,7 +8,7 @@ import w32.fileio as fileio
import w32.win32file
import w32.win32base
import ast
import llvmlite
import mlirlite
import lib.core.VLogger as VLogger
import lib.core.Gen.Translator as HandlesTranslator
import lib.core.IncludesScanner as IncludesScanner
+7 -7
View File
@@ -11,7 +11,7 @@ import w32.win32file
import w32.win32base
import sys
import ast
import llvmlite
import mlirlite
import subprocess
import argparse
import lib.core.VLogger as VLogger
@@ -1069,7 +1069,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*,
stub_buf_a: bytes = stdlib.malloc(PHASE_A_IR_SIZE)
if stub_buf_a is None:
VLogger.error("stub 缓冲区分配失败", "PhaseA")
tr_a.dump_ir(stub_buf_a, PHASE_A_IR_SIZE, llvmlite.OUTPUT_STUB)
tr_a.dump_ir(stub_buf_a, PHASE_A_IR_SIZE, mlirlite.OUTPUT_STUB)
stub_len_a: sizet = string.strlen(stub_buf_a)
# save stub.ll (切片路径: temp_dir/{sha1前缀}/{sha1}.stub.ll)
@@ -1086,7 +1086,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*,
text_buf_a: bytes = stdlib.malloc(PHASE_A_IR_SIZE)
if text_buf_a is None:
VLogger.error("text 缓冲区分配失败", "PhaseA")
tr_a.dump_ir(text_buf_a, PHASE_A_IR_SIZE, llvmlite.OUTPUT_TEXT)
tr_a.dump_ir(text_buf_a, PHASE_A_IR_SIZE, mlirlite.OUTPUT_TEXT)
text_len_a: sizet = string.strlen(text_buf_a)
# save text.ll (切片路径)
@@ -1106,7 +1106,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*,
full_buf_a: bytes = stdlib.malloc(PHASE_A_FULL_SIZE)
if full_buf_a is None:
VLogger.error("full.ll 缓冲区分配失败", "PhaseA")
tr_a.dump_ir(full_buf_a, PHASE_A_FULL_SIZE, llvmlite.OUTPUT_FULL)
tr_a.dump_ir(full_buf_a, PHASE_A_FULL_SIZE, mlirlite.OUTPUT_FULL)
full_len_a: sizet = string.strlen(full_buf_a)
full_path_a: str = StubMergerCollect._sliced_path(temp_dir, td_len_pa, ent.Sha1, "full.ll")
if full_path_a is not None:
@@ -1484,7 +1484,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*,
# 保存 stub.ll (切片路径)
inc_stub_buf: bytes = stdlib.malloc(PBP_IR_SIZE)
if inc_stub_buf is not None:
tr_mi.dump_ir(inc_stub_buf, PBP_IR_SIZE, llvmlite.OUTPUT_STUB)
tr_mi.dump_ir(inc_stub_buf, PBP_IR_SIZE, mlirlite.OUTPUT_STUB)
inc_stub_len: sizet = string.strlen(inc_stub_buf)
inc_stub_path: str = StubMergerCollect._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "stub.ll")
if inc_stub_path is not None:
@@ -1497,7 +1497,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*,
# 保存 text.ll (切片路径)
inc_text_buf: bytes = stdlib.malloc(PBP_IR_SIZE)
if inc_text_buf is not None:
tr_mi.dump_ir(inc_text_buf, PBP_IR_SIZE, llvmlite.OUTPUT_TEXT)
tr_mi.dump_ir(inc_text_buf, PBP_IR_SIZE, mlirlite.OUTPUT_TEXT)
inc_text_len: sizet = string.strlen(inc_text_buf)
inc_text_path: str = StubMergerCollect._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "text.ll")
if inc_text_path is not None:
@@ -1513,7 +1513,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*,
inc_full_buf: bytes = stdlib.malloc(PBP_FULL_SIZE)
if inc_full_buf is None:
VLogger.error("full.ll 缓冲区分配失败", "PhaseB+")
tr_mi.dump_ir(inc_full_buf, PBP_FULL_SIZE, llvmlite.OUTPUT_FULL)
tr_mi.dump_ir(inc_full_buf, PBP_FULL_SIZE, mlirlite.OUTPUT_FULL)
inc_full_len: sizet = string.strlen(inc_full_buf)
inc_full_path: str = StubMergerCollect._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "full.ll")
if inc_full_path is not None:
+16 -66
View File
@@ -44,15 +44,13 @@ IncludesDirs: str = None # 全部 includes 目录(空格分隔,多
_inc_bin_suffix: str = ".binary"
# ============================================================
# 后端(Emitter Backend)
# 发射后端:**单端 MLIR**(2026-10-03 起)
#
# "llvm"(默认):IR 发射走 includes/llvmlite(LLVM IR 文本),opt/llc 直接消费。
# "mlir" :模块名 llvmlite 在解析层重定向到 includes/mlirlite(MLIR 文本),
# 并在 opt/llc 之前插入 mlir-opt(校验)→ mlir-translate(降级回 LLVM IR)。
# 只认字符串 "mlir":缺省 / 未知值一律按 LLVM(BackendIsMlir=0),保证默认路径逐字不变。
# 全树发射器已由 includes/llvmlite 改为 includes/mlirlite(`import mlirlite`),
# 不再有 `--backend` 开关、不再有模块别名:mlirlite 发射的是 MLIR 文本,
# 故 BuildPipeline 恒在 opt/llc 之前插入
# mlir-opt(校验)→ mlir-translate --mlir-to-llvmir(降级回 LLVM IR)。
# ============================================================
BackendTarget: str = "llvm"
BackendIsMlir: int = 0
def Load_project_config(path: str) -> int:
@@ -156,16 +154,6 @@ def Load_project_config(path: str) -> int:
sm: JsonValue | t.CPtr = options["strict_mode"]
if sm is not None and sm.is_bool():
StrictMode = 1 if sm.as_bool() else 0
# 后端:options.backend(新键)优先,回退 options.target(兼容旧键)。
# 只认 "mlir";其余(含缺省/未知)按 LLVM。CLI --backend 由 main.vp
# 在本函数返回后覆盖(CLI 优先级最高)。
be_val: JsonValue | t.CPtr = options["backend"]
if be_val is not None and be_val.is_string():
set_backend(be_val.as_string())
else:
tgt_be: JsonValue | t.CPtr = options["target"]
if tgt_be is not None and tgt_be.is_string():
set_backend(tgt_be.as_string())
# 读取 includes 数组(支持多目录:首元素存 IncludesDir,全部拼接存 IncludesDirs)
includes_val: JsonValue | t.CPtr = root["includes"]
@@ -445,10 +433,10 @@ def resolve_paths(project_dir: str) -> int:
SourceDir = _join_path(SourceDir, project_dir)
BuildDir = _join_path(BuildDir, project_dir)
# TempDir = {BuildDir}/temp(非 LLVM 后端追加隔离后缀,如 _mlir;LLVM 时后缀为空串,路径逐字不变)
# TempDir = {BuildDir}/temp(单端 MLIR 恒追加 _mlir 隔离后缀)
if BuildDir is not None:
bd_len: sizet = string.strlen(BuildDir)
suf_dir: str = backend_dir_suffix()
suf_dir: str = mlir_dir_suffix()
suf_dir_len: sizet = string.strlen(suf_dir)
temp_buf: str = _mbuddy.alloc(bd_len + suf_dir_len + 8)
if temp_buf is not None:
@@ -661,13 +649,13 @@ def get_includes_binary_dir() -> str:
includes 目录如 ../includes,默认返回 ../includes.binary;
asan 模式(set_inc_bin_suffix(".binary_asan"))返回 ../includes.binary_asan,
隔离 asan 插桩 obj,避免与非 asan obj 混链。
非 LLVM 后端再追加后端后缀(如 .binary_asan_mlir),隔离不同后端的 obj。
再追加单端 MLIR 后缀(如 .binary_asan_mlir):隔离旧 LLVM 后端留下的缓存 obj。
"""
if IncludesDir is None:
return None
inc_len: sizet = string.strlen(IncludesDir)
suf_len: sizet = string.strlen(_inc_bin_suffix)
be_suf: str = backend_dir_suffix()
be_suf: str = mlir_dir_suffix()
be_suf_len: sizet = string.strlen(be_suf)
buf: str = _mbuddy.alloc(inc_len + suf_len + be_suf_len + 1)
if buf is None:
@@ -677,53 +665,15 @@ def get_includes_binary_dir() -> str:
# ============================================================
# 后端开关(Emitter Backend)
# 单端 MLIR 的目录隔离后缀
#
# set_backend: 只接受 "llvm" / "mlir"(其余返回 1 且不改动),大小写敏感。
# backend_dir_suffix: 非默认后端的目录隔离后缀;LLVM 后端返回空串(调用方拼出的
# 路径与改前逐字相同)。用于 TempDir/OutputDir/includes.binary。
# is_mlir_backend: 0/1 便捷视图(BuildPipeline 降级管线的门)。
# 发射器固定为 mlirlite(MLIR 文本),故后缀恒为 "_mlir":TempDir/OutputDir/
# includes 缓存都落在 *_mlir 目录,与旧 LLVM 后端留下的 temp/output/.binary
# 缓存彻底分离(否则增量构建会复用旧的 LLVM IR .ll / obj,喂给 mlir-opt 必炸)。
# ============================================================
def set_backend(name: str) -> int:
"""设置后端;0=成功,1=非法(name 为 None 或非 llvm/mlir)"""
global BackendTarget, BackendIsMlir
if name is None:
return 1
if string.strcmp(name, "llvm") == 0:
BackendTarget = name
BackendIsMlir = 0
return 0
if string.strcmp(name, "mlir") == 0:
BackendTarget = name
BackendIsMlir = 1
return 0
return 1
def is_mlir_backend() -> int:
"""是否 MLIR 后端(1=mlir / 0=llvm)"""
return BackendIsMlir
def backend_dir_suffix() -> str:
"""非默认后端的目录隔离后缀(LLVM 后端返回空串 ⇒ 路径逐字不变)"""
if BackendIsMlir != 0:
return "_mlir"
return ""
def alias_module_name(name: str) -> str:
"""MLIR 后端下把模块名 "llvmlite" 重定向到 "mlirlite"(其余原样返回)。
这是"TransPyV 调用点零改动"的唯一开关:所有 **名称→模块/文件/SHA1** 的解析
都应经此函数(模块文件解析 IncludesScanner.ResolveModuleToPath、依赖名→SHA1
StubMergerIR._FindSha1ByModName 等)。LLVM 后端恒等返回,默认路径逐字不变。
"""
if name is None:
return None
if BackendIsMlir != 0 and string.strcmp(name, "llvmlite") == 0:
return "mlirlite"
return name
def mlir_dir_suffix() -> str:
"""单端 MLIR 的目录隔离后缀(恒为 "_mlir")"""
return "_mlir"
def asan_runtime_declared() -> int:
+175 -175
View File
@@ -9,7 +9,7 @@ import stdio
import stdlib
import sys
import memhub
import llvmlite
import mlirlite
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
@@ -774,8 +774,8 @@ def _resolve_vpi_param_annot_seg_template(pool: memhub.MemBuddy*,
cls_name: str,
method_name: str,
seg_idx: int,
i32_ty: llvmlite.LLVMType*,
i8_ptr_ty: llvmlite.LLVMType*) -> llvmlite.LLVMType*:
i32_ty: mlirlite.LLVMType*,
i8_ptr_ty: mlirlite.LLVMType*) -> mlirlite.LLVMType*:
"""特化类 X[arg] 的参数注解段解析(模板 X[T] 注解 + T→arg 替换);未命中 None"""
if pool is None or src_sha1 is None or cls_name is None or method_name is None \
or _g_vpi_param_keys is None:
@@ -802,7 +802,7 @@ def _resolve_vpi_param_annot_seg_template(pool: memhub.MemBuddy*,
string.strncpy(arg_t, lbkt_t + 1, arg_len_t)
arg_t[arg_len_t] = '\0'
sha1_len_t: sizet = string.strlen(src_sha1)
ty_t: llvmlite.LLVMType* = None
ty_t: mlirlite.LLVMType* = None
ki_t: int
for ki_t in range(_g_vpi_param_count):
gk_t: bytes = _g_vpi_param_keys + ki_t * VPI_PARAM_KEY_LEN
@@ -873,13 +873,13 @@ def _resolve_vpi_param_annot_seg_template(pool: memhub.MemBuddy*,
# 补全后 declare 参数数与 define 一致,调用点默认参数填充才能生效,避免被调函数读栈垃圾。
# ============================================================
def _repair_declare_params_from_text(pool: memhub.MemBuddy*,
func: llvmlite.Function*,
func: mlirlite.Function*,
src_sha1: str,
cls_name: str,
method_name: str,
param_count: int,
i32_ty: llvmlite.LLVMType*,
i8_ptr_ty: llvmlite.LLVMType*) -> int:
i32_ty: mlirlite.LLVMType*,
i8_ptr_ty: mlirlite.LLVMType*) -> int:
"""用 vpi 文本缓存的参数注解补全 declare 参数;返回补全后参数数"""
if func is None or src_sha1 is None or method_name is None:
return param_count
@@ -906,18 +906,18 @@ def _repair_declare_params_from_text(pool: memhub.MemBuddy*,
if prm_annots[cur2] == '@':
cur2 += 1
if seg_idx >= param_count:
param_ty_r: llvmlite.LLVMType* = i8_ptr_ty
param_ty_r: mlirlite.LLVMType* = i8_ptr_ty
if seg_len2 > 0:
seg_buf_r: bytes = stdlib.malloc(seg_len2 + 1)
if seg_buf_r is not None:
string.strncpy(seg_buf_r, prm_annots + seg_start2, seg_len2)
seg_buf_r[seg_len2] = '\0'
rt: llvmlite.LLVMType* = _resolve_vpi_ret_annot_str(
rt: mlirlite.LLVMType* = _resolve_vpi_ret_annot_str(
pool, seg_buf_r, i32_ty, i8_ptr_ty)
if rt is not None:
param_ty_r = rt
stdlib.free(seg_buf_r)
llvmlite.add_param(pool, func, param_ty_r, "arg")
mlirlite.add_param(pool, func, param_ty_r, "arg")
seg_start2 = cur2
seg_idx += 1
return pa_count
@@ -935,8 +935,8 @@ def _resolve_vpi_param_annot_seg(pool: memhub.MemBuddy*,
cls_name: str,
method_name: str,
seg_idx: int,
i32_ty: llvmlite.LLVMType*,
i8_ptr_ty: llvmlite.LLVMType*) -> llvmlite.LLVMType*:
i32_ty: mlirlite.LLVMType*,
i8_ptr_ty: mlirlite.LLVMType*) -> mlirlite.LLVMType*:
"""按段索引解析 vpi 参数注解段为 LLVMType,空段/失败返回 None"""
if pool is None or src_sha1 is None or method_name is None:
return None
@@ -963,7 +963,7 @@ def _resolve_vpi_param_annot_seg(pool: memhub.MemBuddy*,
return None
string.strncpy(seg_buf_p, prm_annots_p + seg_start_p, seg_len_p)
seg_buf_p[seg_len_p] = '\0'
seg_ty_p: llvmlite.LLVMType* = _resolve_vpi_ret_annot_str(
seg_ty_p: mlirlite.LLVMType* = _resolve_vpi_ret_annot_str(
pool, seg_buf_p, i32_ty, i8_ptr_ty)
stdlib.free(seg_buf_p)
return seg_ty_p
@@ -1317,7 +1317,7 @@ def _lookup_vpi_ret_annot(src_sha1: str, cls_name: str, method_name: str) -> str
# 纯字符串解析,不构造 AST 节点。
# ============================================================
def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*,
seg: str) -> llvmlite.LLVMType*:
seg: str) -> mlirlite.LLVMType*:
"""解析单个类型段为 LLVMType,无法识别返回 None"""
if seg is None or pool is None:
return None
@@ -1359,37 +1359,37 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*,
while star_k_ps < star_cnt_ps:
string.strcat(star_buf_ps, "]")
star_k_ps += 1
star_ty_ps: llvmlite.LLVMType* = _resolve_single_vpi_type_str(pool, star_buf_ps)
star_ty_ps: mlirlite.LLVMType* = _resolve_single_vpi_type_str(pool, star_buf_ps)
stdlib.free(star_buf_ps)
return star_ty_ps
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
# 内置别名
if string.strcmp(seg, "str") == 0 or string.strcmp(seg, "bytes") == 0:
return i8_ptr_ty
if string.strcmp(seg, "int") == 0:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
if string.strcmp(seg, "bool") == 0:
return llvmlite.Int1(pool)
return mlirlite.Int1(pool)
# LLVM 类型串:vpi 缓存对无返回注解方法默认存 "i32"
# (见 _cache_vpi_return_annots_text;push 等无注解方法返回 i32)。
# 之前缺分支导致解析返回 None → 泛型模板方法(Vector[int].push)调用
# 走 fail-fast"方法返回类型无法精确获取",实际是约定不一致。
if string.strcmp(seg, "i32") == 0: return llvmlite.Int32(pool)
if string.strcmp(seg, "i64") == 0: return llvmlite.Int64(pool)
if string.strcmp(seg, "i16") == 0: return llvmlite.Int16(pool)
if string.strcmp(seg, "i32") == 0: return mlirlite.Int32(pool)
if string.strcmp(seg, "i64") == 0: return mlirlite.Int64(pool)
if string.strcmp(seg, "i16") == 0: return mlirlite.Int16(pool)
if string.strcmp(seg, "i8") == 0: return i8_ty
if string.strcmp(seg, "i1") == 0: return llvmlite.Int1(pool)
if string.strcmp(seg, "f32") == 0: return llvmlite.Float(pool)
if string.strcmp(seg, "f64") == 0: return llvmlite.Double(pool)
if string.strcmp(seg, "void") == 0: return llvmlite.Void(pool)
if string.strcmp(seg, "i1") == 0: return mlirlite.Int1(pool)
if string.strcmp(seg, "f32") == 0: return mlirlite.Float(pool)
if string.strcmp(seg, "f64") == 0: return mlirlite.Double(pool)
if string.strcmp(seg, "void") == 0: return mlirlite.Void(pool)
# vpi 源文本中 `-> None` 被原样缓存为 "None"(_cache_vpi_return_annots_text
# 提取 arrow_pos 后到 ':' 前的内容)。此前无 "None" 分支 → 解析返回 None →
# `-> None` 的跨模块方法(如 AssignGenMixin._register_cdefine_from_value)vpi
# 缓存命中也解析不出 void → 方法返回类型 fail-fast 误报(追加80e 断点 B)。
# None 与 void 同义,归一到 Void。
if string.strcmp(seg, "None") == 0:
return llvmlite.Void(pool)
return mlirlite.Void(pool)
# rawptr[T] 内建裸指针(等价 t.CPtr[T] → Ptr(T)):vpi 返回/参数注解按源码
# 原样保留 Subscript 形态(如 tokens.vp `new_token -> rawptr[Token]`)。
# 此前无此分支 → 整个注解解析返回 None → text.ll 尚未生成(合法时序:依赖
@@ -1404,10 +1404,10 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*,
if inner_buf_rp is not None:
string.strncpy(inner_buf_rp, seg + 7, inner_len_rp)
inner_buf_rp[inner_len_rp] = '\0'
inner_ty_rp: llvmlite.LLVMType* = _resolve_single_vpi_type_str(pool, inner_buf_rp)
inner_ty_rp: mlirlite.LLVMType* = _resolve_single_vpi_type_str(pool, inner_buf_rp)
stdlib.free(inner_buf_rp)
if inner_ty_rp is not None:
return llvmlite.Ptr(pool, inner_ty_rp)
return mlirlite.Ptr(pool, inner_ty_rp)
return None
# t.CPtr[T] / c.CPtr[T] 下标指针(含嵌套,如 t.CPtr[t.CPtr] → Ptr(Ptr(i8))):与定义侧 TypeGenResolve 的 Subscript(CPtr) 分支同口径 Ptr(resolve(T))。
# vpi 注解文本按源码原样缓存;本函数若对该形态返回 None 会让该段被丢弃 → 联合坍缩到首段(i8),与定义侧指针层级不一致(跨模块 declare/define ABI 错位)。
@@ -1422,11 +1422,11 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*,
if inner_buf_cp is not None:
string.strncpy(inner_buf_cp, seg + cptr_sub_pfx, inner_len_cp)
inner_buf_cp[inner_len_cp] = '\0'
inner_ty_cp: llvmlite.LLVMType* = _resolve_single_vpi_type_str(
inner_ty_cp: mlirlite.LLVMType* = _resolve_single_vpi_type_str(
pool, inner_buf_cp)
stdlib.free(inner_buf_cp)
if inner_ty_cp is not None:
return llvmlite.Ptr(pool, inner_ty_cp)
return mlirlite.Ptr(pool, inner_ty_cp)
return None
# t.XXX / c.XXX 内置类型映射
if string.strncmp(seg, "t.", 2) == 0 or string.strncmp(seg, "c.", 2) == 0:
@@ -1437,10 +1437,10 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*,
# 返回类型无法精确获取 fail-fast 误报(VKernel mm.free -> t.CExport
# "1fdad1c76fb116bc.free 返回类型无法精确获取" 根因)。
if string.strcmp(attr_nm, "CExport") == 0:
return llvmlite.Void(pool)
return mlirlite.Void(pool)
# [阶段2] 统一口径:CTypedef 动态表优先(库 typedef 走正常库分析),
# miss 回退 map_t_type(t/c 库内部特判)。
mapped_ty: llvmlite.LLVMType* = GenApi.resolve_typedef_or_map(pool, attr_nm, None, None)
mapped_ty: mlirlite.LLVMType* = GenApi.resolve_typedef_or_map(pool, attr_nm, None, None)
if mapped_ty is not None:
return mapped_ty
return None
@@ -1448,7 +1448,7 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*,
last_dot: str = string.strrchr(seg, '.')
if last_dot is not None:
cls_nm2: str = last_dot + 1
mod_struct_ty: llvmlite.LLVMType* = GenApi.get_struct_type(cls_nm2)
mod_struct_ty: mlirlite.LLVMType* = GenApi.get_struct_type(cls_nm2)
if mod_struct_ty is not None:
return mod_struct_ty
# 枚举兜底:t.CEnum 注册在独立 EnumTable(EnumEntry),不进 StructTable,
@@ -1456,20 +1456,20 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*,
# struct 落空必须回退枚举表取 BaseTy(通常 i32)。否则 vpi 返回注解解析
# 失败 → 跨模块函数返回类型无法精确获取 → text.ll 缺失(依赖环)时
# 永久 pending(VKernel fat32→sched→process→fat32 Phase A 死锁根因)。
mod_enum_ty: llvmlite.LLVMType* = GenApi.get_enum_base_type(cls_nm2)
mod_enum_ty: mlirlite.LLVMType* = GenApi.get_enum_base_type(cls_nm2)
if mod_enum_ty is not None:
return mod_enum_ty
return None
# 裸类名 → 全局 struct 注册表
bare_struct_ty: llvmlite.LLVMType* = GenApi.get_struct_type(seg)
bare_struct_ty: mlirlite.LLVMType* = GenApi.get_struct_type(seg)
if bare_struct_ty is not None:
return bare_struct_ty
# 裸枚举名 → EnumTable 兜底(同上:枚举不在 StructTable)
bare_enum_ty: llvmlite.LLVMType* = GenApi.get_enum_base_type(seg)
bare_enum_ty: mlirlite.LLVMType* = GenApi.get_enum_base_type(seg)
if bare_enum_ty is not None:
return bare_enum_ty
# 裸 typedef 名(如 VOIDPTR):CTypedef 动态表优先,miss 回退 map_t_type
mapped_bare: llvmlite.LLVMType* = GenApi.resolve_typedef_or_map(pool, seg, None, None)
mapped_bare: mlirlite.LLVMType* = GenApi.resolve_typedef_or_map(pool, seg, None, None)
if mapped_bare is not None:
return mapped_bare
return None
@@ -1484,8 +1484,8 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*,
# ============================================================
def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*,
ret_annot: str,
i32_ty: llvmlite.LLVMType*,
i8_ptr_ty: llvmlite.LLVMType*) -> llvmlite.LLVMType*:
i32_ty: mlirlite.LLVMType*,
i8_ptr_ty: mlirlite.LLVMType*) -> mlirlite.LLVMType*:
"""直接解析 vpi 返回注解字符串为 LLVMType(不构造 AST 节点)"""
if ret_annot is None or pool is None:
return None
@@ -1500,10 +1500,10 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*,
inner_len_t += 1
if ret_annot[6 + inner_len_t] != ']' or inner_len_t == 0:
return None
# tuple 返回类型的字段链表是 llvmlite.ParamNode(new_param_node / paramnode_set_next /
# tuple 返回类型的字段链表是 mlirlite.ParamNode(new_param_node / paramnode_set_next /
# Struct 形参均为 rawptr[ParamNode])——原先误注解为 Function*。
tup_head_t: llvmlite.ParamNode* = None
tup_tail_t: llvmlite.ParamNode* = None
tup_head_t: mlirlite.ParamNode* = None
tup_tail_t: mlirlite.ParamNode* = None
tup_count_t: int = 0
p_t: sizet = 0
while p_t < inner_len_t:
@@ -1523,26 +1523,26 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*,
return None
string.strncpy(seg_buf_t, ret_annot + 6 + seg_s_t, seg_len_t)
seg_buf_t[seg_len_t] = '\0'
seg_ty_t: llvmlite.LLVMType* = _resolve_single_vpi_type_str(pool, seg_buf_t)
seg_ty_t: mlirlite.LLVMType* = _resolve_single_vpi_type_str(pool, seg_buf_t)
stdlib.free(seg_buf_t)
if seg_ty_t is None:
return None
tup_node_t: llvmlite.ParamNode* = llvmlite.new_param_node(pool, seg_ty_t)
tup_node_t: mlirlite.ParamNode* = mlirlite.new_param_node(pool, seg_ty_t)
if tup_node_t is None:
return None
if tup_head_t is None:
tup_head_t = tup_node_t
else:
llvmlite.paramnode_set_next(tup_tail_t, tup_node_t)
mlirlite.paramnode_set_next(tup_tail_t, tup_node_t)
tup_tail_t = tup_node_t
tup_count_t += 1
if tup_head_t is None:
return None
return llvmlite.Struct(pool, tup_head_t, tup_count_t, None)
return mlirlite.Struct(pool, tup_head_t, tup_count_t, None)
has_cptr: int = 0
has_cvoid: int = 0
first_ty: llvmlite.LLVMType* = None
first_ty: mlirlite.LLVMType* = None
# 产生 first_ty 那一段文本的属性(供末尾 has_cptr 分支复刻定义侧规则,N12):
# first_qual=1 段是限定名(含 '.',如 mod.Class / int64)
# first_wl =1 段是白名单裸标量名(int/char/str/bytes/bool/float/double)
@@ -1557,7 +1557,7 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*,
# 与定义侧 `X | t.CPtr[T]` 分支同口径:CPtr 侧贡献 N 层指针、另一侧提供基类型 ⇒ Ptr^N(基类型)。
# 与 has_cptr(裸 t.CPtr 段)分开记录:裸标记恒「追加 1 层」且有 struct 吸收特例,下标路径无吸收,两者在定义侧分属互斥分支。
cptr_sub_lvl: int = 0
cptr_sub_ty: llvmlite.LLVMType* = None
cptr_sub_ty: mlirlite.LLVMType* = None
buf_len: sizet = string.strlen(ret_annot)
pos: sizet = 0
@@ -1601,18 +1601,18 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*,
# 语义不同(如 X=struct S、t.CPtr[t.CPtr]:定义侧 Ptr(Ptr(S)),
# 取该段本身则得 i8**)。此处只记录 N 与段类型,末尾统一合并。
if string.strncmp(seg_buf, "t.CPtr[", 7) == 0 or string.strncmp(seg_buf, "c.CPtr[", 7) == 0:
seg_ty_cs: llvmlite.LLVMType* = _resolve_single_vpi_type_str(pool, seg_buf)
seg_ty_cs: mlirlite.LLVMType* = _resolve_single_vpi_type_str(pool, seg_buf)
if seg_ty_cs is not None:
# 计算外层 Ptr 嵌套数(定义侧 L2616-2632 同口径)。注意不能在
# case body 内更新 while 条件变量(自举编译的 match 会写到 subject
# 快照槽 → 条件读旧槽死循环,见 TypeGenResolve.vp L2620-2624):
# case 绑定 pointee 到局部变量,match 外更新循环变量。
lvl_cs: int = 0
cur_cs: llvmlite.LLVMType* = seg_ty_cs
cur_cs: mlirlite.LLVMType* = seg_ty_cs
while cur_cs is not None:
nxt_cs: llvmlite.LLVMType* = None
nxt_cs: mlirlite.LLVMType* = None
match cur_cs:
case llvmlite.LLVMType.Ptr(pointee_cs):
case mlirlite.LLVMType.Ptr(pointee_cs):
lvl_cs += 1
nxt_cs = pointee_cs
case _:
@@ -1631,7 +1631,7 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*,
# (void* 应为 i8*,由下方 has_cptr 分支统一给出)。
has_cvoid = 1
else:
seg_ty: llvmlite.LLVMType* = _resolve_single_vpi_type_str(pool, seg_buf)
seg_ty: mlirlite.LLVMType* = _resolve_single_vpi_type_str(pool, seg_buf)
if seg_ty is not None and first_ty is None:
first_ty = seg_ty
# 记录该段属性(N12):定义侧 TypeGenResolve.resolve_annotation_type
@@ -1652,7 +1652,7 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*,
# 而定义侧已改为「解析成功即保留」⇒ 跨模块同型收敛被破坏。判据直接用 GenApi.resolve_typedef_or_map(与定义侧同一 API),命中即置位保留;
# 仅对**非指针**解析结果置位(指针别名 BYTEPTR/HANDLE/VOIDPTR 不置位 → 仍坍缩 i8*,与定义侧守卫对称)。
if first_qual == 0 and first_wl == 0:
if first_ty.kind() != llvmlite.LLVMType.Ptr:
if first_ty.kind() != mlirlite.LLVMType.Ptr:
if GenApi.resolve_typedef_or_map(pool, seg_buf, None, None) is not None:
first_td = 1
stdlib.free(seg_buf)
@@ -1666,7 +1666,7 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*,
# 解析出 void)⇒ 与 t.CPtr 合并即 void* = i8*,与 has_cvoid 分支同结论
# (否则会拼出非法的 Ptr(void))。
match first_ty:
case llvmlite.LLVMType.Void():
case mlirlite.LLVMType.Void():
return i8_ptr_ty
case _:
pass
@@ -1675,17 +1675,17 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*,
# 指针别名(first_td 不置位,如 VOIDPTR = CVoid|CPtr → i8*):`| t.CPtr`
# **恒追加恰好 1 层** → i8**(不吸收);指针型 T 同理(见下)。
if first_qual != 0 or first_wl != 0 or first_td != 0:
return llvmlite.Ptr(pool, first_ty)
if first_ty.kind() == llvmlite.LLVMType.Struct:
return llvmlite.Ptr(pool, first_ty)
if first_ty.kind() == llvmlite.LLVMType.Ptr:
return mlirlite.Ptr(pool, first_ty)
if first_ty.kind() == mlirlite.LLVMType.Struct:
return mlirlite.Ptr(pool, first_ty)
if first_ty.kind() == mlirlite.LLVMType.Ptr:
# `| t.CPtr` **恒追加恰好 1 层**(与定义侧 TypeGenResolve 的 BinOp 分支同口径):
# 这里原先还做"pointee 命中 find_struct_by_type(类引用语义)就吸收 1 层",
# 那是"裸类名自动升指针"时代的补偿,自裸类名恒为**原型 struct** 后已无对象;
# 而泛型形参实例化为指针类型时(T 的实参文本 `{sha}.AST*`)first_ty 正是
# Ptr(已注册 struct) ⇒ 误吸收把 `T*` 降成 AST*(应为 AST**),
# 现场 includes/_list.vp:54 `elem_ptr[0] = item`。
return llvmlite.Ptr(pool, first_ty)
return mlirlite.Ptr(pool, first_ty)
return i8_ptr_ty
return i8_ptr_ty
# CPtr 下标段联合合并(与定义侧同口径):有另一侧基类型 first_ty → 结果 = Ptr^N(first_ty)(N=cptr_sub_lvl);仅 CPtr 下标段自身 → 该段解析类型本身。
@@ -1693,17 +1693,17 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*,
if cptr_sub_lvl > 0:
if first_ty is None:
return cptr_sub_ty
res_ty_cs: llvmlite.LLVMType* = first_ty
res_ty_cs: mlirlite.LLVMType* = first_ty
wrap_i_cs: int = 0
while wrap_i_cs < cptr_sub_lvl:
res_ty_cs = llvmlite.Ptr(pool, res_ty_cs)
res_ty_cs = mlirlite.Ptr(pool, res_ty_cs)
wrap_i_cs += 1
return res_ty_cs
if has_cvoid != 0:
# t\.CVoid | t.State:State 是装饰器标记(编译侧忽略),t\.CVoid → void。
# 此前缺此分支 → first_ty=None → 返回 None → 跨模块函数返回类型
# fail-fast(CPythonTest Py_Initialize() -> t\.CVoid | t.State 根因)。
return llvmlite.Void(pool)
return mlirlite.Void(pool)
if first_ty is not None:
return first_ty
return None
@@ -2034,7 +2034,7 @@ def _vpi_register_typedef_closure(pool: memhub.MemBuddy*,
# Returns: 1=成功,0=失败
# ============================================================
def ParseVpiIntoModule(pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
vpi_path: str,
trans: HT.Translator*) -> int:
"""解析 .vpi 文件,将函数声明注入到当前模块
@@ -2053,7 +2053,7 @@ def ParseVpiIntoModule(pool: memhub.MemBuddy*,
def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
vpi_path: str,
trans: HT.Translator*) -> int:
"""解析 .vpi 文件,将函数声明注入到当前模块(ParseVpiIntoModule 实际实现)"""
@@ -2331,9 +2331,9 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*,
if imported_modules is not None:
_vpi_register_typedef_closure(pool, imported_modules, GenApi.get_temp_dir(), 0)
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
# 函数表信息
funcs_ptr: GenTypes.FuncEntry* = trans._funcs
@@ -2542,7 +2542,7 @@ def ResetVpiInjectVisited() -> None:
def _ensure_dep_vpi_injected(pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
dep_sha1: str,
trans: HT.Translator*) -> int:
"""按需注入 dep_sha1 对应的 .vpi 到当前模块(防重入),1=就绪 / 0=失败"""
@@ -2617,7 +2617,7 @@ def _ensure_dep_vpi_injected(pool: memhub.MemBuddy*,
# Args: src_name 子模块中的原类名;local_name 包命名空间中的名字(或 as 别名);sub_sha1 子模块(定义文件)sha1;pkg_sha1 当前包 __init__ 的 sha1;trans 翻译器对象(源 entry 缺失时按需注入子模块 vpi 需要)
# ============================================================
def _inject_reexport_class_declare(pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
src_name: str,
local_name: str,
sub_sha1: str,
@@ -2745,7 +2745,7 @@ def _vpi_class_is_renum(class_cd: ast.ClassDef*) -> int:
# 字段解析失败不 fatal(不注册该类,留给源模块编译注册,后续裸类名引用由调用侧 fail-fast 暴露)。
# ============================================================
def _inject_class_struct_declare(pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
class_cd: ast.ClassDef*,
cls_name: str,
trans: HT.Translator*,
@@ -2859,7 +2859,7 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*,
m_tgt_c: ast.Name* = ast.Name*(m_aa_c.target)
if m_tgt_c.id is None:
continue
field_ty_c: llvmlite.LLVMType* = GenApi.resolve_annotation_type(
field_ty_c: mlirlite.LLVMType* = GenApi.resolve_annotation_type(
pool, m_aa_c.annotation, imported_modules, from_imports, trans, 0)
if field_ty_c is None:
# 字段类型解析失败:不注册该类(留给源模块编译注册),不 fatal
@@ -2873,14 +2873,14 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*,
if field_count == 0:
return 0
# 4. 构建 ParamNode 链表
first_node_c: rawptr[llvmlite.ParamNode] = None
prev_node_c: rawptr[llvmlite.ParamNode] = None
first_node_c: rawptr[mlirlite.ParamNode] = None
prev_node_c: rawptr[mlirlite.ParamNode] = None
for fi_c in range(field_count):
fty_c: llvmlite.LLVMType* = (llvmlite.LLVMType*)(field_types_buf[fi_c])
pnode_c: rawptr[llvmlite.ParamNode] = pool.alloc(llvmlite.ParamNode.__sizeof__())
fty_c: mlirlite.LLVMType* = (mlirlite.LLVMType*)(field_types_buf[fi_c])
pnode_c: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__())
if pnode_c is None:
continue
string.memset(pnode_c, 0, llvmlite.ParamNode.__sizeof__())
string.memset(pnode_c, 0, mlirlite.ParamNode.__sizeof__())
pnode_c.Ty = fty_c
if first_node_c is None:
first_node_c = pnode_c
@@ -2904,14 +2904,14 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*,
name_buf_c[sh_len_c] = '.'
string.strcpy(name_buf_c + sh_len_c + 1, real_name)
type_name_c = name_buf_c
struct_ty_c: llvmlite.LLVMType* = llvmlite.Struct(
struct_ty_c: mlirlite.LLVMType* = mlirlite.Struct(
pool, first_node_c, field_count, type_name_c)
if struct_ty_c is None:
return 0
# 5. StdlibAlloc(Phase B)时深拷贝到 perm_pool,跨文件 reset 存活
# (对齐 ClassGenDef.translate_class_def L489-494)
if GenApi.get_stdlib_alloc() != 0:
st_copy_c: llvmlite.LLVMType* = llvmlite.DeepCopyType(
st_copy_c: mlirlite.LLVMType* = mlirlite.DeepCopyType(
CompilerFactory.factory.PermPool, struct_ty_c)
if st_copy_c is not None:
struct_ty_c = st_copy_c
@@ -2923,21 +2923,21 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*,
# ⇒ StructTable 爆表(现场:table full, cannot register Translator)。
# 必须早于 module_add_named_type:避免同一名字先以占位名注册、又以新对象重复注册。
if fill_fwd_c != 0 and existing_c is not None and existing_c.Ty is not None:
fwd_name_c: str = llvmlite.get_struct_name(existing_c.Ty)
fwd_fields_c: rawptr[llvmlite.ParamNode] = llvmlite.get_struct_fields(struct_ty_c)
fwd_fc_c: int = llvmlite.get_struct_fcount(struct_ty_c)
*existing_c.Ty = llvmlite.LLVMType.Struct(fwd_fields_c, fwd_fc_c, fwd_name_c)
fwd_name_c: str = mlirlite.get_struct_name(existing_c.Ty)
fwd_fields_c: rawptr[mlirlite.ParamNode] = mlirlite.get_struct_fields(struct_ty_c)
fwd_fc_c: int = mlirlite.get_struct_fcount(struct_ty_c)
*existing_c.Ty = mlirlite.LLVMType.Struct(fwd_fields_c, fwd_fc_c, fwd_name_c)
struct_ty_c = existing_c.Ty
type_name_c = fwd_name_c
existing_c.IsForwardDecl = 0
existing_c.FieldCount = 0
# 6. 注册到当前模块(输出类型定义行)+ 全局 StructTable + 可见性
llvmlite.module_add_named_type(mod, pool, struct_ty_c)
mlirlite.module_add_named_type(mod, pool, struct_ty_c)
# B5:vpi 保留 @c.Attribute(t.attr.packed) 装饰器,stub 注入的跨模块
# struct 必须同样 packed(<{...}>),否则引用模块 GEP 按非 packed 布局
# 算偏移,与定义侧 packed 布局错位(gdt/elf/fat32 二进制格式字段错读)。
if _vpi_class_has_packed(class_cd.decorator_list) != 0:
llvmlite.module_set_named_type_packed(mod, pool, struct_ty_c, 1)
mlirlite.module_set_named_type_packed(mod, pool, struct_ty_c, 1)
# 注册名用扁平名 real_name:跨模块引用 `外类.内类` 时 TypeGenResolve 查的是
# 扁平名条目(与定义端 StructGen 的登记名同源)。
entry_c: GenTypes.StructEntry* = GenApi.register_struct(
@@ -2955,7 +2955,7 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*,
afi_c: int = 0
for afi_c in range(field_count):
af_name_c: str = str(field_names_buf[afi_c])
af_ty_c: llvmlite.LLVMType* = (llvmlite.LLVMType*)(field_types_buf[afi_c])
af_ty_c: mlirlite.LLVMType* = (mlirlite.LLVMType*)(field_types_buf[afi_c])
GenApi.add_field(pool, entry_c, af_name_c, af_ty_c)
GenApi.add_visible_struct(pool, real_name)
return 1
@@ -2977,7 +2977,7 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*,
# mark_module_class 还原(见 _inject_class_struct_declare 内注释)。
# ============================================================
def _inject_nested_class_declares(pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
class_cd: ast.ClassDef*,
prefix_name: str,
trans: HT.Translator*,
@@ -3012,23 +3012,23 @@ def _inject_nested_class_declares(pool: memhub.MemBuddy*,
# 均报 "use of undefined type"(值类型大小需已知)。vpi 注入类已 add_field 含字段(完整 Ty),在注册表可查时注册完整定义;
# 指针引用(Ptr(Struct))无需——_scan_type_for_cross_module_refs 的 Ptr 分支添加 opaque 即可。
# ============================================================
def _ensure_full_value_types(mod: llvmlite.LLVMModule*,
def _ensure_full_value_types(mod: mlirlite.LLVMModule*,
pool: memhub.MemBuddy*,
ty: llvmlite.LLVMType*) -> None:
ty: mlirlite.LLVMType*) -> None:
"""递归为值 struct / 数组元素 struct 注册完整定义(递归深度守卫)"""
if mod is None or pool is None or ty is None: return
match ty:
case llvmlite.LLVMType.Struct(_, _, _):
case mlirlite.LLVMType.Struct(_, _, _):
full_se_h: GenTypes.StructEntry* = GenApi.find_struct_by_type(ty)
if full_se_h is not None and full_se_h.Ty is not None:
llvmlite.module_add_named_type(mod, pool, full_se_h.Ty)
mlirlite.module_add_named_type(mod, pool, full_se_h.Ty)
# B5:值类型注入同步 packed 标记(对齐 ensure_struct_def_in_module)——
# vpi 全局变量(@_per_cpu = global %per_cpu_data)/值返回类型注入完整
# 定义时若只 add 不 set_packed → 引用模块节点 IsPacked=0 → 输出 {…}
# 非 packed(GEP 与定义侧 packed 布局错位,stub packed 失效根因)。
if full_se_h.IsPacked != 0:
llvmlite.module_set_named_type_packed(mod, pool, full_se_h.Ty, 1)
case llvmlite.LLVMType.Array(aelem_h, _):
mlirlite.module_set_named_type_packed(mod, pool, full_se_h.Ty, 1)
case mlirlite.LLVMType.Array(aelem_h, _):
if aelem_h is not None:
_ensure_full_value_types(mod, pool, aelem_h)
case _:
@@ -3049,18 +3049,18 @@ def _ensure_full_value_types(mod: llvmlite.LLVMModule*,
# Windows x64 ABI 小结构体(≤8 字节)按整数寄存器传、位兼容,且与定义侧同样降级 ⇒ 同符号签名仍逐字一致)。
# * TPV 内部函数/方法(存在 define 侧)→ Ptr(struct):与定义侧逐字一致,指针目标只需 opaque 声明(module_ensure_opaque_for_type)。
# ============================================================
def _AggregateParamTy(mod: llvmlite.LLVMModule*,
def _AggregateParamTy(mod: mlirlite.LLVMModule*,
pool: memhub.MemBuddy*,
ty: llvmlite.LLVMType*,
is_c_abi: int) -> llvmlite.LLVMType*:
ty: mlirlite.LLVMType*,
is_c_abi: int) -> mlirlite.LLVMType*:
"""裸结构体形参类型(C ABI 按值 / 内部 Ptr(struct),见上方注释)"""
if mod is None or pool is None or ty is None:
return ty
if is_c_abi != 0:
# 真 opaque 哨兵:fcount < 0(includes/llvmlite/__module.vp L491)
# 真 opaque 哨兵:fcount < 0(includes/mlirlite/__module.vp L491)
is_opaque_ap: int = 0
match ty:
case llvmlite.LLVMType.Struct(_, fcount_ap, _):
case mlirlite.LLVMType.Struct(_, fcount_ap, _):
if fcount_ap < 0:
is_opaque_ap = 1
case _:
@@ -3068,9 +3068,9 @@ def _AggregateParamTy(mod: llvmlite.LLVMModule*,
if is_opaque_ap == 0 and GenApi.find_struct_by_type(ty) is not None:
_ensure_full_value_types(mod, pool, ty)
return ty
return llvmlite.Int64(pool)
ptr_ty_ap: llvmlite.LLVMType* = llvmlite.Ptr(pool, ty)
llvmlite.module_ensure_opaque_for_type(mod, pool, ptr_ty_ap)
return mlirlite.Int64(pool)
ptr_ty_ap: mlirlite.LLVMType* = mlirlite.Ptr(pool, ty)
mlirlite.module_ensure_opaque_for_type(mod, pool, ptr_ty_ap)
return ptr_ty_ap
@@ -3081,13 +3081,13 @@ def _AggregateParamTy(mod: llvmlite.LLVMModule*,
# 否则跨模块 from-import 读取全局变量时 find_global_in_module 找不到 → 误杀「跨模块全局变量类型未知(stub 未注入)」。
# ============================================================
def _inject_global_variable_declare(pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
aa: ast.AnnAssign*,
trans: HT.Translator*,
imported_modules: str,
from_imports: str,
i32_ty: llvmlite.LLVMType*,
i8_ptr_ty: llvmlite.LLVMType*,
i32_ty: mlirlite.LLVMType*,
i8_ptr_ty: mlirlite.LLVMType*,
src_sha1: str) -> None:
"""从 vpi AnnAssign 创建模块级全局变量 external declare(mangled 名 @<src_sha1>.<name>)"""
if pool is None or mod is None or aa is None or trans is None:
@@ -3130,30 +3130,30 @@ def _inject_global_variable_declare(pool: memhub.MemBuddy*,
if gv_name_m is not None:
viperlib.snprintf(gv_name_m, ml_v, "%s.%s", src_sha1, gname_v)
# 去重:遍历模块全局变量链表(mangled 名匹配)
cur_v: llvmlite.GlobalVariable* = mod.GlobalHead
cur_v: mlirlite.GlobalVariable* = mod.GlobalHead
while cur_v is not None:
if cur_v.Name is not None and string.strcmp(cur_v.Name, gv_name_m) == 0:
return
cur_v = cur_v.Next
# 解析注解类型(裸类 → Ptr(struct),CArray → 元素指针)
resolved_v: llvmlite.LLVMType* = None
resolved_v: mlirlite.LLVMType* = None
if aa.annotation is not None:
resolved_v = GenApi.resolve_annotation_type(
pool, aa.annotation, imported_modules, from_imports, trans)
if resolved_v is None:
return # 类型解析失败跳过:调用侧有 fail-fast 定位
gv_ty_v: llvmlite.LLVMType* = resolved_v
gv_ty_v: mlirlite.LLVMType* = resolved_v
match resolved_v:
case llvmlite.LLVMType.Struct(_, _, _):
case mlirlite.LLVMType.Struct(_, _, _):
# 对象类(@t.Object/@t.CVTable:对象即指针,HasNew/HasVTable/IsOOP)→ Ptr(struct),与定义端 handle_module_level_var 一致;
# 纯 t.CStruct 值类(如 pci_device)保持值实例——一律转 Ptr 会把实例前 8 字节当指针解引用(#GP),一律保持值则 @t.Object 类模块级变量按指针访问读错 vtable(#PF)。
gv_entry_v: GenTypes.StructEntry* = GenApi.find_struct_by_type(resolved_v)
if gv_entry_v is not None \
and (gv_entry_v.HasNew != 0 or gv_entry_v.HasVTable != 0 or gv_entry_v.IsOOP != 0):
gv_ty_v = llvmlite.Ptr(pool, resolved_v)
gv_ty_v = mlirlite.Ptr(pool, resolved_v)
else:
gv_ty_v = resolved_v
case llvmlite.LLVMType.Array(aelem_v, acount_v):
case mlirlite.LLVMType.Array(aelem_v, acount_v):
# 定长数组(CArray[T, N]):保留完整数组类型 [N x T],与定义端
# handle_module_level_var 生成的 global [N x T] 一致——此前一律
# 衰减为元素指针 i32*,链接后引用端 load 把数组前 8 字节当指针
@@ -3163,7 +3163,7 @@ def _inject_global_variable_declare(pool: memhub.MemBuddy*,
gv_ty_v = resolved_v
else:
# 不定长数组(CArray[T, None]):元素指针(C 数组衰减)
gv_ty_v = llvmlite.Ptr(pool, aelem_v)
gv_ty_v = mlirlite.Ptr(pool, aelem_v)
case _:
gv_ty_v = resolved_v
# 确保跨模块结构体类型在模块中有 opaque 声明:external global 类型
@@ -3173,11 +3173,11 @@ def _inject_global_variable_declare(pool: memhub.MemBuddy*,
# (_scan_type_for_cross_module_refs 递归 Array/Struct/Ptr)。
# 值类型(struct 值 / 数组元素 struct)注册完整定义(见 _ensure_full_value_types)
_ensure_full_value_types(mod, pool, gv_ty_v)
llvmlite.module_ensure_opaque_for_type(mod, pool, gv_ty_v)
gv_v: llvmlite.GlobalVariable* = llvmlite.new_global_variable(pool, gv_name_m, gv_ty_v)
mlirlite.module_ensure_opaque_for_type(mod, pool, gv_ty_v)
gv_v: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, gv_name_m, gv_ty_v)
if gv_v is None:
return
llvmlite.module_add_global(mod, gv_v)
mlirlite.module_add_global(mod, gv_v)
gv_v.Linkage = "external"
@@ -3189,14 +3189,14 @@ def _inject_global_variable_declare(pool: memhub.MemBuddy*,
# 注册到函数表。
# ============================================================
def _inject_function_declare(pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
fd: ast.FunctionDef*,
trans: HT.Translator*,
src_sha1: str,
imported_modules: str,
from_imports: str,
i32_ty: llvmlite.LLVMType*,
i8_ptr_ty: llvmlite.LLVMType*,
i32_ty: mlirlite.LLVMType*,
i8_ptr_ty: mlirlite.LLVMType*,
funcs_ptr: GenTypes.FuncEntry*,
max_funcs: int) -> None:
"""为 FunctionDef 创建 declare 声明并注入到模块"""
@@ -3253,12 +3253,12 @@ def _inject_function_declare(pool: memhub.MemBuddy*,
return
# 去重:如果函数已存在则跳过
existing: llvmlite.Function* = GenApi.find_func_in_module(mod, mangled_name)
existing: mlirlite.Function* = GenApi.find_func_in_module(mod, mangled_name)
if existing is not None:
return
# 也检查裸名(非裸名模式时,CExport 函数可能已通过其他途径注册)
if use_bare_name == 0:
existing_bare: llvmlite.Function* = GenApi.find_func_in_module(mod, fd.name)
existing_bare: mlirlite.Function* = GenApi.find_func_in_module(mod, fd.name)
if existing_bare is not None:
return
@@ -3266,7 +3266,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*,
# 优先用缓存的返回注解字符串(tree 解析后立即提取,节点未损坏)
# 直接字符串解析(绕开 _parse_type_string 跨模块 AST 构造在 TPV 中的
# __init__/vtable 未执行问题,节点 kind() 异常导致 resolve 得垃圾类型)
ret_ty: llvmlite.LLVMType* = None
ret_ty: mlirlite.LLVMType* = None
ret_annot_fd: str = _lookup_vpi_ret_annot(src_sha1, None, fd.name)
if ret_annot_fd is not None:
ret_ty = _resolve_vpi_ret_annot_str(pool, ret_annot_fd, i32_ty, i8_ptr_ty)
@@ -3291,7 +3291,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*,
or string.strcmp(pm_at.attr, "CExport") == 0):
is_pure_marker_rt = 1
if is_pure_marker_rt != 0:
ret_ty = llvmlite.Void(pool)
ret_ty = mlirlite.Void(pool)
elif has_state != 0 or has_extern != 0 or has_export != 0:
# 含真实类型但解析失败:回退外部函数返回类型白名单
# (FindFirstFileA/GetStdHandle → i8* HANDLE 等),避免默认 i32
@@ -3310,10 +3310,10 @@ def _inject_function_declare(pool: memhub.MemBuddy*,
# 值 struct 返回类型(如 gfx.vp Mat4_Identity -> Mat4)需要完整定义:
# declare %Mat4 opaque → llc "use of undefined type"。注册完整定义。
_ensure_full_value_types(mod, pool, ret_ty)
llvmlite.module_ensure_opaque_for_type(mod, pool, ret_ty)
mlirlite.module_ensure_opaque_for_type(mod, pool, ret_ty)
# 创建 declare
func: llvmlite.Function* = llvmlite.create_declare(
func: mlirlite.Function* = mlirlite.create_declare(
pool, mod, mangled_name, ret_ty)
if func is None:
return
@@ -3346,35 +3346,35 @@ def _inject_function_declare(pool: memhub.MemBuddy*,
if pname is None:
pname = "arg"
# 解析参数类型
param_ty: llvmlite.LLVMType* = i8_ptr_ty
param_ty: mlirlite.LLVMType* = i8_ptr_ty
# 优先用 vpi 文本注解缓存解析参数类型(与返回类型同源——vpi
# tree 深层节点 kind() 可能损坏,AST resolve 得垃圾类型如
# sizet→i32,跨模块 declare 参数宽错 → 调用侧 trunc 传参、
# callee 按宽类型读栈残留垃圾高位 → 参数巨值崩溃(SlotsBugTest
# 根因)。段索引 = pi(模块级函数无 self,0=首参)。
pseg_ty: llvmlite.LLVMType* = _resolve_vpi_param_annot_seg(
pseg_ty: mlirlite.LLVMType* = _resolve_vpi_param_annot_seg(
pool, src_sha1, None, fd.name, pi, i32_ty, i8_ptr_ty)
if pseg_ty is not None:
match pseg_ty:
case llvmlite.LLVMType.Struct(_, _, _):
case mlirlite.LLVMType.Struct(_, _, _):
# 裸结构体形参:C ABI 按值 / 内部 Ptr(struct)
# (判据与降级见 _AggregateParamTy,三处必须同步)
param_ty = _AggregateParamTy(mod, pool, pseg_ty, agg_is_c_abi)
case llvmlite.LLVMType.Array(aelem_ty, _):
param_ty = llvmlite.Ptr(pool, aelem_ty)
case mlirlite.LLVMType.Array(aelem_ty, _):
param_ty = mlirlite.Ptr(pool, aelem_ty)
case _:
param_ty = pseg_ty
elif ag.annotation is not None:
resolved_ty: llvmlite.LLVMType* = GenApi.resolve_annotation_type(
resolved_ty: mlirlite.LLVMType* = GenApi.resolve_annotation_type(
pool, ag.annotation, imported_modules, from_imports, trans)
if resolved_ty is not None:
# CArray 参数 → 元素指针 ty*(C 数组衰减,与编译侧一致)。
# 裸结构体参数 → _AggregateParamTy(同一判据)。
match resolved_ty:
case llvmlite.LLVMType.Struct(_, _, _):
case mlirlite.LLVMType.Struct(_, _, _):
param_ty = _AggregateParamTy(mod, pool, resolved_ty, agg_is_c_abi)
case llvmlite.LLVMType.Array(aelem_ty, _):
param_ty = llvmlite.Ptr(pool, aelem_ty)
case mlirlite.LLVMType.Array(aelem_ty, _):
param_ty = mlirlite.Ptr(pool, aelem_ty)
case _:
param_ty = resolved_ty
else:
@@ -3384,7 +3384,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*,
ag.annotation,
f"extern 声明 '{fd.name}' 形参 '{pname}' 类型注解解析失败",
"NameError")
llvmlite.add_param(pool, func, param_ty, pname)
mlirlite.add_param(pool, func, param_ty, pname)
# 文本缓存校验/修复:vpi tree args 可能被覆盖损坏(尾部默认参数丢失)
# → declare 参数数不足 → 调用点缺参 → 被调函数读栈垃圾。用 vpi 文本
# 缓存的参数注解补全 declare 参数(与 define 参数数一致)。
@@ -3434,15 +3434,15 @@ def _inject_function_declare(pool: memhub.MemBuddy*,
# 注入正确签名可避免调用时 _ensure_method_declare 用实参类型创建错误 declare(如 size: sizet 被写成 i32 而非 i64)。
# ============================================================
def _inject_method_declare(pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
m_fd: ast.FunctionDef*,
cls_name: str,
trans: HT.Translator*,
src_sha1: str,
imported_modules: str,
from_imports: str,
i32_ty: llvmlite.LLVMType*,
i8_ptr_ty: llvmlite.LLVMType*,
i32_ty: mlirlite.LLVMType*,
i8_ptr_ty: mlirlite.LLVMType*,
funcs_ptr: GenTypes.FuncEntry*,
max_funcs: int) -> None:
"""为 ClassDef 内方法创建 declare 声明并注入到模块"""
@@ -3476,7 +3476,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*,
viperlib.snprintf(mangled_name, mangled_len, "%s.%s", src_sha1, lookup_name)
# 去重:如果方法已存在则跳过
existing: llvmlite.Function* = GenApi.find_func_in_module(mod, mangled_name)
existing: mlirlite.Function* = GenApi.find_func_in_module(mod, mangled_name)
if existing is not None:
return
@@ -3484,7 +3484,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*,
# 优先用缓存的返回注解字符串(tree 解析后立即提取,节点未损坏),
# 用 _parse_type_string 重新解析成新 AST(立即使用不被覆盖)。
# 直接解析 m_fd.returns 可能因 vpi tree 深层节点被覆盖而得到垃圾类型。
ret_ty: llvmlite.LLVMType* = None
ret_ty: mlirlite.LLVMType* = None
ret_annot: str = _lookup_vpi_ret_annot(src_sha1, cls_name, m_fd.name)
if ret_annot is not None:
ret_ty = _resolve_vpi_ret_annot_str(pool, ret_annot, i32_ty, i8_ptr_ty)
@@ -3493,9 +3493,9 @@ def _inject_method_declare(pool: memhub.MemBuddy*,
pool, m_fd.returns, imported_modules, from_imports, trans)
# __new__ 无返回注解时推断为类指针(__new__ 返回 self 指针,默认 i32 会截断指针)
if ret_ty is None and string.strcmp(m_fd.name, "__new__") == 0:
cls_ty: llvmlite.LLVMType* = GenApi.get_struct_type(cls_name)
cls_ty: mlirlite.LLVMType* = GenApi.get_struct_type(cls_name)
if cls_ty is not None:
ret_ty = llvmlite.Ptr(pool, cls_ty)
ret_ty = mlirlite.Ptr(pool, cls_ty)
# [S4 fail-fast] 有返回注解却解析不出类型 → 不再静默退 i32;
# __new__ 无注解、普通方法无注解均走下方 i32 合法默认。
if ret_ty is None and m_fd.returns is not None:
@@ -3508,12 +3508,12 @@ def _inject_method_declare(pool: memhub.MemBuddy*,
# 退成下方 i32 默认,就会出现 declare i32 / define void 的返回类型分裂:
# 同模块内 llc 报 value doesn't match function result type,跨模块是静默 ABI 不一致。
if ret_ty is None and string.strcmp(m_fd.name, "__init__") == 0:
ret_ty = llvmlite.Void(pool)
ret_ty = mlirlite.Void(pool)
if ret_ty is None:
ret_ty = i32_ty
# 创建 declare
func: llvmlite.Function* = llvmlite.create_declare(
func: mlirlite.Function* = mlirlite.create_declare(
pool, mod, mangled_name, ret_ty)
if func is None:
return
@@ -3550,41 +3550,41 @@ def _inject_method_declare(pool: memhub.MemBuddy*,
# 块)。类类型未注册时兜底走下方注解解析/i8*(保持原行为)。
if pi == 0 and (string.strcmp(pname, "self") == 0
or string.strcmp(pname, "cls") == 0):
cls_ty_sd: llvmlite.LLVMType* = GenApi.get_struct_type(cls_name)
cls_ty_sd: mlirlite.LLVMType* = GenApi.get_struct_type(cls_name)
if cls_ty_sd is not None:
llvmlite.add_param(pool, func, llvmlite.Ptr(pool, cls_ty_sd), pname)
mlirlite.add_param(pool, func, mlirlite.Ptr(pool, cls_ty_sd), pname)
continue
param_ty: llvmlite.LLVMType* = i8_ptr_ty
param_ty: mlirlite.LLVMType* = i8_ptr_ty
# 优先用 vpi 文本注解缓存解析参数类型(与返回类型同源——vpi
# tree 深层节点 kind() 可能损坏,AST resolve 得垃圾类型如
# sizet→i32,declare 参数宽错 → 调用侧 trunc i64→i32 传参、
# callee 按 i64 读栈残留垃圾高位 → can=巨值读未写槽位崩溃,
# SlotsBugTest 根因)。段索引 = pi(0=self 空段)。
pseg_ty: llvmlite.LLVMType* = _resolve_vpi_param_annot_seg(
pseg_ty: mlirlite.LLVMType* = _resolve_vpi_param_annot_seg(
pool, src_sha1, cls_name, m_fd.name, pi, i32_ty, i8_ptr_ty)
if pseg_ty is not None:
match pseg_ty:
case llvmlite.LLVMType.Struct(_, _, _):
case mlirlite.LLVMType.Struct(_, _, _):
# 裸结构体形参:方法恒为 TPV 内部符号(mangled =
# {sha1}.{Class}.{method},无 C ABI 外部 define),
# 故 is_c_abi=0 → Ptr(struct),与定义侧
# ClassGenVTable L744-750 逐字一致(三处必须同步)。
param_ty = _AggregateParamTy(mod, pool, pseg_ty, 0)
case llvmlite.LLVMType.Array(aelem_ty, _):
param_ty = llvmlite.Ptr(pool, aelem_ty)
case mlirlite.LLVMType.Array(aelem_ty, _):
param_ty = mlirlite.Ptr(pool, aelem_ty)
case _:
param_ty = pseg_ty
elif ag.annotation is not None:
resolved_ty: llvmlite.LLVMType* = GenApi.resolve_annotation_type(
resolved_ty: mlirlite.LLVMType* = GenApi.resolve_annotation_type(
pool, ag.annotation, imported_modules, from_imports, trans)
if resolved_ty is not None:
# CArray 参数 → 元素指针 ty*(C 数组衰减,与编译侧一致)。
# 裸结构体参数 → _AggregateParamTy(同一判据,is_c_abi=0)。
match resolved_ty:
case llvmlite.LLVMType.Struct(_, _, _):
case mlirlite.LLVMType.Struct(_, _, _):
param_ty = _AggregateParamTy(mod, pool, resolved_ty, 0)
case llvmlite.LLVMType.Array(aelem_ty, _):
param_ty = llvmlite.Ptr(pool, aelem_ty)
case mlirlite.LLVMType.Array(aelem_ty, _):
param_ty = mlirlite.Ptr(pool, aelem_ty)
case _:
param_ty = resolved_ty
else:
@@ -3594,7 +3594,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*,
ag.annotation,
f"extern 方法 '{cls_name}.{m_fd.name}' 形参 '{pname}' 类型注解解析失败",
"NameError")
llvmlite.add_param(pool, func, param_ty, pname)
mlirlite.add_param(pool, func, param_ty, pname)
# 文本缓存校验/修复:vpi tree args 可能被覆盖损坏(尾部默认参数丢失)
# → declare 参数数不足 → 调用点缺参 → 被调函数读栈垃圾(跨模块 CDefine
@@ -3607,11 +3607,11 @@ def _inject_method_declare(pool: memhub.MemBuddy*,
# 与 _translate_method 的 define 签名一致(对齐 TPC HandlesFunctions.py
# L703-705)。for x in obj 循环会以 2 个实参调用 __next__(self, flag)。
if m_fd.name is not None and string.strcmp(m_fd.name, "__next__") == 0:
i1_ty_si: llvmlite.LLVMType* = llvmlite.Int1(pool)
i1_ty_si: mlirlite.LLVMType* = mlirlite.Int1(pool)
if i1_ty_si is not None:
i1_ptr_ty_si: llvmlite.LLVMType* = llvmlite.Ptr(pool, i1_ty_si)
i1_ptr_ty_si: mlirlite.LLVMType* = mlirlite.Ptr(pool, i1_ty_si)
if i1_ptr_ty_si is not None:
llvmlite.add_param(pool, func, i1_ptr_ty_si, "__stop_iter_flag__")
mlirlite.add_param(pool, func, i1_ptr_ty_si, "__stop_iter_flag__")
# 默认参数:vpi 签名含 '= <default>'(Converter 已输出),提取 defaults
# 列表注册默认参数表——跨模块缺参调用(如 resolve_annotation_type 的
# depth=0)才能按表填充,否则被调函数读到栈垃圾(假报递归过深/崩溃)。
@@ -3686,7 +3686,7 @@ def _register_ctypedef_from_annassign(pool: memhub.MemBuddy*,
# (静默读错字段)。
#
# 布局真源 = .stub.ll(批处理落盘点:Phase1Main.vp:1078 / Phase2/__init__.vp:1050
# 用 tr.dump_ir(..., llvmlite.OUTPUT_STUB)):
# 用 tr.dump_ir(..., mlirlite.OUTPUT_STUB)):
# - `%"<sha1>.<Class>" = type { ... }` 是**展平后**的完整布局(ClassGenDef 的
# 字段展平:__vtable__ 首字段 + 父类字段 + 本类字段);
# - `@...<sha1>.<Class>.vtable` 全局的类型槽数 = 该类的虚方法数
@@ -4110,7 +4110,7 @@ def _repl_stub_warn_parent(e: rawptr[ReplStubClass], detail: str, pname: str) ->
"被拒绝(方法调用不受影响)\n", e.Sha1, e.ClassName, detail, pname)
def _repl_stub_try(e: rawptr[ReplStubClass], mod: llvmlite.LLVMModule*) -> int:
def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int:
"""按存根校验并登记完整布局:1=已登记 / 0=父类未就绪(推迟)/ -1=拒绝"""
global ReplStubOk, ReplStubVtOk, ReplStubWarnLeft
if e is None:
@@ -4244,35 +4244,35 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: llvmlite.LLVMModule*) -> int:
e.Sha1, e.ClassName, vn, e.VtArity)
# ⑥ 建 LLVM 结构体(命名 "%<sha1>.<类名>",与定义侧同口径)
total: int = cn + hv
i8_ptr: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
i8_ptr: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
if i8_ptr is None:
return 0
first_node: rawptr[llvmlite.ParamNode] = None
prev_node: rawptr[llvmlite.ParamNode] = None
first_node: rawptr[mlirlite.ParamNode] = None
prev_node: rawptr[mlirlite.ParamNode] = None
if hv == 1:
nd0: rawptr[llvmlite.ParamNode] = pool.alloc(llvmlite.ParamNode.__sizeof__())
nd0: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__())
if nd0 is None:
return 0
string.memset(nd0, 0, llvmlite.ParamNode.__sizeof__())
string.memset(nd0, 0, mlirlite.ParamNode.__sizeof__())
nd0.Ty = i8_ptr
first_node = nd0
prev_node = nd0
fi2: int
for fi2 in range(cn):
fty: llvmlite.LLVMType* = (llvmlite.LLVMType*)(e.Types[fi2])
fty: mlirlite.LLVMType* = (mlirlite.LLVMType*)(e.Types[fi2])
if fty is None:
continue
nd: rawptr[llvmlite.ParamNode] = pool.alloc(llvmlite.ParamNode.__sizeof__())
nd: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__())
if nd is None:
continue
string.memset(nd, 0, llvmlite.ParamNode.__sizeof__())
string.memset(nd, 0, mlirlite.ParamNode.__sizeof__())
nd.Ty = fty
if first_node is None:
first_node = nd
if prev_node is not None:
prev_node.Next = nd
prev_node = nd
struct_ty: llvmlite.LLVMType* = llvmlite.Struct(pool, first_node, total, e.Key)
struct_ty: mlirlite.LLVMType* = mlirlite.Struct(pool, first_node, total, e.Key)
if struct_ty is None:
return 0
# ⑦ 登记(StdlibAlloc=1 期间的注册走 PermPool,跨片段存活)
@@ -4282,18 +4282,18 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: llvmlite.LLVMModule*) -> int:
e.State = _REPL_SS_REFUSED
return -1
if mod is not None:
llvmlite.module_add_named_type(mod, pool, struct_ty)
mlirlite.module_add_named_type(mod, pool, struct_ty)
if (e.Flags & _REPL_SF_PACKED) != 0:
entry.IsPacked = 1
if mod is not None:
llvmlite.module_set_named_type_packed(mod, pool, struct_ty, 1)
mlirlite.module_set_named_type_packed(mod, pool, struct_ty, 1)
if hv == 1:
entry.HasVTable = 1
GenApi.add_field(pool, entry, "__vtable__", i8_ptr)
fi3: int
for fi3 in range(cn):
fname: str = rawptr(e.Names[fi3])
fty3: llvmlite.LLVMType* = (llvmlite.LLVMType*)(e.Types[fi3])
fty3: mlirlite.LLVMType* = (mlirlite.LLVMType*)(e.Types[fi3])
if fname is None or fty3 is None:
continue
GenApi.add_field(pool, entry, fname, fty3)
@@ -4327,7 +4327,7 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: llvmlite.LLVMModule*) -> int:
def _repl_stub_add_class(pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
cd: ast.ClassDef*,
sha1: str,
txt: str,
@@ -4425,7 +4425,7 @@ def _repl_stub_add_class(pool: memhub.MemBuddy*,
tg: ast.Name* = ast.Name*(aa2.target)
if tg.id is None or tg.id[0] == '\0':
continue
fty2: llvmlite.LLVMType* = GenApi.resolve_annotation_type(
fty2: mlirlite.LLVMType* = GenApi.resolve_annotation_type(
pool, aa2.annotation, imported_modules, from_imports, trans, 0)
if fty2 is None:
own_fail = 1
@@ -4501,7 +4501,7 @@ def _repl_stub_add_class(pool: memhub.MemBuddy*,
def _repl_stub_collect_module(pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
ch: list[ast.AST*]*,
n: sizet,
trans: HT.Translator*,
+2 -2
View File
@@ -4,7 +4,7 @@ from stdint import *
import memhub
import string
import stdlib
import llvmlite
import mlirlite
import w32.win32file as win32file
import w32.win32base as win32base
import w32.fileio as fileio
@@ -614,7 +614,7 @@ def LoadFullIR(temp_dir: str, sha1: str,
# Returns: 成功加载的 .vpi 文件数
# ============================================================
def LoadDepVpiIntoModule(pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
imported_modules: str,
from_imports: str,
temp_dir: str,
+1 -1
View File
@@ -3,7 +3,7 @@ from stdint import *
import memhub
import string
import stdlib
import llvmlite
import mlirlite
import w32.win32file as win32file
import w32.win32base as win32base
import w32.fileio as fileio
+11 -16
View File
@@ -4,7 +4,7 @@ from stdint import *
import memhub
import string
import stdlib
import llvmlite
import mlirlite
import w32.win32file as win32file
import w32.win32base as win32base
import w32.fileio as fileio
@@ -47,7 +47,7 @@ import lib.Stub.StubMerger as StubMerger
# Args: mod 已翻译完成的 LLVM 模块;temp_dir 基础目录;td_len temp_dir 长度;sha1 模块 SHA1
# Returns: 0=成功(失败经 VLogger.error 终止进程)
# ============================================================
def WriteModuleMeta(mod: llvmlite.LLVMModule*, temp_dir: str,
def WriteModuleMeta(mod: mlirlite.LLVMModule*, temp_dir: str,
td_len: sizet, sha1: str) -> int:
"""把本模块的函数定义/结构体布局/虚表清单写入 {sha1}.meta"""
if mod is None or temp_dir is None or sha1 is None:
@@ -61,14 +61,14 @@ def WriteModuleMeta(mod: llvmlite.LLVMModule*, temp_dir: str,
if mf.closed:
VLogger.error(f"meta 写出:无法打开 {mpath}", "Meta")
return 1
cur: llvmlite.Function* = mod.FuncHead
cur: mlirlite.Function* = mod.FuncHead
steps: sizet = 0
while cur is not None:
steps += 1
if steps > 100000:
VLogger.error("meta 写出:函数链表成环/超限", "Meta")
break
nm: str = llvmlite.function_get_name(cur)
nm: str = mlirlite.function_get_name(cur)
if nm is not None:
nlen: sizet = string.strlen(nm)
line: bytes = stdlib.malloc(nlen + 16)
@@ -76,28 +76,28 @@ def WriteModuleMeta(mod: llvmlite.LLVMModule*, temp_dir: str,
VLogger.error("meta 写出:行缓冲分配失败", "Meta")
break
mark: str = "DECL"
if llvmlite.function_is_declared(cur) == 0:
if mlirlite.function_is_declared(cur) == 0:
mark = "DEF"
viperlib.snprintf(line, nlen + 16, "FUNC %s %s\n", nm, mark)
mf.write(line, string.strlen(line))
stdlib.free(line)
cur = llvmlite.function_get_next(cur)
cur = mlirlite.function_get_next(cur)
# 2) 结构体布局:STRUCT <name> FIELDS <n> PACKED <0|1>(opaque → STRUCT <name> OPAQUE)
nt: llvmlite.NamedTypeNode* = mod.NamedTypeHead
nt: mlirlite.NamedTypeNode* = mod.NamedTypeHead
nt_steps: sizet = 0
while nt is not None:
nt_steps += 1
if nt_steps > 100000:
VLogger.error("meta 写出:命名类型链表成环/超限", "Meta")
break
tn: str = llvmlite.get_struct_name(nt.Ty)
tn: str = mlirlite.get_struct_name(nt.Ty)
if tn is not None and tn[0] != '\0':
tl: sizet = string.strlen(tn)
lb: bytes = stdlib.malloc(tl + 48)
if lb is None:
VLogger.error("meta 写出:行缓冲分配失败", "Meta")
break
fc: int = llvmlite.get_struct_fcount(nt.Ty)
fc: int = mlirlite.get_struct_fcount(nt.Ty)
if fc < 0:
viperlib.snprintf(lb, tl + 48, "STRUCT %s OPAQUE\n", tn)
else:
@@ -106,7 +106,7 @@ def WriteModuleMeta(mod: llvmlite.LLVMModule*, temp_dir: str,
stdlib.free(lb)
nt = nt.Next
# 3) 虚表槽数:VTABLE <class> SLOTS <n>(全局名 <class>.vtable,Ty 匿名结构体 fcount=槽数)
gv: llvmlite.GlobalVariable* = mod.GlobalHead
gv: mlirlite.GlobalVariable* = mod.GlobalHead
gv_steps: sizet = 0
while gv is not None:
gv_steps += 1
@@ -122,7 +122,7 @@ def WriteModuleMeta(mod: llvmlite.LLVMModule*, temp_dir: str,
if base is not None:
string.strncpy(base, gn, base_len)
base[base_len] = '\0'
ar: int = llvmlite.get_struct_fcount(gv.Ty)
ar: int = mlirlite.get_struct_fcount(gv.Ty)
if ar < 0:
ar = 0
lb2: bytes = stdlib.malloc(base_len + 40)
@@ -274,11 +274,6 @@ def _FindSha1ByModName(sha1_arr: str, mod_arr: str,
return None
if count <= 0:
return None
# MLIR 后端:依赖名 "llvmlite" 重定向到 "mlirlite"
#(与 IncludesScanner.ResolveModuleToPath 同口径;LLVM 后端恒等)
mod_name = Config.alias_module_name(mod_name)
if mod_name is None:
return None
# 第一遍:精确匹配
for i in range(count):
idx: sizet = sizet(i) * 64
+1 -1
View File
@@ -3,7 +3,7 @@ from stdint import *
import memhub
import string
import stdlib
import llvmlite
import mlirlite
import w32.win32file as win32file
import w32.win32base as win32base
import w32.fileio as fileio
+1 -1
View File
@@ -3,7 +3,7 @@ from stdint import *
import memhub
import string
import stdlib
import llvmlite
import mlirlite
import w32.win32file as win32file
import w32.win32base as win32base
import w32.fileio as fileio
+1 -1
View File
@@ -3,7 +3,7 @@ from stdint import *
import memhub
import string
import stdlib
import llvmlite
import mlirlite
import w32.win32file as win32file
import w32.win32base as win32base
import w32.fileio as fileio
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+5 -5
View File
@@ -3,7 +3,7 @@ import lib.core.Gen.Generator as Generator
import t, c
from stdint import *
import memhub
import llvmlite
import mlirlite
# ============================================================
@@ -15,8 +15,8 @@ novirtual class BaseGenMixin:
# 内存/IR 状态
Gen: Generator.Generator*
Pool: memhub.MemBuddy* # 内存池
Module: llvmlite.LLVMModule* # 当前 LLVM 模块
Builder: llvmlite.IRBuilder* # 当前 IRBuilder
Module: mlirlite.LLVMModule* # 当前 LLVM 模块
Builder: mlirlite.IRBuilder* # 当前 IRBuilder
# 符号表/函数表
SymTab: rawptr[GenTypes.SymbolTable]
Funcs: GenTypes.FuncEntry*
@@ -26,8 +26,8 @@ novirtual class BaseGenMixin:
FromImports: str
ModuleSha1: str
# 当前翻译上下文
CurFunc: llvmlite.Function*
CurBuilder: llvmlite.IRBuilder*
CurFunc: mlirlite.Function*
CurBuilder: mlirlite.IRBuilder*
CurClassName: str
def InitBaseGen(self, pool: memhub.MemBuddy*) -> int:
+83 -83
View File
@@ -5,7 +5,7 @@ import lib.core.Gen.Translator as HT
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import hashtable
import string
@@ -117,7 +117,7 @@ novirtual class CallGenBase:
return StubMergerStore.LookupSha1ByModName(mod_name)
def _lookup_module_sha1_suffix(self, mod_suffix: str) -> str:
"""后缀匹配查找模块 SHA1,如 mod_suffix="__types" 匹配 "llvmlite.__types"
"""后缀匹配查找模块 SHA1,如 mod_suffix="__types" 匹配 "mlirlite.__types"
用于 from .X import Y 的相对导入:impf.module 是 ".X"(带前导点),
去掉前导点后为 "X",SHA1 映射表中键是 "pkg.X",需要后缀匹配。
委托给 StubMerger.LookupSha1ByModNameSuffix(精确 + 后缀 + 反向后缀)。
@@ -154,11 +154,11 @@ novirtual class CallGenBase:
def _lookup_reexport_from_vpi(self, pool: memhub.MemBuddy*, mod_sha1: str, func_name: str) -> str:
"""re-export 表未命中时,从模块 .vpi 按需解析 from-import 定位定义模块
includes 模块(如 llvmlite/__init__)的 stub/text 已存在时不会被按需
includes 模块(如 mlirlite/__init__)的 stub/text 已存在时不会被按需
全量翻译(Phase2 3.5 仅在 stub/text 缺失时翻译),而 re-export 表只在
declare_only=0 的全量翻译中注册(HandleImportFromNames),因此表可能为空。
本函数解析该模块 .vpi 的 "from .X import ... func_name ..." 语句,
返回定义模块名(如 llvmlite/__init__ 的 .__builder → "llvmlite.__builder")。
返回定义模块名(如 mlirlite/__init__ 的 .__builder → "mlirlite.__builder")。
"""
if pool is None or mod_sha1 is None or func_name is None: return None
# star import 候选模块累积(空格分隔):from X import * 无法确定归属,收集全部候选由调用方逐个验证
@@ -517,10 +517,10 @@ novirtual class CallGenBase:
def _FuncTyFromFunction(self, pool: memhub.MemBuddy*,
f_ref: llvmlite.Function*) -> llvmlite.LLVMType*:
"""由 llvmlite.Function 的形参链表(Param 链)构造 LLVMType.Func 类型。
f_ref: mlirlite.Function*) -> mlirlite.LLVMType*:
"""由 mlirlite.Function 的形参链表(Param 链)构造 LLVMType.Func 类型。
为什么不能直接把 Param 链交给 llvmlite.Func:`Function.Params` 是 **Param** 链
为什么不能直接把 Param 链交给 mlirlite.Func:`Function.Params` 是 **Param** 链
(__function.vp,`Param.Ty: rawptr[LLVMType]`),而 `LLVMType.Func` 的类型构造链表是
**ParamNode** 链(__types.vp,由 new_param_node 建、paramnode_set_next 串)。两者是
互不相关的 class —— 严格指针规则下不可互传(旧的无条件 bitcast 掩盖了这点,且两者
@@ -528,29 +528,29 @@ novirtual class CallGenBase:
这里逐个 new_param_node 重建 ParamNode 链再交给 Func:语义等价(两侧都只取各参数的
类型),类型也对得上 Func(params: rawptr[ParamNode]) 的形参。
"""
pn_head: llvmlite.ParamNode* = None
pn_prev: llvmlite.ParamNode* = None
pn_head: mlirlite.ParamNode* = None
pn_prev: mlirlite.ParamNode* = None
p_cnt: sizet = 0
p_cur: llvmlite.Param* = llvmlite.function_get_param_head(f_ref)
p_cur: mlirlite.Param* = mlirlite.function_get_param_head(f_ref)
while p_cur is not None:
p_ty: llvmlite.LLVMType* = llvmlite.param_get_ty(p_cur)
p_ty: mlirlite.LLVMType* = mlirlite.param_get_ty(p_cur)
if p_ty is None:
return None
pn: llvmlite.ParamNode* = llvmlite.new_param_node(pool, p_ty)
pn: mlirlite.ParamNode* = mlirlite.new_param_node(pool, p_ty)
if pn is None:
return None
if pn_head is None:
pn_head = pn
if pn_prev is not None:
llvmlite.paramnode_set_next(pn_prev, pn)
mlirlite.paramnode_set_next(pn_prev, pn)
pn_prev = pn
p_cnt += 1
p_cur = llvmlite.param_get_next(p_cur)
return llvmlite.Func(pool, f_ref.RetTy, pn_head, p_cnt)
p_cur = mlirlite.param_get_next(p_cur)
return mlirlite.Func(pool, f_ref.RetTy, pn_head, p_cnt)
def find_func_in_module(self, mod: llvmlite.LLVMModule*,
def find_func_in_module(self, mod: mlirlite.LLVMModule*,
name: str,
owner_sha1: str = None) -> llvmlite.Function*:
owner_sha1: str = None) -> mlirlite.Function*:
"""在模块的函数链表中按名称查找函数
查找策略:
@@ -564,7 +564,7 @@ novirtual class CallGenBase:
pass2 的 IsDeclared==0 判定会跳过它,pass3 又会按链表顺序误绑排在
FuncHead 前面的跨模块 stub declare(lexer.vp _advance 根因)。
使用 llvmlite.function_get_name/next 访问器绕过 stub 类型限制
使用 mlirlite.function_get_name/next 访问器绕过 stub 类型限制
(stub 类型字段不足且字段类型可能错误,直接字段访问会被静默跳过)。
"""
if mod is None or name is None:
@@ -575,18 +575,18 @@ novirtual class CallGenBase:
# 该链表平均数百节点且本函数每次调用都全链遍历,PROF 中本函数及其访问器约占 10%)。
# 优先级与逐趟结果完全一致:精确匹配命中即返回 > 本模块同名 > declare 后缀 > 任意后缀;
# 同类候选均取链表首个命中。
cur: llvmlite.Function* = mod.FuncHead
mangle_hit: llvmlite.Function* = None
declare_hit: llvmlite.Function* = None
any_hit: llvmlite.Function* = None
cur: mlirlite.Function* = mod.FuncHead
mangle_hit: mlirlite.Function* = None
declare_hit: mlirlite.Function* = None
any_hit: mlirlite.Function* = None
while cur is not None:
cur_name: str = llvmlite.function_get_name(cur)
cur_name: str = mlirlite.function_get_name(cur)
if cur_name is not None:
# 快速路径:strcmp 判等蕴含首字符相等,首字符不同者跳过 strcmp(mangled 名以 sha1 十六进制打头,裸名多为字母/下划线)
if cur_name[0] == name[0] and string.strcmp(cur_name, name) == 0:
return cur
# 名字长度取 Function.NameLen(创建时一次算好),免去对热链每个节点重复 strlen
cur_len: sizet = llvmlite.function_get_name_len(cur)
cur_len: sizet = mlirlite.function_get_name_len(cur)
# 本模块同名候选:仅接受恰为 "{owner_sha1}.{name}" 的形态(不匹配 "{sha1}.Class.method");declare 与 define 同名同符号,是否 IsDeclared==0 均可返回
if owner_sha1 is not None and mangle_hit is None and cur_len == 17 + name_len:
if string.strncmp(cur_name, owner_sha1, 16) == 0 and cur_name[16] == '.':
@@ -615,7 +615,7 @@ novirtual class CallGenBase:
# 首个 IsDeclared==0 命中(原第二遍优先)
if cur.IsDeclared == 0 and declare_hit is None:
declare_hit = cur
cur = llvmlite.function_get_next(cur)
cur = mlirlite.function_get_next(cur)
if mangle_hit is not None:
return mangle_hit
if declare_hit is not None:
@@ -625,10 +625,10 @@ novirtual class CallGenBase:
# _ensure_method_declare:found_func 为 None(stub 未注入或跨模块调用)时在当前模块创建 declare,避免 llc 报 undefined value
def _ensure_method_declare(self, pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
call_name: str,
ret_ty: llvmlite.LLVMType*,
param_head: llvmlite.Value*,
ret_ty: mlirlite.LLVMType*,
param_head: mlirlite.Value*,
param_count: int):
"""为跨模块方法调用创建 declare 声明
@@ -643,7 +643,7 @@ novirtual class CallGenBase:
# 无上限遍历会死循环(builtins.vp dump 卡死根因排查),超限即报错终止。
DECLARE_CHAIN_LIMIT: int = 100000
# 检查模块中是否已有同名函数(declare 或 define)
existing: llvmlite.Function* = mod.FuncHead
existing: mlirlite.Function* = mod.FuncHead
existing_steps: int = 0
while existing is not None:
existing_steps += 1
@@ -663,7 +663,7 @@ novirtual class CallGenBase:
return
# 遍历现有参数链表计数(避免依赖 GSList.Count 字段的类型推断)
cur_count: int = 0
cur_p: llvmlite.Param* = llvmlite.function_get_param_head(existing)
cur_p: mlirlite.Param* = mlirlite.function_get_param_head(existing)
while cur_p is not None:
cur_count += 1
if cur_count > DECLARE_CHAIN_LIMIT:
@@ -674,7 +674,7 @@ novirtual class CallGenBase:
# 只追加缺失的参数(cur_count < param_count 时)
if cur_count < param_count:
# 定位到 param_head 的第 cur_count 个节点开始追加
pnode2: llvmlite.Value* = param_head
pnode2: mlirlite.Value* = param_head
pi2: int = 0
# 跳过已有的 cur_count 个参数
while pnode2 is not None and pi2 < cur_count:
@@ -683,19 +683,19 @@ novirtual class CallGenBase:
# 追加剩余参数
while pnode2 is not None and pi2 < param_count:
if pnode2.Ty is not None:
param2: llvmlite.Param* = llvmlite.new_param(pool, pnode2.Ty, None)
param2: mlirlite.Param* = mlirlite.new_param(pool, pnode2.Ty, None)
if param2 is not None:
llvmlite.function_add_param(existing, param2)
mlirlite.function_add_param(existing, param2)
pnode2 = pnode2.Next
pi2 += 1
return
existing = existing.Next
# 裸名 C 库函数(如 string.memset → @memset):call_name 无 sha1 前缀,无法提取定义侧模块查 vpi 参数注解,故按标准签名建 declare(与 CallGenLib._ensure_c_lib_declare 白名单一致)
if call_name is not None and string.strchr(call_name, 46) is None:
std_lib_fn: llvmlite.Function* = self.Gen.CallGenLib._ensure_c_lib_declare(pool, mod, call_name)
std_lib_fn: mlirlite.Function* = self.Gen.CallGenLib._ensure_c_lib_declare(pool, mod, call_name)
if std_lib_fn is not None: return
# 创建函数声明
func: llvmlite.Function* = llvmlite.new_function(pool, call_name, ret_ty)
func: mlirlite.Function* = mlirlite.new_function(pool, call_name, ret_ty)
if func is None: return
func.IsDeclared = 1
# 定义侧参数类型优先:从 call_name 提取 {sha1}.{cls}.{method} 查 vpi 参数注解取定义侧类型。
@@ -734,44 +734,44 @@ novirtual class CallGenBase:
prm_annots_d: str = None
if sha1_d is not None and meth_d is not None:
prm_annots_d = self._vpi_method_param_annot(pool, sha1_d, cls_d, meth_d)
i32_ty_d: llvmlite.LLVMType* = llvmlite.Int32(pool)
i8_ptr_d: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
i32_ty_d: mlirlite.LLVMType* = mlirlite.Int32(pool)
i8_ptr_d: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
# 添加参数(declare 中参数名无意义,设为 None 只输出类型)
pnode: llvmlite.Value* = param_head
pnode: mlirlite.Value* = param_head
pi: int = 0
while pnode is not None and pi < param_count:
param_ty_d: llvmlite.LLVMType* = pnode.Ty
param_ty_d: mlirlite.LLVMType* = pnode.Ty
if prm_annots_d is not None and prm_annots_d[0] != '\0' and pnode.Ty is not None:
seg_ty_d: llvmlite.LLVMType* = VpiReader._resolve_vpi_param_annot_seg(pool, sha1_d, cls_d, meth_d, pi, i32_ty_d, i8_ptr_d)
seg_ty_d: mlirlite.LLVMType* = VpiReader._resolve_vpi_param_annot_seg(pool, sha1_d, cls_d, meth_d, pi, i32_ty_d, i8_ptr_d)
if seg_ty_d is not None:
match pnode.Ty:
case llvmlite.LLVMType.Int(bits_a):
case mlirlite.LLVMType.Int(bits_a):
match seg_ty_d:
case llvmlite.LLVMType.Int(bits_b):
case mlirlite.LLVMType.Int(bits_b):
if bits_b > bits_a:
param_ty_d = seg_ty_d
case _:
pass
case llvmlite.LLVMType.Ptr(_):
case mlirlite.LLVMType.Ptr(_):
# 指针形参:定义侧为准(见上方注释)。定义侧解析不出指针时保留实参类型
match seg_ty_d:
case llvmlite.LLVMType.Ptr(_):
case mlirlite.LLVMType.Ptr(_):
param_ty_d = seg_ty_d
case _:
pass
case _:
pass
if param_ty_d is not None:
param: llvmlite.Param* = llvmlite.new_param(pool, param_ty_d, None)
param: mlirlite.Param* = mlirlite.new_param(pool, param_ty_d, None)
if param is not None:
llvmlite.function_add_param(func, param)
mlirlite.function_add_param(func, param)
pnode = pnode.Next
pi += 1
if sha1_d is not None:
stdlib.free(sha1_d)
if cls_d is not None:
stdlib.free(cls_d)
llvmlite.module_add_function(mod, func)
mlirlite.module_add_function(mod, func)
# _lookup_method_ret_ty_via_vpi:按 模块SHA1 + 类名 + 方法名 查 vpi 返回注解缓存并解析为 LLVMType,未命中返回 None(不硬编码白名单,类型始终来自定义处)
@@ -779,13 +779,13 @@ novirtual class CallGenBase:
def _lookup_method_ret_ty_via_vpi(self, pool: memhub.MemBuddy*,
cls_sha1: str,
cls_name: str,
method_name: str) -> llvmlite.LLVMType*:
method_name: str) -> mlirlite.LLVMType*:
"""从 vpi stub 返回注解缓存获取方法返回类型,未命中返回 None"""
if pool is None or cls_sha1 is None or method_name is None:
return None
# 函数内懒 import:VpiReader imports HandlesExprCall,顶层 import 会成环
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
# 按需加载:缓存未命中时直接读 {temp_dir}/{sha1[0:2]}/{sha1}.vpi
# 覆盖"模块自身翻译时 stub 尚未注入"(同模块方法调用,定义在后)的场景
if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0:
@@ -810,12 +810,12 @@ novirtual class CallGenBase:
# _vpi_resolve_param_annot_ty:解析 vpi 参数注解段为 LLVMType,失败返回 None(调用方以 i8* 兜底)
def _vpi_resolve_param_annot_ty(self, pool: memhub.MemBuddy*,
seg: str) -> llvmlite.LLVMType*:
seg: str) -> mlirlite.LLVMType*:
"""解析单个 vpi 参数注解段为 LLVMType,失败返回 None"""
if pool is None or seg is None:
return None
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
return VpiReader._resolve_vpi_ret_annot_str(pool, seg, i32_ty, i8_ptr_ty)
# _special_method_ret_ty:编译器内置特殊方法的固定返回类型——__before_init__/__init__ → void,__new__ → Ptr(StructTy),非特殊返回 None(vpi 无条目,固定即可避免 fail-fast 误报)
@@ -823,17 +823,17 @@ novirtual class CallGenBase:
# ============================================================
def _special_method_ret_ty(self, pool: memhub.MemBuddy*,
class_name: str,
method_name: str) -> llvmlite.LLVMType*:
method_name: str) -> mlirlite.LLVMType*:
"""编译器内置特殊方法的固定返回类型;非特殊返回 None"""
if pool is None or method_name is None:
return None
if string.strcmp(method_name, "__before_init__") == 0 or string.strcmp(method_name, "__init__") == 0:
return llvmlite.Void(pool)
return mlirlite.Void(pool)
if string.strcmp(method_name, "__new__") == 0:
if class_name is not None:
sp_struct_ty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(class_name)
sp_struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(class_name)
if sp_struct_ty is not None:
return llvmlite.Ptr(pool, sp_struct_ty)
return mlirlite.Ptr(pool, sp_struct_ty)
return None
return None
@@ -841,7 +841,7 @@ novirtual class CallGenBase:
# ============================================================
def _fail_method_ret_ty(self, method_name: str,
node: ast.AST* = None) -> llvmlite.LLVMType*:
node: ast.AST* = None) -> mlirlite.LLVMType*:
"""方法返回类型无法精确获取时 fail-fast(ERROR + 错误堆栈)
返回类型来源(按序):当前模块函数 → text.ll define → vpi stub 返回注解缓存。
@@ -869,8 +869,8 @@ novirtual class CallGenBase:
def _ParseLLVMRetTyStr(self, pool: memhub.MemBuddy*,
buf: bytes,
start: sizet,
end: sizet) -> llvmlite.LLVMType*:
"""将 LLVM IR 返回类型字符串转换为 llvmlite.LLVMType"""
end: sizet) -> mlirlite.LLVMType*:
"""将 LLVM IR 返回类型字符串转换为 mlirlite.LLVMType"""
if pool is None or buf is None or start >= end:
return None
@@ -896,12 +896,12 @@ novirtual class CallGenBase:
# struct 字面量 {T1, T2, ...}(tuple 打包返回类型)必须在 * 检查之前,否则内含 * 会被误判为 i8*(破坏 tuple 解包)
if s < e and buf[s] == '{':
# 字段链表节点必须是 llvmlite.ParamNode(new_param_node 返回 rawptr[ParamNode],
# 字段链表节点必须是 mlirlite.ParamNode(new_param_node 返回 rawptr[ParamNode],
# paramnode_set_next / Struct 的形参也都是 rawptr[ParamNode])。原先误注解为
# Function*(与 ParamNode 是不相关类),严格指针规则下这两处的实参传递会被判
# 「struct↔struct 隐式转换已禁止」;改注解即根治,不需要也不应该加强转。
th_st: llvmlite.ParamNode* = None
tt_st: llvmlite.ParamNode* = None
th_st: mlirlite.ParamNode* = None
tt_st: mlirlite.ParamNode* = None
tc_st: int = 0
ps_st: sizet = s + 1
while ps_st < e and buf[ps_st] != '}':
@@ -914,23 +914,23 @@ novirtual class CallGenBase:
ps_st += 1
ee_st: sizet = ps_st
if ee_st > es_st:
et_st: llvmlite.LLVMType* = self._ParseLLVMRetTyStr(pool, buf, es_st, ee_st)
et_st: mlirlite.LLVMType* = self._ParseLLVMRetTyStr(pool, buf, es_st, ee_st)
if et_st is None: return None
en_st: llvmlite.ParamNode* = llvmlite.new_param_node(pool, et_st)
en_st: mlirlite.ParamNode* = mlirlite.new_param_node(pool, et_st)
if en_st is None: return None
if th_st is None:
th_st = en_st
else:
llvmlite.paramnode_set_next(tt_st, en_st)
mlirlite.paramnode_set_next(tt_st, en_st)
tt_st = en_st
tc_st += 1
if th_st is None or tc_st == 0:
return None
st_ty_st: llvmlite.LLVMType* = llvmlite.Struct(pool, th_st, tc_st, None)
st_ty_st: mlirlite.LLVMType* = mlirlite.Struct(pool, th_st, tc_st, None)
# 指针到 struct({i32, i8}*):返回 Ptr(Struct);纯 tuple 打包
# ({i8*, i16})无尾部 *,返回 Struct 本身。
if ps_st < e and buf[ps_st] == '*':
return llvmlite.Ptr(pool, st_ty_st)
return mlirlite.Ptr(pool, st_ty_st)
return st_ty_st
# 命名类型(%"name" / %name)带指针:先解析到真实结构体/枚举类型再包 Ptr。
@@ -963,15 +963,15 @@ novirtual class CallGenBase:
if nm_buf is not None:
string.strncpy(nm_buf, buf + nm_s, nm_len)
nm_buf[nm_len] = '\0'
nm_ty: llvmlite.LLVMType* = GenApi.get_struct_type(nm_buf)
nm_ty: mlirlite.LLVMType* = GenApi.get_struct_type(nm_buf)
if nm_ty is None:
nm_ty = GenApi.get_enum_base_type(nm_buf)
stdlib.free(nm_buf)
if nm_ty is not None:
nm_wrap: llvmlite.LLVMType* = nm_ty
nm_wrap: mlirlite.LLVMType* = nm_ty
nm_i: int = 0
while nm_i < nm_star:
nm_wrap = llvmlite.Ptr(pool, nm_wrap)
nm_wrap = mlirlite.Ptr(pool, nm_wrap)
nm_i += 1
return nm_wrap
@@ -980,20 +980,20 @@ novirtual class CallGenBase:
ci: sizet = s
while ci < e:
if buf[ci] == '*':
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
ci += 1
# void
if ty_len == 4 and string.strncmp(buf + s, "void", 4) == 0:
return llvmlite.Void(pool)
return mlirlite.Void(pool)
# double
if ty_len == 6 and string.strncmp(buf + s, "double", 6) == 0:
return llvmlite.Double(pool)
return mlirlite.Double(pool)
# float
if ty_len == 5 and string.strncmp(buf + s, "float", 5) == 0:
return llvmlite.Float(pool)
return mlirlite.Float(pool)
# iN (i8, i16, i32, i64)
if ty_len >= 2 and buf[s] == 'i':
@@ -1010,13 +1010,13 @@ novirtual class CallGenBase:
di += 1
if valid != 0 and bits > 0:
if bits == 8:
return llvmlite.Int8(pool)
return mlirlite.Int8(pool)
if bits == 16:
return llvmlite.Int16(pool)
return mlirlite.Int16(pool)
if bits == 32:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
if bits == 64:
return llvmlite.Int64(pool)
return mlirlite.Int64(pool)
# 无法解析
return None
@@ -1056,7 +1056,7 @@ novirtual class CallGenBase:
# _CacheModuleRetTyTexts:单趟扫描某模块 text.ll——把全部 define 行的返回类型写入持久缓存(键/值深拷贝进 PermPool,同名只记首次,只登记 "{sha1}." 开头的本模块 mangled 名),并在同一趟里返回首个匹配 search_buf 的 define 的返回类型(未匹配返回 None);仅在成功读到 text.ll 后调用,负结果绝不缓存
def _CacheModuleRetTyTexts(self, class_sha1: str, text_buf: bytes,
text_len: sizet, pool: memhub.MemBuddy*,
search_buf: str, search_str_len: sizet) -> llvmlite.LLVMType*:
search_buf: str, search_str_len: sizet) -> mlirlite.LLVMType*:
"""单趟「登记 + 查找」text.ll 全部 define 行(建表/分配失败时只查找不登记)"""
if text_buf is None or text_len == 0:
return None
@@ -1078,7 +1078,7 @@ novirtual class CallGenBase:
cache_on = 1
sha1_len = string.strlen(class_sha1)
pos: sizet = 0
result_ty: llvmlite.LLVMType* = None
result_ty: mlirlite.LLVMType* = None
while pos < text_len:
ls: sizet = pos
le: sizet = pos
@@ -1150,7 +1150,7 @@ novirtual class CallGenBase:
class_sha1: str,
class_name: str,
method_name: str,
use_bare: int = 0) -> llvmlite.LLVMType*:
use_bare: int = 0) -> mlirlite.LLVMType*:
"""从依赖模块的 text.ll 中查找方法返回类型
use_bare: 1=按模块级函数查找(搜索 "{sha1}.{method_name}" define,
@@ -1233,7 +1233,7 @@ novirtual class CallGenBase:
# 单趟扫描 text.ll:登记其全部 define 行供后续 O(1) 命中,并同趟取出首个匹配项。
# 文件长度直接用 read_all 的返回值,省掉一次整文件 strlen。
result_ty: llvmlite.LLVMType* = self._CacheModuleRetTyTexts(
result_ty: mlirlite.LLVMType* = self._CacheModuleRetTyTexts(
class_sha1, read_buf, sizet(text_len), pool, search_buf, search_str_len)
stdlib.free(search_buf)
+162 -162
View File
@@ -1,7 +1,7 @@
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import viperlib
@@ -41,10 +41,10 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
"""c.* 内建 + 内联汇编 + LLVMIR 翻译(继承 Base)"""
def translate_c_deref(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
cl: ast.Call*,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""c.Deref(ptr) → load,宽度只由 ptr 的 pointee 类型决定
pointee 是 i8(t.CPtr / void* / str / bytes)恒读 1 字节;不再按赋值
目标注解(CurAssignAnnot)反推宽度——那会让同一处 c.Deref(i8*) 的读取
@@ -54,7 +54,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
if cl is None: return None
cargs: list[ast.AST*]* = cl.args
if cargs is None or len(cargs) < 1: return None
ptr_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), None, 0, trans)
ptr_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), None, 0, trans)
if ptr_val is None: return None
# rawptr[t.CVolatile | T] 实参(volatile 指针指向物):c.Deref(p) 的
# 解引用 load 带 volatile。仅当实参可解析到 VarEntry(Name)/ FieldEntry
@@ -67,19 +67,19 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
# 不再由赋值目标注解反推——否则同一处 c.Deref(i8*) 的宽度会随上下文
# (是否带注解赋值的 RHS)而变。
if self.Gen.ExprGenBase.is_ptr_type(ptr_val.Ty) != 0:
pointee: llvmlite.LLVMType* = ptr_val.Ty.Pointee
pointee: mlirlite.LLVMType* = ptr_val.Ty.Pointee
if pointee is not None:
return llvmlite.build_load(builder, pointee, ptr_val, vol_deref)
return mlirlite.build_load(builder, pointee, ptr_val, vol_deref)
# 非指针参数即类型推断退化:fail-fast,绝不按 i8 兜底读取(会读到垃圾宽度)
self.Gen.TypeGenErr.fatal_error(cl, "c.Deref 参数不是指针类型(类型推断退化)", "TypeError")
return None
def translate_c_derefas(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
cl: ast.Call*,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""c.DerefAs(ptr, val) → store val to ptr(bitcast 后 store)
单参形式 c.DerefAs(ptr) → 读取 ptr 指向的值(等价 c.Deref(ptr))。
"""
@@ -97,8 +97,8 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
if len(cargs) < 2:
return self.translate_c_deref(pool, builder, mod, cl, trans)
ptr_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), None, 0, trans)
val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(1), None, 0, trans)
ptr_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), None, 0, trans)
val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(1), None, 0, trans)
if ptr_val is None or val is None: return None
# 两端均为指向同一结构体类型的指针时执行结构体拷贝(*ptr = *val),
@@ -107,42 +107,42 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
# 只写入 8 字节指针(tag 字段仍是 0x0),导致运行时读 tag 错乱。
# 对应 TPC HandlesExprCall.py:3696-3701 的 struct 拷贝逻辑。
if self.Gen.ExprGenBase.is_ptr_type(ptr_val.Ty) != 0 and self.Gen.ExprGenBase.is_ptr_type(val.Ty) != 0:
ptr_pointee: llvmlite.LLVMType* = ptr_val.Ty.Pointee
val_pointee: llvmlite.LLVMType* = val.Ty.Pointee
ptr_pointee: mlirlite.LLVMType* = ptr_val.Ty.Pointee
val_pointee: mlirlite.LLVMType* = val.Ty.Pointee
if ptr_pointee is not None and val_pointee is not None:
# ptr_pointee 是已注册结构体类型(用 find_struct_by_type 判断)
if self.Gen.StructGen.find_struct_by_type(ptr_pointee) is not None:
if ptr_pointee is val_pointee:
# 同一结构体类型:load 值再 store(结构体拷贝)
loaded: llvmlite.Value* = llvmlite.build_load(builder, val_pointee, val)
loaded: mlirlite.Value* = mlirlite.build_load(builder, val_pointee, val)
if loaded is not None:
# bitcast ptr 到结构体指针再 store
struct_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, ptr_pointee)
casted_ptr: llvmlite.Value* = llvmlite.build_bitcast(builder, ptr_val, struct_ptr_ty)
struct_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, ptr_pointee)
casted_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, ptr_val, struct_ptr_ty)
if casted_ptr is not None:
llvmlite.build_store(builder, loaded, casted_ptr)
mlirlite.build_store(builder, loaded, casted_ptr)
return val
# bitcast ptr 到 val.Ty* 再 store
val_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, val.Ty)
casted_ptr: llvmlite.Value* = llvmlite.build_bitcast(builder, ptr_val, val_ptr_ty)
val_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, val.Ty)
casted_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, ptr_val, val_ptr_ty)
if casted_ptr is None:
return None
llvmlite.build_store(builder, val, casted_ptr)
mlirlite.build_store(builder, val, casted_ptr)
return val
def translate_c_set(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
cl: ast.Call*,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""c.Set(a, b) → a = b(赋值语义,a 为左值)"""
if cl is None: return None
cargs: list[ast.AST*]* = cl.args
if cargs is None or len(cargs) < 2: return None
a_node: ast.AST* = cargs.get(0)
b_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(1), None, 0, trans)
b_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(1), None, 0, trans)
if b_val is None: return None
# 形态 1: c.Set(c.Deref(ptr), b) → *ptr = b
@@ -153,7 +153,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
if d_at.attr is not None and string.strcmp(d_at.attr, "Deref") == 0:
d_args: list[ast.AST*]* = d_call.args
if d_args is not None and len(d_args) >= 1:
ptr_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, d_args.get(0), None, 0, trans)
ptr_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, d_args.get(0), None, 0, trans)
if ptr_val is not None:
# 写入宽度以「左值指针自身的元素类型」为准:
# c.Set(c.Deref(<T*>(p)), v) 应先把 v 转换到 T,再按 T 宽度写入。
@@ -162,10 +162,10 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
# c.Deref(uint32(p)) 被 0xFFFFFFFF(i64) 写成 8 字节(越界 4 字节)。
# 无类型指针(元素为 i8,如 t.CPtr/i8* 形参)维持原行为:
# 按 RHS 类型重解释指针 store(如 paging save_count 写 i32)。
store_ptr: llvmlite.Value* = ptr_val
store_val: llvmlite.Value* = b_val
store_ptr: mlirlite.Value* = ptr_val
store_val: mlirlite.Value* = b_val
typed_elem: int = 0
elem_ty: llvmlite.LLVMType* = None
elem_ty: mlirlite.LLVMType* = None
if ptr_val.Ty is not None:
elem_ty = ptr_val.Ty.Pointee
if elem_ty is not None:
@@ -181,12 +181,12 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
if typed_elem != 0:
store_val = self.Gen.ExprGenBase.coerce_to_type(builder, b_val, elem_ty, a_node)
else:
val_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, b_val.Ty)
casted_ptr: llvmlite.Value* = llvmlite.build_bitcast(builder, ptr_val, val_ptr_ty)
val_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, b_val.Ty)
casted_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, ptr_val, val_ptr_ty)
if casted_ptr is not None:
store_ptr = casted_ptr
if store_ptr is not None and store_val is not None:
llvmlite.build_store(builder, store_val, store_ptr)
mlirlite.build_store(builder, store_val, store_ptr)
return b_val
# 其他 Call 形态不可作左值
return b_val
@@ -196,60 +196,60 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
nm_set: ast.Name* = ast.Name*(a_node)
if nm_set.id is not None:
if GenApi.is_global_name(trans, nm_set.id) != 0:
mod_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm_set.id)
mod_alloca: mlirlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm_set.id)
if mod_alloca is not None:
tg_ty: llvmlite.LLVMType* = None
tg_ty: mlirlite.LLVMType* = None
if mod_alloca.Ty is not None:
tg_ty = mod_alloca.Ty.Pointee
sv: llvmlite.Value* = b_val
sv: mlirlite.Value* = b_val
if tg_ty is not None:
sv = self.Gen.ExprGenBase.coerce_to_type(builder, b_val, tg_ty, a_node)
llvmlite.build_store(builder, sv, mod_alloca)
mlirlite.build_store(builder, sv, mod_alloca)
return b_val
if GenApi.is_nonlocal_name(trans, nm_set.id) != 0:
nl_ptr: llvmlite.Value* = self.Gen.StmtGenDecl.get_nonlocal_var_ptr(trans, nm_set.id)
nl_ptr: mlirlite.Value* = self.Gen.StmtGenDecl.get_nonlocal_var_ptr(trans, nm_set.id)
if nl_ptr is not None:
nl_ty: llvmlite.LLVMType* = None
nl_ty: mlirlite.LLVMType* = None
if nl_ptr.Ty is not None:
nl_ty = nl_ptr.Ty.Pointee
sv2: llvmlite.Value* = b_val
sv2: mlirlite.Value* = b_val
if nl_ty is not None:
sv2 = self.Gen.ExprGenBase.coerce_to_type(builder, b_val, nl_ty, a_node)
llvmlite.build_store(builder, sv2, nl_ptr)
mlirlite.build_store(builder, sv2, nl_ptr)
return b_val
alloca: llvmlite.Value* = self.Gen.VarGen.get_or_create_sym(trans.SymTab, pool, builder, nm_set.id, b_val.Ty)
alloca: mlirlite.Value* = self.Gen.VarGen.get_or_create_sym(trans.SymTab, pool, builder, nm_set.id, b_val.Ty)
if alloca is not None:
ac_ty: llvmlite.LLVMType* = None
ac_ty: mlirlite.LLVMType* = None
if alloca.Ty is not None:
ac_ty = alloca.Ty.Pointee
sv3: llvmlite.Value* = b_val
sv3: mlirlite.Value* = b_val
if ac_ty is not None:
sv3 = self.Gen.ExprGenBase.coerce_to_type(builder, b_val, ac_ty, a_node)
llvmlite.build_store(builder, sv3, alloca)
mlirlite.build_store(builder, sv3, alloca)
return b_val
return b_val
# 形态 3: Attribute 字段赋值
if a_node is not None and a_node.kind() == ast.ASTKind.Attribute:
field_ptr: llvmlite.Value* = self.Gen.ExprGenAttr.get_attribute_ptr(builder, pool, mod, a_node, trans)
field_ptr: mlirlite.Value* = self.Gen.ExprGenAttr.get_attribute_ptr(builder, pool, mod, a_node, trans)
if field_ptr is not None:
fd_ty: llvmlite.LLVMType* = None
fd_ty: mlirlite.LLVMType* = None
if field_ptr.Ty is not None:
fd_ty = field_ptr.Ty.Pointee
sv4: llvmlite.Value* = b_val
sv4: mlirlite.Value* = b_val
if fd_ty is not None:
sv4 = self.Gen.ExprGenBase.coerce_to_type(builder, b_val, fd_ty, a_node)
llvmlite.build_store(builder, sv4, field_ptr)
mlirlite.build_store(builder, sv4, field_ptr)
return b_val
return b_val
def translate_c_addr(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
cl: ast.Call*,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""c.Addr(var) → 返回变量的 alloca 指针(不 load)"""
if cl is None:
return None
@@ -273,11 +273,11 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
self_entry: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id)
if self_entry is not None and self_entry.Alloca is not None and self_entry.Alloca.Ty is not None:
match self_entry.Alloca.Ty:
case llvmlite.LLVMType.Ptr(inner1):
case mlirlite.LLVMType.Ptr(inner1):
match inner1:
case llvmlite.LLVMType.Ptr(inner2):
obj_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, inner2)
return llvmlite.build_load(builder, obj_ty, self_entry.Alloca)
case mlirlite.LLVMType.Ptr(inner2):
obj_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, inner2)
return mlirlite.build_load(builder, obj_ty, self_entry.Alloca)
case _:
pass
case _:
@@ -287,20 +287,20 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
# 与普通局部 c.Addr(obj) 返回对象指针(load 一次)语义一致。
if trans is not None:
if GenApi.is_nonlocal_name(trans, nm.id) != 0:
nl_addr: llvmlite.Value* = self.Gen.StmtGenDecl.load_nonlocal_var(trans, nm.id)
nl_addr: mlirlite.Value* = self.Gen.StmtGenDecl.load_nonlocal_var(trans, nm.id)
if nl_addr is not None:
return nl_addr
return_var: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
return_var: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
# REPL 模式(M2)会话变量取址:c.Addr(x) → ctx 内该槽的地址(地址同一性)。
# 位置在局部查找之后(片段自己声明的局部名优先,与读路径同序)、
# 模块全局/函数引用之前。守卫 trans.ReplCtx:非 REPL 恒 None ⇒ 不变。
if return_var is None and trans is not None and trans.ReplCtx is not None:
sess_addr: llvmlite.Value* = self.Gen.VarGen.repl_try_addr(trans, nm.id, arg0)
sess_addr: mlirlite.Value* = self.Gen.VarGen.repl_try_addr(trans, nm.id, arg0)
if sess_addr is not None:
return sess_addr
if return_var is None and mod is not None:
# 模块全局变量 c.Addr(模块全局) → 返回全局变量指针:必须经 make_global_ref 转成带引号的 Ptr(Ty) 引用(直接返回 GlobalVariable 节点时其 Ty 是 pointee、Name 无 @ 引号,参与 ptrtoint 会渲染成 "ptrtoint void to i64")
gv_ref_nm: llvmlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(mod, nm.id)
gv_ref_nm: mlirlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(mod, nm.id)
if gv_ref_nm is not None and gv_ref_nm.Name is not None and gv_ref_nm.Ty is not None:
return_var = self.Gen.ExprGenAttr.make_global_ref(pool, gv_ref_nm.Name, gv_ref_nm.Ty)
# 模块函数地址:c.Addr(_on_int_complete) → 函数符号本身(@sha1.func)。
@@ -309,13 +309,13 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
# Addr(uhci.vp L130、coroutine.vp L133 c.Addr(_coro_entry)、
# sched.vp L209 c.Addr(_thread_entry) 根因)。
if return_var is None and mod is not None:
f_addr_ref: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, nm.id)
f_addr_ref: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, nm.id)
if f_addr_ref is not None:
f_addr_name: str = llvmlite.function_get_name(f_addr_ref)
f_addr_name: str = mlirlite.function_get_name(f_addr_ref)
if f_addr_name is not None:
# 形参链是 Param 链(__function.vp),而 llvmlite.Func 的类型构造链是
# 形参链是 Param 链(__function.vp),而 mlirlite.Func 的类型构造链是
# ParamNode 链(__types.vp)——不相关类,统一经 _FuncTyFromFunction 重建。
fn_ty_ca: llvmlite.LLVMType* = self.Gen.CallGenBase._FuncTyFromFunction(pool, f_addr_ref)
fn_ty_ca: mlirlite.LLVMType* = self.Gen.CallGenBase._FuncTyFromFunction(pool, f_addr_ref)
# 函数引用名需按需加引号(数字开头/含 '.' 的 sha1 前缀名
# 必须 @\"...\",否则 llc "expected 'to' after cast value",
# uhci.vp c.Addr(_on_int_complete) 根因)。
@@ -327,7 +327,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
viperlib.snprintf(faddr_buf_ca, fnlen_ca + 4, "@\"%s\"", f_addr_name)
else:
viperlib.snprintf(faddr_buf_ca, fnlen_ca + 4, "@%s", f_addr_name)
return_var = llvmlite.SSAValue(pool, llvmlite.Ptr(pool, fn_ty_ca), faddr_buf_ca)
return_var = mlirlite.SSAValue(pool, mlirlite.Ptr(pool, fn_ty_ca), faddr_buf_ca)
# 闭包变量:c.Addr(闭包名) → 返回闭包对象指针(load 一次)。
# 闭包 alloca 是 i8**(存 {fn_ptr, env_ptr} 结构地址);不 load 的话
# 会把 &闭包指针变量(i8**)当对象地址传,回调侧按闭包结构读
@@ -335,9 +335,9 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
# 变量 c.Addr(obj) load 一次的语义一致)。
if return_var is not None and return_var.Ty is not None:
if self.Gen.CallGenLeafKit.is_closure_name(nm.id) != 0:
i8_ty_cb: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty_cb: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty_cb)
return llvmlite.build_load(builder, i8_ptr_ty_cb, return_var)
i8_ty_cb: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty_cb: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_cb)
return mlirlite.build_load(builder, i8_ptr_ty_cb, return_var)
if return_var is not None and return_var.Ty is not None:
# 对象指针变量(如 lit_tree = zhuff.zhuff_tree(),alloca 是
# Ptr(Ptr(Struct)),存对象指针):c.Addr(对象变量) 应返回对象
@@ -347,13 +347,13 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
# 读到指针值/垃圾 → build_decode_tree 越界崩溃
# (zinflate inflate_block_fixed 的 c.Addr(lit_tree) 根因)。
match return_var.Ty:
case llvmlite.LLVMType.Ptr(addr_inner1):
case mlirlite.LLVMType.Ptr(addr_inner1):
match addr_inner1:
case llvmlite.LLVMType.Ptr(addr_inner2):
case mlirlite.LLVMType.Ptr(addr_inner2):
match addr_inner2:
case llvmlite.LLVMType.Struct(_, _, _):
addr_obj_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, addr_inner2)
return llvmlite.build_load(builder, addr_obj_ty, return_var)
case mlirlite.LLVMType.Struct(_, _, _):
addr_obj_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, addr_inner2)
return mlirlite.build_load(builder, addr_obj_ty, return_var)
case _:
pass
case _:
@@ -375,13 +375,13 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
mod_nm2: ast.Name* = ast.Name*(at_addr.value)
if mod_nm2.id is not None:
if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, mod_nm2.id) != 0:
f_ref2: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, at_addr.attr)
f_ref2: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, at_addr.attr)
if f_ref2 is not None:
fname2: str = llvmlite.function_get_name(f_ref2)
fname2: str = mlirlite.function_get_name(f_ref2)
if fname2 is not None:
# 构造带 @ 名的 SSAValue(Ptr(FuncTy)):直接返回 Function 节点会被 IRBuilder 格式化成 RetTy(void)→ "bitcast void to i8*"。Function 无 Ty 字段,用 RetTy+Params 重建函数类型;Params 是 GSList,必须经 function_get_param_head 取链表头(当 Param 直接遍历会读出垃圾参数类型)
# 同上:Function 的 Param 形参链 → 重建 ParamNode 链再交 Func
fn_ty2: llvmlite.LLVMType* = self.Gen.CallGenBase._FuncTyFromFunction(pool, f_ref2)
fn_ty2: mlirlite.LLVMType* = self.Gen.CallGenBase._FuncTyFromFunction(pool, f_ref2)
# 函数引用名按需加引号(数字开头/含 '.' 的
# sha1 前缀名必须 @\"...\")。
fnlen2: sizet = string.strlen(fname2)
@@ -392,15 +392,15 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
viperlib.snprintf(faddr_buf2, fnlen2 + 4, "@\"%s\"", fname2)
else:
viperlib.snprintf(faddr_buf2, fnlen2 + 4, "@%s", fname2)
return llvmlite.SSAValue(pool, llvmlite.Ptr(pool, fn_ty2), faddr_buf2)
return mlirlite.SSAValue(pool, mlirlite.Ptr(pool, fn_ty2), faddr_buf2)
else:
# 模块限定全局 c.Addr(gdt.gp) → 全局符号本身(@gp):跨模块全局(含 CExport 裸名)已注入为 external global,经 make_global_ref 转成带引号的 Ptr(Ty) 引用(直接返回 GlobalVariable 节点会渲染 "ptrtoint void")
g_ref2: llvmlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(mod, at_addr.attr)
g_ref2: mlirlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(mod, at_addr.attr)
if g_ref2 is not None and g_ref2.Name is not None and g_ref2.Ty is not None:
return self.Gen.ExprGenAttr.make_global_ref(pool, g_ref2.Name, g_ref2.Ty)
# 解析 base(Name 变量 / Subscript 数组元素)→ 对象指针
obj_ptr: llvmlite.Value* = None
struct_ty: llvmlite.LLVMType* = None
obj_ptr: mlirlite.Value* = None
struct_ty: mlirlite.LLVMType* = None
if at_addr.value.kind() == ast.ASTKind.Subscript:
# c.Addr(s.threads[0].rsp):base 是数组元素(Subscript)→ 先取
# 元素指针(GEP 数组),再 GEP 到字段。此前仅支持 Name base,
@@ -410,17 +410,17 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
sub_base: ast.Subscript* = ast.Subscript*(at_addr.value)
if sub_base.value is None or sub_base.slice is None:
return None
bval: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub_base.value, None, 0, trans)
bidx: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub_base.slice, None, 0, trans)
bval: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub_base.value, None, 0, trans)
bidx: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub_base.slice, None, 0, trans)
if bval is None or bidx is None or bval.Ty is None:
return None
bpointee: llvmlite.LLVMType* = None
bpointee: mlirlite.LLVMType* = None
if self.Gen.ExprGenBase.is_ptr_type(bval.Ty) != 0:
bpointee = bval.Ty.Pointee
if bpointee is not None:
match bpointee:
case llvmlite.LLVMType.Array(bet, _):
obj_ptr = llvmlite.build_gep_array(builder, bpointee, bet, bval, bidx)
case mlirlite.LLVMType.Array(bet, _):
obj_ptr = mlirlite.build_gep_array(builder, bpointee, bet, bval, bidx)
struct_ty = bet
case _:
return None
@@ -430,15 +430,15 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
self_nm: ast.Name* = ast.Name*(at_addr.value)
if self_nm.id is None:
return None
self_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, self_nm.id)
self_alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, self_nm.id)
if self_alloca is None or self_alloca.Ty is None:
return None
# 从 self 类型提取结构体类型(Ptr(Struct) 或 Ptr(Ptr(Struct)))
self_is_ptr_ptr: int = 0
match self_alloca.Ty:
case llvmlite.LLVMType.Ptr(inner1):
case mlirlite.LLVMType.Ptr(inner1):
match inner1:
case llvmlite.LLVMType.Ptr(inner2):
case mlirlite.LLVMType.Ptr(inner2):
struct_ty = inner2
self_is_ptr_ptr = 1
case _:
@@ -448,8 +448,8 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
# self_alloca 是 Ptr(Ptr(Struct)) 时先 load 成 Ptr(Struct) 对象指针
obj_ptr = self_alloca
if self_is_ptr_ptr == 1:
self_obj_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, struct_ty)
obj_ptr = llvmlite.build_load(builder, self_obj_ty, self_alloca)
self_obj_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, struct_ty)
obj_ptr = mlirlite.build_load(builder, self_obj_ty, self_alloca)
else:
return None
if obj_ptr is None or struct_ty is None:
@@ -459,7 +459,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
if fe_addr is None:
return None
# GEP 到字段地址
return llvmlite.build_gep_struct(builder, struct_ty, fe_addr.Ty, obj_ptr, fe_addr.Index)
return mlirlite.build_gep_struct(builder, struct_ty, fe_addr.Ty, obj_ptr, fe_addr.Index)
# Subscript 形式: c.Addr(arr[i]) / c.Addr(a.b[i][j]) → 元素地址(GEP,不 load)
# 统一走 get_subscript_ptr(递归处理嵌套下标、数组/指针/str|t.CPtr 形态)。
@@ -469,41 +469,41 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
# call @Addr(ld.lld undefined symbol: Addr 根因)。
if arg0.kind() == ast.ASTKind.Subscript:
if trans is None: return None
elem_ptr_ca: llvmlite.Value* = self.Gen.ExprGenName.get_subscript_ptr(builder, pool, mod, arg0, trans)
elem_ptr_ca: mlirlite.Value* = self.Gen.ExprGenName.get_subscript_ptr(builder, pool, mod, arg0, trans)
if elem_ptr_ca is not None: return elem_ptr_ca
# 兜底:单层数组基址 GEP(get_subscript_ptr 未命中的形态)
sub_addr: ast.Subscript* = ast.Subscript*(arg0)
if sub_addr is None or sub_addr.value is None or sub_addr.slice is None: return None
arr_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub_addr.value, None, 0, trans)
arr_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub_addr.value, None, 0, trans)
if arr_val is None or arr_val.Ty is None: return None
idx_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub_addr.slice, None, 0, trans)
idx_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub_addr.slice, None, 0, trans)
if idx_val is None: return None
# 下标 zext 由 llvmlite.build_gep / build_gep_array 内部统一处理
# 下标 zext 由 mlirlite.build_gep / build_gep_array 内部统一处理
# (唯一真源),此处不再自行 zext。
arr_pointee_ca: llvmlite.LLVMType* = None
arr_pointee_ca: mlirlite.LLVMType* = None
if self.Gen.ExprGenBase.is_ptr_type(arr_val.Ty) != 0:
arr_pointee_ca = arr_val.Ty.Pointee
if arr_pointee_ca is not None:
match arr_pointee_ca:
case llvmlite.LLVMType.Array(arr_et_ca, _):
return llvmlite.build_gep_array(builder, arr_pointee_ca, arr_et_ca, arr_val, idx_val)
case mlirlite.LLVMType.Array(arr_et_ca, _):
return mlirlite.build_gep_array(builder, arr_pointee_ca, arr_et_ca, arr_val, idx_val)
case _:
# 标量/指针元素(如字符串 a[4])→ 简单 GEP 元素地址。
# 此前仅 Array 走 GEP,标量 pointee 落 return None →
# 跌落跨模块函数调用生成 call @Addr(main.vp L272
# c.Addr(a[4]) 根因)。
return llvmlite.build_gep(builder, arr_pointee_ca, arr_val, idx_val)
return mlirlite.build_gep(builder, arr_pointee_ca, arr_val, idx_val)
return None
# Call 形式: c.Addr(expr) → 求值 expr 存临时槽(entry alloca),返回槽地址
# 供就地解读使用:tt: Coroutine = c.Addr(task()) —— coerce 指针→结构体时
# 从槽地址 load(target 是 NoVTable 结构体,如 Coroutine={__ptr__} 8 字节)。
if arg0.kind() == ast.ASTKind.Call:
call_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg0, None, 0, trans)
call_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg0, None, 0, trans)
if call_val is None or call_val.Ty is None: return None
tmp_slot: llvmlite.Value* = llvmlite.build_alloca_at_entry(builder, call_val.Ty)
tmp_slot: mlirlite.Value* = mlirlite.build_alloca_at_entry(builder, call_val.Ty)
if tmp_slot is None: return None
llvmlite.build_store(builder, call_val, tmp_slot)
mlirlite.build_store(builder, call_val, tmp_slot)
return tmp_slot
# 其他 arg0 形式(非 Name/Attribute/Subscript/Call):fail-fast。
@@ -515,34 +515,34 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
def translate_c_load(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
cl: ast.Call*,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""c.Load(a, b) → *a = *b(加载 b 的值,存储到 a)"""
if cl is None: return None
cargs: list[ast.AST*]* = cl.args
if cargs is None or len(cargs) < 2: return None
dst_ptr: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), None, 0, trans)
src_ptr: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(1), None, 0, trans)
dst_ptr: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), None, 0, trans)
src_ptr: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(1), None, 0, trans)
if dst_ptr is None or src_ptr is None: return None
# 确定 pointee 类型(优先用 src 的 pointee,回退到 dst 的 pointee)
pointee: llvmlite.LLVMType* = None
pointee: mlirlite.LLVMType* = None
if src_ptr.Ty is not None:
pointee = src_ptr.Ty.Pointee
if pointee is None and dst_ptr.Ty is not None:
pointee = dst_ptr.Ty.Pointee
if pointee is None: return None
# bitcast src 到 pointee* 并 load
target_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, pointee)
src_cast: llvmlite.Value* = llvmlite.build_bitcast(builder, src_ptr, target_ptr_ty)
target_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, pointee)
src_cast: mlirlite.Value* = mlirlite.build_bitcast(builder, src_ptr, target_ptr_ty)
if src_cast is None: return None
loaded: llvmlite.Value* = llvmlite.build_load(builder, pointee, src_cast)
loaded: mlirlite.Value* = mlirlite.build_load(builder, pointee, src_cast)
if loaded is None: return None
# bitcast dst 到 pointee* 并 store
dst_cast: llvmlite.Value* = llvmlite.build_bitcast(builder, dst_ptr, target_ptr_ty)
dst_cast: mlirlite.Value* = mlirlite.build_bitcast(builder, dst_ptr, target_ptr_ty)
if dst_cast is None: return None
llvmlite.build_store(builder, loaded, dst_cast)
mlirlite.build_store(builder, loaded, dst_cast)
return loaded
@@ -565,7 +565,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
def _asm_mangle_global_symbols(self, pool: memhub.MemBuddy*,
asm_text: str, asm_size: sizet,
mod: llvmlite.LLVMModule*) -> str:
mod: mlirlite.LLVMModule*) -> str:
"""asm 模板中裸符号引用模块全局的检查(fail-fast)
内联汇编 `lea rax, [rip + gdt]` 的 gdt 是汇编器符号,若对应模块全局
@@ -588,7 +588,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
i: sizet = 0
while i < src_len:
matched: int = 0
cur: llvmlite.GlobalVariable* = mod.GlobalHead
cur: mlirlite.GlobalVariable* = mod.GlobalHead
while cur is not None:
gname: str = cur.Name
if gname is not None and string.strchr(gname, 46) is not None:
@@ -888,7 +888,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
def _asm_add_operand(self, operands: rawptr[GenTypes.AsmOperand],
count: int,
val: llvmlite.Value*,
val: mlirlite.Value*,
constraint: str,
is_output: int) -> int:
"""添加操作数到数组,返回新计数(失败返回原计数)
@@ -929,10 +929,10 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
def translate_c_asm(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
cl: ast.Call*,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""翻译 c.Asm 内联汇编,返回结果 Value(无输出时返回 None)"""
if cl is None:
return None
@@ -975,7 +975,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
# 首个输出操作数的元素类型缓存(对齐 python 参考 HandlesExprAsm 的
# "收集时即定 ret 类型":不依赖事后从 pool 槽二次读回 Value.Ty.Pointee,
# 避免读回不稳定 → ret 静默 Void → 带名 void asm(atom.vp 根因)。
out_ret_ty_first: llvmlite.LLVMType* = None
out_ret_ty_first: mlirlite.LLVMType* = None
# 全量输出元素类型按序缓存(多输出如 vrandom rdrand*_step 的 val+ok):
# 同样在收集时直接从 alloca 取 Pointee,绕开 AsmOperand 槽读不稳定。
out_ptys: sizet* = pool.alloc(8 * ASM_MAX_OPERANDS)
@@ -1040,7 +1040,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
# Attribute 字段地址)
if val_node is None:
continue
alloca: llvmlite.Value* = None
alloca: mlirlite.Value* = None
if val_node.kind() == ast.ASTKind.Name:
nm: ast.Name* = ast.Name*(val_node)
if nm.id is None:
@@ -1056,7 +1056,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
# —— GlobalVariable.Name 在 Ty 之前,旧的无条件 bitcast 会让
# .Ty 读到 Name),必须按 c.Addr(模块全局) 分支的同一写法构造
# 带引号的 Ptr(Ty) 引用(见 L309 注释)。
gv_asm: llvmlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(mod, nm.id)
gv_asm: mlirlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(mod, nm.id)
if gv_asm is not None and gv_asm.Name is not None and gv_asm.Ty is not None:
alloca = self.Gen.ExprGenAttr.make_global_ref(pool, gv_asm.Name, gv_asm.Ty)
elif val_node.kind() == ast.ASTKind.Attribute:
@@ -1068,14 +1068,14 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
if at_a.attr is not None and at_a.value is not None and at_a.value.kind() == ast.ASTKind.Name:
base_nm_a: ast.Name* = ast.Name*(at_a.value)
if base_nm_a.id is not None:
base_alloca_a: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, base_nm_a.id)
base_alloca_a: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, base_nm_a.id)
if base_alloca_a is not None and base_alloca_a.Ty is not None:
struct_ty_a: llvmlite.LLVMType* = None
struct_ty_a: mlirlite.LLVMType* = None
self_is_ptr_ptr_a: int = 0
match base_alloca_a.Ty:
case llvmlite.LLVMType.Ptr(inner1):
case mlirlite.LLVMType.Ptr(inner1):
match inner1:
case llvmlite.LLVMType.Ptr(inner2):
case mlirlite.LLVMType.Ptr(inner2):
struct_ty_a = inner2
self_is_ptr_ptr_a = 1
case _:
@@ -1085,11 +1085,11 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
if struct_ty_a is not None:
fe_a: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(struct_ty_a, at_a.attr)
if fe_a is not None:
obj_ptr_a: llvmlite.Value* = base_alloca_a
obj_ptr_a: mlirlite.Value* = base_alloca_a
if self_is_ptr_ptr_a == 1:
obj_ptr_a = llvmlite.build_load(builder, llvmlite.Ptr(pool, struct_ty_a), base_alloca_a)
obj_ptr_a = mlirlite.build_load(builder, mlirlite.Ptr(pool, struct_ty_a), base_alloca_a)
if obj_ptr_a is not None:
alloca = llvmlite.build_gep_struct(builder, struct_ty_a, fe_a.Ty, obj_ptr_a, fe_a.Index)
alloca = mlirlite.build_gep_struct(builder, struct_ty_a, fe_a.Ty, obj_ptr_a, fe_a.Index)
if alloca is None:
continue
operand_count = self._asm_add_operand(operands, operand_count, alloca, cons_str, 1)
@@ -1100,7 +1100,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
out_pty_n += 1
else:
# 输入:翻译值
ival: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, val_node, None, 0, trans)
ival: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, val_node, None, 0, trans)
if ival is None:
continue
operand_count = self._asm_add_operand(operands, operand_count, ival, cons_str, 0)
@@ -1144,7 +1144,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
if oval_node is None or oval_node.kind() != ast.ASTKind.Name: continue
onm: ast.Name* = ast.Name*(oval_node)
if onm.id is None: continue
oalloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, onm.id)
oalloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, onm.id)
if oalloca is None: continue
operand_count = self._asm_add_operand(operands, operand_count, oalloca, ocons, 1)
if out_ret_ty_first is None and oalloca is not None and oalloca.Ty is not None and oalloca.Ty.Pointee != 0:
@@ -1172,7 +1172,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
icons: str = ""
if len(iargs) >= 2:
icons = self._resolve_asm_descr(pool, iargs.get(1))
ival2: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, ival_node, None, 0, trans)
ival2: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, ival_node, None, 0, trans)
if ival2 is None: continue
operand_count = self._asm_add_operand(operands, operand_count, ival2, icons, 0)
@@ -1234,31 +1234,31 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
# 多输出(如 vrandom rdrand*_step 的 val+ok 两个 AsmOut)返回
# 匿名 struct {ty1, ty2, ...},元素数 = 输出操作数(LLVM asm
# 要求输出约束数 = 返回 struct 元素数)。
ret_ty: llvmlite.LLVMType* = llvmlite.Void(pool)
ret_ty: mlirlite.LLVMType* = mlirlite.Void(pool)
if output_count > 0 and first_output_idx >= 0:
if output_count > 1:
# 多输出返回类型 {T1, T2, ...} 的字段链表是 ParamNode 链
# (new_param_node 返回 rawptr[ParamNode]、Struct 形参 rawptr[ParamNode]、
# ParamNode.Next: ParamNode|CPtr),原先误注解为 Function*(不相关类)
# → 1264/1268 两处会被判 struct↔struct 隐式转换禁止。
out_pn_head: llvmlite.ParamNode* = None
out_pn_last: llvmlite.ParamNode* = None
out_pn_head: mlirlite.ParamNode* = None
out_pn_last: mlirlite.ParamNode* = None
out_pn_n: int = 0
out_seq: int = 0
for oi5 in range(operand_count):
op5: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, oi5)
if op5 is None or op5.IsOutput == 0:
continue
pty5: llvmlite.LLVMType* = None
pty5: mlirlite.LLVMType* = None
# 优先收集时按序缓存的直接类型,再回退从槽读回
if out_ptys is not None and out_seq < out_pty_n:
pty5 = llvmlite.LLVMType*(out_ptys[out_seq])
pty5 = mlirlite.LLVMType*(out_ptys[out_seq])
elif op5.Value is not None and op5.Value.Ty is not None and op5.Value.Ty.Pointee != 0:
pty5 = op5.Value.Ty.Pointee
out_seq += 1
if pty5 is None:
continue
pn5: llvmlite.ParamNode* = llvmlite.new_param_node(pool, pty5)
pn5: mlirlite.ParamNode* = mlirlite.new_param_node(pool, pty5)
if pn5 is not None:
if out_pn_head is None:
out_pn_head = pn5
@@ -1267,13 +1267,13 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
out_pn_last = pn5
out_pn_n += 1
if out_pn_head is not None and out_pn_n > 0:
ret_ty = llvmlite.Struct(pool, out_pn_head, out_pn_n, None)
ret_ty = mlirlite.Struct(pool, out_pn_head, out_pn_n, None)
else:
self.Gen.TypeGenErr.fatal_error(cl, "c.Asm 输出操作数类型缺失(变量 alloca 类型退化)", "TypeError")
ret_ty = llvmlite.Int32(pool)
ret_ty = mlirlite.Int32(pool)
else:
out_op: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, first_output_idx)
out_pt: llvmlite.LLVMType* = None
out_pt: mlirlite.LLVMType* = None
# 优先用收集时缓存的元素类型(对齐 python 参考),再回退从槽读回
if out_ret_ty_first is not None:
out_pt = out_ret_ty_first
@@ -1283,7 +1283,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
ret_ty = out_pt
else:
self.Gen.TypeGenErr.fatal_error(cl, "c.Asm 输出操作数类型缺失(变量 alloca 类型退化)", "TypeError")
ret_ty = llvmlite.Int32(pool)
ret_ty = mlirlite.Int32(pool)
# 判断 void — 直接基于 output_count 判断,避免 match 类型匹配问题
is_void: int = 1
@@ -1297,8 +1297,8 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
# fail-fast,拒绝静默发射非法 IR。
if is_void == 0:
match ret_ty:
case llvmlite.LLVMType.Void():
ret_re: llvmlite.LLVMType* = None
case mlirlite.LLVMType.Void():
ret_re: mlirlite.LLVMType* = None
for re_i in range(operand_count):
re_op: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, re_i)
if re_op is None or re_op.IsOutput == 0: continue
@@ -1428,7 +1428,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
orig_i2: int = new_order[ai3]
aop: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, orig_i2)
if aop.IsOutput != 0: continue
aval: llvmlite.Value* = aop.Value
aval: mlirlite.Value* = aop.Value
if aval is None or aval.Ty is None or aval.Name is None: continue
if first_arg == 0:
@@ -1439,7 +1439,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
ty_buf: str = pool.alloc(64)
if ty_buf is not None:
ty_buf[0] = '\0'
llvmlite.TypePrint(ty_buf, 64, aval.Ty, pool)
mlirlite.TypePrint(ty_buf, 64, aval.Ty, pool)
self._asm_append_cstr(args_buf, ASM_ARGS_BUF_SIZE, ty_buf)
self._asm_append_cstr(args_buf, ASM_ARGS_BUF_SIZE, " ")
self._asm_append_cstr(args_buf, ASM_ARGS_BUF_SIZE, aval.Name)
@@ -1471,7 +1471,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
ret_ty_buf: str = pool.alloc(64)
if ret_ty_buf is not None:
ret_ty_buf[0] = '\0'
llvmlite.TypePrint(ret_ty_buf, 64, ret_ty, pool)
mlirlite.TypePrint(ret_ty_buf, 64, ret_ty, pool)
if is_void == 1:
viperlib.snprintf(line, ASM_LINE_BUF_SIZE, "call %s asm sideeffect inteldialect \"%s\", \"%s\"(%s)",
@@ -1481,13 +1481,13 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
ssa_name, ret_ty_buf, escaped_asm, const_buf, args_buf)
# 发射 IR 到当前块
llvmlite.block_append_text(pool, builder.CurBlock, line)
mlirlite.block_append_text(pool, builder.CurBlock, line)
# ============================================================
# 9. 处理输出:存储结果到输出变量
# ============================================================
if is_void == 0 and first_output_idx >= 0:
result_val: llvmlite.Value* = llvmlite.SSAValue(pool, ret_ty, ssa_name)
result_val: mlirlite.Value* = mlirlite.SSAValue(pool, ret_ty, ssa_name)
out_emit_idx: int = 0
for oi_out in range(operand_count):
orig_o: int = new_order[oi_out]
@@ -1507,12 +1507,12 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
viperlib.snprintf(ev_line, ASM_LINE_BUF_SIZE,
"%s = extractvalue %s %s, %d",
ev_name, ret_ty_buf, ssa_name, out_emit_idx)
llvmlite.block_append_text(pool, builder.CurBlock, ev_line)
ev_val: llvmlite.Value* = llvmlite.SSAValue(pool, oo.Value.Ty.Pointee, ev_name)
llvmlite.build_store(builder, ev_val, oo.Value)
mlirlite.block_append_text(pool, builder.CurBlock, ev_line)
ev_val: mlirlite.Value* = mlirlite.SSAValue(pool, oo.Value.Ty.Pointee, ev_name)
mlirlite.build_store(builder, ev_val, oo.Value)
else:
if oo.Value is not None:
llvmlite.build_store(builder, result_val, oo.Value)
mlirlite.build_store(builder, result_val, oo.Value)
out_emit_idx += 1
return result_val
@@ -1520,10 +1520,10 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
def translate_c_llvmir(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
cl: ast.Call*,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""c.LLVMIR 内联 LLVM IR:无返回值,直接嵌入原始 IR 文本
不做指令解析,模板文本(c.LInp/c.LOut 替换后)用 block_append_text
@@ -1595,7 +1595,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
if string.strcmp(attr_nm, "LInp") == 0:
# 输入操作数:翻译值,替换为 LLVM 值引用文本(%x 或常量文本)
inp_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, val_node, None, 0, trans)
inp_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, val_node, None, 0, trans)
if inp_val is not None and inp_val.Name is not None:
self._asm_append_cstr(text, LLVMIR_TEMPLATE_BUF, inp_val.Name)
@@ -1605,7 +1605,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
if val_node is not None and val_node.kind() == ast.ASTKind.Name:
nm: ast.Name* = ast.Name*(val_node)
if nm.id is not None:
alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
if alloca is None or out_count >= LLVMIR_MAX_OPS:
self.Gen.TypeGenErr.fatal_error(fcall, f"c.LOut 变量 '{nm.id}' 未定义或输出数超过 {LLVMIR_MAX_OPS}", "TypeError")
self.Gen.CallGenBase.LLVMIRRegSeq += 1
@@ -1618,7 +1618,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
out_count += 1
continue
# 非 c.LInp/c.LOut 的 f-string 表达式:翻译值并嵌入值文本
ival: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fexpr, None, 0, trans)
ival: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fexpr, None, 0, trans)
if ival is not None and ival.Name is not None:
self._asm_append_cstr(text, LLVMIR_TEMPLATE_BUF, ival.Name)
@@ -1632,22 +1632,22 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
# ============================================================
# 2. 直接嵌入模板文本(不做指令解析)+ LOut 写回
# ============================================================
llvmlite.block_append_text(pool, builder.CurBlock, text)
mlirlite.block_append_text(pool, builder.CurBlock, text)
# LOut 写回: store <ty> %llvmirN, <ty>* %var
oi: int
for oi in range(out_count):
oa: llvmlite.Value* = llvmlite.Value*(out_alloca[oi])
oa: mlirlite.Value* = mlirlite.Value*(out_alloca[oi])
rn: str = str(out_regname[oi])
if oa is None or oa.Ty is None or oa.Ty.Pointee == 0 or rn is None:
continue
reg_val: llvmlite.Value* = llvmlite.new_value(pool)
reg_val: mlirlite.Value* = mlirlite.new_value(pool)
if reg_val is None:
continue
reg_val.Ty = oa.Ty.Pointee
reg_val.Name = rn
reg_val.IsConst = 0
llvmlite.build_store(builder, reg_val, oa)
mlirlite.build_store(builder, reg_val, oa)
return None
File diff suppressed because it is too large. Load diff
+100 -100
View File
@@ -1,7 +1,7 @@
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdio
@@ -29,11 +29,11 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# 显式参数(位置/关键字)后续会覆盖默认值
# ============================================================
def _apply_struct_defaults(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
struct_ty: llvmlite.LLVMType*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
struct_ty: mlirlite.LLVMType*,
class_name: str,
tmp: llvmlite.Value*,
tmp: mlirlite.Value*,
trans: HT.Translator*,
is_volatile: int = 0):
"""应用结构体字段的默认值
@@ -58,11 +58,11 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# 误译成动态 list 对象指针,coerce 到 [N x elem] 会失败)。
# Mixin 静态绑定:跨 Mixin 方法必须走 HandlesAnnAssign 模块级委托。
if fe.Ty is not None and self.Gen.ExprGenBase.is_array_type(fe.Ty) != 0 and fe.DefaultVal.kind() == ast.ASTKind.List:
field_ptr_arr2: llvmlite.Value* = llvmlite.build_gep_struct(builder, struct_ty, fe.Ty, tmp, fe.Index)
field_ptr_arr2: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, fe.Ty, tmp, fe.Index)
if field_ptr_arr2 is not None:
zero_arr2: llvmlite.Value* = llvmlite.ConstZero(pool, fe.Ty)
zero_arr2: mlirlite.Value* = mlirlite.ConstZero(pool, fe.Ty)
if zero_arr2 is not None:
llvmlite.build_store(builder, zero_arr2, field_ptr_arr2, is_volatile)
mlirlite.build_store(builder, zero_arr2, field_ptr_arr2, is_volatile)
# owner_ctx 只服务空元素 fail-fast 报文(类名 + 字段名 + 下标)
sd_ctx: str = pool.alloc(192)
if sd_ctx is not None:
@@ -72,18 +72,18 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
viperlib.snprintf(sd_ctx, 192, "类 %s 字段 %s(结构体构造默认值):", class_name, fname_sd)
self.Gen.AssignGen._init_global_array_from_list(builder, pool, mod, field_ptr_arr2, fe.DefaultVal, trans, sd_ctx)
continue
default_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fe.DefaultVal, None, 0, trans, fe.Ty)
default_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fe.DefaultVal, None, 0, trans, fe.Ty)
if default_val is None:
# fast-fail: 默认值翻译失败(如引用了未定义符号)
VLogger.error(f"字段默认值翻译失败: {class_name}", "HandlesExprCall")
continue
field_ptr: llvmlite.Value* = llvmlite.build_gep_struct(builder, struct_ty, fe.Ty, tmp, fe.Index)
field_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, fe.Ty, tmp, fe.Index)
if field_ptr is None:
# fast-fail: GEP 失败(struct_ty 与 fe.Ty 不匹配)
VLogger.error(f"字段 GEP 失败,类型不匹配: {class_name}", "HandlesExprCall")
continue
default_val = self.Gen.ExprGenBase.coerce_to_type(builder, default_val, fe.Ty, fe.DefaultVal)
llvmlite.build_store(builder, default_val, field_ptr, is_volatile)
mlirlite.build_store(builder, default_val, field_ptr, is_volatile)
# ============================================================
# _translate_struct_ctor — 结构体构造函数 Point(10, 20)
#
@@ -99,14 +99,14 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# ============================================================
def _translate_struct_ctor(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
struct_ty: llvmlite.LLVMType*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
struct_ty: mlirlite.LLVMType*,
class_name: str,
cargs: list[ast.AST*]*,
can: sizet,
trans: HT.Translator*,
is_volatile: int = 0) -> llvmlite.Value*:
is_volatile: int = 0) -> mlirlite.Value*:
"""结构体构造函数:按字段顺序 store 参数值,返回结构体值
OOP 结构体:alloca → call __before_init__(ptr) → call __init__(ptr, args) 或 store 参数 → load
@@ -120,9 +120,9 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# 创建临时 alloca
# 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间)
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, struct_ty)
tmp: llvmlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, struct_ty)
tmp: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, struct_ty)
if tmp is None:
return llvmlite.ConstZero(pool, struct_ty)
return mlirlite.ConstZero(pool, struct_ty)
# 诊断节点:取第一个构造实参(有行号),供 _call_method_on_ptr 的
# fatal_error 显示构造调用行号(本函数无 cl 参数,实参节点最接近调用点)
diag_node_ct: ast.AST* = None
@@ -143,7 +143,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
if init_lookup_name is not None:
viperlib.snprintf(init_lookup_name, 128, "%s.__init__", class_name)
# 方案1: 检查当前模块的函数声明
init_found_func: llvmlite.Function* = self.find_func_in_module(mod, init_lookup_name)
init_found_func: mlirlite.Function* = self.find_func_in_module(mod, init_lookup_name)
if init_found_func is not None:
is_oop = 1
if ctor_entry is not None:
@@ -160,7 +160,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
if is_oop != 0:
# 存储指针:默认用 alloca,如果有 __new__ 则用 __new__ 返回的指针
storage_ptr: llvmlite.Value* = tmp
storage_ptr: mlirlite.Value* = tmp
# 如果有 __new__,调用 __new__(tmp, args...) 获取实际存储指针
# __new__ 签名与 __init__ 一样(self + args),返回 Ptr(struct_ty)
@@ -177,13 +177,13 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
new_arg_node: ast.AST* = cargs.get(nai)
if new_arg_node is None:
continue
new_av: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, new_arg_node, None, 0, trans)
new_av: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, new_arg_node, None, 0, trans)
if new_av is not None:
if new_arg_count < 32:
new_arg_vals[new_arg_count] = sizet(new_av)
new_arg_count += 1
new_ptr: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name, "__new__", tmp, new_arg_vals, new_arg_count, trans, diag_node_ct, is_volatile)
new_ptr: mlirlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name, "__new__", tmp, new_arg_vals, new_arg_count, trans, diag_node_ct, is_volatile)
if new_ptr is not None:
storage_ptr = new_ptr
# __new__ 只保证返回"实例存储指针",声明类型通常是
@@ -193,9 +193,9 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# 查不到类名,误报"跨模块调用 'parser.add_argument' 找不到模块 SHA1"。
# bitcast 只改类型层视图,运行时零开销(指针位不变)。
if new_ptr.Ty is not None:
nw_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, struct_ty)
nw_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, struct_ty)
if uint64(new_ptr.Ty) != uint64(nw_ty):
nw_bc: llvmlite.Value* = llvmlite.build_bitcast(builder, new_ptr, nw_ty)
nw_bc: mlirlite.Value* = mlirlite.build_bitcast(builder, new_ptr, nw_ty)
if nw_bc is not None:
storage_ptr = nw_bc
@@ -218,7 +218,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
arg_node: ast.AST* = cargs.get(ai)
if arg_node is None:
continue
av: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg_node, None, 0, trans)
av: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg_node, None, 0, trans)
if av is not None:
if real_arg_count < 32:
arg_vals[real_arg_count] = sizet(av)
@@ -252,25 +252,25 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# fast-fail: 字段索引越界(用户传了多余参数)
VLogger.error(f"构造函数参数过多,字段索引越界: {class_name}", "HandlesExprCall")
continue
arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, fe.Ty)
arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, fe.Ty)
if arg_val is None:
# fast-fail: 参数翻译失败
VLogger.error(f"构造函数参数翻译失败: {class_name}", "HandlesExprCall")
continue
field_ptr: llvmlite.Value* = llvmlite.build_gep_struct(builder, struct_ty, fe.Ty, storage_ptr, fe.Index)
field_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, fe.Ty, storage_ptr, fe.Index)
if field_ptr is None:
# fast-fail: GEP 失败(struct_ty 与 fe.Ty 不匹配)
VLogger.error(f"构造函数字段 GEP 失败: {class_name}", "HandlesExprCall")
continue
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, fe.Ty, arg)
llvmlite.build_store(builder, arg_val, field_ptr, is_volatile)
mlirlite.build_store(builder, arg_val, field_ptr, is_volatile)
# 返回指针(而非结构体值),赋值时由 coerce_to_type 按目标类型决定是否 load
return storage_ptr
# 普通结构体:先 store zeroinitializer 清零(确保未赋值字段为零)
zero: llvmlite.Value* = llvmlite.ConstZero(pool, struct_ty)
llvmlite.build_store(builder, zero, tmp, is_volatile)
zero: mlirlite.Value* = mlirlite.ConstZero(pool, struct_ty)
mlirlite.build_store(builder, zero, tmp, is_volatile)
# 应用默认值(显式参数会覆盖默认值)
self._apply_struct_defaults(pool, builder, mod, struct_ty, class_name, tmp, trans, is_volatile)
@@ -290,20 +290,20 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# fast-fail: 字段索引越界(用户传了多余参数)
VLogger.error(f"构造函数参数过多,字段索引越界: {class_name}", "HandlesExprCall")
continue
arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, fe.Ty)
arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, fe.Ty)
if arg_val is None:
# fast-fail: 参数翻译失败
VLogger.error(f"构造函数参数翻译失败: {class_name}", "HandlesExprCall")
continue
# GEP 到字段 ai
field_ptr: llvmlite.Value* = llvmlite.build_gep_struct(builder, struct_ty, fe.Ty, tmp, fe.Index)
field_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, fe.Ty, tmp, fe.Index)
if field_ptr is None:
# fast-fail: GEP 失败(struct_ty 与 fe.Ty 不匹配)
VLogger.error(f"构造函数字段 GEP 失败: {class_name}", "HandlesExprCall")
continue
# 类型转换并 store
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, fe.Ty, arg)
llvmlite.build_store(builder, arg_val, field_ptr, is_volatile)
mlirlite.build_store(builder, arg_val, field_ptr, is_volatile)
# 返回指针(而非结构体值),赋值时由 coerce_to_type 按目标类型决定是否 load
return tmp
@@ -328,15 +328,15 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# ============================================================
def _translate_renum_construct(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
class_name: str,
variant_name: str,
tag_value: int,
cargs: list[ast.AST*]*,
can: sizet,
trans: HT.Translator*,
is_volatile: int = 0) -> llvmlite.Value*:
is_volatile: int = 0) -> mlirlite.Value*:
"""构造 REnum 变体实例,返回指向 alloca 的指针
class_name: REnum 类名(如 "LLVMType")
@@ -359,20 +359,20 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
VLogger.error(f"REnum construct: type {class_name} not registered", "RENUM")
return None
renum_ty: llvmlite.LLVMType* = renum_entry.Ty
renum_ty: mlirlite.LLVMType* = renum_entry.Ty
if renum_ty is None:
return None
# alloca REnum 类型
# 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间)
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, renum_ty)
tmp: llvmlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, renum_ty)
tmp: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, renum_ty)
if tmp is None:
return llvmlite.ConstZero(pool, renum_ty)
return mlirlite.ConstZero(pool, renum_ty)
# 清零(确保未赋值的 payload 位置为零)
zero: llvmlite.Value* = llvmlite.ConstZero(pool, renum_ty)
llvmlite.build_store(builder, zero, tmp, is_volatile)
zero: mlirlite.Value* = mlirlite.ConstZero(pool, renum_ty)
mlirlite.build_store(builder, zero, tmp, is_volatile)
# 写入 __tag 字段(索引 0)
# tag 的类型取 __tag 的**字段声明类型**(FieldEntry.Ty),与 kind()
@@ -380,17 +380,17 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# 常量与 GEP 必须同类型,否则将来 __tag 换宽度会出现"i32 常量存进 i64 槽"
# 这种静默错配(此前常量硬编码 i32、GEP 用字段类型,两者口径不一致)。
tag_field: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(renum_entry, 0)
tag_field_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
tag_field_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
if tag_field is not None and tag_field.Ty is not None:
tag_field_ty = tag_field.Ty
tag_name_buf: str = pool.alloc(32)
if tag_name_buf is not None:
viperlib.snprintf(tag_name_buf, 32, "%d", tag_value)
tag_const: llvmlite.Value* = llvmlite.ConstInt(pool, tag_field_ty, tag_value,
tag_const: mlirlite.Value* = mlirlite.ConstInt(pool, tag_field_ty, tag_value,
tag_name_buf if tag_name_buf is not None else "0")
tag_ptr: llvmlite.Value* = llvmlite.build_gep_struct(builder, renum_ty, tag_field_ty, tmp, 0)
tag_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, renum_ty, tag_field_ty, tmp, 0)
if tag_ptr is not None:
llvmlite.build_store(builder, tag_const, tag_ptr, is_volatile)
mlirlite.build_store(builder, tag_const, tag_ptr, is_volatile)
# 写入 payload 字段(索引 1, 2, ... 对应 _p1, _p2, ...)
# 参数按位置顺序填充 payload,跳过 __tag(索引 0)
@@ -403,9 +403,9 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
if payload_idx >= renum_entry.FieldCount: break
pfe: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(renum_entry, payload_idx)
if pfe is None: continue
arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, pfe.Ty)
arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, pfe.Ty)
if arg_val is None: continue
payload_ptr: llvmlite.Value* = llvmlite.build_gep_struct(builder, renum_ty, pfe.Ty, tmp, payload_idx)
payload_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, renum_ty, pfe.Ty, tmp, payload_idx)
if payload_ptr is None: continue
# payload 槽位是 i32/i64(布局见 ClassGenEnum:{i32 __tag, _p1, _p2, ...}),
# 而变体成员可能是指针(Ptr.Pointee / Func.Ret / Array.ElemTy / Struct.Fields …)。
@@ -415,13 +415,13 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
if (self.Gen.ExprGenBase.is_ptr_type(arg_val.Ty) != 0
and self.Gen.ExprGenBase.is_ptr_type(pfe.Ty) == 0
and self.Gen.ExprGenBase.get_llvm_type_bits(pfe.Ty) != 0):
casted_arg: llvmlite.Value* = llvmlite.build_ptrtoint(builder, arg_val, pfe.Ty)
casted_arg: mlirlite.Value* = mlirlite.build_ptrtoint(builder, arg_val, pfe.Ty)
if casted_arg is None:
continue
arg_val = casted_arg
# 类型转换并 store(payload 位置可能是 i32 或 i64,按字段类型 coerce)
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, pfe.Ty, arg)
llvmlite.build_store(builder, arg_val, payload_ptr, is_volatile)
mlirlite.build_store(builder, arg_val, payload_ptr, is_volatile)
# 返回指针(与 _translate_struct_ctor 一致,赋值时由 coerce_to_type 决定是否 load)
return tmp
@@ -437,16 +437,16 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# ============================================================
def _translate_struct_ctor_kw(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
struct_ty: llvmlite.LLVMType*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
struct_ty: mlirlite.LLVMType*,
class_name: str,
cargs: list[ast.AST*]*,
can: sizet,
keywords: list[ast.AST*]*,
kw_count: sizet,
trans: HT.Translator*,
is_volatile: int = 0) -> llvmlite.Value*:
is_volatile: int = 0) -> mlirlite.Value*:
"""结构体构造函数(关键字参数版本)
is_volatile=1:`volatile S(x=1)` 构造——同 _translate_struct_ctor,
@@ -455,9 +455,9 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# 创建临时 alloca
# 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间)
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, struct_ty)
tmp: llvmlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, struct_ty)
tmp: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, struct_ty)
if tmp is None:
return llvmlite.ConstZero(pool, struct_ty)
return mlirlite.ConstZero(pool, struct_ty)
# 诊断节点:取第一个构造实参(有行号),供 _call_method_on_ptr 的
# fatal_error 显示构造调用行号(本函数无 cl 参数,实参节点最接近调用点)
diag_node_ct: ast.AST* = None
@@ -479,7 +479,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
if kw_init_lookup is not None:
viperlib.snprintf(kw_init_lookup, 128, "%s.__init__", class_name)
# 方案1: 检查当前模块的函数声明
kw_init_found: llvmlite.Function* = self.find_func_in_module(mod, kw_init_lookup)
kw_init_found: mlirlite.Function* = self.find_func_in_module(mod, kw_init_lookup)
if kw_init_found is not None:
is_oop = 1
if kw_entry is not None:
@@ -499,8 +499,8 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
"__before_init__", tmp, None, 0, trans, None, is_volatile)
else:
# 普通结构体:store zeroinitializer + 应用默认值
zero: llvmlite.Value* = llvmlite.ConstZero(pool, struct_ty)
llvmlite.build_store(builder, zero, tmp, is_volatile)
zero: mlirlite.Value* = mlirlite.ConstZero(pool, struct_ty)
mlirlite.build_store(builder, zero, tmp, is_volatile)
self._apply_struct_defaults(pool, builder, mod, struct_ty, class_name, tmp, trans, is_volatile)
# OOP 结构体且有 __init__:调用 __init__ 而非逐字段 store
@@ -520,7 +520,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
if is_oop != 0 and has_init_flag != 0:
# 有 __init__:构建参数数组并调用 __init__
storage_ptr: llvmlite.Value* = tmp
storage_ptr: mlirlite.Value* = tmp
# 如果有 __new__,调用 __new__ 获取实际存储指针
if has_new_flag != 0:
@@ -531,7 +531,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
for nai in range(can):
new_arg_node: ast.AST* = cargs.get(nai)
if new_arg_node is None: continue
new_av: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, new_arg_node, None, 0, trans)
new_av: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, new_arg_node, None, 0, trans)
if new_av is not None:
if new_arg_count < 32:
new_arg_vals[new_arg_count] = sizet(new_av)
@@ -540,12 +540,12 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
for nki in range(kw_count):
nkw: rawptr[ast.Keyword] = rawptr[ast.Keyword](keywords.get(nki))
if nkw is None or nkw.value is None: continue
nkw_av: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, nkw.value, None, 0, trans)
nkw_av: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, nkw.value, None, 0, trans)
if nkw_av is not None:
if new_arg_count < 32:
new_arg_vals[new_arg_count] = sizet(nkw_av)
new_arg_count += 1
new_ptr: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name, "__new__", tmp, new_arg_vals, new_arg_count, trans, diag_node_ct, is_volatile)
new_ptr: mlirlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name, "__new__", tmp, new_arg_vals, new_arg_count, trans, diag_node_ct, is_volatile)
if new_ptr is not None:
storage_ptr = new_ptr
# __new__ 只保证返回"实例存储指针",声明类型通常是
@@ -555,9 +555,9 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# 查不到类名,误报"跨模块调用 'parser.add_argument' 找不到模块 SHA1"。
# bitcast 只改类型层视图,运行时零开销(指针位不变)。
if new_ptr.Ty is not None:
nw_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, struct_ty)
nw_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, struct_ty)
if uint64(new_ptr.Ty) != uint64(nw_ty):
nw_bc: llvmlite.Value* = llvmlite.build_bitcast(builder, new_ptr, nw_ty)
nw_bc: mlirlite.Value* = mlirlite.build_bitcast(builder, new_ptr, nw_ty)
if nw_bc is not None:
storage_ptr = nw_bc
@@ -570,7 +570,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
for ai_init in range(can):
arg_node_init: ast.AST* = cargs.get(ai_init)
if arg_node_init is None: continue
av_init: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg_node_init, None, 0, trans)
av_init: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg_node_init, None, 0, trans)
if av_init is not None:
if init_arg_count < 32:
init_arg_vals[init_arg_count] = sizet(av_init)
@@ -579,7 +579,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
for ki_init in range(kw_count):
kw_init: rawptr[ast.Keyword] = rawptr[ast.Keyword](keywords.get(ki_init))
if kw_init is None or kw_init.value is None: continue
kw_av_init: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, kw_init.value, None, 0, trans)
kw_av_init: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, kw_init.value, None, 0, trans)
if kw_av_init is not None:
if init_arg_count < 32:
init_arg_vals[init_arg_count] = sizet(kw_av_init)
@@ -606,12 +606,12 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# 位置参数越界(字段表无对应项):fail-fast,绝不静默跳过
self.Gen.TypeGenErr.fatal_error(arg, f"结构体 '{class_name}' 位置参数越界(无对应字段)", "TypeError")
continue
arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, fe.Ty)
arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, fe.Ty)
if arg_val is None: continue
field_ptr: llvmlite.Value* = llvmlite.build_gep_struct(builder, struct_ty, fe.Ty, tmp, fe.Index)
field_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, fe.Ty, tmp, fe.Index)
if field_ptr is None: continue
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, fe.Ty, arg)
llvmlite.build_store(builder, arg_val, field_ptr, is_volatile)
mlirlite.build_store(builder, arg_val, field_ptr, is_volatile)
# 处理关键字参数(按字段名查找)
# SHA1 从 kw_entry 获取(规避跨模块同名 find_struct 找错)
@@ -626,12 +626,12 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# 关键字字段不存在:fail-fast(AttributeError),绝不静默跳过
self.Gen.TypeGenErr.fatal_error(kw, f"结构体 '{class_name}' 无字段 '{kw.arg}'", "AttributeError")
continue
kw_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, kw.value, None, 0, trans, fe.Ty)
kw_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, kw.value, None, 0, trans, fe.Ty)
if kw_val is None: continue
field_ptr: llvmlite.Value* = llvmlite.build_gep_struct(builder, struct_ty, fe.Ty, tmp, fe.Index)
field_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, fe.Ty, tmp, fe.Index)
if field_ptr is None: continue
kw_val = self.Gen.ExprGenBase.coerce_to_type(builder, kw_val, fe.Ty, kw.value)
llvmlite.build_store(builder, kw_val, field_ptr, is_volatile)
mlirlite.build_store(builder, kw_val, field_ptr, is_volatile)
# 返回指针(而非结构体值),赋值时由 coerce_to_type 按目标类型决定是否 load
return tmp
@@ -651,11 +651,11 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# ============================================================
def _translate_t_type_cast(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
val: llvmlite.Value*,
target_ty: llvmlite.LLVMType*,
builder: mlirlite.IRBuilder*,
val: mlirlite.Value*,
target_ty: mlirlite.LLVMType*,
src_node: ast.AST* = None,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""类型转换:根据参数类型和目标类型选择转换方式
整数 → 整数拓宽:拓宽方向由**源**的符号性决定(与 coerce_to_type 的
@@ -680,48 +680,48 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
elif val_bits < target_bits:
if val_bits == 1:
# i1 是布尔值(来自 icmp/fcmp),无符号语义,必须 zext
return llvmlite.build_zext(builder, val, target_ty)
return mlirlite.build_zext(builder, val, target_ty)
# 统一拓宽方向(与 coerce_to_type 的 _zext_or_sext_val 同源):i1/i8 → zext;源为无符号(t.CUIntXXT 强转 / 无符号注解变量)→ zext;否则 sext(默认有符号)。拓宽保持**源**的数值语义(有符号源拓宽即保号),与目标类型无关
if self.Gen.ExprGenBase._zext_or_sext_val(pool, val, src_node, trans) != 0:
return llvmlite.build_zext(builder, val, target_ty)
return llvmlite.build_sext(builder, val, target_ty)
return mlirlite.build_zext(builder, val, target_ty)
return mlirlite.build_sext(builder, val, target_ty)
else:
# 目标 i1(bool / t.CBool):显式强转 `t.CBool(x)` 与隐式落存储
# **同一判据** —— 真值归一化 `x != 0 → 1/0`(coerce_to_type 的同名
# 分支、CallGenDispatch 的 bool(x)、条件归一化三处一致),不是
# trunc(取最低位,会让 x=2 得 false 而 `if 2:` 为真)。
if target_bits == 1:
zero_tc: llvmlite.Value* = llvmlite.const_int(pool, val_bits, 0)
return llvmlite.build_icmp(builder, llvmlite.ICMP_NE, val, zero_tc)
return llvmlite.build_trunc(builder, val, target_ty)
zero_tc: mlirlite.Value* = mlirlite.const_int(pool, val_bits, 0)
return mlirlite.build_icmp(builder, mlirlite.ICMP_NE, val, zero_tc)
return mlirlite.build_trunc(builder, val, target_ty)
# 整数 → 浮点: sitofp
if val_bits != 0 and target_fbits != 0:
return llvmlite.build_si2fp(builder, val, target_ty)
return mlirlite.build_si2fp(builder, val, target_ty)
# 浮点 → 整数: fptosi
if val_fbits != 0 and target_bits != 0:
return llvmlite.build_fp2si(builder, val, target_ty)
return mlirlite.build_fp2si(builder, val, target_ty)
# 浮点 → 浮点: fpext/fptrunc
if val_fbits != 0 and target_fbits != 0:
if val_fbits == target_fbits:
return val
elif val_fbits < target_fbits:
return llvmlite.build_fpext(builder, val, target_ty)
return mlirlite.build_fpext(builder, val, target_ty)
else:
return llvmlite.build_fptrunc(builder, val, target_ty)
return mlirlite.build_fptrunc(builder, val, target_ty)
# 指针 → 整数: ptrtoint
if val_bits == 0 and val_fbits == 0 and target_bits != 0:
return llvmlite.build_ptrtoint(builder, val, target_ty)
return mlirlite.build_ptrtoint(builder, val, target_ty)
# 整数 → 指针: inttoptr(必须排除浮点 target,浮点 target_bits 也是 0)
if val_bits != 0 and target_bits == 0 and target_fbits == 0:
return llvmlite.build_inttoptr(builder, val, target_ty)
return mlirlite.build_inttoptr(builder, val, target_ty)
# 指针 → 指针: bitcast
return llvmlite.build_bitcast(builder, val, target_ty)
return mlirlite.build_bitcast(builder, val, target_ty)
# ============================================================
# 泛型实例化辅助:从 Subscript slice 提取类型实参名
# ============================================================
@@ -856,7 +856,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# 与泛型函数路径 ClassGenGeneric._infer_generic_func_type_arg 同口径。
fk_c: int = cl_f.func.kind()
if (fk_c == ast.ASTKind.Name or fk_c == ast.ASTKind.Attribute) and trans is not None:
cty_c: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
cty_c: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, cl_f.func, trans._imported_modules, trans._from_imports, trans, 0)
if cty_c is not None:
# 符号性从被调名源码文本取(LLVM 层 iN/uN 同形),复用注解侧
@@ -1137,12 +1137,12 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
return type_args_ctx
def _translate_generic_ctor_call(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
spec_name: str,
cl: ast.Call*,
trans: HT.Translator*,
tmpl_name: str = None) -> llvmlite.Value*:
tmpl_name: str = None) -> mlirlite.Value*:
"""泛型类构造调用: list[str](pool, 8) → __new__ + __before_init__ + __init__"""
if pool is None or builder is None or mod is None or spec_name is None or cl is None: return None
@@ -1151,14 +1151,14 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
if struct_entry is None:
self.Gen.TypeGenErr.fatal_error(cl, "泛型类构造调用: 特化类未注册")
return None
struct_ty: llvmlite.LLVMType* = struct_entry.Ty
struct_ty: mlirlite.LLVMType* = struct_entry.Ty
if struct_ty is None: return None
# 确保结构体定义在当前模块中可用(供 alloca 分配空间)
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, struct_ty)
# alloca tmp(self 指针)
tmp: llvmlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, struct_ty)
tmp: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, struct_ty)
if tmp is None: return None
# 翻译实参为参数指针数组(extra_args[slot] = Value 指针):位置实参 → 槽 0..can-1;关键字实参 → 按 __init__ 形参名定位槽位(与 _find_ctor_type_param_kw_arg_index 共用同一套形参遍历)。位置实参优先,关键字不可按出现顺序追加——乱序会串位
@@ -1193,7 +1193,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
break
arg_node: ast.AST* = cargs.get(ai)
if arg_node is not None:
arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg_node, None, 0, trans)
arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg_node, None, 0, trans)
if arg_val is not None:
extra_args[ai] = sizet(arg_val)
arg_filled[ai] = 1
@@ -1218,7 +1218,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# 该形参位已被位置实参/先前关键字占用:位置优先,本次跳过
# (先例 same as 上方:_translate_method_call 名匹配)
continue
kw_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, kw_slot.value, None, 0, trans)
kw_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, kw_slot.value, None, 0, trans)
if kw_val is None: continue
extra_args[sizet(slot_kw)] = sizet(kw_val)
arg_filled[sizet(slot_kw)] = 1
@@ -1243,12 +1243,12 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# 存储指针:默认用 alloca,如果有 __new__ 则用 __new__ 返回的指针
# __new__ 是可选的,仅当泛型类模板定义了 __new__ 方法时才调用
# (与 _translate_struct_ctor 保持一致,避免为无 __new__ 的类生成过度声明)
storage_ptr: llvmlite.Value* = tmp
storage_ptr: mlirlite.Value* = tmp
has_new_flag: int = 0
if struct_entry is not None:
has_new_flag = struct_entry.HasNew
if has_new_flag != 0:
new_ptr: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__new__", tmp, extra_args, arg_count, trans, None, gc_volatile)
new_ptr: mlirlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__new__", tmp, extra_args, arg_count, trans, None, gc_volatile)
if new_ptr is not None:
storage_ptr = new_ptr
# __new__ 只保证返回"实例存储指针",声明类型通常是
@@ -1258,9 +1258,9 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# 查不到类名,误报"跨模块调用 'parser.add_argument' 找不到模块 SHA1"。
# bitcast 只改类型层视图,运行时零开销(指针位不变)。
if new_ptr.Ty is not None:
nw_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, struct_ty)
nw_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, struct_ty)
if uint64(new_ptr.Ty) != uint64(nw_ty):
nw_bc: llvmlite.Value* = llvmlite.build_bitcast(builder, new_ptr, nw_ty)
nw_bc: mlirlite.Value* = mlirlite.build_bitcast(builder, new_ptr, nw_ty)
if nw_bc is not None:
storage_ptr = nw_bc
File diff suppressed because it is too large. Load diff
+69 -69
View File
@@ -2,7 +2,7 @@ import lib.core.Gen.GenTypes as GenTypes
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import viperlib
@@ -18,12 +18,12 @@ from . import CallGenBase
novirtual class CallGenFd(CallGenBase.CallGenBase):
"""FakeDuck / requires 字段注入 / provider 栈"""
def _translate_fakeduck_call(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
cls_name: str,
method_name: str,
cl: ast.Call*,
trans: HT.Translator*) -> llvmlite.Value*:
trans: HT.Translator*) -> mlirlite.Value*:
"""FakeDuck: str 变量方法调用解析到扩展类 _Type/_str,返回 call 结果或 None"""
if pool is None or builder is None or cl is None or trans is None: return None
if method_name is None: return None
@@ -35,7 +35,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase):
if fd_at is None or fd_at.value is None or fd_at.attr is None: return None
if string.strcmp(fd_at.attr, method_name) != 0: return None
# 候选扩展类:先 _Type(a.type_id())后 _str(a.upper() 等)
fd_func: llvmlite.Function* = None
fd_func: mlirlite.Function* = None
fd_cls: str = None
fd_key: str = pool.alloc(160)
if fd_key is not None:
@@ -50,7 +50,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase):
break
if fd_func is None or fd_cls is None: return None
# 扩展类结构体必须已注册(GEP/临时影子需要类型)
fd_sty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(fd_cls)
fd_sty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(fd_cls)
if fd_sty is None: return None
# 扩展类字段数:有字段(_str)时 self 用影子结构体指针;
# 无字段(_Type)时 self 用对象值 bitcast 到扩展类指针(对齐 TPC L2856-2876)
@@ -59,7 +59,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase):
if fd_entry_fd is not None and fd_entry_fd.FieldCount > 0:
fd_has_fields = 1
# self 参数:优先使用已有影子 {var}__meta__(fd2 创建,仅当扩展类有字段时)
fd_self: llvmlite.Value* = None
fd_self: mlirlite.Value* = None
if fd_at.value.kind() == ast.ASTKind.Name:
fd_onm: ast.Name* = ast.Name*(fd_at.value)
if fd_onm.id is not None:
@@ -67,7 +67,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase):
fd_mn: str = pool.alloc(256)
if fd_mn is not None:
viperlib.snprintf(fd_mn, 256, "%s__meta__", fd_onm.id)
fd_meta: llvmlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, fd_mn)
fd_meta: mlirlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, fd_mn)
if fd_meta is not None and fd_has_fields != 0:
fd_self = fd_meta
if fd_self is None:
@@ -77,31 +77,31 @@ novirtual class CallGenFd(CallGenBase.CallGenBase):
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, fd_sty)
fd_self = self.Gen.VarGen._alloca_at_entry(builder, fd_sty)
if fd_self is None: return None
fd_obj_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fd_at.value, None, 0, trans)
fd_obj_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fd_at.value, None, 0, trans)
if fd_obj_val is not None:
fd_dfe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(fd_sty, "__data__")
if fd_dfe is not None and fd_dfe.Ty is not None:
fd_dp: llvmlite.Value* = llvmlite.build_gep_struct(builder, fd_sty, fd_dfe.Ty, fd_self, fd_dfe.Index)
fd_dp: mlirlite.Value* = mlirlite.build_gep_struct(builder, fd_sty, fd_dfe.Ty, fd_self, fd_dfe.Index)
if fd_dp is not None:
llvmlite.build_store(builder, fd_obj_val, fd_dp)
mlirlite.build_store(builder, fd_obj_val, fd_dp)
fd_bfe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(fd_sty, "__mbuddy__")
if fd_bfe is not None and fd_bfe.Ty is not None:
fd_bp: llvmlite.Value* = llvmlite.build_gep_struct(builder, fd_sty, fd_bfe.Ty, fd_self, fd_bfe.Index)
fd_null: llvmlite.Value* = llvmlite.ConstNull(pool, fd_bfe.Ty, "null")
fd_bp: mlirlite.Value* = mlirlite.build_gep_struct(builder, fd_sty, fd_bfe.Ty, fd_self, fd_bfe.Index)
fd_null: mlirlite.Value* = mlirlite.ConstNull(pool, fd_bfe.Ty, "null")
if fd_bp is not None and fd_null is not None:
llvmlite.build_store(builder, fd_null, fd_bp)
mlirlite.build_store(builder, fd_null, fd_bp)
# FakeDuck: with 上下文自动注入 requires 字段(如 __mbuddy__)
self._inject_requires_fields(trans, pool, builder, mod, fd_self, fd_cls)
else:
# 无字段扩展类(_Type):对象值 bitcast 到扩展类指针
fd_obj_v: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fd_at.value, None, 0, trans)
fd_obj_v: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fd_at.value, None, 0, trans)
if fd_obj_v is None: return None
fd_self = llvmlite.build_bitcast(builder, fd_obj_v, llvmlite.Ptr(pool, fd_sty))
fd_self = mlirlite.build_bitcast(builder, fd_obj_v, mlirlite.Ptr(pool, fd_sty))
if fd_self is None: return None
# 构建参数链表: self → 其余参数
llvmlite.value_set_next(fd_self, None)
fd_head: llvmlite.Value* = fd_self
fd_tail: llvmlite.Value* = fd_self
mlirlite.value_set_next(fd_self, None)
fd_head: mlirlite.Value* = fd_self
fd_tail: mlirlite.Value* = fd_self
fd_args: list[ast.AST*]* = cl.args
fd_can: int = 0
if fd_args is not None:
@@ -109,7 +109,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase):
for fd_ai in range(fd_can):
fd_arg: ast.AST* = fd_args.get(fd_ai)
if fd_arg is not None:
fd_av: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fd_arg, None, 0, trans)
fd_av: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fd_arg, None, 0, trans)
# char 常量参数 → 单字符字符串(char 隐式转 str,
# 如 s1.split(','):',' 是 i32 值 44,传给 str 参数须先字符串化,
# 否则运行时 strlen/strncmp 解引用 44 崩溃)
@@ -122,14 +122,14 @@ novirtual class CallGenFd(CallGenBase.CallGenBase):
ch_buf[1] = '\0'
fd_av = self.Gen.ExprGenConst.create_global_string(builder, pool, mod, ch_buf, trans)
if fd_av is not None:
llvmlite.value_set_next(fd_av, None)
llvmlite.value_set_next(fd_tail, fd_av)
mlirlite.value_set_next(fd_av, None)
mlirlite.value_set_next(fd_tail, fd_av)
fd_tail = fd_av
# 返回类型与调用名(来自 find_func_in_module 命中的函数定义)
fd_ret_ty: llvmlite.LLVMType* = llvmlite.function_get_ret_ty(fd_func)
fd_ret_ty: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(fd_func)
if fd_ret_ty is None:
fd_ret_ty = llvmlite.Int32(pool)
fd_fname: str = llvmlite.function_get_name(fd_func)
fd_ret_ty = mlirlite.Int32(pool)
fd_fname: str = mlirlite.function_get_name(fd_func)
if fd_fname is None: return None
# 返回类型精确化:跨模块 declare 的 list[T] 特化返回类型可能被简化为 Ptr(i8),调用方变量 alloca 类型随之退化 → parts[0] 走字符下标路径而非 list 内联 __getitem__(printf %s 崩溃)。权威来源为定义模块 vpi(未命中回退 text.ll);仅当函数名确为 "{16hex}.{func}"(判定走唯一真源 GenApi.sha1_prefix_len)才提取模块 sha1
if GenApi.sha1_prefix_len(fd_fname) != 0:
@@ -137,13 +137,13 @@ novirtual class CallGenFd(CallGenBase.CallGenBase):
if fd_sha1 is not None:
string.strncpy(fd_sha1, fd_fname, 16)
fd_sha1[16] = '\0'
fd_exact: llvmlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, fd_sha1, fd_cls, method_name)
fd_exact: mlirlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, fd_sha1, fd_cls, method_name)
if fd_exact is None:
fd_exact = self._LookupMethodRetTyFromTextLL(pool, fd_sha1, fd_cls, method_name)
if fd_exact is not None:
fd_ret_ty = fd_exact
fd_total: int = 1 + fd_can
return llvmlite.build_call(builder, fd_fname, fd_head, fd_total, fd_ret_ty, 0)
return mlirlite.build_call(builder, fd_fname, fd_head, fd_total, fd_ret_ty, 0)
# ============================================================
# _inject_requires_fields - FakeDuck: with 上下文注入 requires 字段
#
@@ -158,9 +158,9 @@ novirtual class CallGenFd(CallGenBase.CallGenBase):
# ============================================================
def _inject_requires_fields(self, trans: HT.Translator*,
pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
meta_ptr: llvmlite.Value*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
meta_ptr: mlirlite.Value*,
class_name: str) -> int:
"""在 with 上下文注入 requires 字段,返回注入字段数"""
if trans is None or pool is None or builder is None or mod is None:
@@ -172,19 +172,19 @@ novirtual class CallGenFd(CallGenBase.CallGenBase):
# (Gen.functions.get('_find_provider') 不存在则跳过)——否则非 with
# 项目(如 HashTableTest 未 import _withcontent)也会为每个 _str(...)
# 构造发射 {sha1}._find_provider 调用 → ld.lld undefined symbol。
fd_fn_probe: llvmlite.Function* = self.find_func_in_module(mod, "_find_provider")
fd_fn_probe: mlirlite.Function* = self.find_func_in_module(mod, "_find_provider")
if fd_fn_probe is None: return 0
fd_fname: str = llvmlite.function_get_name(fd_fn_probe)
fd_fname: str = mlirlite.function_get_name(fd_fn_probe)
if fd_fname is None: return 0
cnt: int = self.Gen.ClassGenBase.class_meta_count(GenTypes.CLASS_META_REQUIRES, class_name)
if cnt <= 0: return 0
sty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(class_name)
sty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(class_name)
if sty is None: return 0
i8_ty_j: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ty_j: mlirlite.LLVMType* = mlirlite.Int8(pool)
if i8_ty_j is None: return 0
i8_ptr_ty_j: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty_j)
i8_ptr_ty_j: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_j)
if i8_ptr_ty_j is None: return 0
cur_func: llvmlite.Function* = trans._cur_func
cur_func: mlirlite.Function* = trans._cur_func
if cur_func is None: return 0
injected: int = 0
for ji in range(cnt):
@@ -193,16 +193,16 @@ novirtual class CallGenFd(CallGenBase.CallGenBase):
fe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(sty, fname)
if fe is None or fe.Ty is None: continue
# 参数:字段名字符串(i8*)
fd_fstr: llvmlite.Value* = self.Gen.ExprGenConst.create_global_string(builder, pool, mod, fname, trans)
fd_fstr: mlirlite.Value* = self.Gen.ExprGenConst.create_global_string(builder, pool, mod, fname, trans)
if fd_fstr is None: continue
llvmlite.value_set_next(fd_fstr, None)
mlirlite.value_set_next(fd_fstr, None)
self._ensure_method_declare(pool, mod, fd_fname, i8_ptr_ty_j, fd_fstr, 1)
fd_ptr: llvmlite.Value* = llvmlite.build_call(builder, fd_fname, fd_fstr, 1, i8_ptr_ty_j, 0)
fd_ptr: mlirlite.Value* = mlirlite.build_call(builder, fd_fname, fd_fstr, 1, i8_ptr_ty_j, 0)
if fd_ptr is None: continue
# 条件注入:ptr != NULL 才写入(保留用户手动设置的值)
fd_null: llvmlite.Value* = llvmlite.ConstNull(pool, i8_ptr_ty_j, "null")
fd_null: mlirlite.Value* = mlirlite.ConstNull(pool, i8_ptr_ty_j, "null")
if fd_null is None: continue
fd_cmp: llvmlite.Value* = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, fd_ptr, fd_null)
fd_cmp: mlirlite.Value* = mlirlite.build_icmp(builder, mlirlite.ICMP_NE, fd_ptr, fd_null)
if fd_cmp is None: continue
# 块名唯一化(create_block 不自动编号,同名 label 在文本 IR 中
# 冲突 → llc "Terminator found in the middle of a basic block")
@@ -211,20 +211,20 @@ novirtual class CallGenFd(CallGenBase.CallGenBase):
fd_bb_buf2: str = pool.alloc(64)
if fd_bb_buf2 is None: continue
viperlib.snprintf(fd_bb_buf2, 64, "fd.skip.%d", vtc2)
fd_skip_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, cur_func, fd_bb_buf2)
fd_skip_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, cur_func, fd_bb_buf2)
viperlib.snprintf(fd_bb_buf2, 64, "fd.inject.%d", vtc2)
fd_inject_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, cur_func, fd_bb_buf2)
fd_inject_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, cur_func, fd_bb_buf2)
if fd_skip_bb is None or fd_inject_bb is None: continue
llvmlite.build_cond_br(builder, fd_cmp, fd_inject_bb, fd_skip_bb)
mlirlite.build_cond_br(builder, fd_cmp, fd_inject_bb, fd_skip_bb)
# inject 块:bitcast + GEP + store,跳回 skip
llvmlite.position_at_end(builder, fd_inject_bb)
fd_cast: llvmlite.Value* = llvmlite.build_bitcast(builder, fd_ptr, fe.Ty)
mlirlite.position_at_end(builder, fd_inject_bb)
fd_cast: mlirlite.Value* = mlirlite.build_bitcast(builder, fd_ptr, fe.Ty)
if fd_cast is not None:
fd_fp: llvmlite.Value* = llvmlite.build_gep_struct(builder, sty, fe.Ty, meta_ptr, fe.Index)
if fd_fp is not None: llvmlite.build_store(builder, fd_cast, fd_fp)
llvmlite.build_br(builder, fd_skip_bb)
fd_fp: mlirlite.Value* = mlirlite.build_gep_struct(builder, sty, fe.Ty, meta_ptr, fe.Index)
if fd_fp is not None: mlirlite.build_store(builder, fd_cast, fd_fp)
mlirlite.build_br(builder, fd_skip_bb)
# skip 块:恢复 CurBlock,继续后续代码生成
llvmlite.position_at_end(builder, fd_skip_bb)
mlirlite.position_at_end(builder, fd_skip_bb)
injected += 1
return injected
# ============================================================
@@ -240,10 +240,10 @@ novirtual class CallGenFd(CallGenBase.CallGenBase):
# ============================================================
def _emit_provider_push(self, trans: HT.Translator*,
pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
cls_name: str,
ctx_val: llvmlite.Value*) -> int:
ctx_val: mlirlite.Value*) -> int:
"""生成 _push_provider(field, ctx_i8) 调用(每提供字段一次),返回字段数"""
if trans is None or pool is None or builder is None or mod is None: return 0
if cls_name is None or ctx_val is None: return 0
@@ -251,33 +251,33 @@ novirtual class CallGenFd(CallGenBase.CallGenBase):
if fd_pc <= 0: return 0
# _withcontent._push_provider(跨模块,同 _find_provider 的可见性守卫:
# 本模块未 import _withcontent 时跳过,避免 undefined symbol)
fd_pfn_probe: llvmlite.Function* = self.find_func_in_module(mod, "_push_provider")
fd_pfn_probe: mlirlite.Function* = self.find_func_in_module(mod, "_push_provider")
if fd_pfn_probe is None: return 0
fd_pfn: str = llvmlite.function_get_name(fd_pfn_probe)
fd_pfn: str = mlirlite.function_get_name(fd_pfn_probe)
if fd_pfn is None: return 0
i8_ty_p: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ty_p: mlirlite.LLVMType* = mlirlite.Int8(pool)
if i8_ty_p is None: return 0
i8_ptr_ty_p: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty_p)
i8_ptr_ty_p: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_p)
if i8_ptr_ty_p is None: return 0
ret_i32_p: llvmlite.LLVMType* = llvmlite.Int32(pool)
ret_i32_p: mlirlite.LLVMType* = mlirlite.Int32(pool)
if ret_i32_p is None: return 0
# ctx 值 bitcast 到 i8*(provider 栈存 void*)
fd_ctx_i8: llvmlite.Value* = llvmlite.build_bitcast(builder, ctx_val, i8_ptr_ty_p)
fd_ctx_i8: mlirlite.Value* = mlirlite.build_bitcast(builder, ctx_val, i8_ptr_ty_p)
if fd_ctx_i8 is None: return 0
for pi in range(fd_pc):
fname: str = self.Gen.ClassGenBase.class_meta_field_at(GenTypes.CLASS_META_PROVIDES, cls_name, pi)
if fname is None: continue
fd_fstr: llvmlite.Value* = self.Gen.ExprGenConst.create_global_string(builder, pool, mod, fname, trans)
fd_fstr: mlirlite.Value* = self.Gen.ExprGenConst.create_global_string(builder, pool, mod, fname, trans)
if fd_fstr is None: continue
llvmlite.value_set_next(fd_fstr, fd_ctx_i8)
llvmlite.value_set_next(fd_ctx_i8, None)
mlirlite.value_set_next(fd_fstr, fd_ctx_i8)
mlirlite.value_set_next(fd_ctx_i8, None)
self._ensure_method_declare(pool, mod, fd_pfn, ret_i32_p, fd_fstr, 2)
llvmlite.build_call(builder, fd_pfn, fd_fstr, 2, ret_i32_p, 0)
mlirlite.build_call(builder, fd_pfn, fd_fstr, 2, ret_i32_p, 0)
return fd_pc
def _emit_provider_pop(self, trans: HT.Translator*,
pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
cls_name: str) -> int:
"""生成 _pop_provider() 调用(每提供字段一次),返回字段数"""
if trans is None or pool is None or builder is None or mod is None: return 0
@@ -286,13 +286,13 @@ novirtual class CallGenFd(CallGenBase.CallGenBase):
if fd_pc <= 0: return 0
# _withcontent._pop_provider(跨模块,同 _find_provider 的可见性守卫:
# 本模块未 import _withcontent 时跳过,避免 undefined symbol)
fd_pon_probe: llvmlite.Function* = self.find_func_in_module(mod, "_pop_provider")
fd_pon_probe: mlirlite.Function* = self.find_func_in_module(mod, "_pop_provider")
if fd_pon_probe is None: return 0
fd_pon: str = llvmlite.function_get_name(fd_pon_probe)
fd_pon: str = mlirlite.function_get_name(fd_pon_probe)
if fd_pon is None: return 0
ret_i32_q: llvmlite.LLVMType* = llvmlite.Int32(pool)
ret_i32_q: mlirlite.LLVMType* = mlirlite.Int32(pool)
if ret_i32_q is None: return 0
self._ensure_method_declare(pool, mod, fd_pon, ret_i32_q, None, 0)
for _pi in range(fd_pc):
llvmlite.build_call(builder, fd_pon, None, 0, ret_i32_q, 0)
mlirlite.build_call(builder, fd_pon, None, 0, ret_i32_q, 0)
return fd_pc
+194 -194
View File
@@ -2,7 +2,7 @@ import lib.core.Gen.GenTypes as GenTypes
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdlib
@@ -122,16 +122,16 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
# EH 参数(%__eh_msg_out__/__eh_code_out__)由 translate_function_def/
# _translate_method 在含 raise 的函数签名末尾注入(main 除外)。
# ============================================================
def _func_has_eh_params(self, func: llvmlite.Function*) -> int:
def _func_has_eh_params(self, func: mlirlite.Function*) -> int:
"""返回 1=函数带 EH 输出参数 / 0=不带"""
if func is None:
return 0
cur_p: llvmlite.Param* = llvmlite.function_get_param_head(func)
cur_p: mlirlite.Param* = mlirlite.function_get_param_head(func)
while cur_p is not None:
pn: str = llvmlite.param_get_name(cur_p)
pn: str = mlirlite.param_get_name(cur_p)
if pn is not None and string.strcmp(pn, "%__eh_msg_out__") == 0:
return 1
cur_p = llvmlite.param_get_next(cur_p)
cur_p = mlirlite.param_get_next(cur_p)
return 0
# ============================================================
@@ -153,27 +153,27 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
# ============================================================
# ============================================================
def _emit_eh_guarded_call(self, builder: llvmlite.IRBuilder*,
def _emit_eh_guarded_call(self, builder: mlirlite.IRBuilder*,
pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
trans: HT.Translator*,
func: llvmlite.Function*,
func: mlirlite.Function*,
call_name: str,
head: llvmlite.Value*,
head: mlirlite.Value*,
count: int,
ret_ty: llvmlite.LLVMType*,
is_variadic: int) -> llvmlite.Value*:
ret_ty: mlirlite.LLVMType*,
is_variadic: int) -> mlirlite.Value*:
"""带 try-except EH 检测的函数调用,返回 call 结果(检查后位于 ok 块)"""
if trans is None or self._func_has_eh_params(func) == 0:
return llvmlite.build_call(builder, call_name, head, count, ret_ty, is_variadic)
return mlirlite.build_call(builder, call_name, head, count, ret_ty, is_variadic)
# ---- 1. 确定输出指针 ----
i8_ty_g: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty_g: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty_g)
i32_ty_g: llvmlite.LLVMType* = llvmlite.Int32(pool)
i8_ty_g: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty_g: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_g)
i32_ty_g: mlirlite.LLVMType* = mlirlite.Int32(pool)
if i8_ty_g is None or i8_ptr_ty_g is None or i32_ty_g is None:
return llvmlite.build_call(builder, call_name, head, count, ret_ty, is_variadic)
msg_ptr: llvmlite.Value* = None
code_ptr: llvmlite.Value* = None
return mlirlite.build_call(builder, call_name, head, count, ret_ty, is_variadic)
msg_ptr: mlirlite.Value* = None
code_ptr: mlirlite.Value* = None
if trans._eh_msg_ptr is not None and trans._eh_code_ptr is not None:
msg_ptr = trans._eh_msg_ptr
code_ptr = trans._eh_code_ptr
@@ -184,70 +184,70 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
msg_ptr = self.Gen.VarGen._alloca_at_entry(builder, i8_ptr_ty_g)
code_ptr = self.Gen.VarGen._alloca_at_entry(builder, i32_ty_g)
# ---- 2. 调用前清零 ----
null_msg_g: llvmlite.Value* = llvmlite.ConstNull(pool, i8_ptr_ty_g, "null")
zero_code_g: llvmlite.Value* = llvmlite.const_int32(pool, 0)
null_msg_g: mlirlite.Value* = mlirlite.ConstNull(pool, i8_ptr_ty_g, "null")
zero_code_g: mlirlite.Value* = mlirlite.const_int32(pool, 0)
if null_msg_g is not None:
llvmlite.build_store(builder, null_msg_g, msg_ptr)
mlirlite.build_store(builder, null_msg_g, msg_ptr)
if zero_code_g is not None:
llvmlite.build_store(builder, zero_code_g, code_ptr)
mlirlite.build_store(builder, zero_code_g, code_ptr)
# ---- 3. 追加实参(链表末尾 + count+2)----
msg_ptr.Next = code_ptr
code_ptr.Next = None
if head is None:
head = msg_ptr
else:
tail_g: llvmlite.Value* = head
tail_g: mlirlite.Value* = head
while tail_g.Next is not None:
tail_g = tail_g.Next
tail_g.Next = msg_ptr
count = count + 2
# ---- 4. 调用 + 检查 ----
result: llvmlite.Value* = llvmlite.build_call(builder, call_name, head, count, ret_ty, is_variadic)
cur_func_g: llvmlite.Function* = trans._cur_func
result: mlirlite.Value* = mlirlite.build_call(builder, call_name, head, count, ret_ty, is_variadic)
cur_func_g: mlirlite.Function* = trans._cur_func
if cur_func_g is None or null_msg_g is None: return result
msg_val_g: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty_g, msg_ptr)
msg_val_g: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty_g, msg_ptr)
if msg_val_g is None: return result
is_err_g: llvmlite.Value* = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, msg_val_g, null_msg_g)
is_err_g: mlirlite.Value* = mlirlite.build_icmp(builder, mlirlite.ICMP_NE, msg_val_g, null_msg_g)
if is_err_g is None: return result
lc_g: int = trans._label_counter
trans._label_counter = lc_g + 1
bb_buf_g: str = pool.alloc(64)
if bb_buf_g is None: return result
viperlib.snprintf(bb_buf_g, 64, "eh.err.%d", lc_g)
err_bb_g: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, cur_func_g, bb_buf_g)
err_bb_g: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, cur_func_g, bb_buf_g)
viperlib.snprintf(bb_buf_g, 64, "eh.ok.%d", lc_g)
ok_bb_g: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, cur_func_g, bb_buf_g)
ok_bb_g: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, cur_func_g, bb_buf_g)
if err_bb_g is None or ok_bb_g is None: return result
llvmlite.build_cond_br(builder, is_err_g, err_bb_g, ok_bb_g)
mlirlite.build_cond_br(builder, is_err_g, err_bb_g, ok_bb_g)
# err 块
llvmlite.position_at_end(builder, err_bb_g)
mlirlite.position_at_end(builder, err_bb_g)
if trans._eh_dispatch_bb is not None:
# try 内:异常已写入 try 的 alloca(code_ptr 即 try 的 alloca),
# 分支 DispatchBB 交给 except 链
llvmlite.build_br(builder, trans._eh_dispatch_bb)
mlirlite.build_br(builder, trans._eh_dispatch_bb)
else:
# 非 try:异常已写入本函数 out 参数(复用)或局部 alloca(吞掉),
# 仅返回默认值,由调用方检测本函数 out 参数
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
ret_ty_g2: llvmlite.LLVMType* = llvmlite.function_get_ret_ty(cur_func_g)
if mlirlite.builder_cur_block_is_terminated(builder) == 0:
ret_ty_g2: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(cur_func_g)
if ret_ty_g2 is not None:
match ret_ty_g2:
case llvmlite.LLVMType.Void():
llvmlite.build_ret_void(builder)
case llvmlite.LLVMType.Ptr(_pg):
nv_g: llvmlite.Value* = llvmlite.ConstNull(pool, ret_ty_g2, "null")
case mlirlite.LLVMType.Void():
mlirlite.build_ret_void(builder)
case mlirlite.LLVMType.Ptr(_pg):
nv_g: mlirlite.Value* = mlirlite.ConstNull(pool, ret_ty_g2, "null")
if nv_g is not None:
llvmlite.build_ret(builder, nv_g)
case llvmlite.LLVMType.Float(_fg):
zf_g: llvmlite.Value* = llvmlite.ConstFloat(pool, ret_ty_g2, 0.0)
mlirlite.build_ret(builder, nv_g)
case mlirlite.LLVMType.Float(_fg):
zf_g: mlirlite.Value* = mlirlite.ConstFloat(pool, ret_ty_g2, 0.0)
if zf_g is not None:
llvmlite.build_ret(builder, zf_g)
mlirlite.build_ret(builder, zf_g)
case _:
zv_g: llvmlite.Value* = llvmlite.ConstZero(pool, ret_ty_g2)
zv_g: mlirlite.Value* = mlirlite.ConstZero(pool, ret_ty_g2)
if zv_g is not None:
llvmlite.build_ret(builder, zv_g)
mlirlite.build_ret(builder, zv_g)
# ok 块:继续
llvmlite.position_at_end(builder, ok_bb_g)
mlirlite.position_at_end(builder, ok_bb_g)
return result
# ============================================================
@@ -264,38 +264,38 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
def _translate_isinstance(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
obj_node: ast.AST*,
cls_node: ast.AST*,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""isinstance(obj, Cls):运行时 vtable 子类集合比较,返回 i1"""
if obj_node is None or cls_node is None:
# 参数缺失即调用错误:fail-fast,绝不返回 True 掩盖
self.Gen.TypeGenErr.fatal_error(cls_node, "isinstance() 参数类型推断失败", "TypeError")
obj_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, obj_node, None, 0, trans)
obj_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, obj_node, None, 0, trans)
if obj_val is None or obj_val.Ty is None:
# obj 类型推断失败:fail-fast,绝不返回 True 掩盖
self.Gen.TypeGenErr.fatal_error(cls_node, "isinstance() 参数类型推断失败", "TypeError")
# 对象指针规整:二级指针(变量 alloca / 联合 Class|t.CPtr)先 load
obj_ptr: llvmlite.Value* = obj_val
obj_ptr: mlirlite.Value* = obj_val
match obj_val.Ty:
case llvmlite.LLVMType.Ptr(inner_ty):
case mlirlite.LLVMType.Ptr(inner_ty):
match inner_ty:
case llvmlite.LLVMType.Ptr(_):
loaded: llvmlite.Value* = llvmlite.build_load(builder, inner_ty, obj_val)
case mlirlite.LLVMType.Ptr(_):
loaded: mlirlite.Value* = mlirlite.build_load(builder, inner_ty, obj_val)
if loaded is not None:
obj_ptr = loaded
case _:
pass
obj_is_ptr: int = self.Gen.ExprGenBase.is_ptr_type(obj_ptr.Ty)
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i8_ptr_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ptr_ty)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
i8_ptr_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ptr_ty)
# 对象 vtable 指针惰性读取(首个 CVTable 类比较时执行一次)
vtable_ptr: llvmlite.Value* = None
vtable_ptr: mlirlite.Value* = None
vtable_ready: int = 0
res: llvmlite.Value* = None
res: mlirlite.Value* = None
cls_names: sizet* = self._extract_isinstance_class_names(pool, cls_node)
if cls_names is None:
# 类名提取失败:fail-fast,绝不返回 True 掩盖
@@ -308,17 +308,17 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
or self.Gen.StructGen.has_vtable_by_name(cn) == 0:
# NoVTable / 未知类 → 编译时静态判断(obj 静态类型 MRO)
st: int = self._isinstance_compile_time(pool, obj_ptr, cn)
c1: llvmlite.Value* = llvmlite.const_int(pool, 1, 1 if st > 0 else 0)
c1: mlirlite.Value* = mlirlite.const_int(pool, 1, 1 if st > 0 else 0)
if res is None:
res = c1
else:
res = llvmlite.build_or(builder, res, c1)
res = mlirlite.build_or(builder, res, c1)
elif obj_is_ptr != 0:
# CVTable → 运行时 vtable 比较(读对象头部 vtable 指针)
if vtable_ready == 0:
vtable_slot: llvmlite.Value* = llvmlite.build_bitcast(builder, obj_ptr, i8_ptr_ptr_ty)
vtable_slot: mlirlite.Value* = mlirlite.build_bitcast(builder, obj_ptr, i8_ptr_ptr_ty)
if vtable_slot is not None:
vtable_ptr = llvmlite.build_load(builder, i8_ptr_ty, vtable_slot)
vtable_ptr = mlirlite.build_load(builder, i8_ptr_ty, vtable_slot)
vtable_ready = 1
if vtable_ptr is not None:
subs: sizet* = self._collect_subclass_vtable_classes(pool, cn)
@@ -327,14 +327,14 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
while subs[k] != 0:
scn: str = rawptr(subs[k])
if scn is not None:
sub_i8: llvmlite.Value* = self._make_vtable_ref_i8(pool, builder, mod, scn, trans)
sub_i8: mlirlite.Value* = self._make_vtable_ref_i8(pool, builder, mod, scn, trans)
if sub_i8 is not None:
cmp: llvmlite.Value* = llvmlite.build_icmp(builder, llvmlite.ICMP_EQ, vtable_ptr, sub_i8)
cmp: mlirlite.Value* = mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, vtable_ptr, sub_i8)
if cmp is not None:
if res is None:
res = cmp
else:
res = llvmlite.build_or(builder, res, cmp)
res = mlirlite.build_or(builder, res, cmp)
k += 1
ci += 1
if res is None:
@@ -457,15 +457,15 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
def _make_vtable_ref_i8(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
class_name: str,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""构造类 vtable 地址引用(i8*):本模块已定义直接引用,跨模块声明 external"""
if class_name is None:
return None
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
buf: str = pool.alloc(256)
if buf is None:
return None
@@ -484,32 +484,32 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
return None
# vtable 名含 sha1 点号前缀,一律 @"..." 引号形式
viperlib.snprintf(ref_name, 256, "@\"%s\"", mangled)
gv: llvmlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(mod, mangled)
ref_ty: llvmlite.LLVMType* = None
gv: mlirlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(mod, mangled)
ref_ty: mlirlite.LLVMType* = None
if gv is not None:
# 本模块已定义 vtable(constant {i8* x N})→ 引用类型 Ptr(struct)
ref_ty = llvmlite.Ptr(pool, gv.Ty)
ref_ty = mlirlite.Ptr(pool, gv.Ty)
else:
# 跨模块:声明 @mangled = external global i8*,引用类型 i8**
gv2: llvmlite.GlobalVariable* = llvmlite.new_global_variable(pool, mangled, i8_ptr_ty)
gv2: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, mangled, i8_ptr_ty)
if gv2 is None:
return None
llvmlite.module_add_global(mod, gv2)
ref_ty = llvmlite.Ptr(pool, i8_ptr_ty)
ref: llvmlite.Value* = llvmlite.SSAValue(pool, ref_ty, ref_name)
mlirlite.module_add_global(mod, gv2)
ref_ty = mlirlite.Ptr(pool, i8_ptr_ty)
ref: mlirlite.Value* = mlirlite.SSAValue(pool, ref_ty, ref_name)
if ref is None:
return None
return llvmlite.build_bitcast(builder, ref, i8_ptr_ty)
return mlirlite.build_bitcast(builder, ref, i8_ptr_ty)
def _isinstance_compile_time(self, pool: memhub.MemBuddy*,
obj_ptr: llvmlite.Value*,
obj_ptr: mlirlite.Value*,
class_name: str) -> int:
"""编译时静态判断:obj 静态类型 == class_name 或 class_name 在其 MRO 中"""
if obj_ptr is None or obj_ptr.Ty is None or class_name is None:
return 0
match obj_ptr.Ty:
case llvmlite.LLVMType.Ptr(obj_struct_ty):
case mlirlite.LLVMType.Ptr(obj_struct_ty):
sname: str = self.Gen.StructGen.get_class_name_by_type(pool, obj_struct_ty)
if sname is not None:
if string.strcmp(sname, class_name) == 0:
@@ -535,59 +535,59 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
def translate_closure_call(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
closure_alloca: llvmlite.Value*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
closure_alloca: mlirlite.Value*,
cargs: list[ast.AST*]*,
can: sizet,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""通过闭包指针间接调用(支持带参 lambda:i32(i8*, args...))"""
if builder is None or closure_alloca is None:
return None
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
# 1. 加载闭包指针 (i8*)
closure_ptr: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty, closure_alloca)
closure_ptr: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty, closure_alloca)
if closure_ptr is None:
return None
# 2. 加载 fn_ptr (offset 0): bitcast to i8**, load i8*
fn_ptr_addr: llvmlite.Value* = llvmlite.build_bitcast(builder, closure_ptr, llvmlite.Ptr(pool, i8_ptr_ty))
fn_ptr_addr: mlirlite.Value* = mlirlite.build_bitcast(builder, closure_ptr, mlirlite.Ptr(pool, i8_ptr_ty))
if fn_ptr_addr is None:
return None
fn_raw: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty, fn_ptr_addr)
fn_raw: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty, fn_ptr_addr)
if fn_raw is None:
return None
# 3. 加载 env_ptr (offset 8): GEP i8, closure, 8; load i8*
eight_val: llvmlite.Value* = llvmlite.const_int32(pool, 8)
env_addr: llvmlite.Value* = llvmlite.build_gep(builder, i8_ty, closure_ptr, eight_val)
eight_val: mlirlite.Value* = mlirlite.const_int32(pool, 8)
env_addr: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, closure_ptr, eight_val)
if env_addr is None:
return None
env_ptr: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty, env_addr)
env_ptr: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty, env_addr)
if env_ptr is None:
return None
# 4. 构建参数:env 头 + 实参尾(带参 lambda 时翻译实参)
total_args: int = 1
arg_head: llvmlite.Value* = env_ptr
arg_tail: llvmlite.Value* = env_ptr
param_node: llvmlite.ParamNode* = llvmlite.new_param_node(pool, i8_ptr_ty)
pn_tail: llvmlite.ParamNode* = param_node
arg_head: mlirlite.Value* = env_ptr
arg_tail: mlirlite.Value* = env_ptr
param_node: mlirlite.ParamNode* = mlirlite.new_param_node(pool, i8_ptr_ty)
pn_tail: mlirlite.ParamNode* = param_node
if can > 0 and cargs is not None and trans is not None:
for ai in range(can):
arg: ast.AST* = cargs.get(ai)
if arg is None: continue
arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans)
arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans)
if arg_val is None or arg_val.Ty is None: continue
arg_val.Next = None
if arg_tail is not None:
arg_tail.Next = arg_val
arg_tail = arg_val
pn_new: llvmlite.ParamNode* = llvmlite.new_param_node(pool, arg_val.Ty)
pn_new: mlirlite.ParamNode* = mlirlite.new_param_node(pool, arg_val.Ty)
if pn_new is not None:
pn_tail.Next = pn_new
pn_tail = pn_new
@@ -596,26 +596,26 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
env_ptr.Next = None
# 5. bitcast fn_raw 到函数指针类型 i32(i8*, [args...])*
func_ty: llvmlite.LLVMType* = llvmlite.Func(pool, i32_ty, param_node, total_args)
func_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, func_ty)
fn_typed: llvmlite.Value* = llvmlite.build_bitcast(builder, fn_raw, func_ptr_ty)
func_ty: mlirlite.LLVMType* = mlirlite.Func(pool, i32_ty, param_node, total_args)
func_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, func_ty)
fn_typed: mlirlite.Value* = mlirlite.build_bitcast(builder, fn_raw, func_ptr_ty)
if fn_typed is None:
return None
# 6. 间接调用: call i32 %fn_typed(env, args...)
return llvmlite.build_call_indirect(builder, fn_typed, arg_head, total_args, i32_ty)
return mlirlite.build_call_indirect(builder, fn_typed, arg_head, total_args, i32_ty)
def _is_func_ptr_alloca(self, alloca: llvmlite.Value*) -> int:
def _is_func_ptr_alloca(self, alloca: mlirlite.Value*) -> int:
"""判断 alloca 是否为函数指针变量(类型 Ptr(Ptr(i8))),1=是 / 0=否"""
if alloca is None or alloca.Ty is None:
return 0
if self.Gen.ExprGenBase.is_ptr_type(alloca.Ty) == 0:
return 0
pointee: llvmlite.LLVMType* = alloca.Ty.Pointee
pointee: mlirlite.LLVMType* = alloca.Ty.Pointee
if pointee is None or self.Gen.ExprGenBase.is_ptr_type(pointee) == 0:
return 0
inner: llvmlite.LLVMType* = pointee.Pointee
inner: mlirlite.LLVMType* = pointee.Pointee
if inner is None or self.Gen.ExprGenBase.is_ptr_type(inner) != 0:
return 0
return 1
@@ -666,7 +666,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
def _func_ptr_sig_fatal(self, pool: memhub.MemBuddy*,
node: ast.AST*, name: str,
ret_ty: llvmlite.LLVMType*,
ret_ty: mlirlite.LLVMType*,
reason: str) -> None:
"""函数指针签名登记失败 → 编译期报错(文案含变量名/返回类型/上限/处置建议)
@@ -681,7 +681,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
if ret_ty is not None:
typed_buf: str = pool.alloc(96)
if typed_buf is not None:
llvmlite.TypePrint(typed_buf, 96, ret_ty, pool)
mlirlite.TypePrint(typed_buf, 96, ret_ty, pool)
if typed_buf[0] != '\0':
ret_str = typed_buf
msg_buf: str = pool.alloc(1024)
@@ -699,7 +699,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
self.Gen.TypeGenErr.fatal_error(node, "函数指针签名表登记失败(签名表已满或变量名冲突)", "TypeError")
def register_func_ptr_sig(self, pool: memhub.MemBuddy*, name: str,
ret_ty: llvmlite.LLVMType*,
ret_ty: mlirlite.LLVMType*,
node: ast.AST* = None) -> int:
"""注册函数指针变量的返回类型签名,0=成功(含幂等命中)/ 1=失败(已报错终止)
@@ -723,7 +723,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
for i in range(self.FuncptrCount):
idx_hit: sizet = sizet(i) * 64
if string.strcmp(self.FuncptrNames + idx_hit, name) == 0:
prev_ret: llvmlite.LLVMType* = (llvmlite.LLVMType*)(self.FuncptrRets[i])
prev_ret: mlirlite.LLVMType* = (mlirlite.LLVMType*)(self.FuncptrRets[i])
if prev_ret is not None and self.Gen.AssignGen._stg_ty_equal(pool, prev_ret, ret_ty) != 0:
return 0
self._func_ptr_sig_fatal(pool, node, name, ret_ty, "该名字已按另一种返回类型登记过")
@@ -736,7 +736,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
string.strncpy(self.FuncptrNames + idx, name, 63)
# ret_ty 是调用方 pool 分配的裸 LLVMType,1a 每文件 reset 后悬空;
# 深拷贝到 perm_pool(lookup_func_ptr_ret 跨文件读取)
ret_copy_fp: llvmlite.LLVMType* = llvmlite.DeepCopyType(CompilerFactory.factory.PermPool, ret_ty)
ret_copy_fp: mlirlite.LLVMType* = mlirlite.DeepCopyType(CompilerFactory.factory.PermPool, ret_ty)
if ret_copy_fp is not None:
self.FuncptrRets[self.FuncptrCount] = uint64(ret_copy_fp)
else:
@@ -745,45 +745,45 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
return 0
def lookup_func_ptr_ret(self, name: str) -> llvmlite.LLVMType*:
def lookup_func_ptr_ret(self, name: str) -> mlirlite.LLVMType*:
"""查函数指针变量的返回类型,None=未注册(调用时默认 i32)"""
if name is None or self.FuncptrNames is None:
return None
for i in range(self.FuncptrCount):
idx: sizet = sizet(i) * 64
if string.strcmp(self.FuncptrNames + idx, name) == 0:
return (llvmlite.LLVMType*)(self.FuncptrRets[i])
return (mlirlite.LLVMType*)(self.FuncptrRets[i])
return None
def _translate_func_ptr_call(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
fp_alloca: llvmlite.Value*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
fp_alloca: mlirlite.Value*,
func_name: str,
cargs: list[ast.AST*]*,
can: sizet,
trans: HT.Translator*) -> llvmlite.Value*:
trans: HT.Translator*) -> mlirlite.Value*:
"""函数指针变量间接调用,返回结果 Value"""
if builder is None or fp_alloca is None:
return None
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
# 1. load 函数地址 (i8*)
fn_i8: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty, fp_alloca)
fn_i8: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty, fp_alloca)
if fn_i8 is None: return None
# 2. 翻译实参并链接为 Value 链表
head: llvmlite.Value* = None
tail: llvmlite.Value* = None
head: mlirlite.Value* = None
tail: mlirlite.Value* = None
arg_count: int = 0
ai: sizet
for ai in range(can):
arg: ast.AST* = cargs.get(ai)
if arg is not None:
arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans)
arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans)
if arg_val is not None:
arg_val.Next = None
if head is None:
@@ -794,41 +794,41 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
arg_count += 1
# 3. 按实参类型 + 注册的返回类型构造签名(未注册即 t.Callable 注解缺失,fail-fast)
ret_ty: llvmlite.LLVMType* = self.lookup_func_ptr_ret(func_name)
ret_ty: mlirlite.LLVMType* = self.lookup_func_ptr_ret(func_name)
if ret_ty is None:
self.Gen.TypeGenErr.fatal_error(None, f"函数指针变量 '{func_name}' 的返回类型未注册(t.Callable 注解缺失)", "TypeError")
ret_ty = i32_ty
fp_first: llvmlite.ParamNode* = None
fp_prev: llvmlite.ParamNode* = None
cur_v: llvmlite.Value* = head
fp_first: mlirlite.ParamNode* = None
fp_prev: mlirlite.ParamNode* = None
cur_v: mlirlite.Value* = head
for pi in range(arg_count):
if cur_v is None:
break
cur_ty: llvmlite.LLVMType* = llvmlite.value_get_ty(cur_v)
pn2: llvmlite.ParamNode* = llvmlite.new_param_node(pool, cur_ty)
cur_ty: mlirlite.LLVMType* = mlirlite.value_get_ty(cur_v)
pn2: mlirlite.ParamNode* = mlirlite.new_param_node(pool, cur_ty)
if pn2 is not None:
if fp_first is None:
fp_first = pn2
if fp_prev is not None:
llvmlite.paramnode_set_next(fp_prev, pn2)
mlirlite.paramnode_set_next(fp_prev, pn2)
fp_prev = pn2
cur_v = llvmlite.value_get_next(cur_v)
cur_v = mlirlite.value_get_next(cur_v)
func_ty: llvmlite.LLVMType* = llvmlite.Func(pool, ret_ty, fp_first, arg_count)
func_ty: mlirlite.LLVMType* = mlirlite.Func(pool, ret_ty, fp_first, arg_count)
if func_ty is None:
return None
func_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, func_ty)
func_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, func_ty)
# 4. bitcast i8* → 函数指针类型,间接调用
fn_typed: llvmlite.Value* = llvmlite.build_bitcast(builder, fn_i8, func_ptr_ty)
fn_typed: mlirlite.Value* = mlirlite.build_bitcast(builder, fn_i8, func_ptr_ty)
if fn_typed is None:
return None
return llvmlite.build_call_indirect(builder, fn_typed, head, arg_count, ret_ty)
return mlirlite.build_call_indirect(builder, fn_typed, head, arg_count, ret_ty)
def translate_printf_call(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
cl: ast.Call*,
trans: HT.Translator* = None) -> None:
"""翻译 printf 调用(特殊处理格式字符串)"""
@@ -849,17 +849,17 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
if fmt_str is None: return
fmt_ptr: llvmlite.Value* = self.Gen.ExprGenConst.create_global_string(builder, pool, mod, fmt_str, trans)
fmt_ptr: mlirlite.Value* = self.Gen.ExprGenConst.create_global_string(builder, pool, mod, fmt_str, trans)
if fmt_ptr is None: return
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
# 翻译额外参数并链接
prev: llvmlite.Value* = fmt_ptr
prev: mlirlite.Value* = fmt_ptr
for ai in range(1, can):
arg: ast.AST* = cargs.get(ai)
if arg is not None:
arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans)
arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans)
if arg_val is not None:
# C ABI integer promotion: i8/i16 → i32(printf 变参函数要求)
arg_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(arg_val.Ty)
@@ -868,7 +868,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
# C ABI float promotion: float → double(printf 变参函数要求)
arg_fbits: int = self.Gen.ExprGenBase.get_llvm_float_bits(arg_val.Ty)
if arg_fbits != 0 and arg_fbits < 64:
double_ty: llvmlite.LLVMType* = llvmlite.Double(pool)
double_ty: mlirlite.LLVMType* = mlirlite.Double(pool)
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, double_ty, arg)
arg_val.Next = None
prev.Next = arg_val
@@ -877,12 +877,12 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
# is_variadic=1: 生成带显式函数类型签名的 call(如 call i32 (i8*, ...) @printf),
# 让 llc 识别为 variadic 调用,生成正确的 Win64 ABI 代码(浮点参数同时传 XMM 和整数寄存器)
llvmlite.build_call(builder, "printf", fmt_ptr, can, i32_ty, 1)
mlirlite.build_call(builder, "printf", fmt_ptr, can, i32_ty, 1)
def translate_print_call(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
cl: ast.Call*,
trans: HT.Translator* = None) -> None:
"""翻译 print 调用(类型感知格式化 + 默认换行)"""
@@ -896,19 +896,19 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
return
fmt_buf[0] = '\0'
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i64_ty: llvmlite.LLVMType* = llvmlite.Int64(pool)
dbl_ty: llvmlite.LLVMType* = llvmlite.Double(pool)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool)
dbl_ty: mlirlite.LLVMType* = mlirlite.Double(pool)
can: sizet = len(cargs)
arg_head: llvmlite.Value* = None
arg_tail: llvmlite.Value* = None
arg_head: mlirlite.Value* = None
arg_tail: mlirlite.Value* = None
arg_count: int = 1 # 格式串本身是第 1 个 printf 参数
for ai in range(can):
arg: ast.AST* = cargs.get(ai)
if arg is None: continue
arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans)
arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans)
if arg_val is None or arg_val.Ty is None:
# fail-fast:print 参数翻译失败必须终止编译,绝不在格式串写
# 误导为数据问题而非编译器 bug。
@@ -917,7 +917,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
return
# 对象定义了 __str__ → 用其返回的字符串(i8*)按 %s 打印(对齐 TPC)
str_ov_pr: llvmlite.Value* = self.Gen.ExprGenOps._try_named_dunder(pool, builder, mod, arg_val, "__str__", trans)
str_ov_pr: mlirlite.Value* = self.Gen.ExprGenOps._try_named_dunder(pool, builder, mod, arg_val, "__str__", trans)
if str_ov_pr is not None:
arg_val = str_ov_pr
@@ -925,17 +925,17 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
# translate_value 会 load 出数组值([N x T]),print 无法格式化;
# 按数组退化语义取数组 alloca 地址——字符数组 → %s(打印字符串内容),
# 其他元素类型 → 0x%llx(打印数组地址)。
array_ptr: llvmlite.Value* = None
array_ptr: mlirlite.Value* = None
array_elem_bits: int = 0
if arg.kind() == ast.ASTKind.Name and trans is not None:
anm: ast.Name* = ast.Name*(arg)
if anm.id is not None:
arr_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, anm.id)
arr_alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, anm.id)
if arr_alloca is not None and arr_alloca.Ty is not None and self.Gen.ExprGenBase.is_ptr_type(arr_alloca.Ty) != 0:
arr_pointee: llvmlite.LLVMType* = arr_alloca.Ty.Pointee
arr_pointee: mlirlite.LLVMType* = arr_alloca.Ty.Pointee
if arr_pointee is not None:
match arr_pointee:
case llvmlite.LLVMType.Array(arr_et, arr_n):
case mlirlite.LLVMType.Array(arr_et, arr_n):
array_ptr = arr_alloca
array_elem_bits = self.Gen.ExprGenBase.get_llvm_type_bits(arr_et)
case _:
@@ -949,30 +949,30 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
if array_ptr is not None:
# 数组退化:字符数组 → %s(bitcast [N x i8]* 到 i8*);其他 → 0x%llx
if array_elem_bits == 8:
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
token = "%s"
arg_val = llvmlite.build_bitcast(builder, array_ptr, i8_ptr_ty)
arg_val = mlirlite.build_bitcast(builder, array_ptr, i8_ptr_ty)
else:
token = "0x%llx"
arg_val = llvmlite.build_ptrtoint(builder, array_ptr, i64_ty)
arg_val = mlirlite.build_ptrtoint(builder, array_ptr, i64_ty)
elif self.Gen.ExprGenBase.is_ptr_type(arg_val.Ty) != 0:
# i8*(str/bytes)→ %s;其他指针 → 0x%llx
pointee: llvmlite.LLVMType* = arg_val.Ty.Pointee
pointee: mlirlite.LLVMType* = arg_val.Ty.Pointee
if pointee is not None and self.Gen.ExprGenBase.get_llvm_type_bits(pointee) == 8:
token = "%s"
else:
token = "0x%llx"
arg_val = llvmlite.build_ptrtoint(builder, arg_val, i64_ty)
arg_val = mlirlite.build_ptrtoint(builder, arg_val, i64_ty)
elif arg_bits != 0:
if arg_bits == 1:
token = "%d"
arg_val = llvmlite.build_zext(builder, arg_val, i32_ty)
arg_val = mlirlite.build_zext(builder, arg_val, i32_ty)
elif arg_bits == 8:
token = "%d"
arg_val = llvmlite.build_sext(builder, arg_val, i32_ty)
arg_val = mlirlite.build_sext(builder, arg_val, i32_ty)
elif arg_bits == 16:
token = "%d"
arg_val = llvmlite.build_sext(builder, arg_val, i32_ty)
arg_val = mlirlite.build_sext(builder, arg_val, i32_ty)
elif arg_bits == 32:
token = "%d"
else:
@@ -980,7 +980,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
elif arg_fbits != 0:
token = "%f"
if arg_fbits < 64:
arg_val = llvmlite.build_fpext(builder, arg_val, dbl_ty)
arg_val = mlirlite.build_fpext(builder, arg_val, dbl_ty)
else:
# 结构体值/数组/函数等 → "(unknown)",不传参
token = "(unknown)"
@@ -1003,12 +1003,12 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
if string.strlen(fmt_buf) < FMT_BUF_SIZE - 2:
viperlib.snprintf(fmt_buf + string.strlen(fmt_buf), 2, "\n")
fmt_ptr: llvmlite.Value* = self.Gen.ExprGenConst.create_global_string(builder, pool, mod, fmt_buf, trans)
fmt_ptr: mlirlite.Value* = self.Gen.ExprGenConst.create_global_string(builder, pool, mod, fmt_buf, trans)
stdlib.free(fmt_buf)
if fmt_ptr is None: return
fmt_ptr.Next = arg_head
# is_variadic=1: 带显式函数类型签名(C ABI 变参调用)
llvmlite.build_call(builder, "printf", fmt_ptr, arg_count, i32_ty, 1)
mlirlite.build_call(builder, "printf", fmt_ptr, arg_count, i32_ty, 1)
def init_func_table(self, pool: memhub.MemBuddy*, max_count: int) -> GenTypes.FuncEntry*:
@@ -1023,7 +1023,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
def find_func_in_table(self, funcs: GenTypes.FuncEntry*,
func_count: int,
name: str,
owner_sha1: str = None) -> llvmlite.Function*:
owner_sha1: str = None) -> mlirlite.Function*:
"""在函数表中按名称查找,返回 Function 指针或 None
owner_sha1: 当前模块 SHA1。非 None 时"本模块函数优先"——表里同名条目
@@ -1069,7 +1069,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
if fallback_entry is None:
fallback_entry = entry
if entry.Func is not None and owner_sha1 is not None:
fn_nm_o: str = llvmlite.function_get_name(entry.Func)
fn_nm_o: str = mlirlite.function_get_name(entry.Func)
if fn_nm_o is not None:
if string.strncmp(fn_nm_o, owner_sha1, 16) == 0 and fn_nm_o[16] == '.':
return entry.Func
@@ -1081,7 +1081,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
def add_func_to_table(self, funcs: GenTypes.FuncEntry*,
func_count: int,
name: str,
func: llvmlite.Function*,
func: mlirlite.Function*,
max_count: int,
defaults: t.CPtr = None,
default_count: int = 0,
@@ -1144,7 +1144,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
return 1
def _register_global_func(self, name: str, func: llvmlite.Function*,
def _register_global_func(self, name: str, func: mlirlite.Function*,
pool: memhub.MemBuddy* = None) -> int:
"""注册函数到全局表(已存在则跳过),返回 0 成功
@@ -1189,10 +1189,10 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
def update_global_func_spec(self, name: str,
func: llvmlite.Function*) -> int:
func: mlirlite.Function*) -> int:
"""更新全局函数表的 Spec(在函数参数全部添加完成后调用)
调用时机:add_func_to_table 注册后、llvmlite.add_param 全部执行完。
调用时机:add_func_to_table 注册后、mlirlite.add_param 全部执行完。
用 NewTypeFunc 构造整签名 Spec(PermPool 驻留,跨 1b reset 安全),
供 vtable 生成在 func 被 1b reset 后经 SpecToLLVMText 派生类型文本。
"""
@@ -1205,39 +1205,39 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
return 0
# _build_func_spec:由函数对象构造整签名 TypeSpec(S3 条目双写)——Kind=TS_FUNC,含 Ret + 形参 Spec 数组 + ParamCount + IsVarArg,必须在形参全部 add_param 完成后调用。参数沿 function_get_param_head 的 Param 链表两遍遍历(先计数再填充,llvmlite 无按下标取参且无法预知长度)。与 TSpec.SpecFromLLVMType 的 Func 分支不同:后者不含变参信息(恒置 IsVarArg=0),故此处直接用 NewTypeFunc(..., func.IsVarArg)。失败返回 None,调用方保留 None 不造伪 spec
def _build_func_spec(self, func: llvmlite.Function*) -> TSpec.TypeSpec*:
# _build_func_spec:由函数对象构造整签名 TypeSpec(S3 条目双写)——Kind=TS_FUNC,含 Ret + 形参 Spec 数组 + ParamCount + IsVarArg,必须在形参全部 add_param 完成后调用。参数沿 function_get_param_head 的 Param 链表两遍遍历(先计数再填充,mlirlite 无按下标取参且无法预知长度)。与 TSpec.SpecFromLLVMType 的 Func 分支不同:后者不含变参信息(恒置 IsVarArg=0),故此处直接用 NewTypeFunc(..., func.IsVarArg)。失败返回 None,调用方保留 None 不造伪 spec
def _build_func_spec(self, func: mlirlite.Function*) -> TSpec.TypeSpec*:
"""由函数对象构造整签名 TypeSpec,失败返回 None"""
if func is None: return None
arena: TSpec.TypeSpecArena* = self.Gen.TypeGenBase.ensure_spec_arena()
if arena is None: return None
ret_s: TSpec.TypeSpec* = TSpec.SpecFromLLVMType(arena, llvmlite.function_get_ret_ty(func))
ret_s: TSpec.TypeSpec* = TSpec.SpecFromLLVMType(arena, mlirlite.function_get_ret_ty(func))
if ret_s is None: return None
# 第一遍:计数
cnt: int = 0
cur: llvmlite.Param* = llvmlite.function_get_param_head(func)
cur: mlirlite.Param* = mlirlite.function_get_param_head(func)
while cur is not None and cnt < 256:
cnt += 1
cur = llvmlite.param_get_next(cur)
cur = mlirlite.param_get_next(cur)
# 第二遍:逐个构造并写入连续参数数组
params_arr: sizet* = None
if cnt > 0:
params_arr = CompilerFactory.factory.PermPool.alloc(8 * cnt)
if params_arr is None: return None
cur = llvmlite.function_get_param_head(func)
cur = mlirlite.function_get_param_head(func)
i: int = 0
while cur is not None and i < cnt:
ps: TSpec.TypeSpec* = TSpec.SpecFromLLVMType(arena, llvmlite.param_get_ty(cur))
ps: TSpec.TypeSpec* = TSpec.SpecFromLLVMType(arena, mlirlite.param_get_ty(cur))
if ps is None: return None
slot: sizet* = (sizet*)(uint64(params_arr) + uint64(i * 8))
if slot is None: return None
slot[0] = sizet(ps)
cur = llvmlite.param_get_next(cur)
cur = mlirlite.param_get_next(cur)
i += 1
return TSpec.NewTypeFunc(arena, ret_s, params_arr, cnt, func.IsVarArg)
def find_func_global(self, name: str) -> llvmlite.Function*:
def find_func_global(self, name: str) -> mlirlite.Function*:
"""在全局函数表中按名称查找,返回 Function 指针或 None"""
if name is None or self.GlobalFuncs is None: return None
return self.find_func_in_table(self.GlobalFuncs, self.GlobalFuncCount, name)
@@ -1423,11 +1423,11 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
def _build_const_from_snapshot(self, pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
gd_entry: GenTypes.FuncDefaultsEntry*,
di: int,
trans: HT.Translator*,
builder: llvmlite.IRBuilder*) -> llvmlite.Value*:
builder: mlirlite.IRBuilder*) -> mlirlite.Value*:
"""从快照重建第 di 个默认值常量 IR"""
if gd_entry is None or gd_entry.ConstKinds is None or gd_entry.ConstInts is None:
return None
@@ -1437,16 +1437,16 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
ival: int64 = gd_entry.ConstInts[di]
if kind == ast.CONST_INT:
if ival > 2147483647 or ival < -2147483648:
return llvmlite.const_int64(pool, ival)
return llvmlite.const_int32(pool, ival)
return mlirlite.const_int64(pool, ival)
return mlirlite.const_int32(pool, ival)
elif kind == ast.CONST_BOOL:
if ival != 0:
return llvmlite.const_int32(pool, 1)
return llvmlite.const_int32(pool, 0)
return mlirlite.const_int32(pool, 1)
return mlirlite.const_int32(pool, 0)
elif kind == ast.CONST_NONE:
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
return llvmlite.ConstNull(pool, i8_ptr_ty, "null")
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
return mlirlite.ConstNull(pool, i8_ptr_ty, "null")
elif kind == ast.CONST_STR:
if gd_entry.ConstStrs is not None and gd_entry.ConstStrs[di] != 0:
sv: str = rawptr(gd_entry.ConstStrs[di])
@@ -1500,7 +1500,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
if owner_sha1 is None:
return entry
if entry.Func is not None:
fn_nm_o: str = llvmlite.function_get_name(entry.Func)
fn_nm_o: str = mlirlite.function_get_name(entry.Func)
if fn_nm_o is not None:
if string.strncmp(fn_nm_o, owner_sha1, 16) == 0 and fn_nm_o[16] == '.':
return entry
@@ -1530,7 +1530,7 @@ novirtual class ExprCallHandle(HT.Mixin):
# ============================================================
# HandleCall - 翻译函数调用,返回 call 结果 Value
# ============================================================
def HandleCall(self, node: ast.AST*) -> llvmlite.Value*:
def HandleCall(self, node: ast.AST*) -> mlirlite.Value*:
"""翻译函数调用,从 self.Trans 获取共享状态"""
return GenApi.translate_call(self.Trans.Pool, self.Trans._cur_builder, self.Trans.Module, node, self.Trans._funcs, self.Trans._func_count, self.Trans)
+147 -147
View File
@@ -1,7 +1,7 @@
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdlib
@@ -20,17 +20,17 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
"""C 库声明 / 返回类型推断 / kwargs 调用辅助(继承 Base)"""
def _ensure_c_lib_declare(self, pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
name: str) -> llvmlite.Function*:
mod: mlirlite.LLVMModule*,
name: str) -> mlirlite.Function*:
"""为已知的 C 库函数创建 declare 声明"""
if pool is None or mod is None or name is None: return None
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i64_ty: llvmlite.LLVMType* = llvmlite.Int64(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
ret_ty: llvmlite.LLVMType* = None
ret_ty: mlirlite.LLVMType* = None
params: int = 0 # 参数数量
if string.strcmp(name, "strlen") == 0 or string.strcmp(name, "strlength") == 0:
@@ -82,37 +82,37 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
return None
# 创建 declare
fn: llvmlite.Function* = llvmlite.create_declare(pool, mod, name, ret_ty)
fn: mlirlite.Function* = mlirlite.create_declare(pool, mod, name, ret_ty)
if fn is None:
return None
# 添加参数
if params == 1:
if string.strcmp(name, "abs") == 0:
llvmlite.add_param(pool, fn, i32_ty, "n")
mlirlite.add_param(pool, fn, i32_ty, "n")
elif string.strcmp(name, "labs") == 0:
llvmlite.add_param(pool, fn, i64_ty, "n")
mlirlite.add_param(pool, fn, i64_ty, "n")
else:
llvmlite.add_param(pool, fn, i8_ptr_ty, "s")
mlirlite.add_param(pool, fn, i8_ptr_ty, "s")
elif params == 2:
llvmlite.add_param(pool, fn, i8_ptr_ty, "dst")
llvmlite.add_param(pool, fn, i8_ptr_ty, "src")
mlirlite.add_param(pool, fn, i8_ptr_ty, "dst")
mlirlite.add_param(pool, fn, i8_ptr_ty, "src")
elif params == 3:
if string.strcmp(name, "memset") == 0:
llvmlite.add_param(pool, fn, i8_ptr_ty, "dst")
llvmlite.add_param(pool, fn, i32_ty, "c")
llvmlite.add_param(pool, fn, i64_ty, "n")
mlirlite.add_param(pool, fn, i8_ptr_ty, "dst")
mlirlite.add_param(pool, fn, i32_ty, "c")
mlirlite.add_param(pool, fn, i64_ty, "n")
else:
llvmlite.add_param(pool, fn, i8_ptr_ty, "dst")
llvmlite.add_param(pool, fn, i8_ptr_ty, "src")
llvmlite.add_param(pool, fn, i64_ty, "n")
mlirlite.add_param(pool, fn, i8_ptr_ty, "dst")
mlirlite.add_param(pool, fn, i8_ptr_ty, "src")
mlirlite.add_param(pool, fn, i64_ty, "n")
return fn
def _promote_clib_call_args(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
call_name: str,
head: llvmlite.Value*,
count: int) -> llvmlite.Value*:
head: mlirlite.Value*,
count: int) -> mlirlite.Value*:
"""裸名 C 库函数实参按标准签名提升(B3)。
跨模块裸名调用(string.memset → @memset)时 _ensure_method_declare 用
@@ -140,36 +140,36 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
if size_idx < 0 or count <= size_idx:
return head
# 定位长度参数(index size_idx)
cur: llvmlite.Value* = head
cur: mlirlite.Value* = head
idx: int = 0
while cur is not None and idx < size_idx:
cur = cur.Next
idx += 1
if cur is None or cur.Ty is None:
return head
i64_ty: llvmlite.LLVMType* = llvmlite.Int64(pool)
promoted: llvmlite.Value* = None
i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool)
promoted: mlirlite.Value* = None
match cur.Ty:
case llvmlite.LLVMType.Int(bits):
case mlirlite.LLVMType.Int(bits):
if bits >= 64:
return head
if cur.IsConst != 0:
# 常量:直接 i64 常量(位模式保留,无符号长度语义)
promoted = llvmlite.const_int(pool, 64, cur.IntVal)
promoted = mlirlite.const_int(pool, 64, cur.IntVal)
else:
# SSA 值:zext 到 i64(size_t 无符号长度)
promoted = llvmlite.build_zext(builder, cur, i64_ty)
promoted = mlirlite.build_zext(builder, cur, i64_ty)
case _:
return head
if promoted is None:
return head
# 重建实参链表:index size_idx 替换为提升后的值
new_head: llvmlite.Value* = None
new_tail: llvmlite.Value* = None
cur2: llvmlite.Value* = head
new_head: mlirlite.Value* = None
new_tail: mlirlite.Value* = None
cur2: mlirlite.Value* = head
i2: int = 0
while cur2 is not None:
node_v: llvmlite.Value* = cur2
node_v: mlirlite.Value* = cur2
if i2 == size_idx:
node_v = promoted
if new_head is None:
@@ -183,13 +183,13 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
# _coerce_args_to_def_params:按 vpi 定义侧形参注解把跨模块调用实参 coerce 到目标类型并重建实参链,使 call/declare/define 宽度一致;支持 {sha1}.{func} 与 {sha1}.{cls}.{method} 两形态(段下标与实参下标一一对应),裸名 C 库走 _promote_clib_call_args/_ensure_c_lib_declare,未命中原样保留
def _coerce_args_to_def_params(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
builder: mlirlite.IRBuilder*,
call_name: str,
head: llvmlite.Value*,
head: mlirlite.Value*,
count: int,
cargs: list[ast.AST*]* = None,
self_off: int = 0,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""把跨模块调用实参 coerce 到 vpi 定义侧形参类型,返回重建的实参链
cargs/self_off/trans:实参 AST 列表与其在实参链中的偏移(模块级函数 0、
@@ -243,15 +243,15 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
if cls_nm is not None:
stdlib.free(cls_nm)
return head
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
new_head: llvmlite.Value* = None
new_tail: llvmlite.Value* = None
cur: llvmlite.Value* = head
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
new_head: mlirlite.Value* = None
new_tail: mlirlite.Value* = None
cur: mlirlite.Value* = head
idx: int = 0
while cur is not None and idx < count:
node_v: llvmlite.Value* = cur
tgt_ty: llvmlite.LLVMType* = None
node_v: mlirlite.Value* = cur
tgt_ty: mlirlite.LLVMType* = None
if tpl_src != 0:
tgt_ty = VpiReader._resolve_vpi_param_annot_seg_template(pool, sha1_buf, cls_nm, meth_nm, idx, i32_ty, i8_ptr_ty)
else:
@@ -291,12 +291,12 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
# _coerce_arg_value_to_ty:单个实参 Value 转换到目标形参类型——整型同宽原样、窄化 trunc/按宽度重建常量、扩宽按源符号性 zext/sext;同层指针类型不一致则 bitcast 到目标类型;其余原样返回(不可转换亦不改型)
def _coerce_arg_value_to_ty(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
val: llvmlite.Value*,
tgt_ty: llvmlite.LLVMType*,
builder: mlirlite.IRBuilder*,
val: mlirlite.Value*,
tgt_ty: mlirlite.LLVMType*,
node: ast.AST* = None,
trans: HT.Translator* = None,
tpl_src: int = 0) -> llvmlite.Value*:
tpl_src: int = 0) -> mlirlite.Value*:
"""把单个实参 Value 转换到目标形参类型,无法安全转换时原样返回
node/trans:实参 AST 与其翻译器(仅 SSA 整型扩宽的源符号性判定用,
@@ -308,38 +308,38 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
if pool is None or builder is None or val is None or tgt_ty is None or val.Ty is None:
return val
match val.Ty:
case llvmlite.LLVMType.Int(bits_a):
case mlirlite.LLVMType.Int(bits_a):
match tgt_ty:
case llvmlite.LLVMType.Int(bits_b):
case mlirlite.LLVMType.Int(bits_b):
if bits_b == bits_a:
return val
if bits_b < bits_a:
if val.IsConst != 0:
nv_c: llvmlite.Value* = llvmlite.const_int(pool, bits_b, val.IntVal)
nv_c: mlirlite.Value* = mlirlite.const_int(pool, bits_b, val.IntVal)
if nv_c is not None: return nv_c
else:
nv_t: llvmlite.Value* = llvmlite.build_trunc(builder, val, tgt_ty)
nv_t: mlirlite.Value* = mlirlite.build_trunc(builder, val, tgt_ty)
if nv_t is not None: return nv_t
# 扩宽(实参窄于形参):编译期常量按十进制值重建,各自保持原类型数值,无需 AST 判符号性
if val.IsConst != 0:
nv_w: llvmlite.Value* = llvmlite.const_int(pool, bits_b, val.IntVal)
nv_w: mlirlite.Value* = mlirlite.const_int(pool, bits_b, val.IntVal)
if nv_w is not None:
return nv_w
return val
# 非常量(SSA)扩宽:扩宽方向由源符号性决定(i1/i8、无符号源 → zext,否则 sext),使 declare/call/define 三者同宽
if bits_b > bits_a:
if self.Gen.ExprGenBase._zext_or_sext_val(pool, val, node, trans) != 0:
nv_zw: llvmlite.Value* = llvmlite.build_zext(builder, val, tgt_ty)
nv_zw: mlirlite.Value* = mlirlite.build_zext(builder, val, tgt_ty)
if nv_zw is not None: return nv_zw
else:
nv_sw: llvmlite.Value* = llvmlite.build_sext(builder, val, tgt_ty)
nv_sw: mlirlite.Value* = mlirlite.build_sext(builder, val, tgt_ty)
if nv_sw is not None: return nv_sw
return val
case _:
pass
case llvmlite.LLVMType.Ptr(_):
case mlirlite.LLVMType.Ptr(_):
match tgt_ty:
case llvmlite.LLVMType.Ptr(_):
case mlirlite.LLVMType.Ptr(_):
# 同层指针:实参类型与定义侧形参类型不一致就 bitcast 对齐(一致则不比,
# 避免生成非法 `bitcast T* to T*`)。跨模块调用的 call/declare 都以
# 定义侧为准(declare 见 CallGenBase._ensure_method_declare),故这里
@@ -348,19 +348,19 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
# 原判据只覆盖"一侧为 i8*"与"模板注解来源",漏了两侧同为具体结构体指针
# 但基类型不同的情形(实参 MemBuddy* vs 定义侧形参 MemManager*)。
if self.Gen.AssignGen._stg_ty_equal(pool, val.Ty, tgt_ty) == 0:
nv_p: llvmlite.Value* = llvmlite.build_bitcast(builder, val, tgt_ty)
nv_p: mlirlite.Value* = mlirlite.build_bitcast(builder, val, tgt_ty)
if nv_p is not None: return nv_p
case _:
pass
case _:
# 聚合值 → 指针:rvalue 结构体/数组落栈取址(FuncGenDef 形参一律 lowering 为 Ptr,跨模块时上游 coerce_to_type 不参与)
match tgt_ty:
case llvmlite.LLVMType.Ptr(_):
case mlirlite.LLVMType.Ptr(_):
vk_a: int = val.Ty.kind()
if vk_a == llvmlite.LLVMType.Struct or vk_a == llvmlite.LLVMType.Array:
tmp_a: llvmlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, val.Ty)
if vk_a == mlirlite.LLVMType.Struct or vk_a == mlirlite.LLVMType.Array:
tmp_a: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, val.Ty)
if tmp_a is not None:
llvmlite.build_store(builder, val, tmp_a)
mlirlite.build_store(builder, val, tmp_a)
return tmp_a
case _:
pass
@@ -369,7 +369,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
def _infer_external_func_ret_ty(self, pool: memhub.MemBuddy*,
func_name: str,
node: ast.AST*,
fatal_if_unknown: int) -> llvmlite.LLVMType*:
fatal_if_unknown: int) -> mlirlite.LLVMType*:
"""根据函数名推断外部 includes 函数的返回类型
支持三种函数名形式:
@@ -384,7 +384,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
i32 占位,不输出 WARN(下遍依赖就绪后走 text.ll/vpi 精确解析)。
"""
if pool is None or func_name is None:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
# 提取裸函数名:去掉 SHA1 前缀(如 "240a9a4157959a9f.parse" → "parse")
# SHA1 前缀是 16 位十六进制 + '.',检查是否有 '.' 分隔
@@ -394,7 +394,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
# '.' 后的部分是裸函数名
bare_name = dot_pos + 1
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
# 返回 i8* 的函数(指针返回值,截断会导致错误)
if string.strcmp(bare_name, "strchr") == 0 or string.strcmp(func_name, "strchr") == 0:
@@ -427,48 +427,48 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
# 指针 → mm.malloc 实际返回非空但调用方判 None(uhci frame list /
# desktop bg_row_buf 根因)。calloc/realloc/alloc 均已登记,malloc 遗漏。
if string.strcmp(bare_name, "malloc") == 0 or string.strcmp(func_name, "malloc") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
if string.strcmp(func_name, "alloc") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
if string.strcmp(func_name, "calloc") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
if string.strcmp(func_name, "realloc") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
if string.strcmp(func_name, "alloc_buf") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
# VLogger 模块函数(跨模块调用时 stub 未注入,返回指针被截断为 i32 导致崩溃)
if string.strcmp(func_name, "get_logger") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
if string.strcmp(func_name, "fmt_buf") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
# Config 模块函数(跨模块调用时 stub 未注入,返回 i8* 被 inttoptr i32 截断导致路径损坏)
if string.strcmp(func_name, "get_includes_binary_dir") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
# HandlesType 模块函数(返回 ast.AST|t.CPtr 联合类型,跨模块推断为 i32 导致指针截断)
if string.strcmp(bare_name, "_parse_type_string") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
# 返回 i64 的函数
if string.strcmp(func_name, "strlen") == 0:
return llvmlite.Int64(pool)
return mlirlite.Int64(pool)
if string.strcmp(func_name, "atoll") == 0:
return llvmlite.Int64(pool)
# llvmlite 函数名长度访问器返回 sizet(i64):默认 i32 与 declare 的 i64 签名不一致,须登记
return mlirlite.Int64(pool)
# mlirlite 函数名长度访问器返回 sizet(i64):默认 i32 与 declare 的 i64 签名不一致,须登记
if string.strcmp(bare_name, "function_get_name_len") == 0 or \
string.strcmp(func_name, "function_get_name_len") == 0:
return llvmlite.Int64(pool)
return mlirlite.Int64(pool)
# 返回 double 的函数
if string.strcmp(func_name, "atof") == 0:
return llvmlite.Double(pool)
return mlirlite.Double(pool)
# 返回 i8 的函数
if string.strcmp(func_name, "samestr") == 0:
return llvmlite.Int8(pool)
return mlirlite.Int8(pool)
# Win32 API 返回指针(VOIDPTR/HANDLE)的函数
# stubs 翻译时未注入,需推断返回 i8* 避免指针被截断为 i32 导致解引用崩溃
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
if string.strcmp(func_name, "VirtualAlloc") == 0:
return i8_ptr_ty
if string.strcmp(func_name, "HeapAlloc") == 0:
@@ -521,26 +521,26 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
# Win32 API 返回 i64 (SIZE_T) 的函数
if string.strcmp(func_name, "VirtualQuery") == 0:
return llvmlite.Int64(pool)
return mlirlite.Int64(pool)
if string.strcmp(func_name, "HeapSize") == 0:
return llvmlite.Int64(pool)
return mlirlite.Int64(pool)
if string.strcmp(func_name, "HeapCompact") == 0:
return llvmlite.Int64(pool)
return mlirlite.Int64(pool)
if string.strcmp(func_name, "GlobalSize") == 0:
return llvmlite.Int64(pool)
return mlirlite.Int64(pool)
# llvmlite build_* 返回类型推断:多数返回 Value*,少数终止指令返回 void(stubs 未注入时防指针截断)
# mlirlite build_* 返回类型推断:多数返回 Value*,少数终止指令返回 void(stubs 未注入时防指针截断)
if string.strncmp(func_name, "build_", 6) == 0:
# 返回 void 的 build_* 函数(终止指令和无返回值指令)
if string.strcmp(func_name, "build_ret") == 0 or string.strcmp(func_name, "build_ret_void") == 0 or \
string.strcmp(func_name, "build_store") == 0 or string.strcmp(func_name, "build_br") == 0 or \
string.strcmp(func_name, "build_cond_br") == 0 or string.strcmp(func_name, "build_unreachable") == 0 or \
string.strcmp(func_name, "build_switch") == 0:
return llvmlite.Void(pool)
return mlirlite.Void(pool)
# 其他 build_* 函数返回 Value*(指针)
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
# llvmlite 类型工厂 / 常量构造 / 访问器函数返回指针(LLVMType*/Value*):Int*/Ptr/Func/Array/Struct/Void 等、const_*/Const*、function_get_*/param_get_*
# mlirlite 类型工厂 / 常量构造 / 访问器函数返回指针(LLVMType*/Value*):Int*/Ptr/Func/Array/Struct/Void 等、const_*/Const*、function_get_*/param_get_*
if string.strcmp(func_name, "Int1") == 0 or string.strcmp(func_name, "Int8") == 0 or string.strcmp(func_name, "Int16") == 0 or \
string.strcmp(func_name, "Int32") == 0 or string.strcmp(func_name, "Int64") == 0 or string.strcmp(func_name, "Ptr") == 0 or \
string.strcmp(func_name, "Func") == 0 or string.strcmp(func_name, "Array") == 0 or string.strcmp(func_name, "Struct") == 0 or \
@@ -554,15 +554,15 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
string.strcmp(func_name, "value_get_ty") == 0 or string.strcmp(func_name, "value_get_next") == 0 or \
string.strcmp(func_name, "function_get_ret_ty") == 0 or string.strcmp(func_name, "function_get_params") == 0 or \
string.strcmp(func_name, "function_get_param_head") == 0 or string.strcmp(func_name, "param_get_next") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
# 默认 i32 占位:fatal_if_unknown=1 → fail-fast 报错;=0(Phase A 中间遍)保持占位,不输出 WARN
if fatal_if_unknown != 0:
self.Gen.TypeGenErr.fatal_error(node, f"外部函数返回类型未登记且无法收敛推断(默认 i32 会截断指针/i64,需提供 stub 声明或加入白名单): {func_name}", "TypeError")
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
def _get_external_func_param_ty(self, pool: memhub.MemBuddy*,
func_name: str,
param_idx: int) -> llvmlite.LLVMType*:
param_idx: int) -> mlirlite.LLVMType*:
"""获取外部函数第 param_idx 个参数的期望类型,None 表示用字面量原类型
对 Win32 API 函数的所有非指针参数返回 i64,匹配 declare 中
@@ -571,7 +571,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
if pool is None or func_name is None:
return None
i64_ty: llvmlite.LLVMType* = llvmlite.Int64(pool)
i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool)
# Win32 API 函数列表:所有非指针参数在 declare 中都是 i64
# (因为 ULONG/DWORD/SIZE_T 在 LLVM stubs 翻译时都被映射为 i64)
@@ -621,11 +621,11 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
return 1
return 0
def _emit_llvm_memcpy_intrinsic(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
dst_val: llvmlite.Value*,
src_val: llvmlite.Value*,
num_val: llvmlite.Value*) -> llvmlite.Value*:
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
dst_val: mlirlite.Value*,
src_val: mlirlite.Value*,
num_val: mlirlite.Value*) -> mlirlite.Value*:
"""将 memcpy 调用映射到 @llvm.memcpy 内联函数
直接接收三个 Value 参数,避免通过 Next 链表遍历(共享 alloca 对象的
@@ -637,72 +637,72 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
return None
# 在函数顶部声明 void_ty,避免后续遮蔽
void_ty: llvmlite.LLVMType* = llvmlite.Void(pool)
void_ty: mlirlite.LLVMType* = mlirlite.Void(pool)
# 声明 @llvm.memcpy(如未声明)
memcpy_func: llvmlite.Function* = self.find_func_in_module(mod, "llvm.memcpy")
memcpy_func: mlirlite.Function* = self.find_func_in_module(mod, "llvm.memcpy")
if memcpy_func is None:
memcpy_func = llvmlite.create_declare(pool, mod, "llvm.memcpy", void_ty)
memcpy_func = mlirlite.create_declare(pool, mod, "llvm.memcpy", void_ty)
if memcpy_func is not None:
i8_ptr_ty_d: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
i64_ty_d: llvmlite.LLVMType* = llvmlite.Int64(pool)
i1_ty_d: llvmlite.LLVMType* = llvmlite.Int1(pool)
llvmlite.add_param(pool, memcpy_func, i8_ptr_ty_d, "dst")
llvmlite.add_param(pool, memcpy_func, i8_ptr_ty_d, "src")
llvmlite.add_param(pool, memcpy_func, i64_ty_d, "len")
llvmlite.add_param(pool, memcpy_func, i1_ty_d, "isvolatile")
i8_ptr_ty_d: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
i64_ty_d: mlirlite.LLVMType* = mlirlite.Int64(pool)
i1_ty_d: mlirlite.LLVMType* = mlirlite.Int1(pool)
mlirlite.add_param(pool, memcpy_func, i8_ptr_ty_d, "dst")
mlirlite.add_param(pool, memcpy_func, i8_ptr_ty_d, "src")
mlirlite.add_param(pool, memcpy_func, i64_ty_d, "len")
mlirlite.add_param(pool, memcpy_func, i1_ty_d, "isvolatile")
# 类型转换: dst, src → i8*; num → i64
# 注意: 使用 value_get_ty 访问器获取 Ty,避免本地 Value 类型字段索引偏移
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
i64_ty: llvmlite.LLVMType* = llvmlite.Int64(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool)
# dst → i8*
dst_coerced: llvmlite.Value* = dst_val
dst_ty: llvmlite.LLVMType* = llvmlite.value_get_ty(dst_val)
dst_coerced: mlirlite.Value* = dst_val
dst_ty: mlirlite.LLVMType* = mlirlite.value_get_ty(dst_val)
if self.Gen.ExprGenBase.is_ptr_type(dst_ty) != 0:
dst_coerced = llvmlite.build_bitcast(builder, dst_val, i8_ptr_ty)
dst_coerced = mlirlite.build_bitcast(builder, dst_val, i8_ptr_ty)
else:
dst_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(dst_ty)
if dst_bits != 0:
if dst_bits < 64:
dst_coerced = llvmlite.build_zext(builder, dst_val, i64_ty)
dst_coerced = llvmlite.build_inttoptr(builder, dst_coerced, i8_ptr_ty)
dst_coerced = mlirlite.build_zext(builder, dst_val, i64_ty)
dst_coerced = mlirlite.build_inttoptr(builder, dst_coerced, i8_ptr_ty)
# src → i8*
src_coerced: llvmlite.Value* = src_val
src_ty: llvmlite.LLVMType* = llvmlite.value_get_ty(src_val)
src_coerced: mlirlite.Value* = src_val
src_ty: mlirlite.LLVMType* = mlirlite.value_get_ty(src_val)
if self.Gen.ExprGenBase.is_ptr_type(src_ty) != 0:
src_coerced = llvmlite.build_bitcast(builder, src_val, i8_ptr_ty)
src_coerced = mlirlite.build_bitcast(builder, src_val, i8_ptr_ty)
else:
src_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(src_ty)
if src_bits != 0:
if src_bits < 64:
src_coerced = llvmlite.build_zext(builder, src_val, i64_ty)
src_coerced = llvmlite.build_inttoptr(builder, src_coerced, i8_ptr_ty)
src_coerced = mlirlite.build_zext(builder, src_val, i64_ty)
src_coerced = mlirlite.build_inttoptr(builder, src_coerced, i8_ptr_ty)
# num → i64
num_coerced: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, num_val, i64_ty)
num_coerced: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, num_val, i64_ty)
if dst_coerced is None or src_coerced is None or num_coerced is None:
return None
# 添加 i1 false 参数(isvolatile)— llvm.memcpy 需要 4 个参数
false_val: llvmlite.Value* = llvmlite.ConstInt(pool, llvmlite.Int1(pool), 0, "false")
false_val: mlirlite.Value* = mlirlite.ConstInt(pool, mlirlite.Int1(pool), 0, "false")
# 使用 includes 中的访问器函数构建参数链表,避免本地 Value 类型字段索引偏移
# (f26cd4c78b4d554c.Value 缺少 GSListNode 的 Next 字段,直接访问 .Next 会修改 .Ty)
llvmlite.value_set_next(dst_coerced, src_coerced)
llvmlite.value_set_next(src_coerced, num_coerced)
mlirlite.value_set_next(dst_coerced, src_coerced)
mlirlite.value_set_next(src_coerced, num_coerced)
if false_val is not None:
llvmlite.value_set_next(num_coerced, false_val)
llvmlite.value_set_next(false_val, None)
mlirlite.value_set_next(num_coerced, false_val)
mlirlite.value_set_next(false_val, None)
else:
llvmlite.value_set_next(num_coerced, None)
mlirlite.value_set_next(num_coerced, None)
# 使用 build_call 发射 call 指令(内部用 includes Value 类型访问字段,索引正确)
# _ll_name_needs_quote 已对 llvm. 前缀豁免引号
result: llvmlite.Value* = llvmlite.build_call(builder, "llvm.memcpy", dst_coerced, 4, void_ty, 0)
result: mlirlite.Value* = mlirlite.build_call(builder, "llvm.memcpy", dst_coerced, 4, void_ty, 0)
# 返回 dst(匹配 C memcpy 语义: 返回 dest 指针)
return dst_coerced
@@ -710,28 +710,28 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
# ============================================================
def _translate_call_with_kwargs(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
func_name: str,
found_func: llvmlite.Function*,
found_func: mlirlite.Function*,
cargs: list[ast.AST*]*,
can: sizet,
keywords: list[ast.AST*]*,
kw_count: sizet,
trans: HT.Translator*) -> llvmlite.Value*:
trans: HT.Translator*) -> mlirlite.Value*:
"""带关键字参数的函数调用,按参数顺序构建调用链表
使用 llvmlite 访问器函数绕过 stub 类型限制:
使用 mlirlite 访问器函数绕过 stub 类型限制:
found_func.Params/RetTy/Name 和 cur_param.Name/Ty/Next 在 stub
类型中字段不足,直接访问会被 TransPyC 静默跳过。
"""
head: llvmlite.Value* = None
tail: llvmlite.Value* = None
head: mlirlite.Value* = None
tail: mlirlite.Value* = None
actual_count: sizet = 0
# memcpy 专用: 收集前三个 Value 的独立引用(避免共享 alloca 对象的 Next 被污染)
mc_dst1: llvmlite.Value* = None
mc_src1: llvmlite.Value* = None
mc_num1: llvmlite.Value* = None
mc_dst1: mlirlite.Value* = None
mc_src1: mlirlite.Value* = None
mc_num1: mlirlite.Value* = None
# 省略参数补齐用的默认参数表查询(与 CallGenMixin 非 kwargs 路径同一真源)。
# 根因:本路径此前对"位置/关键字均未提供的形参"直接跳过 → 调用实参数 <
@@ -742,7 +742,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
# 「名 + 定义模块 SHA1」登记(_register_global_defaults),注册时已对常量
# 快照,跨 1b reset 永久存活 ⇒ 跨模块也能取到定义处的真实默认值。
kw_callee_sha: str = None
kw_found_name: str = llvmlite.function_get_name(found_func)
kw_found_name: str = mlirlite.function_get_name(found_func)
if kw_found_name is not None:
if GenApi.sha1_prefix_len(kw_found_name) != 0:
kw_sha_buf: str = pool.alloc(17)
@@ -765,11 +765,11 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
# 遍历函数参数链表(使用访问器获取 Head)
param_idx: sizet = 0
cur_param: llvmlite.Param* = llvmlite.function_get_param_head(found_func)
cur_param: mlirlite.Param* = mlirlite.function_get_param_head(found_func)
while cur_param is not None:
arg_val: llvmlite.Value* = None
param_ty: llvmlite.LLVMType* = llvmlite.param_get_ty(cur_param)
arg_val: mlirlite.Value* = None
param_ty: mlirlite.LLVMType* = mlirlite.param_get_ty(cur_param)
if param_idx < can:
# 优先使用位置参数
arg: ast.AST* = cargs.get(param_idx)
@@ -778,7 +778,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
arg_val = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, param_ty)
else:
# 查找匹配的关键字参数
param_name: str = llvmlite.param_get_name(cur_param)
param_name: str = mlirlite.param_get_name(cur_param)
if param_name is not None:
for ki in range(kw_count):
kw: rawptr[ast.Keyword] = rawptr[ast.Keyword](keywords.get(ki))
@@ -826,16 +826,16 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
actual_count += 1
param_idx += 1
cur_param = llvmlite.param_get_next(cur_param)
cur_param = mlirlite.param_get_next(cur_param)
# declare 与 define 统一用 found_func.Name:普通函数带 SHA1 前缀,t.CExtern/t.State/t.CExport 用裸名(用裸名会造成 call 与 define 符号名不一致)
call_name: str = func_name
found_name: str = llvmlite.function_get_name(found_func)
found_name: str = mlirlite.function_get_name(found_func)
if found_name is not None:
call_name = found_name
# 返回类型(使用访问器)
call_ret_ty: llvmlite.LLVMType* = llvmlite.function_get_ret_ty(found_func)
call_ret_ty: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(found_func)
if call_ret_ty is None:
# found_func 已有 declare 却读不到返回类型(访问器异常,罕见防御):
# 白名单未命中也不 fail-fast,保持默认 i32(有声明即有类型来源)。
@@ -844,4 +844,4 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
# memcpy → @llvm.memcpy 内联函数(避免 monomorphization 跨模块 @memcpy 声明缺失)
if string.strcmp(func_name, "memcpy") == 0 and actual_count >= 3:
return self._emit_llvm_memcpy_intrinsic(pool, builder, mod, mc_dst1, mc_src1, mc_num1)
return llvmlite.build_call(builder, call_name, head, actual_count, call_ret_ty, 0)
return mlirlite.build_call(builder, call_name, head, actual_count, call_ret_ty, 0)
+104 -104
View File
@@ -2,7 +2,7 @@ import lib.core.Gen.GenTypes as GenTypes
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdio
@@ -92,12 +92,12 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# 翻译函数调用 Call(func, args) — 模块级版本
# ============================================================
def translate_call(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
node: ast.AST*,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""翻译函数调用,返回 call 结果 Value"""
cl: ast.Call* = ast.Call*(node)
# static 符号(禁止跨模块使用):`mod.fn(...)` 命中别的模块登记的 static 函数
@@ -119,7 +119,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
h0_hit: t.CPtr = stdlib.malloc(4)
if h0_hit is not None:
h0_hit[0] = 0
_tc_h0_generic_func_res: llvmlite.Value* = self.Gen.CallGenDispatch._tc_h0_generic_func(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h0_hit)
_tc_h0_generic_func_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h0_generic_func(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h0_hit)
h0_hit_val: int = 0
if h0_hit is not None:
h0_hit_val = h0_hit[0]
@@ -135,7 +135,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
h1_hit: t.CPtr = stdlib.malloc(4)
if h1_hit is not None:
h1_hit[0] = 0
_tc_h1_super_ctraits_res: llvmlite.Value* = self.Gen.CallGenDispatch._tc_h1_super_ctraits(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h1_hit)
_tc_h1_super_ctraits_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h1_super_ctraits(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h1_hit)
h1_hit_val: int = 0
if h1_hit is not None:
h1_hit_val = h1_hit[0]
@@ -183,9 +183,9 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# CArray 不是泛型类模板,是类型注解下标。先按注解解析出
# 类型再单参转换(ast/base.vp L392 ops_list 行根因)。
if cl.args is not None and len(cl.args) == 1:
sub_cast_ty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, cl.func, trans._imported_modules, trans._from_imports, trans, 0)
sub_cast_ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, cl.func, trans._imported_modules, trans._from_imports, trans, 0)
if sub_cast_ty is not None:
sub_cast_arg: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cl.args.get(0), funcs_ptr, func_count, trans)
sub_cast_arg: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cl.args.get(0), funcs_ptr, func_count, trans)
if sub_cast_arg is not None:
return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, sub_cast_arg, sub_cast_ty,
cl.args.get(0), trans)
@@ -199,11 +199,11 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# 检查是否是 (A | t.CPtr)(value) 形式的类型转换
# BinOp 节点作为 Call func: 联合类型注解用作类型转换
if cl.func is not None and cl.func.kind() == ast.ASTKind.BinOp and trans is not None:
binop_ty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, cl.func, trans._imported_modules, trans._from_imports, trans, 0)
binop_ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, cl.func, trans._imported_modules, trans._from_imports, trans, 0)
if binop_ty is not None:
binop_args: list[ast.AST*]* = cl.args
if binop_args is not None and len(binop_args) == 1:
binop_arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, binop_args.get(0), funcs_ptr, func_count, trans)
binop_arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, binop_args.get(0), funcs_ptr, func_count, trans)
if binop_arg_val is not None:
return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, binop_arg_val, binop_ty)
return None
@@ -215,7 +215,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
h2_hit: t.CPtr = stdlib.malloc(4)
if h2_hit is not None:
h2_hit[0] = 0
_tc_h2_c_special_res: llvmlite.Value* = self.Gen.CallGenDispatch._tc_h2_c_special(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h2_hit)
_tc_h2_c_special_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h2_c_special(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h2_hit)
h2_hit_val: int = 0
if h2_hit is not None:
h2_hit_val = h2_hit[0]
@@ -226,15 +226,15 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# 命中 c.Asm/c.LLVMIR 但无返回值(void):视为已处理
return None
_tc_h3_stdarg_cast_res: llvmlite.Value* = self.Gen.CallGenDispatch._tc_h3_stdarg_cast(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can)
_tc_h3_stdarg_cast_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h3_stdarg_cast(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can)
if _tc_h3_stdarg_cast_res is not None:
return _tc_h3_stdarg_cast_res
_tc_h4_type_casts_res: llvmlite.Value* = self.Gen.CallGenDispatch._tc_h4_type_casts(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can)
_tc_h4_type_casts_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h4_type_casts(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can)
if _tc_h4_type_casts_res is not None:
return _tc_h4_type_casts_res
_tc_h5_sizeof_len_isinst_res: llvmlite.Value* = self.Gen.CallGenDispatch._tc_h5_sizeof_len_isinst(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can)
_tc_h5_sizeof_len_isinst_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h5_sizeof_len_isinst(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can)
if _tc_h5_sizeof_len_isinst_res is not None:
return _tc_h5_sizeof_len_isinst_res
@@ -247,7 +247,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
h6_hit: t.CPtr = stdlib.malloc(4)
if h6_hit is not None:
h6_hit[0] = 0
_tc_h6_method_dispatch_res: llvmlite.Value* = self.Gen.CallGenDispatch._tc_h6_method_dispatch(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h6_hit)
_tc_h6_method_dispatch_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h6_method_dispatch(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h6_hit)
h6_hit_val: int = 0
if h6_hit is not None:
h6_hit_val = h6_hit[0]
@@ -269,7 +269,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# - 裸名 Class(): 需要 from X import Class 或本地定义
# - 模块限定 Module.Class(): 需要 import Module
# 用 find_struct_by_module 规避跨模块同名 find_struct 找错
struct_ty: llvmlite.LLVMType* = None
struct_ty: mlirlite.LLVMType* = None
gen_ctor_entry: GenTypes.StructEntry* = None
# 模块限定构造 Module.Class(...) 优先:按模块名解析 SHA1 精确命中类。
# 必须在裸名可见性分支之前——跨模块同名类(VKernel gfx 与 App gfx 都
@@ -406,7 +406,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# 有默认值:走构造函数路径应用默认值
return self.Gen.CallGenCtor._translate_struct_ctor(pool, builder, mod, struct_ty, func_name, cargs, sizet(0), trans, cl.IsVolatile)
# 无默认值:返回 zeroinitializer
ret: llvmlite.Value* = llvmlite.ConstZero(pool, struct_ty)
ret: mlirlite.Value* = mlirlite.ConstZero(pool, struct_ty)
return ret
if kw_count > 0:
# 有关键字参数:按字段名赋值
@@ -522,10 +522,10 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
return self.Gen.CallGenCtor._translate_renum_construct(pool, builder, mod, rc_cls_name, func_name, rc_tag, cargs, can, trans, cl.IsVolatile)
elif rc_at.value is not None and rc_at.value.kind() == ast.ASTKind.Attribute:
# 模块限定 REnum 变体构造: mod.Class.Variant(args...)
# 如 llvmlite.LLVMType.Struct(...) → 构造 llvmlite 模块 LLVMType 的 Struct 变体。
# 如 mlirlite.LLVMType.Struct(...) → 构造 mlirlite 模块 LLVMType 的 Struct 变体。
# 根因:此前只支持单层 Name(ClassName.Variant),嵌套属性漏检 → 误走跨模块
# 函数路径 → _lookup_module_sha1("llvmlite.LLVMType") 查无 → 报"跨模块调用
# 'llvmlite.LLVMType.Struct' 找不到模块 SHA1"。跨模块任意同名可接受(REnum
# 函数路径 → _lookup_module_sha1("mlirlite.LLVMType") 查无 → 报"跨模块调用
# 'mlirlite.LLVMType.Struct' 找不到模块 SHA1"。跨模块任意同名可接受(REnum
# 表按类名全局注册):仅要求最左模块已导入 + 末段类名在全局 REnum 表中命中,
# 不做"类必须属于该模块"校验(未命中则按后续函数路径 fast-fail)。
rc_mq_path: str = self.Gen.ExprGenAttr._attr_module_path_str(pool, rc_at.value)
@@ -563,23 +563,23 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
if can_buf is not None:
viperlib.snprintf(can_buf, 64, "create_%s", func_name)
create_an: str = self.Gen.FuncGenBase._mangle_func_name(trans, can_buf, 0)
create_fn_an: llvmlite.Function* = self.find_func_in_module(mod, create_an)
create_fn_an: mlirlite.Function* = self.find_func_in_module(mod, create_an)
if create_fn_an is not None:
frame_ty_an: llvmlite.LLVMType* = self.Gen.AsyncGen._lookup_coro_frame(trans, func_name)
frame_ty_an: mlirlite.LLVMType* = self.Gen.AsyncGen._lookup_coro_frame(trans, func_name)
if frame_ty_an is not None:
ret_ptr_ty_an: llvmlite.LLVMType* = llvmlite.Ptr(pool, frame_ty_an)
i8_ptr_ty_an: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
ret_ptr_ty_an: mlirlite.LLVMType* = mlirlite.Ptr(pool, frame_ty_an)
i8_ptr_ty_an: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
# M2:async 调用参数(task(5, 6) → create_task(5, 6))
arg_head_an: llvmlite.Value* = None
arg_tail_an: llvmlite.Value* = None
arg_head_an: mlirlite.Value* = None
arg_tail_an: mlirlite.Value* = None
arg_cnt_an: int = 0
if cl.args is not None:
nb_an: sizet = len(cl.args)
j_an: sizet = 0
for j_an in range(nb_an):
av_an: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cl.args.get(j_an), None, 0, trans)
av_an: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cl.args.get(j_an), None, 0, trans)
if av_an is None:
av_an = llvmlite.const_int32(pool, 0)
av_an = mlirlite.const_int32(pool, 0)
av_an.Next = None
if arg_head_an is None:
arg_head_an = av_an
@@ -588,10 +588,10 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
arg_tail_an.Next = av_an
arg_tail_an = av_an
arg_cnt_an = arg_cnt_an + 1
child_an: llvmlite.Value* = llvmlite.build_call(builder, create_an, arg_head_an, arg_cnt_an, ret_ptr_ty_an, 0)
child_an: mlirlite.Value* = mlirlite.build_call(builder, create_an, arg_head_an, arg_cnt_an, ret_ptr_ty_an, 0)
if child_an is not None:
return llvmlite.build_bitcast(builder, child_an, i8_ptr_ty_an)
return llvmlite.const_int32(pool, 0)
return mlirlite.build_bitcast(builder, child_an, i8_ptr_ty_an)
return mlirlite.const_int32(pool, 0)
# 查找函数:优先从函数表按裸名精确匹配(同模块函数),
# 再从模块函数链表按后缀匹配(SHA1 前缀名)。
@@ -608,7 +608,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
if actual_funcs is None and trans is not None:
actual_funcs = trans._funcs
actual_func_count = trans._func_count
found_func: llvmlite.Function* = None
found_func: mlirlite.Function* = None
if cl.func is not None and cl.func.kind() == ast.ASTKind.Name:
# 裸名调用:允许精确 + 后缀匹配
# 自定义装饰器 wrapper 重写:原函数名 → __decor_wrap_{name}
@@ -619,7 +619,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
found_func = self.find_func_in_module(mod, decor_wrap_nm)
else:
# 本模块已定义函数名的裸名调用:先按裸名在模块函数表(FuncEntry 数组,forward_declare_functions 已把所有模块级函数以 Name=裸名、Func=其 declare/define 登记进 trans._funcs)精确命中,再回落 find_func_in_module 的 LLVM 模块链表扫描。函数表才是同模块函数名的权威注册表(链表扫描漏掉本模块定义时会误走 C 库自动 declare / from_imports 回退)。模块表只含模块级函数(无方法),CExport 条目 Func 名即裸名,复用不改变既有符号语义
mod_fn_tb: llvmlite.Function* = None
mod_fn_tb: mlirlite.Function* = None
if actual_funcs is not None:
# 同模块函数优先:_funcs 表在 forward_declare_functions 之前
# 已被 LoadDepVpiIntoModule 注入的依赖模块 stub 污染——外来
@@ -650,7 +650,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# (栈溢出 0xC0000005)。裸名调用应优先解析为模块级函数
# (同模块函数表 / from_imports),方法调用需显式 obj.method。
if found_func is not None:
bn_name: str = llvmlite.function_get_name(found_func)
bn_name: str = mlirlite.function_get_name(found_func)
if bn_name is not None:
bn_dots: int = 0
bni2: sizet = 0
@@ -730,11 +730,11 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# llc "instruction expected to be numbered" 根因)。
mod_sha1_chk = self.Gen.StructGen._resolve_module_sha1(xm_mod_path, trans._from_imports)
if mod_sha1_chk is not None:
ff_nm2: str = llvmlite.function_get_name(found_func)
ff_nm2: str = mlirlite.function_get_name(found_func)
if ff_nm2 is not None:
if string.strncmp(ff_nm2, mod_sha1_chk, 16) != 0:
found_func = None
ff_name: str = llvmlite.function_get_name(found_func)
ff_name: str = mlirlite.function_get_name(found_func)
if ff_name is not None:
ff_dots: int = 0
ffi2: sizet = 0
@@ -786,7 +786,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
if abs_cls is not None:
abs_sc: str = self.Gen.ExprGenOps._resolve_dunder_by_class(pool, mod, abs_cls, "__abs__", trans)
if abs_sc is not None:
abs_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, abs_arg, None, 0, trans)
abs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, abs_arg, None, 0, trans)
if abs_val is not None:
return self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, abs_sc, "__abs__", abs_val, None, 0, trans)
# C 库函数裸名调用支持:若模块中找不到且是已知 C 库函数,自动创建 declare
@@ -800,21 +800,21 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
if found_func is None:
bi_sha1: str = self._lookup_module_sha1("builtins")
if bi_sha1 is not None:
bi_ret: llvmlite.LLVMType* = None
bi_p1: llvmlite.LLVMType* = None
bi_p2: llvmlite.LLVMType* = None
bi_ret: mlirlite.LLVMType* = None
bi_p1: mlirlite.LLVMType* = None
bi_p2: mlirlite.LLVMType* = None
if string.strcmp(func_name, "ord") == 0:
bi_ret = llvmlite.Int32(pool)
bi_p1 = llvmlite.Int8(pool)
bi_ret = mlirlite.Int32(pool)
bi_p1 = mlirlite.Int8(pool)
elif string.strcmp(func_name, "chr") == 0:
bi_ret = llvmlite.Int8(pool)
bi_p1 = llvmlite.Int32(pool)
bi_ret = mlirlite.Int8(pool)
bi_p1 = mlirlite.Int32(pool)
elif string.strcmp(func_name, "min") == 0 or string.strcmp(func_name, "max") == 0:
# min/max 数值比较(builtins.vp 定义 double 参数/返回,
# int/float 实参经 coerce 提升;两参数)
bi_ret = llvmlite.Double(pool)
bi_p1 = llvmlite.Double(pool)
bi_p2 = llvmlite.Double(pool)
bi_ret = mlirlite.Double(pool)
bi_p1 = mlirlite.Double(pool)
bi_p2 = mlirlite.Double(pool)
if bi_ret is not None:
bi_sym: str = func_name
if self.Gen.CallGenBase.is_cexport_func(bi_sha1, func_name) == 0:
@@ -823,20 +823,20 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
if bi_sym_buf is not None:
viperlib.snprintf(bi_sym_buf, bi_sym_len, "%s.%s", bi_sha1, func_name)
bi_sym = bi_sym_buf
bi_decl: llvmlite.Function* = llvmlite.create_declare(pool, mod, bi_sym, bi_ret)
bi_decl: mlirlite.Function* = mlirlite.create_declare(pool, mod, bi_sym, bi_ret)
if bi_decl is not None:
llvmlite.add_param(pool, bi_decl, bi_p1, "v")
mlirlite.add_param(pool, bi_decl, bi_p1, "v")
if bi_p2 is not None:
llvmlite.add_param(pool, bi_decl, bi_p2, "w")
mlirlite.add_param(pool, bi_decl, bi_p2, "w")
found_func = bi_decl
# 使用访问器绕过 stub 类型限制
found_ret_ty: llvmlite.LLVMType* = None
found_ret_ty: mlirlite.LLVMType* = None
found_params: t.CPtr = None
if found_func is not None:
found_ret_ty = llvmlite.function_get_ret_ty(found_func)
found_params = llvmlite.function_get_params(found_func)
found_ret_ty = mlirlite.function_get_ret_ty(found_func)
found_params = mlirlite.function_get_params(found_func)
if found_ret_ty is not None:
call_ret_ty: llvmlite.LLVMType* = found_ret_ty
call_ret_ty: mlirlite.LLVMType* = found_ret_ty
else:
# found_func=None(跨模块 stub 未注入):先从 vpi stub 返回注解
# 缓存精确获取返回类型(含 tuple[T1,T2] → 匿名结构体,如
@@ -847,14 +847,14 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# 与定义侧 {i8*, i16} 不匹配 → HandlesAssign 的 tuple 解包
# (依赖 rhs_val.Ty 是 Struct)静默跳过 → 目标变量从未赋值 →
# free 未初始化栈垃圾指针崩溃(HashLibTest hqx 段)。
vpi_ret_ty: llvmlite.LLVMType* = None
vpi_ret_ty: mlirlite.LLVMType* = None
# 跨模块返回类型解析的来源模块 SHA1:仅在下方 cl.func 是
# Attribute(模块.函数) 分支赋值。必须显式初始化 None——此前声明在
# if 块内、elif mod_ret_sha1 is not None 在外层读取,裸名调用
# (cl.func 是 Name,如 LLVMModuleCore 方法内裸名 create_global_int)
# 时该 alloca 从未 store,读到栈残留垃圾(0x1)→
# _LookupMethodRetTyFromTextLL 的 strlen(0x1) 零页崩溃
# (llvmlite/__init__.vp CreateGlobalInt 翻译时 0xC0000005 根因)。
# (mlirlite/__init__.vp CreateGlobalInt 翻译时 0xC0000005 根因)。
mod_ret_sha1: str = None
# 模块路径(cl.func 为 Attribute 时赋值,否则保持 None)。声明在 if 外,
# 使下方裸名兜底分支也能安全读取(读未声明的局部 = 栈垃圾)。
@@ -915,7 +915,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
VpiReader._ensure_vpi_ret_annot_loaded(rr_sha1, self.Gen.CallGenBase.TempDir)
ret_annot_fc = VpiReader._lookup_vpi_ret_annot(rr_sha1, None, func_name)
if ret_annot_fc is not None:
vpi_ret_ty = VpiReader._resolve_vpi_ret_annot_str(pool, ret_annot_fc, llvmlite.Int32(pool), llvmlite.Ptr(pool, llvmlite.Int8(pool)))
vpi_ret_ty = VpiReader._resolve_vpi_ret_annot_str(pool, ret_annot_fc, mlirlite.Int32(pool), mlirlite.Ptr(pool, mlirlite.Int8(pool)))
if vpi_ret_ty is not None:
call_ret_ty = vpi_ret_ty
elif mod_ret_sha1 is not None:
@@ -923,7 +923,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# 时从依赖模块精确解析返回类型(对齐 mangled 路径),避免静默默认
# i32 截断指针/i64(uhci.vp mm.malloc 根因:call i32 @malloc 截断
# 0xbb69000 → null)。权威来源:vpi 注解缓存;未命中回退 text.ll。
cross_ret: llvmlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, mod_ret_sha1, None, func_name)
cross_ret: mlirlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, mod_ret_sha1, None, func_name)
if cross_ret is None:
if trans is not None and trans._declare_only == 0:
cross_ret = self._LookupMethodRetTyFromTextLL(pool, mod_ret_sha1, None, func_name, 1)
@@ -958,7 +958,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
call_ret_ty = self.Gen.CallGenLib._infer_external_func_ret_ty(pool, func_name, node, 1 - bare_resolvable)
if found_func is None:
fp_alloca: llvmlite.Value* = None
fp_alloca: mlirlite.Value* = None
if cl.func is None or cl.func.kind() == ast.ASTKind.Name:
# 闭包内调用捕获的闭包变量(如 _cmd_cd 调 _build_path):
# 从 env 读闭包对象指针,不能 lookup_var 跨函数命中父函数
@@ -970,11 +970,11 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# translate_closure_call 期望 i8** 存储(load 一次得闭包
# 对象指针);load_nonlocal_var 已返回对象指针 → 临时
# alloca 暂存
i8_ty_nl: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty_nl: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty_nl)
tmp_alloca_nl: llvmlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, i8_ptr_ty_nl)
i8_ty_nl: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty_nl: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_nl)
tmp_alloca_nl: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, i8_ptr_ty_nl)
if tmp_alloca_nl is not None:
llvmlite.build_store(builder, fp_alloca, tmp_alloca_nl)
mlirlite.build_store(builder, fp_alloca, tmp_alloca_nl)
fp_alloca = tmp_alloca_nl
else:
fp_alloca = self.Gen.VarGen.lookup_var(trans.SymTab, func_name)
@@ -986,10 +986,10 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
if trans is not None \
and self.Gen.CallGenLeafKit.is_closure_name(func_name) == 0 \
and self.Gen.CallGenLeafKit._is_func_ptr_alloca(fp_alloca) == 0:
c_obj: llvmlite.Value* = self.Gen.ExprGenBase._deref_if_ptr_ptr(builder, fp_alloca)
c_obj: mlirlite.Value* = self.Gen.ExprGenBase._deref_if_ptr_ptr(builder, fp_alloca)
if c_obj is None:
c_obj = fp_alloca
c_struct: llvmlite.LLVMType* = None
c_struct: mlirlite.LLVMType* = None
if c_obj is not None:
c_struct = self.Gen.StructGen.get_struct_type_from_value(c_obj)
if c_struct is not None:
@@ -1047,7 +1047,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
sfn_box = stdlib.malloc(4)
if sfn_box is not None:
sfn_box[0] = 0
sfn_val: llvmlite.Value* = self.Gen.VarGen.repl_try_session_func_call(trans, pool, builder, mod, func_name, cargs, int(can), int(kw_count), node, sfn_box)
sfn_val: mlirlite.Value* = self.Gen.VarGen.repl_try_session_func_call(trans, pool, builder, mod, func_name, cargs, int(can), int(kw_count), node, sfn_box)
sfn_handled: int = int(sfn_box[0])
stdlib.free(sfn_box)
if sfn_handled != 0:
@@ -1060,12 +1060,12 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
if kw_count > 0 and found_func is not None and found_params is not None:
return self.Gen.CallGenLib._translate_call_with_kwargs(pool, builder, mod, func_name, found_func, cargs, can, keywords, kw_count, trans)
head: llvmlite.Value* = None
tail: llvmlite.Value* = None
head: mlirlite.Value* = None
tail: mlirlite.Value* = None
# memcpy 专用: 收集前三个 Value 的独立引用(避免共享 alloca 对象的 Next 被污染)
mc_dst2: llvmlite.Value* = None
mc_src2: llvmlite.Value* = None
mc_num2: llvmlite.Value* = None
mc_dst2: mlirlite.Value* = None
mc_src2: mlirlite.Value* = None
mc_num2: mlirlite.Value* = None
# 「str/bytes 不是通用指针通配」前置:同模块**裸名**函数的形参注解来自本
# 模块的 .vpi(与跨模块路径 CallGenLib._coerce_args_to_def_params 同源同
# 键式:模块级函数 cls=None、段下标 == 形参下标)。在参数循环前一次性确保
@@ -1084,17 +1084,17 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# 形参时需物化 1 字符字符串(translate_constant 依据 target_ty
# 判定),否则 coerce inttoptr 把字符值当指针(如 '"'=0x22)→
# strlen 访问低地址 ASan 崩溃(二代编 StringTest PyI 生成根因)。
fp: llvmlite.Param* = None
fpty: llvmlite.LLVMType* = None
fp: mlirlite.Param* = None
fpty: mlirlite.LLVMType* = None
if found_func is not None:
fp = llvmlite.function_get_param_head(found_func)
fp = mlirlite.function_get_param_head(found_func)
fpi: int = 0
while fp is not None and fpi < ai:
fp = llvmlite.param_get_next(fp)
fp = mlirlite.param_get_next(fp)
fpi += 1
if fp is not None:
fpty = llvmlite.param_get_ty(fp)
arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, fpty, "形参")
fpty = mlirlite.param_get_ty(fp)
arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, fpty, "形参")
if arg_val is not None:
# 参数类型提升:当 found_func 为 None(stub 未注入)时,
# 根据外部函数签名推断期望类型,提升字面量(如 i32→i64)
@@ -1103,11 +1103,11 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# 数组实参按 C 语义衰减为元素指针(对齐 TPC
# _decay_array_to_ptr),与 _translate_method_call 一致。
if self.Gen.ExprGenBase.is_ptr_type(arg_val.Ty) != 0:
arr_pointee_fc: llvmlite.LLVMType* = arg_val.Ty.Pointee
arr_pointee_fc: mlirlite.LLVMType* = arg_val.Ty.Pointee
if arr_pointee_fc is not None:
match arr_pointee_fc:
case llvmlite.LLVMType.Array(arr_et_fc, _):
decayed_fc: llvmlite.Value* = llvmlite.build_gep_array(builder, arr_pointee_fc, arr_et_fc, arg_val, llvmlite.const_int32(pool, 0))
case mlirlite.LLVMType.Array(arr_et_fc, _):
decayed_fc: mlirlite.Value* = mlirlite.build_gep_array(builder, arr_pointee_fc, arr_et_fc, arg_val, mlirlite.const_int32(pool, 0))
if decayed_fc is not None:
arg_val = decayed_fc
case _:
@@ -1117,16 +1117,16 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# 参数类型是 C ABI 硬约束(snprintf size 为 i64),不提升
# 则 call(i32 1024) 与 declare(i64 size) 不匹配,且 Win64
# 变参槽高 4 字节残留栈垃圾(clean 日志 0x7ff700000052 根因)。
kvc_ty: llvmlite.LLVMType* = self.Gen.CallGenVa._get_known_vararg_cfunc_param_ty(pool, func_name, ai)
kvc_ty: mlirlite.LLVMType* = self.Gen.CallGenVa._get_known_vararg_cfunc_param_ty(pool, func_name, ai)
if kvc_ty is not None:
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, kvc_ty, arg)
ext_param_ty: llvmlite.LLVMType* = self.Gen.CallGenLib._get_external_func_param_ty(pool, func_name, ai)
ext_param_ty: mlirlite.LLVMType* = self.Gen.CallGenLib._get_external_func_param_ty(pool, func_name, ai)
if ext_param_ty is not None:
val_bits_ap: int = self.Gen.ExprGenBase.get_llvm_type_bits(arg_val.Ty)
tgt_bits_ap: int = self.Gen.ExprGenBase.get_llvm_type_bits(ext_param_ty)
if val_bits_ap != 0 and tgt_bits_ap != 0 and val_bits_ap != tgt_bits_ap:
if val_bits_ap == 1 and val_bits_ap < tgt_bits_ap:
arg_val = llvmlite.build_zext(builder, arg_val, ext_param_ty)
arg_val = mlirlite.build_zext(builder, arg_val, ext_param_ty)
else:
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, ext_param_ty, arg)
elif found_func is not None:
@@ -1152,14 +1152,14 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# f32 提升为 f64。若按原窄类型传,调用点只写 4 字节进 8 字节槽,
# 高 4 字节残留旧栈数据,va_arg(i64) 读到垃圾(如 DefineTest
# PAGE=%d 读到 0x400921FB00001000,高位是 PI 残留)。
# 对齐 TPC FuncGen/Python-llvmlite 的 ABI 自动提升。
# 对齐 TPC FuncGen/Python-mlirlite 的 ABI 自动提升。
ab_va: int = self.Gen.ExprGenBase.get_llvm_type_bits(arg_val.Ty)
af_va: int = self.Gen.ExprGenBase.get_llvm_float_bits(arg_val.Ty)
i64_va: llvmlite.LLVMType* = llvmlite.Int64(pool)
i64_va: mlirlite.LLVMType* = mlirlite.Int64(pool)
if ab_va != 0 and ab_va < 64:
arg_val = llvmlite.build_sext(builder, arg_val, i64_va)
arg_val = mlirlite.build_sext(builder, arg_val, i64_va)
elif af_va == 32:
arg_val = llvmlite.build_fpext(builder, arg_val, llvmlite.Double(pool))
arg_val = mlirlite.build_fpext(builder, arg_val, mlirlite.Double(pool))
arg_val.Next = None
if head is None:
head = arg_val
@@ -1245,13 +1245,13 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# 交由下方 `elif found_func is not None` 分支按真实形参数零值兜底。
if found_func is not None and df_default_count > 0:
dfx_cnt: int = 0
dfx_p: llvmlite.Param* = llvmlite.function_get_param_head(found_func)
dfx_p: mlirlite.Param* = mlirlite.function_get_param_head(found_func)
while dfx_p is not None:
dfx_nm: str = llvmlite.param_get_name(dfx_p)
dfx_nm: str = mlirlite.param_get_name(dfx_p)
if dfx_nm is None or (string.strcmp(dfx_nm, "%__eh_msg_out__") != 0
and string.strcmp(dfx_nm, "%__eh_code_out__") != 0):
dfx_cnt += 1
dfx_p = llvmlite.param_get_next(dfx_p)
dfx_p = mlirlite.param_get_next(dfx_p)
if dfx_cnt > 0 and dfx_cnt != df_param_count:
df_defaults = None
df_default_count = 0
@@ -1263,7 +1263,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
df_param_idx: int = df_offset + df_di
if df_param_idx >= can:
# 优先用 stdlib 常量快照重建(gd_entry.Defaults 的 pool 内 AST 可能已被 reset 回收)
df_arg_val: llvmlite.Value* = None
df_arg_val: mlirlite.Value* = None
if gd_entry is not None:
df_arg_val = self.Gen.CallGenLeafKit._build_const_from_snapshot(pool, mod, gd_entry, df_di, trans, builder)
if df_arg_val is None and df_defaults is not None:
@@ -1287,24 +1287,24 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
elif found_func is not None:
# 默认参数缺失/表信息不全时的零值兜底:函数表有参数数但无默认值记录、或调用方先于定义文件编译导致查不到默认值时,用 found_func 实际参数数(stub declare,与 define 一致)兜底并缺参填零值(对齐 TPC _fill_default_args 语义)。注意排除 EH 输出参数(%__eh_msg_out__/%__eh_code_out__),否则会与 _emit_eh_guarded_call 追加的真实 EH 实参重复导致 ABI 错位
fc_cnt: int = 0
fc_p: llvmlite.Param* = llvmlite.function_get_param_head(found_func)
fc_p: mlirlite.Param* = mlirlite.function_get_param_head(found_func)
while fc_p is not None:
fp_nm_z: str = llvmlite.param_get_name(fc_p)
fp_nm_z: str = mlirlite.param_get_name(fc_p)
if fp_nm_z is None or (string.strcmp(fp_nm_z, "%__eh_msg_out__") != 0
and string.strcmp(fp_nm_z, "%__eh_code_out__") != 0):
fc_cnt += 1
fc_p = llvmlite.param_get_next(fc_p)
fc_p = mlirlite.param_get_next(fc_p)
if fc_cnt == 0:
fc_cnt = df_param_count if df_param_count > 0 else 0
if can < fc_cnt:
fp_z: llvmlite.Param* = llvmlite.function_get_param_head(found_func)
fp_z: mlirlite.Param* = mlirlite.function_get_param_head(found_func)
fpi_z: int = 0
while fp_z is not None and fpi_z < can:
fp_z = llvmlite.param_get_next(fp_z)
fp_z = mlirlite.param_get_next(fp_z)
fpi_z += 1
while fp_z is not None and fpi_z < fc_cnt:
zero_ty_z: llvmlite.LLVMType* = llvmlite.param_get_ty(fp_z)
zero_val_z: llvmlite.Value* = llvmlite.ConstZero(pool, zero_ty_z)
zero_ty_z: mlirlite.LLVMType* = mlirlite.param_get_ty(fp_z)
zero_val_z: mlirlite.Value* = mlirlite.ConstZero(pool, zero_ty_z)
if zero_val_z is not None:
zero_val_z.Next = None
if head is None:
@@ -1313,7 +1313,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
tail.Next = zero_val_z
tail = zero_val_z
can += 1 # 零值兜底实参同样计入实参数(同默认实参)
fp_z = llvmlite.param_get_next(fp_z)
fp_z = mlirlite.param_get_next(fp_z)
fpi_z += 1
# 使用模块中的实际函数名(可能带 SHA1 前缀,如 "83210a72e829a086.atoi")
@@ -1328,7 +1328,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# 用于在别名处理后重新推断返回类型,避免 _infer_external_func_ret_ty 用别名匹配失败
orig_func_name: str = None
if found_func is not None:
found_name: str = llvmlite.function_get_name(found_func)
found_name: str = mlirlite.function_get_name(found_func)
if found_name is not None:
call_name = found_name
# CExport 裸名兜底:跨模块 stub declare 可能带 SHA1 前缀
@@ -1606,7 +1606,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# 别名附加尝试:仅作为 mangled 精确解析前的临时推断(fatal_if_unknown=0)。
# 若 call_name 是 mangled,L1272 起的 text.ll/vpi 精确解析会覆盖并 fail-fast;
# 未命中时保持白名单/默认 i32 由后续路径兜底。
re_inferred_ty: llvmlite.LLVMType* = self.Gen.CallGenLib._infer_external_func_ret_ty(pool, orig_func_name, node, 0)
re_inferred_ty: mlirlite.LLVMType* = self.Gen.CallGenLib._infer_external_func_ret_ty(pool, orig_func_name, node, 0)
if re_inferred_ty is not None:
call_ret_ty = re_inferred_ty
# ============================================================
@@ -1643,15 +1643,15 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
if string.strncmp(cf_sha1, trans.ModuleSha1, 16) == 0:
is_local_mod = 1
if is_local_mod != 0:
local_fn: llvmlite.Function* = self.find_func_in_module(mod, call_name)
local_fn: mlirlite.Function* = self.find_func_in_module(mod, call_name)
if local_fn is not None and local_fn.RetTy is not None:
call_ret_ty = local_fn.RetTy
else:
cf_vpi: llvmlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, cf_sha1, None, cf_bare)
cf_vpi: mlirlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, cf_sha1, None, cf_bare)
if cf_vpi is not None:
call_ret_ty = cf_vpi
else:
cf_ret: llvmlite.LLVMType* = self._LookupMethodRetTyFromTextLL(pool, cf_sha1, None, cf_bare, 1)
cf_ret: mlirlite.LLVMType* = self._LookupMethodRetTyFromTextLL(pool, cf_sha1, None, cf_bare, 1)
if cf_ret is not None:
call_ret_ty = cf_ret
else:
+56 -56
View File
@@ -3,7 +3,7 @@ import lib.core.Gen.GenApi as GenApi
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdio
@@ -38,13 +38,13 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
# call_head/call_count: 已构建好的参数链表(如 getter 只有 obj 一个参数)
# ============================================================
def _translate_property_call(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
class_name: str,
method_name: str,
call_head: llvmlite.Value*,
call_head: mlirlite.Value*,
call_count: int,
trans: HT.Translator*) -> llvmlite.Value*:
trans: HT.Translator*) -> mlirlite.Value*:
"""翻译属性/静态方法调用,返回 call 结果 Value"""
if pool is None or builder is None or class_name is None or method_name is None: return None
@@ -54,12 +54,12 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, method_name)
# 查找函数(精确/后缀匹配)
found_func: llvmlite.Function* = self.find_func_in_module(mod, lookup_name)
found_func: mlirlite.Function* = self.find_func_in_module(mod, lookup_name)
# 确定调用名
call_name: str = lookup_name
if found_func is not None:
found_name: str = llvmlite.function_get_name(found_func)
found_name: str = mlirlite.function_get_name(found_func)
if found_name is not None:
call_name = found_name
else:
@@ -73,25 +73,25 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
call_name = mangled_pc
# 确定返回类型
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
call_ret_ty: llvmlite.LLVMType* = i32_ty
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
call_ret_ty: mlirlite.LLVMType* = i32_ty
if found_func is not None:
frt: llvmlite.LLVMType* = llvmlite.function_get_ret_ty(found_func)
frt: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(found_func)
if frt is not None:
call_ret_ty = frt
else:
sp_ty1: llvmlite.LLVMType* = self._special_method_ret_ty(pool, class_name, method_name)
sp_ty1: mlirlite.LLVMType* = self._special_method_ret_ty(pool, class_name, method_name)
if sp_ty1 is not None:
call_ret_ty = sp_ty1
else:
cls_sha1_rt: str = self.Gen.StructGen.get_struct_sha1(class_name)
# 权威来源:vpi stub 返回注解缓存(方法定义处,不硬编码白名单)
vpi_ret_ty: llvmlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, cls_sha1_rt, class_name, method_name)
vpi_ret_ty: mlirlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, cls_sha1_rt, class_name, method_name)
if vpi_ret_ty is not None:
call_ret_ty = vpi_ret_ty
else:
# 回退:依赖模块 text.ll 的 define 行解析(vpi 未覆盖的历史形态)
looked_up_ty: llvmlite.LLVMType* = self._LookupMethodRetTyFromTextLL(pool, cls_sha1_rt, class_name, method_name)
looked_up_ty: mlirlite.LLVMType* = self._LookupMethodRetTyFromTextLL(pool, cls_sha1_rt, class_name, method_name)
if looked_up_ty is not None:
call_ret_ty = looked_up_ty
else:
@@ -99,7 +99,7 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
# 保持默认 i32(build_call(Void) 返回 None 会破坏表达式翻译)。
if cls_sha1_rt is None \
or self._dep_text_ll_exists(pool, cls_sha1_rt) == 0:
call_ret_ty = llvmlite.Int32(pool)
call_ret_ty = mlirlite.Int32(pool)
else:
call_ret_ty = self._fail_method_ret_ty(method_name)
@@ -107,32 +107,32 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
# 一致)。例如 from_long(10) 的 i32 字面量 → i64 形参(v: t.CLong),
# 不转换则 call(i32) 与 declare(i64) 不匹配,llc 报参数类型错误。
# 目标函数优先用已找到的 found_func,否则按 mangled 调用名查模块 declare。
tgt_func_pc: llvmlite.Function* = found_func
tgt_func_pc: mlirlite.Function* = found_func
if tgt_func_pc is None:
tgt_func_pc = self.find_func_in_module(mod, call_name)
if tgt_func_pc is not None:
prev_pc: llvmlite.Value* = None
cur_arg_pc: llvmlite.Value* = call_head
cur_param_pc: llvmlite.Param* = llvmlite.function_get_param_head(tgt_func_pc)
prev_pc: mlirlite.Value* = None
cur_arg_pc: mlirlite.Value* = call_head
cur_param_pc: mlirlite.Param* = mlirlite.function_get_param_head(tgt_func_pc)
while cur_arg_pc is not None and cur_param_pc is not None:
param_ty_pc: llvmlite.LLVMType* = llvmlite.param_get_ty(cur_param_pc)
param_ty_pc: mlirlite.LLVMType* = mlirlite.param_get_ty(cur_param_pc)
if param_ty_pc is not None and cur_arg_pc.Ty is not None:
coerced_pc: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, cur_arg_pc, param_ty_pc)
coerced_pc: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, cur_arg_pc, param_ty_pc)
if coerced_pc is not None and coerced_pc != cur_arg_pc:
# 保持链表完整性:新 Value 继承原节点的 Next,前驱指向新节点
llvmlite.value_set_next(coerced_pc, cur_arg_pc.Next)
mlirlite.value_set_next(coerced_pc, cur_arg_pc.Next)
if prev_pc is None:
call_head = coerced_pc
else:
llvmlite.value_set_next(prev_pc, coerced_pc)
mlirlite.value_set_next(prev_pc, coerced_pc)
cur_arg_pc = coerced_pc
prev_pc = cur_arg_pc
cur_arg_pc = cur_arg_pc.Next
cur_param_pc = llvmlite.param_get_next(cur_param_pc)
cur_param_pc = mlirlite.param_get_next(cur_param_pc)
# 确保 declare 存在,然后调用
self._ensure_method_declare(pool, mod, call_name, call_ret_ty, call_head, call_count)
return llvmlite.build_call(builder, call_name, call_head, call_count, call_ret_ty, 0)
return mlirlite.build_call(builder, call_name, call_head, call_count, call_ret_ty, 0)
# ============================================================
# _resolve_obj_class_name — 解析对象表达式的类名(短名)
#
@@ -185,12 +185,12 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
# ============================================================
def _try_property_getter_attr(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
at_node: ast.Attribute*,
obj_ptr: llvmlite.Value*,
obj_ptr: mlirlite.Value*,
trans: HT.Translator*,
fallback_class_name: str = None) -> llvmlite.Value*:
fallback_class_name: str = None) -> mlirlite.Value*:
"""尝试 property getter 属性访问,返回调用结果 Value;非 getter 返回 None
fallback_class_name: 对象表达式非 Name 时从 LLVM 类型解析出的类名兜底。
@@ -206,7 +206,7 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
if meta & GenTypes.META_PROP_GETTER == 0:
return None
# 单参数调用: obj → getter
llvmlite.value_set_next(obj_ptr, None)
mlirlite.value_set_next(obj_ptr, None)
return self._translate_property_call(pool, builder, mod, class_name, at_node.attr, obj_ptr, 1, trans)
# ============================================================
# _try_property_setter — 尝试将 obj.attr = v 翻译为 property setter 调用
@@ -217,10 +217,10 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
# ============================================================
def _try_property_setter(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
target_attr: ast.Attribute*,
rhs_val: llvmlite.Value*,
rhs_val: mlirlite.Value*,
trans: HT.Translator*) -> int:
"""尝试 property setter 赋值,返回 1=已处理(生成调用)"""
if pool is None or builder is None or mod is None or trans is None: return 0
@@ -230,12 +230,12 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
meta: int = self.Gen.ClassGenBase.lookup_method_meta(class_name, target_attr.attr)
if meta & GenTypes.META_PROP_SETTER == 0: return 0
# 翻译对象值(self 参数)
obj_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, target_attr.value, None, 0, trans)
obj_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, target_attr.value, None, 0, trans)
if obj_val is None: return 0
# 构建参数链表: obj → rhs
llvmlite.value_set_next(obj_val, None)
llvmlite.value_set_next(rhs_val, None)
llvmlite.value_set_next(obj_val, rhs_val)
mlirlite.value_set_next(obj_val, None)
mlirlite.value_set_next(rhs_val, None)
mlirlite.value_set_next(obj_val, rhs_val)
# setter 函数名带 $set 后缀
setter_name_buf: str = pool.alloc(128)
if setter_name_buf is None: return 0
@@ -252,8 +252,8 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
# ============================================================
def _try_property_deleter(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
target_attr: ast.Attribute*,
trans: HT.Translator*) -> int:
"""尝试 property deleter 删除,返回 1=已处理(生成调用)"""
@@ -264,9 +264,9 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
meta: int = self.Gen.ClassGenBase.lookup_method_meta(class_name, target_attr.attr)
if meta & GenTypes.META_PROP_DELETER == 0: return 0
# 翻译对象值(self 参数)
obj_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, target_attr.value, None, 0, trans)
obj_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, target_attr.value, None, 0, trans)
if obj_val is None: return 0
llvmlite.value_set_next(obj_val, None)
mlirlite.value_set_next(obj_val, None)
# deleter 函数名带 $del 后缀
del_name_buf: str = pool.alloc(128)
if del_name_buf is None: return 0
@@ -283,12 +283,12 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
# ============================================================
def _translate_static_class_call(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
class_name: str,
method_name: str,
cl: ast.Call*,
trans: HT.Translator*) -> llvmlite.Value*:
trans: HT.Translator*) -> mlirlite.Value*:
"""翻译类名静态/类方法调用,返回 call 结果 Value;非静态/类方法返回 None"""
if pool is None or builder is None or mod is None or trans is None: return None
if class_name is None or method_name is None or cl is None: return None
@@ -300,16 +300,16 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
if is_static == 0 and is_class == 0: return None
# 构建参数链表
head: llvmlite.Value* = None
head: mlirlite.Value* = None
total_count: int = 0
# @classmethod: 插入栈上分配的类实例指针作为 cls 参数
if is_class != 0:
struct_ty_cc: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(class_name)
struct_ty_cc: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(class_name)
if struct_ty_cc is None: return None
cls_ptr: llvmlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, struct_ty_cc)
cls_ptr: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, struct_ty_cc)
if cls_ptr is None: return None
llvmlite.value_set_next(cls_ptr, None)
mlirlite.value_set_next(cls_ptr, None)
head = cls_ptr
total_count = 1
@@ -318,18 +318,18 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
can: sizet = 0
if cargs is not None:
can = len(cargs)
tail: llvmlite.Value* = head
tail: mlirlite.Value* = head
for ai in range(can):
arg_node: ast.AST* = cargs.get(ai)
if arg_node is None: continue
arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg_node, None, 0, trans)
arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg_node, None, 0, trans)
if arg_val is None: continue
llvmlite.value_set_next(arg_val, None)
mlirlite.value_set_next(arg_val, None)
if head is None:
head = arg_val
tail = arg_val
else:
llvmlite.value_set_next(tail, arg_val)
mlirlite.value_set_next(tail, arg_val)
tail = arg_val
total_count += 1
@@ -387,13 +387,13 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
# _resolve_generic_receiver_name:解析接收者实际泛型特化名(IR 真值)——接收者实际 LLVM 结构体类型名比可能退化的注解/注册名可靠,故泛型判定以此为准:去 sha1 前缀取 '[' 前基名,基名是已注册泛型模板时含类型实参 ⇒ 返回实际特化名,无类型实参 ⇒ fail-fast(D25);基名非泛型模板或实际类型不可得 ⇒ 返回 None(调用方各自回退)。与 CallGenCall._translate_method_call 的 D25 分派修复共用本函数(唯一口径)
def _resolve_generic_receiver_name(self, pool: memhub.MemBuddy*,
struct_ty: llvmlite.LLVMType*,
struct_ty: mlirlite.LLVMType*,
method_name: str,
cl: ast.Call*) -> str:
"""返回实际泛型特化名(去 sha1)或 None;裸泛型基类 fail-fast"""
if struct_ty is None:
return None
ty_nm: str = llvmlite.get_struct_name(struct_ty)
ty_nm: str = mlirlite.get_struct_name(struct_ty)
if ty_nm is None or ty_nm[0] == '\0':
return None
short_nm: str = self._strip_module_sha1_prefix(ty_nm)
@@ -427,14 +427,14 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
# _is_list_builtin_receiver:基于接收者实际类型判定 list 内建方法,判据与 _resolve_generic_receiver_name 同源——优先采用接收者实际 LLVM 结构体类型名(去 sha1 判基名),不可得时回退注解名/注册名判定。返回 1=list 内置方法 / 0=非
def _is_list_builtin_receiver(self, pool: memhub.MemBuddy*,
recv_val: llvmlite.Value*,
recv_val: mlirlite.Value*,
fallback_name: str,
method_name: str,
cl: ast.Call*) -> int:
"""基于接收者实际类型判定 list 内建方法(实际类型不可得回退注解名)"""
sty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(recv_val)
sty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(recv_val)
if sty is not None:
ty_nm: str = llvmlite.get_struct_name(sty)
ty_nm: str = mlirlite.get_struct_name(sty)
if ty_nm is not None and ty_nm[0] != '\0':
# 泛型模板接收者:裸基类 fail-fast;含实参用实际特化名
act_nm: str = self._resolve_generic_receiver_name(pool, sty, method_name, cl)
+82 -82
View File
@@ -1,7 +1,7 @@
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import lib.core.Gen.Translator as HT
@@ -23,12 +23,12 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
# ============================================================
def _va_arg_get_alloca_ptr(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
arg_node: ast.AST*,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator*) -> llvmlite.Value*:
trans: HT.Translator*) -> mlirlite.Value*:
"""获取 va_list 变量的 alloca 指针(不 load)
va_arg/va_start/va_end 需要的是 va_list 对象的地址(alloca 指针),
@@ -40,14 +40,14 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
if arg_node.kind() == ast.ASTKind.Name:
nm: ast.Name* = ast.Name*(arg_node)
if nm.id is not None:
alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
if alloca is not None:
return alloca
# 回退:translate_value(可能返回 load 后的值,仅适用于已是指针的情况)
return self.Gen.ExprGen.translate_value(builder, pool, mod, arg_node, funcs_ptr, func_count, trans)
def _resolve_va_arg_type(self, pool: memhub.MemBuddy*,
type_node: ast.AST*,
trans: HT.Translator*) -> llvmlite.LLVMType*:
trans: HT.Translator*) -> mlirlite.LLVMType*:
"""解析 va_arg/arg 的类型参数为 LLVMType
支持的类型表达式:
@@ -59,41 +59,41 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
无类型参数时默认 i32(vsnprintf 中 va_arg(ap) 常用于读取 i32)
"""
if type_node is None:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
# 使用 HandlesType.resolve_annotation_type 解析类型表达式
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, type_node, trans._imported_modules, trans._from_imports, trans, 0)
resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, type_node, trans._imported_modules, trans._from_imports, trans, 0)
if resolved is not None:
return resolved
# 类型节点存在但解析失败:fail-fast,绝不回退 i32(会按错宽度读变参槽位)
self.Gen.TypeGenErr.fatal_error(type_node, "va_arg 类型解析失败", "TypeError")
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
def _translate_va_arg_sugar(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
cl: ast.Call*,
cargs: list[ast.AST*]*,
can: sizet,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator*) -> llvmlite.Value*:
trans: HT.Translator*) -> mlirlite.Value*:
"""va_arg(ap, type) / va_arg(ap) → %N = va_arg <ap_ty> <ap>, <type>
生成 LLVM va_arg 指令,从 va_list 读取下一个变长参数。
"""
if can == 0 or cargs is None:
return llvmlite.const_int32(pool, 0)
return mlirlite.const_int32(pool, 0)
# 第一个参数:va_list(求值为 i8* 地址值,对齐 TPC _HandleVaArgLlvm)
# 当前函数 *args:translate_value 经 vararg 名映射直接返回 va_list 缓冲区地址;
# 转发场景(sprintf → vsnprintf 的 ap 参数):translate_value load 参数得到地址值。
ap_node: ast.AST* = cargs.get(0)
ap_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, ap_node, None, 0, trans)
ap_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, ap_node, None, 0, trans)
if ap_val is None:
return llvmlite.const_int32(pool, 0)
ap_ptr: llvmlite.Value* = ap_val
return mlirlite.const_int32(pool, 0)
ap_ptr: mlirlite.Value* = ap_val
# 第二个参数:目标类型(可选,默认 i32)
arg_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
arg_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
if can >= 2:
type_node: ast.AST* = cargs.get(1)
arg_ty = self._resolve_va_arg_type(pool, type_node, trans)
@@ -102,125 +102,125 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
# 再 trunc 回目标宽度——否则返回 8 字节含高位垃圾,%d/%i 语义错误
# (viperlib vsnprintf %d 非 long 分支 `int64(va_arg(ap, int))`
# 编译成直接 va_arg i64,高 32 位未定义 → 负数当大正数 A6 根因)。
read_ty: llvmlite.LLVMType* = arg_ty
read_ty: mlirlite.LLVMType* = arg_ty
abits_va: int = self.Gen.ExprGenBase.get_llvm_type_bits(arg_ty)
if abits_va != 0 and abits_va < 64:
read_ty = llvmlite.Int64(pool)
va_raw: llvmlite.Value* = llvmlite.build_va_arg(builder, ap_ptr, read_ty)
read_ty = mlirlite.Int64(pool)
va_raw: mlirlite.Value* = mlirlite.build_va_arg(builder, ap_ptr, read_ty)
if va_raw is None:
return llvmlite.const_int32(pool, 0)
return mlirlite.const_int32(pool, 0)
# 8 字节槽 → 目标宽度(低 bits 位);调用方 int64(...) 会再 sext/zext
return llvmlite.build_trunc(builder, va_raw, arg_ty)
return mlirlite.build_trunc(builder, va_raw, arg_ty)
# 生成 va_arg 指令
return llvmlite.build_va_arg(builder, ap_ptr, read_ty)
return mlirlite.build_va_arg(builder, ap_ptr, read_ty)
def _translate_arg_sugar(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
cl: ast.Call*,
cargs: list[ast.AST*]*,
can: sizet,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator*) -> llvmlite.Value*:
trans: HT.Translator*) -> mlirlite.Value*:
"""arg(type) → %N = va_arg <va_list_ty> <trans._va_list_ptr>, <type>
使用当前函数的隐式 va_list(trans._va_list_ptr),
简化 *args 函数体内的 va_arg 调用。
"""
if trans._va_list_ptr is None:
return llvmlite.const_int32(pool, 0)
return mlirlite.const_int32(pool, 0)
# 第一个参数:目标类型(可选,默认 i32)
arg_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
arg_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
if can >= 1 and cargs is not None:
type_node: ast.AST* = cargs.get(0)
arg_ty = self._resolve_va_arg_type(pool, type_node, trans)
# Win64 变参槽位为 8 字节:<64 位整数按 i64 读取(与 _translate_va_arg_sugar 一致),
# 再 trunc 回目标宽度(%d/%i 高位垃圾 A6 修复,见 _translate_va_arg_sugar)
read_ty: llvmlite.LLVMType* = arg_ty
read_ty: mlirlite.LLVMType* = arg_ty
abits_arg: int = self.Gen.ExprGenBase.get_llvm_type_bits(arg_ty)
if abits_arg != 0 and abits_arg < 64:
read_ty = llvmlite.Int64(pool)
arg_raw: llvmlite.Value* = llvmlite.build_va_arg(builder, trans._va_list_ptr, read_ty)
read_ty = mlirlite.Int64(pool)
arg_raw: mlirlite.Value* = mlirlite.build_va_arg(builder, trans._va_list_ptr, read_ty)
if arg_raw is None:
return llvmlite.const_int32(pool, 0)
return llvmlite.build_trunc(builder, arg_raw, arg_ty)
return mlirlite.const_int32(pool, 0)
return mlirlite.build_trunc(builder, arg_raw, arg_ty)
# 生成 va_arg 指令(使用 trans._va_list_ptr 作为 va_list 地址)
return llvmlite.build_va_arg(builder, trans._va_list_ptr, read_ty)
return mlirlite.build_va_arg(builder, trans._va_list_ptr, read_ty)
def _translate_va_start_sugar(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
cargs: list[ast.AST*]*,
can: sizet,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator*) -> llvmlite.Value*:
trans: HT.Translator*) -> mlirlite.Value*:
"""va_start(ap, last_arg) → call void @llvm.va_start(i8* %ap)
初始化 va_list。第二个参数 last_arg 在 LLVM intrinsic 中不使用(C 宏兼容)。
"""
if can == 0 or cargs is None:
return llvmlite.const_int32(pool, 0)
return mlirlite.const_int32(pool, 0)
# 第一个参数:va_list 指针(获取 alloca,不 load)
ap_node: ast.AST* = cargs.get(0)
ap_ptr: llvmlite.Value* = self._va_arg_get_alloca_ptr(pool, builder, mod, ap_node, funcs_ptr, func_count, trans)
ap_ptr: mlirlite.Value* = self._va_arg_get_alloca_ptr(pool, builder, mod, ap_node, funcs_ptr, func_count, trans)
if ap_ptr is None:
return llvmlite.const_int32(pool, 0)
return mlirlite.const_int32(pool, 0)
# bitcast 到 i8*(@llvm.va_start 接受 i8*)
i8_ty_vs: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty_vs: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty_vs)
ap_i8: llvmlite.Value* = llvmlite.build_bitcast(builder, ap_ptr, i8_ptr_ty_vs)
i8_ty_vs: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty_vs: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_vs)
ap_i8: mlirlite.Value* = mlirlite.build_bitcast(builder, ap_ptr, i8_ptr_ty_vs)
if ap_i8 is None:
return llvmlite.const_int32(pool, 0)
return mlirlite.const_int32(pool, 0)
void_ty_vs: llvmlite.LLVMType* = llvmlite.Void(pool)
llvmlite.build_call(builder, "llvm.va_start", ap_i8, 1, void_ty_vs, 0)
return llvmlite.const_int32(pool, 0)
void_ty_vs: mlirlite.LLVMType* = mlirlite.Void(pool)
mlirlite.build_call(builder, "llvm.va_start", ap_i8, 1, void_ty_vs, 0)
return mlirlite.const_int32(pool, 0)
def _translate_va_end_sugar(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
cargs: list[ast.AST*]*,
can: sizet,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator*) -> llvmlite.Value*:
trans: HT.Translator*) -> mlirlite.Value*:
"""va_end(ap) → call void @llvm.va_end(i8* %ap)
清理 va_list。在大多数平台上是 no-op,但调用它是良好的 C ABI 习惯。
"""
if can == 0 or cargs is None:
return llvmlite.const_int32(pool, 0)
return mlirlite.const_int32(pool, 0)
# 第一个参数:va_list 指针(获取 alloca,不 load)
ap_node: ast.AST* = cargs.get(0)
ap_ptr: llvmlite.Value* = self._va_arg_get_alloca_ptr(pool, builder, mod, ap_node, funcs_ptr, func_count, trans)
ap_ptr: mlirlite.Value* = self._va_arg_get_alloca_ptr(pool, builder, mod, ap_node, funcs_ptr, func_count, trans)
if ap_ptr is None:
return llvmlite.const_int32(pool, 0)
return mlirlite.const_int32(pool, 0)
# bitcast 到 i8*(@llvm.va_end 接受 i8*)
i8_ty_ve: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty_ve: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty_ve)
ap_i8: llvmlite.Value* = llvmlite.build_bitcast(builder, ap_ptr, i8_ptr_ty_ve)
i8_ty_ve: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty_ve: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_ve)
ap_i8: mlirlite.Value* = mlirlite.build_bitcast(builder, ap_ptr, i8_ptr_ty_ve)
if ap_i8 is None:
return llvmlite.const_int32(pool, 0)
return mlirlite.const_int32(pool, 0)
void_ty_ve: llvmlite.LLVMType* = llvmlite.Void(pool)
llvmlite.build_call(builder, "llvm.va_end", ap_i8, 1, void_ty_ve, 0)
return llvmlite.const_int32(pool, 0)
def _get_func_fixed_param_count(self, func: llvmlite.Function*) -> int:
void_ty_ve: mlirlite.LLVMType* = mlirlite.Void(pool)
mlirlite.build_call(builder, "llvm.va_end", ap_i8, 1, void_ty_ve, 0)
return mlirlite.const_int32(pool, 0)
def _get_func_fixed_param_count(self, func: mlirlite.Function*) -> int:
"""获取函数的固定参数数量(遍历 Params 链表)"""
if func is None:
return 0
count: int = 0
param: llvmlite.Param* = llvmlite.function_get_param_head(func)
param: mlirlite.Param* = mlirlite.function_get_param_head(func)
while param is not None:
count += 1
param = llvmlite.param_get_next(param)
param = mlirlite.param_get_next(param)
return count
def _get_known_vararg_cfunc_fixed_count(self, name: str) -> int:
"""已知变参 C 库函数固定参数个数(-1=未知)
@@ -241,7 +241,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
return -1
def _get_known_vararg_cfunc_param_ty(self, pool: memhub.MemBuddy*,
name: str, idx: int) -> llvmlite.LLVMType*:
name: str, idx: int) -> mlirlite.LLVMType*:
"""已知变参 C 库函数第 idx 个固定参数类型(变参位置/未知返回 None)
固定参数类型是 C ABI 硬约束(snprintf 的 size 为 i64),stub 未注入
@@ -249,8 +249,8 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
"""
if pool is None or name is None or idx < 0:
return None
i8_ptr_kv: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
i64_kv: llvmlite.LLVMType* = llvmlite.Int64(pool)
i8_ptr_kv: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
i64_kv: mlirlite.LLVMType* = mlirlite.Int64(pool)
if string.strcmp(name, "snprintf") == 0:
if idx == 0:
return i8_ptr_kv
@@ -267,10 +267,10 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
return None
return None
def _check_and_promote_variadic_call(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
call_name: str,
head: llvmlite.Value*,
head: mlirlite.Value*,
can: sizet,
arg_nodes: list[ast.AST*]* = None,
self_offset: int = 0,
@@ -287,7 +287,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
if mod is None or call_name is None or head is None:
return 0
# 查找函数对象
func: llvmlite.Function* = self.find_func_in_module(mod, call_name)
func: mlirlite.Function* = self.find_func_in_module(mod, call_name)
fixed_count: int = -1
if func is not None and func.IsVarArg == 1:
fixed_count = self._get_func_fixed_param_count(func)
@@ -302,8 +302,8 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
return 1
# 遍历到第 fixed_count 个节点(固定参数的最后一个)
cur: llvmlite.Value* = head
prev: llvmlite.Value* = None
cur: mlirlite.Value* = head
prev: mlirlite.Value* = None
idx: int = 0
while cur is not None and idx < fixed_count:
prev = cur
@@ -312,12 +312,12 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
# cur 指向第 fixed_count+1 个节点(第一个变长参数)
# 对变长参数进行 C ABI 提升
i32_ty_promote: llvmlite.LLVMType* = llvmlite.Int32(pool)
double_ty_promote: llvmlite.LLVMType* = llvmlite.Double(pool)
i32_ty_promote: mlirlite.LLVMType* = mlirlite.Int32(pool)
double_ty_promote: mlirlite.LLVMType* = mlirlite.Double(pool)
v_idx: int = fixed_count
while cur is not None:
next_node: llvmlite.Value* = cur.Next
promoted: llvmlite.Value* = cur
next_node: mlirlite.Value* = cur.Next
promoted: mlirlite.Value* = cur
# C ABI integer promotion: i8/i16 → i32
arg_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(cur.Ty)
if arg_bits != 0 and arg_bits < 32:
@@ -333,7 +333,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
if self.Gen.ExprGenOps._node_type_unsigned(pool, an_va, trans) != 0:
is_u_va = 1
if is_u_va != 0:
promoted = llvmlite.build_zext(builder, cur, i32_ty_promote)
promoted = mlirlite.build_zext(builder, cur, i32_ty_promote)
else:
# is_u_va 判断失败(arg_nodes/trans 缺失或变量注解查不到)时,
# i8 按系统编程惯例默认 zext(对齐 should_zext_widen 的
@@ -341,7 +341,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
# 否则 printf("%02x", buf[i]) 中 uint8 字节被 sext 成
# 0xFFFFFFF3,哈希摘要输出 ffffffXX 垃圾。
if self.Gen.ExprGenBase.get_llvm_type_bits(cur.Ty) == 8:
promoted = llvmlite.build_zext(builder, cur, i32_ty_promote)
promoted = mlirlite.build_zext(builder, cur, i32_ty_promote)
else:
promoted = self.Gen.ExprGenBase.coerce_to_type(builder, cur, i32_ty_promote, None)
if promoted is not None:
@@ -361,10 +361,10 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
# 调用方必须写满 8 字节槽,否则高 4 字节残留旧栈数据,%d 读到
# 0x7ff700000052 类垃圾(clean 日志根因;对齐 CallGenMixin
# L798-811 的 found_func.IsVarArg 提升)。
i64_ty_promote: llvmlite.LLVMType* = llvmlite.Int64(pool)
i64_ty_promote: mlirlite.LLVMType* = mlirlite.Int64(pool)
pb_va: int = self.Gen.ExprGenBase.get_llvm_type_bits(promoted.Ty)
if pb_va != 0 and pb_va < 64:
promoted_va2: llvmlite.Value* = None
promoted_va2: mlirlite.Value* = None
is_u_va2: int = 0
if arg_nodes is not None and trans is not None:
ast_idx_va2: int = v_idx - self_offset
@@ -374,9 +374,9 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
if self.Gen.ExprGenOps._node_type_unsigned(pool, an_va2, trans) != 0:
is_u_va2 = 1
if is_u_va2 != 0:
promoted_va2 = llvmlite.build_zext(builder, promoted, i64_ty_promote)
promoted_va2 = mlirlite.build_zext(builder, promoted, i64_ty_promote)
else:
promoted_va2 = llvmlite.build_sext(builder, promoted, i64_ty_promote)
promoted_va2 = mlirlite.build_sext(builder, promoted, i64_ty_promote)
if promoted_va2 is not None:
promoted_va2.Next = next_node
if prev is not None:
+42 -42
View File
@@ -1,7 +1,7 @@
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import viperlib
@@ -21,50 +21,50 @@ novirtual class CallGenVt(CallGenBase.CallGenBase):
# ============================================================
def _write_vtable_slot(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
obj_ptr: llvmlite.Value*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
obj_ptr: mlirlite.Value*,
class_name: str,
method_index: int,
func_val: llvmlite.Value*,
func_val: mlirlite.Value*,
trans: HT.Translator*) -> int:
"""生成 vtable 槽位写入(写时复制),成功返回 1"""
if pool is None or builder is None or mod is None or trans is None: return 0
if obj_ptr is None or class_name is None or func_val is None: return 0
if method_index < 0 or trans._cur_func is None: return 0
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
if i8_ty is None: return 0
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
if i8_ptr_ty is None: return 0
i8_ptr_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ptr_ty)
i8_ptr_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ptr_ty)
if i8_ptr_ptr_ty is None: return 0
method_count: int = self.Gen.StructGen.get_vtable_method_count(class_name)
if method_count <= 0: return 0
# 构造 vtable 类型 { i8*, i8*, ... }
# vtable 类型的字段链表是 llvmlite.ParamNode(new_param_node / paramnode_set_next /
# vtable 类型的字段链表是 mlirlite.ParamNode(new_param_node / paramnode_set_next /
# Struct 形参均为 rawptr[ParamNode])——原先误注解为 Function*。
vt_first: llvmlite.ParamNode* = None
vt_prev: llvmlite.ParamNode* = None
vt_first: mlirlite.ParamNode* = None
vt_prev: mlirlite.ParamNode* = None
for vi in range(method_count):
pn: llvmlite.ParamNode* = llvmlite.new_param_node(pool, i8_ptr_ty)
pn: mlirlite.ParamNode* = mlirlite.new_param_node(pool, i8_ptr_ty)
if pn is None: continue
if vt_first is None:
vt_first = pn
if vt_prev is not None:
llvmlite.paramnode_set_next(vt_prev, pn)
mlirlite.paramnode_set_next(vt_prev, pn)
vt_prev = pn
vtable_ty: llvmlite.LLVMType* = llvmlite.Struct(pool, vt_first, method_count, None)
vtable_ty: mlirlite.LLVMType* = mlirlite.Struct(pool, vt_first, method_count, None)
if vtable_ty is None:
return 0
# 对象 vtable 槽位(对象头 → i8**,vtable 指针总是第一个字段)
vtable_slot: llvmlite.Value* = llvmlite.build_bitcast(builder, obj_ptr, i8_ptr_ptr_ty)
vtable_slot: mlirlite.Value* = mlirlite.build_bitcast(builder, obj_ptr, i8_ptr_ptr_ty)
if vtable_slot is None: return 0
vtable_ptr: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty, vtable_slot)
vtable_ptr: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty, vtable_slot)
if vtable_ptr is None: return 0
# 类默认 vtable 地址(比较用)
class_vt: llvmlite.Value* = self.Gen.CallGenLeafKit._make_vtable_ref_i8(pool, builder, mod, class_name, trans)
class_vt: mlirlite.Value* = self.Gen.CallGenLeafKit._make_vtable_ref_i8(pool, builder, mod, class_name, trans)
if class_vt is None: return 0
cmp_vt: llvmlite.Value* = llvmlite.build_icmp(builder, llvmlite.ICMP_EQ, vtable_ptr, class_vt)
cmp_vt: mlirlite.Value* = mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, vtable_ptr, class_vt)
if cmp_vt is None: return 0
# 块名唯一化(create_block 不自动编号;同函数多次 vtable 写入(如
# devfs open/close/read/write 连续赋值)同名 label 冲突)
@@ -73,21 +73,21 @@ novirtual class CallGenVt(CallGenBase.CallGenBase):
vt_bb_buf3: str = pool.alloc(64)
if vt_bb_buf3 is None: return 0
viperlib.snprintf(vt_bb_buf3, 64, "vt.copy.%d", vtc3)
vt_copy_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, trans._cur_func, vt_bb_buf3)
vt_copy_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, trans._cur_func, vt_bb_buf3)
viperlib.snprintf(vt_bb_buf3, 64, "vt.skip.%d", vtc3)
vt_skip_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, trans._cur_func, vt_bb_buf3)
vt_skip_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, trans._cur_func, vt_bb_buf3)
if vt_copy_bb is None or vt_skip_bb is None: return 0
llvmlite.build_cond_br(builder, cmp_vt, vt_copy_bb, vt_skip_bb)
mlirlite.build_cond_br(builder, cmp_vt, vt_copy_bb, vt_skip_bb)
# copy 块:创建 internal 副本全局(zeroinit)+ memcpy + 对象指向副本
llvmlite.position_at_end(builder, vt_copy_bb)
mlirlite.position_at_end(builder, vt_copy_bb)
vtc: int = trans._label_counter
trans._label_counter = vtc + 1
vcopy_buf: str = pool.alloc(256)
if vcopy_buf is not None:
viperlib.snprintf(vcopy_buf, 256, "%s.vtable.copy.%d", class_name, vtc)
vcopy_gv: llvmlite.GlobalVariable* = llvmlite.new_global_variable(pool, vcopy_buf, vtable_ty)
vcopy_gv: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, vcopy_buf, vtable_ty)
if vcopy_gv is not None:
llvmlite.module_add_global(mod, vcopy_gv)
mlirlite.module_add_global(mod, vcopy_gv)
vcopy_gv.Linkage = None
vcopy_gv.Initializer = "zeroinitializer"
# 引用名必须带 @ 前缀:SSAValue 名原样输出,裸名
@@ -99,9 +99,9 @@ novirtual class CallGenVt(CallGenBase.CallGenBase):
vcopy_ref_nm = vcopy_buf
else:
viperlib.snprintf(vcopy_ref_nm, 272, "@%s", vcopy_buf)
vcopy_ref: llvmlite.Value* = llvmlite.SSAValue(pool, llvmlite.Ptr(pool, vtable_ty), vcopy_ref_nm)
vcopy_ref: mlirlite.Value* = mlirlite.SSAValue(pool, mlirlite.Ptr(pool, vtable_ty), vcopy_ref_nm)
if vcopy_ref is not None:
vcopy_i8: llvmlite.Value* = llvmlite.build_bitcast(builder, vcopy_ref, i8_ptr_ty)
vcopy_i8: mlirlite.Value* = mlirlite.build_bitcast(builder, vcopy_ref, i8_ptr_ty)
if vcopy_i8 is not None:
# ConstInt 的 name 必须是数字文本(如 "56"),不能是
# 标识符 "vtsz"——参数经 Name 原样输出,裸名 vtsz 无 %
@@ -109,28 +109,28 @@ novirtual class CallGenVt(CallGenBase.CallGenBase):
vtsz_buf: str = pool.alloc(32)
if vtsz_buf is not None:
viperlib.snprintf(vtsz_buf, 32, "%lld", method_count * 8)
vt_size: llvmlite.Value* = llvmlite.ConstInt(pool, llvmlite.Int64(pool), method_count * 8, vtsz_buf)
vt_size: mlirlite.Value* = mlirlite.ConstInt(pool, mlirlite.Int64(pool), method_count * 8, vtsz_buf)
if vt_size is not None:
self.Gen.CallGenLib._emit_llvm_memcpy_intrinsic(pool, builder, mod, vcopy_i8, class_vt, vt_size)
llvmlite.build_store(builder, vcopy_i8, vtable_slot)
llvmlite.build_br(builder, vt_skip_bb)
mlirlite.build_store(builder, vcopy_i8, vtable_slot)
mlirlite.build_br(builder, vt_skip_bb)
# skip 块:reload vtable → GEP 槽位 → store 函数指针(i8*)
llvmlite.position_at_end(builder, vt_skip_bb)
vt_ptr2: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty, vtable_slot)
mlirlite.position_at_end(builder, vt_skip_bb)
vt_ptr2: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty, vtable_slot)
if vt_ptr2 is None: return 0
vt_typed: llvmlite.Value* = llvmlite.build_bitcast(builder, vt_ptr2, llvmlite.Ptr(pool, vtable_ty))
vt_typed: mlirlite.Value* = mlirlite.build_bitcast(builder, vt_ptr2, mlirlite.Ptr(pool, vtable_ty))
if vt_typed is None: return 0
vt_slotp: llvmlite.Value* = llvmlite.build_gep_struct(builder, vtable_ty, i8_ptr_ty, vt_typed, method_index)
vt_slotp: mlirlite.Value* = mlirlite.build_gep_struct(builder, vtable_ty, i8_ptr_ty, vt_typed, method_index)
if vt_slotp is None: return 0
fptr_i8: llvmlite.Value* = llvmlite.build_bitcast(builder, func_val, i8_ptr_ty)
fptr_i8: mlirlite.Value* = mlirlite.build_bitcast(builder, func_val, i8_ptr_ty)
if fptr_i8 is not None:
llvmlite.build_store(builder, fptr_i8, vt_slotp)
mlirlite.build_store(builder, fptr_i8, vt_slotp)
return 1
def _write_vtable_attr(self, builder: llvmlite.IRBuilder*,
def _write_vtable_attr(self, builder: mlirlite.IRBuilder*,
pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
node: ast.AST*,
rhs_val: llvmlite.Value*,
rhs_val: mlirlite.Value*,
trans: HT.Translator*) -> int:
"""属性写入 obj.method = func:检测 vtable 方法并生成槽位写入(成功返回 1)"""
if node is None or builder is None or pool is None or mod is None: return 0
@@ -156,7 +156,7 @@ novirtual class CallGenVt(CallGenBase.CallGenBase):
vm_idx_v: int = self.Gen.StructGen.get_vtable_method_index(class_nm_v, at.attr)
if vm_idx_v < 0: return 0
# 解析 obj_ptr(对齐 get_attribute_ptr 前半段:Name 直接查 alloca)
obj_ptr_v: llvmlite.Value* = None
obj_ptr_v: mlirlite.Value* = None
if at.value.kind() == ast.ASTKind.Name:
obj_ptr_v = self.Gen.VarGen.lookup_var(trans.SymTab, (ast.Name*(at.value)).id)
else:
@@ -164,10 +164,10 @@ novirtual class CallGenVt(CallGenBase.CallGenBase):
if obj_ptr_v is None or obj_ptr_v.Ty is None: return 0
# X|t.CPtr 变量(Ptr(Ptr))load 解引用取对象指针
match obj_ptr_v.Ty:
case llvmlite.LLVMType.Ptr(inner_v):
case mlirlite.LLVMType.Ptr(inner_v):
match inner_v:
case llvmlite.LLVMType.Ptr(_):
obj_ptr_v = llvmlite.build_load(builder, inner_v, obj_ptr_v)
case mlirlite.LLVMType.Ptr(_):
obj_ptr_v = mlirlite.build_load(builder, inner_v, obj_ptr_v)
case _:
pass
case _:
+1 -1
View File
@@ -832,7 +832,7 @@ novirtual class ClassGenBase:
# 按位或合并:同一属性名先 @property(getter=4) 再 @x.setter(8)/
# @x.deleter(16) 会多次注册(如 Config.value / Counter.value)。
# 若整值替换,后注册的位会覆盖 GETTER 位 → _try_property_getter_attr
# 不再拦截 obj.prop → 落入字段查找失败返回 None → 上游 llvmlite
# 不再拦截 obj.prop → 落入字段查找失败返回 None → 上游 mlirlite
# 收到 NULL Value → 编译器进程段错误(BuiltinDecoratorTest Phase A 崩溃)。
flags_ptr[0] = flags_ptr[0] | meta
stdlib.free(key_buf)
+31 -31
View File
@@ -2,7 +2,7 @@ import lib.core.Gen.GenTypes as GenTypes
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdio
@@ -127,10 +127,10 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
# _ensure_field_types_in_module 遍历悬空字段 ParamNode 链表
# 读悬空挂起(G3 LinkedNode.prepend 挂起根因)。DeepCopyType
# 递归深拷贝字段链表/子类型/Name 到 stdlib(深度上限+链守卫)。
ty_deep: llvmlite.LLVMType* = llvmlite.DeepCopyType(CompilerFactory.factory.PermPool, existing.Ty)
ty_deep: mlirlite.LLVMType* = mlirlite.DeepCopyType(CompilerFactory.factory.PermPool, existing.Ty)
if ty_deep is not None:
existing.Ty = ty_deep
old_name: str = llvmlite.get_struct_name(existing.Ty)
old_name: str = mlirlite.get_struct_name(existing.Ty)
if old_name is not None:
on_len: sizet = string.strlen(old_name)
on_copy: str = CompilerFactory.factory.PermPool.alloc(on_len + 1)
@@ -142,14 +142,14 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
# 属「构造物化」(boxed 指针 → 值槽的整对象拷贝,语义即
# load+store),按严格规则③的构造物化例外放行——与
# c.DerefAs(ptr, <boxed 变体>) 等价,用 * 写法更直白。
*existing.Ty = llvmlite.LLVMType.Struct(llvmlite.get_struct_fields(existing.Ty), llvmlite.get_struct_fcount(existing.Ty), on_copy)
*existing.Ty = mlirlite.LLVMType.Struct(mlirlite.get_struct_fields(existing.Ty), mlirlite.get_struct_fcount(existing.Ty), on_copy)
# Phase B: 将已存在的命名结构体注册到当前模块(输出类型定义行)
llvmlite.module_add_named_type(trans.Module, pool, existing.Ty)
mlirlite.module_add_named_type(trans.Module, pool, existing.Ty)
# B5:existing 路径(Phase B 已注册类)同样需设置 packed/aligned——
# Phase A 注册时虽已设置,但 Phase B 重新 add_named_type 后节点
# IsPacked=0,打印输出 `{...}`(idt_entry packed 未生效根因)。
if self.Gen.ClassGenBase._class_has_tattr(cd.decorator_list, "packed") != 0:
llvmlite.module_set_named_type_packed(trans.Module, pool, existing.Ty, 1)
mlirlite.module_set_named_type_packed(trans.Module, pool, existing.Ty, 1)
# StructTable 每 Phase 可能重建(existing 是 Phase B 新 entry),
# 必须补设 IsPacked——否则跨模块 stub 注入(ensure_struct_def
# _in_module)按 entry.IsPacked 判定 packed 时读 0 → stub 非 packed。
@@ -291,7 +291,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
# 多继承去重:字段名已存在跳过(先声明父类优先)
if self.Gen.ClassGenBase._field_name_exists(field_names_buf, field_count, pfn) != 0: continue
if field_count < GenTypes.FIELD_MAX:
pft: llvmlite.LLVMType* = self.Gen.StructGen.get_field_type_ptr(pfe)
pft: mlirlite.LLVMType* = self.Gen.StructGen.get_field_type_ptr(pfe)
pfd: ast.AST* = self.Gen.StructGen.get_field_default_ptr(pfe)
pfa: str = self.Gen.StructGen.get_field_annot_class_name(pfe)
field_names_buf[field_count] = sizet(pfn)
@@ -347,7 +347,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
# 该路径的实例)Phase B 会 NameError: 't.CDefine' is not defined。
# 与类头常量(MRO_MAX 等)的 i32 字段语义保持一致。
if field_count < GenTypes.FIELD_MAX:
cdef_ty_l: llvmlite.LLVMType* = llvmlite.Int32(pool)
cdef_ty_l: mlirlite.LLVMType* = mlirlite.Int32(pool)
if cdef_ty_l is not None:
field_names_buf[field_count] = sizet(tgt.id)
field_types_buf[field_count] = sizet(cdef_ty_l)
@@ -373,7 +373,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
continue
# 解析字段类型
field_ty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, aa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
field_ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, aa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
# void 不是合法字段类型(用户 2026-10-01:void 只能用于 `void*` 与
# `typedef 不透明结构体 = void`);`void*` 已在上游归并为 i8*,不会命中。
# 放任会按 LLVM void 建字段槽 ⇒ 结构体布局非法(拖到 llc 才暴露),
@@ -416,7 +416,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
is_generic_sub = 1
if is_generic_sub != 0:
# 泛型未特化:回退为 Ptr(i8),依赖 AnnotClassName 做后续类型恢复
field_ty = llvmlite.Ptr(pool, llvmlite.Int8(pool))
field_ty = mlirlite.Ptr(pool, mlirlite.Int8(pool))
else:
# Phase A-pre(declare_only=1):依赖的类可能尚未注册,
# 静默 return 0 让多遍收敛机制生效(下一遍依赖类已注册即可成功)
@@ -489,18 +489,18 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
# 2. 创建 LLVM StructType
# ============================================================
# 构建 ParamNode 链表
first_node: rawptr[llvmlite.ParamNode] = None
prev_node: rawptr[llvmlite.ParamNode] = None
first_node: rawptr[mlirlite.ParamNode] = None
prev_node: rawptr[mlirlite.ParamNode] = None
total_field_count: int = field_count
# 如果有虚表,首字段添加 i8* vtable 指针
if has_vtable == 1:
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
vtable_node: rawptr[llvmlite.ParamNode] = pool.alloc(llvmlite.ParamNode.__sizeof__())
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
vtable_node: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__())
if vtable_node is None:
VLogger.error(f"failed to alloc vtable node for {class_name}", "CLASS")
return 0
string.memset(vtable_node, 0, llvmlite.ParamNode.__sizeof__())
string.memset(vtable_node, 0, mlirlite.ParamNode.__sizeof__())
vtable_node.Ty = i8_ptr_ty
first_node = vtable_node
prev_node = vtable_node
@@ -510,13 +510,13 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
fty_addr: sizet = field_types_buf[fi]
if fty_addr == 0:
continue
fty: llvmlite.LLVMType* = (llvmlite.LLVMType*)(fty_addr)
fty: mlirlite.LLVMType* = (mlirlite.LLVMType*)(fty_addr)
# 创建 ParamNode
pnode: rawptr[llvmlite.ParamNode] = pool.alloc(llvmlite.ParamNode.__sizeof__())
pnode: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__())
if pnode is None:
continue
string.memset(pnode, 0, llvmlite.ParamNode.__sizeof__())
string.memset(pnode, 0, mlirlite.ParamNode.__sizeof__())
pnode.Ty = fty
if first_node is None:
@@ -543,7 +543,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
type_name = tn_copy
# 创建 StructType(命名结构体)
struct_ty: llvmlite.LLVMType* = llvmlite.Struct(pool, first_node, total_field_count, type_name)
struct_ty: mlirlite.LLVMType* = mlirlite.Struct(pool, first_node, total_field_count, type_name)
if struct_ty is None:
VLogger.error(f"failed to create StructType for {class_name}", "CLASS")
return 0
@@ -558,34 +558,34 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
# 后续文件字段类型引用(resolve → Ptr(entry.Ty))→ opaque 扫描遍历悬空 fields
# 崩溃(LoopTest _scan_type_for_cross_module_refs 0xFFFF 根因)。
if trans._declare_only == 0 or self.Gen.StructGen.get_stdlib_alloc() != 0:
st_copy: llvmlite.LLVMType* = llvmlite.DeepCopyType(CompilerFactory.factory.PermPool, struct_ty)
st_copy: mlirlite.LLVMType* = mlirlite.DeepCopyType(CompilerFactory.factory.PermPool, struct_ty)
if st_copy is not None:
struct_ty = st_copy
type_name = llvmlite.get_struct_name(struct_ty)
type_name = mlirlite.get_struct_name(struct_ty)
# 前向声明占位命中:**原位填充**——保持 existing.Ty 指针身份不变,仅把刚构建
# 的字段体写进同一个类型对象(名称沿用占位的 "{sha}.Class")。此后所有已发出的
# Ptr(占位.Ty) 引用(如 CallGenBase.Gen)自动指向完整定义。这一步必须早于
# module_add_named_type:避免同一名字先以占位名注册、又以新对象重复注册。
if fill_fwd != 0 and existing is not None and existing.Ty is not None:
_fwd_name: str = llvmlite.get_struct_name(existing.Ty)
_fwd_fields: rawptr[llvmlite.ParamNode] = llvmlite.get_struct_fields(struct_ty)
_fwd_fc: int = llvmlite.get_struct_fcount(struct_ty)
*existing.Ty = llvmlite.LLVMType.Struct(_fwd_fields, _fwd_fc, _fwd_name)
_fwd_name: str = mlirlite.get_struct_name(existing.Ty)
_fwd_fields: rawptr[mlirlite.ParamNode] = mlirlite.get_struct_fields(struct_ty)
_fwd_fc: int = mlirlite.get_struct_fcount(struct_ty)
*existing.Ty = mlirlite.LLVMType.Struct(_fwd_fields, _fwd_fc, _fwd_name)
struct_ty = existing.Ty
type_name = _fwd_name
existing.IsForwardDecl = 0
existing.FieldCount = 0
# 注册命名结构体到模块(输出 %"name" = type { ... } 定义行)
llvmlite.module_add_named_type(trans.Module, pool, struct_ty)
mlirlite.module_add_named_type(trans.Module, pool, struct_ty)
# B5:@c.Attribute(t.attr.packed) 打包结构体 → 类型定义输出 <{...}>
# (LLVM packed struct,无字段填充,GEP 按 packed 布局计算偏移)。
# idt/gdt/elf/fat32 等二进制格式结构体依赖它读写硬件/磁盘布局。
is_packed_cd: int = self.Gen.ClassGenBase._class_has_tattr(cd.decorator_list, "packed")
if is_packed_cd != 0:
llvmlite.module_set_named_type_packed(trans.Module, pool, struct_ty, 1)
mlirlite.module_set_named_type_packed(trans.Module, pool, struct_ty, 1)
# 扫描字段类型:跨模块结构体引用在当前模块补声明
# 例如 list[int].__pool__ 引用 memhub.MemManager,需要在当前模块添加 %"sha1.MemManager" = type opaque
@@ -593,10 +593,10 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
fty_addr_op: sizet = field_types_buf[fi]
if fty_addr_op == 0:
continue
fty_op: llvmlite.LLVMType* = (llvmlite.LLVMType*)(fty_addr_op)
fty_op: mlirlite.LLVMType* = (mlirlite.LLVMType*)(fty_addr_op)
if self.Gen.ExprGenBase.is_ptr_type(fty_op) != 0:
# 指针字段:指向物只需 opaque 声明(GEP 不按字段下标解引用指向物本体)
llvmlite.module_ensure_opaque_for_type(trans.Module, pool, fty_op)
mlirlite.module_ensure_opaque_for_type(trans.Module, pool, fty_op)
else:
# 值类型字段(结构体本体 / 结构体数组):必须复制**完整定义**。只给
# opaque 会让**本类**变成 unsized(LLVM:含 unsized 成员的结构体自身
@@ -656,7 +656,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
# 添加字段信息
# 如果有虚表,先添加 __vtable__ 字段占位(索引 0),用户字段从索引 1 开始
if has_vtable == 1:
i8_ptr_ty2: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
i8_ptr_ty2: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
self.Gen.StructGen.add_field(pool, entry, "__vtable__", i8_ptr_ty2, None, None)
for fi in range(field_count):
@@ -667,7 +667,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
fty_addr2: sizet = field_types_buf[fi]
if fty_addr2 == 0:
continue
fty2: llvmlite.LLVMType* = (llvmlite.LLVMType*)(fty_addr2)
fty2: mlirlite.LLVMType* = (mlirlite.LLVMType*)(fty_addr2)
# 恢复默认值 AST 指针
fdef_addr: sizet = field_defaults_buf[fi]
fdef: ast.AST* = None
+76 -76
View File
@@ -2,7 +2,7 @@ import lib.core.Gen.GenTypes as GenTypes
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import viperlib
@@ -32,10 +32,10 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
def _resolve_enum_member_type(self, pool: memhub.MemBuddy*,
ann_node: ast.AST*,
imported_modules: str,
from_imports: str) -> llvmlite.LLVMType*:
from_imports: str) -> mlirlite.LLVMType*:
"""解析枚举成员的类型注解为 LLVM 整数类型"""
if ann_node is None:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
k: int = ann_node.kind()
@@ -45,22 +45,22 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
if at.attr is None:
# [S4 fail-fast] Attribute 缺失成员名(AST 损坏),不再静默回退 i32
self.Gen.TypeGenErr.fatal_error(ann_node, "枚举成员类型注解 Attribute 缺失成员名", "TypeError")
return llvmlite.Int32(pool) # 不可达(fatal_error 已退出)
return mlirlite.Int32(pool) # 不可达(fatal_error 已退出)
# t.State → 默认 i32
if string.strcmp(at.attr, "State") == 0:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
# [枚举侧 bool 口径] `t.CBool` 与裸名 `bool` 同宽(8 位),否则同一
# 枚举成员两种写法会分裂出 i1 / i8 两种宽度。全局 `t.CBool` = i1
# (map_t_type L1447-1449)保持不变,仅在**枚举成员注解**这一处按
# 8 位物化(枚举存储须可按字节寻址;TPC 侧 t.CBool.Size = 8 同口径)。
if string.strcmp(at.attr, "CBool") == 0:
return llvmlite.Int8(pool)
return mlirlite.Int8(pool)
# 其他 t.CXxx 类型:统一口径(CTypedef 动态表优先,miss 回退 map_t_type)
ty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_typedef_or_map(pool, at.attr, imported_modules, from_imports)
ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_typedef_or_map(pool, at.attr, imported_modules, from_imports)
if ty is not None: return ty
# [S4 fail-fast] 有注解但解析失败 → 不再静默回退 i32
self.Gen.TypeGenErr.fatal_error(ann_node, f"枚举成员类型注解解析失败: t.{at.attr}", "NameError")
return llvmlite.Int32(pool) # 不可达(fatal_error 已退出)
return mlirlite.Int32(pool) # 不可达(fatal_error 已退出)
# Name 节点: from-import 形式(State / CInt)
if k == ast.ASTKind.Name:
@@ -68,42 +68,42 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
if nm.id is None:
# [S4 fail-fast] Name 缺失标识符(AST 损坏),不再静默回退 i32
self.Gen.TypeGenErr.fatal_error(ann_node, "枚举成员类型注解 Name 缺失标识符", "TypeError")
return llvmlite.Int32(pool) # 不可达(fatal_error 已退出)
return mlirlite.Int32(pool) # 不可达(fatal_error 已退出)
if string.strcmp(nm.id, "State") == 0:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
# 内建裸名整数类型(与 resolve_annotation_type 的 Name 分支同口径,
# TypeGenResolve.vp L2189-2203):枚举成员是整数常量,`int` / `char` /
# `bool` 裸名直通。其余裸名(含 str/bytes 指针形态与未知名)仍走
# typedef / builtins 表,miss 即下方 fail-fast(不静默当 int);
# 指针与非整数成员的统一拦截见 _translate_enum_def。
if string.strcmp(nm.id, "int") == 0:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
if string.strcmp(nm.id, "char") == 0:
return llvmlite.Int8(pool)
return mlirlite.Int8(pool)
if string.strcmp(nm.id, "bool") == 0:
# [枚举侧 bool 口径] 枚举存储必须是可按字节寻址的整数类型,
# i1 不能作为独立枚举宽度 ⇒ 枚举成员注解的 bool 一律 8 位。
# **不改**全局 bool = i1(TypeGenResolve.vp L2201-2203 与
# map_t_type 的 CBool,用于普通变量/形参/字段)。
# 两侧一致:TPC 侧枚举成员 bool 经 t.CBool.Size 亦为 8。
return llvmlite.Int8(pool)
ty2: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_typedef_or_map(pool, nm.id, imported_modules, from_imports)
return mlirlite.Int8(pool)
ty2: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_typedef_or_map(pool, nm.id, imported_modules, from_imports)
if ty2 is not None:
return ty2
# [S4 fail-fast] 有注解但解析失败 → 不再静默回退 i32
self.Gen.TypeGenErr.fatal_error(ann_node, f"枚举成员类型注解解析失败: {nm.id}", "NameError")
return llvmlite.Int32(pool) # 不可达(fatal_error 已退出)
return mlirlite.Int32(pool) # 不可达(fatal_error 已退出)
# BinOp 节点: t.State | int8(递归查找实际类型)
if k == ast.ASTKind.BinOp:
bop: ast.BinOp* = ast.BinOp*(ann_node)
if bop.op == ast.OpKind.BitOr:
left_ty: llvmlite.LLVMType* = self._resolve_enum_member_type(pool, bop.left, imported_modules, from_imports)
left_ty: mlirlite.LLVMType* = self._resolve_enum_member_type(pool, bop.left, imported_modules, from_imports)
# 跳过 t.State(i32 默认),优先返回具体类型
left_bits: int = self.Gen.TypeGenErr.get_llvm_type_bits(left_ty)
if left_bits != 0 and not self._is_state_annotation(bop.left):
return left_ty
right_ty: llvmlite.LLVMType* = self._resolve_enum_member_type(pool, bop.right, imported_modules, from_imports)
right_ty: mlirlite.LLVMType* = self._resolve_enum_member_type(pool, bop.right, imported_modules, from_imports)
if right_ty is not None and not self._is_state_annotation(bop.right):
return right_ty
# 两边都是 State 或无法确定,返回较宽的
@@ -113,11 +113,11 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
return right_ty
# fail-fast:BinOp 但非 BitOr(未知联合运算),不再静默回退 i32
self.Gen.TypeGenErr.fatal_error(ann_node, f"枚举成员类型注解解析失败: {self.Gen.TypeGenResolve.annotation_to_str(ann_node)}", "TypeError")
return llvmlite.Int32(pool) # 不可达(fatal_error 已退出)
return mlirlite.Int32(pool) # 不可达(fatal_error 已退出)
# fail-fast:未知注解节点 kind,不再静默回退 i32
self.Gen.TypeGenErr.fatal_error(ann_node, f"枚举成员类型注解解析失败: {self.Gen.TypeGenResolve.annotation_to_str(ann_node)}", "TypeError")
return llvmlite.Int32(pool) # 不可达(fatal_error 已退出)
return mlirlite.Int32(pool) # 不可达(fatal_error 已退出)
def _is_state_annotation(self, node: ast.AST*) -> int:
"""检查注解节点是否为 t.State,返回 1=是 / 0=否"""
if node is None:
@@ -373,7 +373,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
return 0 # 不可达(fatal_error 已退出)
# 解析成员类型
member_ty: llvmlite.LLVMType* = self._resolve_enum_member_type(pool, aa.annotation, trans._imported_modules, trans._from_imports)
member_ty: mlirlite.LLVMType* = self._resolve_enum_member_type(pool, aa.annotation, trans._imported_modules, trans._from_imports)
# [枚举规格 fail-fast] 成员类型必须是整数类型:浮点/void/结构体/
# 数组的位宽均为 0,无法参与"枚举宽度 = 最宽成员类型"的推导,
@@ -417,7 +417,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
continue
# Assign 无类型注释,默认使用 i32
member_ty_a: llvmlite.LLVMType* = llvmlite.Int32(pool)
member_ty_a: mlirlite.LLVMType* = mlirlite.Int32(pool)
# 解析成员值(同一语句的所有 target 共享该值,next_val 只推进一次)
cur_val_a: int64 = 0
@@ -474,13 +474,13 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
return 0
# 确定基准类型:所有成员类型中 Bits 最大的
base_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
base_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
max_bits: int = 0
for mi in range(member_count):
ty_addr: sizet = member_types_buf[mi]
if ty_addr == 0:
continue
mty: llvmlite.LLVMType* = (llvmlite.LLVMType*)(ty_addr)
mty: mlirlite.LLVMType* = (mlirlite.LLVMType*)(ty_addr)
bits: int = self.Gen.TypeGenErr.get_llvm_type_bits(mty)
if bits > max_bits:
max_bits = bits
@@ -501,7 +501,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
fty_addr2: sizet = member_types_buf[mi]
if fty_addr2 == 0:
continue
mty2: llvmlite.LLVMType* = (llvmlite.LLVMType*)(fty_addr2)
mty2: mlirlite.LLVMType* = (mlirlite.LLVMType*)(fty_addr2)
mval: int64 = member_values_buf[mi]
if mname is not None and mty2 is not None:
self.Gen.StmtGenDecl.add_enum_member(pool, entry, mname, mval, mty2)
@@ -509,20 +509,20 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
VLogger.info(f"registered {class_name} with {member_count} members, base_bits={max_bits}", "ENUM")
return 0
def _get_type_size(self, ty: llvmlite.LLVMType*) -> int:
def _get_type_size(self, ty: mlirlite.LLVMType*) -> int:
"""计算 LLVM 类型的字节大小(含对齐 padding)"""
if ty is None:
return 0
match ty:
case llvmlite.LLVMType.Int(bits):
case mlirlite.LLVMType.Int(bits):
return (bits + 7) // 8
case llvmlite.LLVMType.Float(bits):
case mlirlite.LLVMType.Float(bits):
return bits // 8
case llvmlite.LLVMType.Ptr(pointee):
case mlirlite.LLVMType.Ptr(pointee):
return 8
case llvmlite.LLVMType.Array(elem_ty, count):
case mlirlite.LLVMType.Array(elem_ty, count):
return self._get_type_size(elem_ty) * count
case llvmlite.LLVMType.Struct(fields, fcount, name):
case mlirlite.LLVMType.Struct(fields, fcount, name):
# 计算结构体大小,考虑字段对齐 padding
# 规则: 每个字段的对齐 = 该字段类型的自然对齐
# 指针/i64 → 8, i32 → 4, i16 → 2, i8 → 1
@@ -532,11 +532,11 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
is_packed: int = self.Gen.StructGen.struct_type_is_packed(ty)
total: int = 0
max_align: int = 1
cur: rawptr[llvmlite.ParamNode] = fields
cur: rawptr[mlirlite.ParamNode] = fields
i: int = 0
while cur is not None and i < fcount:
if cur.Ty is not None:
fty: llvmlite.LLVMType* = (llvmlite.LLVMType*)(cur.Ty)
fty: mlirlite.LLVMType* = (mlirlite.LLVMType*)(cur.Ty)
fsize: int = self._get_type_size(fty)
falign: int = self._get_type_align(fty)
# 对齐当前偏移到字段对齐边界(packed 不插填充)
@@ -558,12 +558,12 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
return total
case _:
return 8
def _get_type_align(self, ty: llvmlite.LLVMType*) -> int:
def _get_type_align(self, ty: mlirlite.LLVMType*) -> int:
"""返回类型的自然对齐(字节)"""
if ty is None:
return 1
match ty:
case llvmlite.LLVMType.Int(bits):
case mlirlite.LLVMType.Int(bits):
if bits <= 8:
return 1
elif bits <= 16:
@@ -572,26 +572,26 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
return 4
else:
return 8
case llvmlite.LLVMType.Float(bits):
case mlirlite.LLVMType.Float(bits):
if bits <= 32:
return 4
else:
return 8
case llvmlite.LLVMType.Ptr(pointee):
case mlirlite.LLVMType.Ptr(pointee):
return 8
case llvmlite.LLVMType.Array(elem_ty, count):
case mlirlite.LLVMType.Array(elem_ty, count):
return self._get_type_align(elem_ty)
case llvmlite.LLVMType.Struct(fields, fcount, name):
case mlirlite.LLVMType.Struct(fields, fcount, name):
# packed 结构体整体按字节对齐(对齐 1,无填充)
if self.Gen.StructGen.struct_type_is_packed(ty) != 0:
return 1
# 结构体的对齐 = 最大字段对齐
max_align: int = 1
cur: rawptr[llvmlite.ParamNode] = fields
cur: rawptr[mlirlite.ParamNode] = fields
i: int = 0
while cur is not None and i < fcount:
if cur.Ty is not None:
fty: llvmlite.LLVMType* = (llvmlite.LLVMType*)(cur.Ty)
fty: mlirlite.LLVMType* = (mlirlite.LLVMType*)(cur.Ty)
fa: int = self._get_type_align(fty)
if fa > max_align:
max_align = fa
@@ -616,7 +616,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
if existing is not None:
# Phase B: 将已存在的命名结构体注册到当前模块
if existing.Ty is not None:
llvmlite.module_add_named_type(trans.Module, pool, existing.Ty)
mlirlite.module_add_named_type(trans.Module, pool, existing.Ty)
# SHA1 已在 register_struct 时设置,无需再补
return 0
@@ -653,7 +653,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
if tgt.id is None: continue
# 解析字段类型
field_ty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, aa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
field_ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, aa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
if field_ty is None:
# Phase A-pre(declare_only=1):依赖的类可能尚未注册,
# 静默 return 1 让多遍收敛机制生效(renum 返回 1=跳过该类)
@@ -661,7 +661,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
# Phase B(declare_only=0):真正的类型解析错误,fast-fail 终止
type_name: str = self.Gen.TypeGenResolve.annotation_to_str(aa.annotation)
self.Gen.TypeGenErr.fatal_error(aa, f"'{type_name}' is not defined", "NameError")
field_ty = llvmlite.Int32(pool)
field_ty = mlirlite.Int32(pool)
# 计算字段大小,更新 max_size
fsize: int = self._get_type_size(field_ty)
@@ -683,14 +683,14 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
# 创建联合体的 LLVM 类型: Struct([Array(Int8, max_size)])
# 即 { [max_size x i8] }
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
array_ty: llvmlite.LLVMType* = llvmlite.Array(pool, i8_ty, max_size)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
array_ty: mlirlite.LLVMType* = mlirlite.Array(pool, i8_ty, max_size)
# 构建 ParamNode 链表(单字段:字节数组)
pnode: rawptr[llvmlite.ParamNode] = pool.alloc(llvmlite.ParamNode.__sizeof__())
pnode: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__())
if pnode is None:
return 0
string.memset(pnode, 0, llvmlite.ParamNode.__sizeof__())
string.memset(pnode, 0, mlirlite.ParamNode.__sizeof__())
pnode.Ty = array_ty
# 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName"
@@ -701,7 +701,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
viperlib.snprintf(union_name_buf, 64, "%s.%s", trans.ModuleSha1, class_name)
union_type_name = union_name_buf
union_ty: llvmlite.LLVMType* = llvmlite.Struct(pool, pnode, 1, union_type_name)
union_ty: mlirlite.LLVMType* = mlirlite.Struct(pool, pnode, 1, union_type_name)
if union_ty is None:
VLogger.error(f"failed to create type for {class_name}", "UNION")
return 0
@@ -712,12 +712,12 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
# entry.Ty 悬空 → 后续文件 opaque 扫描跨模块引用遍历悬空 fields 崩溃
# (LoopTest _scan_type_for_cross_module_refs 0xFFFF 根因)。
if trans._declare_only == 0 or self.Gen.StructGen.get_stdlib_alloc() != 0:
union_copy: llvmlite.LLVMType* = llvmlite.DeepCopyType(CompilerFactory.factory.PermPool, union_ty)
union_copy: mlirlite.LLVMType* = mlirlite.DeepCopyType(CompilerFactory.factory.PermPool, union_ty)
if union_copy is not None:
union_ty = union_copy
# 注册命名结构体到模块
llvmlite.module_add_named_type(trans.Module, pool, union_ty)
mlirlite.module_add_named_type(trans.Module, pool, union_ty)
# 注册到 HandlesStruct(传递 SHA1 在注册时直接设置,避免跨模块同名找错 entry)
entry: GenTypes.StructEntry* = self.Gen.StructGen.register_struct(pool, class_name, union_ty, trans.ModuleSha1)
@@ -740,7 +740,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
fty_addr2: sizet = field_types_buf[fi]
if fty_addr2 == 0:
continue
fty2: llvmlite.LLVMType* = (llvmlite.LLVMType*)(fty_addr2)
fty2: mlirlite.LLVMType* = (mlirlite.LLVMType*)(fty_addr2)
if fname is not None and fty2 is not None:
self.Gen.StructGen.add_field(pool, entry, fname, fty2, None, None)
@@ -788,7 +788,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
if string.strcmp(type_name, "bytes") == 0: return 8
if string.strcmp(type_name, "bool") == 0: return 1
# 已注册的结构体类型
struct_ty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(type_name)
struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(type_name)
if struct_ty is not None:
sz: int = self._get_type_size(struct_ty)
if sz > 0:
@@ -816,7 +816,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
# 恒 0 ⇒ match 走 _handle_simple_match(无变体绑定)⇒ case 绑定名未定义。
if self._is_renum_class_name(class_name) != 0:
if existing.Ty is not None:
llvmlite.module_add_named_type(trans.Module, pool, existing.Ty)
mlirlite.module_add_named_type(trans.Module, pool, existing.Ty)
return 0
# 变体表缺失:中和旧 entry(对齐 ClassGenDef needs_rereg 先例),使
# find_struct_by_module 不再命中(按 Name 精确匹配),走下方完整注册路径
@@ -888,7 +888,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
# 不存类型,绑定回退槽位类型。variant_cd.name 在 1a reset
# 后悬空,注册内部会 strcpy 到 perm_pool。
if vnm is not None and vnm.id is not None:
mem_ty_l: llvmlite.LLVMType* = None
mem_ty_l: mlirlite.LLVMType* = None
if trans is not None:
mem_ty_l = self.Gen.TypeGenResolve.resolve_annotation_type(pool, vaa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
self._register_renum_field_alias(pool, class_name, vnm.id, field_idx + 1, mem_ty_l, variant_cd.name)
@@ -953,21 +953,21 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
position_max_sizes[pos] = sizet(pos_max)
# 构建 ParamNode 链表
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i64_ty: llvmlite.LLVMType* = llvmlite.Int64(pool)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool)
first_node: llvmlite.ParamNode* = None
tail_node: llvmlite.ParamNode* = None
first_node: mlirlite.ParamNode* = None
tail_node: mlirlite.ParamNode* = None
for pos in range(total_positions):
psize: int = position_max_sizes[pos]
field_ty: llvmlite.LLVMType* = i32_ty
field_ty: mlirlite.LLVMType* = i32_ty
if psize > 4:
field_ty = i64_ty
pnode: llvmlite.ParamNode* = llvmlite.new_param_node(pool, field_ty)
pnode: mlirlite.ParamNode* = mlirlite.new_param_node(pool, field_ty)
if pnode is None:
continue
tail_node = llvmlite.param_list_append(first_node, tail_node, pnode)
tail_node = mlirlite.param_list_append(first_node, tail_node, pnode)
if first_node is None:
first_node = tail_node
@@ -983,7 +983,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
viperlib.snprintf(renum_name_buf, 64, "%s.%s", trans.ModuleSha1, class_name)
renum_type_name = renum_name_buf
renum_ty: llvmlite.LLVMType* = llvmlite.Struct(pool, first_node, total_positions, renum_type_name)
renum_ty: mlirlite.LLVMType* = mlirlite.Struct(pool, first_node, total_positions, renum_type_name)
if renum_ty is None:
VLogger.error(f"failed to create type for {class_name}", "RENUM")
return 0
@@ -992,12 +992,12 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
# 与 entry.Ty 保持同一指针,find_struct_by_type 匹配不失效)
# StdlibAlloc=1(Phase2 mark2 后)也必须深拷贝:同 union 的悬空根因。
if trans._declare_only == 0 or self.Gen.StructGen.get_stdlib_alloc() != 0:
renum_copy: llvmlite.LLVMType* = llvmlite.DeepCopyType(CompilerFactory.factory.PermPool, renum_ty)
renum_copy: mlirlite.LLVMType* = mlirlite.DeepCopyType(CompilerFactory.factory.PermPool, renum_ty)
if renum_copy is not None:
renum_ty = renum_copy
# 注册命名结构体到模块
llvmlite.module_add_named_type(trans.Module, pool, renum_ty)
mlirlite.module_add_named_type(trans.Module, pool, renum_ty)
# 注册到 HandlesStruct
entry: GenTypes.StructEntry* = self.Gen.StructGen.register_struct(pool, class_name, renum_ty, trans.ModuleSha1)
@@ -1011,7 +1011,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
# 添加 payload 字段(位置 1+,i32 或 i64)
for pos in range(1, total_positions):
psize2: int = position_max_sizes[pos]
payload_ty: llvmlite.LLVMType* = i32_ty
payload_ty: mlirlite.LLVMType* = i32_ty
if psize2 > 4:
payload_ty = i64_ty
field_name_buf: str = pool.alloc(16)
@@ -1044,7 +1044,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
类型槽(RenumAliasTy)落 0。match 绑定时 _lookup_renum_member_ty 查不到
成员类型 → 绑定变量按 payload 槽位(i64)读取,把指针字段读成整数 →
递归传参/赋值给 rawptr[LLVMType] 形参被 int→ptr 显式拦截误报 CastError
(llvmlite __types.vp L448 根因)。
(mlirlite __types.vp L448 根因)。
本方法在 register_struct 完成(自身类已可查)后按与第一遍相同的位置
顺序重遍历变体字段并重新解析注解;命中已存在的 (class, field) 别名
@@ -1086,7 +1086,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
# 与第一遍同规则:有效 AnnAssign 仍占用 payload 槽位
field_idx += 1
continue
mem_ty_l: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, vaa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
mem_ty_l: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, vaa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
# 解析成功 → 触发别名表去重路径(类型槽为 0 时回填;非 0 跳过)
if mem_ty_l is not None:
self._register_renum_field_alias(pool, class_name, vnm.id, field_idx + 1, mem_ty_l, variant_cd.name)
@@ -1307,11 +1307,11 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
定义本身即持久凭证(perm_pool)。用途:变体表因**任何**原因缺失时,
match 分派仍能走带变体绑定的 `_handle_renum_match` 路径,避免退化为
`_handle_simple_match`(不绑定)→ case 绑定名 NameError
(includes/llvmlite/__types.vp L407 `bits` 根因)。
(includes/mlirlite/__types.vp L407 `bits` 根因)。
"""
if class_name is None:
return 0
st: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(class_name)
st: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(class_name)
if st is None:
return 0
if self.Gen.StructGen.lookup_field(st, "__tag") is None:
@@ -1347,7 +1347,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
class_name: str,
field_name: str,
payload_idx: int,
field_ty: llvmlite.LLVMType* = None,
field_ty: mlirlite.LLVMType* = None,
variant_name: str = None):
"""注册 REnum 变体字段名别名到全局表
@@ -1407,7 +1407,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
# _refill_renum_field_types)类型槽为 0 时,本次解析成功则
# 回填真实类型;非 0 槽保持原样(避免重复 DeepCopy 覆盖抖动)。
if self.RenumAliasTy[i] == 0 and field_ty is not None:
ty_copy_rf2: llvmlite.LLVMType* = llvmlite.DeepCopyType(CompilerFactory.factory.PermPool, field_ty)
ty_copy_rf2: mlirlite.LLVMType* = mlirlite.DeepCopyType(CompilerFactory.factory.PermPool, field_ty)
if ty_copy_rf2 is not None:
self.RenumAliasTy[i] = sizet(ty_copy_rf2)
return
@@ -1434,7 +1434,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
# 未解析成功(自引用等)存 0,绑定回退槽位类型)
self.RenumAliasTy[idx] = 0
if field_ty is not None:
ty_copy_rfa: llvmlite.LLVMType* = llvmlite.DeepCopyType(CompilerFactory.factory.PermPool, field_ty)
ty_copy_rfa: mlirlite.LLVMType* = mlirlite.DeepCopyType(CompilerFactory.factory.PermPool, field_ty)
if ty_copy_rfa is not None:
self.RenumAliasTy[idx] = sizet(ty_copy_rfa)
# 变体名同样 strcpy 到 perm_pool(1a reset 后 variant_cd.name 悬空)
@@ -1465,7 +1465,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
return self.RenumAliasIndex[i]
return -1
def _lookup_renum_field_alias_ty(self, class_name: str,
field_name: str) -> llvmlite.LLVMType*:
field_name: str) -> mlirlite.LLVMType*:
"""查找 REnum 变体成员的实际 LLVM 类型,返回类型或 None
与 _lookup_renum_field_alias 同表同键(class/field 均 strcmp 内容比较)。
@@ -1480,11 +1480,11 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
if fld_existing_ptr is not None and string.strcmp(fld_existing_ptr, field_name) == 0:
if self.RenumAliasTy[i] == 0:
return None
return (llvmlite.LLVMType*)(self.RenumAliasTy[i])
return (mlirlite.LLVMType*)(self.RenumAliasTy[i])
return None
def _lookup_renum_member_ty(self, class_name: str,
variant_name: str,
payload_idx: int) -> llvmlite.LLVMType*:
payload_idx: int) -> mlirlite.LLVMType*:
"""按 (class, 变体名, payload 位置) 查找变体成员的实际 LLVM 类型
match 绑定用:同一 payload 位置跨变体类型不同(Int.Bits=i32 vs
@@ -1508,5 +1508,5 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
continue
if self.RenumAliasTy[i] == 0:
return None
return (llvmlite.LLVMType*)(self.RenumAliasTy[i])
return (mlirlite.LLVMType*)(self.RenumAliasTy[i])
return None
+17 -17
View File
@@ -2,7 +2,7 @@ import lib.core.Gen.GenTypes as GenTypes
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import viperlib
@@ -406,7 +406,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase):
# (现场:GenericOopTest `fxi2(a, b, CUInt64T(178900))` 的 T3=u64
# 被猜成 i32)。此处不做兜底猜测,宁缺毋错。
if (fk_f == ast.ASTKind.Name or fk_f == ast.ASTKind.Attribute) and trans is not None:
cty_f: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
cty_f: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, cl_f.func, trans._imported_modules, trans._from_imports, trans, 0)
if cty_f is not None:
# 符号性只能从**被调名源码文本**取(LLVM 层 iN/uN 同形,
@@ -511,7 +511,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase):
return None
def infer_scalar_type_arg_from_llvm_ty(self, pool: memhub.MemBuddy*,
ty: llvmlite.LLVMType*,
ty: mlirlite.LLVMType*,
sign: int) -> str:
"""LLVM **标量**类型 → 泛型类型实参票名(精确位宽;非标量返回 None)
@@ -566,7 +566,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase):
spec_name: str,
template_key: str,
tp_names: list[str]*,
type_args: list[str]*) -> llvmlite.Function*:
type_args: list[str]*) -> mlirlite.Function*:
"""确保当前模块存在特化函数的 declare(跨模块缓存命中时用)
特化 define 全局只发射一份(SpecKeys 去重);命中缓存的调用方模块里没有
@@ -574,9 +574,9 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase):
declare;失败返回 None。
"""
if trans is None or pool is None or spec_name is None: return None
mod: llvmlite.LLVMModule* = trans.Module
mod: mlirlite.LLVMModule* = trans.Module
if mod is None: return None
existing: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, spec_name)
existing: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, spec_name)
if existing is not None: return existing
template_fd: ast.FunctionDef* = self._find_generic_func_template(template_key)
if template_fd is None: return None
@@ -586,7 +586,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase):
if spec_base is None: return None
spec_fd: ast.FunctionDef* = self._clone_funcdef_for_spec(pool, template_fd, spec_base, tp_names, type_args)
if spec_fd is None: return None
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
saved_ms: str = trans.ModuleSha1
saved_imp: str = trans._imported_modules
saved_gtpn: list[str]* = trans.GenericTypeParamNames
@@ -600,12 +600,12 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase):
tpl_file: str = self._find_generic_func_template_file(template_key)
if tpl_file is not None:
self.Gen.TypeGenResolve.set_current_file(tpl_file)
ret_ty: llvmlite.LLVMType* = None
ret_ty: mlirlite.LLVMType* = None
if spec_fd.returns is not None:
ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, spec_fd.returns, trans._imported_modules, trans._from_imports, trans, 0)
if ret_ty is None:
ret_ty = i32_ty
func: llvmlite.Function* = llvmlite.create_declare(pool, mod, spec_name, ret_ty)
func: mlirlite.Function* = mlirlite.create_declare(pool, mod, spec_name, ret_ty)
if func is not None and spec_fd.args is not None and spec_fd.args.kind() == ast.ASTKind.Arguments:
ags: ast.Arguments* = ast.Arguments*(spec_fd.args)
if ags.args is not None:
@@ -617,21 +617,21 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase):
if pa is None or pa.kind() != ast.ASTKind.Arg: continue
arg: ast.Arg* = ast.Arg*(pa)
if arg.arg is None: continue
param_ty: llvmlite.LLVMType* = i32_ty
param_ty: mlirlite.LLVMType* = i32_ty
if arg.annotation is not None:
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, trans._imported_modules, trans._from_imports, trans, 0)
resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, trans._imported_modules, trans._from_imports, trans, 0)
if resolved is not None:
match resolved:
case llvmlite.LLVMType.Struct(_, _, _):
param_ty = llvmlite.Ptr(pool, resolved)
case llvmlite.LLVMType.Array(aelem_ty, _):
param_ty = llvmlite.Ptr(pool, aelem_ty)
case mlirlite.LLVMType.Struct(_, _, _):
param_ty = mlirlite.Ptr(pool, resolved)
case mlirlite.LLVMType.Array(aelem_ty, _):
param_ty = mlirlite.Ptr(pool, aelem_ty)
case _:
param_ty = resolved
pname: str = pool.alloc(32)
if pname is not None:
viperlib.snprintf(pname, 32, "%%%s", arg.arg)
llvmlite.add_param(pool, func, param_ty, pname)
mlirlite.add_param(pool, func, param_ty, pname)
if tpl_file is not None:
self.Gen.TypeGenResolve.set_current_file(saved_cur)
trans.ModuleSha1 = saved_ms
@@ -722,7 +722,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase):
# 发射(translate_function_def 对已 define 的同名会新建 → 模块内重复符号)。
# 仅 declare(跨模块补的声明)时继续走发射路径(translate_function_def 会
# 复用该 declare 并补函数体转 define)。
existing_fn: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(trans.Module, spec_name)
existing_fn: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(trans.Module, spec_name)
if existing_fn is not None and existing_fn.IsDeclared == 0:
self._cache_spec(pool, spec_key, spec_name)
self.GenericSpecDepth -= 1
+128 -128
View File
@@ -3,7 +3,7 @@ import lib.core.Gen.Type.TypeSpec as TSpec
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdio
@@ -79,7 +79,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
return 0
pool: memhub.MemBuddy* = trans.Pool
mod: llvmlite.LLVMModule* = trans.Module
mod: mlirlite.LLVMModule* = trans.Module
children: list[ast.AST*]* = cd.children
if children is None:
@@ -288,7 +288,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
pool: memhub.MemBuddy* = trans.Pool
mod: llvmlite.LLVMModule* = trans.Module
mod: mlirlite.LLVMModule* = trans.Module
# 收集虚方法信息(继承父类 + 自身,结果存 self.VtFullNames 等暂存区)
# 同时设置 entry.VTableMethodCount/VTableMethods(虚分派查询用)
@@ -302,20 +302,20 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
vt_self_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(class_name, trans.ModuleSha1)
# 2. 构造 VTable 类型: { i8*, i8*, ..., i8* }
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
first_node: llvmlite.ParamNode* = None
tail_node: llvmlite.ParamNode* = None
first_node: mlirlite.ParamNode* = None
tail_node: mlirlite.ParamNode* = None
for i in range(method_count):
pnode: llvmlite.ParamNode* = llvmlite.new_param_node(pool, i8_ptr_ty)
pnode: mlirlite.ParamNode* = mlirlite.new_param_node(pool, i8_ptr_ty)
if pnode is None:
continue
tail_node = llvmlite.param_list_append(first_node, tail_node, pnode)
tail_node = mlirlite.param_list_append(first_node, tail_node, pnode)
if first_node is None:
first_node = tail_node
vtable_ty: llvmlite.LLVMType* = llvmlite.Struct(pool, first_node, method_count, None)
vtable_ty: mlirlite.LLVMType* = mlirlite.Struct(pool, first_node, method_count, None)
if vtable_ty is None:
return 0
@@ -386,7 +386,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
vtable_mangled: str = self.Gen.FuncGenBase._mangle_name(trans, vtable_name_buf)
# 5. 创建全局变量
gv: llvmlite.GlobalVariable* = llvmlite.new_global_variable(pool, vtable_mangled, vtable_ty)
gv: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, vtable_mangled, vtable_ty)
if gv is None:
return 0
gv.Initializer = init_buf
@@ -394,11 +394,11 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
# 默认 linkage(external,2026-08-10):isinstance 内建函数需要跨模块
# 引用其他模块类的 vtable 符号({模块sha1}.Class.vtable),internal 不对外
# 导出会导致链接失败。vtable 名含模块 sha1 前缀全局唯一,外部可见不冲突。
# llvmlite 打印规则:Initializer 非空 + external 时不打印 external 关键字,
# mlirlite 打印规则:Initializer 非空 + external 时不打印 external 关键字,
# 输出 @name = constant {...}(合法外部强定义)。
# 添加到模块
llvmlite.module_add_global(mod, gv)
mlirlite.module_add_global(mod, gv)
# 6. 存储虚方法名列表到 StructEntry(直接用 entry,规避跨模块同名 find_struct 找错)
if vt_self_entry is not None:
@@ -417,7 +417,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
# ============================================================
def _translate_oop_methods(self, trans: HT.Translator*,
cd: ast.ClassDef*,
struct_ty: llvmlite.LLVMType*,
struct_ty: mlirlite.LLVMType*,
class_name: str,
mark_only: int = 0,
reemit: int = 0) -> int:
@@ -577,7 +577,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
# ============================================================
def _translate_method(self, trans: HT.Translator*,
fd: ast.FunctionDef*,
struct_ty: llvmlite.LLVMType*,
struct_ty: mlirlite.LLVMType*,
class_name: str,
sig_only: int = 0) -> int:
"""翻译单个方法,返回 0
@@ -596,14 +596,14 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
pool: memhub.MemBuddy* = trans.Pool
mod: llvmlite.LLVMModule* = trans.Module
mod: mlirlite.LLVMModule* = trans.Module
imported_modules: str = trans._imported_modules
from_imports: str = trans._from_imports
funcs_ptr: GenTypes.FuncEntry* = trans._funcs
func_count: int = trans._func_count
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
self_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, struct_ty)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
self_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, struct_ty)
method_name: str = fd.name
if method_name is None:
@@ -650,7 +650,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
mangled_name: str = self.Gen.FuncGenBase._mangle_name(trans, full_name)
# 推断返回类型
ret_ty: llvmlite.LLVMType* = None
ret_ty: mlirlite.LLVMType* = None
if fd.returns is not None:
ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, fd.returns, imported_modules, from_imports, trans, 0)
if ret_ty is None and fd.returns is not None:
@@ -660,7 +660,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
if self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0) != 0 \
or self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CExport", 0) != 0 \
or self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CExtern", 0) != 0:
ret_ty = llvmlite.Void(pool)
ret_ty = mlirlite.Void(pool)
else:
# [S4 fail-fast] 有返回注解但解析失败 → 不再退回 infer_return_type()
# (推断可能给出与真实注解不符的类型,静默错到运行期才暴露)
@@ -669,10 +669,10 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
if ret_ty is None:
# __init__ 和 __before_init__ 返回 void
if string.strcmp(method_name, "__init__") == 0:
ret_ty = llvmlite.Void(pool)
ret_ty = mlirlite.Void(pool)
# __new__ 返回 Ptr(struct_ty)(结构体指针作为存储空间)
elif string.strcmp(method_name, "__new__") == 0:
ret_ty = llvmlite.Ptr(pool, struct_ty)
ret_ty = mlirlite.Ptr(pool, struct_ty)
else:
param_types_str: str = self.Gen.TypeGenErr.build_param_types_str(pool, fd.args)
ret_ty = self.Gen.TypeGenErr.infer_return_type(pool, fd.children, param_types_str)
@@ -683,7 +683,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
# 只把 IsDeclared 清零转 define——与 FuncGenDef.forward_declare_functions
# (FuncGenDef.vp:25-30)→ translate_function_def(FuncGenDef.vp:544-545)的
# 模块级函数前向声明机制同构。
func: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, mangled_name)
func: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, mangled_name)
decl_reuse: int = 0
if func is not None:
if func.IsDeclared == 0:
@@ -691,7 +691,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
return 0
decl_reuse = 1
else:
func = llvmlite.create_declare(pool, mod, mangled_name, ret_ty)
func = mlirlite.create_declare(pool, mod, mangled_name, ret_ty)
if func is None:
return 0
@@ -751,7 +751,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
first_pname_buf: str = pool.alloc(32)
if first_pname_buf is not None:
viperlib.snprintf(first_pname_buf, 32, "%%%s", first_pname)
llvmlite.add_param(pool, func, self_ptr_ty, first_pname_buf)
mlirlite.add_param(pool, func, self_ptr_ty, first_pname_buf)
# 添加其他参数(支持类型注解;@staticmethod 从索引 0 开始,其余跳过索引 0 的 self/cls)
# args_node 已在 decl_reuse 分支之外声明(函数体段同样要用)
@@ -766,9 +766,9 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
for ai in range(start_idx, an):
arg: ast.Arg* = ast.Arg*(alist.get(ai))
if arg is not None and arg.arg is not None:
param_ty: llvmlite.LLVMType* = i32_ty
param_ty: mlirlite.LLVMType* = i32_ty
if arg.annotation is not None:
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, imported_modules, from_imports, trans, 0)
resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, imported_modules, from_imports, trans, 0)
if resolved is None:
# [S4 fail-fast] 有注解但解析失败:不再静默用 i32
# (方法签名与调用点/实现体三方不一致)
@@ -779,33 +779,33 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
# (append 返回后悬垂,G5 Test4 head.Value 读到垃圾)。
# CArray 形参 → 元素指针 ty*(数组衰减,C 语义,与函数形参一致)。
match resolved:
case llvmlite.LLVMType.Void():
case mlirlite.LLVMType.Void():
# void 不是合法形参类型(用户 2026-10-01:void 只能用于
# `void*` 与 `typedef 不透明结构体 = void`);`void*` 已在上游
# 归并为 i8*,不会命中此分支。放任会按 LLVM void 建形参 ⇒
# 非法 IR 拖到 llc 才暴露,改编译期 fail-fast。
self.Gen.TypeGenErr.fatal_error(arg, f"方法 '{class_name}.{method_name}' 形参 '{arg.arg}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError")
return 0
case llvmlite.LLVMType.Struct(_, _, _):
param_ty = llvmlite.Ptr(pool, resolved)
case llvmlite.LLVMType.Array(aelem_ty, _):
param_ty = llvmlite.Ptr(pool, aelem_ty)
case mlirlite.LLVMType.Struct(_, _, _):
param_ty = mlirlite.Ptr(pool, resolved)
case mlirlite.LLVMType.Array(aelem_ty, _):
param_ty = mlirlite.Ptr(pool, aelem_ty)
case _:
param_ty = resolved
pname: str = pool.alloc(32)
if pname is not None:
viperlib.snprintf(pname, 32, "%%%s", arg.arg)
llvmlite.add_param(pool, func, param_ty, pname)
mlirlite.add_param(pool, func, param_ty, pname)
# OOP iter 协议:__next__ 方法注入隐藏参数 __stop_iter_flag__(i1*)。
# raise StopIteration 时置 1(对齐 TPC HandlesFunctions.py L703-705)。
# 该参数不计入 md_param_count(逻辑参数),调用侧(for 循环)显式传。
if string.strcmp(method_name, "__next__") == 0:
i1_ty_si: llvmlite.LLVMType* = llvmlite.Int1(pool)
i1_ty_si: mlirlite.LLVMType* = mlirlite.Int1(pool)
if i1_ty_si is not None:
i1_ptr_ty_si: llvmlite.LLVMType* = llvmlite.Ptr(pool, i1_ty_si)
i1_ptr_ty_si: mlirlite.LLVMType* = mlirlite.Ptr(pool, i1_ty_si)
if i1_ptr_ty_si is not None:
llvmlite.add_param(pool, func, i1_ptr_ty_si, "%__stop_iter_flag__")
mlirlite.add_param(pool, func, i1_ptr_ty_si, "%__stop_iter_flag__")
# 参数添加完成,补全全局函数表的 Spec(供 vtable 在 func 被 reset 后派生类型文本)
self.Gen.CallGenLeafKit.update_global_func_spec(full_name, func)
@@ -815,15 +815,15 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
return 0
# 创建 entry 块
entry_blk: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, "entry")
entry_blk: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "entry")
if entry_blk is None:
return 0
# 创建方法专属 builder
func_builder: llvmlite.IRBuilder* = llvmlite.new_builder(pool, func)
func_builder: mlirlite.IRBuilder* = mlirlite.new_builder(pool, func)
if func_builder is None:
return 0
llvmlite.position_at_end(func_builder, entry_blk)
mlirlite.position_at_end(func_builder, entry_blk)
# --traceback: attach a DISubprogram to this method define (same as the
# module-level function path). No-op when DI is disabled.
@@ -836,48 +836,48 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
tls_m_flag_name: str = pool.alloc(128)
if tls_m_flag_name is not None:
viperlib.snprintf(tls_m_flag_name, 128, "__tls_init_done_%s", method_name)
tls_m_gv: llvmlite.GlobalVariable* = llvmlite.create_global_int(pool, mod, tls_m_flag_name, 1, 0)
tls_m_gv: mlirlite.GlobalVariable* = mlirlite.create_global_int(pool, mod, tls_m_flag_name, 1, 0)
if tls_m_gv is not None:
i1_ty_m: llvmlite.LLVMType* = llvmlite.Int1(pool)
i1_ty_m: mlirlite.LLVMType* = mlirlite.Int1(pool)
if i1_ty_m is not None:
# GlobalVariable 非 Value 子类:构造 Value 视图后再 load/store
tls_m_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i1_ty_m)
tls_m_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i1_ty_m)
tls_m_rn: str = pool.alloc(64)
if tls_m_rn is not None:
viperlib.snprintf(tls_m_rn, 64, "@%s", tls_m_flag_name)
tls_m_ref: llvmlite.Value* = llvmlite.SSAValue(pool, tls_m_ptr_ty, tls_m_rn)
tls_m_ref: mlirlite.Value* = mlirlite.SSAValue(pool, tls_m_ptr_ty, tls_m_rn)
if tls_m_ref is not None:
tls_m_ld: llvmlite.Value* = llvmlite.build_load(func_builder, i1_ty_m, tls_m_ref)
tls_m_ld: mlirlite.Value* = mlirlite.build_load(func_builder, i1_ty_m, tls_m_ref)
lc_m: int = trans._label_counter
trans._label_counter = lc_m + 1
tls_m_buf: str = pool.alloc(64)
if tls_m_buf is not None:
viperlib.snprintf(tls_m_buf, 64, "tls.skip.%d", lc_m)
tls_m_skip: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, tls_m_buf)
tls_m_skip: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, tls_m_buf)
viperlib.snprintf(tls_m_buf, 64, "tls.cont.%d", lc_m)
tls_m_cont: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, tls_m_buf)
tls_m_cont: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, tls_m_buf)
if tls_m_skip is not None and tls_m_cont is not None:
llvmlite.build_cond_br(func_builder, tls_m_ld, tls_m_skip, tls_m_cont)
llvmlite.position_at_end(func_builder, tls_m_skip)
mlirlite.build_cond_br(func_builder, tls_m_ld, tls_m_skip, tls_m_cont)
mlirlite.position_at_end(func_builder, tls_m_skip)
match ret_ty:
case llvmlite.LLVMType.Void():
llvmlite.build_ret_void(func_builder)
case llvmlite.LLVMType.Int(_):
tlm0: llvmlite.Value* = llvmlite.ConstInt(pool, ret_ty, 0, "0")
case mlirlite.LLVMType.Void():
mlirlite.build_ret_void(func_builder)
case mlirlite.LLVMType.Int(_):
tlm0: mlirlite.Value* = mlirlite.ConstInt(pool, ret_ty, 0, "0")
if tlm0 is not None:
llvmlite.build_ret(func_builder, tlm0)
case llvmlite.LLVMType.Float(_):
tlmf: llvmlite.Value* = llvmlite.ConstFloat(pool, ret_ty, 0.0)
mlirlite.build_ret(func_builder, tlm0)
case mlirlite.LLVMType.Float(_):
tlmf: mlirlite.Value* = mlirlite.ConstFloat(pool, ret_ty, 0.0)
if tlmf is not None:
llvmlite.build_ret(func_builder, tlmf)
mlirlite.build_ret(func_builder, tlmf)
case _:
tlmn: llvmlite.Value* = llvmlite.ConstNull(pool, ret_ty, "null")
tlmn: mlirlite.Value* = mlirlite.ConstNull(pool, ret_ty, "null")
if tlmn is not None:
llvmlite.build_ret(func_builder, tlmn)
llvmlite.position_at_end(func_builder, tls_m_cont)
tlmo: llvmlite.Value* = llvmlite.ConstInt(pool, i1_ty_m, 1, "1")
mlirlite.build_ret(func_builder, tlmn)
mlirlite.position_at_end(func_builder, tls_m_cont)
tlmo: mlirlite.Value* = mlirlite.ConstInt(pool, i1_ty_m, 1, "1")
if tlmo is not None:
llvmlite.build_store(func_builder, tlmo, tls_m_ref)
mlirlite.build_store(func_builder, tlmo, tls_m_ref)
# 进入函数作用域
self.Gen.VarGen.enter_scope(trans.SymTab, SCOPE_FUNCTION)
@@ -886,7 +886,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
# self 必须走 alloca:注册为 SSA 值会让 translate_name_value 多 load 一次,
# 把 Ptr(struct_ty) 变成 struct 值 → 变参函数 ABI 不匹配崩溃。
if is_static_m == 0:
self_alloca: llvmlite.Value* = llvmlite.build_alloca(func_builder, self_ptr_ty)
self_alloca: mlirlite.Value* = mlirlite.build_alloca(func_builder, self_ptr_ty)
if self_alloca is not None:
self_var_name: str = "self"
self_ssa_name: str = "%self"
@@ -903,8 +903,8 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
self.Gen.VarGen.define_var(trans.SymTab, self_var_name, self_alloca)
# 设置 self/cls 的类型注解类名(属性访问 lookup_field 回退查找用)
self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, self_var_name, class_name)
self_val: llvmlite.Value* = llvmlite.SSAValue(pool, self_ptr_ty, self_ssa_name)
llvmlite.build_store(func_builder, self_val, self_alloca)
self_val: mlirlite.Value* = mlirlite.SSAValue(pool, self_ptr_ty, self_ssa_name)
mlirlite.build_store(func_builder, self_val, self_alloca)
# 为其他参数创建 alloca 并 store(与普通函数一致;
# @staticmethod 从索引 0 开始,其余跳过索引 0 的 self/cls 参数)
@@ -919,9 +919,9 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
for ai2 in range(start_idx2, an2):
arg2: ast.Arg* = ast.Arg*(alist2.get(ai2))
if arg2 is not None and arg2.arg is not None:
param_ty2: llvmlite.LLVMType* = i32_ty
param_ty2: mlirlite.LLVMType* = i32_ty
if arg2.annotation is not None:
resolved2: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg2.annotation, imported_modules, from_imports, trans, 0)
resolved2: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg2.annotation, imported_modules, from_imports, trans, 0)
if resolved2 is None:
# fail-fast:参数有注解但类型解析失败,不再静默保持 i32
self.Gen.TypeGenErr.fatal_error(arg2, f"方法 '{class_name}.{method_name}' 参数 '{arg2.arg}' 类型解析失败", "NameError")
@@ -930,17 +930,17 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
# 与 add_param 保持一致:裸类形参 → Ptr(struct)(对象即指针)
# CArray 形参 → 元素指针 ty*(数组衰减,与 add_param 一致)
match resolved2:
case llvmlite.LLVMType.Void():
case mlirlite.LLVMType.Void():
# void 不是合法形参类型(用户 2026-10-01,见上方同款判据)
self.Gen.TypeGenErr.fatal_error(arg2, f"方法 '{class_name}.{method_name}' 形参 '{arg2.arg}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError")
return 0
case llvmlite.LLVMType.Struct(_, _, _):
param_ty2 = llvmlite.Ptr(pool, resolved2)
case llvmlite.LLVMType.Array(aelem_ty2, _):
param_ty2 = llvmlite.Ptr(pool, aelem_ty2)
case mlirlite.LLVMType.Struct(_, _, _):
param_ty2 = mlirlite.Ptr(pool, resolved2)
case mlirlite.LLVMType.Array(aelem_ty2, _):
param_ty2 = mlirlite.Ptr(pool, aelem_ty2)
case _:
param_ty2 = resolved2
alloca: llvmlite.Value* = llvmlite.build_alloca(func_builder, param_ty2)
alloca: mlirlite.Value* = mlirlite.build_alloca(func_builder, param_ty2)
if alloca is not None:
self.Gen.VarGen.define_var(trans.SymTab, arg2.arg, alloca)
# 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体)
@@ -952,31 +952,31 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
pname2: str = pool.alloc(32)
if pname2 is not None:
viperlib.snprintf(pname2, 32, "%%%s", arg2.arg)
param_val: llvmlite.Value* = llvmlite.SSAValue(pool, param_ty2, pname2)
llvmlite.build_store(func_builder, param_val, alloca)
param_val: mlirlite.Value* = mlirlite.SSAValue(pool, param_ty2, pname2)
mlirlite.build_store(func_builder, param_val, alloca)
# OOP iter 协议:__next__ 的 stop-flag 参数初始化(store 0)并保存
# 指针到 trans,供 translate_raise 的 raise StopIteration 写 1。
# 参数名必须与上面 add_param 的 "%__stop_iter_flag__" 一致。
if string.strcmp(method_name, "__next__") == 0:
i1_ty_sf: llvmlite.LLVMType* = llvmlite.Int1(pool)
i1_ty_sf: mlirlite.LLVMType* = mlirlite.Int1(pool)
if i1_ty_sf is not None:
i1_ptr_ty_sf: llvmlite.LLVMType* = llvmlite.Ptr(pool, i1_ty_sf)
i1_ptr_ty_sf: mlirlite.LLVMType* = mlirlite.Ptr(pool, i1_ty_sf)
if i1_ptr_ty_sf is not None:
flag_ref_sf: llvmlite.Value* = llvmlite.SSAValue(pool, i1_ptr_ty_sf, "%__stop_iter_flag__")
flag_ref_sf: mlirlite.Value* = mlirlite.SSAValue(pool, i1_ptr_ty_sf, "%__stop_iter_flag__")
if flag_ref_sf is not None:
trans._stop_iter_flag_ptr = flag_ref_sf
zero_i1_sf: llvmlite.Value* = llvmlite.ConstInt(pool, i1_ty_sf, 0, "0")
zero_i1_sf: mlirlite.Value* = mlirlite.ConstInt(pool, i1_ty_sf, 0, "0")
if zero_i1_sf is not None:
llvmlite.build_store(func_builder, zero_i1_sf, flag_ref_sf)
mlirlite.build_store(func_builder, zero_i1_sf, flag_ref_sf)
# 保存模块级作用域状态
old_func: llvmlite.Function* = trans._cur_func
old_builder: llvmlite.IRBuilder* = trans._cur_builder
old_func: mlirlite.Function* = trans._cur_func
old_builder: mlirlite.IRBuilder* = trans._cur_builder
old_global_count: int = trans._global_name_count
old_nonlocal_count: int = trans._nonlocal_name_count
old_env_count: int = trans._closure_env_count
old_stop_iter_flag: llvmlite.Value* = trans._stop_iter_flag_ptr
old_stop_iter_flag: mlirlite.Value* = trans._stop_iter_flag_ptr
trans._cur_func = func
trans._cur_builder = func_builder
@@ -1026,7 +1026,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
if last_stmt_m is not None and last_stmt_m.kind() == ast.ASTKind.Return:
last_is_return = 1
if last_is_return == 0:
if llvmlite.builder_cur_block_is_terminated(func_builder) == 0:
if mlirlite.builder_cur_block_is_terminated(func_builder) == 0:
last_is_ctrl: int = 0
if bn3 > 0:
last_stmt3_m: ast.AST* = body.get(bn3 - 1)
@@ -1039,7 +1039,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
_is_void: int = 0
if ret_ty is not None:
match ret_ty:
case llvmlite.LLVMType.Void():
case mlirlite.LLVMType.Void():
_is_void = 1
case _:
pass
@@ -1059,20 +1059,20 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
if ret_none_cn_m.const_kind == ast.CONST_NONE:
_is_void = 1
if _is_void != 0:
llvmlite.build_ret_void(func_builder)
mlirlite.build_ret_void(func_builder)
elif last_is_ctrl != 0 and trans._ctrl_merge_reachable == 0:
# 非 void 方法末句是控制流且 merge 块**结构性**不可达(全分支 return,无 br
# 到 merge)→ LLVM 语义 unreachable。merge 可达时须正常收尾(下方
# ConstZero / fail-fast):可达块的 unreachable 是 UB,llc 不生成指令 ⇒
# 执行掉进布局紧随其后的块(同 FuncGenDef 模块级函数口径;实测反例见该处
# 注释里的 _TypePrintDepth 用 snprintf 返回值当 tag 走进 switch 跳转表)。
llvmlite.build_unreachable(func_builder)
mlirlite.build_unreachable(func_builder)
elif fd.returns is None:
# 无返回类型注解 → 无返回值过程方法,默认零值返回
if ret_ty is not None:
_m_zero_val: llvmlite.Value* = llvmlite.ConstZero(pool, ret_ty)
_m_zero_val: mlirlite.Value* = mlirlite.ConstZero(pool, ret_ty)
if _m_zero_val is not None:
llvmlite.build_ret(func_builder, _m_zero_val)
mlirlite.build_ret(func_builder, _m_zero_val)
else:
self.Gen.TypeGenErr.fatal_error(fd, "方法流程掉出末尾但未显式 return", "TypeError")
else:
@@ -1082,7 +1082,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
if ret_ty is not None:
rt_name_m: str = pool.alloc(64)
if rt_name_m is not None:
llvmlite.TypePrint(rt_name_m, 64, ret_ty, pool)
mlirlite.TypePrint(rt_name_m, 64, ret_ty, pool)
if rt_name_m[0] == '\0':
rt_name_m = "?"
err_fn_m: str = pool.alloc(256)
@@ -1117,7 +1117,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
# 3. ret void
# ============================================================
def _generate_before_init(self, trans: HT.Translator*,
struct_ty: llvmlite.LLVMType*,
struct_ty: mlirlite.LLVMType*,
class_name: str) -> int:
"""生成 __before_init__ 函数,返回 0"""
if trans is None or struct_ty is None or class_name is None:
@@ -1125,12 +1125,12 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
pool: memhub.MemBuddy* = trans.Pool
mod: llvmlite.LLVMModule* = trans.Module
mod: mlirlite.LLVMModule* = trans.Module
funcs_ptr: GenTypes.FuncEntry* = trans._funcs
func_count: int = trans._func_count
self_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, struct_ty)
void_ty: llvmlite.LLVMType* = llvmlite.Void(pool)
self_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, struct_ty)
void_ty: mlirlite.LLVMType* = mlirlite.Void(pool)
# 构建函数名: ClassName.__before_init__
full_name_buf: str = pool.alloc(128)
@@ -1148,7 +1148,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
# create_function 追加一条同名 define,同模块内 declare+define 并存 → llc
# "invalid redefinition of function"。故按名复用该声明,清零 IsDeclared 转
# define——与 _generate_method(本文件 L686-705)、FuncGenDef(L552-555)同构。
bi_func: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, mangled_name)
bi_func: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, mangled_name)
bi_decl_reuse: int = 0
if bi_func is not None:
if bi_func.IsDeclared == 0:
@@ -1156,9 +1156,9 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
return 0
bi_decl_reuse = 1
else:
bi_func = llvmlite.create_function(pool, mod, mangled_name, void_ty)
bi_func = mlirlite.create_function(pool, mod, mangled_name, void_ty)
if bi_func is None: return 0
func: llvmlite.Function* = bi_func
func: mlirlite.Function* = bi_func
# 注册到函数表
max_funcs: int = 1024
@@ -1169,39 +1169,39 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
if bi_decl_reuse != 0:
# 复用前向声明:self 参数已由 _ensure_method_declare 添加(无名),
# 此处只需命名首参 %self 并校准为定义侧类型——函数体以 %self 引用它,
# 无名形参会让函数体的 %self 无定义(llvmlite FunctionPrint 仅在
# 无名形参会让函数体的 %self 无定义(mlirlite FunctionPrint 仅在
# Param.Name 非空时打印参数名)。
bi_first_param: llvmlite.Param* = llvmlite.function_get_param_head(func)
bi_first_param: mlirlite.Param* = mlirlite.function_get_param_head(func)
if bi_first_param is not None:
bi_first_param.Ty = self_ptr_ty
bi_first_param.Name = "%self"
func.IsDeclared = 0
else:
# 添加 self 参数
llvmlite.add_param(pool, func, self_ptr_ty, "%self")
mlirlite.add_param(pool, func, self_ptr_ty, "%self")
# 参数添加完成,补全全局函数表的 Spec
rc_ut: int = self.Gen.CallGenLeafKit.update_global_func_spec(full_name, func)
# 创建 entry 块 + builder
entry_blk: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, "entry")
entry_blk: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "entry")
if entry_blk is None: return 0
func_builder: llvmlite.IRBuilder* = llvmlite.new_builder(pool, func)
func_builder: mlirlite.IRBuilder* = mlirlite.new_builder(pool, func)
if func_builder is None: return 0
llvmlite.position_at_end(func_builder, entry_blk)
mlirlite.position_at_end(func_builder, entry_blk)
# 注册 self 为 SSA 值
self_val: llvmlite.Value* = llvmlite.SSAValue(pool, self_ptr_ty, "%self")
self_val: mlirlite.Value* = mlirlite.SSAValue(pool, self_ptr_ty, "%self")
# 1. 零值填充: store zeroinitializer, Ptr(struct_ty)* %self
# 空 struct({})在 LLVM 中不允许 zeroinitializer(invalid type for null constant),
# 无字段类(接口/标记类,如多继承的 Vec2Extra)跳过零值填充;
# @t.CVTable 类必有 vtable 指针字段(非空),不受影响。
struct_fcount_zi: int = llvmlite.get_struct_fcount(struct_ty)
struct_fcount_zi: int = mlirlite.get_struct_fcount(struct_ty)
if struct_fcount_zi > 0:
zero: llvmlite.Value* = llvmlite.ConstZero(pool, struct_ty)
zero: mlirlite.Value* = mlirlite.ConstZero(pool, struct_ty)
if zero is not None:
llvmlite.build_store(func_builder, zero, self_val)
mlirlite.build_store(func_builder, zero, self_val)
# 1.5 如果有虚表,store vtable 全局地址到 __vtable__ 字段(索引 0)
# 用 find_struct_by_type 定位 entry,规避跨模块同名 find_struct 找错
@@ -1215,23 +1215,23 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
vt_method_count = bi_entry.VTableMethodCount
if vt_method_count > 0:
# 构造 vtable 类型 { i8*, i8*, ..., i8* }
vt_i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
vt_i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, vt_i8_ty)
vt_i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
vt_i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, vt_i8_ty)
vt_first_node: llvmlite.ParamNode* = None
vt_prev_node: llvmlite.ParamNode* = None
vt_first_node: mlirlite.ParamNode* = None
vt_prev_node: mlirlite.ParamNode* = None
for vti in range(vt_method_count):
vtnode: llvmlite.ParamNode* = llvmlite.new_param_node(pool, vt_i8_ptr_ty)
vtnode: mlirlite.ParamNode* = mlirlite.new_param_node(pool, vt_i8_ptr_ty)
if vtnode is None:
continue
if vt_first_node is None:
vt_first_node = vtnode
if vt_prev_node is not None:
llvmlite.paramnode_set_next(vt_prev_node, vtnode)
mlirlite.paramnode_set_next(vt_prev_node, vtnode)
vt_prev_node = vtnode
vt_ty: llvmlite.LLVMType* = llvmlite.Struct(pool, vt_first_node, vt_method_count, None)
vt_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, vt_ty)
vt_ty: mlirlite.LLVMType* = mlirlite.Struct(pool, vt_first_node, vt_method_count, None)
vt_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, vt_ty)
# 构造 vtable 全局变量名
vt_name_buf: str = pool.alloc(128)
@@ -1241,13 +1241,13 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
vt_mangled: str = self.Gen.FuncGenBase._mangle_name(trans, vt_full_name)
# GEP 到 __vtable__ 字段(索引 0)
vt_slot: llvmlite.Value* = llvmlite.build_gep_struct(func_builder, struct_ty, vt_i8_ptr_ty, self_val, 0)
vt_slot: mlirlite.Value* = mlirlite.build_gep_struct(func_builder, struct_ty, vt_i8_ptr_ty, self_val, 0)
if vt_slot is not None:
# 创建全局变量引用 Value
vt_ref: llvmlite.Value* = llvmlite.new_value(pool)
vt_ref: mlirlite.Value* = mlirlite.new_value(pool)
if vt_ref is not None:
llvmlite.value_set_ty(vt_ref, vt_ptr_ty)
llvmlite.value_set_isconst(vt_ref, 1)
mlirlite.value_set_ty(vt_ref, vt_ptr_ty)
mlirlite.value_set_isconst(vt_ref, 1)
# Name 格式: @"mangled" 或 @mangled
vt_ref_name: str = pool.alloc(256)
if vt_ref_name is not None:
@@ -1256,12 +1256,12 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
viperlib.snprintf(vt_ref_name, 256, "@\"%s\"", vt_mangled)
else:
viperlib.snprintf(vt_ref_name, 256, "@%s", vt_mangled)
llvmlite.value_set_name(vt_ref, vt_ref_name)
mlirlite.value_set_name(vt_ref, vt_ref_name)
# bitcast 到 i8*
vt_as_i8: llvmlite.Value* = llvmlite.build_bitcast(func_builder, vt_ref, vt_i8_ptr_ty)
vt_as_i8: mlirlite.Value* = mlirlite.build_bitcast(func_builder, vt_ref, vt_i8_ptr_ty)
if vt_as_i8 is not None:
llvmlite.build_store(func_builder, vt_as_i8, vt_slot)
mlirlite.build_store(func_builder, vt_as_i8, vt_slot)
# 2. 逐字段 store 默认值(用 bi_entry 直接访问,规避跨模块同名 find_struct 找错)
if bi_entry is not None:
@@ -1276,11 +1276,11 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
# 推断为静态数组,此处保证 __before_init__ 填充真实字符串指针。
if fe.Ty is not None and self.Gen.ExprGenBase.is_array_type(fe.Ty) != 0 \
and fe.DefaultVal.kind() == ast.ASTKind.List:
field_ptr_arr: llvmlite.Value* = llvmlite.build_gep_struct(func_builder, struct_ty, fe.Ty, self_val, fe.Index)
field_ptr_arr: mlirlite.Value* = mlirlite.build_gep_struct(func_builder, struct_ty, fe.Ty, self_val, fe.Index)
if field_ptr_arr is not None:
zero_arr_f: llvmlite.Value* = llvmlite.ConstZero(pool, fe.Ty)
zero_arr_f: mlirlite.Value* = mlirlite.ConstZero(pool, fe.Ty)
if zero_arr_f is not None:
llvmlite.build_store(func_builder, zero_arr_f, field_ptr_arr)
mlirlite.build_store(func_builder, zero_arr_f, field_ptr_arr)
# Mixin 静态绑定:self._xxx 只沿本类查找,跨 Mixin 方法
# (AssignGenMixin._init_global_array_from_list)会生成不存在
# 符号 → 必须走 HandlesAnnAssign 模块级委托(延迟 import Gen)。
@@ -1293,16 +1293,16 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
self.Gen.AssignGen._init_global_array_from_list(func_builder, pool, mod, field_ptr_arr, fe.DefaultVal, trans, arr_ctx)
continue
# 翻译默认值表达式
default_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(func_builder, pool, mod, fe.DefaultVal, None, 0, trans)
default_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(func_builder, pool, mod, fe.DefaultVal, None, 0, trans)
if default_val is None: continue
# GEP 到字段
field_ptr: llvmlite.Value* = llvmlite.build_gep_struct(func_builder, struct_ty, fe.Ty, self_val, fe.Index)
field_ptr: mlirlite.Value* = mlirlite.build_gep_struct(func_builder, struct_ty, fe.Ty, self_val, fe.Index)
if field_ptr is None: continue
# 类型转换并 store
default_val = self.Gen.ExprGenBase.coerce_to_type(func_builder, default_val, fe.Ty, fe.DefaultVal)
llvmlite.build_store(func_builder, default_val, field_ptr)
mlirlite.build_store(func_builder, default_val, field_ptr)
# 3. ret void
llvmlite.build_ret_void(func_builder)
mlirlite.build_ret_void(func_builder)
return 0
+31 -31
View File
@@ -1,6 +1,6 @@
import t, c
from stdint import *
import llvmlite
import mlirlite
import memhub
import string
import stdlib
@@ -9,7 +9,7 @@ import w32.win32file as w32file
import lib.core.VLogger as VLogger
# ============================================================
# DebugInfoGen - function-level DWARF metadata emitter (llvmlite text IR)
# DebugInfoGen - function-level DWARF metadata emitter (mlirlite text IR)
#
# Node layout mirrors TPC lib/core/LLVMCG/DebugInfo.py node-for-node:
# !DIFile -> !{ null } -> !DISubroutineType -> distinct !DICompileUnit
@@ -18,7 +18,7 @@ import lib.core.VLogger as VLogger
#
# Enabled only while --traceback is on: the Phase layer mirrors
# BuildPipeline._traceback_mode here via SetEnabled(). While disabled every
# entry point returns before touching any llvmlite DI API, so the emitted IR
# entry point returns before touching any mlirlite DI API, so the emitted IR
# stays byte-identical to the pre-DWARF output.
#
# Scope/statement hooks are driven from the Gen layer:
@@ -31,7 +31,7 @@ import lib.core.VLogger as VLogger
# ---- module-scope state (reset per module by BeginModule) ----
_g_enabled: int = 0
_g_finalized: int = 0
_g_mod: llvmlite.LLVMModule* = None
_g_mod: mlirlite.LLVMModule* = None
_g_file_path: str = None
_g_file_id: int = -1
_g_null_id: int = -1
@@ -39,7 +39,7 @@ _g_subtype_id: int = -1
_g_cu_id: int = -1
_g_cur_sp: int = -1
_g_cur_entry_ref: str = None
_g_cur_builder: llvmlite.IRBuilder* = None
_g_cur_builder: mlirlite.IRBuilder* = None
_g_depth: int = 0
# Push/Pop save stack: enclosing (sp id + 1, entry DILocation ref, builder)
@@ -122,7 +122,7 @@ def _RefOf(pool: memhub.MemBuddy*, node_id: int) -> str:
# ============================================================
# BeginModule - start of one module translation
# ============================================================
def BeginModule(mod: llvmlite.LLVMModule*, file_path: str) -> int:
def BeginModule(mod: mlirlite.LLVMModule*, file_path: str) -> int:
"""Reset per-module DI state. Call once at the start of each module."""
global _g_mod, _g_file_path, _g_finalized, _g_file_id, _g_null_id
global _g_subtype_id, _g_cu_id, _g_cur_sp, _g_cur_entry_ref, _g_cur_builder, _g_depth
@@ -154,7 +154,7 @@ def _EnsureModuleNodes(pool: memhub.MemBuddy*) -> int:
global _g_file_id, _g_null_id, _g_subtype_id, _g_cu_id
if _g_cu_id >= 0:
return 0
mod: llvmlite.LLVMModule* = _g_mod
mod: mlirlite.LLVMModule* = _g_mod
if mod is None:
return 1
# DIFile: **绝对**路径(正斜杠),filename 保留整条路径。
@@ -213,13 +213,13 @@ def _EnsureModuleNodes(pool: memhub.MemBuddy*) -> int:
VLogger.error("--traceback: DIFile 节点缓冲分配失败,终止编译", "DWARF")
return 1
viperlib.snprintf(dbuf, dsize, "!DIFile(filename: \"%s\", directory: \"%s\")", fname, directory)
fid: int = llvmlite.module_add_di_node(mod, pool, dbuf)
fid: int = mlirlite.module_add_di_node(mod, pool, dbuf)
if fid < 0:
VLogger.error("--traceback: DIFile 元数据节点分配失败,终止编译", "DWARF")
return 1
_g_file_id = fid
# types: !{ null } placeholder list, then DISubroutineType referencing it
nid: int = llvmlite.module_add_di_node(mod, pool, "!{ null }")
nid: int = mlirlite.module_add_di_node(mod, pool, "!{ null }")
if nid < 0:
VLogger.error("--traceback: DISubroutineType 类型表分配失败,终止编译", "DWARF")
return 1
@@ -229,7 +229,7 @@ def _EnsureModuleNodes(pool: memhub.MemBuddy*) -> int:
VLogger.error("--traceback: DISubroutineType 缓冲分配失败,终止编译", "DWARF")
return 1
viperlib.snprintf(tbuf, 64, "!DISubroutineType(types: !%d)", _g_null_id)
tid: int = llvmlite.module_add_di_node(mod, pool, tbuf)
tid: int = mlirlite.module_add_di_node(mod, pool, tbuf)
if tid < 0:
VLogger.error("--traceback: DISubroutineType 元数据节点分配失败,终止编译", "DWARF")
return 1
@@ -241,7 +241,7 @@ def _EnsureModuleNodes(pool: memhub.MemBuddy*) -> int:
viperlib.snprintf(cbuf, 256,
"distinct !DICompileUnit(language: DW_LANG_C99, file: !%d, producer: \"TPC\", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)",
_g_file_id)
cid: int = llvmlite.module_add_di_node(mod, pool, cbuf)
cid: int = mlirlite.module_add_di_node(mod, pool, cbuf)
if cid < 0:
VLogger.error("--traceback: DICompileUnit 元数据节点分配失败,终止编译", "DWARF")
return 1
@@ -284,7 +284,7 @@ def _EnsureLocation(pool: memhub.MemBuddy*, sp: int, line: int, col: int) -> str
if lbuf is None:
return None
viperlib.snprintf(lbuf, 96, "!DILocation(line: %d, column: %d, scope: !%d)", line, c, sp)
lid: int = llvmlite.module_add_di_node(_g_mod, pool, lbuf)
lid: int = mlirlite.module_add_di_node(_g_mod, pool, lbuf)
if lid < 0:
VLogger.error("--traceback: DILocation 元数据节点分配失败,终止编译", "DWARF")
return None
@@ -307,8 +307,8 @@ def _EnsureLocation(pool: memhub.MemBuddy*, sp: int, line: int, col: int) -> str
# ============================================================
# PushFunction - create the DISubprogram for one define
# ============================================================
def PushFunction(pool: memhub.MemBuddy*, builder: llvmlite.IRBuilder*,
func: llvmlite.Function*, line: int, col: int) -> int:
def PushFunction(pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*,
func: mlirlite.Function*, line: int, col: int) -> int:
"""Attach a DISubprogram to one define and set the builder's entry DILocation.
Returns 1 when pushed (caller must call PopFunction), 0 when DI is disabled
@@ -325,7 +325,7 @@ def PushFunction(pool: memhub.MemBuddy*, builder: llvmlite.IRBuilder*,
return 0
if _EnsureModuleNodes(pool) != 0:
return 0
name: str = llvmlite.function_get_name(func)
name: str = mlirlite.function_get_name(func)
if name is None:
VLogger.error("--traceback: 函数名为空,无法发射 DISubprogram,终止编译", "DWARF")
return 0
@@ -343,7 +343,7 @@ def PushFunction(pool: memhub.MemBuddy*, builder: llvmlite.IRBuilder*,
viperlib.snprintf(spbuf, ssize,
"distinct !DISubprogram(name: \"%s\", scope: !%d, file: !%d, type: !%d, line: %d, scopeLine: %d, unit: !%d, spFlags: DISPFlagDefinition)",
name, _g_file_id, _g_file_id, _g_subtype_id, dline, dline, _g_cu_id)
sp_id: int = llvmlite.module_add_di_node(_g_mod, pool, spbuf)
sp_id: int = mlirlite.module_add_di_node(_g_mod, pool, spbuf)
if sp_id < 0:
VLogger.error("--traceback: DISubprogram 元数据节点分配失败,终止编译", "DWARF")
return 0
@@ -351,7 +351,7 @@ def PushFunction(pool: memhub.MemBuddy*, builder: llvmlite.IRBuilder*,
if sp_ref is None:
VLogger.error("--traceback: DISubprogram 引用缓冲分配失败,终止编译", "DWARF")
return 0
llvmlite.function_set_dbg(func, sp_ref)
mlirlite.function_set_dbg(func, sp_ref)
# save the enclosing function's DI context (LIFO), then switch to this one
_g_stk_sp[_g_depth] = sizet(_g_cur_sp + 1)
rslot: str | t.CPtr = (str | t.CPtr)(uint64(_g_stk_ref) + sizet(_g_depth) * 8)
@@ -366,14 +366,14 @@ def PushFunction(pool: memhub.MemBuddy*, builder: llvmlite.IRBuilder*,
VLogger.error("--traceback: 入口 DILocation 生成失败,终止编译", "DWARF")
return 0
_g_cur_entry_ref = entry_ref
llvmlite.builder_set_debug_location(builder, entry_ref)
mlirlite.builder_set_debug_location(builder, entry_ref)
return 1
# ============================================================
# PopFunction - restore the enclosing function's DI context
# ============================================================
def PopFunction(builder: llvmlite.IRBuilder*) -> int:
def PopFunction(builder: mlirlite.IRBuilder*) -> int:
global _g_cur_sp, _g_cur_entry_ref, _g_cur_builder, _g_depth
if _g_enabled == 0:
return 0
@@ -384,16 +384,16 @@ def PopFunction(builder: llvmlite.IRBuilder*) -> int:
rslot: str | t.CPtr = (str | t.CPtr)(uint64(_g_stk_ref) + sizet(_g_depth) * 8)
_g_cur_entry_ref = rslot[0]
bslot: str | t.CPtr = (str | t.CPtr)(uint64(_g_stk_bld) + sizet(_g_depth) * 8)
_g_cur_builder = (llvmlite.IRBuilder*)(bslot[0])
_g_cur_builder = (mlirlite.IRBuilder*)(bslot[0])
if builder is not None:
llvmlite.builder_clear_debug_location(builder)
mlirlite.builder_clear_debug_location(builder)
return 0
# ============================================================
# SetStatement - point the current builder at a statement DILocation
# ============================================================
def SetStatement(pool: memhub.MemBuddy*, builder: llvmlite.IRBuilder*,
def SetStatement(pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*,
line: int, col: int) -> int:
"""Update the builder's DILocation to the current statement (line precision).
@@ -407,25 +407,25 @@ def SetStatement(pool: memhub.MemBuddy*, builder: llvmlite.IRBuilder*,
ref: str = _EnsureLocation(pool, _g_cur_sp, line, col)
if ref is None:
return 0
llvmlite.builder_set_debug_location(builder, ref)
mlirlite.builder_set_debug_location(builder, ref)
return 1
# ============================================================
# _ModuleHasDefine - does the module emit any define (IsDeclared == 0)?
# ============================================================
def _ModuleHasDefine(mod: llvmlite.LLVMModule*) -> int:
def _ModuleHasDefine(mod: mlirlite.LLVMModule*) -> int:
if mod is None:
return 0
cur: llvmlite.Function* = mod.FuncHead
cur: mlirlite.Function* = mod.FuncHead
steps: int = 0
while cur is not None:
steps += 1
if steps > 100000:
break
if llvmlite.function_is_declared(cur) == 0:
if mlirlite.function_is_declared(cur) == 0:
return 1
cur = llvmlite.function_get_next(cur)
cur = mlirlite.function_get_next(cur)
return 0
@@ -439,7 +439,7 @@ def Finalize(pool: memhub.MemBuddy*) -> int:
return 0
if _g_finalized != 0:
return 0
mod: llvmlite.LLVMModule* = _g_mod
mod: mlirlite.LLVMModule* = _g_mod
if mod is None or pool is None:
return 0
_g_finalized = 1
@@ -453,13 +453,13 @@ def Finalize(pool: memhub.MemBuddy*) -> int:
if cu_ref is None:
VLogger.error("--traceback: DICompileUnit 引用缓冲分配失败,终止编译", "DWARF")
return 1
llvmlite.module_add_named_metadata(mod, pool, "llvm.dbg.cu", cu_ref)
mlirlite.module_add_named_metadata(mod, pool, "llvm.dbg.cu", cu_ref)
fbuf: str = pool.alloc(64)
if fbuf is None:
VLogger.error("--traceback: 模块级调试标志缓冲分配失败,终止编译", "DWARF")
return 1
viperlib.snprintf(fbuf, 64, "!{i32 2, !\"Debug Info Version\", i32 3}")
flags_id: int = llvmlite.module_add_di_node(mod, pool, fbuf)
flags_id: int = mlirlite.module_add_di_node(mod, pool, fbuf)
if flags_id < 0:
VLogger.error("--traceback: llvm.module.flags 元数据节点分配失败,终止编译", "DWARF")
return 1
@@ -467,5 +467,5 @@ def Finalize(pool: memhub.MemBuddy*) -> int:
if fl_ref is None:
VLogger.error("--traceback: llvm.module.flags 引用缓冲分配失败,终止编译", "DWARF")
return 1
llvmlite.module_add_named_metadata(mod, pool, "llvm.module.flags", fl_ref)
mlirlite.module_add_named_metadata(mod, pool, "llvm.module.flags", fl_ref)
return 0
+110 -110
View File
@@ -2,7 +2,7 @@ import lib.core.Gen.GenTypes as GenTypes
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdio
@@ -29,13 +29,13 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
# 1. 精确匹配 (如 "_mbuddy" 匹配 @_mbuddy)
# 2. 后缀匹配 (如 "_mbuddy" 匹配 @"sha1._mbuddy")
# ============================================================
def find_global_in_module(self, mod: llvmlite.LLVMModule*,
name: str) -> llvmlite.GlobalVariable*:
def find_global_in_module(self, mod: mlirlite.LLVMModule*,
name: str) -> mlirlite.GlobalVariable*:
"""在模块全局变量链表中按名称查找全局变量"""
if mod is None or name is None:
return None
name_len: sizet = string.strlen(name)
cur: llvmlite.GlobalVariable* = mod.GlobalHead
cur: mlirlite.GlobalVariable* = mod.GlobalHead
# 第一遍: 精确匹配
while cur is not None:
if cur.Name is not None:
@@ -67,11 +67,11 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
# ============================================================
def make_global_ref(self, pool: memhub.MemBuddy*,
name: str,
ty: llvmlite.LLVMType*) -> llvmlite.Value*:
ty: mlirlite.LLVMType*) -> mlirlite.Value*:
"""创建全局变量引用 (类型为 ty*,名称为 @name)"""
if name is None or ty is None:
return None
ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, ty)
ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, ty)
ref_name: str = pool.alloc(96)
if ref_name is None:
return None
@@ -83,7 +83,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
viperlib.snprintf(ref_name, 96, "@\"%s\"", name)
else:
viperlib.snprintf(ref_name, 96, "@%s", name)
return llvmlite.SSAValue(pool, ptr_ty, ref_name)
return mlirlite.SSAValue(pool, ptr_ty, ref_name)
# ============================================================
# _resolve_module_attribute_global - 解析模块属性访问的全局变量引用
#
@@ -220,10 +220,10 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
"NameError")
return 0
def _resolve_module_attribute_global(self, pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
trans: HT.Translator*,
at: ast.Attribute*,
ty_hint: llvmlite.LLVMType*) -> llvmlite.Value*:
ty_hint: mlirlite.LLVMType*) -> mlirlite.Value*:
"""解析模块属性访问,返回全局变量引用 (用于跨模块 global 访问)"""
if at is None or at.value is None or at.attr is None:
return None
@@ -261,7 +261,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
# 避免多模块同名全局(@<A>._mbuddy / @<B>._mbuddy 同时注入)时裸名后缀
# 匹配返回错误模块的全局(串扰)。目标 sha1 未知时退化裸名(后缀匹配兜底)
gv_q: str = self.Gen.FuncGenBase._mangle_name_with_sha1(self._lookup_module_sha1(mod_path_w), at.attr)
gv: llvmlite.GlobalVariable* = self.find_global_in_module(mod, gv_q)
gv: mlirlite.GlobalVariable* = self.find_global_in_module(mod, gv_q)
# CExport 全局(定义端裸名 @_sched_ptr):mangled 名查不到时回退裸名精确
# 查找。此前只查 mangled 名 → 找不到 → 新建 mangled external global 声明
# (@"ef5b0ba0dc895058._sched_ptr")→ 与定义端裸名不匹配 → ld.lld
@@ -275,11 +275,11 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
return self.make_global_ref(pool, gv.Name, gv.Ty)
# 未找到: 创建 external global 声明并添加到模块
# 否则只生成 @_argc 引用而无声明,LLVM 报 "use of undefined value '@_argc'"
use_ty: llvmlite.LLVMType* = ty_hint
use_ty: mlirlite.LLVMType* = ty_hint
if use_ty is None:
use_ty = llvmlite.Int8(pool)
use_ty = mlirlite.Int8(pool)
# 确保 use_ty 中的跨模块结构体类型有 opaque 声明
llvmlite.module_ensure_opaque_for_type(mod, pool, use_ty)
mlirlite.module_ensure_opaque_for_type(mod, pool, use_ty)
# 特殊处理: t.py 中的类型对象(CPtr/CInt/CDouble 等)
# t.py 不被编译,但这些类型对象在运行时被引用(如 va_arg(ap, t.CPtr))。
# 创建带 null 初值的 linkonce_odr 全局变量定义,避免链接时 undefined reference。
@@ -287,7 +287,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
is_t_type_obj: int = 0
if string.strcmp(mod_path_w, "t") == 0:
is_t_type_obj = self._is_t_type_object_name(at.attr)
# 类名不是模块级全局变量:Module.ClassName(如 llvmlite.LLVMType,定义在 .__types.vp,包 __init__.vp 仅再导出)此前被制造成 @"sha1.LLVMType" = external global i8* 并 load,而全仓无该全局定义(唯一引用点是变体构造时被丢弃的 callee 求值),ASan 插桩下 ld.lld undefined symbol。已注册类/结构体/REnum 一律交给类/REnum 路径,不在此制造全局
# 类名不是模块级全局变量:Module.ClassName(如 mlirlite.LLVMType,定义在 .__types.vp,包 __init__.vp 仅再导出)此前被制造成 @"sha1.LLVMType" = external global i8* 并 load,而全仓无该全局定义(唯一引用点是变体构造时被丢弃的 callee 求值),ASan 插桩下 ld.lld undefined symbol。已注册类/结构体/REnum 一律交给类/REnum 路径,不在此制造全局
if is_t_type_obj == 0 and self.Gen.StructGen.find_struct(at.attr) is not None:
return None
# 兜底声明名:t 类型对象(t.py 不编译、无 sha1)保持裸名 linkonce_odr;
@@ -296,7 +296,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
gv_name_ba: str = at.attr
if is_t_type_obj == 0:
gv_name_ba = self.Gen.FuncGenBase._mangle_name_with_sha1(self._lookup_module_sha1(mod_path_w), at.attr)
ext_gv: llvmlite.GlobalVariable* = llvmlite.new_global_variable(pool, gv_name_ba, use_ty)
ext_gv: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, gv_name_ba, use_ty)
if ext_gv is not None:
if is_t_type_obj != 0:
# t.CPtr 等类型对象: 创建带 null 初值的定义(linkonce_odr)
@@ -316,7 +316,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
# 普通模块属性: external 声明(由其他模块提供定义)
ext_gv.Linkage = "external"
ext_gv.Initializer = None
llvmlite.module_add_global(mod, ext_gv)
mlirlite.module_add_global(mod, ext_gv)
return self.make_global_ref(pool, gv_name_ba, use_ty)
def _lookup_module_sha1(self, mod_name: str) -> str:
"""查找模块名对应的 SHA1(委托 StubMergerStore,支持包名回退;
@@ -346,11 +346,11 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
# ptr 指针值(Ptr(Struct) 或 Ptr(Ptr(Struct)),交由 _deref_if_ptr_ptr 解层级)
# 非 c.Deref 模式返回 None
# ============================================================
def _get_cderef_attr_base(self, builder: llvmlite.IRBuilder*,
def _get_cderef_attr_base(self, builder: mlirlite.IRBuilder*,
pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
at_value: ast.AST*,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""检测 at.value 是否为 c.Deref(ptr) 调用,返回 ptr 指针(不做 load)"""
if at_value is None or at_value.kind() != ast.ASTKind.Call:
return None
@@ -367,15 +367,15 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
return None
if cl_cd.args is None or len(cl_cd.args) < 1:
return None
inner_cd: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cl_cd.args.get(0), None, 0, trans)
inner_cd: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cl_cd.args.get(0), None, 0, trans)
if inner_cd is not None and self.is_ptr_type(inner_cd.Ty) != 0:
return inner_cd
return None
def translate_attribute(self, builder: llvmlite.IRBuilder*,
def translate_attribute(self, builder: mlirlite.IRBuilder*,
pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
node: ast.AST*,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""翻译属性访问,返回加载的字段值"""
if node is None or builder is None:
return None
@@ -426,13 +426,13 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
if doc_mod_buf[0] != '\0' and doc_sym_buf[0] != '\0':
doc_val = self.Gen.ExprGenCls.lookup_docstring(doc_mod_buf, doc_sym_buf)
if doc_val is None:
i8_ty_doc: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ty_doc: mlirlite.LLVMType* = mlirlite.Int8(pool)
if i8_ty_doc is None:
return None
i8_ptr_ty_doc: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty_doc)
i8_ptr_ty_doc: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_doc)
if i8_ptr_ty_doc is None:
return None
return llvmlite.ConstNull(pool, i8_ptr_ty_doc, "null")
return mlirlite.ConstNull(pool, i8_ptr_ty_doc, "null")
return self.Gen.ExprGenConst.create_global_string(builder, pool, mod, doc_val, trans)
# 枚举成员访问: EnumName.MemberName → 常量值
@@ -443,14 +443,14 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
if self.Gen.StmtGenDecl.is_enum_class(enum_nm.id) == 1:
member: rawptr[GenTypes.EnumMember] = self.Gen.StmtGenDecl.lookup_enum_member(enum_nm.id, at.attr)
if member is not None:
base_ty: llvmlite.LLVMType* = self.Gen.StmtGenDecl.get_enum_base_type(enum_nm.id)
base_ty: mlirlite.LLVMType* = self.Gen.StmtGenDecl.get_enum_base_type(enum_nm.id)
if base_ty is not None:
# 生成数字字符串作为常量名(LLVM IR 要求常量输出数字值)
name_buf: str = pool.alloc(32)
if name_buf is not None:
viperlib.snprintf(name_buf, 32, "%lld", member.Value)
return llvmlite.ConstInt(pool, base_ty, member.Value, name_buf)
return llvmlite.const_int32(pool, member.Value)
return mlirlite.ConstInt(pool, base_ty, member.Value, name_buf)
return mlirlite.const_int32(pool, member.Value)
# fast-fail: 枚举成员未找到
VLogger.error(f"枚举成员未找到: {enum_nm.id}.{at.attr}", "ATTR")
return None
@@ -467,13 +467,13 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
if self.Gen.StmtGenDecl.is_enum_class(inner_at_e.attr) == 1:
member_e: rawptr[GenTypes.EnumMember] = self.Gen.StmtGenDecl.lookup_enum_member( inner_at_e.attr, at.attr)
if member_e is not None:
base_ty_e: llvmlite.LLVMType* = self.Gen.StmtGenDecl.get_enum_base_type(inner_at_e.attr)
base_ty_e: mlirlite.LLVMType* = self.Gen.StmtGenDecl.get_enum_base_type(inner_at_e.attr)
if base_ty_e is not None:
name_buf_e: str = pool.alloc(32)
if name_buf_e is not None:
viperlib.snprintf(name_buf_e, 32, "%lld", member_e.Value)
return llvmlite.ConstInt(pool, base_ty_e, member_e.Value, name_buf_e)
return llvmlite.const_int32(pool, member_e.Value)
return mlirlite.ConstInt(pool, base_ty_e, member_e.Value, name_buf_e)
return mlirlite.const_int32(pool, member_e.Value)
# fast-fail: 嵌套枚举成员未找到
dbg_ee: rawptr[GenTypes.EnumEntry] = self.Gen.StmtGenDecl.find_enum(inner_at_e.attr)
dbg_mc: int = -1
@@ -483,7 +483,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
return None
# REnum 变体引用作为值: ClassName.Variant / Module.ClassName.Variant → 变体 tag 常量
# 如 llvmlite.LLVMType.Struct(if resolved.kind() == llvmlite.LLVMType.Struct 比较)。
# 如 mlirlite.LLVMType.Struct(if resolved.kind() == mlirlite.LLVMType.Struct 比较)。
# 无括号引用(非构造调用)时变体名解析为该变体 tag(i32 常量),与 match 机制
# _lookup_renum_variant_in_class 一致。工厂函数名(LLVMType.Int8 等非变体,
# 见 __types.vp)查变体返回 -1 → 自然落空不拦截。
@@ -503,8 +503,8 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
name_buf_rv: str = pool.alloc(32)
if name_buf_rv is not None:
viperlib.snprintf(name_buf_rv, 32, "%d", rv_tag)
return llvmlite.ConstInt(pool, llvmlite.Int32(pool), rv_tag, name_buf_rv)
return llvmlite.ConstInt(pool, llvmlite.Int32(pool), rv_tag, "0")
return mlirlite.ConstInt(pool, mlirlite.Int32(pool), rv_tag, name_buf_rv)
return mlirlite.ConstInt(pool, mlirlite.Int32(pool), rv_tag, "0")
# FakeDuck: 影子结构体属性读取 (str 变量的 per-instance 字段)
# a.__data__ / a.__mbuddy__ → GEP {a}__meta__[field] 并加载
@@ -517,16 +517,16 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
fd_meta_buf: str = pool.alloc(256)
if fd_meta_buf is not None:
viperlib.snprintf(fd_meta_buf, 256, "%s__meta__", fd_nm.id)
fd_meta_v: llvmlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, fd_meta_buf)
fd_meta_v: mlirlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, fd_meta_buf)
if fd_meta_v is not None:
fd_sty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type("_str")
fd_sty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type("_str")
if fd_sty is not None:
fd_fe: GenTypes.FieldEntry* = \
self.Gen.StructGen.lookup_field(fd_sty, at.attr)
if fd_fe is not None and fd_fe.Ty is not None:
fd_fp: llvmlite.Value* = llvmlite.build_gep_struct(builder, fd_sty, fd_fe.Ty, fd_meta_v, fd_fe.Index)
fd_fp: mlirlite.Value* = mlirlite.build_gep_struct(builder, fd_sty, fd_fe.Ty, fd_meta_v, fd_fe.Index)
if fd_fp is not None:
return llvmlite.build_load(builder, fd_fe.Ty, fd_fp)
return mlirlite.build_load(builder, fd_fe.Ty, fd_fp)
# 模块属性访问 (读路径): sys._mbuddy → 加载全局变量 @_mbuddy
# 当 obj 是已导入模块名且不是普通变量时,查找/创建全局变量引用并加载
@@ -534,7 +534,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
nm_ma: ast.Name* = ast.Name*(at.value)
if nm_ma.id is not None:
# 先检查是否是普通变量 (优先级高于模块属性)
ma_is_var: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm_ma.id)
ma_is_var: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm_ma.id)
if ma_is_var is None:
# 先检查是否是 CDefine 编译期常量 (如 ast.CONST_INT / win32base.INVALID_HANDLE_VALUE)
# 模块属性访问的 CDefine 常量需要跨模块查找源 .vp / .vpi 文件
@@ -578,7 +578,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
# 跨模块浮点 CDefine(如 vipermath.U_M_PI)→ 浮点常量
dchk_ma: double = self.Gen.TypeGenCDef.lookup_cdefine_double(at.attr)
if self.Gen.TypeGenCDef.is_cdefine_double() != 0:
return llvmlite.ConstFloat(pool, llvmlite.Double(pool), dchk_ma)
return mlirlite.ConstFloat(pool, mlirlite.Double(pool), dchk_ma)
return self.Gen.ExprGenCdef._const_int_for_cdefine(pool, cdef_ma_val)
# 检查 nm_ma.id.at.attr 是否是已导入子模块 (如 w32.win32file)
# 如果是子模块,不应创建全局变量,让嵌套属性访问路径处理
@@ -631,20 +631,20 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
self.Gen.TypeGenErr.fatal_error(at, f"跨模块 CDefine 未找到: '{nm_ma.id}.{at.attr}'(CDefine cross-module lookup failed)", "TypeError")
# 命中跨模块全局 → 落到下方跨模块全局加载路径
# 非 CDefine: 使用 i8* 作为类型提示 (模块级变量通常存储指针)
i8_ptr_hint: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
mod_gv_ref: llvmlite.Value* = self._resolve_module_attribute_global(pool, mod, trans, at, i8_ptr_hint)
i8_ptr_hint: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
mod_gv_ref: mlirlite.Value* = self._resolve_module_attribute_global(pool, mod, trans, at, i8_ptr_hint)
if mod_gv_ref is not None and mod_gv_ref.Ty is not None:
load_ty_mod: llvmlite.LLVMType* = mod_gv_ref.Ty.Pointee
load_ty_mod: mlirlite.LLVMType* = mod_gv_ref.Ty.Pointee
if load_ty_mod is not None:
# 模块级全局数组(如 zdef.zdeflate_len_base: CArray[T, N]):
# 按 C 语义衰减为基址返回(对齐 translate_name_value 局部
# 数组分支 L3383-3388),load [N x T] 数组值无法作 GEP 基址。
match load_ty_mod:
case llvmlite.LLVMType.Array(_, _):
case mlirlite.LLVMType.Array(_, _):
return mod_gv_ref
case _:
pass
return llvmlite.build_load(builder, load_ty_mod, mod_gv_ref)
return mlirlite.build_load(builder, load_ty_mod, mod_gv_ref)
# 嵌套模块属性访问 (w32.win32file.GENERIC_READ → 查找全局 @GENERIC_READ)
# 当 at.value 是 Attribute 且解析为已导入子模块时,查找 at.attr 作为全局常量
@@ -672,24 +672,24 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
# 查找全局变量 at.attr(带限定模块 SHA1 前缀精确匹配,
# 避免多模块同名全局后缀匹配串扰;sha1 未知退化裸名)
gv_nested_q: str = self.Gen.FuncGenBase._mangle_name_with_sha1(self._lookup_module_sha1(qual_buf), at.attr)
gv_nested: llvmlite.GlobalVariable* = self.find_global_in_module(mod, gv_nested_q)
gv_nested: mlirlite.GlobalVariable* = self.find_global_in_module(mod, gv_nested_q)
# CExport 全局(定义端裸名 @idt)mangled 名查不到时回退
# 裸名精确查找(对齐读路径 _resolve_module_attribute_global)
if gv_nested is None:
gv_nested = self.find_global_in_module(mod, at.attr)
if gv_nested is not None and gv_nested.Ty is not None:
gv_ref_nested: llvmlite.Value* = self.make_global_ref(pool, gv_nested.Name, gv_nested.Ty)
gv_ref_nested: mlirlite.Value* = self.make_global_ref(pool, gv_nested.Name, gv_nested.Ty)
if gv_ref_nested is not None and gv_ref_nested.Ty is not None:
load_ty_nested: llvmlite.LLVMType* = gv_ref_nested.Ty.Pointee
load_ty_nested: mlirlite.LLVMType* = gv_ref_nested.Ty.Pointee
if load_ty_nested is not None:
# 模块级全局数组(如 idt.idt: CArray[T, N])按 C 语义
# 返回基址指针(对齐读路径 L629-634),下标/取址继续 GEP
match load_ty_nested:
case llvmlite.LLVMType.Array(_, _):
case mlirlite.LLVMType.Array(_, _):
return gv_ref_nested
case _:
pass
return llvmlite.build_load(builder, load_ty_nested, gv_ref_nested)
return mlirlite.build_load(builder, load_ty_nested, gv_ref_nested)
# 未找到全局: 尝试 CDefine 常量查找
# 对于 w32.win32base.INVALID_HANDLE_VALUE 等嵌套模块属性访问,
# 先从限定模块的 .vpi 文件中查找 CDefine 常量值并内联
@@ -705,7 +705,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
# 跨模块浮点 CDefine → 浮点常量
dchk_nst: double = self.Gen.TypeGenCDef.lookup_cdefine_double(at.attr)
if self.Gen.TypeGenCDef.is_cdefine_double() != 0:
return llvmlite.ConstFloat(pool, llvmlite.Double(pool), dchk_nst)
return mlirlite.ConstFloat(pool, mlirlite.Double(pool), dchk_nst)
return self.Gen.ExprGenCdef._const_int_for_cdefine(pool, cdef_val_nested)
# CDefine 未找到: fail-fast 终止编译(不再创建未定义的全局变量引用)
# 之前此处创建 @INVALID_HANDLE_VALUE 等前向引用,但全局未定义,
@@ -718,28 +718,28 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
# 对于 Name 类型的 obj,直接查找 alloca(不 load 结构体);
# nonlocal 变量(提升函数内)从 env 读共享堆值,避免 lookup_var
# 跨函数引用外层 alloca(SSA 编号跨函数错乱崩溃)
obj_ptr: llvmlite.Value* = None
obj_ptr: mlirlite.Value* = None
if at.value.kind() == ast.ASTKind.Name and trans is not None:
nm: ast.Name* = ast.Name*(at.value)
if nm.id is not None:
if GenApi.is_nonlocal_name(trans, nm.id) != 0:
raw_nl_a: llvmlite.Value* = self.Gen.StmtGenDecl._load_raw_var_ptr(trans, nm.id)
raw_nl_a: mlirlite.Value* = self.Gen.StmtGenDecl._load_raw_var_ptr(trans, nm.id)
if raw_nl_a is not None:
nl_ty_a: llvmlite.LLVMType* = GenApi.get_nonlocal_type(trans, nm.id)
nl_ty_a: mlirlite.LLVMType* = GenApi.get_nonlocal_type(trans, nm.id)
if nl_ty_a is not None:
# 对象即指针:Struct/Array 类型直接用堆地址(bitcast 后
# 作为对象指针,不 load);指针类型(如 Ptr(Point))堆里
# 存对象指针,需 load 出对象指针
match nl_ty_a:
case llvmlite.LLVMType.Struct(_, _, _):
obj_ptr = llvmlite.build_bitcast(builder, raw_nl_a, llvmlite.Ptr(pool, nl_ty_a))
case llvmlite.LLVMType.Array(_, _):
obj_ptr = llvmlite.build_bitcast(builder, raw_nl_a, llvmlite.Ptr(pool, nl_ty_a))
case mlirlite.LLVMType.Struct(_, _, _):
obj_ptr = mlirlite.build_bitcast(builder, raw_nl_a, mlirlite.Ptr(pool, nl_ty_a))
case mlirlite.LLVMType.Array(_, _):
obj_ptr = mlirlite.build_bitcast(builder, raw_nl_a, mlirlite.Ptr(pool, nl_ty_a))
case _:
nl_val_ptr_a: llvmlite.Value* = \
llvmlite.build_bitcast(builder, raw_nl_a, llvmlite.Ptr(pool, nl_ty_a))
nl_val_ptr_a: mlirlite.Value* = \
mlirlite.build_bitcast(builder, raw_nl_a, mlirlite.Ptr(pool, nl_ty_a))
if nl_val_ptr_a is not None:
obj_ptr = llvmlite.build_load(builder, nl_ty_a, nl_val_ptr_a)
obj_ptr = mlirlite.build_load(builder, nl_ty_a, nl_val_ptr_a)
else:
obj_ptr = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
@@ -747,7 +747,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
if obj_ptr is None:
# c.Deref(ptr).attr: 属性访问 base 取指针本身而非 load 后的结构体值
# (如 c.Deref(p).a 语义是 (*p).a,直接对 p 做 GEP)
cd_base_rd: llvmlite.Value* = self._get_cderef_attr_base(builder, pool, mod, at.value, trans)
cd_base_rd: mlirlite.Value* = self._get_cderef_attr_base(builder, pool, mod, at.value, trans)
if cd_base_rd is not None:
obj_ptr = cd_base_rd
elif at.value.kind() == ast.ASTKind.Subscript:
@@ -782,7 +782,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
# 查找结构体类型信息
# obj_ptr 类型应该是 Ptr(Struct(...))
match obj_ptr.Ty:
case llvmlite.LLVMType.Ptr(struct_ty):
case mlirlite.LLVMType.Ptr(struct_ty):
# 确保跨模块结构体的完整定义在当前模块中可用(供 getelementptr 访问字段)
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, struct_ty)
# 查找字段索引和类型
@@ -798,22 +798,22 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
if alias_idx >= 1:
alias_fe: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(renum_se, alias_idx)
if alias_fe is not None and alias_fe.Ty is not None:
alias_ptr: llvmlite.Value* = llvmlite.build_gep_struct(builder, struct_ty, alias_fe.Ty, obj_ptr, alias_idx)
alias_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, alias_fe.Ty, obj_ptr, alias_idx)
if alias_ptr is not None:
# REnum 变体字段按声明类型读取(对齐 match 绑定 _lookup_renum_member_ty):槽位是 i32/i64(布局按最大字段大小),直接 load 得整数位模式,赋给 X|t.CPtr 指针变量会触发 int→ptr 禁令误报。用别名表存的成员声明类型(自引用退化为 i8*)把槽位地址 bitcast 后按声明类型 load——同宽无信息丢失,指针字段读出真正的指针值
decl_ty_rn: llvmlite.LLVMType* = self.Gen.ClassGenEnum._lookup_renum_field_alias_ty(renum_se.Name, at.attr)
decl_ty_rn: mlirlite.LLVMType* = self.Gen.ClassGenEnum._lookup_renum_field_alias_ty(renum_se.Name, at.attr)
if decl_ty_rn is not None:
decl_ptr_rn: llvmlite.LLVMType* = llvmlite.Ptr(pool, decl_ty_rn)
decl_ptr_rn: mlirlite.LLVMType* = mlirlite.Ptr(pool, decl_ty_rn)
if decl_ptr_rn is not None:
cast_ptr_rn: llvmlite.Value* = llvmlite.build_bitcast(builder, alias_ptr, decl_ptr_rn)
cast_ptr_rn: mlirlite.Value* = mlirlite.build_bitcast(builder, alias_ptr, decl_ptr_rn)
if cast_ptr_rn is not None:
return llvmlite.build_load(builder, decl_ty_rn, cast_ptr_rn)
return llvmlite.build_load(builder, alias_fe.Ty, alias_ptr, vol_ba_rd)
return mlirlite.build_load(builder, decl_ty_rn, cast_ptr_rn)
return mlirlite.build_load(builder, alias_fe.Ty, alias_ptr, vol_ba_rd)
# property getter 回退: obj.attr 是 @property/@x.getter 方法时生成调用
# (字段未找到时先尝试,避免报误导性的"字段未找到"错误)
if field_info is None and at.value is not None and trans is not None:
prop_cls_fb: str = self.Gen.StructGen.get_class_name_by_type(pool, struct_ty)
prop_val: llvmlite.Value* = self.Gen.CallGenProp._try_property_getter_attr(pool, builder, mod, at, obj_ptr, trans, prop_cls_fb)
prop_val: mlirlite.Value* = self.Gen.CallGenProp._try_property_getter_attr(pool, builder, mod, at, obj_ptr, trans, prop_cls_fb)
if prop_val is not None:
return prop_val
# 按需过滤: struct_ty 为 i8(简化联合类型)时,通过 AnnotClassName 按类名查找
@@ -859,8 +859,8 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
if field_info is not None:
annot_se: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(base_class)
if annot_se is not None and annot_se.Ty is not None:
annot_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, annot_se.Ty)
casted_ptr: llvmlite.Value* = llvmlite.build_bitcast(builder, obj_ptr, annot_ptr_ty)
annot_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, annot_se.Ty)
casted_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, obj_ptr, annot_ptr_ty)
if casted_ptr is not None:
obj_ptr = casted_ptr
struct_ty = annot_se.Ty
@@ -869,7 +869,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
# (原始 struct_ty 可能是 i8,ensure 无效)
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, annot_se.Ty)
if field_info is not None:
field_ty: llvmlite.LLVMType* = field_info.Ty
field_ty: mlirlite.LLVMType* = field_info.Ty
# t.CVolatile 字段:经对象访问的 load 带 volatile 限定符
field_vol_rd: int = self.Gen.StructGen.field_is_volatile(field_info)
# 合并"字段所指物 volatile"(基址是 rawptr[t.CVolatile|T] 时,
@@ -878,14 +878,14 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
field_vol_rd = 1
# 联合体:bitcast obj_ptr 到 field_ty* 后 load
if self.Gen.StructGen.is_union_by_type(struct_ty) == 1:
field_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, field_ty)
casted: llvmlite.Value* = llvmlite.build_bitcast(builder, obj_ptr, field_ptr_ty)
field_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, field_ty)
casted: mlirlite.Value* = mlirlite.build_bitcast(builder, obj_ptr, field_ptr_ty)
if casted is not None:
return llvmlite.build_load(builder, field_ty, casted, field_vol_rd)
return mlirlite.build_load(builder, field_ty, casted, field_vol_rd)
return None
# 普通结构体:GEP + load
field_idx: int = field_info.Index
field_ptr: llvmlite.Value* = llvmlite.build_gep_struct(builder, struct_ty, field_ty, obj_ptr, field_idx)
field_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, field_ty, obj_ptr, field_idx)
if field_ptr is not None:
# [FIX 2026-08-31] REnum 变体字段按声明类型读取(与主路径
# 变体别名回退一致):field_info 是 _pN 槽位(i32/i64),
@@ -895,19 +895,19 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
self.Gen.StructGen.find_struct_by_type(struct_ty)
if rn_rd_se is not None and rn_rd_se.Name is not None \
and self.Gen.ClassGenEnum._is_renum_class_name(rn_rd_se.Name) != 0:
decl_ty_rd: llvmlite.LLVMType* = \
decl_ty_rd: mlirlite.LLVMType* = \
self.Gen.ClassGenEnum._lookup_renum_field_alias_ty(rn_rd_se.Name, at.attr)
if decl_ty_rd is not None and self.is_array_type(decl_ty_rd) == 0:
decl_ptr_rd: llvmlite.LLVMType* = llvmlite.Ptr(pool, decl_ty_rd)
decl_ptr_rd: mlirlite.LLVMType* = mlirlite.Ptr(pool, decl_ty_rd)
if decl_ptr_rd is not None:
cast_ptr_rd: llvmlite.Value* = llvmlite.build_bitcast(builder, field_ptr, decl_ptr_rd)
cast_ptr_rd: mlirlite.Value* = mlirlite.build_bitcast(builder, field_ptr, decl_ptr_rd)
if cast_ptr_rd is not None:
return llvmlite.build_load(builder, decl_ty_rd, cast_ptr_rd, field_vol_rd)
return mlirlite.build_load(builder, decl_ty_rd, cast_ptr_rd, field_vol_rd)
# 数组类型字段不能 load 为 SSA value,直接返回字段指针
# 用于后续下标访问: self.state[0] → GEP state 字段 → GEP 数组元素
if self.is_array_type(field_ty) != 0:
return field_ptr
loaded_val: llvmlite.Value* = llvmlite.build_load(builder, field_ty, field_ptr, field_vol_rd)
loaded_val: mlirlite.Value* = mlirlite.build_load(builder, field_ty, field_ptr, field_vol_rd)
# 联合类型字段(如 Token | t.CPtr)被编译为 i8*,
# 若 AnnotClassName 指示了具体结构体类型,bitcast 为正确的结构体指针。
# 注意:仅当字段类型本身是指针时才 bitcast(指针→指针);
@@ -925,9 +925,9 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
# _scan_type_for_cross_module_refs 只扫 Ptr(Struct) 模式,
# 因此传 Ptr(Ty) 让结构体名本身被 opaque 声明。
# opaque 声明足以支撑指针 bitcast(不访问字段),行为不变。
llvmlite.module_ensure_opaque_for_type(mod, pool, llvmlite.Ptr(pool, annot_struct.Ty))
annot_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, annot_struct.Ty)
return llvmlite.build_bitcast(builder, loaded_val, annot_ptr_ty)
mlirlite.module_ensure_opaque_for_type(mod, pool, mlirlite.Ptr(pool, annot_struct.Ty))
annot_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, annot_struct.Ty)
return mlirlite.build_bitcast(builder, loaded_val, annot_ptr_ty)
return loaded_val
# 字段未找到:可能是 Phase A 依赖未就绪(定义侧模块未编译,vpi
# stub 空类 FieldCount=0,如 LARGE_INTEGER)→ 走下方真实报错
@@ -1112,7 +1112,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
"""解析模块限定全局 Mod.g 的元素类型类名;非该形态返回 None"""
if pool is None or trans is None or mod_name is None or global_name is None:
return None
mod: llvmlite.LLVMModule* = trans.Module
mod: mlirlite.LLVMModule* = trans.Module
if mod is None or trans._imported_modules is None:
return None
# 模块路径:import 别名还原(对齐 _resolve_module_attribute_global 的同款截断)
@@ -1132,14 +1132,14 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, mod_path) == 0:
return None
# 全局定位:SHA1 前缀名(对齐定义端 mangling)→ 裸名回退(CExport 全局)
gv: llvmlite.GlobalVariable* = self.find_global_in_module(mod, self.Gen.FuncGenBase._mangle_name_with_sha1(self._lookup_module_sha1(mod_path), global_name))
gv: mlirlite.GlobalVariable* = self.find_global_in_module(mod, self.Gen.FuncGenBase._mangle_name_with_sha1(self._lookup_module_sha1(mod_path), global_name))
if gv is None:
gv = self.find_global_in_module(mod, global_name)
if gv is None or gv.Ty is None: return None
if self.is_ptr_type(gv.Ty) == 0: return None
# 全局变量类型是「元素类型的指针」(@"<sha1>._g_gen" : %Generator*)⇒ 类名
# 取其元素类型;元素类型仍可能是指针("多一层"形态 %Generator**)⇒ 逐层内推。
elem_ty: llvmlite.LLVMType* = gv.Ty.Pointee
elem_ty: mlirlite.LLVMType* = gv.Ty.Pointee
level_mg: int = 0
while elem_ty is not None and level_mg < 3:
cls_mg: str = self.Gen.StructGen.get_class_name_by_type(pool, elem_ty)
@@ -1272,11 +1272,11 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
return self.attr_field_pointee_is_volatile(pool, trans, base_node)
return 0
def get_attribute_ptr(self, builder: llvmlite.IRBuilder*,
def get_attribute_ptr(self, builder: mlirlite.IRBuilder*,
pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
node: ast.AST*,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""获取属性访问的字段指针(用于赋值 lhs)"""
if node is None or builder is None:
return None
@@ -1287,27 +1287,27 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
# 对于 Name 类型的 obj,直接查找 alloca(不 load 结构体);
# nonlocal 变量(提升函数内)从 env 读共享堆值,避免 lookup_var
# 跨函数引用外层 alloca(SSA 编号跨函数错乱崩溃)
obj_ptr: llvmlite.Value* = None
obj_ptr: mlirlite.Value* = None
if at.value.kind() == ast.ASTKind.Name and trans is not None:
nm: ast.Name* = ast.Name*(at.value)
if nm.id is not None:
if GenApi.is_nonlocal_name(trans, nm.id) != 0:
raw_nl_a: llvmlite.Value* = self.Gen.StmtGenDecl._load_raw_var_ptr(trans, nm.id)
raw_nl_a: mlirlite.Value* = self.Gen.StmtGenDecl._load_raw_var_ptr(trans, nm.id)
if raw_nl_a is not None:
nl_ty_a: llvmlite.LLVMType* = GenApi.get_nonlocal_type(trans, nm.id)
nl_ty_a: mlirlite.LLVMType* = GenApi.get_nonlocal_type(trans, nm.id)
if nl_ty_a is not None:
# 对象即指针:Struct/Array 类型直接用堆地址(bitcast 后
# 作为对象指针,不 load);指针类型(如 Ptr(Point))堆里
# 存对象指针,需 load 出对象指针
match nl_ty_a:
case llvmlite.LLVMType.Struct(_, _, _):
obj_ptr = llvmlite.build_bitcast(builder, raw_nl_a, llvmlite.Ptr(pool, nl_ty_a))
case llvmlite.LLVMType.Array(_, _):
obj_ptr = llvmlite.build_bitcast(builder, raw_nl_a, llvmlite.Ptr(pool, nl_ty_a))
case mlirlite.LLVMType.Struct(_, _, _):
obj_ptr = mlirlite.build_bitcast(builder, raw_nl_a, mlirlite.Ptr(pool, nl_ty_a))
case mlirlite.LLVMType.Array(_, _):
obj_ptr = mlirlite.build_bitcast(builder, raw_nl_a, mlirlite.Ptr(pool, nl_ty_a))
case _:
nl_val_ptr_a: llvmlite.Value* = llvmlite.build_bitcast(builder, raw_nl_a, llvmlite.Ptr(pool, nl_ty_a))
nl_val_ptr_a: mlirlite.Value* = mlirlite.build_bitcast(builder, raw_nl_a, mlirlite.Ptr(pool, nl_ty_a))
if nl_val_ptr_a is not None:
obj_ptr = llvmlite.build_load(builder, nl_ty_a, nl_val_ptr_a)
obj_ptr = mlirlite.build_load(builder, nl_ty_a, nl_val_ptr_a)
else:
obj_ptr = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
@@ -1331,8 +1331,8 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
VLogger.error(err_buf_wma, "CD")
return None
# 使用 i8* 作为类型提示 (模块级变量通常存储指针)
i8_ptr_w: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
wma_ref: llvmlite.Value* = self._resolve_module_attribute_global(pool, mod, trans, at, i8_ptr_w)
i8_ptr_w: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
wma_ref: mlirlite.Value* = self._resolve_module_attribute_global(pool, mod, trans, at, i8_ptr_w)
if wma_ref is not None:
return wma_ref
@@ -1340,7 +1340,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
if obj_ptr is None:
# c.Deref(ptr).attr: 属性写入 base 取指针本身而非 load 后的结构体值
# (如 c.Deref(p).a = val 语义是 (*p).a = val,直接对 p 做 GEP)
cd_base_wr: llvmlite.Value* = self._get_cderef_attr_base(builder, pool, mod, at.value, trans)
cd_base_wr: mlirlite.Value* = self._get_cderef_attr_base(builder, pool, mod, at.value, trans)
if cd_base_wr is not None:
obj_ptr = cd_base_wr
elif at.value.kind() == ast.ASTKind.Subscript:
@@ -1368,7 +1368,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
obj_ptr = self._deref_if_ptr_ptr(builder, obj_ptr)
match obj_ptr.Ty:
case llvmlite.LLVMType.Ptr(struct_ty):
case mlirlite.LLVMType.Ptr(struct_ty):
# 确保跨模块结构体的完整定义在当前模块中可用(供 getelementptr 访问字段)
# 与 translate_attribute 一致,避免 opaque 类型导致 GEP 报错
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, struct_ty)
@@ -1418,8 +1418,8 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
if field_info is not None:
annot_se: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(base_class)
if annot_se is not None and annot_se.Ty is not None:
annot_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, annot_se.Ty)
casted_ptr: llvmlite.Value* = llvmlite.build_bitcast(builder, obj_ptr, annot_ptr_ty)
annot_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, annot_se.Ty)
casted_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, obj_ptr, annot_ptr_ty)
if casted_ptr is not None:
obj_ptr = casted_ptr
struct_ty = annot_se.Ty
@@ -1429,10 +1429,10 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
if field_info is not None:
# 联合体:bitcast obj_ptr 到 field_ty*(字段指针用于 store)
if self.Gen.StructGen.is_union_by_type(struct_ty) == 1:
field_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, field_info.Ty)
return llvmlite.build_bitcast(builder, obj_ptr, field_ptr_ty)
field_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, field_info.Ty)
return mlirlite.build_bitcast(builder, obj_ptr, field_ptr_ty)
# 普通结构体:GEP 获取字段指针
return llvmlite.build_gep_struct(builder, struct_ty, field_info.Ty, obj_ptr, field_info.Index)
return mlirlite.build_gep_struct(builder, struct_ty, field_info.Ty, obj_ptr, field_info.Index)
# 字段未找到:可能是 Phase A 依赖未就绪(定义侧模块未编译,vpi
# stub 空类 FieldCount=0,如 SECURITY_ATTRIBUTES)→ 走下方真实报错
# (lookup_field_by_class 已对空 stub 返回 None 而非 fatal)。
+104 -104
View File
@@ -2,7 +2,7 @@ import lib.core.Gen.Generator as Generator
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdlib
@@ -117,17 +117,17 @@ novirtual class ExprGenBase:
# 同样委托到它)。两份副本一旦分叉,会出现「同一类型在两处算出不同位宽」的
# 隐蔽不一致。私有调用点(self.get_llvm_type_bits)保持原样不受影响。
# ============================================================
def get_llvm_type_bits(self, ty: llvmlite.LLVMType*) -> int:
def get_llvm_type_bits(self, ty: mlirlite.LLVMType*) -> int:
"""获取 LLVM 整数类型的位宽,非整数类型返回 0(委托 SpecTypeBits)"""
return TSpec.SpecTypeBits(ty)
# ============================================================
# 获取 LLVM 浮点类型的位宽
# ============================================================
def get_llvm_float_bits(self, ty: llvmlite.LLVMType*) -> int:
def get_llvm_float_bits(self, ty: mlirlite.LLVMType*) -> int:
"""获取 LLVM 浮点类型的位宽,非浮点类型返回 0"""
if ty is None: return 0
match ty:
case llvmlite.LLVMType.Float(bits):
case mlirlite.LLVMType.Float(bits):
return bits
case _:
return 0
@@ -136,11 +136,11 @@ novirtual class ExprGenBase:
#
# 返回 1=是, 0=否。作为类型检查工具函数被广泛使用(50+ 处调用)。
# ============================================================
def is_ptr_type(self, ty: llvmlite.LLVMType*) -> int:
def is_ptr_type(self, ty: mlirlite.LLVMType*) -> int:
"""检查 ty 是否是 Ptr 类型,返回 1=是, 0=否"""
if ty is None: return 0
match ty:
case llvmlite.LLVMType.Ptr(pointee):
case mlirlite.LLVMType.Ptr(pointee):
return 1
case _:
return 0
@@ -159,7 +159,7 @@ novirtual class ExprGenBase:
# - 数值(0) vs 指针(1+) → 禁止(fast-fail)
# - 不同级指针(1 vs 2) → 禁止(fast-fail)
# ============================================================
def get_ptr_level(self, ty: llvmlite.LLVMType*) -> int:
def get_ptr_level(self, ty: mlirlite.LLVMType*) -> int:
"""计算指针层级,0=非指针, 1=一级指针, 2=二级指针...
[S3 切读·指针层级块] 实现已收拢到 `TSpec.SpecTypePtrLevel`
@@ -186,11 +186,11 @@ novirtual class ExprGenBase:
#
# 返回 1=是, 0=否。类型检查工具函数。
# ============================================================
def is_array_type(self, ty: llvmlite.LLVMType*) -> int:
def is_array_type(self, ty: mlirlite.LLVMType*) -> int:
"""检查 ty 是否是 Array 类型,返回 1=是, 0=否"""
if ty is None: return 0
match ty:
case llvmlite.LLVMType.Array(_, _):
case mlirlite.LLVMType.Array(_, _):
return 1
case _:
return 0
@@ -205,7 +205,7 @@ novirtual class ExprGenBase:
# 转发到 __getitem__/__setitem__ 而非生成 GEP。
# ============================================================
def _get_custom_struct_cls_nm(self, pool: memhub.MemBuddy*,
ty: llvmlite.LLVMType*) -> str:
ty: mlirlite.LLVMType*) -> str:
"""检查 ty 或 ty 的 pointee 是否是已注册的自定义结构体,返回类名或 None"""
if ty is None:
return None
@@ -215,7 +215,7 @@ novirtual class ExprGenBase:
return cls_nm_direct
# 如果 ty 是 Ptr,检查 pointee
if self.is_ptr_type(ty) != 0:
pointee_cs: llvmlite.LLVMType* = ty.Pointee
pointee_cs: mlirlite.LLVMType* = ty.Pointee
if pointee_cs is not None:
return self.Gen.StructGen.get_class_name_by_type(pool, pointee_cs)
return None
@@ -236,16 +236,16 @@ novirtual class ExprGenBase:
if sub is None or sub.value is None or sub.value.kind() != ast.ASTKind.Name: return 0
nm: ast.Name* = ast.Name*(sub.value)
if nm.id is None: return 0
alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
if alloca is None or alloca.Ty is None: return 0
if self.is_ptr_type(alloca.Ty) == 0: return 0
pointee: llvmlite.LLVMType* = alloca.Ty.Pointee
pointee: mlirlite.LLVMType* = alloca.Ty.Pointee
if pointee is None: return 0
match pointee:
case llvmlite.LLVMType.Ptr(inner_ty):
case mlirlite.LLVMType.Ptr(inner_ty):
lsn_ls: str = None
match inner_ty:
case llvmlite.LLVMType.Struct(_, _, lsn3):
case mlirlite.LLVMType.Struct(_, _, lsn3):
lsn_ls = lsn3
case _:
pass
@@ -266,13 +266,13 @@ novirtual class ExprGenBase:
if sub is None or sub.value is None or sub.value.kind() != ast.ASTKind.Name: return None
nm: ast.Name* = ast.Name*(sub.value)
if nm.id is None: return None
alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
if alloca is None or alloca.Ty is None: return None
if self.is_ptr_type(alloca.Ty) == 0: return None
pointee: llvmlite.LLVMType* = alloca.Ty.Pointee
pointee: mlirlite.LLVMType* = alloca.Ty.Pointee
if pointee is None: return None
if self.is_ptr_type(pointee) != 0:
inner: llvmlite.LLVMType* = pointee.Pointee
inner: mlirlite.LLVMType* = pointee.Pointee
if inner is not None:
return self.Gen.StructGen.get_class_name_by_type(pool, inner)
return self.Gen.StructGen.get_class_name_by_type(pool, pointee)
@@ -286,7 +286,7 @@ novirtual class ExprGenBase:
# (GEP 元素地址,避免结构体值 base=非指针 报错)
# ============================================================
def _sub_base_uses_getitem(self, pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
trans: HT.Translator*,
sub_node: ast.AST*) -> int:
"""下标基座应走 __getitem__ 语义时返回 1,否则 0(应走 GEP 地址语义)"""
@@ -305,16 +305,16 @@ novirtual class ExprGenBase:
# - 值类型变量 (cnt: Counter): alloca 类型是 Ptr(Struct) → 不解引用
# - 指针类型变量 (r: Vec2|t.CPtr): alloca 类型是 Ptr(Ptr(Struct)) → load 解引用
# ============================================================
def _deref_if_ptr_ptr(self, builder: llvmlite.IRBuilder*,
obj_ptr: llvmlite.Value*) -> llvmlite.Value*:
def _deref_if_ptr_ptr(self, builder: mlirlite.IRBuilder*,
obj_ptr: mlirlite.Value*) -> mlirlite.Value*:
"""如果 obj_ptr 是 Ptr(Ptr(...)),load 解引用获取内层指针"""
if obj_ptr is None or obj_ptr.Ty is None: return obj_ptr
if self.is_ptr_type(obj_ptr.Ty) == 0: return obj_ptr
pointee: llvmlite.LLVMType* = obj_ptr.Ty.Pointee
pointee: mlirlite.LLVMType* = obj_ptr.Ty.Pointee
if pointee is None: return obj_ptr
if self.is_ptr_type(pointee) == 0: return obj_ptr
# obj_ptr 是 Ptr(Ptr(...)),load 解引用
loaded: llvmlite.Value* = llvmlite.build_load(builder, pointee, obj_ptr)
loaded: mlirlite.Value* = mlirlite.build_load(builder, pointee, obj_ptr)
if loaded is None: return obj_ptr
return loaded
# ============================================================
@@ -369,7 +369,7 @@ novirtual class ExprGenBase:
# (实测上述用例 node 是 Assign,kind=3,col_offset=-1),拿不到 Constant
# 节点,只能靠已经生成好的值来判定。
# ============================================================
def IsNoneValue(self, val: llvmlite.Value*,
def IsNoneValue(self, val: mlirlite.Value*,
node: ast.AST* = None) -> int:
"""判据:val/node 是否表示 None(空值常量),1=是 / 0=否"""
# 判据①:AST 是 None 字面量
@@ -393,19 +393,19 @@ novirtual class ExprGenBase:
# 指针目标不在此处处理:coerce_to_type 的「指针→指针 bitcast」路径已能
# 接受 None(i8* null → T*),保留其原有 IR 形态。
# ============================================================
def _NoneValueAsTarget(self, builder: llvmlite.IRBuilder*,
target_ty: llvmlite.LLVMType*) -> llvmlite.Value*:
def _NoneValueAsTarget(self, builder: mlirlite.IRBuilder*,
target_ty: mlirlite.LLVMType*) -> mlirlite.Value*:
"""把 None 转换为目标类型的空值/零值"""
if target_ty is None:
return None
pool: memhub.MemBuddy* = builder.Pool
t_bits: int = self.get_llvm_type_bits(target_ty)
if t_bits != 0:
return llvmlite.ConstInt(pool, target_ty, 0, "0")
return mlirlite.ConstInt(pool, target_ty, 0, "0")
t_fbits: int = self.get_llvm_float_bits(target_ty)
if t_fbits != 0:
return llvmlite.ConstFloat(pool, target_ty, 0.0)
return llvmlite.ConstZero(pool, target_ty)
return mlirlite.ConstFloat(pool, target_ty, 0.0)
return mlirlite.ConstZero(pool, target_ty)
# ============================================================
# _is_universal_ptr_ty - 判据:类型是否为「通用指针」(t.CPtr / i8* = void*)
#
@@ -416,13 +416,13 @@ novirtual class ExprGenBase:
# 多级指针(如 i8**)不是通用指针(需逐级比较 pointee)。
# 返回 1=是 / 0=否。
# ============================================================
def _is_universal_ptr_ty(self, ty: llvmlite.LLVMType*) -> int:
def _is_universal_ptr_ty(self, ty: mlirlite.LLVMType*) -> int:
"""ty 是否为通用指针(i8*/t.CPtr),1=是 / 0=否"""
if ty is None or self.is_ptr_type(ty) == 0:
return 0
if self.get_ptr_level(ty) != 1:
return 0
pointee: llvmlite.LLVMType* = ty.Pointee
pointee: mlirlite.LLVMType* = ty.Pointee
if pointee is None:
return 1
if self.get_llvm_type_bits(pointee) == 8:
@@ -455,7 +455,7 @@ novirtual class ExprGenBase:
if nm is None or nm.id is None:
return 0
return self._annot_name_is_bare_str(nm.id)
def _str_rejects_ptr_kind(self, val: llvmlite.Value*) -> int:
def _str_rejects_ptr_kind(self, val: mlirlite.Value*) -> int:
"""val 是否为「str/bytes 不应接受」的聚合指针(1/2/3=是,0=否)
1 = 结构体/类/联合指针;2 = 非字符数组指针;3 = 函数指针。
@@ -468,24 +468,24 @@ novirtual class ExprGenBase:
return 0
if self.is_ptr_type(val.Ty) == 0:
return 0
pointee: llvmlite.LLVMType* = val.Ty.Pointee
pointee: mlirlite.LLVMType* = val.Ty.Pointee
if pointee is None:
return 0
pk: int = pointee.kind()
if pk == llvmlite.LLVMType.Struct:
if pk == mlirlite.LLVMType.Struct:
return 1
if pk == llvmlite.LLVMType.Func:
if pk == mlirlite.LLVMType.Func:
return 3
if pk == llvmlite.LLVMType.Array:
if pk == mlirlite.LLVMType.Array:
match pointee:
case llvmlite.LLVMType.Array(elem, _):
case mlirlite.LLVMType.Array(elem, _):
if self.get_llvm_type_bits(elem) == 8:
return 0
case _:
pass
return 2
return 0
def fail_if_str_annot_agg_ptr(self, val: llvmlite.Value*,
def fail_if_str_annot_agg_ptr(self, val: mlirlite.Value*,
annot_is_str: int,
node: ast.AST* = None) -> int:
"""注解侧是裸 str/bytes 而值是指向聚合类型的指针 → fail-fast(返回 1)
@@ -503,7 +503,7 @@ novirtual class ExprGenBase:
"同为 i8*,但语义不同(str/bytes 不是通用指针通配)。若确需传递指针,"
"请改用 t.CPtr/rawptr 形参,或显式转换(如 t.CPtr(p))", "CastError")
return 1
def fail_if_str_annot_ast_agg_ptr(self, val: llvmlite.Value*,
def fail_if_str_annot_ast_agg_ptr(self, val: mlirlite.Value*,
annot: ast.AST*,
node: ast.AST* = None) -> int:
"""注解 AST 形态的入口:注解为裸 str/bytes 且值是指向聚合类型的指针 → fail-fast
@@ -519,7 +519,7 @@ novirtual class ExprGenBase:
# 非基本类型 = 结构体/类/联合/数组/函数等(LLVM 层 Struct/Array/Func)。
# 规则 2/3:非基本类型一律不允许参与指针间隐式转换(除完全相同类型,见规则 4)。
# ============================================================
def _is_basic_scalar_ty(self, ty: llvmlite.LLVMType*) -> int:
def _is_basic_scalar_ty(self, ty: mlirlite.LLVMType*) -> int:
"""ty 是否为基本类型(整数/浮点),1=是 / 0=否"""
if ty is None:
return 0
@@ -535,8 +535,8 @@ novirtual class ExprGenBase:
# ≥ 整数位宽;浮点→整数不允许)。
# 返回 PC_OK(无损/允许)或 PC_LOSSY(有损/禁止)。
# ============================================================
def _scalar_convert_reason(self, src_pt: llvmlite.LLVMType*,
dst_pt: llvmlite.LLVMType*) -> int:
def _scalar_convert_reason(self, src_pt: mlirlite.LLVMType*,
dst_pt: mlirlite.LLVMType*) -> int:
"""基本标量 src_pt → dst_pt 的隐式转换判定码(PC_OK / PC_LOSSY)"""
s_int: int = self.get_llvm_type_bits(src_pt)
d_int: int = self.get_llvm_type_bits(dst_pt)
@@ -565,7 +565,7 @@ novirtual class ExprGenBase:
# 返回 None。不新造表。
# ============================================================
def _class_name_of_ptr_pointee(self, pool: memhub.MemBuddy*,
pt: llvmlite.LLVMType*) -> str:
pt: mlirlite.LLVMType*) -> str:
"""指针被指类型映射到已注册类名;失败返回 None"""
if pt is None:
return None
@@ -580,8 +580,8 @@ novirtual class ExprGenBase:
# 类型(Foo* ↔ Bar*)都不命中 ⇒ 返回 0,仍按规则 2/3 禁止。
# ============================================================
def _is_inheritance_upcast(self, pool: memhub.MemBuddy*,
src_pt: llvmlite.LLVMType*,
dst_pt: llvmlite.LLVMType*) -> int:
src_pt: mlirlite.LLVMType*,
dst_pt: mlirlite.LLVMType*) -> int:
"""派生类指针 → 基类指针(含多级):1=允许上转 / 0=否"""
src_name: str = self._class_name_of_ptr_pointee(pool, src_pt)
if src_name is None:
@@ -614,16 +614,16 @@ novirtual class ExprGenBase:
# 返回 1=允许退让 / 0=否。
# ============================================================
def _is_array_decay(self, pool: memhub.MemBuddy*,
src_pt: llvmlite.LLVMType*,
dst_pt: llvmlite.LLVMType*) -> int:
src_pt: mlirlite.LLVMType*,
dst_pt: mlirlite.LLVMType*) -> int:
"""源被指类型是定长数组且目标被指类型是其元素类型:1=是 / 0=否"""
if src_pt is None or dst_pt is None:
return 0
if self.is_array_type(src_pt) == 0:
return 0
elem: llvmlite.LLVMType* = None
elem: mlirlite.LLVMType* = None
match src_pt:
case llvmlite.LLVMType.Array(et, _):
case mlirlite.LLVMType.Array(et, _):
elem = et
case _:
return 0
@@ -644,8 +644,8 @@ novirtual class ExprGenBase:
# 被指类型仍是指针(T** → U**):递归按指针规则判。
# ============================================================
def _pointee_convert_reason(self, pool: memhub.MemBuddy*,
src_pt: llvmlite.LLVMType*,
dst_pt: llvmlite.LLVMType*) -> int:
src_pt: mlirlite.LLVMType*,
dst_pt: mlirlite.LLVMType*) -> int:
"""被指类型 src_pt → dst_pt 的判定码(PC_OK/PC_NONBASIC/PC_LOSSY/PC_DEPTH)"""
if src_pt is None or dst_pt is None:
return PC_OK
@@ -680,8 +680,8 @@ novirtual class ExprGenBase:
# 返回 PC_OK(允许)/ PC_DEPTH / PC_NONBASIC / PC_LOSSY。
# ============================================================
def _ptr_cast_reason(self, pool: memhub.MemBuddy*,
src_ty: llvmlite.LLVMType*,
dst_ty: llvmlite.LLVMType*) -> int:
src_ty: mlirlite.LLVMType*,
dst_ty: mlirlite.LLVMType*) -> int:
"""指针 → 指针对隐式转换的判定码(PC_OK 表示允许)"""
if src_ty is None or dst_ty is None:
return PC_OK
@@ -704,14 +704,14 @@ novirtual class ExprGenBase:
# _type_text - LLVM 类型的可读文本(TypePrint),供报文使用(失败返回 "?")
# ============================================================
def _type_text(self, pool: memhub.MemBuddy*,
ty: llvmlite.LLVMType*) -> str:
ty: mlirlite.LLVMType*) -> str:
"""LLVM 类型文本(TypePrint);失败返回 "?" """
if ty is None:
return "?"
buf: str = pool.alloc(256)
if buf is None:
return "?"
llvmlite.TypePrint(buf, 256, ty, pool)
mlirlite.TypePrint(buf, 256, ty, pool)
if buf[0] == 0:
return "?"
return buf
@@ -722,8 +722,8 @@ novirtual class ExprGenBase:
# 源/目标 LLVM 类型文本。返回值会逃逸 ⇒ 经 escape_fstring_copy 拷到 stdlib 堆。
# ============================================================
def _ptr_cast_reason_text(self, code: int, pool: memhub.MemBuddy*,
src_ty: llvmlite.LLVMType*,
dst_ty: llvmlite.LLVMType*) -> str:
src_ty: mlirlite.LLVMType*,
dst_ty: mlirlite.LLVMType*) -> str:
"""指针间隐式转换禁止原因的可读文本(含源/目标类型)"""
why: str = "原因未知"
if code == PC_DEPTH:
@@ -746,7 +746,7 @@ novirtual class ExprGenBase:
# - 泛型类模板(Box(42))特化名需类型实参推断,静态取不到类型 → 保守返回 None。
# 非构造调用(普通函数/方法/未知符号)一律返回 None(→ 不进豁免,照常报错)。
# ============================================================
def _ctor_call_agg_ty(self, node: ast.AST*) -> llvmlite.LLVMType*:
def _ctor_call_agg_ty(self, node: ast.AST*) -> mlirlite.LLVMType*:
"""node(或其值子节点)是构造调用 → 返回其构造的聚合类型;否则 None"""
n: ast.AST* = self._value_node_of(node)
if n is None or n.kind() != ast.ASTKind.Call:
@@ -770,12 +770,12 @@ novirtual class ExprGenBase:
# 结构体名(find_struct 必 miss);但构造结果物化的就是**基础枚举**的整对象
# (boxed 指针指向该枚举结构体)⇒ 返回该 REnum 的聚合类型,使「构造物化」豁免
# 覆盖 `*槽 = <boxed 变体>`。否则该写法会被「指针 → 非基本类型值」禁令拦下
# (现场 ClassGenDef.vp:128 `*existing.Ty = llvmlite.LLVMType.Struct(...)`)。
# (现场 ClassGenDef.vp:128 `*existing.Ty = mlirlite.LLVMType.Struct(...)`)。
if cl.func.kind() == ast.ASTKind.Attribute:
# 取「变体名左边那一段」作为枚举类名:被调方形如 `<限定链>.<变体>`,
# EnumType.Variant → 限定段是裸名 EnumType
# llvmlite.LLVMType.Struct → 限定段是属性 LLVMType(**不是**链根
# llvmlite,早期实现走到链根导致漏判)
# mlirlite.LLVMType.Struct → 限定段是属性 LLVMType(**不是**链根
# mlirlite,早期实现走到链根导致漏判)
qual: ast.AST* = (ast.Attribute*(cl.func)).value
base_nm: str = None
if qual is not None:
@@ -792,7 +792,7 @@ novirtual class ExprGenBase:
# _same_agg_ty - 两个聚合类型是否为「同一非基本类型」(构造物化豁免的类型匹配)
# ============================================================
def _same_agg_ty(self, pool: memhub.MemBuddy*,
a: llvmlite.LLVMType*, b: llvmlite.LLVMType*) -> int:
a: mlirlite.LLVMType*, b: mlirlite.LLVMType*) -> int:
"""a、b 是否为同一聚合类型,1=是 / 0=否"""
if a is None or b is None:
return 0
@@ -800,11 +800,11 @@ novirtual class ExprGenBase:
# ============================================================
# 类型强制转换:整数 sext/trunc,浮点 fpext/fptrunc,int↔float si2fp/fp2si
# ============================================================
def coerce_to_type(self, builder: llvmlite.IRBuilder*,
val: llvmlite.Value*,
target_ty: llvmlite.LLVMType*,
def coerce_to_type(self, builder: mlirlite.IRBuilder*,
val: mlirlite.Value*,
target_ty: mlirlite.LLVMType*,
node: ast.AST* = None,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""将 val 强制转换为 target_ty
整数: sext(扩展)/ trunc(截断)
@@ -825,7 +825,7 @@ novirtual class ExprGenBase:
# 「指针隐式转整数已禁止」拦成 CastError。
if self.IsNoneValue(val, node) != 0:
if self.is_ptr_type(target_ty) != 0:
return llvmlite.build_bitcast(builder, val, target_ty)
return mlirlite.build_bitcast(builder, val, target_ty)
return self._NoneValueAsTarget(builder, target_ty)
# void 类型的值**不允许被当作值使用**(用户 2026-10-01:void 只能用于 `void*`
# 与 `typedef 不透明结构体 = void`)。任何把 void 值 coerce 到非 void 目标
@@ -840,9 +840,9 @@ novirtual class ExprGenBase:
# 函数 → 指针: bitcast(如 CreateThread(..., _thread_alloc_free, ...) 传函数指针)
# 函数 Value 的 Ty 是 Func,既不是整数也不是指针,需在整数/浮点转换之前处理
match val.Ty:
case llvmlite.LLVMType.Func(_, _, _):
case mlirlite.LLVMType.Func(_, _, _):
if self.is_ptr_type(target_ty) != 0:
return llvmlite.build_bitcast(builder, val, target_ty)
return mlirlite.build_bitcast(builder, val, target_ty)
return val
case _:
pass
@@ -863,7 +863,7 @@ novirtual class ExprGenBase:
# 属标准 C 空指针用法,须放行而非报 CastError。先拓宽到 i64
# (inttoptr 要求同宽,对齐 MatchGenMixin 模式),再 inttoptr 成空指针。
if val.IsConst == 1 and val.IntVal == 0:
return llvmlite.build_inttoptr(builder, llvmlite.const_int64(builder.Pool, 0), target_ty)
return mlirlite.build_inttoptr(builder, mlirlite.const_int64(builder.Pool, 0), target_ty)
m_i2p: str = "整数隐式转指针已禁止:必须显式强转为指针(如 t.CPtr(x))才能把整数赋给指针类型"
self.Gen.TypeGenErr.fatal_error(self._value_node_of(node),
m_i2p, "CastError")
@@ -889,8 +889,8 @@ novirtual class ExprGenBase:
# 值 3 得 true 而同值域下 `!= 0` 亦为 true,故只在偶数非零时暴露。
# 归一化不丢位 ⇒ 下方「窄化截断溢出」常量诊断对 i1 目标不适用(先返回)。
if target_bits == 1:
zero_i1: llvmlite.Value* = llvmlite.const_int(builder.Pool, val_bits, 0)
return llvmlite.build_icmp(builder, llvmlite.ICMP_NE, val, zero_i1)
zero_i1: mlirlite.Value* = mlirlite.const_int(builder.Pool, val_bits, 0)
return mlirlite.build_icmp(builder, mlirlite.ICMP_NE, val, zero_i1)
if val_bits < target_bits:
# 统一 zext/sext(问题2修正):i1/i8 默认 zext;AST 节点解析为
# 无符号类型(t.CUIntXXT 强转/无符号类型名)走 zext;否则 sext。
@@ -901,8 +901,8 @@ novirtual class ExprGenBase:
# trans.SymTab 查变量注解(uint16/sec:uint32 等)才能判定无符号,
# 否则返回未知 → 退回 sext(无符号扩展缺陷根因)。
if self._zext_or_sext_val(builder.Pool, val, node, trans) != 0:
return llvmlite.build_zext(builder, val, target_ty)
return llvmlite.build_sext(builder, val, target_ty)
return mlirlite.build_zext(builder, val, target_ty)
return mlirlite.build_sext(builder, val, target_ty)
# 窄化截断诊断(_Type.md 问题 8):宽→窄 trunc 静默丢位。
# 编译期已知常量且正溢出目标位宽无符号范围 → fail-fast(确定性数据
# 损坏,如 buf[idx] = 0x1FF 写入 i8 槽位被静默截断)。负常量按模
@@ -913,7 +913,7 @@ novirtual class ExprGenBase:
if uint64(val.IntVal) > target_max_u:
max_print: int64 = int64(target_max_u)
self.Gen.TypeGenErr.fatal_error(node, f"窄化截断溢出:常量 {val.IntVal} 超出目标类型 {target_bits} 位范围 [0, {max_print}],赋值将被静默截断", "OverflowError")
return llvmlite.build_trunc(builder, val, target_ty)
return mlirlite.build_trunc(builder, val, target_ty)
# 浮点转换
val_fbits: int = self.get_llvm_float_bits(val.Ty)
target_fbits: int = self.get_llvm_float_bits(target_ty)
@@ -927,21 +927,21 @@ novirtual class ExprGenBase:
if val_fbits == target_fbits:
return val
if val_fbits < target_fbits:
return llvmlite.build_fpext(builder, val, target_ty)
return llvmlite.build_fptrunc(builder, val, target_ty)
return mlirlite.build_fpext(builder, val, target_ty)
return mlirlite.build_fptrunc(builder, val, target_ty)
# int → float
if val_bits != 0 and target_fbits != 0:
return llvmlite.build_si2fp(builder, val, target_ty)
return mlirlite.build_si2fp(builder, val, target_ty)
# float → int
if val_fbits != 0 and target_bits != 0:
return llvmlite.build_fp2si(builder, val, target_ty)
return mlirlite.build_fp2si(builder, val, target_ty)
# 聚合值 → 指针:落栈 materialize 临时对象后传其地址。FuncGenDef 已确认「裸类/数组形参一律 lowering 为 Ptr(struct/array)」——TPV 内部函数/方法不存在"按值传结构体"的形参(唯一例外:C ABI 外部声明的裸结构体形参按值,见 VpiReader._AggregateParamTy「三处必须同步」)。故调用点的 rvalue 聚合(函数调用返回值、下标元素 load 等)必须落栈取址,否则实参类型与指针形参失配。alloca 走入口块(支配性安全),生命周期覆盖整个调用,pointee 与聚合类型一致时直接用 alloca 地址
if self.is_ptr_type(val.Ty) == 0 and self.is_ptr_type(target_ty) != 0:
vk_agg: int = val.Ty.kind()
if vk_agg == llvmlite.LLVMType.Struct or vk_agg == llvmlite.LLVMType.Array:
if vk_agg == mlirlite.LLVMType.Struct or vk_agg == mlirlite.LLVMType.Array:
# 规则 3:非基本类型的「值 → 指针」隐式转换(Foo → Foo*)一律禁止,
# 唯一例外=「构造物化」:右值来自该类型的构造调用时放行(见 _ctor_call_agg_ty)。
ctor_v2p: llvmlite.LLVMType* = self._ctor_call_agg_ty(node)
ctor_v2p: mlirlite.LLVMType* = self._ctor_call_agg_ty(node)
if self._same_agg_ty(builder.Pool, ctor_v2p, val.Ty) == 0:
m_v2p: str = "非基本类型的值/指针隐式转换已禁止(构造物化除外):不能把非基本类型值隐式转为指针(Foo → Foo*),如需取址请显式 c.addr(...) / &v,或显式强转"
v2p_txt: str = GenApi.escape_fstring_copy(
@@ -949,16 +949,16 @@ novirtual class ExprGenBase:
self.Gen.TypeGenErr.fatal_error(self._value_node_of(node),
f"{m_v2p}{v2p_txt}", "CastError")
return val
tmp_agg: llvmlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, val.Ty)
tmp_agg: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, val.Ty)
if tmp_agg is not None:
llvmlite.build_store(builder, val, tmp_agg)
mlirlite.build_store(builder, val, tmp_agg)
match target_ty:
case llvmlite.LLVMType.Ptr(pointee_agg):
case mlirlite.LLVMType.Ptr(pointee_agg):
if self.Gen.AssignGen._stg_ty_equal(builder.Pool, pointee_agg, val.Ty) != 0:
return tmp_agg
case _:
pass
bc_agg: llvmlite.Value* = llvmlite.build_bitcast(builder, tmp_agg, target_ty)
bc_agg: mlirlite.Value* = mlirlite.build_bitcast(builder, tmp_agg, target_ty)
if bc_agg is not None:
return bc_agg
return tmp_agg
@@ -968,10 +968,10 @@ novirtual class ExprGenBase:
# dereferenced. Scalar integer targets were already rejected above.
if self.is_ptr_type(val.Ty) != 0 and self.is_ptr_type(target_ty) == 0:
target_kind: int = target_ty.kind()
if target_kind == llvmlite.LLVMType.Struct or target_kind == llvmlite.LLVMType.Array:
if target_kind == mlirlite.LLVMType.Struct or target_kind == mlirlite.LLVMType.Array:
# 规则 3:非基本类型的「指针 → 值」隐式转换(Foo* → Foo)一律禁止,
# 唯一例外=「构造物化」:右值来自该类型的构造调用时放行(见 _ctor_call_agg_ty)。
ctor_p2v: llvmlite.LLVMType* = self._ctor_call_agg_ty(node)
ctor_p2v: mlirlite.LLVMType* = self._ctor_call_agg_ty(node)
if self._same_agg_ty(builder.Pool, ctor_p2v, target_ty) == 0:
m_p2v: str = "非基本类型的值/指针隐式转换已禁止(构造物化除外):不能把指针类型隐式转为非基本类型值(Foo* → Foo),如需解引用请显式 c.deref(p) / *p,或显式强转"
p2v_txt: str = GenApi.escape_fstring_copy(
@@ -979,7 +979,7 @@ novirtual class ExprGenBase:
self.Gen.TypeGenErr.fatal_error(self._value_node_of(node),
f"{m_p2v}{p2v_txt}", "CastError")
return val
return llvmlite.build_load(builder, target_ty, val)
return mlirlite.build_load(builder, target_ty, val)
self.Gen.TypeGenErr.fatal_error(self._value_node_of(node),
f"指针隐式转非指针值已禁止:必须显式解引用(c.Deref(p) / *p)或显式强转(uint64(p))", "CastError")
return val
@@ -996,11 +996,11 @@ novirtual class ExprGenBase:
self.Gen.TypeGenErr.fatal_error(self._value_node_of(node),
reason, "CastError")
return val
return llvmlite.build_bitcast(builder, val, target_ty)
return mlirlite.build_bitcast(builder, val, target_ty)
return val
def _zext_or_sext_val(self, pool: memhub.MemBuddy*,
val: llvmlite.Value*,
val: mlirlite.Value*,
node: ast.AST* = None,
trans: HT.Translator* = None) -> int:
"""统一整数拓宽方向:1=zext(无符号语义),0=sext
@@ -1019,43 +1019,43 @@ novirtual class ExprGenBase:
# translate_ptr_arith:指针算术 ptr±int,用 getelementptr(按 pointee 元素大小缩放索引,对齐 TPC ExprGen.emit_binary_op / HandlesAugAssign.py);数组 pointee([N x ty]*)先 decay 为元素指针(GEP 0,0),避免以整个数组为步长
def translate_ptr_arith(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
ptr_val: llvmlite.Value*,
int_val: llvmlite.Value*,
op: int) -> llvmlite.Value*:
builder: mlirlite.IRBuilder*,
ptr_val: mlirlite.Value*,
int_val: mlirlite.Value*,
op: int) -> mlirlite.Value*:
"""指针算术: ptr + int / ptr - int → GEP(按元素大小缩放索引)"""
if ptr_val is None or int_val is None or ptr_val.Ty is None: return None
# 提取 pointee 类型(非指针 → 不处理返回 None)
elem_ty: llvmlite.LLVMType* = None
elem_ty: mlirlite.LLVMType* = None
match ptr_val.Ty:
case llvmlite.LLVMType.Ptr(pointee):
case mlirlite.LLVMType.Ptr(pointee):
elem_ty = pointee
case _:
return None
if elem_ty is None: return None
# 索引统一到 i64(对齐 TPC zext 到 i64)
i64_ty: llvmlite.LLVMType* = llvmlite.Int64(pool)
idx: llvmlite.Value* = self.coerce_to_type(builder, int_val, i64_ty, None)
i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool)
idx: mlirlite.Value* = self.coerce_to_type(builder, int_val, i64_ty, None)
if idx is None: return None
# ptr - int → 负索引(LLVM GEP 索引为加法语义)
if op == ast.OpKind.Sub:
neg_idx: llvmlite.Value* = llvmlite.build_sub(builder, llvmlite.const_int64(pool, 0), idx)
neg_idx: mlirlite.Value* = mlirlite.build_sub(builder, mlirlite.const_int64(pool, 0), idx)
if neg_idx is None: return None
idx = neg_idx
# 数组 pointee → 先 decay 为元素指针(getelementptr [N x ty], [N x ty]* %p, i32 0, i32 0)
if self.is_array_type(elem_ty) != 0:
inner_ty: llvmlite.LLVMType* = None
inner_ty: mlirlite.LLVMType* = None
match elem_ty:
case llvmlite.LLVMType.Array(inner, _):
case mlirlite.LLVMType.Array(inner, _):
inner_ty = inner
case _:
return None
if inner_ty is None:
return None
decayed: llvmlite.Value* = llvmlite.build_gep_array(builder, elem_ty, inner_ty, ptr_val, llvmlite.const_int64(pool, 0))
decayed: mlirlite.Value* = mlirlite.build_gep_array(builder, elem_ty, inner_ty, ptr_val, mlirlite.const_int64(pool, 0))
if decayed is None: return None
return llvmlite.build_gep(builder, inner_ty, decayed, idx)
return llvmlite.build_gep(builder, elem_ty, ptr_val, idx)
return mlirlite.build_gep(builder, inner_ty, decayed, idx)
return mlirlite.build_gep(builder, elem_ty, ptr_val, idx)
def InitExprGen(self) -> int:
"""初始化 ExprGen 族字段(构造时由 Generator 调用)"""
if self is None: return 1
+7 -7
View File
@@ -1,7 +1,7 @@
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdio
@@ -1060,7 +1060,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
# 翻译变量引用(Name 节点)→ load
# ============================================================
def _const_int_for_cdefine(self, pool: memhub.MemBuddy*,
value: int64) -> llvmlite.Value*:
value: int64) -> mlirlite.Value*:
"""CDefine 整数常量 → LLVM 常量(对齐 TPC TypeConvert 的 64 位升级)
**使用处宽度("W_min + 使用处宽度"规则)与物化宽度的关系**(与 TPC 同口径,
@@ -1103,8 +1103,8 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
ExprGenConst.vp:108 / CallGenLeafKit.vp:1477 的写法一致。
"""
if (value >= 0 and uint64(uint32(value)) != value) or value < -2147483648:
return llvmlite.const_int64(pool, value)
return llvmlite.const_int32(pool, int(value))
return mlirlite.const_int64(pool, value)
return mlirlite.const_int32(pool, int(value))
# ============================================================
# cdefine_use_width_value - "使用处宽度"下的 CDefine 常量物化
@@ -1135,8 +1135,8 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
def cdefine_use_width_value(self, pool: memhub.MemBuddy*,
node: ast.AST*, name: str,
value: int64,
target_ty: llvmlite.LLVMType*,
use_ctx: str = None) -> llvmlite.Value*:
target_ty: mlirlite.LLVMType*,
use_ctx: str = None) -> mlirlite.Value*:
"""CDefine 整数常量在**已知使用处类型**时的物化(与 TPC 同口径)。
返回 None ⇒ "取不到使用处宽度"(调用方沿用 _const_int_for_cdefine 的
@@ -1190,4 +1190,4 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
f"(如 t.CInt{wmin}T / CUInt{wmin}T 及更宽类型),或改用更小的常量值。",
"TypeError")
return None
return llvmlite.const_int(pool, bits, self._cdefine_bits_value(value, bits))
return mlirlite.const_int(pool, bits, self._cdefine_bits_value(value, bits))
+3 -3
View File
@@ -1,7 +1,7 @@
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdlib
@@ -267,7 +267,7 @@ novirtual class ExprGenCls(ExprGenBase.ExprGenBase):
# 仅采用已注册结构体;无法精确推断返回 None(fail-fast 由调用方暴露)。
# ============================================================
def infer_expr_class(self, pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
node: ast.AST*,
trans: HT.Translator*) -> str:
"""从表达式推断结构体类名,无法推断返回 None"""
@@ -369,7 +369,7 @@ novirtual class ExprGenCls(ExprGenBase.ExprGenBase):
# SHA1(stub 中声明)即视为存在。仅在确实存在时采用推断类名,
# 避免把原生运算误标为类类型。
# ============================================================
def _cls_has_dunder(self, pool: memhub.MemBuddy*, mod: llvmlite.LLVMModule*, class_name: str, dunder: str) -> int:
def _cls_has_dunder(self, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, class_name: str, dunder: str) -> int:
"""类及其 MRO 祖先链中是否存在 dunder 方法,存在返回 1"""
if class_name is None or dunder is None or mod is None: return 0
lookup_name: str = pool.alloc(128)
+56 -56
View File
@@ -1,7 +1,7 @@
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdio
@@ -22,11 +22,11 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
# ============================================================
# 创建全局字符串常量
# ============================================================
def create_global_string(self, builder: llvmlite.IRBuilder*,
def create_global_string(self, builder: mlirlite.IRBuilder*,
pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
str_val: str,
trans: HT.Translator*) -> llvmlite.Value*:
trans: HT.Translator*) -> mlirlite.Value*:
"""创建全局字符串常量并返回 i8* bitcast"""
escaped: str = self.escape_llvm_string(pool, str_val)
if escaped is None: return None
@@ -34,8 +34,8 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
slen: sizet = string.strlen(str_val)
count: int = slen + 1
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
arr_ty: llvmlite.LLVMType* = llvmlite.Array(pool, i8_ty, count)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
arr_ty: mlirlite.LLVMType* = mlirlite.Array(pool, i8_ty, count)
# 使用模块级计数器(trans._label_counter)避免跨函数命名冲突
str_idx: int = trans._label_counter
@@ -50,38 +50,38 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
else:
viperlib.snprintf(gv_name, 48, ".str.%d", str_idx)
gv: llvmlite.GlobalVariable* = llvmlite.new_global_variable(pool, gv_name, arr_ty)
gv: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, gv_name, arr_ty)
if gv is None:
return None
llvmlite.module_add_global(mod, gv)
mlirlite.module_add_global(mod, gv)
# 去掉 private 链接,和函数一致:stub 中 declare,text 中 define
llvmlite.global_set_unnamed_addr(gv, 1)
llvmlite.global_set_constant(gv, 1)
mlirlite.global_set_unnamed_addr(gv, 1)
mlirlite.global_set_constant(gv, 1)
# LLVM 22+ 不允许 external linkage 全局变量带初始值,设为 internal
gv.Linkage = "internal"
gv.Initializer = escaped
arr_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, arr_ty)
arr_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, arr_ty)
gv_ref_name: str = pool.alloc(64)
if gv_ref_name is None:
return None
viperlib.snprintf(gv_ref_name, 64, "@%s", gv.Name)
gv_ref: llvmlite.Value* = llvmlite.SSAValue(pool, arr_ptr_ty, gv_ref_name)
gv_ref: mlirlite.Value* = mlirlite.SSAValue(pool, arr_ptr_ty, gv_ref_name)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
bc: llvmlite.Value* = llvmlite.build_bitcast(builder, gv_ref, i8_ptr_ty)
bc: mlirlite.Value* = mlirlite.build_bitcast(builder, gv_ref, i8_ptr_ty)
return bc
# ============================================================
# 翻译常量表达式
# ============================================================
def translate_constant(self, builder: llvmlite.IRBuilder*,
def translate_constant(self, builder: mlirlite.IRBuilder*,
pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
node: ast.AST*,
trans: HT.Translator* = None,
target_ty: llvmlite.LLVMType* = None) -> llvmlite.Value*:
target_ty: mlirlite.LLVMType* = None) -> mlirlite.Value*:
"""翻译常量(int/str/bool)"""
cn: ast.Constant* = ast.Constant*(node)
if cn is None:
@@ -98,47 +98,47 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
iv: int64 = cn.int_val
if target_ty is not None and self.is_ptr_type(target_ty) == 0 \
and self.get_llvm_type_bits(target_ty) > 32:
return llvmlite.const_int64(pool, iv)
return mlirlite.const_int64(pool, iv)
if iv > 2147483647 or iv < -2147483648:
return llvmlite.const_int64(pool, iv)
return llvmlite.const_int32(pool, iv)
return mlirlite.const_int64(pool, iv)
return mlirlite.const_int32(pool, iv)
elif cn.const_kind == ast.CONST_FLOAT:
# 浮点常量默认创建为 double(64 位),赋值时由 coerce_to_type 自动 fptrunc
double_ty: llvmlite.LLVMType* = llvmlite.Double(pool)
return llvmlite.ConstFloat(pool, double_ty, cn.float_val)
double_ty: mlirlite.LLVMType* = mlirlite.Double(pool)
return mlirlite.ConstFloat(pool, double_ty, cn.float_val)
elif cn.const_kind == ast.CONST_CHAR:
# 单引号单字符字面量(CONST_CHAR):默认按字符值(i32,coerce 截断为 i8);但当目标类型是指针(str/bytes/t.CPtr)时须物化为 1 字符字符串,否则 coerce inttoptr 把字符值当指针(如 '"'=0x22)→ 运行期 strlen 访问低地址崩溃。1a 阶段(declare_only=1)依赖函数 found_func=None,target_ty 未对齐即视为垃圾跳过,避免 is_ptr_type 解引用崩溃
if target_ty is not None and (uint64(target_ty) & 7) == 0 \
and self.is_ptr_type(target_ty) != 0:
cbuf: bytes = stdlib.malloc(2)
if cbuf is None:
return llvmlite.const_int32(pool, 0)
return mlirlite.const_int32(pool, 0)
cbuf[0] = char(cn.int_val)
cbuf[1] = '\0'
r_cs: llvmlite.Value* = self.create_global_string(builder, pool, mod, cbuf, trans)
r_cs: mlirlite.Value* = self.create_global_string(builder, pool, mod, cbuf, trans)
stdlib.free(cbuf)
return r_cs
cv: int64 = cn.int_val
return llvmlite.const_int32(pool, cv)
return mlirlite.const_int32(pool, cv)
elif cn.const_kind == ast.CONST_STR:
sv: str = cn.str_val
if sv is None:
return None
r: llvmlite.Value* = self.create_global_string(builder, pool, mod, sv, trans)
r: mlirlite.Value* = self.create_global_string(builder, pool, mod, sv, trans)
return r
elif cn.const_kind == ast.CONST_BOOL:
if cn.int_val != 0:
return llvmlite.const_int32(pool, 1)
return llvmlite.const_int32(pool, 0)
return mlirlite.const_int32(pool, 1)
return mlirlite.const_int32(pool, 0)
elif cn.const_kind == ast.CONST_NONE:
# None → i8* null(空指针常量),用于 `p is None` / `p is not None` 比较
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
if i8_ty is None:
return None
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
if i8_ptr_ty is None:
return None
rv_none: llvmlite.Value* = llvmlite.ConstNull(pool, i8_ptr_ty, "null")
rv_none: mlirlite.Value* = mlirlite.ConstNull(pool, i8_ptr_ty, "null")
return rv_none
return None
# ============================================================
@@ -147,7 +147,7 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
# 用于 list 字面量 [a, b, c] 的元素类型推断
# ============================================================
def _infer_elem_type_from_value(self, pool: memhub.MemBuddy*,
value: llvmlite.Value*) -> str:
value: mlirlite.Value*) -> str:
"""从 LLVM Value 的类型推断 list 元素类型名
fail-fast:值类型缺失/无法映射时返回 None(调用方携带节点报错终止),
@@ -155,7 +155,7 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
"""
if value is None or value.Ty is None:
return None
ty: llvmlite.LLVMType* = value.Ty
ty: mlirlite.LLVMType* = value.Ty
bits: int = self.get_llvm_type_bits(ty)
if bits != 0:
if bits == 32:
@@ -181,7 +181,7 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
#
# 依次尝试 "pool", "_mbuddy", "mbuddy", "mb"
# ============================================================
def _find_pool_var(self, trans: HT.Translator*) -> llvmlite.Value*:
def _find_pool_var(self, trans: HT.Translator*) -> mlirlite.Value*:
"""查找上下文中的 pool 变量,返回 alloca 或 None
查找顺序: pool → _mbuddy → mbuddy → mb
@@ -192,7 +192,7 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
"""
if trans is None:
return None
alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, "pool")
alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, "pool")
if alloca is not None:
return alloca
alloca = self.Gen.VarGen.lookup_var(trans.SymTab, "_mbuddy")
@@ -214,22 +214,22 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
if pool is None or trans.Module is None or trans.SymTab is None:
return None
# 先检查是否已注册到模块作用域(避免重复创建全局变量)
existing: llvmlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, "_mbuddy")
existing: mlirlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, "_mbuddy")
if existing is not None:
return existing
# 创建 i8* 类型(t.CPtr = i8*)
i8_ty_fb: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty_fb: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty_fb)
i8_ty_fb: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty_fb: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_fb)
# 当前模块 mangled 名(@<模块sha1>._mbuddy)
mb_name_fb: str = self.Gen.FuncGenBase._mangle_name(trans, "_mbuddy")
# 创建 linkonce_odr 定义(可被链接器合并,自给自足保证链接通过)
gv_ext: llvmlite.GlobalVariable* = llvmlite.new_global_variable(pool, mb_name_fb, i8_ptr_ty_fb)
gv_ext: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, mb_name_fb, i8_ptr_ty_fb)
if gv_ext is not None:
gv_ext.Linkage = "linkonce_odr"
gv_ext.Initializer = "zeroinitializer"
llvmlite.module_add_global(trans.Module, gv_ext)
mlirlite.module_add_global(trans.Module, gv_ext)
# 创建 Value 引用(@<模块sha1>._mbuddy, 类型为 i8**)
i8_ptr_ptr_ty_fb: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ptr_ty_fb)
i8_ptr_ptr_ty_fb: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ptr_ty_fb)
ref_name_fb: str = pool.alloc(96)
if ref_name_fb is not None:
# mangled 名带 SHA1 前缀(数字开头),引用必须加引号(见 make_global_ref)
@@ -237,17 +237,17 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
viperlib.snprintf(ref_name_fb, 96, "@\"%s\"", mb_name_fb)
else:
viperlib.snprintf(ref_name_fb, 96, "@%s", mb_name_fb)
gv_ref_fb: llvmlite.Value* = llvmlite.SSAValue(pool, i8_ptr_ptr_ty_fb, ref_name_fb)
gv_ref_fb: mlirlite.Value* = mlirlite.SSAValue(pool, i8_ptr_ptr_ty_fb, ref_name_fb)
# 注册到模块作用域,避免重复创建
self.Gen.VarGen.define_module_var(trans.SymTab, "_mbuddy", gv_ref_fb)
return gv_ref_fb
# translate_list_literal:把 list 字面量 [a, b, c] 翻译为 list[T](pool) 构造 + append 调用序列。elem_type_name 为元素类型名(如 "str"/"int"),None 表示从元素推断。返回 list 对象指针(Ptr(list[T] struct)),失败返回 None
def translate_list_literal(self, builder: llvmlite.IRBuilder*,
def translate_list_literal(self, builder: mlirlite.IRBuilder*,
pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
node: ast.AST*,
elem_type_name: str,
trans: HT.Translator*) -> llvmlite.Value*:
trans: HT.Translator*) -> mlirlite.Value*:
"""翻译 list 字面量 [a, b, c] → list[T](pool) + append 序列"""
if node is None or trans is None:
return None
@@ -263,7 +263,7 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
# 推断元素类型
inferred_type_name: str = elem_type_name
first_elem_val: llvmlite.Value* = None
first_elem_val: mlirlite.Value* = None
if inferred_type_name is None:
if elts_count > 0:
first_elem_node: ast.AST* = elts.get(0)
@@ -280,15 +280,15 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
inferred_type_name = "str"
# 查找 pool 变量
pool_alloca: llvmlite.Value* = self._find_pool_var(trans)
pool_alloca: mlirlite.Value* = self._find_pool_var(trans)
if pool_alloca is None:
self.Gen.TypeGenErr.fatal_error(node, "list literal requires pool variable in context")
return None
# load pool 变量值(i8*)
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
pool_val: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty, pool_alloca)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
pool_val: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty, pool_alloca)
if pool_val is None:
return None
@@ -305,14 +305,14 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
if struct_entry is None:
self.Gen.TypeGenErr.fatal_error(node, "list literal specialized class not registered")
return None
struct_ty: llvmlite.LLVMType* = struct_entry.Ty
struct_ty: mlirlite.LLVMType* = struct_entry.Ty
if struct_ty is None:
return None
# alloca 临时 list 空间
# 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间)
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, struct_ty)
tmp: llvmlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, struct_ty)
tmp: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, struct_ty)
if tmp is None:
return None
@@ -320,7 +320,7 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
# __new__ 是可选的,仅当泛型类模板定义了 __new__ 方法时才调用
# (与 _translate_struct_ctor/_translate_generic_ctor_call 保持一致,
# 避免为无 __new__ 的类生成过度声明)
storage_ptr: llvmlite.Value* = tmp
storage_ptr: mlirlite.Value* = tmp
has_new_flag: int = 0
if struct_entry is not None:
has_new_flag = struct_entry.HasNew
@@ -330,7 +330,7 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
return None
string.memset(new_args, 0, 8 * 32)
new_args[0] = sizet(pool_val)
new_ptr: llvmlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__new__", tmp, new_args, 1, trans)
new_ptr: mlirlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__new__", tmp, new_args, 1, trans)
if new_ptr is not None:
storage_ptr = new_ptr
@@ -342,7 +342,7 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
if init_args is None: return None
string.memset(init_args, 0, 8 * 32)
init_args[0] = sizet(pool_val)
elem_size_val: llvmlite.Value* = llvmlite.const_int64(pool, 0)
elem_size_val: mlirlite.Value* = mlirlite.const_int64(pool, 0)
init_args[1] = sizet(elem_size_val)
self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__init__", storage_ptr, init_args, 2, trans)
@@ -359,7 +359,7 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
# 翻译剩余元素
for i in range(1, elts_count):
elem_node_i: ast.AST* = elts.get(i)
elem_val_i: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, elem_node_i, None, 0, trans)
elem_val_i: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, elem_node_i, None, 0, trans)
if elem_val_i is not None:
ap_args: sizet* = pool.alloc(8 * 32)
if ap_args is not None:
+46 -46
View File
@@ -1,7 +1,7 @@
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import lib.core.Gen.Translator as HT
@@ -33,11 +33,11 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
# 之前 f-string 未翻译导致 print/赋值拿到 NULL 指针
# ("(null)"输出 + printf("%s", 垃圾) 崩溃 0xC0000005)。
# ============================================================
def translate_joined_str(self, builder: llvmlite.IRBuilder*,
def translate_joined_str(self, builder: mlirlite.IRBuilder*,
pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
node: ast.AST*,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""f-string → snprintf 生成 i8* 栈缓冲(函数内临时值,禁止逃逸)"""
if node is None or builder is None or trans is None: return None
js: rawptr[ast.JoinedStr] = rawptr[ast.JoinedStr](node)
@@ -49,8 +49,8 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
fmt_buf[0] = '\0'
# 运行时参数链表(Value.Next 链接,与 printf 调用一致)
arg_head: llvmlite.Value* = None
arg_tail: llvmlite.Value* = None
arg_head: mlirlite.Value* = None
arg_tail: mlirlite.Value* = None
arg_count: int = 0
parts: list[ast.AST*]* = js.values
@@ -66,14 +66,14 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
if part.kind() != ast.ASTKind.FormattedValue: continue
fv: rawptr[ast.FormattedValue] = rawptr[ast.FormattedValue](part)
if fv.value is None: continue
val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fv.value, None, 0, trans)
val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fv.value, None, 0, trans)
if val is None:
# fail-fast:f-string 格式化值翻译失败必须终止编译,绝不在
self.Gen.TypeGenErr.fatal_error(fv.value, "f-string 格式化值翻译失败(表达式返回 None)", "TypeError")
continue
# 对象定义了 __str__ 且未指定格式 → 用其返回的字符串(对齐 TPC)
if fv.format_spec is None:
str_ov_fs: llvmlite.Value* = self.Gen.ExprGenOps._try_named_dunder(pool, builder, mod, val, "__str__", trans)
str_ov_fs: mlirlite.Value* = self.Gen.ExprGenOps._try_named_dunder(pool, builder, mod, val, "__str__", trans)
if str_ov_fs is not None:
val = str_ov_fs
# 确定 C 格式说明符(format_spec 优先,否则按值类型推断)
@@ -89,7 +89,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
if string.strlen(fmt_buf) + string.strlen(c_fmt) < FSTR_BUF_SIZE - 1:
string.strcat(fmt_buf, c_fmt)
# 转换参数类型(i8/i16→i32、bool→i32、f32→f64)
cast_val: llvmlite.Value* = self._fstr_cast_value(builder, pool, val, c_fmt, fv.value, trans)
cast_val: mlirlite.Value* = self._fstr_cast_value(builder, pool, val, c_fmt, fv.value, trans)
if cast_val is None:
cast_val = val
cast_val.Next = None
@@ -101,11 +101,11 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
arg_count += 1
return self._fstr_finalize(builder, pool, mod, fmt_buf, arg_head, arg_tail, arg_count, trans)
def translate_formatted_value(self, builder: llvmlite.IRBuilder*,
def translate_formatted_value(self, builder: mlirlite.IRBuilder*,
pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
node: ast.AST*,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""翻译裸 FormattedValue(f"{expr:spec}" 无字面量时解析器返回 FormattedValue 而非 JoinedStr)"""
if node is None or builder is None or trans is None:
return None
@@ -116,17 +116,17 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
if fmt_buf is None:
return None
fmt_buf[0] = '\0'
arg_head: llvmlite.Value* = None
arg_tail: llvmlite.Value* = None
arg_head: mlirlite.Value* = None
arg_tail: mlirlite.Value* = None
arg_count: int = 0
val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fv.value, None, 0, trans)
val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fv.value, None, 0, trans)
if val is None:
# fail-fast:裸 FormattedValue 翻译失败必须终止编译,绝不在
self.Gen.TypeGenErr.fatal_error(fv.value, "f-string 格式化值翻译失败(表达式返回 None)", "TypeError")
else:
# 对象定义了 __str__ 且未指定格式 → 用其返回的字符串(对齐 TPC)
if fv.format_spec is None:
str_ov_sf: llvmlite.Value* = self.Gen.ExprGenOps._try_named_dunder(pool, builder, mod, val, "__str__", trans)
str_ov_sf: mlirlite.Value* = self.Gen.ExprGenOps._try_named_dunder(pool, builder, mod, val, "__str__", trans)
if str_ov_sf is not None:
val = str_ov_sf
c_fmt: str = None
@@ -139,7 +139,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
self.Gen.TypeGenErr.fatal_error(fv.value, "f-string 格式无法推断(值类型缺失)", "TypeError")
if string.strlen(fmt_buf) + string.strlen(c_fmt) < FSTR_BUF_SIZE - 1:
string.strcat(fmt_buf, c_fmt)
cast_val: llvmlite.Value* = self._fstr_cast_value(builder, pool, val, c_fmt, fv.value, trans)
cast_val: mlirlite.Value* = self._fstr_cast_value(builder, pool, val, c_fmt, fv.value, trans)
if cast_val is None:
cast_val = val
cast_val.Next = None
@@ -147,22 +147,22 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
arg_tail = cast_val
arg_count = 1
return self._fstr_finalize(builder, pool, mod, fmt_buf, arg_head, arg_tail, arg_count, trans)
def _fstr_finalize(self, builder: llvmlite.IRBuilder*,
def _fstr_finalize(self, builder: mlirlite.IRBuilder*,
pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
fmt_buf: str,
arg_head: llvmlite.Value*,
arg_tail: llvmlite.Value*,
arg_head: mlirlite.Value*,
arg_tail: mlirlite.Value*,
arg_count: int,
trans: HT.Translator*) -> llvmlite.Value*:
trans: HT.Translator*) -> mlirlite.Value*:
"""f-string 尾部:全局格式串 + 每站点栈缓冲 + snprintf,返回 i8*(函数内临时值)"""
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
if fmt_buf is None or fmt_buf[0] == '\0':
# 空 f-string(f"")→ 空字符串常量
return self.Gen.ExprGenConst.create_global_string(builder, pool, mod, "", trans)
# 格式串 → 全局字符串常量(i8*)
fmt_ptr: llvmlite.Value* = self.Gen.ExprGenConst.create_global_string(builder, pool, mod, fmt_buf, trans)
fmt_ptr: mlirlite.Value* = self.Gen.ExprGenConst.create_global_string(builder, pool, mod, fmt_buf, trans)
if fmt_ptr is None: return None
# 结果缓冲:**每站点独立栈缓冲**(entry 块 alloca;每次翻译本站点各建一个,
# 站点之间不共享 ⇒ 同函数多个 f-string 不再互相覆盖)。
@@ -177,11 +177,11 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
# · 确需逃逸时**显式分配后拷贝**:GenApi.escape_fstring_copy
# (stdlib.malloc + string.strcpy);编译器自身的报文构造即此写法
# (AssignGenMixin.const_assign_msg)。
buf_ty: llvmlite.LLVMType* = llvmlite.Array(pool, i8_ty, FSTR_BUF_SIZE)
buf_alloca: llvmlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, buf_ty)
buf_ty: mlirlite.LLVMType* = mlirlite.Array(pool, i8_ty, FSTR_BUF_SIZE)
buf_alloca: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, buf_ty)
if buf_alloca is None: return None
zero_i32: llvmlite.Value* = llvmlite.const_int32(pool, 0)
buf_ptr: llvmlite.Value* = llvmlite.build_gep_array(builder, buf_ty, i8_ty, buf_alloca, zero_i32)
zero_i32: mlirlite.Value* = mlirlite.const_int32(pool, 0)
buf_ptr: mlirlite.Value* = mlirlite.build_gep_array(builder, buf_ty, i8_ty, buf_alloca, zero_i32)
if buf_ptr is None: return None
# f-string 降级为 snprintf 调用,而 snprintf 的声明在 includes/stdio.vp:7
# (`extern def snprintf(buf, size, fmt, *args) -> int`)。源文件若未
@@ -190,20 +190,20 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
# 提供"原则在使用点补 declare(先例:AsyncGenMixin 的 GetTickCount64)。
# 签名三段固定参数(i8*, i64, i8*)+ 变参,与下面的 build_call 一致。
if self.Gen.CallGenBase.find_func_in_module(mod, "snprintf") is None:
snprintf_decl: llvmlite.Function* = llvmlite.create_declare(pool, mod, "snprintf", i32_ty)
snprintf_decl: mlirlite.Function* = mlirlite.create_declare(pool, mod, "snprintf", i32_ty)
if snprintf_decl is not None:
snprintf_decl.IsVarArg = 1
llvmlite.add_param(pool, snprintf_decl, i8_ty, "buf")
llvmlite.add_param(pool, snprintf_decl, llvmlite.Int64(pool), "size")
llvmlite.add_param(pool, snprintf_decl, i8_ty, "fmt")
mlirlite.add_param(pool, snprintf_decl, i8_ty, "buf")
mlirlite.add_param(pool, snprintf_decl, mlirlite.Int64(pool), "size")
mlirlite.add_param(pool, snprintf_decl, i8_ty, "fmt")
# snprintf(buf, FSTR_BUF_SIZE, fmt, args...)
size_val: llvmlite.Value* = llvmlite.const_int64(pool, FSTR_BUF_SIZE)
size_val: mlirlite.Value* = mlirlite.const_int64(pool, FSTR_BUF_SIZE)
buf_ptr.Next = size_val
size_val.Next = fmt_ptr
fmt_ptr.Next = arg_head
if arg_tail is not None:
arg_tail.Next = None
llvmlite.build_call(builder, "snprintf", buf_ptr, 3 + arg_count, i32_ty, 1)
mlirlite.build_call(builder, "snprintf", buf_ptr, 3 + arg_count, i32_ty, 1)
return buf_ptr
def _fstr_append_literal(self, fmt_buf: str,
lit: str) -> None:
@@ -239,7 +239,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
string.strcpy(fmt_buf + cur_len, s)
def _fstr_parse_format_spec(self, pool: memhub.MemBuddy*,
spec_node: ast.AST*,
val: llvmlite.Value*,
val: mlirlite.Value*,
arg_node: ast.AST*) -> str:
"""Python format_spec → C printf 格式串(pool 分配),无法解析返回 None"""
if spec_node is None or pool is None or val is None:
@@ -408,7 +408,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
return None
return out
def _fstr_infer_c_fmt(self, pool: memhub.MemBuddy*,
val: llvmlite.Value*,
val: mlirlite.Value*,
arg_node: ast.AST*,
trans: HT.Translator*) -> str:
"""无 format_spec 时按值类型推断 C printf 格式(对齐 TPC 无 spec 分支,带 % 前缀)"""
@@ -439,12 +439,12 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
# fail-fast:值类型缺失(非整数/浮点/指针),无法推断 C 格式,立即终止编译
self.Gen.TypeGenErr.fatal_error(arg_node, "f-string 格式无法推断(值类型缺失)", "TypeError")
return None
def _fstr_cast_value(self, builder: llvmlite.IRBuilder*,
def _fstr_cast_value(self, builder: mlirlite.IRBuilder*,
pool: memhub.MemBuddy*,
val: llvmlite.Value*,
val: mlirlite.Value*,
c_fmt: str,
arg_node: ast.AST*,
trans: HT.Translator*) -> llvmlite.Value*:
trans: HT.Translator*) -> mlirlite.Value*:
"""按 C 格式转换值类型(i8/i16→i32、bool→i32、f32→f64)"""
if val is None or c_fmt is None:
return None
@@ -461,28 +461,28 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
if ch != 'l' and ch != 'h':
fmt_char = ch
break
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
if fmt_char == 's':
return val
if fmt_char == 'c':
ibits: int = self.Gen.ExprGenBase.get_llvm_type_bits(val.Ty)
if ibits != 0 and ibits < 32:
return llvmlite.build_zext(builder, val, i32_ty)
return mlirlite.build_zext(builder, val, i32_ty)
return val
if fmt_char == 'd' or fmt_char == 'i' or fmt_char == 'x' \
or fmt_char == 'X' or fmt_char == 'o' or fmt_char == 'u':
ibits = self.Gen.ExprGenBase.get_llvm_type_bits(val.Ty)
if ibits == 1:
return llvmlite.build_zext(builder, val, i32_ty)
return mlirlite.build_zext(builder, val, i32_ty)
if ibits == 8 or ibits == 16:
if self.Gen.ExprGenOps._node_type_unsigned(pool, arg_node, trans) != 0:
return llvmlite.build_zext(builder, val, i32_ty)
return llvmlite.build_sext(builder, val, i32_ty)
return mlirlite.build_zext(builder, val, i32_ty)
return mlirlite.build_sext(builder, val, i32_ty)
return val
if fmt_char == 'f' or fmt_char == 'e' or fmt_char == 'E' \
or fmt_char == 'g' or fmt_char == 'G':
fbits: int = self.Gen.ExprGenBase.get_llvm_float_bits(val.Ty)
if fbits == 32:
return llvmlite.build_fpext(builder, val, llvmlite.Double(pool))
return mlirlite.build_fpext(builder, val, mlirlite.Double(pool))
return val
return val
+11 -11
View File
@@ -2,7 +2,7 @@ import t, c
from stdint import *
import ast
import memhub
import llvmlite
import mlirlite
import lib.core.Gen.Translator as HT
import lib.core.Gen.Expr.ExprGenBase as ExprGenBase
@@ -45,15 +45,15 @@ novirtual class ExprGenMixin(ExprGenBase.ExprGenBase):
# ============================================================
# 翻译值表达式(RHS 分派)— 模块级版本
# ============================================================
def translate_value(self, builder: llvmlite.IRBuilder*,
def translate_value(self, builder: mlirlite.IRBuilder*,
pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
node: ast.AST*,
funcs_ptr: t.CPtr = None,
func_count: int = 0,
trans: HT.Translator* = None,
target_ty: llvmlite.LLVMType* = None,
use_ctx: str = None) -> llvmlite.Value*:
target_ty: mlirlite.LLVMType* = None,
use_ctx: str = None) -> mlirlite.Value*:
"""翻译值表达式为 LLVM Value(深度守卫包装器,原逻辑见 _translate_value_impl)
target_ty: 目标类型上下文(如调用形参类型/赋值目标类型),用于单引号
@@ -65,26 +65,26 @@ novirtual class ExprGenMixin(ExprGenBase.ExprGenBase):
if trans.TranslateDepth >= HT.TRANSLATE_MAX_DEPTH:
self.Gen.TypeGenErr.fatal_error(node, "表达式翻译嵌套过深(疑似 AST 自引用环或翻译 bug)", "RecursionError")
trans.TranslateDepth += 1
rv: llvmlite.Value* = self._translate_value_impl(builder, pool, mod, node, funcs_ptr, func_count, trans, target_ty, use_ctx)
rv: mlirlite.Value* = self._translate_value_impl(builder, pool, mod, node, funcs_ptr, func_count, trans, target_ty, use_ctx)
if trans is not None:
trans.TranslateDepth -= 1
return rv
def _translate_value_impl(self, builder: llvmlite.IRBuilder*,
def _translate_value_impl(self, builder: mlirlite.IRBuilder*,
pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
node: ast.AST*,
funcs_ptr: t.CPtr = None,
func_count: int = 0,
trans: HT.Translator* = None,
target_ty: llvmlite.LLVMType* = None,
use_ctx: str = None) -> llvmlite.Value*:
target_ty: mlirlite.LLVMType* = None,
use_ctx: str = None) -> mlirlite.Value*:
"""翻译值表达式为 LLVM Value"""
if node is None:
return None
k: int = node.kind()
if k == ast.ASTKind.Constant:
rv: llvmlite.Value* = self.Gen.ExprGenConst.translate_constant(builder, pool, mod, node, trans, target_ty)
rv: mlirlite.Value* = self.Gen.ExprGenConst.translate_constant(builder, pool, mod, node, trans, target_ty)
return rv
elif k == ast.ASTKind.Name: return self.Gen.ExprGenName.translate_name_value(builder, pool, node, trans, target_ty, use_ctx)
elif k == ast.ASTKind.BinOp: return self.Gen.ExprGenOps.translate_binop(pool, builder, mod, node, trans)
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+8 -8
View File
@@ -1,7 +1,7 @@
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import viperlib
@@ -329,14 +329,14 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase):
# 创建 LLVM 函数(简单版本,仅声明)
# ============================================================
def create_function(self, pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
name: str,
args_node: ast.AST*,
ret_ty: llvmlite.LLVMType*) -> llvmlite.Function*:
ret_ty: mlirlite.LLVMType*) -> mlirlite.Function*:
"""创建 LLVM 函数并添加参数"""
if name is None or mod is None: return None
func: llvmlite.Function* = llvmlite.create_function(pool, mod, name, ret_ty)
func: mlirlite.Function* = mlirlite.create_function(pool, mod, name, ret_ty)
if func is None: return None
if args_node is not None:
@@ -344,7 +344,7 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase):
if ags.args is not None:
alist: list[ast.AST*]* = ags.args
an: sizet = len(alist)
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
for ai in range(an):
arg: ast.Arg* = ast.Arg*(alist.get(ai))
if arg is not None and arg.arg is not None:
@@ -353,9 +353,9 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase):
if arg.annotation.kind() == ast.ASTKind.Attribute:
at_cf: ast.Attribute* = ast.Attribute*(arg.annotation)
if at_cf.attr is not None and string.strcmp(at_cf.attr, "CVoid") == 0: continue
param_ty: llvmlite.LLVMType* = i32_ty
param_ty: mlirlite.LLVMType* = i32_ty
if arg.annotation is not None:
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, None, None, None, 0)
resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, None, None, None, 0)
if resolved is None:
# [S4 fail-fast] 有注解但解析失败:不再静默用 i32。
# 本函数不传 trans/imports 上下文,解析失败即调用方未补齐
@@ -366,6 +366,6 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase):
pname: str = pool.alloc(32)
if pname is not None:
viperlib.snprintf(pname, 32, "%%%s", arg.arg)
llvmlite.add_param(pool, func, param_ty, pname)
mlirlite.add_param(pool, func, param_ty, pname)
return func
+246 -246
View File
@@ -3,7 +3,7 @@ import lib.core.Gen.Func.FuncGenMixin as FuncGenMixin
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import viperlib
@@ -33,16 +33,16 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
"""预扫描所有顶层 FunctionDef,创建前向声明"""
if trans is None or tree is None: return 0
pool: memhub.MemBuddy* = trans.Pool
mod: llvmlite.LLVMModule* = trans.Module
mod: mlirlite.LLVMModule* = trans.Module
if pool is None or mod is None: return 0
imported_modules: str = trans._imported_modules
from_imports: str = trans._from_imports
funcs_ptr: GenTypes.FuncEntry* = trans._funcs
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
ch: list[ast.AST*]* = tree.children
if ch is None: return 0
@@ -99,7 +99,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
tp_names_fd: list[str]* = None
# 推断返回类型
ret_ty: llvmlite.LLVMType* = None
ret_ty: mlirlite.LLVMType* = None
if fd.returns is not None:
ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, fd.returns, imported_modules, from_imports, trans, 0)
# 单独 t.CExport 返回注解(def free(...) -> t.CExport:)=
@@ -112,10 +112,10 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
if ce_at.value is not None and ce_at.value.kind() == ast.ASTKind.Name:
ce_nm: ast.Name* = ast.Name*(ce_at.value)
if ce_nm.id is not None and string.strcmp(ce_nm.id, "t") == 0:
ret_ty = llvmlite.Void(pool)
ret_ty = mlirlite.Void(pool)
if ret_ty is None and fd.returns is not None:
if self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0) != 0:
ret_ty = llvmlite.Void(pool)
ret_ty = mlirlite.Void(pool)
# @c.CReturn 装饰器已移除:遇到即编译期报错(多返回值改用 -> tuple[...])
if ret_ty is None:
self.Gen.FuncGenBase.RejectCReturnDecorator(fd, fd.decorator_list)
@@ -169,14 +169,14 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
mangled_name = self.Gen.FuncGenBase._mangle_func_name(trans, fd.name, 0)
# 如果函数已存在(如重复定义),跳过
existing: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, mangled_name)
existing: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, mangled_name)
if existing is not None:
if tp_names_fd is not None:
self.Gen.TypeGenBase.clear_generic_context()
continue
# 创建 declare
func: llvmlite.Function* = llvmlite.create_declare(pool, mod, mangled_name, ret_ty)
func: mlirlite.Function* = mlirlite.create_declare(pool, mod, mangled_name, ret_ty)
if func is None:
if tp_names_fd is not None:
self.Gen.TypeGenBase.clear_generic_context()
@@ -224,9 +224,9 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
# CVoid 表示空参:跳过
if arg.annotation is not None:
if self.Gen.TypeGenResolve._is_t_attr(arg.annotation, "CVoid", imported_modules) != 0: continue
param_ty: llvmlite.LLVMType* = i32_ty
param_ty: mlirlite.LLVMType* = i32_ty
if arg.annotation is not None:
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, imported_modules, from_imports, trans, 0)
resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, imported_modules, from_imports, trans, 0)
if resolved is None:
# [S4 fail-fast] 有注解但解析失败:不再静默用 i32
# (declare 与 define 签名不一致 → ABI 错位,运行期读栈垃圾)
@@ -248,27 +248,27 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
# 注册完整定义再按值(ensure_struct_def_in_module,先例
# CallGenCtor.vp L478);不命中(真 opaque)保持 Ptr(struct)。
match resolved:
case llvmlite.LLVMType.Void():
case mlirlite.LLVMType.Void():
# void 不是合法形参类型(用户 2026-10-01:void 只能用于
# `void*` 与 `typedef 不透明结构体 = void`)。放任会按
# LLVM void 建形参 ⇒ 非法 IR 拖到 llc 才暴露,改编译期 fail-fast。
# 注意 `void*` 已在上游归并为 i8*,不会命中此分支。
self.Gen.TypeGenErr.fatal_error(arg, f"形参 '{arg.arg}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError")
return 0
case llvmlite.LLVMType.Struct(_, _, _):
case mlirlite.LLVMType.Struct(_, _, _):
if is_extern_decl != 0 and self.Gen.StructGen.find_struct_by_type(resolved) is not None:
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, resolved)
param_ty = resolved
else:
param_ty = llvmlite.Ptr(pool, resolved)
case llvmlite.LLVMType.Array(aelem_ty, _):
param_ty = llvmlite.Ptr(pool, aelem_ty)
param_ty = mlirlite.Ptr(pool, resolved)
case mlirlite.LLVMType.Array(aelem_ty, _):
param_ty = mlirlite.Ptr(pool, aelem_ty)
case _:
param_ty = resolved
pname: str = pool.alloc(32)
if pname is not None:
viperlib.snprintf(pname, 32, "%%%s", arg.arg)
llvmlite.add_param(pool, func, param_ty, pname)
mlirlite.add_param(pool, func, param_ty, pname)
# *args 变长参数:设置 IsVarArg=1,生成 ... 后缀
if ags.vararg is not None:
@@ -312,16 +312,16 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
return self.Gen.AsyncGen.translate_async_function(trans, node)
pool: memhub.MemBuddy* = trans.Pool
mod: llvmlite.LLVMModule* = trans.Module
mod: mlirlite.LLVMModule* = trans.Module
imported_modules: str = trans._imported_modules
from_imports: str = trans._from_imports
funcs_ptr: GenTypes.FuncEntry* = trans._funcs
func_count: int = trans._func_count
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
# 推断返回类型:优先使用返回类型注解
ret_ty: llvmlite.LLVMType* = None
ret_ty: mlirlite.LLVMType* = None
if fd.returns is not None:
ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, fd.returns, imported_modules, from_imports, trans, 0)
# 单独 t.CExport 返回注解(def free(...) -> t.CExport:)= 导出
@@ -334,13 +334,13 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
if ce_at2.value is not None and ce_at2.value.kind() == ast.ASTKind.Name:
ce_nm2: ast.Name* = ast.Name*(ce_at2.value)
if ce_nm2.id is not None and string.strcmp(ce_nm2.id, "t") == 0:
ret_ty = llvmlite.Void(pool)
ret_ty = mlirlite.Void(pool)
# 如果返回类型注解纯装饰器标记(如 t.State,无实际类型),使用 void
# 注意:必须在 infer_return_type 之前检测,因为 infer_return_type 至少返回 i32
if ret_ty is None and fd.returns is not None:
if self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0) != 0:
ret_ty = llvmlite.Void(pool)
ret_ty = mlirlite.Void(pool)
# @c.CReturn 装饰器已移除:遇到即编译期报错(多返回值改用 -> tuple[...])
if ret_ty is None:
@@ -473,10 +473,10 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
if is_extern_decl != 0:
# 外部声明函数:生成 declare(仅声明,不定义)
# 先检查是否已由 forward_declare_functions 创建,避免重复 declare
existing_extern: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, mangled_name)
existing_extern: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, mangled_name)
if existing_extern is not None: return 0
func: llvmlite.Function* = llvmlite.create_declare(pool, mod, mangled_name, ret_ty)
func: mlirlite.Function* = mlirlite.create_declare(pool, mod, mangled_name, ret_ty)
if func is None: return 0
# 注册到函数表
@@ -498,9 +498,9 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
if arg_e.annotation is not None \
and self.Gen.TypeGenResolve._is_t_attr(arg_e.annotation, "CVoid", imported_modules) != 0:
continue
param_ty_e: llvmlite.LLVMType* = i32_ty
param_ty_e: mlirlite.LLVMType* = i32_ty
if arg_e.annotation is not None:
resolved_e: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg_e.annotation, imported_modules, from_imports, trans, 0)
resolved_e: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg_e.annotation, imported_modules, from_imports, trans, 0)
if resolved_e is None:
# fail-fast:外部声明函数参数有注解但类型解析失败,
# 不再静默保持 i32(声明签名错误会在 ABI 层暴露)
@@ -514,32 +514,32 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
# 同 forward_declare_functions / VpiReader
# _AggregateParamTy,三处必须同步)。
match resolved_e:
case llvmlite.LLVMType.Void():
case mlirlite.LLVMType.Void():
# void 不是合法形参类型(用户 2026-10-01,见上方同款判据)
self.Gen.TypeGenErr.fatal_error(arg_e, f"形参 '{arg_e.arg}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError")
case llvmlite.LLVMType.Struct(_, _, _):
case mlirlite.LLVMType.Struct(_, _, _):
if self.Gen.StructGen.find_struct_by_type(resolved_e) is not None:
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, resolved_e)
param_ty_e = resolved_e
else:
param_ty_e = llvmlite.Ptr(pool, resolved_e)
case llvmlite.LLVMType.Array(aelem_ty_e, _):
param_ty_e = llvmlite.Ptr(pool, aelem_ty_e)
param_ty_e = mlirlite.Ptr(pool, resolved_e)
case mlirlite.LLVMType.Array(aelem_ty_e, _):
param_ty_e = mlirlite.Ptr(pool, aelem_ty_e)
case _:
param_ty_e = resolved_e
pname_e: str = pool.alloc(32)
if pname_e is not None:
viperlib.snprintf(pname_e, 32, "%%%s", arg_e.arg)
llvmlite.add_param(pool, func, param_ty_e, pname_e)
mlirlite.add_param(pool, func, param_ty_e, pname_e)
# 提取 @c.Attribute 装饰器属性并设置到函数
func_attrs_e: str = self.Gen.FuncGenBase.extract_func_attrs(pool, fd.decorator_list, imported_modules)
if func_attrs_e is not None:
llvmlite.function_set_attrs(func, func_attrs_e)
mlirlite.function_set_attrs(func, func_attrs_e)
# B5:section 字符串属性走属性组 #N
func_section_e: str = self.Gen.FuncGenBase.extract_func_section(pool, fd.decorator_list, imported_modules)
if func_section_e is not None:
llvmlite.function_set_attr_group(func, func_section_e)
mlirlite.function_set_attr_group(func, func_section_e)
# 参数添加完成,补全全局函数表的 Spec
self.Gen.CallGenLeafKit.update_global_func_spec(fd.name, func)
@@ -550,21 +550,21 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
args_node: ast.Arguments* = fd.args
# 检查是否已有前向声明(由 forward_declare_functions 创建)
func: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, mangled_name)
if func is not None and llvmlite.function_is_declared(func) != 0:
func: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, mangled_name)
if func is not None and mlirlite.function_is_declared(func) != 0:
# 复用前向声明:清除 IsDeclared 标记,转为 define
func.IsDeclared = 0
# 装饰器属性设置(前向声明时未设置)
func_attrs_reuse: str = self.Gen.FuncGenBase.extract_func_attrs(pool, fd.decorator_list, imported_modules)
if func_attrs_reuse is not None:
llvmlite.function_set_attrs(func, func_attrs_reuse)
mlirlite.function_set_attrs(func, func_attrs_reuse)
# B5:section 字符串属性走属性组 #N
func_section_reuse: str = self.Gen.FuncGenBase.extract_func_section(pool, fd.decorator_list, imported_modules)
if func_section_reuse is not None:
llvmlite.function_set_attr_group(func, func_section_reuse)
mlirlite.function_set_attr_group(func, func_section_reuse)
else:
# 创建新的 LLVM 函数(使用 SHA1 混淆名)
func = llvmlite.create_function(pool, mod, mangled_name, ret_ty)
func = mlirlite.create_function(pool, mod, mangled_name, ret_ty)
if func is None:
VLogger.error(f"create_function {fd.name} failed", "FUNC")
return 0
@@ -572,11 +572,11 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
# 提取 @c.Attribute 装饰器属性并设置到函数
func_attrs: str = self.Gen.FuncGenBase.extract_func_attrs(pool, fd.decorator_list, imported_modules)
if func_attrs is not None:
llvmlite.function_set_attrs(func, func_attrs)
mlirlite.function_set_attrs(func, func_attrs)
# B5:section 字符串属性走属性组 #N(LLVM 不接受内联 section="...")
func_section: str = self.Gen.FuncGenBase.extract_func_section(pool, fd.decorator_list, imported_modules)
if func_section is not None:
llvmlite.function_set_attr_group(func, func_section)
mlirlite.function_set_attr_group(func, func_section)
# 提取默认参数信息
tfd_defaults: t.CPtr = None
@@ -612,9 +612,9 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
if arg.annotation is not None \
and self.Gen.TypeGenResolve._is_t_attr(arg.annotation, "CVoid", imported_modules) != 0:
continue
param_ty: llvmlite.LLVMType* = i32_ty
param_ty: mlirlite.LLVMType* = i32_ty
if arg.annotation is not None:
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, imported_modules, from_imports, trans, 0)
resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, imported_modules, from_imports, trans, 0)
if resolved is None:
# [S4 fail-fast] 有注解但解析失败:不再静默用 i32
# (形参类型错 → ABI 错位/字段访问错)
@@ -625,20 +625,20 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
# 的 out 指向调用方数组首元素;传 Ptr(数组) 会使 out[i] 的
# GEP 以整个数组为步长错位,摘要垃圾根因)
match resolved:
case llvmlite.LLVMType.Void():
case mlirlite.LLVMType.Void():
# void 不是合法形参类型(用户 2026-10-01,见上方同款判据)
self.Gen.TypeGenErr.fatal_error(arg, f"形参 '{arg.arg}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError")
return 0
case llvmlite.LLVMType.Struct(_, _, _):
param_ty = llvmlite.Ptr(pool, resolved)
case llvmlite.LLVMType.Array(aelem_ty, _):
param_ty = llvmlite.Ptr(pool, aelem_ty)
case mlirlite.LLVMType.Struct(_, _, _):
param_ty = mlirlite.Ptr(pool, resolved)
case mlirlite.LLVMType.Array(aelem_ty, _):
param_ty = mlirlite.Ptr(pool, aelem_ty)
case _:
param_ty = resolved
pname: str = pool.alloc(32)
if pname is not None:
viperlib.snprintf(pname, 32, "%%%s", arg.arg)
llvmlite.add_param(pool, func, param_ty, pname)
mlirlite.add_param(pool, func, param_ty, pname)
# *args 变长参数:设置 IsVarArg=1,生成 ... 后缀
if ags.vararg is not None:
@@ -653,28 +653,28 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
# store %__eh_code_out__ 但签名无此参数(llc: use of undefined value)。
if string.strcmp(fd.name, "main") != 0:
if self.Gen.FuncGenBase._body_has_raise(fd) != 0:
i8_ty_eh: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty_eh: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty_eh)
i8_ptr_ptr_ty_eh: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ptr_ty_eh)
i32_ty_eh: llvmlite.LLVMType* = llvmlite.Int32(pool)
i32_ptr_ty_eh: llvmlite.LLVMType* = llvmlite.Ptr(pool, i32_ty_eh)
i8_ty_eh: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty_eh: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_eh)
i8_ptr_ptr_ty_eh: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ptr_ty_eh)
i32_ty_eh: mlirlite.LLVMType* = mlirlite.Int32(pool)
i32_ptr_ty_eh: mlirlite.LLVMType* = mlirlite.Ptr(pool, i32_ty_eh)
if i8_ptr_ptr_ty_eh is not None and i32_ptr_ty_eh is not None:
llvmlite.add_param(pool, func, i8_ptr_ptr_ty_eh, "%__eh_msg_out__")
llvmlite.add_param(pool, func, i32_ptr_ty_eh, "%__eh_code_out__")
mlirlite.add_param(pool, func, i8_ptr_ptr_ty_eh, "%__eh_msg_out__")
mlirlite.add_param(pool, func, i32_ptr_ty_eh, "%__eh_code_out__")
# 参数添加完成,补全全局函数表的 Spec
self.Gen.CallGenLeafKit.update_global_func_spec(fd.name, func)
# 创建 entry 块
entry_blk: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, "entry")
entry_blk: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "entry")
if entry_blk is None:
return 0
# 创建函数专属 builder
func_builder: llvmlite.IRBuilder* = llvmlite.new_builder(pool, func)
func_builder: mlirlite.IRBuilder* = mlirlite.new_builder(pool, func)
if func_builder is None:
return 0
llvmlite.position_at_end(func_builder, entry_blk)
mlirlite.position_at_end(func_builder, entry_blk)
# --traceback: attach a DISubprogram to this define and set every
# instruction in the body to the entry DILocation (the statement hook
@@ -689,53 +689,53 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
tls_flag_name: str = pool.alloc(128)
if tls_flag_name is not None:
viperlib.snprintf(tls_flag_name, 128, "__tls_init_done_%s", fd.name)
tls_flag_gv: llvmlite.GlobalVariable* = llvmlite.create_global_int(pool, mod, tls_flag_name, 1, 0)
tls_flag_gv: mlirlite.GlobalVariable* = mlirlite.create_global_int(pool, mod, tls_flag_name, 1, 0)
if tls_flag_gv is not None:
i1_ty_t: llvmlite.LLVMType* = llvmlite.Int1(pool)
i1_ty_t: mlirlite.LLVMType* = mlirlite.Int1(pool)
if i1_ty_t is not None:
# GlobalVariable 不是 Value 子类(字段布局不同),build_load/store
# 按 Value 读 ptr.Ty/ptr.Name 会错位(Ty 读到 Name → void,Name 为空)。
# 与 create_global_string 一致:构造 Value 视图(Ty=Ptr(i1), Name="@name")。
tls_gv_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i1_ty_t)
tls_gv_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i1_ty_t)
tls_ref_name: str = pool.alloc(64)
if tls_ref_name is not None:
viperlib.snprintf(tls_ref_name, 64, "@%s", tls_flag_name)
tls_flag_ref: llvmlite.Value* = llvmlite.SSAValue(pool, tls_gv_ptr_ty, tls_ref_name)
tls_flag_ref: mlirlite.Value* = mlirlite.SSAValue(pool, tls_gv_ptr_ty, tls_ref_name)
if tls_flag_ref is not None:
tls_flag_ld: llvmlite.Value* = llvmlite.build_load(func_builder, i1_ty_t, tls_flag_ref)
tls_flag_ld: mlirlite.Value* = mlirlite.build_load(func_builder, i1_ty_t, tls_flag_ref)
# 块名唯一化(create_block 不自动编号,同函数同名 label 冲突)
lc_t: int = trans._label_counter
trans._label_counter = lc_t + 1
tls_bb_buf: str = pool.alloc(64)
if tls_bb_buf is not None:
viperlib.snprintf(tls_bb_buf, 64, "tls.skip.%d", lc_t)
tls_skip_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, tls_bb_buf)
tls_skip_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, tls_bb_buf)
viperlib.snprintf(tls_bb_buf, 64, "tls.cont.%d", lc_t)
tls_cont_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, tls_bb_buf)
tls_cont_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, tls_bb_buf)
if tls_skip_bb is not None and tls_cont_bb is not None:
llvmlite.build_cond_br(func_builder, tls_flag_ld, tls_skip_bb, tls_cont_bb)
mlirlite.build_cond_br(func_builder, tls_flag_ld, tls_skip_bb, tls_cont_bb)
# skip 块:按返回类型生成默认值直接返回
llvmlite.position_at_end(func_builder, tls_skip_bb)
mlirlite.position_at_end(func_builder, tls_skip_bb)
match ret_ty:
case llvmlite.LLVMType.Void():
llvmlite.build_ret_void(func_builder)
case llvmlite.LLVMType.Int(_):
tlz0: llvmlite.Value* = llvmlite.ConstInt(pool, ret_ty, 0, "0")
case mlirlite.LLVMType.Void():
mlirlite.build_ret_void(func_builder)
case mlirlite.LLVMType.Int(_):
tlz0: mlirlite.Value* = mlirlite.ConstInt(pool, ret_ty, 0, "0")
if tlz0 is not None:
llvmlite.build_ret(func_builder, tlz0)
case llvmlite.LLVMType.Float(_):
tlf0: llvmlite.Value* = llvmlite.ConstFloat(pool, ret_ty, 0.0)
mlirlite.build_ret(func_builder, tlz0)
case mlirlite.LLVMType.Float(_):
tlf0: mlirlite.Value* = mlirlite.ConstFloat(pool, ret_ty, 0.0)
if tlf0 is not None:
llvmlite.build_ret(func_builder, tlf0)
mlirlite.build_ret(func_builder, tlf0)
case _:
tln0: llvmlite.Value* = llvmlite.ConstNull(pool, ret_ty, "null")
tln0: mlirlite.Value* = mlirlite.ConstNull(pool, ret_ty, "null")
if tln0 is not None:
llvmlite.build_ret(func_builder, tln0)
mlirlite.build_ret(func_builder, tln0)
# cont 块:置标志=1,继续函数体
llvmlite.position_at_end(func_builder, tls_cont_bb)
tlone: llvmlite.Value* = llvmlite.ConstInt(pool, i1_ty_t, 1, "1")
mlirlite.position_at_end(func_builder, tls_cont_bb)
tlone: mlirlite.Value* = mlirlite.ConstInt(pool, i1_ty_t, 1, "1")
if tlone is not None:
llvmlite.build_store(func_builder, tlone, tls_flag_ref)
mlirlite.build_store(func_builder, tlone, tls_flag_ref)
# 进入函数作用域(嵌套符号表)
self.Gen.VarGen.enter_scope(trans.SymTab, FuncGenMixin.SCOPE_FUNCTION)
@@ -757,9 +757,9 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
if arg2.annotation is not None:
if self.Gen.TypeGenResolve._is_t_attr(arg2.annotation, "CVoid", imported_modules) != 0:
continue
param_ty2: llvmlite.LLVMType* = i32_ty
param_ty2: mlirlite.LLVMType* = i32_ty
if arg2.annotation is not None:
resolved2: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg2.annotation, imported_modules, from_imports, trans, 0)
resolved2: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg2.annotation, imported_modules, from_imports, trans, 0)
if resolved2 is None:
# fail-fast:参数有注解但类型解析失败,不再静默保持 i32
self.Gen.TypeGenErr.fatal_error(arg2, f"参数 '{arg2.arg}' 类型解析失败: {self.Gen.TypeGenResolve.annotation_to_str(arg2.annotation)}", "NameError")
@@ -769,17 +769,17 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
# CArray 形参 → 元素指针 ty*(数组衰减,alloca 类型须与形参一致,
# 否则 store ty* 到 [N x ty]* 容器类型不匹配)
match resolved2:
case llvmlite.LLVMType.Void():
case mlirlite.LLVMType.Void():
# void 不是合法形参类型(用户 2026-10-01,见上方同款判据)
self.Gen.TypeGenErr.fatal_error(arg2, f"形参 '{arg2.arg}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError")
return 0
case llvmlite.LLVMType.Struct(_, _, _):
param_ty2 = llvmlite.Ptr(pool, resolved2)
case llvmlite.LLVMType.Array(aelem_ty2, _):
param_ty2 = llvmlite.Ptr(pool, aelem_ty2)
case mlirlite.LLVMType.Struct(_, _, _):
param_ty2 = mlirlite.Ptr(pool, resolved2)
case mlirlite.LLVMType.Array(aelem_ty2, _):
param_ty2 = mlirlite.Ptr(pool, aelem_ty2)
case _:
param_ty2 = resolved2
alloca: llvmlite.Value* = llvmlite.build_alloca(func_builder, param_ty2)
alloca: mlirlite.Value* = mlirlite.build_alloca(func_builder, param_ty2)
if alloca is not None:
self.Gen.VarGen.define_var(trans.SymTab, arg2.arg, alloca)
# 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体)
@@ -808,9 +808,9 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
pname2: str = pool.alloc(32)
if pname2 is not None:
viperlib.snprintf(pname2, 32, "%%%s", arg2.arg)
param_val: llvmlite.Value* = llvmlite.SSAValue(pool, param_ty2, pname2)
param_val: mlirlite.Value* = mlirlite.SSAValue(pool, param_ty2, pname2)
vol_p2: int = self.Gen.VarGen.var_is_volatile(self.Gen.VarGen.lookup_var_entry(trans.SymTab, arg2.arg))
llvmlite.build_store(func_builder, param_val, alloca, vol_p2)
mlirlite.build_store(func_builder, param_val, alloca, vol_p2)
# *args 变长参数:创建 va_list 缓冲区 + 调用 va_start + 注册到符号表
# 生成 IR:
@@ -827,19 +827,19 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
vararg_name_str: str = vararg_node.arg
# va_list 缓冲区 24 字节(Win64 的 __va_list_tag = {i32,i32,i8*,i8*})+ 16 对齐
# (对齐 TPC HandlesFunctions.py:1739-1741)
i8_ty_va: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty_va: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty_va)
va_buf_ty: llvmlite.LLVMType* = llvmlite.Array(pool, i8_ty_va, 24)
va_list_alloca: llvmlite.Value* = llvmlite.build_alloca_aligned(func_builder, va_buf_ty, 16)
i8_ty_va: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty_va: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_va)
va_buf_ty: mlirlite.LLVMType* = mlirlite.Array(pool, i8_ty_va, 24)
va_list_alloca: mlirlite.Value* = mlirlite.build_alloca_aligned(func_builder, va_buf_ty, 16)
if va_list_alloca is not None:
# i8* 地址(指向 24 字节 va_list 缓冲区)——vararg 名的值语义
va_list_addr: llvmlite.Value* = llvmlite.build_bitcast(func_builder, va_list_alloca, i8_ptr_ty_va)
va_list_addr: mlirlite.Value* = mlirlite.build_bitcast(func_builder, va_list_alloca, i8_ptr_ty_va)
if va_list_addr is not None:
# 注册到符号表(translate_name_value 对 vararg 名特殊处理返回地址)
self.Gen.VarGen.define_var(trans.SymTab, vararg_name_str, va_list_alloca)
# 调用 @llvm.va_start(i8* %va_list_addr)
void_ty_va: llvmlite.LLVMType* = llvmlite.Void(pool)
llvmlite.build_call(func_builder, "llvm.va_start",
void_ty_va: mlirlite.LLVMType* = mlirlite.Void(pool)
mlirlite.build_call(func_builder, "llvm.va_start",
va_list_addr, 1, void_ty_va, 0)
# 保存到 trans 供 arg(type) 糖函数与 vararg 名翻译使用
trans._va_list_ptr = va_list_addr
@@ -849,8 +849,8 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
# (调用方/包围函数)的 EH 输出参数,翻译完本函数后再恢复——否则
# 下方设置本函数 EH 参数会覆盖外层值,恢复时 old_eh_* 拿到的是
# 本函数自身参数(嵌套函数/多函数链 EH 状态错乱)。
old_eh_msg_out: llvmlite.Value* = trans._eh_msg_out_param
old_eh_code_out: llvmlite.Value* = trans._eh_code_out_param
old_eh_msg_out: mlirlite.Value* = trans._eh_msg_out_param
old_eh_code_out: mlirlite.Value* = trans._eh_code_out_param
old_cur_func_has_eh: int = trans._cur_func_has_eh
trans._eh_msg_out_param = None
trans._eh_code_out_param = None
@@ -859,33 +859,33 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
# try-except:保存当前函数的 EH 输出参数(__eh_msg_out__/__eh_code_out__)
# 供 translate_raise / UnhandledBB 写入并向上传播。无 EH 参数的函数置空。
if string.strcmp(fd.name, "main") != 0 and self.Gen.FuncGenBase._body_has_raise(fd) != 0:
i8_ty_eh2: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty_eh2: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty_eh2)
i8_ptr_ptr_ty_eh2: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ptr_ty_eh2)
i32_ty_eh2: llvmlite.LLVMType* = llvmlite.Int32(pool)
i32_ptr_ty_eh2: llvmlite.LLVMType* = llvmlite.Ptr(pool, i32_ty_eh2)
i8_ty_eh2: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty_eh2: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_eh2)
i8_ptr_ptr_ty_eh2: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ptr_ty_eh2)
i32_ty_eh2: mlirlite.LLVMType* = mlirlite.Int32(pool)
i32_ptr_ty_eh2: mlirlite.LLVMType* = mlirlite.Ptr(pool, i32_ty_eh2)
if i8_ptr_ptr_ty_eh2 is not None and i32_ptr_ty_eh2 is not None:
msg_out_ref: llvmlite.Value* = llvmlite.SSAValue(pool, i8_ptr_ptr_ty_eh2, "%__eh_msg_out__")
code_out_ref: llvmlite.Value* = llvmlite.SSAValue(pool, i32_ptr_ty_eh2, "%__eh_code_out__")
msg_out_ref: mlirlite.Value* = mlirlite.SSAValue(pool, i8_ptr_ptr_ty_eh2, "%__eh_msg_out__")
code_out_ref: mlirlite.Value* = mlirlite.SSAValue(pool, i32_ptr_ty_eh2, "%__eh_code_out__")
trans._eh_msg_out_param = msg_out_ref
trans._eh_code_out_param = code_out_ref
trans._cur_func_has_eh = 1
# 保存模块级作用域状态(仅非变量表相关)
old_func: llvmlite.Function* = trans._cur_func
old_builder: llvmlite.IRBuilder* = trans._cur_builder
old_func: mlirlite.Function* = trans._cur_func
old_builder: mlirlite.IRBuilder* = trans._cur_builder
old_global_count: int = trans._global_name_count
old_nonlocal_count: int = trans._nonlocal_name_count
old_env_count: int = trans._closure_env_count
old_va_list_ptr: llvmlite.Value* = trans._va_list_ptr
old_va_list_ptr: mlirlite.Value* = trans._va_list_ptr
old_vararg_name: str = trans._vararg_name
# 返回注解上下文([C①] 裸名泛型构造的类型实参回退来源之一):
# 进入函数体前记录本函数返回注解,退出时恢复外层函数的值
old_ret_annot: ast.AST* = trans.CurFuncRetAnnot
# break/continue 目标与 match-case 标记:新函数作用域必须清空(见下方赋值),
# 否则嵌套函数体内的 break/continue 会继承外层函数(甚至跨函数)的 br 目标
old_break_bb: rawptr[llvmlite.BasicBlock] = trans._break_bb
old_continue_bb: rawptr[llvmlite.BasicBlock] = trans._continue_bb
old_break_bb: rawptr[mlirlite.BasicBlock] = trans._break_bb
old_continue_bb: rawptr[mlirlite.BasicBlock] = trans._continue_bb
old_insw: int = trans._in_switch_case
trans._cur_func = func
@@ -925,7 +925,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
# 嵌套函数定义前:预扫描其链内 nonlocal 并建堆
# (不同层捕获不同变量的场景,见 _prepare_chain_nonlocals)
if stmt2.kind() == ast.ASTKind.FunctionDef:
self.Gen.FuncGen._prepare_chain_nonlocals(trans, stmt2, pool, func_builder, mod, llvmlite.Int8(pool), llvmlite.Ptr(pool, llvmlite.Int8(pool)))
self.Gen.FuncGen._prepare_chain_nonlocals(trans, stmt2, pool, func_builder, mod, mlirlite.Int8(pool), mlirlite.Ptr(pool, mlirlite.Int8(pool)))
self.Gen.StmtGen.translate_stmt(trans, stmt2)
# 如果函数体最后一条语句不是 Return,添加隐式 ret
@@ -940,7 +940,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return:
last_is_return = 1
if last_is_return == 0:
if llvmlite.builder_cur_block_is_terminated(func_builder) == 0:
if mlirlite.builder_cur_block_is_terminated(func_builder) == 0:
# 编译器不替代码发明返回值——函数流程真实掉出末尾而未显式 return 时 fail-fast
# (要求补 return,定位到函数)。三种合法收尾:
# ① void 函数掉出末尾 → ret void(无值可发明,Python 语义)
@@ -965,7 +965,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
_is_void: int = 0
if ret_ty is not None:
match ret_ty:
case llvmlite.LLVMType.Void():
case mlirlite.LLVMType.Void():
_is_void = 1
case _:
pass
@@ -986,7 +986,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
if ret_none_cn.const_kind == ast.CONST_NONE:
_is_void = 1
if _is_void != 0:
llvmlite.build_ret_void(func_builder)
mlirlite.build_ret_void(func_builder)
elif last_is_ctrl != 0 and trans._ctrl_merge_reachable == 0:
# 追加90:非 void 函数末句是控制流且 merge 块**结构性**不可达
# (全分支 return,无 br 到 merge)→ LLVM 语义 unreachable。
@@ -995,20 +995,20 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
# unreachable 是 UB,llc 不生成任何指令 ⇒ 执行掉进布局紧随其后的块。
# ★ 可达性判据**只用 `_ctrl_merge_reachable`**(MatchGenMixin 逐臂真正
# `br end_bb` 时才置 1,并由"用本 match 自身的 br 记录覆盖"写回):
# 实测反面教材 —— includes/llvmlite/__types.vp::_TypePrintDepth 末句
# 实测反面教材 —— includes/mlirlite/__types.vp::_TypePrintDepth 末句
# `match ty:` 带 `case _:`,各臂只 snprintf 后 br 到 merge;旧判据(追加92
# 的 MatchHasWildcardArm 子句)按"穷尽 ⇒ 流程不可能掉出末尾"推断,给这个
# 可达 merge 生成了 unreachable ⇒ 打印完 "i32" 后掉进同一 switch 的跳转表,
# 用上一条 snprintf 的返回值("i%d" → 3)当 tag 取 table[3] = Array 臂,
# 把 Int 的 Bits(32) 当指针递归解引用 ⇒ AV at 0x20。
# 穷尽性 ≠ 各臂都终止:只有"有没有 br 到 merge"才是可达性。
llvmlite.build_unreachable(func_builder)
mlirlite.build_unreachable(func_builder)
elif fd.returns is None:
# 无返回类型注解 → 无返回值过程函数,默认零值返回
if ret_ty is not None:
zero_val: llvmlite.Value* = llvmlite.ConstZero(pool, ret_ty)
zero_val: mlirlite.Value* = mlirlite.ConstZero(pool, ret_ty)
if zero_val is not None:
llvmlite.build_ret(func_builder, zero_val)
mlirlite.build_ret(func_builder, zero_val)
else:
self.Gen.TypeGenErr.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError")
else:
@@ -1017,11 +1017,11 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
# fail-fast:有 -> 注解但流程真实掉出末尾(定位到函数定义
# 节点,fatal_error 输出 traceback 风格错误)
if ret_ty is not None:
# llvmlite 无 type_get_name API,类型序列化用真实接口
# mlirlite 无 type_get_name API,类型序列化用真实接口
# TypePrint(buf, size, ty, pool)(追加89 修正)
rt_name: str = pool.alloc(64)
if rt_name is not None:
llvmlite.TypePrint(rt_name, 64, ret_ty, pool)
mlirlite.TypePrint(rt_name, 64, ret_ty, pool)
if rt_name[0] == '\0':
rt_name = "?"
err_fn: str = pool.alloc(256)
@@ -1114,27 +1114,27 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
# ============================================================
def _gen_decor_wrapper(self, trans: HT.Translator*,
pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
func: llvmlite.Function*,
mod: mlirlite.LLVMModule*,
func: mlirlite.Function*,
func_name: str,
wrapper_name: str,
handler_name: str,
decor_arg0: int64) -> llvmlite.Function*:
decor_arg0: int64) -> mlirlite.Function*:
"""生成装饰器 wrapper 函数,返回 wrapper 或 None"""
if trans is None or pool is None or mod is None or func is None:
return None
if func_name is None or wrapper_name is None or handler_name is None:
return None
ret_ty: llvmlite.LLVMType* = llvmlite.function_get_ret_ty(func)
ret_ty: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(func)
if ret_ty is None:
return None
orig_call_name: str = llvmlite.function_get_name(func)
orig_call_name: str = mlirlite.function_get_name(func)
if orig_call_name is None:
return None
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
# ---- 收集原函数参数类型(按位置,最多 16 个)----
n_params: int = 0
@@ -1142,246 +1142,246 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
if param_tys is None:
return None
string.memset(param_tys, 0, 16 * 8)
pp: llvmlite.Param* = llvmlite.function_get_param_head(func)
pp: mlirlite.Param* = mlirlite.function_get_param_head(func)
while pp is not None:
pty: llvmlite.LLVMType* = llvmlite.param_get_ty(pp)
pty: mlirlite.LLVMType* = mlirlite.param_get_ty(pp)
if pty is not None and n_params < 16:
param_tys[n_params] = sizet(pty)
n_params += 1
pp = llvmlite.param_get_next(pp)
pp = mlirlite.param_get_next(pp)
# ---- 创建 wrapper 函数并添加参数(名字 %a0..%aN)----
wrapper: llvmlite.Function* = llvmlite.create_function(pool, mod, wrapper_name, ret_ty)
wrapper: mlirlite.Function* = mlirlite.create_function(pool, mod, wrapper_name, ret_ty)
if wrapper is None: return None
pi: int = 0
for pi in range(n_params):
pname_w: str = pool.alloc(16)
if pname_w is not None:
viperlib.snprintf(pname_w, 16, "%%a%d", pi)
llvmlite.add_param(pool, wrapper, (llvmlite.LLVMType*)(param_tys[pi]), pname_w)
mlirlite.add_param(pool, wrapper, (mlirlite.LLVMType*)(param_tys[pi]), pname_w)
# ---- 创建块 ----
entry_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, wrapper, "entry")
loop_h_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, wrapper, "loop.header")
loop_b_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, wrapper, "loop.body")
post_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, wrapper, "post")
entry_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, wrapper, "entry")
loop_h_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, wrapper, "loop.header")
loop_b_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, wrapper, "loop.body")
post_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, wrapper, "post")
if entry_bb is None or loop_h_bb is None or loop_b_bb is None or post_bb is None:
return None
# 递归保护标志(最外层):@__decor_rec_{wrapper} = global i8 0
rec_flag_ref: llvmlite.Value* = None
rec_flag_ref: mlirlite.Value* = None
rec_flag_name: str = pool.alloc(128)
if rec_flag_name is not None:
viperlib.snprintf(rec_flag_name, 128, "__decor_rec_%s", wrapper_name)
llvmlite.create_global_int(pool, mod, rec_flag_name, 8, 0)
mlirlite.create_global_int(pool, mod, rec_flag_name, 8, 0)
rec_ref_nm: str = pool.alloc(96)
if rec_ref_nm is not None:
viperlib.snprintf(rec_ref_nm, 96, "@%s", rec_flag_name)
rec_flag_ref = llvmlite.SSAValue(pool, llvmlite.Ptr(pool, i8_ty), rec_ref_nm)
rec_flag_ref = mlirlite.SSAValue(pool, mlirlite.Ptr(pool, i8_ty), rec_ref_nm)
wb: llvmlite.IRBuilder* = llvmlite.new_builder(pool, wrapper)
wb: mlirlite.IRBuilder* = mlirlite.new_builder(pool, wrapper)
if wb is None:
return None
# 返回类型分类
ret_is_void: int = 0
match ret_ty:
case llvmlite.LLVMType.Void():
case mlirlite.LLVMType.Void():
ret_is_void = 1
case _:
pass
# ---- entry:递归保护检查(最外层)----
llvmlite.position_at_end(wb, entry_bb)
loop_pred_bb: rawptr[llvmlite.BasicBlock] = entry_bb
mlirlite.position_at_end(wb, entry_bb)
loop_pred_bb: rawptr[mlirlite.BasicBlock] = entry_bb
if rec_flag_ref is not None:
rec_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, wrapper, "recursive_call")
dec_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, wrapper, "decorated_entry")
rec_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, wrapper, "recursive_call")
dec_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, wrapper, "decorated_entry")
if rec_bb is None or dec_bb is None:
return None
rec_val: llvmlite.Value* = llvmlite.build_load(wb, i8_ty, rec_flag_ref)
rec_zero: llvmlite.Value* = llvmlite.ConstInt(pool, i8_ty, 0, "0")
rec_is: llvmlite.Value* = llvmlite.build_icmp(wb, llvmlite.ICMP_NE, rec_val, rec_zero)
llvmlite.build_cond_br(wb, rec_is, rec_bb, dec_bb)
rec_val: mlirlite.Value* = mlirlite.build_load(wb, i8_ty, rec_flag_ref)
rec_zero: mlirlite.Value* = mlirlite.ConstInt(pool, i8_ty, 0, "0")
rec_is: mlirlite.Value* = mlirlite.build_icmp(wb, mlirlite.ICMP_NE, rec_val, rec_zero)
mlirlite.build_cond_br(wb, rec_is, rec_bb, dec_bb)
# recursive_call:直接调用原函数返回(跳过所有装饰逻辑)
llvmlite.position_at_end(wb, rec_bb)
rec_args: llvmlite.Value* = None
mlirlite.position_at_end(wb, rec_bb)
rec_args: mlirlite.Value* = None
ri: int = 0
for ri in range(n_params):
an_r: str = pool.alloc(16)
if an_r is None:
continue
viperlib.snprintf(an_r, 16, "%%a%d", ri)
av_r: llvmlite.Value* = llvmlite.SSAValue(pool, (llvmlite.LLVMType*)(param_tys[ri]), an_r)
av_r: mlirlite.Value* = mlirlite.SSAValue(pool, (mlirlite.LLVMType*)(param_tys[ri]), an_r)
if av_r is not None:
llvmlite.value_set_next(av_r, None)
mlirlite.value_set_next(av_r, None)
if rec_args is None:
rec_args = av_r
else:
# 链尾追加
rt: llvmlite.Value* = rec_args
rt: mlirlite.Value* = rec_args
while rt.Next is not None:
rt = rt.Next
llvmlite.value_set_next(rt, av_r)
mlirlite.value_set_next(rt, av_r)
if ret_is_void != 0:
llvmlite.build_call(wb, orig_call_name, rec_args, n_params, ret_ty, 0)
llvmlite.build_ret_void(wb)
mlirlite.build_call(wb, orig_call_name, rec_args, n_params, ret_ty, 0)
mlirlite.build_ret_void(wb)
else:
rc_res: llvmlite.Value* = llvmlite.build_call(wb, orig_call_name, rec_args, n_params, ret_ty, 0)
rc_res: mlirlite.Value* = mlirlite.build_call(wb, orig_call_name, rec_args, n_params, ret_ty, 0)
if rc_res is not None:
llvmlite.build_ret(wb, rc_res)
mlirlite.build_ret(wb, rc_res)
else:
llvmlite.build_ret_void(wb)
mlirlite.build_ret_void(wb)
# decorated_entry:置递归标志,继续装饰路径
llvmlite.position_at_end(wb, dec_bb)
rec_one: llvmlite.Value* = llvmlite.ConstInt(pool, i8_ty, 1, "1")
mlirlite.position_at_end(wb, dec_bb)
rec_one: mlirlite.Value* = mlirlite.ConstInt(pool, i8_ty, 1, "1")
if rec_one is not None:
llvmlite.build_store(wb, rec_one, rec_flag_ref)
mlirlite.build_store(wb, rec_one, rec_flag_ref)
loop_pred_bb = dec_bb
# ---- 公共装饰路径(entry 或 decorated_entry)----
# 1. ctx = alloca [32 x i8]; ctx_ptr = bitcast i8*
ctx_ty: llvmlite.LLVMType* = llvmlite.Array(pool, i8_ty, 32)
ctx_alloca: llvmlite.Value* = llvmlite.build_alloca(wb, ctx_ty)
ctx_ptr: llvmlite.Value* = llvmlite.build_bitcast(wb, ctx_alloca, i8_ptr_ty)
ctx_ty: mlirlite.LLVMType* = mlirlite.Array(pool, i8_ty, 32)
ctx_alloca: mlirlite.Value* = mlirlite.build_alloca(wb, ctx_ty)
ctx_ptr: mlirlite.Value* = mlirlite.build_bitcast(wb, ctx_alloca, i8_ptr_ty)
# 2. 打包函数参数到结构体 {param_types}(装饰器可读写 args_ptr)
args_alloca: llvmlite.Value* = None
args_ptr: llvmlite.Value* = None
args_alloca: mlirlite.Value* = None
args_ptr: mlirlite.Value* = None
if n_params > 0:
fields_head: llvmlite.ParamNode* = None
fields_head: mlirlite.ParamNode* = None
fk: int = 0
for fk in range(n_params - 1, -1, -1):
pn_n: llvmlite.ParamNode* = llvmlite.new_param_node(pool, (llvmlite.LLVMType*)(param_tys[fk]))
pn_n: mlirlite.ParamNode* = mlirlite.new_param_node(pool, (mlirlite.LLVMType*)(param_tys[fk]))
if pn_n is not None:
pn_n.Next = fields_head
fields_head = pn_n
args_ty: llvmlite.LLVMType* = llvmlite.Struct(pool, fields_head, n_params, None)
args_ty: mlirlite.LLVMType* = mlirlite.Struct(pool, fields_head, n_params, None)
if args_ty is not None:
args_alloca = llvmlite.build_alloca(wb, args_ty)
args_alloca = mlirlite.build_alloca(wb, args_ty)
fi2: int = 0
for fi2 in range(n_params):
fld_ty: llvmlite.LLVMType* = (llvmlite.LLVMType*)(param_tys[fi2])
fld_ptr: llvmlite.Value* = llvmlite.build_gep_struct(wb, args_ty, fld_ty, args_alloca, fi2)
fld_ty: mlirlite.LLVMType* = (mlirlite.LLVMType*)(param_tys[fi2])
fld_ptr: mlirlite.Value* = mlirlite.build_gep_struct(wb, args_ty, fld_ty, args_alloca, fi2)
if fld_ptr is not None:
fld_nm: str = pool.alloc(16)
if fld_nm is not None:
viperlib.snprintf(fld_nm, 16, "%%a%d", fi2)
fld_v: llvmlite.Value* = llvmlite.SSAValue(pool, fld_ty, fld_nm)
fld_v: mlirlite.Value* = mlirlite.SSAValue(pool, fld_ty, fld_nm)
if fld_v is not None:
llvmlite.build_store(wb, fld_v, fld_ptr)
args_ptr = llvmlite.build_bitcast(wb, args_alloca, i8_ptr_ty)
mlirlite.build_store(wb, fld_v, fld_ptr)
args_ptr = mlirlite.build_bitcast(wb, args_alloca, i8_ptr_ty)
else:
args_ptr = llvmlite.ConstNull(pool, i8_ptr_ty, "null")
args_ptr = mlirlite.ConstNull(pool, i8_ptr_ty, "null")
# 3. 返回值存储(零初始化;跳过原函数时返回安全默认值)
ret_alloca: llvmlite.Value* = None
ret_alloca: mlirlite.Value* = None
if ret_is_void == 0:
ret_alloca = llvmlite.build_alloca(wb, ret_ty)
ret_zero: llvmlite.Value* = None
ret_alloca = mlirlite.build_alloca(wb, ret_ty)
ret_zero: mlirlite.Value* = None
match ret_ty:
case llvmlite.LLVMType.Int(_):
ret_zero = llvmlite.ConstInt(pool, ret_ty, 0, "0")
case llvmlite.LLVMType.Float(_):
ret_zero = llvmlite.ConstFloat(pool, ret_ty, 0.0)
case mlirlite.LLVMType.Int(_):
ret_zero = mlirlite.ConstInt(pool, ret_ty, 0, "0")
case mlirlite.LLVMType.Float(_):
ret_zero = mlirlite.ConstFloat(pool, ret_ty, 0.0)
case _:
ret_zero = llvmlite.ConstNull(pool, ret_ty, "null")
ret_zero = mlirlite.ConstNull(pool, ret_ty, "null")
if ret_zero is not None and ret_alloca is not None:
llvmlite.build_store(wb, ret_zero, ret_alloca)
mlirlite.build_store(wb, ret_zero, ret_alloca)
# 4. 函数名字符串常量
fn_str: llvmlite.Value* = self.Gen.ExprGenConst.create_global_string(wb, pool, mod, func_name, trans)
fn_str: mlirlite.Value* = self.Gen.ExprGenConst.create_global_string(wb, pool, mod, func_name, trans)
if fn_str is None:
fn_str = llvmlite.ConstNull(pool, i8_ptr_ty, "null")
fn_str = mlirlite.ConstNull(pool, i8_ptr_ty, "null")
# 5. handler 声明(未翻译时 declare,固定签名 i32 (i8*,i8*,i32,i8*,i8*,i8*))
if self.Gen.CallGenBase.find_func_in_module(mod, handler_name) is None:
handler_d: llvmlite.Function* = llvmlite.create_declare(pool, mod, handler_name, i32_ty)
handler_d: mlirlite.Function* = mlirlite.create_declare(pool, mod, handler_name, i32_ty)
if handler_d is not None:
llvmlite.add_param(pool, handler_d, i8_ptr_ty, "ctx")
llvmlite.add_param(pool, handler_d, i8_ptr_ty, "func_name")
llvmlite.add_param(pool, handler_d, i32_ty, "phase")
llvmlite.add_param(pool, handler_d, i8_ptr_ty, "args_ptr")
llvmlite.add_param(pool, handler_d, i8_ptr_ty, "ret_ptr")
llvmlite.add_param(pool, handler_d, i8_ptr_ty, "decor_args_ptr")
mlirlite.add_param(pool, handler_d, i8_ptr_ty, "ctx")
mlirlite.add_param(pool, handler_d, i8_ptr_ty, "func_name")
mlirlite.add_param(pool, handler_d, i32_ty, "phase")
mlirlite.add_param(pool, handler_d, i8_ptr_ty, "args_ptr")
mlirlite.add_param(pool, handler_d, i8_ptr_ty, "ret_ptr")
mlirlite.add_param(pool, handler_d, i8_ptr_ty, "decor_args_ptr")
# 6. 前置阶段:handler 返回调用次数 n_calls
ph0: llvmlite.Value* = llvmlite.ConstInt(pool, i32_ty, 0, "0")
null_ret: llvmlite.Value* = llvmlite.ConstNull(pool, i8_ptr_ty, "null")
null_dec: llvmlite.Value* = llvmlite.ConstNull(pool, i8_ptr_ty, "null")
ph0: mlirlite.Value* = mlirlite.ConstInt(pool, i32_ty, 0, "0")
null_ret: mlirlite.Value* = mlirlite.ConstNull(pool, i8_ptr_ty, "null")
null_dec: mlirlite.Value* = mlirlite.ConstNull(pool, i8_ptr_ty, "null")
# 参数链表(6 个独立值):ctx_ptr → fn_str → 0 → args_ptr → null → null
# 注意:不能 self 链接(null.Next = null 会让 build_call 遍历死循环)
if ctx_ptr is not None: llvmlite.value_set_next(ctx_ptr, fn_str)
if fn_str is not None: llvmlite.value_set_next(fn_str, ph0)
if ph0 is not None: llvmlite.value_set_next(ph0, args_ptr)
if args_ptr is not None: llvmlite.value_set_next(args_ptr, null_ret)
if null_ret is not None: llvmlite.value_set_next(null_ret, null_dec)
n_calls: llvmlite.Value* = llvmlite.build_call(wb, handler_name, ctx_ptr, 6, i32_ty, 0)
if ctx_ptr is not None: mlirlite.value_set_next(ctx_ptr, fn_str)
if fn_str is not None: mlirlite.value_set_next(fn_str, ph0)
if ph0 is not None: mlirlite.value_set_next(ph0, args_ptr)
if args_ptr is not None: mlirlite.value_set_next(args_ptr, null_ret)
if null_ret is not None: mlirlite.value_set_next(null_ret, null_dec)
n_calls: mlirlite.Value* = mlirlite.build_call(wb, handler_name, ctx_ptr, 6, i32_ty, 0)
# 7. 计数器 alloca(TPV 用 alloca 计数器替代 phi)
cnt_alloca: llvmlite.Value* = llvmlite.build_alloca(wb, i32_ty)
cnt_zero: llvmlite.Value* = llvmlite.ConstInt(pool, i32_ty, 0, "0")
cnt_alloca: mlirlite.Value* = mlirlite.build_alloca(wb, i32_ty)
cnt_zero: mlirlite.Value* = mlirlite.ConstInt(pool, i32_ty, 0, "0")
if cnt_alloca is not None and cnt_zero is not None:
llvmlite.build_store(wb, cnt_zero, cnt_alloca)
llvmlite.build_br(wb, loop_h_bb)
mlirlite.build_store(wb, cnt_zero, cnt_alloca)
mlirlite.build_br(wb, loop_h_bb)
# 8. loop.header:cur = load cnt; cur < n_calls → body / post
llvmlite.position_at_end(wb, loop_h_bb)
cur_i: llvmlite.Value* = llvmlite.build_load(wb, i32_ty, cnt_alloca)
loop_cond: llvmlite.Value* = llvmlite.build_icmp(wb, llvmlite.ICMP_SLT, cur_i, n_calls)
llvmlite.build_cond_br(wb, loop_cond, loop_b_bb, post_bb)
mlirlite.position_at_end(wb, loop_h_bb)
cur_i: mlirlite.Value* = mlirlite.build_load(wb, i32_ty, cnt_alloca)
loop_cond: mlirlite.Value* = mlirlite.build_icmp(wb, mlirlite.ICMP_SLT, cur_i, n_calls)
mlirlite.build_cond_br(wb, loop_cond, loop_b_bb, post_bb)
# 9. loop.body:读回参数(装饰器可能已修改)→ 调用原函数 → store ret
llvmlite.position_at_end(wb, loop_b_bb)
call_args: llvmlite.Value* = None
mlirlite.position_at_end(wb, loop_b_bb)
call_args: mlirlite.Value* = None
if n_params > 0:
k: int = 0
for k in range(n_params):
fld_ty_k: llvmlite.LLVMType* = (llvmlite.LLVMType*)(param_tys[k])
fld_pk: llvmlite.Value* = llvmlite.build_gep_struct(wb, args_ty, fld_ty_k, args_alloca, k)
fld_ty_k: mlirlite.LLVMType* = (mlirlite.LLVMType*)(param_tys[k])
fld_pk: mlirlite.Value* = mlirlite.build_gep_struct(wb, args_ty, fld_ty_k, args_alloca, k)
if fld_pk is None: continue
fld_vk: llvmlite.Value* = llvmlite.build_load(wb, fld_ty_k, fld_pk)
fld_vk: mlirlite.Value* = mlirlite.build_load(wb, fld_ty_k, fld_pk)
if fld_vk is not None:
llvmlite.value_set_next(fld_vk, None)
mlirlite.value_set_next(fld_vk, None)
if call_args is None:
call_args = fld_vk
else:
ct: llvmlite.Value* = call_args
ct: mlirlite.Value* = call_args
while ct.Next is not None:
ct = ct.Next
llvmlite.value_set_next(ct, fld_vk)
res_v: llvmlite.Value* = llvmlite.build_call(wb, orig_call_name, call_args, n_params, ret_ty, 0)
mlirlite.value_set_next(ct, fld_vk)
res_v: mlirlite.Value* = mlirlite.build_call(wb, orig_call_name, call_args, n_params, ret_ty, 0)
if ret_alloca is not None and res_v is not None:
llvmlite.build_store(wb, res_v, ret_alloca)
nxt_i: llvmlite.Value* = llvmlite.build_add(wb, cur_i, llvmlite.ConstInt(pool, i32_ty, 1, "1"))
mlirlite.build_store(wb, res_v, ret_alloca)
nxt_i: mlirlite.Value* = mlirlite.build_add(wb, cur_i, mlirlite.ConstInt(pool, i32_ty, 1, "1"))
if nxt_i is not None and cnt_alloca is not None:
llvmlite.build_store(wb, nxt_i, cnt_alloca)
llvmlite.build_br(wb, loop_h_bb)
mlirlite.build_store(wb, nxt_i, cnt_alloca)
mlirlite.build_br(wb, loop_h_bb)
# 10. post:handler 后置 → 清递归标志 → 返回结果
llvmlite.position_at_end(wb, post_bb)
ret_ptr: llvmlite.Value* = null_ret
mlirlite.position_at_end(wb, post_bb)
ret_ptr: mlirlite.Value* = null_ret
if ret_alloca is not None:
ret_ptr = llvmlite.build_bitcast(wb, ret_alloca, i8_ptr_ty)
ph1: llvmlite.Value* = llvmlite.ConstInt(pool, i32_ty, 1, "1")
ret_ptr = mlirlite.build_bitcast(wb, ret_alloca, i8_ptr_ty)
ph1: mlirlite.Value* = mlirlite.ConstInt(pool, i32_ty, 1, "1")
# 后置参数链:ctx_ptr → fn_str → 1 → args_ptr → ret_ptr → null
if ctx_ptr is not None: llvmlite.value_set_next(ctx_ptr, fn_str)
if fn_str is not None: llvmlite.value_set_next(fn_str, ph1)
if ph1 is not None: llvmlite.value_set_next(ph1, args_ptr)
if args_ptr is not None: llvmlite.value_set_next(args_ptr, ret_ptr)
if ret_ptr is not None: llvmlite.value_set_next(ret_ptr, null_dec)
llvmlite.build_call(wb, handler_name, ctx_ptr, 6, i32_ty, 0)
if ctx_ptr is not None: mlirlite.value_set_next(ctx_ptr, fn_str)
if fn_str is not None: mlirlite.value_set_next(fn_str, ph1)
if ph1 is not None: mlirlite.value_set_next(ph1, args_ptr)
if args_ptr is not None: mlirlite.value_set_next(args_ptr, ret_ptr)
if ret_ptr is not None: mlirlite.value_set_next(ret_ptr, null_dec)
mlirlite.build_call(wb, handler_name, ctx_ptr, 6, i32_ty, 0)
if rec_flag_ref is not None:
rec_zero2: llvmlite.Value* = llvmlite.ConstInt(pool, i8_ty, 0, "0")
rec_zero2: mlirlite.Value* = mlirlite.ConstInt(pool, i8_ty, 0, "0")
if rec_zero2 is not None:
llvmlite.build_store(wb, rec_zero2, rec_flag_ref)
mlirlite.build_store(wb, rec_zero2, rec_flag_ref)
if ret_is_void != 0:
llvmlite.build_ret_void(wb)
mlirlite.build_ret_void(wb)
else:
final_v: llvmlite.Value* = llvmlite.build_load(wb, ret_ty, ret_alloca)
final_v: mlirlite.Value* = mlirlite.build_load(wb, ret_ty, ret_alloca)
if final_v is not None:
llvmlite.build_ret(wb, final_v)
mlirlite.build_ret(wb, final_v)
else:
llvmlite.build_ret_void(wb)
mlirlite.build_ret_void(wb)
return wrapper
+179 -179
View File
@@ -2,7 +2,7 @@ import lib.core.Gen.GenTypes as GenTypes
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import viperlib
@@ -45,12 +45,12 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
if fd is None or fd.name is None: return 0
pool: memhub.MemBuddy* = trans.Pool
mod: llvmlite.LLVMModule* = trans.Module
mod: mlirlite.LLVMModule* = trans.Module
func_name: str = fd.name
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
# 1. 构建提升后的函数名: __closure_{name}(加 SHA1 前缀避免跨模块冲突)
promoted_name: str = pool.alloc(64)
@@ -59,9 +59,9 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
mangled_promoted: str = self.Gen.FuncGenBase._mangle_name(trans, promoted_name)
# 2. 创建提升后的函数: define i32 @__closure_{name}(i8* %env, args...)
func: llvmlite.Function* = llvmlite.create_function(pool, mod, mangled_promoted, i32_ty)
func: mlirlite.Function* = mlirlite.create_function(pool, mod, mangled_promoted, i32_ty)
if func is None: return 0
llvmlite.add_param(pool, func, i8_ptr_ty, "%env")
mlirlite.add_param(pool, func, i8_ptr_ty, "%env")
# 2a. 嵌套函数参数:加入提升函数签名(i8* %env, 参数...),
# 类型存入 param_tys 缓冲(CVoid 跳过,与 alloca 创建索引对齐)
@@ -81,15 +81,15 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
if arg_n is None or arg_n.arg is None: continue
if arg_n.annotation is not None:
if self.Gen.TypeGenResolve._is_t_attr(arg_n.annotation, "CVoid", imported_modules) != 0: continue
pty_n: llvmlite.LLVMType* = i32_ty
pty_n: mlirlite.LLVMType* = i32_ty
if arg_n.annotation is not None:
resolved_n: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg_n.annotation, imported_modules, from_imports, trans, 0)
resolved_n: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg_n.annotation, imported_modules, from_imports, trans, 0)
if resolved_n is not None:
match resolved_n:
case llvmlite.LLVMType.Struct(_, _, _):
pty_n = llvmlite.Ptr(pool, resolved_n)
case llvmlite.LLVMType.Array(aelem_ty_n, _):
pty_n = llvmlite.Ptr(pool, aelem_ty_n)
case mlirlite.LLVMType.Struct(_, _, _):
pty_n = mlirlite.Ptr(pool, resolved_n)
case mlirlite.LLVMType.Array(aelem_ty_n, _):
pty_n = mlirlite.Ptr(pool, aelem_ty_n)
case _:
pty_n = resolved_n
if param_count < 64 and param_tys is not None:
@@ -98,15 +98,15 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
pname_n: str = pool.alloc(32)
if pname_n is not None:
viperlib.snprintf(pname_n, 32, "%%%s", arg_n.arg)
llvmlite.add_param(pool, func, pty_n, pname_n)
mlirlite.add_param(pool, func, pty_n, pname_n)
param_count += 1
# 3. 创建 entry 块 + builder
entry_blk: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, "entry")
entry_blk: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "entry")
if entry_blk is None: return 0
func_builder: llvmlite.IRBuilder* = llvmlite.new_builder(pool, func)
func_builder: mlirlite.IRBuilder* = mlirlite.new_builder(pool, func)
if func_builder is None: return 0
llvmlite.position_at_end(func_builder, entry_blk)
mlirlite.position_at_end(func_builder, entry_blk)
# --traceback: promoted nested closure gets its own DISubprogram.
dbg_pushed_n: int = DebugInfoGen.PushFunction(pool, func_builder, func,
@@ -116,11 +116,11 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
self.Gen.VarGen.enter_scope(trans.SymTab, SCOPE_FUNCTION)
# 5. 创建 _env_ptr alloca 并存储 %env 参数
env_alloca: llvmlite.Value* = llvmlite.build_alloca(func_builder, i8_ptr_ty)
env_alloca: mlirlite.Value* = mlirlite.build_alloca(func_builder, i8_ptr_ty)
if env_alloca is not None:
self.Gen.VarGen.define_var(trans.SymTab, "_env_ptr", env_alloca)
env_param_val: llvmlite.Value* = llvmlite.SSAValue(pool, i8_ptr_ty, "%env")
llvmlite.build_store(func_builder, env_param_val, env_alloca)
env_param_val: mlirlite.Value* = mlirlite.SSAValue(pool, i8_ptr_ty, "%env")
mlirlite.build_store(func_builder, env_param_val, env_alloca)
# 5a. 创建嵌套函数参数 alloca(函数体内参数名可引用,如
# accumulate(n) 内 for i in range(n)、set_result(val) 内 result = val)
@@ -139,14 +139,14 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
continue
if idx_p >= param_count:
break
pty2_n: llvmlite.LLVMType* = i32_ty
pty2_n: mlirlite.LLVMType* = i32_ty
if param_tys is not None:
ty_addr_n: uint64 = uint64(param_tys) + idx_p * 8
ty_slot_n: str | t.CPtr = (str | t.CPtr)(ty_addr_n)
pty2_n = (llvmlite.LLVMType*)(ty_slot_n[0])
pty2_n = (mlirlite.LLVMType*)(ty_slot_n[0])
if pty2_n is None:
pty2_n = i32_ty
p_alloca: llvmlite.Value* = llvmlite.build_alloca(func_builder, pty2_n)
p_alloca: mlirlite.Value* = mlirlite.build_alloca(func_builder, pty2_n)
if p_alloca is not None:
self.Gen.VarGen.define_var(trans.SymTab, arg_p.arg, p_alloca)
if arg_p.annotation is not None:
@@ -169,22 +169,22 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
pname2_n: str = pool.alloc(32)
if pname2_n is not None:
viperlib.snprintf(pname2_n, 32, "%%%s", arg_p.arg)
p_val: llvmlite.Value* = llvmlite.SSAValue(pool, pty2_n, pname2_n)
p_val: mlirlite.Value* = mlirlite.SSAValue(pool, pty2_n, pname2_n)
vol_pn: int = self.Gen.VarGen.var_is_volatile(self.Gen.VarGen.lookup_var_entry(trans.SymTab, arg_p.arg))
llvmlite.build_store(func_builder, p_val, p_alloca, vol_pn)
mlirlite.build_store(func_builder, p_val, p_alloca, vol_pn)
idx_p += 1
# 6. 保存父函数作用域状态(仅非变量表相关)
old_func: llvmlite.Function* = trans._cur_func
old_builder: llvmlite.IRBuilder* = trans._cur_builder
old_func: mlirlite.Function* = trans._cur_func
old_builder: mlirlite.IRBuilder* = trans._cur_builder
old_func_name: str = trans._cur_func_name
old_global_count: int = trans._global_name_count
old_nonlocal_count: int = trans._nonlocal_name_count
old_env_count: int = trans._closure_env_count
# break/continue 目标与 match-case 标记:新函数作用域必须清空(见下方赋值),
# 否则嵌套函数体内的 break/continue 会继承外层函数的跳转目标(跨函数 br)
old_break_bb: rawptr[llvmlite.BasicBlock] = trans._break_bb
old_continue_bb: rawptr[llvmlite.BasicBlock] = trans._continue_bb
old_break_bb: rawptr[mlirlite.BasicBlock] = trans._break_bb
old_continue_bb: rawptr[mlirlite.BasicBlock] = trans._continue_bb
old_insw: int = trans._in_switch_case
# nonlocal 集合独立缓冲:嵌套函数注册 nonlocal 写入共享缓冲 [0] 会
# 覆盖父函数集合(ClosureTest2 Test 7 不同变量场景:level2 的 b 覆盖
@@ -252,8 +252,8 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return:
last_is_return = 1
if last_is_return == 0:
zero_val: llvmlite.Value* = llvmlite.const_int32(pool, 0)
llvmlite.build_ret(func_builder, zero_val)
zero_val: mlirlite.Value* = mlirlite.const_int32(pool, 0)
mlirlite.build_ret(func_builder, zero_val)
# 11. 保存嵌套函数的 nonlocal 信息
nested_nonlocal_count: int = trans._nonlocal_name_count
@@ -270,7 +270,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
# NOTE: _nonlocal_names 和 _nonlocal_name_count 仍为嵌套函数的值
# 13. 在父函数中创建闭包对象
parent_builder: llvmlite.IRBuilder* = old_builder
parent_builder: mlirlite.IRBuilder* = old_builder
if parent_builder is None:
# 无 builder(模块级嵌套函数?)→ 无法创建闭包,仅恢复状态
trans._cur_func_name = old_func_name
@@ -283,13 +283,13 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
# 13a. 创建 env: malloc(8 * nested_nonlocal_count) — env 存储指针数组
# 每个 nonlocal 变量占 8 字节(i8*),指向父函数的 alloca(共享存储)
env_ptr: llvmlite.Value* = None
env_ptr: mlirlite.Value* = None
if nested_nonlocal_count > 0:
env_size: int64 = nested_nonlocal_count * 8
env_size_val: llvmlite.Value* = llvmlite.const_int64(pool, env_size)
env_size_val: mlirlite.Value* = mlirlite.const_int64(pool, env_size)
if env_size_val is not None:
env_size_val.Next = None
env_ptr = llvmlite.build_call(parent_builder, "malloc", env_size_val, 1, i8_ptr_ty, 0)
env_ptr = mlirlite.build_call(parent_builder, "malloc", env_size_val, 1, i8_ptr_ty, 0)
# 为每个 nonlocal 变量建立堆存储并注册到 env:
# 运行时 env 链式共享(无需编译期映射——映射存编译期 Value 对象
@@ -302,7 +302,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
# → 从父函数 env 读该变量的堆地址(_load_raw_var_ptr),
# env[ni] = 同一堆地址(运行时链式共享,各层写同一堆)
if env_ptr is not None:
i8_ptr_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ptr_ty)
i8_ptr_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ptr_ty)
for ni in range(nested_nonlocal_count):
# 从 _nonlocal_names 缓冲区读取名称
name_addr: uint64 = uint64(trans._nonlocal_names) + ni * 8
@@ -310,53 +310,53 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
nl_name: str = nl_slot[0]
if nl_name is None:
continue
heap_store: llvmlite.Value* = None
heap_store: mlirlite.Value* = None
# 1. 优先查全局堆地址映射(_prepare_chain_nonlocals 已为
# 链内 nonlocal 建堆并 store 到 @nlheap.*;不同层捕获
# 不同变量时(ClosureTest2 Test 7)level2 的 b 经此共享)
gname_ck: str = self._nl_heap_global_name(pool, trans, nl_name)
if gname_ck is not None and self._nl_heap_global_exists(mod, gname_ck) != 0:
gv_ref0: llvmlite.Value* = self._nl_heap_global_ref(pool, trans, nl_name)
gv_ref0: mlirlite.Value* = self._nl_heap_global_ref(pool, trans, nl_name)
if gv_ref0 is not None:
heap_store = llvmlite.build_load(parent_builder, i8_ptr_ty, gv_ref0)
heap_store = mlirlite.build_load(parent_builder, i8_ptr_ty, gv_ref0)
if heap_store is None:
local_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, nl_name)
local_alloca: mlirlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, nl_name)
if local_alloca is not None and local_alloca.Ty is not None:
# 父函数局部变量:新建堆存储 + 拷贝当前值 + 重定向
nl_load_ty: llvmlite.LLVMType* = local_alloca.Ty.Pointee
nl_load_ty: mlirlite.LLVMType* = local_alloca.Ty.Pointee
if nl_load_ty is not None:
cur_val_nl: llvmlite.Value* = llvmlite.build_load(parent_builder, nl_load_ty, local_alloca)
cur_val_nl: mlirlite.Value* = mlirlite.build_load(parent_builder, nl_load_ty, local_alloca)
# 堆存储大小按类型字节数:数组(如 [4 x i32]=16 字节)
# 不能固定 8 字节(越界写崩溃);指针/标量 ≥ 8 字节
st_size: int = self._type_byte_size(pool, nl_load_ty)
st_size_val: llvmlite.Value* = llvmlite.const_int64(pool, st_size)
st_size_val: mlirlite.Value* = mlirlite.const_int64(pool, st_size)
if st_size_val is not None:
st_size_val.Next = None
var_storage: llvmlite.Value* = llvmlite.build_call(parent_builder, "malloc", st_size_val, 1, i8_ptr_ty, 0)
var_storage: mlirlite.Value* = mlirlite.build_call(parent_builder, "malloc", st_size_val, 1, i8_ptr_ty, 0)
if var_storage is not None:
# 拷贝当前值到堆存储
st_slot_nl: llvmlite.Value* = llvmlite.build_bitcast(parent_builder, var_storage, llvmlite.Ptr(pool, nl_load_ty))
st_slot_nl: mlirlite.Value* = mlirlite.build_bitcast(parent_builder, var_storage, mlirlite.Ptr(pool, nl_load_ty))
if st_slot_nl is not None and cur_val_nl is not None:
llvmlite.build_store(parent_builder, cur_val_nl, st_slot_nl)
mlirlite.build_store(parent_builder, cur_val_nl, st_slot_nl)
# 父函数 VarEntry.Alloca 重定向到堆(父函数读写走共享堆)
ve_nl: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nl_name)
heap_typed: llvmlite.Value* = llvmlite.build_bitcast(parent_builder, var_storage, llvmlite.Ptr(pool, nl_load_ty))
heap_typed: mlirlite.Value* = mlirlite.build_bitcast(parent_builder, var_storage, mlirlite.Ptr(pool, nl_load_ty))
if ve_nl is not None and heap_typed is not None:
ve_nl.Alloca = heap_typed
# 记录到全局映射(后续层/父函数可见)
gv_ref_new: llvmlite.Value* = None
gv_ref_new: mlirlite.Value* = None
if gname_ck is not None \
and self._nl_heap_global_exists(mod, gname_ck) == 0:
gv_new: llvmlite.GlobalVariable* = \
llvmlite.new_global_variable(pool, gname_ck, i8_ptr_ty)
gv_new: mlirlite.GlobalVariable* = \
mlirlite.new_global_variable(pool, gname_ck, i8_ptr_ty)
if gv_new is not None:
# 清除 external linkage + 零初始化(防 undefined reference)
gv_new.Linkage = None
gv_new.Initializer = "null"
llvmlite.module_add_global(mod, gv_new)
mlirlite.module_add_global(mod, gv_new)
gv_ref_new = self._nl_heap_global_ref(pool, trans, nl_name)
if gv_ref_new is not None:
llvmlite.build_store(parent_builder, var_storage, gv_ref_new)
mlirlite.build_store(parent_builder, var_storage, gv_ref_new)
heap_store = var_storage
else:
# 父函数中该变量是 nonlocal(多层嵌套):从父函数 env
@@ -365,18 +365,18 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
if heap_store is None:
continue
# env[ni] = 堆存储地址(共享)
offset_val: llvmlite.Value* = llvmlite.const_int32(pool, ni * 8)
slot: llvmlite.Value* = llvmlite.build_gep(parent_builder, i8_ty, env_ptr, offset_val)
offset_val: mlirlite.Value* = mlirlite.const_int32(pool, ni * 8)
slot: mlirlite.Value* = mlirlite.build_gep(parent_builder, i8_ty, env_ptr, offset_val)
if slot is not None:
slot_typed: llvmlite.Value* = llvmlite.build_bitcast(parent_builder, slot, i8_ptr_ptr_ty)
slot_typed: mlirlite.Value* = mlirlite.build_bitcast(parent_builder, slot, i8_ptr_ptr_ty)
if slot_typed is not None:
llvmlite.build_store(parent_builder, heap_store, slot_typed)
mlirlite.build_store(parent_builder, heap_store, slot_typed)
# 13b. 创建闭包结构: malloc(16)
closure_size_val: llvmlite.Value* = llvmlite.const_int64(pool, 16)
closure_size_val: mlirlite.Value* = mlirlite.const_int64(pool, 16)
if closure_size_val is not None:
closure_size_val.Next = None
closure_ptr: llvmlite.Value* = llvmlite.build_call(parent_builder, "malloc", closure_size_val, 1, i8_ptr_ty, 0)
closure_ptr: mlirlite.Value* = mlirlite.build_call(parent_builder, "malloc", closure_size_val, 1, i8_ptr_ty, 0)
if closure_ptr is None:
# malloc 失败,恢复状态
trans._cur_func_name = old_func_name
@@ -389,9 +389,9 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
# 13c. 存储 fn_ptr 到 offset 0
# 创建函数指针类型 i32(i8*)*
fn_param_node: llvmlite.ParamNode* = llvmlite.new_param_node(pool, i8_ptr_ty)
fn_func_ty: llvmlite.LLVMType* = llvmlite.Func(pool, i32_ty, fn_param_node, 1)
fn_func_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, fn_func_ty)
fn_param_node: mlirlite.ParamNode* = mlirlite.new_param_node(pool, i8_ptr_ty)
fn_func_ty: mlirlite.LLVMType* = mlirlite.Func(pool, i32_ty, fn_param_node, 1)
fn_func_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, fn_func_ty)
# 创建函数引用 Value(类型为 i32(i8*)*,使用 SHA1 混淆名)
fn_ptr_name: str = pool.alloc(64)
@@ -401,31 +401,31 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
viperlib.snprintf(fn_ptr_name, 64, "@\"%s\"", mangled_promoted)
else:
viperlib.snprintf(fn_ptr_name, 64, "@%s", mangled_promoted)
fn_ptr_val: llvmlite.Value* = llvmlite.SSAValue(pool, fn_func_ptr_ty, fn_ptr_name)
fn_ptr_val: mlirlite.Value* = mlirlite.SSAValue(pool, fn_func_ptr_ty, fn_ptr_name)
# bitcast 函数指针到 i8*(闭包存储 i8* 类型)
fn_as_i8ptr: llvmlite.Value* = llvmlite.build_bitcast(parent_builder, fn_ptr_val, i8_ptr_ty)
fn_slot: llvmlite.Value* = llvmlite.build_bitcast(parent_builder, closure_ptr, llvmlite.Ptr(pool, i8_ptr_ty))
fn_as_i8ptr: mlirlite.Value* = mlirlite.build_bitcast(parent_builder, fn_ptr_val, i8_ptr_ty)
fn_slot: mlirlite.Value* = mlirlite.build_bitcast(parent_builder, closure_ptr, mlirlite.Ptr(pool, i8_ptr_ty))
if fn_slot is not None and fn_as_i8ptr is not None:
llvmlite.build_store(parent_builder, fn_as_i8ptr, fn_slot)
mlirlite.build_store(parent_builder, fn_as_i8ptr, fn_slot)
# 13d. 存储 env_ptr 到 offset 8
eight_val: llvmlite.Value* = llvmlite.const_int32(pool, 8)
env_slot_addr: llvmlite.Value* = llvmlite.build_gep(parent_builder, i8_ty, closure_ptr, eight_val)
eight_val: mlirlite.Value* = mlirlite.const_int32(pool, 8)
env_slot_addr: mlirlite.Value* = mlirlite.build_gep(parent_builder, i8_ty, closure_ptr, eight_val)
if env_slot_addr is not None:
env_slot: llvmlite.Value* = llvmlite.build_bitcast(parent_builder, env_slot_addr, llvmlite.Ptr(pool, i8_ptr_ty))
env_slot: mlirlite.Value* = mlirlite.build_bitcast(parent_builder, env_slot_addr, mlirlite.Ptr(pool, i8_ptr_ty))
if env_slot is not None:
if env_ptr is not None:
llvmlite.build_store(parent_builder, env_ptr, env_slot)
mlirlite.build_store(parent_builder, env_ptr, env_slot)
else:
# 无 nonlocal 变量,存储 null
null_val: llvmlite.Value* = llvmlite.SSAValue(pool, i8_ptr_ty, "null")
llvmlite.build_store(parent_builder, null_val, env_slot)
null_val: mlirlite.Value* = mlirlite.SSAValue(pool, i8_ptr_ty, "null")
mlirlite.build_store(parent_builder, null_val, env_slot)
# 13e. 将闭包指针存储到父函数的局部变量 {func_name}
closure_alloca: llvmlite.Value* = self.Gen.VarGen._alloca_at_entry(parent_builder, i8_ptr_ty)
closure_alloca: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(parent_builder, i8_ptr_ty)
if closure_alloca is not None:
llvmlite.build_store(parent_builder, closure_ptr, closure_alloca)
mlirlite.build_store(parent_builder, closure_ptr, closure_alloca)
self.Gen.VarGen.define_var(trans.SymTab, func_name, closure_alloca)
# 注册闭包变量名(供调用时区分闭包 vs 函数指针变量,
# 两者 alloca 类型同为 i8**,_is_func_ptr_alloca 无法区分)
@@ -462,10 +462,10 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
if GenApi.is_nonlocal_name(trans, nm.id) != 0: return 1
ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id)
if ve is None or ve.Alloca is None or ve.Alloca.Ty is None: return 1
nl_ty: llvmlite.LLVMType* = ve.Alloca.Ty.Pointee
nl_ty: mlirlite.LLVMType* = ve.Alloca.Ty.Pointee
if nl_ty is None: return 1
# 模块级全局直接解析,无需 env 捕获
mod_gv: llvmlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm.id)
mod_gv: mlirlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm.id)
if mod_gv is not None:
if uint64(mod_gv) == uint64(ve.Alloca): return 1
# 外层函数局部变量 → 隐式捕获(注册为 nonlocal)
@@ -811,24 +811,24 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
# (结构体尺寸需查布局表,本函数只做 LLVMType 递归);改 fatal 会拒绝
# "nonlocal 结构体"这一合法用法,需先补布局查询能力。
def _type_byte_size(self, pool: memhub.MemBuddy*,
ty: llvmlite.LLVMType*) -> int:
ty: mlirlite.LLVMType*) -> int:
"""计算 LLVM 类型占用的字节大小(递归)"""
if ty is None:
# [S4 fail-fast] 类型缺失 → 不再保守 8 字节(分配不足会越界写邻块)
self.Gen.TypeGenErr.fatal_error(None, "nonlocal 共享存储:类型缺失,无法计算尺寸", "TypeError")
return 0
match ty:
case llvmlite.LLVMType.Int(bits):
case mlirlite.LLVMType.Int(bits):
sz_i: int = (bits + 7) // 8
if sz_i < 8: sz_i = 8
return sz_i
case llvmlite.LLVMType.Ptr(_pe):
case mlirlite.LLVMType.Ptr(_pe):
return 8
case llvmlite.LLVMType.Float(fb):
case mlirlite.LLVMType.Float(fb):
if fb == 64: return 8
if fb >= 128: return 16
return 4
case llvmlite.LLVMType.Array(et, cnt):
case mlirlite.LLVMType.Array(et, cnt):
esz: int = self._type_byte_size(pool, et)
return esz * cnt
case _:
@@ -857,30 +857,30 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
# ============================================================
def _nl_heap_global_ref(self, pool: memhub.MemBuddy*,
trans: HT.Translator*,
name: str) -> llvmlite.Value*:
name: str) -> mlirlite.Value*:
"""获取 nonlocal 堆地址全局映射变量的引用(@"..." 引号包裹)"""
if pool is None or trans is None or name is None:
return None
gname: str = self._nl_heap_global_name(pool, trans, name)
if gname is None:
return None
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
ref_buf: str = pool.alloc(176)
if ref_buf is None:
return None
viperlib.snprintf(ref_buf, 176, "@\"%s\"", gname)
return llvmlite.SSAValue(pool, llvmlite.Ptr(pool, i8_ptr_ty), ref_buf)
return mlirlite.SSAValue(pool, mlirlite.Ptr(pool, i8_ptr_ty), ref_buf)
# ============================================================
# _nl_heap_global_exists - 检查 nonlocal 堆地址全局映射变量是否存在
# ============================================================
def _nl_heap_global_exists(self, mod: llvmlite.LLVMModule*,
def _nl_heap_global_exists(self, mod: mlirlite.LLVMModule*,
gname: str) -> int:
"""检查全局映射变量 gname 是否已在模块中,1=存在"""
if mod is None or gname is None:
return 0
gcur: llvmlite.GlobalVariable* = mod.GlobalHead
gcur: mlirlite.GlobalVariable* = mod.GlobalHead
while gcur is not None:
if gcur.Name is not None and string.strcmp(gcur.Name, gname) == 0:
return 1
@@ -948,10 +948,10 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
def _prepare_chain_nonlocals(self, trans: HT.Translator*,
node: ast.AST*,
pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
i8_ty: llvmlite.LLVMType*,
i8_ptr_ty: llvmlite.LLVMType*) -> int:
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
i8_ty: mlirlite.LLVMType*,
i8_ptr_ty: mlirlite.LLVMType*) -> int:
"""预收集嵌套函数链内 nonlocal 并建堆,1 成功"""
if node is None or trans is None or builder is None or mod is None: return 0
# 每函数只预建一次:多个嵌套函数定义共享同一堆(防重复 malloc +
@@ -969,9 +969,9 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
nl_name: str = nm_slot[0]
if nl_name is None: continue
# 只在"定义它的函数"(当前顶层作用域有 alloca)中建堆
local_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, nl_name)
local_alloca: mlirlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, nl_name)
if local_alloca is None or local_alloca.Ty is None: continue
nl_ty: llvmlite.LLVMType* = local_alloca.Ty.Pointee
nl_ty: mlirlite.LLVMType* = local_alloca.Ty.Pointee
if nl_ty is None: continue
gname: str = self._nl_heap_global_name(pool, trans, nl_name)
if gname is None: continue
@@ -980,42 +980,42 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
# @nlheap.* 保持上一函数的堆地址,env 读到错堆。映射变量仅首次 add(模块去重),
# store 指令每次照发。
st_size: int = self._type_byte_size(pool, nl_ty)
st_size_val: llvmlite.Value* = llvmlite.const_int64(pool, st_size)
st_size_val: mlirlite.Value* = mlirlite.const_int64(pool, st_size)
if st_size_val is not None:
st_size_val.Next = None
var_storage: llvmlite.Value* = llvmlite.build_call(builder, "malloc", st_size_val, 1, i8_ptr_ty, 0)
var_storage: mlirlite.Value* = mlirlite.build_call(builder, "malloc", st_size_val, 1, i8_ptr_ty, 0)
if var_storage is None:
continue
cur_val: llvmlite.Value* = llvmlite.build_load(builder, nl_ty, local_alloca)
st_slot: llvmlite.Value* = llvmlite.build_bitcast(builder, var_storage, llvmlite.Ptr(pool, nl_ty))
cur_val: mlirlite.Value* = mlirlite.build_load(builder, nl_ty, local_alloca)
st_slot: mlirlite.Value* = mlirlite.build_bitcast(builder, var_storage, mlirlite.Ptr(pool, nl_ty))
if st_slot is not None and cur_val is not None:
llvmlite.build_store(builder, cur_val, st_slot)
mlirlite.build_store(builder, cur_val, st_slot)
# 重定向 VarEntry(父函数读写走共享堆)
ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nl_name)
if ve is not None:
heap_typed: llvmlite.Value* = llvmlite.build_bitcast(builder, var_storage, llvmlite.Ptr(pool, nl_ty))
heap_typed: mlirlite.Value* = mlirlite.build_bitcast(builder, var_storage, mlirlite.Ptr(pool, nl_ty))
if heap_typed is not None:
ve.Alloca = heap_typed
# 创建/复用全局映射变量并 store 堆地址(跨函数可见)
gv_found: llvmlite.GlobalVariable* = None
gcur: llvmlite.GlobalVariable* = mod.GlobalHead
gv_found: mlirlite.GlobalVariable* = None
gcur: mlirlite.GlobalVariable* = mod.GlobalHead
while gcur is not None:
if gcur.Name is not None and string.strcmp(gcur.Name, gname) == 0:
gv_found = gcur
break
gcur = gcur.Next
if gv_found is None:
gv_found = llvmlite.new_global_variable(pool, gname, i8_ptr_ty)
gv_found = mlirlite.new_global_variable(pool, gname, i8_ptr_ty)
if gv_found is not None:
# 清除 external linkage 并给零初始化,否则打印为 external
# 声明、store 引用无定义体 → 链接 undefined reference
gv_found.Linkage = None
gv_found.Initializer = "null"
llvmlite.module_add_global(mod, gv_found)
mlirlite.module_add_global(mod, gv_found)
if gv_found is not None:
gv_ref: llvmlite.Value* = self._nl_heap_global_ref(pool, trans, nl_name)
gv_ref: mlirlite.Value* = self._nl_heap_global_ref(pool, trans, nl_name)
if gv_ref is not None:
llvmlite.build_store(builder, var_storage, gv_ref)
mlirlite.build_store(builder, var_storage, gv_ref)
return 1
# ============================================================
@@ -1029,11 +1029,11 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
# 3. 创建闭包 {fn_ptr, env_ptr},返回 i8* 闭包指针
# 赋值语句据此创建 i8** alloca,调用走 translate_closure_call
# ============================================================
def translate_lambda(self, builder: llvmlite.IRBuilder*,
def translate_lambda(self, builder: mlirlite.IRBuilder*,
pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
node: ast.AST*,
trans: HT.Translator* = None) -> llvmlite.Value*:
trans: HT.Translator* = None) -> mlirlite.Value*:
"""翻译 lambda 表达式,返回闭包指针(i8*)"""
if node is None or trans is None or builder is None:
return None
@@ -1041,10 +1041,10 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
if lam is None:
return None
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i8_ptr_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ptr_ty)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
i8_ptr_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ptr_ty)
# 1. lambda id + 提升函数名
# 注意:计数器放 trans(_lambda_count)而非 self——Mixin 类自身无字段,
@@ -1080,19 +1080,19 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
if arg_n is None or arg_n.arg is None:
continue
string.strncpy(param_names + param_count * 32, arg_n.arg, 31)
p_ty: llvmlite.LLVMType* = i32_ty
p_ty: mlirlite.LLVMType* = i32_ty
if arg_n.annotation is not None:
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg_n.annotation, trans._imported_modules, trans._from_imports, trans, 0)
resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg_n.annotation, trans._imported_modules, trans._from_imports, trans, 0)
if resolved is None:
# fail-fast:lambda 参数有注解但类型解析失败,不再静默保持 i32
self.Gen.TypeGenErr.fatal_error(arg_n, f"参数 '{arg_n.arg}' 类型解析失败: {self.Gen.TypeGenResolve.annotation_to_str(arg_n.annotation)}", "NameError")
resolved = i32_ty # 不可达(fatal_error 已退出)
if resolved is not None:
match resolved:
case llvmlite.LLVMType.Struct(_, _, _):
p_ty = llvmlite.Ptr(pool, resolved)
case llvmlite.LLVMType.Array(aelem_ty_l, _):
p_ty = llvmlite.Ptr(pool, aelem_ty_l)
case mlirlite.LLVMType.Struct(_, _, _):
p_ty = mlirlite.Ptr(pool, resolved)
case mlirlite.LLVMType.Array(aelem_ty_l, _):
p_ty = mlirlite.Ptr(pool, aelem_ty_l)
case _:
p_ty = resolved
ty_slot_p: str* = str*(uint64(param_tys) + param_count * 8)
@@ -1115,28 +1115,28 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
cap_count: int = self._lambda_scan_body(trans, lam.body, param_names, param_count, cap_names, cap_allocas, cap_tys, 0)
# 4. 创建提升函数 __lambda_{id}(i8* %env, [args...])
func: llvmlite.Function* = llvmlite.create_function(pool, mod, mangled_promoted, i32_ty)
func: mlirlite.Function* = mlirlite.create_function(pool, mod, mangled_promoted, i32_ty)
if func is None: return None
llvmlite.add_param(pool, func, i8_ptr_ty, "%env")
mlirlite.add_param(pool, func, i8_ptr_ty, "%env")
for pi2 in range(param_count):
ty_addr2: uint64 = uint64(param_tys) + pi2 * 8
ty_slot2: str* = str*(ty_addr2)
p_ty2: llvmlite.LLVMType* = (llvmlite.LLVMType*)(ty_slot2[0])
p_ty2: mlirlite.LLVMType* = (mlirlite.LLVMType*)(ty_slot2[0])
if p_ty2 is None:
p_ty2 = i32_ty
pname_l: str = pool.alloc(32)
if pname_l is not None:
viperlib.snprintf(pname_l, 32, "%%%s", param_names + pi2 * 32)
llvmlite.add_param(pool, func, p_ty2, pname_l)
mlirlite.add_param(pool, func, p_ty2, pname_l)
# 5. entry 块 + builder
entry_blk: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, "entry")
entry_blk: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "entry")
if entry_blk is None:
return None
func_builder: llvmlite.IRBuilder* = llvmlite.new_builder(pool, func)
func_builder: mlirlite.IRBuilder* = mlirlite.new_builder(pool, func)
if func_builder is None:
return None
llvmlite.position_at_end(func_builder, entry_blk)
mlirlite.position_at_end(func_builder, entry_blk)
# --traceback: promoted lambda gets its own DISubprogram.
dbg_pushed_l: int = DebugInfoGen.PushFunction(pool, func_builder, func,
@@ -1146,23 +1146,23 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
self.Gen.VarGen.enter_scope(trans.SymTab, SCOPE_FUNCTION)
# 7. _env_ptr alloca(存储 %env 参数)
env_alloca: llvmlite.Value* = llvmlite.build_alloca(func_builder, i8_ptr_ty)
env_alloca: mlirlite.Value* = mlirlite.build_alloca(func_builder, i8_ptr_ty)
if env_alloca is not None:
self.Gen.VarGen.define_var(trans.SymTab, "_env_ptr", env_alloca)
env_param_val: llvmlite.Value* = llvmlite.SSAValue(pool, i8_ptr_ty, "%env")
llvmlite.build_store(func_builder, env_param_val, env_alloca)
env_param_val: mlirlite.Value* = mlirlite.SSAValue(pool, i8_ptr_ty, "%env")
mlirlite.build_store(func_builder, env_param_val, env_alloca)
# 8. 保存父函数状态并切换到提升函数
old_func: llvmlite.Function* = trans._cur_func
old_builder: llvmlite.IRBuilder* = trans._cur_builder
old_func: mlirlite.Function* = trans._cur_func
old_builder: mlirlite.IRBuilder* = trans._cur_builder
old_func_name: str = trans._cur_func_name
old_global_count: int = trans._global_name_count
old_nonlocal_count: int = trans._nonlocal_name_count
old_env_count: int = trans._closure_env_count
# break/continue 目标与 match-case 标记:新函数作用域必须清空(见下方赋值),
# 否则 lambda 体内的 break/continue 会继承外层函数的跳转目标(跨函数 br)
old_break_bb: rawptr[llvmlite.BasicBlock] = trans._break_bb
old_continue_bb: rawptr[llvmlite.BasicBlock] = trans._continue_bb
old_break_bb: rawptr[mlirlite.BasicBlock] = trans._break_bb
old_continue_bb: rawptr[mlirlite.BasicBlock] = trans._continue_bb
old_insw: int = trans._in_switch_case
trans._cur_func = func
trans._cur_builder = func_builder
@@ -1181,27 +1181,27 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
if cap_slot[0] == '\0': continue
ty_addr3: uint64 = uint64(cap_tys) + ci * 8
ty_slot3: str | t.CPtr = (str | t.CPtr)(ty_addr3)
cap_ty: llvmlite.LLVMType* = (llvmlite.LLVMType*)(ty_slot3[0])
cap_ty: mlirlite.LLVMType* = (mlirlite.LLVMType*)(ty_slot3[0])
if cap_ty is None: continue
off_val: llvmlite.Value* = llvmlite.const_int32(pool, ci * 8)
slot_addr: llvmlite.Value* = llvmlite.build_gep(func_builder, i8_ty, env_param_val, off_val)
off_val: mlirlite.Value* = mlirlite.const_int32(pool, ci * 8)
slot_addr: mlirlite.Value* = mlirlite.build_gep(func_builder, i8_ty, env_param_val, off_val)
if slot_addr is None: continue
storage_addr: llvmlite.Value* = llvmlite.build_load(func_builder, i8_ptr_ty, slot_addr)
storage_addr: mlirlite.Value* = mlirlite.build_load(func_builder, i8_ptr_ty, slot_addr)
if storage_addr is None: continue
st_typed: llvmlite.Value* = llvmlite.build_bitcast(func_builder, storage_addr, llvmlite.Ptr(pool, cap_ty))
st_typed: mlirlite.Value* = mlirlite.build_bitcast(func_builder, storage_addr, mlirlite.Ptr(pool, cap_ty))
if st_typed is None: continue
cap_val: llvmlite.Value* = llvmlite.build_load(func_builder, cap_ty, st_typed)
cap_val: mlirlite.Value* = mlirlite.build_load(func_builder, cap_ty, st_typed)
if cap_val is None: continue
var_alloca: llvmlite.Value* = llvmlite.build_alloca(func_builder, cap_ty)
var_alloca: mlirlite.Value* = mlirlite.build_alloca(func_builder, cap_ty)
if var_alloca is not None:
llvmlite.build_store(func_builder, cap_val, var_alloca)
mlirlite.build_store(func_builder, cap_val, var_alloca)
self.Gen.VarGen.define_var(trans.SymTab, cap_slot, var_alloca)
# 10. 参数 alloca
for pi3 in range(param_count):
ty_addr4: uint64 = uint64(param_tys) + pi3 * 8
ty_slot4: str | t.CPtr = (str | t.CPtr)(ty_addr4)
p_ty3: llvmlite.LLVMType* = (llvmlite.LLVMType*)(ty_slot4[0])
p_ty3: mlirlite.LLVMType* = (mlirlite.LLVMType*)(ty_slot4[0])
if p_ty3 is None:
# fail-fast:lambda 参数类型槽缺失(内部状态不一致),不再静默保持 i32
self.Gen.TypeGenErr.fatal_error(lam, f"lambda 参数 '{param_names + pi3 * 32}' 类型信息缺失", "InternalCompilerError")
@@ -1209,21 +1209,21 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
pname_ref: str = pool.alloc(32)
if pname_ref is not None:
viperlib.snprintf(pname_ref, 32, "%%%s", param_names + pi3 * 32)
param_ref: llvmlite.Value* = llvmlite.SSAValue(pool, p_ty3, pname_ref)
arg_alloca: llvmlite.Value* = llvmlite.build_alloca(func_builder, p_ty3)
param_ref: mlirlite.Value* = mlirlite.SSAValue(pool, p_ty3, pname_ref)
arg_alloca: mlirlite.Value* = mlirlite.build_alloca(func_builder, p_ty3)
if arg_alloca is not None:
llvmlite.build_store(func_builder, param_ref, arg_alloca)
mlirlite.build_store(func_builder, param_ref, arg_alloca)
self.Gen.VarGen.define_var(trans.SymTab, param_names + pi3 * 32, arg_alloca)
# 11. 翻译 body 表达式,coerce 到 i32 后 ret
body_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(func_builder, pool, mod, lam.body, None, 0, trans)
body_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(func_builder, pool, mod, lam.body, None, 0, trans)
if body_val is not None and body_val.Ty is not None:
if self.Gen.ExprGenBase.get_llvm_type_bits(body_val.Ty) == 32 and self.Gen.ExprGenBase.is_ptr_type(body_val.Ty) == 0:
llvmlite.build_ret(func_builder, body_val)
mlirlite.build_ret(func_builder, body_val)
else:
ret_val: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(func_builder, body_val, i32_ty, lam.body)
ret_val: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(func_builder, body_val, i32_ty, lam.body)
if ret_val is not None:
llvmlite.build_ret(func_builder, ret_val)
mlirlite.build_ret(func_builder, ret_val)
else:
# fail-fast:lambda 体类型转换失败,不再静默 ret 0
self.Gen.TypeGenErr.fatal_error(lam.body, "lambda 体表达式翻译失败", "TypeError")
@@ -1246,13 +1246,13 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
DebugInfoGen.PopFunction(func_builder)
# 13. 在父函数中创建 env(每个捕获变量 8 字节堆存储,env[i] = 堆地址)
env_ptr: llvmlite.Value* = None
env_ptr: mlirlite.Value* = None
if cap_count > 0:
env_size: int64 = cap_count * 8
env_size_val: llvmlite.Value* = llvmlite.const_int64(pool, env_size)
env_size_val: mlirlite.Value* = mlirlite.const_int64(pool, env_size)
if env_size_val is not None:
env_size_val.Next = None
env_ptr = llvmlite.build_call(builder, "malloc", env_size_val, 1, i8_ptr_ty, 0)
env_ptr = mlirlite.build_call(builder, "malloc", env_size_val, 1, i8_ptr_ty, 0)
if env_ptr is not None:
for ci3 in range(cap_count):
# 与步骤 9 一致:str 指针偏移判空,避免整数转换 itoa 语义
@@ -1261,69 +1261,69 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
continue
al_addr: uint64 = uint64(cap_allocas) + ci3 * 8
al_slot: str | t.CPtr = (str | t.CPtr)(al_addr)
var_alloca2: llvmlite.Value* = (llvmlite.Value*)(al_slot[0])
var_alloca2: mlirlite.Value* = (mlirlite.Value*)(al_slot[0])
if var_alloca2 is None: continue
ty_addr5: uint64 = uint64(cap_tys) + ci3 * 8
ty_slot5: str | t.CPtr = (str | t.CPtr)(ty_addr5)
cap_ty2: llvmlite.LLVMType* = (llvmlite.LLVMType*)(ty_slot5[0])
cap_ty2: mlirlite.LLVMType* = (mlirlite.LLVMType*)(ty_slot5[0])
if cap_ty2 is None: continue
# 堆存储大小:位宽/8,至少 8 字节(容纳指针/标量)
ty_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(cap_ty2)
st_size: int = 8
if ty_bits > 64:
st_size = ty_bits // 8
st_size_val: llvmlite.Value* = llvmlite.const_int64(pool, st_size)
st_size_val: mlirlite.Value* = mlirlite.const_int64(pool, st_size)
if st_size_val is not None:
st_size_val.Next = None
var_storage: llvmlite.Value* = llvmlite.build_call(builder, "malloc", st_size_val, 1, i8_ptr_ty, 0)
var_storage: mlirlite.Value* = mlirlite.build_call(builder, "malloc", st_size_val, 1, i8_ptr_ty, 0)
if var_storage is not None:
cur_val: llvmlite.Value* = llvmlite.build_load(builder, cap_ty2, var_alloca2)
cur_val: mlirlite.Value* = mlirlite.build_load(builder, cap_ty2, var_alloca2)
if cur_val is not None:
st_slot5: llvmlite.Value* = llvmlite.build_bitcast(builder, var_storage, llvmlite.Ptr(pool, cap_ty2))
st_slot5: mlirlite.Value* = mlirlite.build_bitcast(builder, var_storage, mlirlite.Ptr(pool, cap_ty2))
if st_slot5 is not None:
llvmlite.build_store(builder, cur_val, st_slot5)
off_val2: llvmlite.Value* = llvmlite.const_int32(pool, ci3 * 8)
slot2: llvmlite.Value* = llvmlite.build_gep(builder, i8_ty, env_ptr, off_val2)
mlirlite.build_store(builder, cur_val, st_slot5)
off_val2: mlirlite.Value* = mlirlite.const_int32(pool, ci3 * 8)
slot2: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, env_ptr, off_val2)
if slot2 is not None:
slot_typed2: llvmlite.Value* = llvmlite.build_bitcast(builder, slot2, i8_ptr_ptr_ty)
slot_typed2: mlirlite.Value* = mlirlite.build_bitcast(builder, slot2, i8_ptr_ptr_ty)
if slot_typed2 is not None:
llvmlite.build_store(builder, var_storage, slot_typed2)
mlirlite.build_store(builder, var_storage, slot_typed2)
# 14. 在父函数中创建闭包 malloc(16)
closure_size_val: llvmlite.Value* = llvmlite.const_int64(pool, 16)
closure_size_val: mlirlite.Value* = mlirlite.const_int64(pool, 16)
if closure_size_val is not None:
closure_size_val.Next = None
closure_ptr: llvmlite.Value* = llvmlite.build_call(builder, "malloc", closure_size_val, 1, i8_ptr_ty, 0)
closure_ptr: mlirlite.Value* = mlirlite.build_call(builder, "malloc", closure_size_val, 1, i8_ptr_ty, 0)
if closure_ptr is None:
return None
# 15. [0] = fn_ptr(函数引用 bitcast 到 i8*)
fn_param_node: llvmlite.ParamNode* = llvmlite.new_param_node(pool, i8_ptr_ty)
fn_func_ty: llvmlite.LLVMType* = llvmlite.Func(pool, i32_ty, fn_param_node, 1)
fn_func_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, fn_func_ty)
fn_param_node: mlirlite.ParamNode* = mlirlite.new_param_node(pool, i8_ptr_ty)
fn_func_ty: mlirlite.LLVMType* = mlirlite.Func(pool, i32_ty, fn_param_node, 1)
fn_func_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, fn_func_ty)
fn_ptr_name: str = pool.alloc(64)
if fn_ptr_name is not None:
if string.strchr(mangled_promoted, '.') is not None:
viperlib.snprintf(fn_ptr_name, 64, "@\"%s\"", mangled_promoted)
else:
viperlib.snprintf(fn_ptr_name, 64, "@%s", mangled_promoted)
fn_ptr_val: llvmlite.Value* = llvmlite.SSAValue(pool, fn_func_ptr_ty, fn_ptr_name)
fn_as_i8ptr: llvmlite.Value* = llvmlite.build_bitcast(builder, fn_ptr_val, i8_ptr_ty)
fn_slot: llvmlite.Value* = llvmlite.build_bitcast(builder, closure_ptr, llvmlite.Ptr(pool, i8_ptr_ty))
fn_ptr_val: mlirlite.Value* = mlirlite.SSAValue(pool, fn_func_ptr_ty, fn_ptr_name)
fn_as_i8ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, fn_ptr_val, i8_ptr_ty)
fn_slot: mlirlite.Value* = mlirlite.build_bitcast(builder, closure_ptr, mlirlite.Ptr(pool, i8_ptr_ty))
if fn_slot is not None and fn_as_i8ptr is not None:
llvmlite.build_store(builder, fn_as_i8ptr, fn_slot)
mlirlite.build_store(builder, fn_as_i8ptr, fn_slot)
# 16. [8] = env_ptr(无捕获存 null)
eight_val: llvmlite.Value* = llvmlite.const_int32(pool, 8)
env_slot_addr: llvmlite.Value* = llvmlite.build_gep(builder, i8_ty, closure_ptr, eight_val)
eight_val: mlirlite.Value* = mlirlite.const_int32(pool, 8)
env_slot_addr: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, closure_ptr, eight_val)
if env_slot_addr is not None:
env_slot: llvmlite.Value* = llvmlite.build_bitcast(builder, env_slot_addr, llvmlite.Ptr(pool, i8_ptr_ty))
env_slot: mlirlite.Value* = mlirlite.build_bitcast(builder, env_slot_addr, mlirlite.Ptr(pool, i8_ptr_ty))
if env_slot is not None:
if env_ptr is not None:
llvmlite.build_store(builder, env_ptr, env_slot)
mlirlite.build_store(builder, env_ptr, env_slot)
else:
null_val: llvmlite.Value* = llvmlite.SSAValue(pool, i8_ptr_ty, "null")
llvmlite.build_store(builder, null_val, env_slot)
null_val: mlirlite.Value* = mlirlite.SSAValue(pool, i8_ptr_ty, "null")
mlirlite.build_store(builder, null_val, env_slot)
# 17. 返回闭包指针(i8*)
return closure_ptr
@@ -1360,14 +1360,14 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
if string.strcmp(cap_names + ci * 64, nm.id) == 0:
return cap_count
# 查当前作用域链
alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
if alloca is None or alloca.Ty is None:
return cap_count
pointee: llvmlite.LLVMType* = alloca.Ty.Pointee
pointee: mlirlite.LLVMType* = alloca.Ty.Pointee
if pointee is None:
return cap_count
# 跳过模块级全局(body 直接解析全局,无需 env 捕获)
mod_gv: llvmlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm.id)
mod_gv: mlirlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm.id)
if mod_gv is not None:
if uint64(mod_gv) == uint64(alloca):
return cap_count
+19 -19
View File
@@ -1,7 +1,7 @@
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdlib
@@ -118,7 +118,7 @@ def fatal_error(node: ast.AST*, msg: str,
# ---------------- map_t_type(委托 TypeGenResolve.map_t_type) ----------------
def map_t_type(pool: memhub.MemBuddy*, type_name: str) -> llvmlite.LLVMType*:
def map_t_type(pool: memhub.MemBuddy*, type_name: str) -> mlirlite.LLVMType*:
"""委托到 gen.map_t_type(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.TypeGenResolve.map_t_type(pool, type_name)
@@ -130,7 +130,7 @@ def resolve_typedef_or_map(pool: memhub.MemBuddy*,
name: str,
imported_modules: str,
from_imports: str,
trans: HT.Translator* = None) -> llvmlite.LLVMType*:
trans: HT.Translator* = None) -> mlirlite.LLVMType*:
"""委托到 gen.resolve_typedef_or_map(CTypedef 动态表优先,miss 回退 map_t_type)"""
if _g_gen is not None:
return _g_gen.TypeGenResolve.resolve_typedef_or_map(pool, name, imported_modules, from_imports, trans)
@@ -139,7 +139,7 @@ def resolve_typedef_or_map(pool: memhub.MemBuddy*,
# ---------------- infer_external_func_ret_ty(委托 CallGenLib._infer_external_func_ret_ty) ----------------
def infer_external_func_ret_ty(pool: memhub.MemBuddy*,
func_name: str) -> llvmlite.LLVMType*:
func_name: str) -> mlirlite.LLVMType*:
"""委托到 gen.CallGenLib._infer_external_func_ret_ty(外部函数返回类型白名单)
vpi 注入 extern declare 时返回类型解析 miss 的兜底:FindFirstFileA/
@@ -170,7 +170,7 @@ def _is_ctypedef_annotation(annotation: ast.AST*) -> int:
# ---------------- resolve_annotation_type(委托 TypeGenResolve.resolve_annotation_type) ----------------
def resolve_annotation_type(pool: memhub.MemBuddy*, node: ast.AST*, imported_modules: str, from_imports: str, trans: HT.Translator* = None, depth: int = 0) -> llvmlite.LLVMType*:
def resolve_annotation_type(pool: memhub.MemBuddy*, node: ast.AST*, imported_modules: str, from_imports: str, trans: HT.Translator* = None, depth: int = 0) -> mlirlite.LLVMType*:
"""委托到 gen.resolve_annotation_type(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.TypeGenResolve.resolve_annotation_type(pool, node, imported_modules, from_imports, trans, depth)
@@ -302,7 +302,7 @@ def reset_module_methods_emitted(sha1: str) -> int:
# ---------------- get_struct_type(委托 StructGenMixin.get_struct_type) ----------------
def get_struct_type(class_name: str) -> llvmlite.LLVMType*:
def get_struct_type(class_name: str) -> mlirlite.LLVMType*:
"""委托到 gen.get_struct_type(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.StructGen.get_struct_type(class_name)
@@ -310,7 +310,7 @@ def get_struct_type(class_name: str) -> llvmlite.LLVMType*:
# ---------------- get_enum_base_type(委托 StmtGenDeclMixin.get_enum_base_type) ----------------
def get_enum_base_type(enum_name: str) -> llvmlite.LLVMType*:
def get_enum_base_type(enum_name: str) -> mlirlite.LLVMType*:
"""委托到 gen.get_enum_base_type(原 Handles 壳)
枚举(t.CEnum)注册在独立的 EnumTable(EnumEntry),不进 StructTable,
@@ -377,7 +377,7 @@ def is_file_func(name: str) -> int:
# ---------------- find_struct_by_type(委托 StructGenMixin.find_struct_by_type) ----------------
def find_struct_by_type(struct_ty: llvmlite.LLVMType*) -> GenTypes.StructEntry*:
def find_struct_by_type(struct_ty: mlirlite.LLVMType*) -> GenTypes.StructEntry*:
"""委托到 gen.find_struct_by_type(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.StructGen.find_struct_by_type(struct_ty)
@@ -387,7 +387,7 @@ def find_struct_by_type(struct_ty: llvmlite.LLVMType*) -> GenTypes.StructEntry*:
# ---------------- register_struct(委托 StructGenMixin.register_struct) ----------------
def register_struct(pool: memhub.MemBuddy*,
name: str,
struct_ty: llvmlite.LLVMType*,
struct_ty: mlirlite.LLVMType*,
sha1: str = None) -> GenTypes.StructEntry*:
"""委托到 gen.register_struct(原 Handles 壳)"""
if _g_gen is not None:
@@ -399,7 +399,7 @@ def register_struct(pool: memhub.MemBuddy*,
def add_field(pool: memhub.MemBuddy*,
struct_entry: GenTypes.StructEntry*,
field_name: str,
field_ty: llvmlite.LLVMType*) -> int:
field_ty: mlirlite.LLVMType*) -> int:
"""委托到 gen.add_field(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.StructGen.add_field(pool, struct_entry, field_name, field_ty)
@@ -625,7 +625,7 @@ def escape_fstring_copy(src: str) -> str:
# ---------------- create_wrapper_main(委托 TranslatorGenMixin.create_wrapper_main) ----------------
def create_wrapper_main(trans: HT.Translator*, tree: ast.AST*, i32_ty: llvmlite.LLVMType*) -> int:
def create_wrapper_main(trans: HT.Translator*, tree: ast.AST*, i32_ty: mlirlite.LLVMType*) -> int:
"""委托到 gen.create_wrapper_main(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.TranslatorGen.create_wrapper_main(trans, tree, i32_ty)
@@ -664,7 +664,7 @@ def SetTempDir(temp_dir: str):
# ---------------- find_func_in_module(委托 CallGenBase.find_func_in_module) ----------------
def find_func_in_module(mod: llvmlite.LLVMModule*, name: str) -> llvmlite.Function*:
def find_func_in_module(mod: mlirlite.LLVMModule*, name: str) -> mlirlite.Function*:
"""委托到 gen.find_func_in_module(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.CallGenBase.find_func_in_module(mod, name)
@@ -672,7 +672,7 @@ def find_func_in_module(mod: llvmlite.LLVMModule*, name: str) -> llvmlite.Functi
# ---------------- add_func_to_table(委托 CallGenLeafKit.add_func_to_table) ----------------
def add_func_to_table(funcs: GenTypes.FuncEntry*, func_count: int, name: str, func: llvmlite.Function*, max_count: int, defaults: t.CPtr = None, default_count: int = 0, param_count: int = 0, pool: memhub.MemBuddy* = None, def_sha1: str = None) -> int:
def add_func_to_table(funcs: GenTypes.FuncEntry*, func_count: int, name: str, func: mlirlite.Function*, max_count: int, defaults: t.CPtr = None, default_count: int = 0, param_count: int = 0, pool: memhub.MemBuddy* = None, def_sha1: str = None) -> int:
"""委托到 gen.add_func_to_table(原 Handles 壳)
def_sha1:定义该函数的模块 SHA1(依赖注入路径必须传,避免默认值被挂到导入方名下)
@@ -691,7 +691,7 @@ def init_func_table(pool: memhub.MemBuddy*, max_count: int) -> GenTypes.FuncEntr
# ---------------- translate_call(委托 CallGenMixin.translate_call) ----------------
def translate_call(pool: memhub.MemBuddy*, builder: llvmlite.IRBuilder*, mod: llvmlite.LLVMModule*, node: ast.AST*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator* = None) -> llvmlite.Value*:
def translate_call(pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, node: ast.AST*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator* = None) -> mlirlite.Value*:
"""委托到 gen.translate_call(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.CallGen.translate_call(pool, builder, mod, node, funcs_ptr, func_count, trans)
@@ -699,14 +699,14 @@ def translate_call(pool: memhub.MemBuddy*, builder: llvmlite.IRBuilder*, mod: ll
# ---------------- translate_printf_call(委托 CallGenLeafKit.translate_printf_call) ----------------
def translate_printf_call(pool: memhub.MemBuddy*, builder: llvmlite.IRBuilder*, mod: llvmlite.LLVMModule*, cl: ast.Call*, trans: HT.Translator* = None):
def translate_printf_call(pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, trans: HT.Translator* = None):
"""委托到 gen.translate_printf_call(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.CallGenLeafKit.translate_printf_call(pool, builder, mod, cl, trans)
# ---------------- translate_print_call(委托 CallGenLeafKit.translate_print_call) ----------------
def translate_print_call(pool: memhub.MemBuddy*, builder: llvmlite.IRBuilder*, mod: llvmlite.LLVMModule*, cl: ast.Call*, trans: HT.Translator* = None):
def translate_print_call(pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, trans: HT.Translator* = None):
"""委托到 gen.translate_print_call(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.CallGenLeafKit.translate_print_call(pool, builder, mod, cl, trans)
@@ -729,7 +729,7 @@ def is_global_name(trans: HT.Translator*, name: str) -> int:
# ---------------- add_nonlocal_name(委托 TranslatorGenMixin.add_nonlocal_name) ----------------
def add_nonlocal_name(trans: HT.Translator*, name: str,
var_ty: llvmlite.LLVMType* = None):
var_ty: mlirlite.LLVMType* = None):
"""委托到 gen.TranslatorGen.add_nonlocal_name(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.TranslatorGen.add_nonlocal_name(trans, name, var_ty)
@@ -737,7 +737,7 @@ def add_nonlocal_name(trans: HT.Translator*, name: str,
# ---------------- get_nonlocal_type(委托 TranslatorGenMixin.get_nonlocal_type) ----------------
def get_nonlocal_type(trans: HT.Translator*,
name: str) -> llvmlite.LLVMType*:
name: str) -> mlirlite.LLVMType*:
"""委托到 gen.TranslatorGen.get_nonlocal_type(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.TranslatorGen.get_nonlocal_type(trans, name)
@@ -769,7 +769,7 @@ def clear_scope_names(trans: HT.Translator*):
# ---------------- update_global_func_spec(委托 CallGenLeafKit.update_global_func_spec) ----------------
def update_global_func_spec(name: str,
func: llvmlite.Function*) -> int:
func: mlirlite.Function*) -> int:
"""委托到 gen.CallGenLeafKit.update_global_func_spec(原 ExprCallTable 壳)"""
if _g_gen is not None:
return _g_gen.CallGenLeafKit.update_global_func_spec(name, func)
+8 -8
View File
@@ -1,7 +1,7 @@
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
# TypeSpec:统一类型描述符(Debugger/_Type.md 第 6 节设计)。
# 别名用 TSpec:模块内类名同为 TypeSpec,别名同名会被解析器误判为类静态方法。
@@ -63,7 +63,7 @@ class TraceFrame:
class VarEntry:
"""变量表条目"""
Name: str
Alloca: llvmlite.Value*
Alloca: mlirlite.Value*
Used: int
# TypeSpec(S3 起为**唯一类型承载**):由 add_var 用 SpecFromLLVMType 从
# alloca.Ty 的 pointee 填充(PermPool 分配 ⇒ 跨文件安全),注解侧再由
@@ -117,7 +117,7 @@ novirtual class SymbolTable:
class FieldEntry:
Name: str # 字段名(字符串)
Index: int # 字段在结构体中的索引
Ty: llvmlite.LLVMType* # 字段的 LLVM 类型
Ty: mlirlite.LLVMType* # 字段的 LLVM 类型
DefaultVal: ast.AST* # 默认值 AST 节点(None=无默认值)
# TypeSpec(S3 起为**唯一类型承载**):由 add_field 用 SpecFromLLVMType 从
# field_ty 填充(PermPool 分配 ⇒ 跨 1b reset 安全,无需 DeepCopyType),
@@ -145,7 +145,7 @@ class FieldEntry:
# ============================================================
novirtual class StructEntry:
Name: str # 类名
Ty: llvmlite.LLVMType* # LLVM StructType
Ty: mlirlite.LLVMType* # LLVM StructType
FieldCount: int # 字段数量
Fields: FieldEntry | t.CPtr # 字段数组(FIELD_MAX 个槽位)
IsUnion: int # 1=联合体 / 0=普通结构体
@@ -178,7 +178,7 @@ novirtual class StructEntry:
class EnumMember:
Name: str # 成员名(字符串)
Value: int64 # 成员的整数值
Ty: llvmlite.LLVMType* # 成员的 LLVM 类型(用于混用类型场景)
Ty: mlirlite.LLVMType* # 成员的 LLVM 类型(用于混用类型场景)
# ============================================================
@@ -186,7 +186,7 @@ class EnumMember:
# ============================================================
novirtual class EnumEntry:
Name: str # 枚举类名
BaseTy: llvmlite.LLVMType* # 基准类型(所有成员类型中最大的)
BaseTy: mlirlite.LLVMType* # 基准类型(所有成员类型中最大的)
MemberCount: int # 成员数量
Members: EnumMember | t.CPtr # 成员数组(ENUM_MEMBER_MAX 个槽位)
@@ -196,7 +196,7 @@ novirtual class EnumEntry:
# ============================================================
class AsmOperand:
"""内联汇编操作数条目"""
Value: llvmlite.Value* # 输入值或输出 alloca
Value: mlirlite.Value* # 输入值或输出 alloca
Constraint: str # 约束字符串 (如 "r", "=r")
IsOutput: int # 1=输出, 0=输入
@@ -207,7 +207,7 @@ class AsmOperand:
novirtual class FuncEntry:
"""函数表条目"""
Name: str
Func: llvmlite.Function*
Func: mlirlite.Function*
Defaults: t.CPtr # defaults 列表节点指针 (list[AST | CPtr]),None=无默认值
DefaultCount: int # 默认值数量
ParamCount: int # 形参数量(不含 self)
+1 -1
View File
@@ -5,7 +5,7 @@ from stdint import *
import stdio
import stdlib
import memhub
import llvmlite
import mlirlite
import lib.core.Gen.BaseGenMixin as BaseGenMixin
import lib.core.Gen.Type.TypeGenBase as TypeGenBase
import lib.core.Gen.Type.TypeGenMixin as TypeGenMixin
+5 -5
View File
@@ -542,7 +542,7 @@ novirtual class ImportsGenMixin:
#
# Args:
# pool: 内存池
# current_package: 当前文件所属包名(如 "llvmlite"),None 表示无包
# current_package: 当前文件所属包名(如 "mlirlite"),None 表示无包
# level: 相对导入级别(0=绝对,1=., 2=..)
# module: ImportFrom 的 module 字段(可能为 None)
#
@@ -618,8 +618,8 @@ novirtual class ImportsGenMixin:
# 对于顶级文件(无目录分隔符),返回 None
#
# 示例:
# "llvmlite/__init__.vp" → "llvmlite"
# "llvmlite/__types.vp" → "llvmlite"
# "mlirlite/__init__.vp" → "mlirlite"
# "mlirlite/__types.vp" → "mlirlite"
# "ast/parser.vp" → "ast"
# "ast.vp" → None(顶级文件)
# ============================================================
@@ -849,7 +849,7 @@ novirtual class ImportsGenMixin:
# (迁移自 HandlesImports.ImportsHandle.HandleImportFromModule)
#
# 对相对导入(level > 0),使用 trans.CurrentPackage 解析为
# 完整模块名(如 __types → llvmlite.__types),确保 .deps.txt
# 完整模块名(如 __types → mlirlite.__types),确保 .deps.txt
# 记录的模块名与 SHA1 映射表一致。
# ============================================================
def translate_import_from_module(self, trans: HT.Translator*,
@@ -906,7 +906,7 @@ novirtual class ImportsGenMixin:
# (迁移自 HandlesImports.ImportsHandle.HandleImportFromNames)
#
# 同样使用解析后的完整模块名,确保 from-import 映射
# (如 LLVMType:llvmlite.__types)能正确查到 SHA1。
# (如 LLVMType:mlirlite.__types)能正确查到 SHA1。
# ============================================================
# _CheckStaticFromImport - static 符号 from-import 拦截
#
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+54 -54
View File
@@ -2,7 +2,7 @@ import lib.core.Gen.GenTypes as GenTypes
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdlib
@@ -70,8 +70,8 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
nm: ast.Name* = ast.Name*(nm_node)
if nm.id is not None:
# 查找父作用域中的变量 alloca,获取类型信息
var_ty: llvmlite.LLVMType* = None
var_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
var_ty: mlirlite.LLVMType* = None
var_alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
if var_alloca is not None and var_alloca.Ty is not None:
var_ty = var_alloca.Ty.Pointee
# Void 类型视为无效(Pointee 访问异常时可能返回 Void),
@@ -79,7 +79,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
# "bitcast ... to void*" / "load void, void*" 非法 IR
if var_ty is not None:
match var_ty:
case llvmlite.LLVMType.Void():
case mlirlite.LLVMType.Void():
self.Gen.TypeGenErr.fatal_error(nm_node, f"nonlocal 变量 '{nm.id}' 类型无效(Void/无法解析)", "TypeError")
case _:
pass
@@ -137,10 +137,10 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
sfn_ent: rawptr[GenTypes.ReplFuncEntry] = \
self.Gen.VarGen.repl_find_func_entry(trans.ReplCtx, func_name)
if sfn_ent is not None and sfn_ent.RetTag != GenTypes.REPL_TY_VOID:
sfn_v: llvmlite.Value* = self.Gen.CallGen.translate_call(trans.Pool, trans._cur_builder, trans.Module, call_node,
sfn_v: mlirlite.Value* = self.Gen.CallGen.translate_call(trans.Pool, trans._cur_builder, trans.Module, call_node,
trans._funcs, trans._func_count, trans)
if sfn_v is not None:
ctx_v: llvmlite.Value* = self.Gen.VarGen.repl_ctx_ptr(trans, trans.ReplCtx, call_node)
ctx_v: mlirlite.Value* = self.Gen.VarGen.repl_ctx_ptr(trans, trans.ReplCtx, call_node)
if ctx_v is not None:
self.Gen.VarGen.repl_emit_result(trans, ctx_v, sfn_v, sfn_ent.RetTag, sfn_ent.RetBits,
call_node)
@@ -259,8 +259,8 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
def translate_break(self, trans: HT.Translator*, node: ast.AST*) -> int:
"""翻译 break 语句:跳转到 break 目标(循环 end / match end)"""
builder: llvmlite.IRBuilder* = trans._cur_builder
func: llvmlite.Function* = trans._cur_func
builder: mlirlite.IRBuilder* = trans._cur_builder
func: mlirlite.Function* = trans._cur_func
pool: memhub.MemBuddy* = trans.Pool
if builder is None or func is None:
@@ -271,16 +271,16 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
# fail-fast:没有循环 / switch / match 时 break 无处可跳,禁止静默无效果
self.Gen.TypeGenErr.fatal_error(node,
"break 只能用在循环或 switch/match 的 case 体内(当前没有可跳出的目标)", "SyntaxError")
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
llvmlite.build_br(builder, trans._break_bb)
if mlirlite.builder_cur_block_is_terminated(builder) == 0:
mlirlite.build_br(builder, trans._break_bb)
# 创建死代码 BB,用于后续语句(break 后面的代码不可达)
cnt: int = trans._label_counter
trans._label_counter = cnt + 1
name_buf: str = pool.alloc(32)
viperlib.snprintf(name_buf, 32, "dead.%d", cnt)
dead_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, name_buf)
llvmlite.position_at_end(builder, dead_bb)
dead_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
mlirlite.position_at_end(builder, dead_bb)
return 0
def translate_fallthrough(self, trans: HT.Translator*, node: ast.AST*) -> int:
@@ -301,8 +301,8 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
def translate_continue(self, trans: HT.Translator*, node: ast.AST*) -> int:
"""翻译 continue 语句:跳转到循环 cond/incr 块"""
builder: llvmlite.IRBuilder* = trans._cur_builder
func: llvmlite.Function* = trans._cur_func
builder: mlirlite.IRBuilder* = trans._cur_builder
func: mlirlite.Function* = trans._cur_func
pool: memhub.MemBuddy* = trans.Pool
if builder is None or func is None:
@@ -313,16 +313,16 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
# fail-fast:循环之外的 continue 无处可跳,禁止静默无效果
self.Gen.TypeGenErr.fatal_error(node,
"continue 只能用在循环体内(当前没有可继续的循环)", "SyntaxError")
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
llvmlite.build_br(builder, trans._continue_bb)
if mlirlite.builder_cur_block_is_terminated(builder) == 0:
mlirlite.build_br(builder, trans._continue_bb)
# 创建死代码 BB,用于后续语句
cnt: int = trans._label_counter
trans._label_counter = cnt + 1
name_buf: str = pool.alloc(32)
viperlib.snprintf(name_buf, 32, "dead.%d", cnt)
dead_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, name_buf)
llvmlite.position_at_end(builder, dead_bb)
dead_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
mlirlite.position_at_end(builder, dead_bb)
return 0
def get_stmt_kind_name(self, node: ast.AST*) -> str:
@@ -335,34 +335,34 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
# 簇 D:nonlocal/闭包 env 访问(迁移自 HandlesNonlocal.vp)
# ============================================================
def _is_void_type(self, ty: llvmlite.LLVMType*) -> int:
def _is_void_type(self, ty: mlirlite.LLVMType*) -> int:
"""判断是否为 Void 类型,是则返回 1,否则 0"""
if ty is None:
return 0
match ty:
case llvmlite.LLVMType.Void():
case mlirlite.LLVMType.Void():
return 1
case _:
return 0
def get_env_ptr_var(self, trans: HT.Translator*) -> llvmlite.Value*:
def get_env_ptr_var(self, trans: HT.Translator*) -> mlirlite.Value*:
"""获取或创建 _env_ptr 变量(存储闭包 env 指针)"""
env_var: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, "_env_ptr")
env_var: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, "_env_ptr")
if env_var is not None:
return env_var
# 创建 alloca 存储 env
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
alloca: llvmlite.Value* = llvmlite.build_alloca(builder, i8_ptr_ty)
builder: mlirlite.IRBuilder* = trans._cur_builder
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
alloca: mlirlite.Value* = mlirlite.build_alloca(builder, i8_ptr_ty)
if alloca is None:
return None
self.Gen.VarGen.define_var(trans.SymTab, "_env_ptr", alloca)
return alloca
def _load_raw_var_ptr(self, trans: HT.Translator*,
name: str) -> llvmlite.Value*:
name: str) -> mlirlite.Value*:
"""从闭包 env 加载 nonlocal 变量的原始指针(i8*)
返回 i8* 类型的 Value,调用方需 bitcast 为具体类型指针后 load/store。
@@ -372,79 +372,79 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
return None
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i8_ptr_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ptr_ty)
builder: mlirlite.IRBuilder* = trans._cur_builder
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
i8_ptr_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ptr_ty)
# 1. 加载 env_ptr
env_alloca: llvmlite.Value* = self.get_env_ptr_var(trans)
env_alloca: mlirlite.Value* = self.get_env_ptr_var(trans)
if env_alloca is None:
return None
env_ptr: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty, env_alloca)
env_ptr: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty, env_alloca)
if env_ptr is None:
return None
# 2. GEP to offset (idx * 8) — env 存储指针数组,每槽 8 字节
offset_val: llvmlite.Value* = llvmlite.const_int32(pool, idx * 8)
addr: llvmlite.Value* = llvmlite.build_gep(builder, i8_ty, env_ptr, offset_val)
offset_val: mlirlite.Value* = mlirlite.const_int32(pool, idx * 8)
addr: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, env_ptr, offset_val)
if addr is None:
return None
# 3. Bitcast to i8** and load the raw pointer
ptr_addr: llvmlite.Value* = llvmlite.build_bitcast(builder, addr, i8_ptr_ptr_ty)
ptr_addr: mlirlite.Value* = mlirlite.build_bitcast(builder, addr, i8_ptr_ptr_ty)
if ptr_addr is None:
return None
return llvmlite.build_load(builder, i8_ptr_ty, ptr_addr)
return mlirlite.build_load(builder, i8_ptr_ty, ptr_addr)
def load_nonlocal_var(self, trans: HT.Translator*,
name: str) -> llvmlite.Value*:
name: str) -> mlirlite.Value*:
"""从闭包 env 加载 nonlocal 变量值
通过 HT.get_nonlocal_type 获取变量类型,bitcast 原始指针后 load。
"""
raw_ptr: llvmlite.Value* = self._load_raw_var_ptr(trans, name)
raw_ptr: mlirlite.Value* = self._load_raw_var_ptr(trans, name)
if raw_ptr is None:
return None
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
builder: mlirlite.IRBuilder* = trans._cur_builder
# 获取变量类型(从注册时存储的类型信息)
var_ty: llvmlite.LLVMType* = GenApi.get_nonlocal_type(trans, name)
var_ty: mlirlite.LLVMType* = GenApi.get_nonlocal_type(trans, name)
if var_ty is None or self._is_void_type(var_ty) != 0:
# 类型缺失/无效直接报错终止(fail-fast),避免生成 "load void, void*" 非法 IR
self.Gen.TypeGenErr.fatal_error(None, f"nonlocal 变量 '{name}' 类型缺失,无法 load", "TypeError")
# bitcast raw i8* to var_ty*
var_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, var_ty)
var_ptr: llvmlite.Value* = llvmlite.build_bitcast(builder, raw_ptr, var_ptr_ty)
var_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, var_ty)
var_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, raw_ptr, var_ptr_ty)
if var_ptr is None:
return None
return llvmlite.build_load(builder, var_ty, var_ptr)
return mlirlite.build_load(builder, var_ty, var_ptr)
def get_nonlocal_var_ptr(self, trans: HT.Translator*,
name: str) -> llvmlite.Value*:
name: str) -> mlirlite.Value*:
"""获取 nonlocal 变量的存储指针(var_ty*),用于 store 操作
返回的指针指向父函数的 alloca,store 操作对父函数可见。
"""
raw_ptr: llvmlite.Value* = self._load_raw_var_ptr(trans, name)
raw_ptr: mlirlite.Value* = self._load_raw_var_ptr(trans, name)
if raw_ptr is None:
return None
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
builder: mlirlite.IRBuilder* = trans._cur_builder
# 获取变量类型
var_ty: llvmlite.LLVMType* = GenApi.get_nonlocal_type(trans, name)
var_ty: mlirlite.LLVMType* = GenApi.get_nonlocal_type(trans, name)
if var_ty is None or self._is_void_type(var_ty) != 0:
# 类型缺失/无效直接报错终止(fail-fast),避免生成 "bitcast ... to void*" 非法 IR
self.Gen.TypeGenErr.fatal_error(None, f"nonlocal 变量 '{name}' 类型缺失,无法 load", "TypeError")
# bitcast raw i8* to var_ty*
var_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, var_ty)
return llvmlite.build_bitcast(builder, raw_ptr, var_ptr_ty)
var_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, var_ty)
return mlirlite.build_bitcast(builder, raw_ptr, var_ptr_ty)
# ============================================================
# 簇 E:枚举注册表(迁移自 HandlesEnum.vp)
@@ -487,7 +487,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
def register_enum(self, pool: memhub.MemBuddy*,
name: str,
base_ty: llvmlite.LLVMType*) -> rawptr[GenTypes.EnumEntry]:
base_ty: mlirlite.LLVMType*) -> rawptr[GenTypes.EnumEntry]:
"""注册枚举类型,返回 EnumEntry 指针"""
if self.init_enum_table(pool) == 0:
return None
@@ -525,7 +525,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
# 注意:StdlibAlloc 是 StructGenMixin 字段,本 Mixin 方法体不能直接 self.StdlibAlloc
# (NoVTable 按本 Mixin 字段布局编译),走模块级委托。
if self.Gen.StructGen.get_stdlib_alloc() != 0:
base_ty_copy: llvmlite.LLVMType* = llvmlite.DeepCopyType(CompilerFactory.factory.PermPool, base_ty)
base_ty_copy: mlirlite.LLVMType* = mlirlite.DeepCopyType(CompilerFactory.factory.PermPool, base_ty)
if base_ty_copy is not None:
entry.BaseTy = base_ty_copy
else:
@@ -541,7 +541,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
enum_entry: rawptr[GenTypes.EnumEntry],
member_name: str,
member_val: int64,
member_ty: llvmlite.LLVMType*) -> int:
member_ty: mlirlite.LLVMType*) -> int:
"""向枚举添加成员,返回成员索引(-1 失败)"""
if enum_entry is None or member_name is None or member_ty is None:
return -1
@@ -610,7 +610,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
return 1
return 0
def get_enum_base_type(self, enum_name: str) -> llvmlite.LLVMType*:
def get_enum_base_type(self, enum_name: str) -> mlirlite.LLVMType*:
"""按枚举类名获取基准类型"""
entry: rawptr[GenTypes.EnumEntry] = self.find_enum(enum_name)
if entry is not None:
+127 -127
View File
@@ -4,7 +4,7 @@ import lib.core.Gen.Call.CallGenFd as CallGenFd
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdlib
@@ -115,8 +115,8 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
if dnode is None or dnode.targets is None:
return 0
pool: memhub.MemBuddy* = trans.Pool
mod: llvmlite.LLVMModule* = trans.Module
builder: llvmlite.IRBuilder* = trans._cur_builder
mod: mlirlite.LLVMModule* = trans.Module
builder: mlirlite.IRBuilder* = trans._cur_builder
if pool is None or mod is None or builder is None:
return 0
tn: sizet = len(dnode.targets)
@@ -127,9 +127,9 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
# del obj → __delete__(对齐 TPC HandlesDelete.py:Name 目标调用 __delete__,
# 类未定义 __delete__ 时静默无操作)
if tgt.kind() == ast.ASTKind.Name:
del_obj: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, tgt, None, 0, trans)
del_obj: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, tgt, None, 0, trans)
if del_obj is not None:
del_st_nm: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(del_obj)
del_st_nm: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(del_obj)
if del_st_nm is not None:
del_cls_nm: str = self.Gen.StructGen.get_class_name_by_type(pool, del_st_nm)
if del_cls_nm is not None:
@@ -140,7 +140,7 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
if del_at is not None:
del_prop: int = self.Gen.CallGenProp._try_property_deleter(pool, builder, mod, del_at, trans)
if del_prop == 0:
del_av: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, del_at, None, 0, trans)
del_av: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, del_at, None, 0, trans)
if del_av is not None:
self.Gen.ExprGenOps._try_named_dunder(pool, builder, mod, del_av, "__del__", trans)
# del obj[key] → __delitem__(obj, key)(对齐 TPC HandlesDelete.py)。
@@ -148,33 +148,33 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
elif tgt.kind() == ast.ASTKind.Subscript:
dl_sub: ast.Subscript* = ast.Subscript*(tgt)
if dl_sub is not None and dl_sub.value is not None and dl_sub.slice is not None:
dl_obj: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, dl_sub.value, None, 0, trans)
dl_idx: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, dl_sub.slice, None, 0, trans)
dl_obj: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, dl_sub.value, None, 0, trans)
dl_idx: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, dl_sub.slice, None, 0, trans)
if dl_obj is not None and dl_idx is not None:
dl_st: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(dl_obj)
dl_st: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(dl_obj)
if dl_st is not None:
dl_cls: str = self.Gen.StructGen.get_class_name_by_type(pool, dl_st)
if dl_cls is not None:
dl_lookup: str = pool.alloc(128)
if dl_lookup is not None:
viperlib.snprintf(dl_lookup, 128, "%s.__delitem__", dl_cls)
dl_fn: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, dl_lookup)
dl_fn: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, dl_lookup)
if dl_fn is not None:
dl_ret: llvmlite.LLVMType* = llvmlite.function_get_ret_ty(dl_fn)
dl_fn_name: str = llvmlite.function_get_name(dl_fn)
dl_ret: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(dl_fn)
dl_fn_name: str = mlirlite.function_get_name(dl_fn)
if dl_ret is not None and dl_fn_name is not None:
# self 参数(容器)按 __delitem__ 首参类型对齐
dl_self: llvmlite.Value* = dl_obj
dl_first: llvmlite.Param* = llvmlite.function_get_param_head(dl_fn)
dl_self: mlirlite.Value* = dl_obj
dl_first: mlirlite.Param* = mlirlite.function_get_param_head(dl_fn)
if dl_first is not None:
dl_self_ty: llvmlite.LLVMType* = llvmlite.param_get_ty(dl_first)
dl_self_ty: mlirlite.LLVMType* = mlirlite.param_get_ty(dl_first)
if dl_self_ty is not None:
dl_self = llvmlite.build_bitcast(builder, dl_obj, dl_self_ty)
dl_self = mlirlite.build_bitcast(builder, dl_obj, dl_self_ty)
if dl_self is not None:
# 参数链表: self → key(独立 null 结尾)
dl_self.Next = dl_idx
dl_idx.Next = None
llvmlite.build_call(builder, dl_fn_name, dl_self, 2, dl_ret, 0)
mlirlite.build_call(builder, dl_fn_name, dl_self, 2, dl_ret, 0)
return 0
# ============================================================
@@ -201,29 +201,29 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
if tr is None:
return 0
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
func: llvmlite.Function* = trans._cur_func
builder: mlirlite.IRBuilder* = trans._cur_builder
func: mlirlite.Function* = trans._cur_func
if pool is None or builder is None or func is None:
return 0
if llvmlite.builder_cur_block_is_terminated(builder) != 0:
if mlirlite.builder_cur_block_is_terminated(builder) != 0:
return 0
# ---- 1. 异常编码/消息 alloca(当前 try 上下文)----
i32_ty_t: llvmlite.LLVMType* = llvmlite.Int32(pool)
i8_ty_t: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty_t: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty_t)
i32_ty_t: mlirlite.LLVMType* = mlirlite.Int32(pool)
i8_ty_t: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty_t: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_t)
if i32_ty_t is None or i8_ptr_ty_t is None:
return 0
exception_code: llvmlite.Value* = llvmlite.build_alloca(builder, i32_ty_t)
eh_message: llvmlite.Value* = llvmlite.build_alloca(builder, i8_ptr_ty_t)
exception_code: mlirlite.Value* = mlirlite.build_alloca(builder, i32_ty_t)
eh_message: mlirlite.Value* = mlirlite.build_alloca(builder, i8_ptr_ty_t)
if exception_code is None or eh_message is None:
return 0
init_code_t: llvmlite.Value* = llvmlite.const_int32(pool, 0)
init_msg_t: llvmlite.Value* = llvmlite.ConstNull(pool, i8_ptr_ty_t, "null")
init_code_t: mlirlite.Value* = mlirlite.const_int32(pool, 0)
init_msg_t: mlirlite.Value* = mlirlite.ConstNull(pool, i8_ptr_ty_t, "null")
if init_code_t is not None:
llvmlite.build_store(builder, init_code_t, exception_code)
mlirlite.build_store(builder, init_code_t, exception_code)
if init_msg_t is not None:
llvmlite.build_store(builder, init_msg_t, eh_message)
mlirlite.build_store(builder, init_msg_t, eh_message)
# ---- 2. 块布局(块名唯一化,create_block 不自动编号)----
lc_t: int = trans._label_counter
@@ -232,50 +232,50 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
if bb_buf_t is None:
return 0
viperlib.snprintf(bb_buf_t, 64, "try.dispatch.%d", lc_t)
dispatch_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, bb_buf_t)
dispatch_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, bb_buf_t)
viperlib.snprintf(bb_buf_t, 64, "try.after.%d", lc_t)
after_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, bb_buf_t)
after_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, bb_buf_t)
viperlib.snprintf(bb_buf_t, 64, "try.unhandled.%d", lc_t)
unhandled_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, bb_buf_t)
unhandled_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, bb_buf_t)
viperlib.snprintf(bb_buf_t, 64, "try.body.%d", lc_t)
try_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, bb_buf_t)
try_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, bb_buf_t)
if dispatch_bb is None or after_bb is None or unhandled_bb is None or try_bb is None:
return 0
else_bb: rawptr[llvmlite.BasicBlock] = None
else_bb: rawptr[mlirlite.BasicBlock] = None
if tr.orelse is not None and len(tr.orelse) > 0:
viperlib.snprintf(bb_buf_t, 64, "try.else.%d", lc_t)
else_bb = llvmlite.create_block(pool, func, bb_buf_t)
else_bb = mlirlite.create_block(pool, func, bb_buf_t)
n_handlers_t: sizet = 0
if tr.handlers is not None:
n_handlers_t = len(tr.handlers)
# 注意:list[ptr](pool, N) 第二参数是 elem_size 不是容量!
# 指针元素必须显式传 8(T.__sizeof__ 对联合类型不可靠),
# 否则 append 按 N 字节步长错位存取 → 读出垃圾指针(崩溃)。
except_bbs: list[rawptr[llvmlite.BasicBlock]] | t.CPtr = \
list[rawptr[llvmlite.BasicBlock]](pool, 8)
match_bbs: list[rawptr[llvmlite.BasicBlock]] | t.CPtr = \
list[rawptr[llvmlite.BasicBlock]](pool, 8)
except_bbs: list[rawptr[mlirlite.BasicBlock]] | t.CPtr = \
list[rawptr[mlirlite.BasicBlock]](pool, 8)
match_bbs: list[rawptr[mlirlite.BasicBlock]] | t.CPtr = \
list[rawptr[mlirlite.BasicBlock]](pool, 8)
if except_bbs is None or match_bbs is None:
return 0
for i_t in range(n_handlers_t):
viperlib.snprintf(bb_buf_t, 64, "try.except.%d.%d", lc_t, i_t)
eb_t: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, bb_buf_t)
eb_t: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, bb_buf_t)
viperlib.snprintf(bb_buf_t, 64, "try.match.%d.%d", lc_t, i_t)
mb_t: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, bb_buf_t)
mb_t: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, bb_buf_t)
except_bbs.append(eb_t)
match_bbs.append(mb_t)
# ---- 3. 保存外层 try 上下文,设置本 try 上下文 ----
old_dispatch_t: rawptr[llvmlite.BasicBlock] = trans._eh_dispatch_bb
old_code_t: llvmlite.Value* = trans._eh_code_ptr
old_msg_t: llvmlite.Value* = trans._eh_msg_ptr
old_dispatch_t: rawptr[mlirlite.BasicBlock] = trans._eh_dispatch_bb
old_code_t: mlirlite.Value* = trans._eh_code_ptr
old_msg_t: mlirlite.Value* = trans._eh_msg_ptr
trans._eh_dispatch_bb = dispatch_bb
trans._eh_code_ptr = exception_code
trans._eh_msg_ptr = eh_message
# ---- 4. Try 体 ----
llvmlite.build_br(builder, try_bb)
llvmlite.position_at_end(builder, try_bb)
mlirlite.build_br(builder, try_bb)
mlirlite.position_at_end(builder, try_bb)
if tr.children is not None:
tb_n: sizet = len(tr.children)
for tbi in range(tb_n):
@@ -283,31 +283,31 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
if stmt_t is not None:
self.translate_stmt(trans, stmt_t)
# 正常走完 try 体:清异常码,进 else(若有)或 After
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
if mlirlite.builder_cur_block_is_terminated(builder) == 0:
if init_code_t is not None:
llvmlite.build_store(builder, init_code_t, exception_code)
mlirlite.build_store(builder, init_code_t, exception_code)
if else_bb is not None:
llvmlite.build_br(builder, else_bb)
mlirlite.build_br(builder, else_bb)
else:
llvmlite.build_br(builder, after_bb)
mlirlite.build_br(builder, after_bb)
# ---- 5. DispatchBB:编码检查链 ----
llvmlite.position_at_end(builder, dispatch_bb)
mlirlite.position_at_end(builder, dispatch_bb)
if n_handlers_t == 0:
# 无 except(非法 try,防御):直接吞掉
llvmlite.build_br(builder, unhandled_bb)
mlirlite.build_br(builder, unhandled_bb)
else:
eh_code_val: llvmlite.Value* = llvmlite.build_load(builder, i32_ty_t, exception_code)
next_check_t: rawptr[llvmlite.BasicBlock] = None
eh_code_val: mlirlite.Value* = mlirlite.build_load(builder, i32_ty_t, exception_code)
next_check_t: rawptr[mlirlite.BasicBlock] = None
for i_t in range(n_handlers_t):
hdr_t: ast.ExceptHandler* = ast.ExceptHandler*(tr.handlers.get(i_t))
match_bb_t: rawptr[llvmlite.BasicBlock] = match_bbs.get(i_t)
match_bb_t: rawptr[mlirlite.BasicBlock] = match_bbs.get(i_t)
if i_t > 0 and next_check_t is not None:
llvmlite.position_at_end(builder, next_check_t)
eh_code_val = llvmlite.build_load(builder, i32_ty_t, exception_code)
mlirlite.position_at_end(builder, next_check_t)
eh_code_val = mlirlite.build_load(builder, i32_ty_t, exception_code)
if hdr_t is None or hdr_t.type is None:
# 裸 except:无条件匹配
llvmlite.build_br(builder, match_bb_t)
mlirlite.build_br(builder, match_bb_t)
else:
# 展开匹配编码集(handler.type 自身 + 全部子孙异常类)
hname_t: str = None
@@ -333,22 +333,22 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
c0_t = 1
codes_buf_t[0] = c0_t
n_codes_t = 1
match_cond_t: llvmlite.Value* = None
match_cond_t: mlirlite.Value* = None
for ci_t in range(n_codes_t):
code_val_t: llvmlite.Value* = llvmlite.const_int32(pool, codes_buf_t[ci_t])
is_match_t: llvmlite.Value* = llvmlite.build_icmp(builder, llvmlite.ICMP_EQ, eh_code_val, code_val_t)
code_val_t: mlirlite.Value* = mlirlite.const_int32(pool, codes_buf_t[ci_t])
is_match_t: mlirlite.Value* = mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, eh_code_val, code_val_t)
if match_cond_t is None:
match_cond_t = is_match_t
elif is_match_t is not None:
match_cond_t = llvmlite.build_or(builder, match_cond_t, is_match_t)
match_cond_t = mlirlite.build_or(builder, match_cond_t, is_match_t)
if i_t < n_handlers_t - 1:
viperlib.snprintf(bb_buf_t, 64, "try.check.%d.%d", lc_t, i_t)
next_check_t = llvmlite.create_block(pool, func, bb_buf_t)
next_check_t = mlirlite.create_block(pool, func, bb_buf_t)
else:
next_check_t = unhandled_bb
llvmlite.build_cond_br(builder, match_cond_t, match_bb_t, next_check_t)
mlirlite.build_cond_br(builder, match_cond_t, match_bb_t, next_check_t)
# MatchBB:绑定 handler 变量(e = 消息指针),跳 ExceptBB
llvmlite.position_at_end(builder, match_bb_t)
mlirlite.position_at_end(builder, match_bb_t)
if hdr_t is not None and hdr_t.name is not None and hdr_t.name[0] != '\0':
# 同名 handler 变量复用函数入口 alloca(find_var 首条命中、
# 重复 define_var 不 shadow——多 try 共用 `as e` 时各 MatchBB
@@ -356,62 +356,62 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
# 非支配 alloca 触发 "does not dominate all uses")。
h_ent_t: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, hdr_t.name)
if h_ent_t is not None and h_ent_t.Alloca is not None:
h_alloca_t: llvmlite.Value* = h_ent_t.Alloca
h_alloca_t: mlirlite.Value* = h_ent_t.Alloca
else:
h_alloca_t = self.Gen.VarGen._alloca_at_entry(builder, i8_ptr_ty_t)
if h_alloca_t is not None:
self.Gen.VarGen.define_var(trans.SymTab, hdr_t.name, h_alloca_t)
if h_alloca_t is not None:
h_msg_t: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty_t, eh_message)
h_msg_t: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty_t, eh_message)
if h_msg_t is not None:
llvmlite.build_store(builder, h_msg_t, h_alloca_t)
except_bb_t: rawptr[llvmlite.BasicBlock] = except_bbs.get(i_t)
llvmlite.build_br(builder, except_bb_t)
mlirlite.build_store(builder, h_msg_t, h_alloca_t)
except_bb_t: rawptr[mlirlite.BasicBlock] = except_bbs.get(i_t)
mlirlite.build_br(builder, except_bb_t)
# ---- 6. UnhandledBB:无 except 匹配 → 向上传播或吞掉 ----
llvmlite.position_at_end(builder, unhandled_bb)
mlirlite.position_at_end(builder, unhandled_bb)
if trans._cur_func_has_eh != 0 and trans._eh_msg_out_param is not None \
and trans._eh_code_out_param is not None:
un_msg_t: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty_t, eh_message)
un_code_t: llvmlite.Value* = llvmlite.build_load(builder, i32_ty_t, exception_code)
un_msg_t: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty_t, eh_message)
un_code_t: mlirlite.Value* = mlirlite.build_load(builder, i32_ty_t, exception_code)
if un_msg_t is not None:
llvmlite.build_store(builder, un_msg_t, trans._eh_msg_out_param)
mlirlite.build_store(builder, un_msg_t, trans._eh_msg_out_param)
if un_code_t is not None:
llvmlite.build_store(builder, un_code_t, trans._eh_code_out_param)
mlirlite.build_store(builder, un_code_t, trans._eh_code_out_param)
self._eh_ret_default(trans, pool, builder)
else:
if init_code_t is not None:
llvmlite.build_store(builder, init_code_t, exception_code)
llvmlite.build_br(builder, after_bb)
mlirlite.build_store(builder, init_code_t, exception_code)
mlirlite.build_br(builder, after_bb)
# ---- 7. Except 体 ----
for i_t in range(n_handlers_t):
hdr2_t: ast.ExceptHandler* = ast.ExceptHandler*(tr.handlers.get(i_t))
except_bb2_t: rawptr[llvmlite.BasicBlock] = except_bbs.get(i_t)
llvmlite.position_at_end(builder, except_bb2_t)
except_bb2_t: rawptr[mlirlite.BasicBlock] = except_bbs.get(i_t)
mlirlite.position_at_end(builder, except_bb2_t)
if hdr2_t is not None and hdr2_t.children is not None:
hn2_t: sizet = len(hdr2_t.children)
for hi2 in range(hn2_t):
stmt2_t: ast.AST* = hdr2_t.children.get(hi2)
if stmt2_t is not None:
self.translate_stmt(trans, stmt2_t)
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
llvmlite.build_br(builder, after_bb)
if mlirlite.builder_cur_block_is_terminated(builder) == 0:
mlirlite.build_br(builder, after_bb)
# ---- 8. Else 体 ----
if else_bb is not None:
llvmlite.position_at_end(builder, else_bb)
mlirlite.position_at_end(builder, else_bb)
if tr.orelse is not None:
en_t: sizet = len(tr.orelse)
for ei in range(en_t):
stmt3_t: ast.AST* = tr.orelse.get(ei)
if stmt3_t is not None:
self.translate_stmt(trans, stmt3_t)
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
llvmlite.build_br(builder, after_bb)
if mlirlite.builder_cur_block_is_terminated(builder) == 0:
mlirlite.build_br(builder, after_bb)
# ---- 9. AfterBB + 恢复外层 try 上下文 ----
llvmlite.position_at_end(builder, after_bb)
mlirlite.position_at_end(builder, after_bb)
trans._eh_dispatch_bb = old_dispatch_t
trans._eh_code_ptr = old_code_t
trans._eh_msg_ptr = old_msg_t
@@ -433,8 +433,8 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
if trans is None or node is None:
return 0
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
mod: llvmlite.LLVMModule* = trans.Module
builder: mlirlite.IRBuilder* = trans._cur_builder
mod: mlirlite.LLVMModule* = trans.Module
if pool is None or builder is None or mod is None:
return 0
rn: rawptr[ast.Raise] = rawptr[ast.Raise](node)
@@ -459,17 +459,17 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
is_stop_iter = 1
if is_stop_iter != 0:
if trans._stop_iter_flag_ptr is not None:
i1_ty_r: llvmlite.LLVMType* = llvmlite.Int1(pool)
i1_ty_r: mlirlite.LLVMType* = mlirlite.Int1(pool)
if i1_ty_r is not None:
one_i1_r: llvmlite.Value* = llvmlite.ConstInt(pool, i1_ty_r, 1, "1")
one_i1_r: mlirlite.Value* = mlirlite.ConstInt(pool, i1_ty_r, 1, "1")
if one_i1_r is not None:
llvmlite.build_store(builder, one_i1_r, trans._stop_iter_flag_ptr)
mlirlite.build_store(builder, one_i1_r, trans._stop_iter_flag_ptr)
self._eh_ret_default(trans, pool, builder)
return 0
# ---- 非 StopIteration:计算异常编码与消息 ----
exc_code: int = 1
exc_msg: llvmlite.Value* = None
exc_msg: mlirlite.Value* = None
if ek == ast.ASTKind.Constant:
cst_r: ast.Constant* = ast.Constant*(rn.exc)
if cst_r is not None and cst_r.const_kind == ast.CONST_INT:
@@ -494,25 +494,25 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
# ---- 异常分发 ----
# 1. try 内:写入 try 的 eh_code/eh_message alloca,分支 DispatchBB
if trans._eh_dispatch_bb is not None and trans._eh_code_ptr is not None:
code_val_r: llvmlite.Value* = llvmlite.const_int32(pool, exc_code)
code_val_r: mlirlite.Value* = mlirlite.const_int32(pool, exc_code)
if code_val_r is not None:
llvmlite.build_store(builder, code_val_r, trans._eh_code_ptr)
mlirlite.build_store(builder, code_val_r, trans._eh_code_ptr)
if exc_msg is None:
exc_msg = llvmlite.ConstNull(pool, llvmlite.Ptr(pool, llvmlite.Int8(pool)), "null")
exc_msg = mlirlite.ConstNull(pool, mlirlite.Ptr(pool, mlirlite.Int8(pool)), "null")
if exc_msg is not None and trans._eh_msg_ptr is not None:
llvmlite.build_store(builder, exc_msg, trans._eh_msg_ptr)
llvmlite.build_br(builder, trans._eh_dispatch_bb)
mlirlite.build_store(builder, exc_msg, trans._eh_msg_ptr)
mlirlite.build_br(builder, trans._eh_dispatch_bb)
return 0
# 2. 函数有 EH 输出参数:写入 out 参数(异常向调用方传播)
if trans._cur_func_has_eh != 0 and trans._eh_msg_out_param is not None \
and trans._eh_code_out_param is not None:
code_val_r2: llvmlite.Value* = llvmlite.const_int32(pool, exc_code)
code_val_r2: mlirlite.Value* = mlirlite.const_int32(pool, exc_code)
if code_val_r2 is not None:
llvmlite.build_store(builder, code_val_r2, trans._eh_code_out_param)
mlirlite.build_store(builder, code_val_r2, trans._eh_code_out_param)
if exc_msg is None:
exc_msg = llvmlite.ConstNull(pool, llvmlite.Ptr(pool, llvmlite.Int8(pool)), "null")
exc_msg = mlirlite.ConstNull(pool, mlirlite.Ptr(pool, mlirlite.Int8(pool)), "null")
if exc_msg is not None:
llvmlite.build_store(builder, exc_msg, trans._eh_msg_out_param)
mlirlite.build_store(builder, exc_msg, trans._eh_msg_out_param)
self._eh_ret_default(trans, pool, builder)
return 0
# 3. 无 try 无 EH 参数:仅返回默认值
@@ -528,33 +528,33 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
# ============================================================
def _eh_ret_default(self, trans: HT.Translator*,
pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*) -> int:
builder: mlirlite.IRBuilder*) -> int:
"""异常路径返回当前函数默认零值,返回 0"""
if trans is None or builder is None:
return 0
if llvmlite.builder_cur_block_is_terminated(builder) != 0:
if mlirlite.builder_cur_block_is_terminated(builder) != 0:
return 0
cur_func: llvmlite.Function* = trans._cur_func
cur_func: mlirlite.Function* = trans._cur_func
if cur_func is None:
return 0
ret_ty: llvmlite.LLVMType* = llvmlite.function_get_ret_ty(cur_func)
ret_ty: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(cur_func)
if ret_ty is None:
return 0
match ret_ty:
case llvmlite.LLVMType.Void():
llvmlite.build_ret_void(builder)
case llvmlite.LLVMType.Ptr(_pe):
null_v: llvmlite.Value* = llvmlite.ConstNull(pool, ret_ty, "null")
case mlirlite.LLVMType.Void():
mlirlite.build_ret_void(builder)
case mlirlite.LLVMType.Ptr(_pe):
null_v: mlirlite.Value* = mlirlite.ConstNull(pool, ret_ty, "null")
if null_v is not None:
llvmlite.build_ret(builder, null_v)
case llvmlite.LLVMType.Float(_fb):
zero_f: llvmlite.Value* = llvmlite.ConstFloat(pool, ret_ty, 0.0)
mlirlite.build_ret(builder, null_v)
case mlirlite.LLVMType.Float(_fb):
zero_f: mlirlite.Value* = mlirlite.ConstFloat(pool, ret_ty, 0.0)
if zero_f is not None:
llvmlite.build_ret(builder, zero_f)
mlirlite.build_ret(builder, zero_f)
case _:
zero_v: llvmlite.Value* = llvmlite.ConstZero(pool, ret_ty)
zero_v: mlirlite.Value* = mlirlite.ConstZero(pool, ret_ty)
if zero_v is not None:
llvmlite.build_ret(builder, zero_v)
mlirlite.build_ret(builder, zero_v)
return 0
# ============================================================
@@ -582,8 +582,8 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
if wt is None:
return 0
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
mod: llvmlite.LLVMModule* = trans.Module
builder: mlirlite.IRBuilder* = trans._cur_builder
mod: mlirlite.LLVMModule* = trans.Module
if pool is None or builder is None or mod is None:
return 0
items: list[ast.AST*]* = wt.items
@@ -592,7 +592,7 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
n: sizet = len(items)
# 保存外层 __with_ctx(嵌套 with 时退出后恢复)
old_ctx_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, "__with_ctx")
old_ctx_alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, "__with_ctx")
# 记录每个 item 的类名(__exit__ 调用时设置 __with_ctx 类型用)
ctx_class_buf: sizet* = pool.alloc(8 * n)
@@ -611,7 +611,7 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
if item is None or item.context_expr is None:
continue
# 翻译 context_expr(对象构造,如 MemPool(arena, 4096))
ctx_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, item.context_expr, trans._funcs, trans._func_count, trans)
ctx_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, item.context_expr, trans._funcs, trans._func_count, trans)
if ctx_val is None:
continue
# 提取类名(注解类名,Attribute 时带模块前缀,如 "memhub.MemPool"——
@@ -637,29 +637,29 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
elif cfn.kind() == ast.ASTKind.Name:
cls_name = (ast.Name*(cfn)).id
# context 对象存入 __with_ctx(方法调用解析 self 用)
ctx_alloca: llvmlite.Value* = llvmlite.build_alloca(builder, ctx_val.Ty)
ctx_alloca: mlirlite.Value* = mlirlite.build_alloca(builder, ctx_val.Ty)
if ctx_alloca is None:
continue
llvmlite.build_store(builder, ctx_val, ctx_alloca)
mlirlite.build_store(builder, ctx_val, ctx_alloca)
self.Gen.VarGen.define_var(trans.SymTab, "__with_ctx", ctx_alloca)
if cls_name is not None:
self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, "__with_ctx", cls_name)
ctx_class_buf[i] = sizet(cls_name)
# 调用 __enter__()
enter_val: llvmlite.Value* = self._with_ctx_call(trans, pool, builder, mod, "__enter__")
enter_val: mlirlite.Value* = self._with_ctx_call(trans, pool, builder, mod, "__enter__")
# asname 绑定(__enter__ 返回值,缺失时退回 context 对象)
if item.optional_vars is not None:
ov: ast.AST* = item.optional_vars
if ov.kind() == ast.ASTKind.Name:
asname: str = (ast.Name*(ov)).id
if asname is not None:
bind_val: llvmlite.Value* = enter_val
bind_val: mlirlite.Value* = enter_val
if bind_val is None:
bind_val = ctx_val
if bind_val is not None:
asn_alloca: llvmlite.Value* = llvmlite.build_alloca(builder, bind_val.Ty)
asn_alloca: mlirlite.Value* = mlirlite.build_alloca(builder, bind_val.Ty)
if asn_alloca is not None:
llvmlite.build_store(builder, bind_val, asn_alloca)
mlirlite.build_store(builder, bind_val, asn_alloca)
self.Gen.VarGen.define_var(trans.SymTab, asname, asn_alloca)
if cls_name is not None:
self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, asname, cls_name)
@@ -711,9 +711,9 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
def _with_ctx_call(self, trans: HT.Translator*,
pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
method_name: str) -> llvmlite.Value*:
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
method_name: str) -> mlirlite.Value*:
"""构造并翻译 __with_ctx.<method_name>() 调用(__enter__/__exit__)"""
if pool is None or method_name is None: return None
name_node: ast.AST* = ast.Name(pool, "__with_ctx", ast.ASTCtx.Load)
+42 -42
View File
@@ -3,7 +3,7 @@ from stdint import *
import memhub
import string
import stdlib
import llvmlite
import mlirlite
import stdio
import ast
import hashtable
@@ -585,7 +585,7 @@ novirtual class StructGenMixin:
def register_struct(self, pool: memhub.MemBuddy*,
name: str,
struct_ty: llvmlite.LLVMType*,
struct_ty: mlirlite.LLVMType*,
sha1: str = None) -> GenTypes.StructEntry*:
"""注册结构体类型,返回 StructEntry 指针
@@ -685,7 +685,7 @@ novirtual class StructGenMixin:
string.strcpy(name_buf, sha1)
name_buf[sh_len] = '.'
string.strcpy(name_buf + sh_len + 1, class_name)
fwd_ty: llvmlite.LLVMType* = llvmlite.Struct(fwd_pool, None, 0, name_buf)
fwd_ty: mlirlite.LLVMType* = mlirlite.Struct(fwd_pool, None, 0, name_buf)
if fwd_ty is None:
return None
entry: GenTypes.StructEntry* = self.register_struct(pool, class_name, fwd_ty, sha1)
@@ -789,7 +789,7 @@ novirtual class StructGenMixin:
def add_field(self, pool: memhub.MemBuddy*,
struct_entry: GenTypes.StructEntry*,
field_name: str,
field_ty: llvmlite.LLVMType*,
field_ty: mlirlite.LLVMType*,
default_val: ast.AST* = None,
annot_class_name: str = None) -> int:
"""向结构体添加字段,返回字段索引(-1 失败)
@@ -825,7 +825,7 @@ novirtual class StructGenMixin:
if self.StdlibAlloc != 0:
dp_pool_sg: memhub.MemBuddy* = CompilerFactory.factory.PermPool
if dp_pool_sg is None: dp_pool_sg = pool
ty_copy: llvmlite.LLVMType* = llvmlite.DeepCopyType(dp_pool_sg, field_ty)
ty_copy: mlirlite.LLVMType* = mlirlite.DeepCopyType(dp_pool_sg, field_ty)
if ty_copy is not None: fe.Ty = ty_copy
else: fe.Ty = field_ty
# DefaultVal:跨文件结构体构造(_translate_struct_ctor→_apply_struct_defaults)
@@ -1231,7 +1231,7 @@ novirtual class StructGenMixin:
reset_count += 1
return reset_count
def find_struct_by_type(self, struct_ty: llvmlite.LLVMType*) -> GenTypes.StructEntry*:
def find_struct_by_type(self, struct_ty: mlirlite.LLVMType*) -> GenTypes.StructEntry*:
"""按类型指针查找结构体(指针值比较),返回 StructEntry 或 None
注意: 不能用 `entry.Ty is struct_ty` 的 is 比较——TPV 编译 is 时会触发
@@ -1258,7 +1258,7 @@ novirtual class StructGenMixin:
return entry
return None
def struct_type_is_packed(self, struct_ty: llvmlite.LLVMType*) -> int:
def struct_type_is_packed(self, struct_ty: mlirlite.LLVMType*) -> int:
"""判断命名结构体是否 packed(@c.Attribute(t.attr.packed)),返回 1/0
先按类型指针身份匹配(find_struct_by_type,跨模块 deep copy 后仍
@@ -1268,7 +1268,7 @@ novirtual class StructGenMixin:
"""
if struct_ty is None:
return 0
sname: str = llvmlite.get_struct_name(struct_ty)
sname: str = mlirlite.get_struct_name(struct_ty)
if sname is None:
return 0
entry: GenTypes.StructEntry* = self.find_struct_by_type(struct_ty)
@@ -1299,7 +1299,7 @@ novirtual class StructGenMixin:
# 空字段表(FieldCount=0,vpi 注入的"仅签名类")不判:既有语义是"按名查不到
# 返回 None",由调用方处理。
# ============================================================
def verify_field_slot_consistency(self, struct_ty: llvmlite.LLVMType*,
def verify_field_slot_consistency(self, struct_ty: mlirlite.LLVMType*,
entry: GenTypes.StructEntry*) -> int:
"""字段表条数须等于结构体槽位数;每条目 Ty 须与其 Index 槽位同类"""
if struct_ty is None or entry is None:
@@ -1312,7 +1312,7 @@ novirtual class StructGenMixin:
# 故本护栏不适用(误报实证:EdgeCaseTest 的 `class Data(t.CUnion)`,2 成员 → 1 槽)。
if entry.IsUnion != 0 or self.is_union_by_type(struct_ty) != 0:
return 0
fcount: int = llvmlite.get_struct_fcount(struct_ty)
fcount: int = mlirlite.get_struct_fcount(struct_ty)
if fcount <= 0:
return 0
if entry.FieldCount != fcount:
@@ -1322,11 +1322,11 @@ novirtual class StructGenMixin:
f"(实证:ast.Name.id 落到 ctx 槽 ⇒ 指针被读成整数 1 ⇒ strlen(0x1) 崩溃)。",
"TypeError")
return 0
node: rawptr[llvmlite.ParamNode] = llvmlite.get_struct_fields(struct_ty)
node: rawptr[mlirlite.ParamNode] = mlirlite.get_struct_fields(struct_ty)
i: int = 0
while i < entry.FieldCount and node is not None:
fe: GenTypes.FieldEntry* = self._get_field_entry(entry, i)
slot_ty: llvmlite.LLVMType* = llvmlite.paramnode_get_ty(node)
slot_ty: mlirlite.LLVMType* = mlirlite.paramnode_get_ty(node)
if fe is not None and fe.Name is not None and fe.Ty is not None and slot_ty is not None:
ptr_f: int = self.Gen.ExprGenBase.is_ptr_type(fe.Ty)
ptr_s: int = self.Gen.ExprGenBase.is_ptr_type(slot_ty)
@@ -1342,11 +1342,11 @@ novirtual class StructGenMixin:
f"字段条目与结构体布局错位(实证:id 落到 ctx 槽 ⇒ 指针被读成整数 1 ⇒ strlen(0x1) 崩溃)。",
"TypeError")
return 0
node = llvmlite.paramnode_get_next(node)
node = mlirlite.paramnode_get_next(node)
i += 1
return 0
def lookup_field(self, struct_ty: llvmlite.LLVMType*,
def lookup_field(self, struct_ty: mlirlite.LLVMType*,
field_name: str) -> GenTypes.FieldEntry*:
"""按结构体类型和字段名查找字段信息
@@ -1549,7 +1549,7 @@ novirtual class StructGenMixin:
stdlib.free(mod_buf_q)
return fe_q
# REnum 变体字段别名回退(与裸名路径一致):模块限定访问
# (llvmlite.LLVMType.Pointee)类命中后字段未找到时,直接查
# (mlirlite.LLVMType.Pointee)类命中后字段未找到时,直接查
# 变体别名(REnum 字段是 _p1/_p2 槽位)。此前该回退只在裸名
# 路径,模块限定路径此处 fatal 先触发 → 永远走不到。
rn_cls_q: str = mod_entry_q.Name
@@ -1671,7 +1671,7 @@ novirtual class StructGenMixin:
# 诊断:找到结构体但字段未找到
return None
def get_struct_type(self, class_name: str) -> llvmlite.LLVMType*:
def get_struct_type(self, class_name: str) -> mlirlite.LLVMType*:
"""按类名获取结构体的 LLVM 类型"""
entry: GenTypes.StructEntry* = self.find_struct(class_name)
if entry is not None:
@@ -1703,7 +1703,7 @@ novirtual class StructGenMixin:
return 1
return 0
def get_struct_type_from_value(self, val: llvmlite.Value*) -> llvmlite.LLVMType*:
def get_struct_type_from_value(self, val: mlirlite.Value*) -> mlirlite.LLVMType*:
"""从 Value 的类型推断结构体类型
递归解 Ptr:支持 X|t.CPtr 联合简化产生的 Ptr(Ptr(Struct)) 对象指针
@@ -1713,17 +1713,17 @@ novirtual class StructGenMixin:
"""
if val is None or val.Ty is None:
return None
ty: llvmlite.LLVMType* = val.Ty
ty: mlirlite.LLVMType* = val.Ty
while ty is not None:
# 同类编译 bug(见 TypeGenResolve L1463 注释):case body 直接
# 更新 while 条件变量(ty = pointee)时自举编译出的 match 把赋值
# 写到 subject 快照槽,while 条件读旧槽 → 死循环。改法:case
# 绑定到局部变量,match 外更新循环变量。
nxt_ty: llvmlite.LLVMType* = None
nxt_ty: mlirlite.LLVMType* = None
match ty:
case llvmlite.LLVMType.Ptr(pointee):
case mlirlite.LLVMType.Ptr(pointee):
nxt_ty = pointee
case llvmlite.LLVMType.Struct(fields, fcount, name):
case mlirlite.LLVMType.Struct(fields, fcount, name):
return ty
case _:
return None
@@ -1749,7 +1749,7 @@ novirtual class StructGenMixin:
return 0
return entry.IsUnion
def is_union_by_type(self, struct_ty: llvmlite.LLVMType*) -> int:
def is_union_by_type(self, struct_ty: mlirlite.LLVMType*) -> int:
"""按类型指针检查是否为联合体,返回 1=是 / 0=否
先尝试类型指针 == 比较,失败时回退到名称匹配
@@ -1831,7 +1831,7 @@ novirtual class StructGenMixin:
return entry.HasNew
def get_class_name_by_type(self, pool: memhub.MemBuddy*,
struct_ty: llvmlite.LLVMType*) -> str:
struct_ty: mlirlite.LLVMType*) -> str:
"""按类型指针查找类名,返回类名字符串或 None"""
if struct_ty is None or self.StructTable is None:
return None
@@ -1878,12 +1878,12 @@ novirtual class StructGenMixin:
return entry2.Name
return None
def _extract_struct_name(self, ty: llvmlite.LLVMType*) -> str:
def _extract_struct_name(self, ty: mlirlite.LLVMType*) -> str:
"""从 LLVMType 提取 Struct 变体的 Name 字段,返回 None 非 Struct"""
if ty is None:
return None
match ty:
case llvmlite.LLVMType.Struct(fields, fcount, name):
case mlirlite.LLVMType.Struct(fields, fcount, name):
return name
case _:
return None
@@ -2129,8 +2129,8 @@ novirtual class StructGenMixin:
return entry.FieldCount
def ensure_struct_def_in_module(self, pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
ty: llvmlite.LLVMType*):
mod: mlirlite.LLVMModule*,
ty: mlirlite.LLVMType*):
"""确保跨模块结构体的完整定义在当前模块中可用(供 alloca 使用)
处理两种情况:
@@ -2141,8 +2141,8 @@ novirtual class StructGenMixin:
return
# 指针类型:确保 pointee 至少有 opaque 声明
match ty:
case llvmlite.LLVMType.Ptr(pointee):
llvmlite.module_ensure_opaque_for_type(mod, pool, ty)
case mlirlite.LLVMType.Ptr(pointee):
mlirlite.module_ensure_opaque_for_type(mod, pool, ty)
# 如果 pointee 是 Struct,递归复制完整定义
# (GEP 访问字段需要 sized 类型,仅 opaque 会导致 llc 报错)
if pointee is not None:
@@ -2151,7 +2151,7 @@ novirtual class StructGenMixin:
case _:
pass
# 获取结构体名称(非 Struct 类型返回 None)
sname: str = llvmlite.get_struct_name(ty)
sname: str = mlirlite.get_struct_name(ty)
if sname is None:
return
# 检查是否为跨模块引用(名称包含 '.')
@@ -2190,28 +2190,28 @@ novirtual class StructGenMixin:
if entry.Ty is None:
return
# 将完整定义添加到当前模块(会替换已存在的 opaque 声明)
llvmlite.module_add_named_type(mod, pool, entry.Ty)
mlirlite.module_add_named_type(mod, pool, entry.Ty)
# B5:跨模块注入的 packed 类必须同步 packed 标记(<{...}>),否则引用
# 模块按非 packed 布局 GEP,与定义侧 packed 布局错位(gdt/elf/fat32
# 二进制格式字段错读;合并 IR 中 idt_entry/gdt_entry 退化 {…} 根因)。
if entry.IsPacked != 0:
llvmlite.module_set_named_type_packed(mod, pool, entry.Ty, 1)
mlirlite.module_set_named_type_packed(mod, pool, entry.Ty, 1)
# 递归扫描字段类型,确保值类型子结构体(如 WIN32_FIND_DATAA 中的 FILETIME)
# 也有完整定义。指针类型字段只需 opaque 声明(已由 module_ensure_opaque_for_type 处理)。
self._ensure_field_types_in_module(pool, mod, entry.Ty)
def _ensure_field_types_in_module(self, pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
ty: llvmlite.LLVMType*):
mod: mlirlite.LLVMModule*,
ty: mlirlite.LLVMType*):
"""递归扫描类型树,确保值类型子结构体有完整定义"""
if ty is None or mod is None or pool is None:
return
# 嵌套 match 遍历类型树
match ty:
case llvmlite.LLVMType.Struct(fields, fcount, sname):
case mlirlite.LLVMType.Struct(fields, fcount, sname):
# 遍历字段链表
if fields is not None:
fld: rawptr[llvmlite.ParamNode] = fields
fld: rawptr[mlirlite.ParamNode] = fields
cnt_ef: int = 0
while fld is not None:
# 步数守卫:字段链表成环(内存损坏)导致无限遍历挂起
@@ -2223,23 +2223,23 @@ novirtual class StructGenMixin:
if fld.Ty is not None:
# 值类型子结构体(如 FILETIME)需要完整定义
match fld.Ty:
case llvmlite.LLVMType.Struct(f2, fc2, n2):
case mlirlite.LLVMType.Struct(f2, fc2, n2):
self.ensure_struct_def_in_module(pool, mod, fld.Ty)
case _:
pass
self._ensure_field_types_in_module(pool, mod, fld.Ty)
fld = fld.Next
case llvmlite.LLVMType.Ptr(pointee):
case mlirlite.LLVMType.Ptr(pointee):
# 指针类型:pointee 只需 opaque 声明,不需要完整定义
# 但如果 pointee 是 Struct,确保 opaque 声明存在
if pointee is not None:
llvmlite.module_ensure_opaque_for_type(mod, pool, ty)
case llvmlite.LLVMType.Array(elem_ty, acount):
mlirlite.module_ensure_opaque_for_type(mod, pool, ty)
case mlirlite.LLVMType.Array(elem_ty, acount):
# 数组类型:元素如果是值类型结构体,需要完整定义(Array 元素只递归
# 字段不发射定义 → llc "use of undefined type named '...'")。
if elem_ty is not None:
match elem_ty:
case llvmlite.LLVMType.Struct(_, _, _):
case mlirlite.LLVMType.Struct(_, _, _):
self.ensure_struct_def_in_module(pool, mod, elem_ty)
case _:
pass
@@ -2253,7 +2253,7 @@ novirtual class StructGenMixin:
return None
return fe.Name
def get_field_type_ptr(self, fe: GenTypes.FieldEntry*) -> llvmlite.LLVMType*:
def get_field_type_ptr(self, fe: GenTypes.FieldEntry*) -> mlirlite.LLVMType*:
"""获取 FieldEntry 的字段类型,返回 None=未设置"""
if fe is None:
return None
+81 -81
View File
@@ -3,7 +3,7 @@ import lib.core.Gen.GenTypes as GenTypes
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdio
@@ -85,7 +85,7 @@ novirtual class Translator:
"""翻译器:管理编译状态,委托 Handles 模块执行翻译"""
# LLVM 上下文(共享状态)
Module: llvmlite.LLVMModule*
Module: mlirlite.LLVMModule*
Pool: memhub.MemBuddy*
# 函数表
@@ -106,12 +106,12 @@ novirtual class Translator:
_coro_frames: str
_coro_frame_count: int
# resume_<name> 翻译上下文(AsyncGenMixin 段翻译共享)
_coro_state_ptr: llvmlite.Value*
_coro_done_ptr: llvmlite.Value*
_coro_ret_ptr: llvmlite.Value*
_coro_exit_bb: rawptr[llvmlite.BasicBlock]
_coro_await_slot: llvmlite.Value*
_coro_frame: llvmlite.Value*
_coro_state_ptr: mlirlite.Value*
_coro_done_ptr: mlirlite.Value*
_coro_ret_ptr: mlirlite.Value*
_coro_exit_bb: rawptr[mlirlite.BasicBlock]
_coro_await_slot: mlirlite.Value*
_coro_frame: mlirlite.Value*
_coro_next_state: int
_coro_nseg: int
# M2:async 参数表(char* 数组,8 字节/项)+ 预扫描计数
@@ -121,13 +121,13 @@ novirtual class Translator:
_coro_await_count: int # 总 await 数(= 恢复块数 = switch case 数)
_coro_local_base: int # 局部槽起始 index(= 3 + nparams)
_coro_extra_base: int # 额外槽(__await_N)起始 index
_coro_break_bb: rawptr[llvmlite.BasicBlock] # While break 目标(M2 单层)
_coro_continue_bb: rawptr[llvmlite.BasicBlock] # While continue 目标
_coro_break_bb: rawptr[mlirlite.BasicBlock] # While break 目标(M2 单层)
_coro_continue_bb: rawptr[mlirlite.BasicBlock] # While continue 目标
_coro_state_bbs: sizet* # 预建 state 块数组(await 恢复块定位)
# M3-M7 协程扩展
_coro_exc_ptr: llvmlite.Value* # 帧 exc 槽(i32,M4)
_coro_msg_ptr: llvmlite.Value* # 帧 msg 槽(i8*,M7)
_coro_wake_ptr: llvmlite.Value* # 帧 wake 槽(i64,M3 coro_sleep)
_coro_exc_ptr: mlirlite.Value* # 帧 exc 槽(i32,M4)
_coro_msg_ptr: mlirlite.Value* # 帧 msg 槽(i8*,M7)
_coro_wake_ptr: mlirlite.Value* # 帧 wake 槽(i64,M3 coro_sleep)
_coro_try_stack: sizet* # try 栈:except/finally 块指针数组(8B/项)
_coro_try_stack_count: int
_coro_for_counter: int # range-For 编号(M3,翻译期递增)
@@ -147,8 +147,8 @@ novirtual class Translator:
_from_imports: str
# 当前翻译上下文
_cur_func: llvmlite.Function*
_cur_builder: llvmlite.IRBuilder*
_cur_func: mlirlite.Function*
_cur_builder: mlirlite.IRBuilder*
# 当前赋值语句的注解节点(AnnAssign 翻译 rhs 前设置,Assign 翻译前清空)。
# 供裸名泛型构造从注解推断类型实参:`s: Stack[int] = Stack()` 用注解里的
@@ -173,8 +173,8 @@ novirtual class Translator:
# 循环控制流目标(break/continue)。注意 match-case 体内的 break 语义是
# "跳出 match":MatchGenMixin 进出 case 体时暂存并把 _break_bb 覆盖为 match
# 的 end_bb(出 case 恢复),故 case 内 break 不会误跳外层循环。
_break_bb: rawptr[llvmlite.BasicBlock]
_continue_bb: rawptr[llvmlite.BasicBlock]
_break_bb: rawptr[mlirlite.BasicBlock]
_continue_bb: rawptr[mlirlite.BasicBlock]
# 当前是否处于 **switch** 的 case 语句体内(1=是)。供 `fallthrough` 语句判定
# 合法性:只在 switch 的 case 体内合法;写进 match 的 case 体或 switch 之外
@@ -214,7 +214,7 @@ novirtual class Translator:
# *args 变长参数支持:当前函数的 va_list 指针(i8* alloca)
# 仅当函数声明了 *args 时设置,供 arg(type) 糖函数使用
_va_list_ptr: llvmlite.Value*
_va_list_ptr: mlirlite.Value*
# *args 参数名(如 "args"),用于符号表注册
_vararg_name: str
@@ -222,24 +222,24 @@ novirtual class Translator:
# _translate_method 注入 __stop_iter_flag__ 参数时设置;translate_raise
# 检测 raise StopIteration 时对该指针 store 1(对齐 TPC HandlesRaise.py)。
# 非 __next__ 函数中为 None。
_stop_iter_flag_ptr: llvmlite.Value*
_stop_iter_flag_ptr: mlirlite.Value*
# try-except 机制(对齐 TPC HandlesTry.py):当前最内层 try 的
# 分发块 + 异常编码/消息 alloca。translate_try 设置,translate_raise
# 与调用侧 EH 检测写入/跳转。try 外为 None。
_eh_dispatch_bb: rawptr[llvmlite.BasicBlock]
_eh_code_ptr: llvmlite.Value*
_eh_msg_ptr: llvmlite.Value*
_eh_dispatch_bb: rawptr[mlirlite.BasicBlock]
_eh_code_ptr: mlirlite.Value*
_eh_msg_ptr: mlirlite.Value*
# 当前函数的 __eh_msg_out__(i8**)/__eh_code_out__(i32*)输出参数
# (函数签名含 raise 时由 translate_function_def/_translate_method 注入)。
# 无 EH 参数时 _cur_func_has_eh == 0。
_eh_msg_out_param: llvmlite.Value*
_eh_code_out_param: llvmlite.Value*
_eh_msg_out_param: mlirlite.Value*
_eh_code_out_param: mlirlite.Value*
_cur_func_has_eh: int
# 模块 SHA1 前缀(16 字符),用于函数名混淆(SHA1 命名空间)
ModuleSha1: str
# 当前文件所属包名(如 "llvmlite"),用于解析相对导入(from . import ...)
# 当前文件所属包名(如 "mlirlite"),用于解析相对导入(from . import ...)
# None 表示当前文件是顶级模块(无包),相对导入无法解析
CurrentPackage: str
# 闭包 env 中的 nonlocal 变量偏移映射(每个 nonlocal 变量在 env 中的字节偏移)
@@ -473,7 +473,7 @@ novirtual class Translator:
self._init_state(pool)
# 创建 LLVM 模块
mod: llvmlite.LLVMModule* = llvmlite.new_module(pool, "main")
mod: mlirlite.LLVMModule* = mlirlite.new_module(pool, "main")
if mod is None:
VLogger.error("NewModule returned NULL", "TR")
return 1
@@ -486,40 +486,40 @@ novirtual class Translator:
triple: str = Config.TargetTriple
if triple is None:
triple = "x86_64-pc-windows-msvc"
llvmlite.module_set_target(mod, triple)
mlirlite.module_set_target(mod, triple)
# 数据布局:project.vpj / viperbuild 的 target.datalayout(None 时不输出该行)。
# 写入 .ll 模块头,使生成的 IR 自带 LLVM 布局信息,与目标 triple 配套。
if Config.TargetDataLayout is not None:
llvmlite.module_set_datalayout(mod, Config.TargetDataLayout)
mlirlite.module_set_datalayout(mod, Config.TargetDataLayout)
# 类型
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
# 声明 printf
printf_func: llvmlite.Function* = llvmlite.create_declare(pool, mod, "printf", i32_ty)
printf_func: mlirlite.Function* = mlirlite.create_declare(pool, mod, "printf", i32_ty)
if printf_func is None:
VLogger.error("CreateDeclare printf returned NULL", "TR")
return 1
llvmlite.add_param(pool, printf_func, i8_ptr_ty, "fmt")
mlirlite.add_param(pool, printf_func, i8_ptr_ty, "fmt")
printf_func.IsVarArg = 1
# 声明 LLVM va_start/va_end intrinsic(供 *args 函数体内使用)
# declare void @llvm.va_start(i8*)
# declare void @llvm.va_end(i8*)
void_ty_decl: llvmlite.LLVMType* = llvmlite.Void(pool)
va_start_func: llvmlite.Function* = llvmlite.create_declare(pool, mod, "llvm.va_start", void_ty_decl)
void_ty_decl: mlirlite.LLVMType* = mlirlite.Void(pool)
va_start_func: mlirlite.Function* = mlirlite.create_declare(pool, mod, "llvm.va_start", void_ty_decl)
if va_start_func is not None:
llvmlite.add_param(pool, va_start_func, i8_ptr_ty, "ap")
va_end_func: llvmlite.Function* = llvmlite.create_declare(pool, mod, "llvm.va_end", void_ty_decl)
mlirlite.add_param(pool, va_start_func, i8_ptr_ty, "ap")
va_end_func: mlirlite.Function* = mlirlite.create_declare(pool, mod, "llvm.va_end", void_ty_decl)
if va_end_func is not None:
llvmlite.add_param(pool, va_end_func, i8_ptr_ty, "ap")
mlirlite.add_param(pool, va_end_func, i8_ptr_ty, "ap")
# 声明 malloc(闭包分配用)
malloc_func: llvmlite.Function* = llvmlite.create_declare(pool, mod, "malloc", i8_ptr_ty)
malloc_func: mlirlite.Function* = mlirlite.create_declare(pool, mod, "malloc", i8_ptr_ty)
if malloc_func is not None:
i64_ty: llvmlite.LLVMType* = llvmlite.Int64(pool)
llvmlite.add_param(pool, malloc_func, i64_ty, "size")
i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool)
mlirlite.add_param(pool, malloc_func, i64_ty, "size")
# 检查用户是否定义了 main 函数
has_user_main: int = 0
@@ -556,9 +556,9 @@ novirtual class Translator:
# 包装 main 函数(无用户 main 时)→ 委托 HandlesMain
# ============================================================
def _translate_wrapper_main(self, pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
tree: ast.AST*,
i32_ty: llvmlite.LLVMType*):
i32_ty: mlirlite.LLVMType*):
"""委托 GenApi.create_wrapper_main() 创建包装 main(trans 单参)"""
added: int = GenApi.create_wrapper_main(self, tree, i32_ty)
@@ -566,7 +566,7 @@ novirtual class Translator:
# 模块级翻译(用户已定义 main)→ 委托 HandlesMain
# ============================================================
def _translate_module_level(self, pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
tree: ast.AST*):
"""委托 GenApi.translate_children() 翻译模块级语句(trans 单参)"""
# 【文件级类名预登记:三种模式都必须先做(2026-09-30)】
@@ -1089,14 +1089,14 @@ novirtual class Translator:
if _mbuddy is None:
return
buf[0] = '\0'
llvmlite.LLVMModulePrint(buf, size, self.Module, _mbuddy, mode)
mlirlite.LLVMModulePrint(buf, size, self.Module, _mbuddy, mode)
# ============================================================
# --traceback: startup Install() ctor injection
#
# Lives here (not in BuildPipeline) because this module already imports
# llvmlite. Calling llvmlite.* from a module without that import mangles the
# mlirlite. Calling mlirlite.* from a module without that import mangles the
# calls with the package (__init__) SHA1, which no object defines, instead of
# the defining submodule's SHA1 (link-time undefined symbol). BuildPipeline
# only decides whether to trigger the injection.
@@ -1110,10 +1110,10 @@ novirtual class Translator:
# ============================================================
# _tb_module_has_global_ctors - does the module already define @llvm.global_ctors
def _tb_module_has_global_ctors(mod: llvmlite.LLVMModule*) -> int:
def _tb_module_has_global_ctors(mod: mlirlite.LLVMModule*) -> int:
if mod is None:
return 0
g: llvmlite.GlobalVariable* = mod.GlobalHead
g: mlirlite.GlobalVariable* = mod.GlobalHead
steps: sizet = 0
while g is not None:
steps += 1
@@ -1128,23 +1128,23 @@ def _tb_module_has_global_ctors(mod: llvmlite.LLVMModule*) -> int:
# _tb_find_install_function - locate this module's own Install()
#
# Accepts "<16hex>.Install" (the usual SHA1-mangled form) or the bare name.
def _tb_find_install_function(mod: llvmlite.LLVMModule*) -> llvmlite.Function*:
def _tb_find_install_function(mod: mlirlite.LLVMModule*) -> mlirlite.Function*:
if mod is None:
return None
cur: llvmlite.Function* = mod.FuncHead
cur: mlirlite.Function* = mod.FuncHead
steps: sizet = 0
while cur is not None:
steps += 1
if steps > 100000:
return None
nm: str = llvmlite.function_get_name(cur)
nm: str = mlirlite.function_get_name(cur)
if nm is not None:
if string.strcmp(nm, "Install") == 0:
return cur
nl: sizet = llvmlite.function_get_name_len(cur)
nl: sizet = mlirlite.function_get_name_len(cur)
if nl == 24 and string.strcmp(nm + 16, ".Install") == 0:
return cur
cur = llvmlite.function_get_next(cur)
cur = mlirlite.function_get_next(cur)
return None
@@ -1162,63 +1162,63 @@ def InjectTracebackInstallCtor(tr: rawptr[Translator]) -> int:
if pool is None:
VLogger.error("--traceback: 内存池未初始化,无法注入 Install 构造器", "TRACEBACK")
return 1
mod: llvmlite.LLVMModule* = tr.Module
mod: mlirlite.LLVMModule* = tr.Module
if _tb_module_has_global_ctors(mod) != 0:
VLogger.error("--traceback: 模块内已存在 @llvm.global_ctors,无法注入 traceback 启动期构造器(不静默降级)", "TRACEBACK")
return 1
install_fn: llvmlite.Function* = _tb_find_install_function(mod)
install_fn: mlirlite.Function* = _tb_find_install_function(mod)
if install_fn is None:
VLogger.error("--traceback: 在 traceback 模块内找不到 Install() 函数,无法注入启动期构造器(不静默降级)", "TRACEBACK")
return 1
# 1) ctor: entry { call <ret> @Install(); ret void }
void_ty: llvmlite.LLVMType* = llvmlite.Void(pool)
ctor: llvmlite.Function* = llvmlite.new_function(pool, "__traceback_install_ctor", void_ty)
void_ty: mlirlite.LLVMType* = mlirlite.Void(pool)
ctor: mlirlite.Function* = mlirlite.new_function(pool, "__traceback_install_ctor", void_ty)
if ctor is None:
VLogger.error("--traceback: 构造器函数分配失败", "TRACEBACK")
return 1
blk: llvmlite.BasicBlock* = llvmlite.new_basic_block(pool, "entry")
blk: mlirlite.BasicBlock* = mlirlite.new_basic_block(pool, "entry")
if blk is None:
VLogger.error("--traceback: 构造器基本块分配失败", "TRACEBACK")
return 1
llvmlite.function_add_block(ctor, blk)
llvmlite.module_add_function(mod, ctor)
builder: llvmlite.IRBuilder* = llvmlite.new_builder(pool, ctor)
mlirlite.function_add_block(ctor, blk)
mlirlite.module_add_function(mod, ctor)
builder: mlirlite.IRBuilder* = mlirlite.new_builder(pool, ctor)
if builder is None:
VLogger.error("--traceback: 构造器 IRBuilder 分配失败", "TRACEBACK")
return 1
llvmlite.position_at_end(builder, blk)
iname: str = llvmlite.function_get_name(install_fn)
install_ret: llvmlite.LLVMType* = llvmlite.function_get_ret_ty(install_fn)
llvmlite.build_call(builder, iname, None, 0, install_ret, 0)
llvmlite.build_ret_void(builder)
mlirlite.position_at_end(builder, blk)
iname: str = mlirlite.function_get_name(install_fn)
install_ret: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(install_fn)
mlirlite.build_call(builder, iname, None, 0, install_ret, 0)
mlirlite.build_ret_void(builder)
# 2) @llvm.global_ctors = appending global [1 x {i32, void ()*, i8*}] [ ... ]
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8p_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
fnv_ty: llvmlite.LLVMType* = llvmlite.Func(pool, void_ty, None, 0)
fnp_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, fnv_ty)
f1: llvmlite.ParamNode* = llvmlite.new_param_node(pool, i32_ty)
f2: llvmlite.ParamNode* = llvmlite.new_param_node(pool, fnp_ty)
f3: llvmlite.ParamNode* = llvmlite.new_param_node(pool, i8p_ty)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8p_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
fnv_ty: mlirlite.LLVMType* = mlirlite.Func(pool, void_ty, None, 0)
fnp_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, fnv_ty)
f1: mlirlite.ParamNode* = mlirlite.new_param_node(pool, i32_ty)
f2: mlirlite.ParamNode* = mlirlite.new_param_node(pool, fnp_ty)
f3: mlirlite.ParamNode* = mlirlite.new_param_node(pool, i8p_ty)
if f1 is None or f2 is None or f3 is None:
VLogger.error("--traceback: global_ctors 结构体字段分配失败", "TRACEBACK")
return 1
llvmlite.paramnode_set_next(f1, f2)
llvmlite.paramnode_set_next(f2, f3)
elem_ty: llvmlite.LLVMType* = llvmlite.Struct(pool, f1, 3, None)
arr_ty: llvmlite.LLVMType* = llvmlite.Array(pool, elem_ty, 1)
mlirlite.paramnode_set_next(f1, f2)
mlirlite.paramnode_set_next(f2, f3)
elem_ty: mlirlite.LLVMType* = mlirlite.Struct(pool, f1, 3, None)
arr_ty: mlirlite.LLVMType* = mlirlite.Array(pool, elem_ty, 1)
if elem_ty is None or arr_ty is None:
VLogger.error("--traceback: global_ctors 类型构造失败", "TRACEBACK")
return 1
gv: llvmlite.GlobalVariable* = llvmlite.new_global_variable(pool, "llvm.global_ctors", arr_ty)
gv: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, "llvm.global_ctors", arr_ty)
if gv is None:
VLogger.error("--traceback: @llvm.global_ctors 全局变量分配失败", "TRACEBACK")
return 1
llvmlite.global_set_linkage(gv, "appending")
mlirlite.global_set_linkage(gv, "appending")
gv.Initializer = "[{ i32, void ()*, i8* } { i32 65535, void ()* @__traceback_install_ctor, i8* null }]"
llvmlite.module_add_global(mod, gv)
mlirlite.module_add_global(mod, gv)
VLogger.info("--traceback: 已注入启动期 Install() 构造器(@llvm.global_ctors)", "TRACEBACK")
return 0
+65 -65
View File
@@ -2,7 +2,7 @@ import lib.core.Gen.Generator as Generator
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdio
@@ -176,7 +176,7 @@ novirtual class TranslatorGenMixin:
# 用于模块级 t.CArray 列表字面量初始化(不依赖 builder,直接生成常量初始化器)
# ============================================================
def _build_array_initializer_text(self, pool: memhub.MemBuddy*,
var_ty: llvmlite.LLVMType*,
var_ty: mlirlite.LLVMType*,
list_node: ast.List*) -> str:
"""从 AST List 节点生成 LLVM IR 数组初始化器文本,None 失败"""
if var_ty is None or list_node is None:
@@ -189,10 +189,10 @@ novirtual class TranslatorGenMixin:
return None
# 从 var_ty 提取数组元素类型和数量
elem_ty: llvmlite.LLVMType* = None
elem_ty: mlirlite.LLVMType* = None
arr_count: int = 0
match var_ty:
case llvmlite.LLVMType.Array(et, cnt):
case mlirlite.LLVMType.Array(et, cnt):
elem_ty = et
arr_count = cnt
@@ -203,7 +203,7 @@ novirtual class TranslatorGenMixin:
elem_ir_ty: str = "i8"
is_int_elem: int = 1
match elem_ty:
case llvmlite.LLVMType.Int(bits):
case mlirlite.LLVMType.Int(bits):
is_int_elem = 1
if bits == 8:
elem_ir_ty = "i8"
@@ -236,7 +236,7 @@ novirtual class TranslatorGenMixin:
# 递归构建子数组初始化器文本,内层类型省略(由外层全局类型推断),llc 合法。
is_nested_arr: int = 0
match elem_ty:
case llvmlite.LLVMType.Array(_, _):
case mlirlite.LLVMType.Array(_, _):
is_nested_arr = 1
case _:
pass
@@ -255,7 +255,7 @@ novirtual class TranslatorGenMixin:
elem_ty_str_n: str = pool.alloc(96)
if elem_ty_str_n is None:
return None
llvmlite.TypePrint(elem_ty_str_n, 96, elem_ty, pool)
mlirlite.TypePrint(elem_ty_str_n, 96, elem_ty, pool)
i_n: sizet = 0
while i_n < cnt_total_n:
sub_n: str = None
@@ -361,14 +361,14 @@ novirtual class TranslatorGenMixin:
# 零填充到数组长度;空串返回 zeroinitializer)。
# 不能用字符串指针 GEP 初始化器:会导致 @g = global [N x i8] <ptr> 类型不匹配。
def _build_string_array_initializer_text(self, pool: memhub.MemBuddy*,
var_ty: llvmlite.LLVMType*,
var_ty: mlirlite.LLVMType*,
str_val: str) -> str:
"""字符串字面量初始化数组全局,返回初始化器文本或 None"""
if var_ty is None or str_val is None:
return None
arr_count: int = 0
match var_ty:
case llvmlite.LLVMType.Array(_, cnt):
case mlirlite.LLVMType.Array(_, cnt):
arr_count = cnt
if arr_count <= 0:
return None
@@ -403,7 +403,7 @@ novirtual class TranslatorGenMixin:
# 用于 b64_tab: t.CArray[char, None] = "ABC..." 等字符串初始化指针类型
# ============================================================
def _build_string_ptr_initializer(self, pool: memhub.MemBuddy*,
mod: llvmlite.LLVMModule*,
mod: mlirlite.LLVMModule*,
var_name: str,
str_val: str) -> str:
"""为字符串字面量创建内部常量全局并返回 GEP 初始化器文本,None 失败"""
@@ -416,8 +416,8 @@ novirtual class TranslatorGenMixin:
return None
viperlib.snprintf(str_name_buf, 64, ".str.%s", var_name)
# 调用 llvmlite.create_global_string 创建字符串常量全局
str_gv: llvmlite.GlobalVariable* = llvmlite.create_global_string(pool, mod, str_name_buf, str_val)
# 调用 mlirlite.create_global_string 创建字符串常量全局
str_gv: mlirlite.GlobalVariable* = mlirlite.create_global_string(pool, mod, str_name_buf, str_val)
if str_gv is None:
return None
@@ -432,7 +432,7 @@ novirtual class TranslatorGenMixin:
return init_buf
def _stg_field_zero_text(self, pool: memhub.MemBuddy*,
fty: llvmlite.LLVMType*,
fty: mlirlite.LLVMType*,
ty_str: str) -> str:
"""按 LLVM 类型生成 storage struct 字段的零值初始化器文本
@@ -446,11 +446,11 @@ novirtual class TranslatorGenMixin:
if buf is None:
return None
match fty:
case llvmlite.LLVMType.Ptr(_):
case mlirlite.LLVMType.Ptr(_):
viperlib.snprintf(buf, 160, "%s null", ty_str)
case llvmlite.LLVMType.Int(_):
case mlirlite.LLVMType.Int(_):
viperlib.snprintf(buf, 160, "%s 0", ty_str)
case llvmlite.LLVMType.Float(_):
case mlirlite.LLVMType.Float(_):
viperlib.snprintf(buf, 160, "%s 0.0", ty_str)
case _:
# Array / Struct 等 aggregate → zeroinitializer
@@ -464,7 +464,7 @@ novirtual class TranslatorGenMixin:
# 其余(浮点/字符串/None/名字/表达式)返回 None,由调用方按零值兜底。
# ============================================================
def _default_val_const_text(self, pool: memhub.MemBuddy*,
fty: llvmlite.LLVMType*,
fty: mlirlite.LLVMType*,
ty_str: str,
dval: ast.AST*) -> str:
"""字段默认值 → "ty 值" 文本;不可折叠返回 None"""
@@ -486,7 +486,7 @@ novirtual class TranslatorGenMixin:
return None
# 仅整型字段可写整数常量(浮点/指针/聚合交给零值兜底)
match fty:
case llvmlite.LLVMType.Int(_):
case mlirlite.LLVMType.Int(_):
pass
case _:
return None
@@ -526,7 +526,7 @@ novirtual class TranslatorGenMixin:
ty_str: str = pool.alloc(128)
if ty_str is None:
continue
llvmlite.TypePrint(ty_str, 128, fe.Ty, pool)
mlirlite.TypePrint(ty_str, 128, fe.Ty, pool)
elem: str = self._default_val_const_text(pool, fe.Ty, ty_str, fe.DefaultVal)
is_zero: int = 0
if elem is None:
@@ -574,7 +574,7 @@ novirtual class TranslatorGenMixin:
# 与函数侧口径差异:函数属性来自 decorator_list,提取为属性组文本
# `"section"="xxx"`(LLVM 字符串属性必须带引号,走 attributes #N);
# 全局变量属性没有属性组,直接写入 GlobalVariable.Section/Align/Linkage
# 字段,打印时由 includes/llvmlite/__module.vp 的 _print_global 补引号
# 字段,打印时由 includes/mlirlite/__module.vp 的 _print_global 补引号
# (`, section "xxx"` / `, align N`),故此处 Section 值不带引号。
# ============================================================
def _scan_global_tattr(self, node: ast.AST*,
@@ -671,7 +671,7 @@ novirtual class TranslatorGenMixin:
node: ast.AST*) -> int:
"""处理模块级变量声明,创建全局变量"""
pool: memhub.MemBuddy* = trans.Pool
mod: llvmlite.LLVMModule* = trans.Module
mod: mlirlite.LLVMModule* = trans.Module
# CDefine 注解: 编译期常量,不创建全局变量
# 注册到全局 CDefine 表供 t.CArray[elem_ty, NAME] 解析
@@ -702,8 +702,8 @@ novirtual class TranslatorGenMixin:
return 0
var_name: str = None
var_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
resolved_stg_ty: llvmlite.LLVMType* = None # 对象类全局:静态 storage 类型(BSS 实例)
var_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
resolved_stg_ty: mlirlite.LLVMType* = None # 对象类全局:静态 storage 类型(BSS 实例)
resolved_stg_entry: GenTypes.StructEntry* = None # 对象类全局:对应 StructEntry(vtable 初始化用)
init_val: int64 = 0
init_fval: t.CDouble = 0.0 # init_kind==4(浮点字面量)时的数值
@@ -748,7 +748,7 @@ novirtual class TranslatorGenMixin:
# (CallGenLeafKit.vp:698-699、:783-788),跨文件查找可见。
# t.CDefine/t.CTypedef 等分支已在 :675-689 提前返回,行为不变。
if annot_node is not None:
ml_callable_ret: llvmlite.LLVMType* = self.Gen.TypeGenErr.try_extract_callable_ret(pool, annot_node, trans._imported_modules,trans._from_imports, trans)
ml_callable_ret: mlirlite.LLVMType* = self.Gen.TypeGenErr.try_extract_callable_ret(pool, annot_node, trans._imported_modules,trans._from_imports, trans)
if ml_callable_ret is not None:
# 返回值:0=成功/同类型幂等命中;非 0 已在 register_func_ptr_sig
# 内部 fatal_error 终止编译,此处分支仅防御(见 AssignGenMixin 同处)。
@@ -756,13 +756,13 @@ novirtual class TranslatorGenMixin:
return 0
# 解析类型
if aa.annotation is not None:
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, aa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, aa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
if resolved is not None:
# 对象类模块级变量(@t.Object/@t.CVTable:对象即指针)→ Ptr(struct):
# 裸类名注解 resolve 返回 struct 值,模块级变量此处需包装 Ptr;若建成
# 值实例,跨模块字段访问/虚表调用会按指针处理读首 8 字节当 vtable → 崩溃。
# 纯 t.CStruct(无方法无虚表无 __new__)保持值实例。
if resolved.kind() == llvmlite.LLVMType.Struct:
if resolved.kind() == mlirlite.LLVMType.Struct:
gv_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_type(resolved)
if gv_entry is not None \
and (gv_entry.HasNew != 0 or gv_entry.HasVTable != 0 or gv_entry.IsOOP != 0):
@@ -771,13 +771,13 @@ novirtual class TranslatorGenMixin:
# 对象字段落在物理页 0。
resolved_stg_ty = resolved
resolved_stg_entry = gv_entry
resolved = llvmlite.Ptr(pool, resolved)
elif resolved.kind() == llvmlite.LLVMType.Ptr:
resolved = mlirlite.Ptr(pool, resolved)
elif resolved.kind() == mlirlite.LLVMType.Ptr:
# 对象类联合注解(T | t.CPtr → T*):同样创建 storage;否则入口/方法
# 虚调用 load @g 得 NULL → 读 [NULL] 拿 vtable → #PF。
# var_ty 保持 Ptr(联合注解语义:指针全局),storage 承载对象实例。
pointee_uv: llvmlite.LLVMType* = resolved.Pointee
if pointee_uv is not None and pointee_uv.kind() == llvmlite.LLVMType.Struct:
pointee_uv: mlirlite.LLVMType* = resolved.Pointee
if pointee_uv is not None and pointee_uv.kind() == mlirlite.LLVMType.Struct:
gv_entry_u: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_type(pointee_uv)
if gv_entry_u is not None \
and (gv_entry_u.HasNew != 0 or gv_entry_u.HasVTable != 0 or gv_entry_u.IsOOP != 0):
@@ -844,7 +844,7 @@ novirtual class TranslatorGenMixin:
# 无注解的模块级浮点赋值:字面量本身即类型依据,提升为 double
# (默认 var_ty 是 i32,不提升会把浮点位模式写进 i32 全局)
init_kind = 4
var_ty = llvmlite.Double(pool)
var_ty = mlirlite.Double(pool)
elif val_kind2 == ast.ASTKind.UnaryOp:
# 负数字面量(同 AnnAssign 分支,见上):UnaryOp(USub, Constant)
init_val = self.Gen.AssignGen.extract_cdefine_int_value(asgn.value)
@@ -878,7 +878,7 @@ novirtual class TranslatorGenMixin:
if init_kind == 4:
is_fty_g: int = 0
match var_ty:
case llvmlite.LLVMType.Float(_):
case mlirlite.LLVMType.Float(_):
is_fty_g = 1
case _:
pass
@@ -891,7 +891,7 @@ novirtual class TranslatorGenMixin:
return 0
# 检查是否已注册
existing: llvmlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, var_name)
existing: mlirlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, var_name)
if existing is not None:
return 0
@@ -900,7 +900,7 @@ novirtual class TranslatorGenMixin:
# 否则 @var_name = global %"sha1.ClassName"* zeroinitializer 会报
# "use of undefined type named 'sha1.ClassName'" 错误
# (如 _mbuddy: rawptr[memhub.MemManager] → Ptr(Struct("aeb3...MemManager")))
llvmlite.module_ensure_opaque_for_type(mod, pool, var_ty)
mlirlite.module_ensure_opaque_for_type(mod, pool, var_ty)
# 模块级全局命名带 SHA1 前缀(对齐函数名 mangling):多个模块声明同名
# 全局(如 _mbuddy)时各自独立命名,消除 ld.lld duplicate symbol。
# SymTab 注册 key 保持裸名(查找逻辑零改动),LLVM 符号名用 mangled 名。
@@ -933,27 +933,27 @@ novirtual class TranslatorGenMixin:
mangled_name: str = var_name
if is_global_cexport == 0 and is_global_extern == 0:
mangled_name = self.Gen.FuncGenBase._mangle_name(trans, var_name)
gv: llvmlite.GlobalVariable* = llvmlite.new_global_variable(pool, mangled_name, var_ty)
gv: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, mangled_name, var_ty)
if gv is None:
return 0
llvmlite.module_add_global(mod, gv)
mlirlite.module_add_global(mod, gv)
# 段名:直接写字段(_print_global 会补 `, section "xxx"` 的引号)。
if gv_attr_section is not None:
llvmlite.global_set_section(gv, gv_attr_section)
mlirlite.global_set_section(gv, gv_attr_section)
# B5:@c.Attribute(t.attr.aligned(N)) 类的全局实例施加对齐(如 fpu_context 16 对齐,
# FXSAVE 区域要求 16 字节对齐,否则 fxsave/fxrstor #GP)。
# 优先级:变量级显式 `T | t.attr.aligned(N)` 比类级(struct entry Align)更具体,
# 显式值胜出;无显式属性时沿用类级对齐(既有行为不变)。
al_ty: llvmlite.LLVMType* = var_ty
al_ty: mlirlite.LLVMType* = var_ty
match var_ty:
case llvmlite.LLVMType.Ptr(pointee_al):
case mlirlite.LLVMType.Ptr(pointee_al):
al_ty = pointee_al
case _:
pass
al_entry: GenTypes.StructEntry* = None
if al_ty is not None and al_ty.kind() == llvmlite.LLVMType.Struct:
if al_ty is not None and al_ty.kind() == mlirlite.LLVMType.Struct:
al_entry = self.Gen.StructGen.find_struct_by_type(al_ty)
if gv_attr_align > 0:
gv.Align = gv_attr_align
@@ -968,7 +968,7 @@ novirtual class TranslatorGenMixin:
gv.Linkage = None
# t.attr.weak → weak linkage(须在 Linkage 清空之后设置)。
if gv_attr_weak != 0:
llvmlite.global_set_linkage(gv, "weak")
mlirlite.global_set_linkage(gv, "weak")
if init_kind == 1:
# 整数初始值
init_buf: str = pool.alloc(48)
@@ -989,7 +989,7 @@ novirtual class TranslatorGenMixin:
# 不能用字符串指针 GEP 初始化器(@g = global [N x i8] <ptr> 类型不匹配)。
is_arr_g: int = 0
match var_ty:
case llvmlite.LLVMType.Array(_, _):
case mlirlite.LLVMType.Array(_, _):
is_arr_g = 1
case _:
pass
@@ -1009,9 +1009,9 @@ novirtual class TranslatorGenMixin:
self.Gen.TypeGenErr.fatal_error(node, f"模块级变量 '{var_name}' 初始化器构建失败", "TypeError")
elif init_kind == 4:
# 浮点初始值:LLVM IR 的浮点常量必须写成位模式文本(0x%016llx / 0x%08x)——
# 十进制文本经 llc 解析对部分值有 ±1 ulp 误差(见 llvmlite.ConstFloat 注释)。
# 十进制文本经 llc 解析对部分值有 ±1 ulp 误差(见 mlirlite.ConstFloat 注释)。
# 浮点分支缺失时模块级 t.CDouble 全局会退化成 zeroinitializer(值全变 0)。
fc_g: llvmlite.Value* = llvmlite.ConstFloat(pool, var_ty, init_fval)
fc_g: mlirlite.Value* = mlirlite.ConstFloat(pool, var_ty, init_fval)
if fc_g is not None and fc_g.Name is not None:
gv.Initializer = fc_g.Name
else:
@@ -1068,10 +1068,10 @@ novirtual class TranslatorGenMixin:
vt_cross = 1
if vt_cross != 0 \
and self.Gen.ExprGenAttr.find_global_in_module(mod, vt_mangled) is None:
vt_decl_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
vt_gv: llvmlite.GlobalVariable* = llvmlite.new_global_variable(pool, vt_mangled, vt_decl_ty)
vt_decl_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
vt_gv: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, vt_mangled, vt_decl_ty)
if vt_gv is not None:
llvmlite.module_add_global(mod, vt_gv)
mlirlite.module_add_global(mod, vt_gv)
# 完整 struct 初始化器(LLVM 拒绝部分初始化):
# 字段 0 = __vtable__(i8* @vtable),其余用户字段按类型零值。
init_full_len: sizet = 16384
@@ -1101,7 +1101,7 @@ novirtual class TranslatorGenMixin:
ty_buf_v: str = pool.alloc(128)
if ty_buf_v is None:
continue
llvmlite.TypePrint(ty_buf_v, 128, fe_v.Ty, pool)
mlirlite.TypePrint(ty_buf_v, 128, fe_v.Ty, pool)
zero_v: str = self._stg_field_zero_text(pool, fe_v.Ty, ty_buf_v)
if zero_v is None:
continue
@@ -1120,9 +1120,9 @@ novirtual class TranslatorGenMixin:
stg_name_buf: str = pool.alloc(stg_name_len)
if stg_name_buf is not None:
viperlib.snprintf(stg_name_buf, stg_name_len, "%s.stg", mangled_name)
stg_gv: llvmlite.GlobalVariable* = llvmlite.new_global_variable(pool, stg_name_buf, resolved_stg_ty)
stg_gv: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, stg_name_buf, resolved_stg_ty)
if stg_gv is not None:
llvmlite.module_add_global(mod, stg_gv)
mlirlite.module_add_global(mod, stg_gv)
stg_gv.Linkage = None
stg_gv.Initializer = stg_init_text
# B5:storage(BSS 对象实例)同样施加 aligned 对齐
@@ -1139,7 +1139,7 @@ novirtual class TranslatorGenMixin:
gv.Initializer = stg_init_buf
# 注册 storage 引用(key: var_name.__stg),供 AssignGenMixin
# 全局赋值分支检测对象类全局并复制对象到 storage。
stg_ref: llvmlite.Value* = self.Gen.ExprGenAttr.make_global_ref(pool, stg_name_buf, resolved_stg_ty)
stg_ref: mlirlite.Value* = self.Gen.ExprGenAttr.make_global_ref(pool, stg_name_buf, resolved_stg_ty)
if stg_ref is not None:
stg_key_len: sizet = sizet(string.strlen(var_name)) + 8
stg_key: str = pool.alloc(stg_key_len)
@@ -1148,7 +1148,7 @@ novirtual class TranslatorGenMixin:
self.Gen.VarGen.define_module_var(trans.SymTab, stg_key, stg_ref)
# 创建 Value 引用(@mangled_name, 类型为 var_ty*)
var_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, var_ty)
var_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, var_ty)
ref_name: str = pool.alloc(96)
if ref_name is not None:
# mangled 名带 SHA1 前缀(数字开头),引用必须加引号(对齐 make_global_ref)
@@ -1156,7 +1156,7 @@ novirtual class TranslatorGenMixin:
viperlib.snprintf(ref_name, 96, "@\"%s\"", mangled_name)
else:
viperlib.snprintf(ref_name, 96, "@%s", mangled_name)
gv_ref: llvmlite.Value* = llvmlite.SSAValue(pool, var_ptr_ty, ref_name)
gv_ref: mlirlite.Value* = mlirlite.SSAValue(pool, var_ptr_ty, ref_name)
# 注册到模块作用域
if self.Gen.VarGen.define_module_var(trans.SymTab, var_name, gv_ref) == 0:
@@ -1206,7 +1206,7 @@ novirtual class TranslatorGenMixin:
# ============================================================
def create_wrapper_main(self, trans: HT.Translator*,
tree: ast.AST*,
i32_ty: llvmlite.LLVMType*) -> int:
i32_ty: mlirlite.LLVMType*) -> int:
"""创建包装 main 函数并翻译所有顶层语句
Args:
@@ -1218,23 +1218,23 @@ novirtual class TranslatorGenMixin:
int: 新增的变量数
"""
pool: memhub.MemBuddy* = trans.Pool
mod: llvmlite.LLVMModule* = trans.Module
mod: mlirlite.LLVMModule* = trans.Module
main_func: llvmlite.Function* = llvmlite.create_function(pool, mod, "main", i32_ty)
main_func: mlirlite.Function* = mlirlite.create_function(pool, mod, "main", i32_ty)
if main_func is None:
VLogger.error("CreateFunction main returned NULL", "TR")
return 0
entry_blk: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, main_func, "entry")
entry_blk: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, main_func, "entry")
if entry_blk is None:
VLogger.error("CreateBlock returned NULL", "TR")
return 0
builder: llvmlite.IRBuilder* = llvmlite.new_builder(pool, main_func)
builder: mlirlite.IRBuilder* = mlirlite.new_builder(pool, main_func)
if builder is None:
VLogger.error("NewBuilder returned NULL", "TR")
return 0
llvmlite.position_at_end(builder, entry_blk)
mlirlite.position_at_end(builder, entry_blk)
# 设置当前翻译上下文(供 Handle 通过 self.Trans._cur_builder 访问)
trans._cur_func = main_func
@@ -1265,8 +1265,8 @@ novirtual class TranslatorGenMixin:
added_total: int = self.translate_children(trans, tree)
# 返回 0
zero_val: llvmlite.Value* = llvmlite.const_int32(pool, 0)
llvmlite.build_ret(builder, zero_val)
zero_val: mlirlite.Value* = mlirlite.const_int32(pool, 0)
mlirlite.build_ret(builder, zero_val)
return added_total
@@ -1312,7 +1312,7 @@ novirtual class TranslatorGenMixin:
return 0
def add_nonlocal_name(self, trans: HT.Translator*, name: str,
var_ty: llvmlite.LLVMType* = None):
var_ty: mlirlite.LLVMType* = None):
"""添加一个 nonlocal 变量名
Args:
@@ -1355,7 +1355,7 @@ novirtual class TranslatorGenMixin:
ty_addr2: uint64 = uint64(trans._nonlocal_types) + trans._nonlocal_name_count * 8
ty_slot2: str | t.CPtr = (str | t.CPtr)(ty_addr2)
# var_ty 为 None 时直接报错终止(fail-fast),不再默认 i32
stored_ty: llvmlite.LLVMType* = var_ty
stored_ty: mlirlite.LLVMType* = var_ty
if stored_ty is None:
self.Gen.TypeGenErr.fatal_error(None, f"nonlocal 变量 '{name}' 类型缺失,无法注册", "TypeError")
return
@@ -1364,7 +1364,7 @@ novirtual class TranslatorGenMixin:
trans._closure_env_count += 1
def get_nonlocal_type(self, trans: HT.Translator*,
name: str) -> llvmlite.LLVMType*:
name: str) -> mlirlite.LLVMType*:
"""获取 nonlocal 变量的 LLVM 类型
Returns: 找到的类型指针,找不到返回 None
@@ -1376,7 +1376,7 @@ novirtual class TranslatorGenMixin:
return None
ty_addr: uint64 = uint64(trans._nonlocal_types) + idx * 8
ty_slot: str | t.CPtr = (str | t.CPtr)(ty_addr)
return (llvmlite.LLVMType*)(ty_slot[0])
return (mlirlite.LLVMType*)(ty_slot[0])
def is_nonlocal_name(self, trans: HT.Translator*, name: str) -> int:
"""检查 name 是否在当前函数的 nonlocal 集合中"""
+1 -1
View File
@@ -4,7 +4,7 @@ import lib.core.Gen.Generator as Generator
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import hashtable
import string
+1 -1
View File
@@ -1,7 +1,7 @@
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import viperlib
+1 -1
View File
@@ -1,7 +1,7 @@
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import viperlib
+22 -22
View File
@@ -3,7 +3,7 @@ import lib.core.Gen.Generator as Generator
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import viperlib
@@ -183,7 +183,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase):
annot: ast.AST*,
imported_modules: str,
from_imports: str,
trans: HT.Translator*) -> llvmlite.LLVMType*:
trans: HT.Translator*) -> mlirlite.LLVMType*:
"""提取函数指针注解(t.Callable[[A,B], R] / callable[[A,B], R])的返回类型
LLVMType;非 Callable 注解或无签名形态([]、[[]])返回 None"""
if annot is None or annot.kind() != ast.ASTKind.Subscript:
@@ -264,7 +264,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase):
return self.has_decorator_marker(sub.slice, "CVolatile", 0)
def is_const_object_marker(self, node: ast.AST*,
var_ty: llvmlite.LLVMType*) -> int:
var_ty: mlirlite.LLVMType*) -> int:
"""变量/字段本身是否 **const 对象**(1=是 / 0=否)。
判据与 TPC 的 BaseGen._IsConstObject **逐条一致**(见 Debugger/type-descriptors.md):
@@ -279,7 +279,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase):
return 0
if var_ty is None:
return 0
if var_ty.kind() == llvmlite.LLVMType.Ptr:
if var_ty.kind() == mlirlite.LLVMType.Ptr:
return 0
return 1
@@ -298,23 +298,23 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase):
# 获取 LLVM 整数类型的位宽
# 实现已收拢到 TSpec.SpecTypeBits(该块在 TypeSpec 模块中的唯一实现),此处只做委托。
# 私有调用点(self.get_llvm_type_bits)保持原样不受影响。
def get_llvm_type_bits(self, ty: llvmlite.LLVMType*) -> int:
def get_llvm_type_bits(self, ty: mlirlite.LLVMType*) -> int:
"""获取 LLVM 整数类型的位宽,非整数类型返回 0(委托 SpecTypeBits)"""
return TSpec.SpecTypeBits(ty)
def infer_expr_type(self, pool: memhub.MemBuddy*,
node: ast.AST*,
param_types: str) -> llvmlite.LLVMType*:
param_types: str) -> mlirlite.LLVMType*:
"""推断表达式的 LLVM 类型
param_types 格式: "name:bits,name:bits,..."
"""
if node is None:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
k: int = node.kind()
if k == ast.ASTKind.Constant:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
elif k == ast.ASTKind.Name:
nm: ast.Name* = ast.Name*(node)
@@ -340,39 +340,39 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase):
else:
break
if bits == 64:
return llvmlite.Int64(pool)
return mlirlite.Int64(pool)
elif bits == 16:
return llvmlite.Int16(pool)
return mlirlite.Int16(pool)
elif bits == 8:
return llvmlite.Int8(pool)
return llvmlite.Int32(pool)
return mlirlite.Int8(pool)
return mlirlite.Int32(pool)
elif k == ast.ASTKind.BinOp:
binop: ast.BinOp* = ast.BinOp*(node)
lhs_ty: llvmlite.LLVMType* = self.infer_expr_type(pool, binop.left, param_types)
rhs_ty: llvmlite.LLVMType* = self.infer_expr_type(pool, binop.right, param_types)
lhs_ty: mlirlite.LLVMType* = self.infer_expr_type(pool, binop.left, param_types)
rhs_ty: mlirlite.LLVMType* = self.infer_expr_type(pool, binop.right, param_types)
lhs_bits: int = self.get_llvm_type_bits(lhs_ty)
rhs_bits: int = self.get_llvm_type_bits(rhs_ty)
if lhs_bits >= rhs_bits:
return lhs_ty
return rhs_ty
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
def infer_return_type(self, pool: memhub.MemBuddy*,
body: list[ast.AST*]*,
param_types: str) -> llvmlite.LLVMType*:
param_types: str) -> mlirlite.LLVMType*:
"""扫描函数体中的 return 语句,推断返回类型"""
if body is None:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
ret_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
ret_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
bn: sizet = len(body)
for bi in range(bn):
stmt: ast.AST* = body.get(bi)
if stmt is not None and stmt.kind() == ast.ASTKind.Return:
rt: rawptr[ast.Return] = rawptr[ast.Return](stmt)
if rt.value is not None:
expr_ty: llvmlite.LLVMType* = self.infer_expr_type(pool, rt.value, param_types)
expr_ty: mlirlite.LLVMType* = self.infer_expr_type(pool, rt.value, param_types)
if expr_ty is not None:
cur_bits: int = self.get_llvm_type_bits(ret_ty)
new_bits: int = self.get_llvm_type_bits(expr_ty)
@@ -457,19 +457,19 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase):
# 2) 单遍:解析类型 → 就地格式化条目 → 立即拼接(缓冲为上界,不会截断)
cnt: sizet = 0
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
for ai in range(an):
arg: ast.Arg* = ast.Arg*(alist.get(ai))
if arg is None or arg.arg is None:
continue
param_ty: llvmlite.LLVMType* = i32_ty
param_ty: mlirlite.LLVMType* = i32_ty
if arg.annotation is not None:
# 统一口径:CTypedef 动态表优先,miss 回退 map_t_type
# (阶段 2:删除 map_t_type 硬编码别名后,BYTE 等靠库 typedef)
if arg.annotation.kind() == ast.ASTKind.Attribute:
at: ast.Attribute* = ast.Attribute*(arg.annotation)
if at.attr is not None:
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_typedef_or_map(pool, at.attr, None, None)
resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_typedef_or_map(pool, at.attr, None, None)
if resolved is not None:
param_ty = resolved
bits: int = self.get_llvm_type_bits(param_ty)
+1 -1
View File
@@ -1,7 +1,7 @@
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdio
+142 -142
View File
@@ -6,7 +6,7 @@ import lib.core.Gen.Type.TypeGenMixin as TypeGenMixin
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import hashtable
import string
@@ -278,7 +278,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
e = self.Gen.StructGen.find_struct_by_module(cls_name, rr_sha)
if e is None or e.Ty is None:
return rr_sha
nm: str = llvmlite.get_struct_name(e.Ty)
nm: str = mlirlite.get_struct_name(e.Ty)
if nm is None:
return cand_sha1
# GenApi.sha1_prefix_len 返回的是**含末尾 '.' 的前缀字节数 17**(见其文档),
@@ -317,7 +317,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
def _resolve_nested_class_type(self, pool: memhub.MemBuddy*,
outer_name: str,
inner_name: str,
trans: HT.Translator*) -> llvmlite.LLVMType*:
trans: HT.Translator*) -> mlirlite.LLVMType*:
"""`外类.内类` → 嵌套类 Ty;无证据返回 None"""
if pool is None or outer_name is None or inner_name is None:
return None
@@ -347,7 +347,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
return None
def _repl_opaque_class_ty(self, pool: memhub.MemBuddy*,
mod_sha1: str,
cls_name: str) -> llvmlite.LLVMType*:
cls_name: str) -> mlirlite.LLVMType*:
"""(REPL 会话专用)未登记类别的"仅类型"占位:`%"{sha1}.{类名}"` opaque 具名结构体
背景:REPL 的 includes 类注册(M4.2)只登记**布局可信**的类;缺 `.stub.ll`
@@ -375,12 +375,12 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
full: str = self._concat_sha1_class(pool, mod_sha1, cls_name)
if full is None:
return None
ex: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(full)
ex: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(full)
if ex is not None:
return ex
# fcount=-1 = opaque 哨兵(区别于空结构体 {}:后者 fcount==0 是"完整定义、
# 可 alloca");与 llvmlite 的跨模块 opaque 声明同一表示。
return llvmlite.Struct(pool, None, -1, full)
# 可 alloca");与 mlirlite 的跨模块 opaque 声明同一表示。
return mlirlite.Struct(pool, None, -1, full)
def _is_count_arg_container(self, container: str) -> int:
"""该容器的**第 2 个实参**是否为「元素个数」(编译期整数,不是类型名)。
@@ -948,7 +948,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
_tp_buf: str = pool.alloc(288)
if _tp_buf is not None:
_tp_buf[0] = '\0'
llvmlite.TypePrint(_tp_buf, 288, _bare_entry.Ty, pool)
mlirlite.TypePrint(_tp_buf, 288, _bare_entry.Ty, pool)
_tp_nm: str = _tp_buf
if _tp_nm[0] == '%' and _tp_nm[1] == '"':
_tp_nm += 2
@@ -1026,7 +1026,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
_w_buf: str = pool.alloc(288)
if _w_buf is not None:
_w_buf[0] = '\0'
llvmlite.TypePrint(_w_buf, 288, _bare_entry.Ty, pool)
mlirlite.TypePrint(_w_buf, 288, _bare_entry.Ty, pool)
if _w_buf[0] != '\0': _w_ty = _w_buf
VLogger.error(
f"[类型实参归属] 裸类名 '{type_name}' 本次保留裸名(可能与带前缀形式分裂):"
@@ -1276,7 +1276,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
name: str,
imported_modules: str,
from_imports: str,
trans: HT.Translator* = None) -> llvmlite.LLVMType*:
trans: HT.Translator* = None) -> mlirlite.LLVMType*:
"""统一口径:CTypedef 动态表优先展开,miss 回退 map_t_type 硬编码
供 resolve_annotation_type 之外的旁路调用点(TypeGenErr/ClassGenEnum/
@@ -1292,7 +1292,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
inner_rt: ast.AST* = self._parse_type_string(pool, ts_rt, ast.ASTCtx.Load)
if inner_rt is not None:
self.Gen.TypeGenCType.CTypedefResolveDepth += 1
ity_rt: llvmlite.LLVMType* = self.resolve_annotation_type(pool, inner_rt, imported_modules, from_imports, trans, 1)
ity_rt: mlirlite.LLVMType* = self.resolve_annotation_type(pool, inner_rt, imported_modules, from_imports, trans, 1)
self.Gen.TypeGenCType.CTypedefResolveDepth -= 1
self.Gen.TypeGenCType._ctypedef_pop_visiting()
if ity_rt is not None:
@@ -1307,7 +1307,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if btd_node_r is not None:
if self.Gen.TypeGenCType.CTypedefResolveDepth < TypeGenMixin.MAX_CTYPEDEF_DEPTH:
self.Gen.TypeGenCType.CTypedefResolveDepth += 1
btd_ty_r: llvmlite.LLVMType* = self.resolve_annotation_type(pool, btd_node_r, imported_modules, from_imports, trans, 1)
btd_ty_r: mlirlite.LLVMType* = self.resolve_annotation_type(pool, btd_node_r, imported_modules, from_imports, trans, 1)
self.Gen.TypeGenCType.CTypedefResolveDepth -= 1
if btd_ty_r is not None:
return btd_ty_r
@@ -1323,7 +1323,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if lib_node is not None:
if self.Gen.TypeGenCType.CTypedefResolveDepth < TypeGenMixin.MAX_CTYPEDEF_DEPTH:
self.Gen.TypeGenCType.CTypedefResolveDepth += 1
lib_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, lib_node, imported_modules, from_imports, trans, 1)
lib_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, lib_node, imported_modules, from_imports, trans, 1)
self.Gen.TypeGenCType.CTypedefResolveDepth -= 1
if lib_ty is not None:
return lib_ty
@@ -1339,7 +1339,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
"""
if name is None:
return 0
ty_sz: llvmlite.LLVMType* = self.resolve_typedef_or_map(pool, name, imported_modules, from_imports)
ty_sz: mlirlite.LLVMType* = self.resolve_typedef_or_map(pool, name, imported_modules, from_imports)
if ty_sz is None:
return 0
bits_sz: int = self.Gen.TypeGenErr.get_llvm_type_bits(ty_sz)
@@ -1929,7 +1929,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
and string.strcmp(ts_x, type_str) != 0:
return self._expand_typedef_ref(pool, ts_x, depth + 1)
return type_str
def _long_llvm_ty(self, pool: memhub.MemBuddy*) -> llvmlite.LLVMType*:
def _long_llvm_ty(self, pool: memhub.MemBuddy*) -> mlirlite.LLVMType*:
"""C 的 long / unsigned long 的目标平台 LLVM 类型
Windows 目标(LLP64)下 long = 32 位——对齐 TPC
@@ -1947,8 +1947,8 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
or string.strstr(triple, "win32") is not None \
or string.strstr(triple, "mingw") is not None \
or string.strstr(triple, "msvc") is not None:
return llvmlite.Int32(pool)
return llvmlite.Int64(pool)
return mlirlite.Int32(pool)
return mlirlite.Int64(pool)
# ============================================================
# _IsCallableSubscriptValue - Subscript 的 value 是否为函数指针类型构造子
#
@@ -1996,7 +1996,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
def _forward_declare_ptr_from_node(self, pool: memhub.MemBuddy*,
node: ast.AST*,
imported_modules: str,
from_imports: str) -> llvmlite.LLVMType*:
from_imports: str) -> mlirlite.LLVMType*:
if node is None:
return None
cls_nm: str = None
@@ -2088,10 +2088,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
entry: GenTypes.StructEntry* = self.Gen.StructGen.ensure_forward_class(pool, sha1, cls_nm)
if entry is None or entry.Ty is None:
return None
return llvmlite.Ptr(pool, entry.Ty)
return mlirlite.Ptr(pool, entry.Ty)
def map_t_type(self, pool: memhub.MemBuddy*,
type_name: str) -> llvmlite.LLVMType*:
type_name: str) -> mlirlite.LLVMType*:
"""将 t.CXxx / c.CXxx 类型名映射到 LLVMType
注意: str = i8* = str = bytes
@@ -2101,53 +2101,53 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# 基本整数类型
if string.strcmp(type_name, "CInt") == 0:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
elif string.strcmp(type_name, "CChar") == 0:
return llvmlite.Int8(pool)
return mlirlite.Int8(pool)
elif string.strcmp(type_name, "CShort") == 0:
return llvmlite.Int16(pool)
return mlirlite.Int16(pool)
elif string.strcmp(type_name, "CLong") == 0:
# long 宽度随目标平台:Windows LLP64 = 32 位(对齐 TPC),LP64 = 64 位
return self._long_llvm_ty(pool)
elif string.strcmp(type_name, "CLongLong") == 0:
return llvmlite.Int64(pool)
return mlirlite.Int64(pool)
# 精确宽度有符号类型
elif string.strcmp(type_name, "CInt8T") == 0:
return llvmlite.Int8(pool)
return mlirlite.Int8(pool)
elif string.strcmp(type_name, "CInt16T") == 0:
return llvmlite.Int16(pool)
return mlirlite.Int16(pool)
elif string.strcmp(type_name, "CInt32T") == 0:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
elif string.strcmp(type_name, "CInt64T") == 0:
return llvmlite.Int64(pool)
return mlirlite.Int64(pool)
# 精确宽度无符号类型
elif string.strcmp(type_name, "CUInt8T") == 0:
return llvmlite.Int8(pool)
return mlirlite.Int8(pool)
elif string.strcmp(type_name, "CUInt16T") == 0:
return llvmlite.Int16(pool)
return mlirlite.Int16(pool)
elif string.strcmp(type_name, "CUInt32T") == 0:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
elif string.strcmp(type_name, "CUInt64T") == 0:
return llvmlite.Int64(pool)
return mlirlite.Int64(pool)
# 浮点类型
elif string.strcmp(type_name, "CFloat") == 0:
return llvmlite.Float(pool)
return mlirlite.Float(pool)
elif string.strcmp(type_name, "CDouble") == 0:
return llvmlite.Double(pool)
return mlirlite.Double(pool)
# 精确宽度浮点类型(t.py 的 float_map: 8/16→half, 32→float, 64→double, 128→fp128)
elif string.strcmp(type_name, "CFloat8T") == 0:
return llvmlite.Half(pool)
return mlirlite.Half(pool)
elif string.strcmp(type_name, "CFloat16T") == 0:
return llvmlite.Half(pool)
return mlirlite.Half(pool)
elif string.strcmp(type_name, "CFloat32T") == 0:
return llvmlite.Float(pool)
return mlirlite.Float(pool)
elif string.strcmp(type_name, "CFloat64T") == 0:
return llvmlite.Double(pool)
return mlirlite.Double(pool)
elif string.strcmp(type_name, "CFloat128T") == 0:
return llvmlite.FP128(pool)
return mlirlite.FP128(pool)
# 指针/void: t.CPtr = i8*, str = i8* = str = bytes
elif string.strcmp(type_name, "CPtr") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
# 无签名函数指针: t.Callable(裸名) → i8*,与带完整签名的
# t.Callable[[A, B], Ret](见 resolve_annotation_type 的 Subscript 分支)
# 同一 LLVM 表示:函数值按 TPV 惯例 bitcast 为 i8* 存储/传递。
@@ -2156,56 +2156,56 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# 大写裸名同时服务 `from t import Callable` 与 Attribute 分支的 t.Callable
# (Attribute 分支传 at.attr = "Callable")。
elif string.strcmp(type_name, "Callable") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
# 小写别名 callable:注解位置等价于 t.Callable(`func: callable = 函数名`)。
elif string.strcmp(type_name, "callable") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
# 裸名 void 是 t.CVoid 的别名(用户 2026-10-01 定):单独出现即 LLVM void;
# `void*`(= `void | t.CPtr`)由下方 BinOp 分支归并为 i8*。
elif string.strcmp(type_name, "CVoid") == 0 or string.strcmp(type_name, "void") == 0:
return llvmlite.Void(pool)
return mlirlite.Void(pool)
# CDefine: 编译期常量定义标记(X: t.CDefine = 64),底层为 32 位有符号整数
# (对齐 TPC t.CDefine Size=32 IsSigned=True;超大值由 DefineValue 路径升 i64)。
# 用作函数返回注解时表示宏函数(def MAKE_FLAG(bit) -> t.CDefine: return 1 << bit),
# 返回类型即 i32。全局/字段的 CDefine 注解已由 is_cdefine_annotation 先行短路
# (不创建 LLVM 全局/字段,仅注册编译期常量),不会走到此处。
elif string.strcmp(type_name, "CDefine") == 0:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
# CNeedPtr/CAutoPtr: 参数自动取地址标记,LLVM 层均为通用指针 i8*。
# (TPC 中二者继承 CPtr;TPV 未实现调用点自动取地址,非指针实参应在调用点报错,
# 而非静默降级为 i32 导致指针截断。)
elif string.strcmp(type_name, "CNeedPtr") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
elif string.strcmp(type_name, "CAutoPtr") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
# 无符号修饰
elif string.strcmp(type_name, "CUnsigned") == 0:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
elif string.strcmp(type_name, "CUnsignedInt") == 0:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
elif string.strcmp(type_name, "CUnsignedChar") == 0:
return llvmlite.Int8(pool)
return mlirlite.Int8(pool)
elif string.strcmp(type_name, "CUnsignedShort") == 0:
return llvmlite.Int16(pool)
return mlirlite.Int16(pool)
elif string.strcmp(type_name, "CUnsignedLong") == 0:
# unsigned long 同上:Windows LLP64 = 32 位(ULONG/DWORD 同宽),LP64 = 64 位
return self._long_llvm_ty(pool)
elif string.strcmp(type_name, "CUnsignedLongLong") == 0:
return llvmlite.Int64(pool)
return mlirlite.Int64(pool)
# size_t / ptr 类型
elif string.strcmp(type_name, "CSizeT") == 0:
return llvmlite.Int64(pool)
return mlirlite.Int64(pool)
elif string.strcmp(type_name, "CIntPtrT") == 0:
return llvmlite.Int64(pool)
return mlirlite.Int64(pool)
elif string.strcmp(type_name, "CUIntPtrT") == 0:
return llvmlite.Int64(pool)
return mlirlite.Int64(pool)
# bool
elif string.strcmp(type_name, "CBool") == 0:
# bool = t.CBool = i1(LLVM 1 位整数,语义与 C _Bool 一致)
return llvmlite.Int1(pool)
return mlirlite.Int1(pool)
# ptrdiff_t
elif string.strcmp(type_name, "CPtrDiffT") == 0:
return llvmlite.Int64(pool)
return mlirlite.Int64(pool)
# ============================================================
# stdint.vp 大写/定长/小写/指针/C 标准别名(INT/BYTE/DWORD/int8_t/
@@ -2218,11 +2218,11 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# char = char = i8;int/bool 由 resolve_annotation_type Name 分支直通,
# 小写 stdint 别名由 stdint.vp CTypedef 声明提供)
elif string.strcmp(type_name, "char") == 0:
return llvmlite.Int8(pool)
return mlirlite.Int8(pool)
elif string.strcmp(type_name, "float") == 0:
return llvmlite.Float(pool)
return mlirlite.Float(pool)
elif string.strcmp(type_name, "double") == 0:
return llvmlite.Double(pool)
return mlirlite.Double(pool)
return None
def _is_t_attr(self, node: ast.AST*,
attr_name: str,
@@ -2658,7 +2658,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
trans: HT.Translator*,
imported_modules: str,
from_imports: str,
depth: int = 0) -> llvmlite.LLVMType*:
depth: int = 0) -> mlirlite.LLVMType*:
"""解析泛型类类型注解(特化或查找已注册结构体),失败返回 None"""
if pool is None or sub is None or gen_cls_name is None:
return None
@@ -2684,27 +2684,27 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
tp_count = 1
if tp_count == 0 or tp_elts is None:
return None
tup_head: llvmlite.ParamNode* = None
tup_tail: llvmlite.ParamNode* = None
tup_head: mlirlite.ParamNode* = None
tup_tail: mlirlite.ParamNode* = None
tui: sizet
for tui in range(tp_count):
tup_elt: ast.AST* = tp_elts.get(tui)
if tup_elt is None:
continue
tup_ety: llvmlite.LLVMType* = self.resolve_annotation_type(pool, tup_elt, imported_modules, from_imports, trans, depth + 1)
tup_ety: mlirlite.LLVMType* = self.resolve_annotation_type(pool, tup_elt, imported_modules, from_imports, trans, depth + 1)
if tup_ety is None:
return None
tup_node: llvmlite.ParamNode* = llvmlite.new_param_node(pool, tup_ety)
tup_node: mlirlite.ParamNode* = mlirlite.new_param_node(pool, tup_ety)
if tup_node is None:
return None
if tup_head is None:
tup_head = tup_node
else:
llvmlite.paramnode_set_next(tup_tail, tup_node)
mlirlite.paramnode_set_next(tup_tail, tup_node)
tup_tail = tup_node
if tup_head is None:
return None
return llvmlite.Struct(pool, tup_head, tp_count, None)
return mlirlite.Struct(pool, tup_head, tp_count, None)
# 先收集类型实参名,再分配缓冲区拼接 mangled name(elem_size=8:str 是指针)
gen_arg_names: list[str]* = list[str](pool, 8)
if sub.slice.kind() == ast.ASTKind.Tuple:
@@ -2770,7 +2770,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if trans is not None and trans.ReplCtx is not None \
and VpiReader.ReplStubLayoutMode != 0:
# 已登记的特化结构体(会话期先前注册)直接复用:本分支只读、不翻译
spec_ty_inj: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(gen_mangled)
spec_ty_inj: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(gen_mangled)
if spec_ty_inj is not None:
return spec_ty_inj
# 归属模块 sha1:优先取**全局模板表**(步骤③'' 已按 includes 全量注册,
@@ -2780,14 +2780,14 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if inj_owner is None:
inj_owner = StubMergerStore.LookupGenericOwnerSha1(gen_cls_name)
if inj_owner is not None:
ty_inj: llvmlite.LLVMType* = self._repl_opaque_class_ty(pool, inj_owner, gen_mangled)
ty_inj: mlirlite.LLVMType* = self._repl_opaque_class_ty(pool, inj_owner, gen_mangled)
if ty_inj is not None:
return ty_inj
# 归属未知(模板/归属均未登记)⇒ 保持原口径返回 None,由上层按
# "注解解析失败"明确报错(不伪造无模块前缀的类名)
return None
# 查找已特化的 struct(特化由实例化调用 list[int](pool) 触发)
gen_spec_ty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(gen_mangled)
gen_spec_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(gen_mangled)
if gen_spec_ty is not None:
# Phase B 补译泛型特化类方法体:Phase 1a 特化时只注册结构体不译方法体,
# Phase B 解析字段类型命中已注册结构体时本会早返回 → 方法体永不生成
@@ -2861,7 +2861,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if trans is not None and trans.ReplCtx is not None:
gowner_sha1: str = StubMergerStore.LookupGenericOwnerSha1(gen_cls_name)
if gowner_sha1 is not None:
ty_repl_g: llvmlite.LLVMType* = self._repl_opaque_class_ty(pool, gowner_sha1, gen_mangled)
ty_repl_g: mlirlite.LLVMType* = self._repl_opaque_class_ty(pool, gowner_sha1, gen_mangled)
if ty_repl_g is not None:
return ty_repl_g
# 未特化:返回 None(不报错,让后续流程处理)
@@ -2910,7 +2910,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
imported_modules: str,
from_imports: str,
trans: HT.Translator* = None,
depth: int = 0) -> llvmlite.LLVMType*:
depth: int = 0) -> mlirlite.LLVMType*:
"""解析类型注解节点为 LLVMType
Args:
@@ -2940,7 +2940,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if k == ast.ASTKind.Constant:
cn: ast.Constant* = ast.Constant*(node)
if cn.const_kind == ast.CONST_NONE:
return llvmlite.Void(pool)
return mlirlite.Void(pool)
if cn.const_kind == ast.CONST_STR and cn.str_val is not None:
sub_node: ast.AST* = self._parse_type_string(pool, cn.str_val, ast.ASTCtx.Load)
if sub_node is not None:
@@ -3026,30 +3026,30 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# 天然同口径,故 TPC 无需同步改)。
return sp_entry2.Ty
# 兜底:按完整前缀名直接查(部分注册键即全名)
sp_full2: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(nm.id)
sp_full2: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(nm.id)
if sp_full2 is not None:
return sp_full2
return None
# str = bytes = str = i8*
if string.strcmp(nm.id, "str") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
elif string.strcmp(nm.id, "None") == 0:
return llvmlite.Void(pool)
return mlirlite.Void(pool)
elif string.strcmp(nm.id, "int") == 0:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
elif string.strcmp(nm.id, "char") == 0:
# char = char = i8(与 map_t_type 中 CChar/char 映射一致)
return llvmlite.Int8(pool)
return mlirlite.Int8(pool)
elif string.strcmp(nm.id, "bytes") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
elif string.strcmp(nm.id, "bool") == 0:
# bool = t.CBool = i1(与 map_t_type 中 CBool 映射一致)
return llvmlite.Int1(pool)
return mlirlite.Int1(pool)
# 裸名浮点类型: float = t.CFloat = f32, double = t.CDouble = f64
elif string.strcmp(nm.id, "float") == 0:
return llvmlite.Float(pool)
return mlirlite.Float(pool)
elif string.strcmp(nm.id, "double") == 0:
return llvmlite.Double(pool)
return mlirlite.Double(pool)
# class 名称: 查找已注册的 StructType,返回 StructType 本身(不包装 Ptr)
# 这样 build_alloca 会分配结构体大小的空间,alloca 返回 struct_ty*
# 命名空间隔离:严格模式下仅解析可见的结构体
@@ -3104,7 +3104,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# 裸类名恒为原型(见上方同口径注释)
return fi_entry.Ty
if self.Gen.StructGen.is_struct_visible(nm.id) != 0:
struct_ty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(nm.id)
struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(nm.id)
if struct_ty is not None:
# 裸类名恒为原型(见上方同口径注释):不再因 HasNew 升成 Ptr
return struct_ty
@@ -3124,7 +3124,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
inner_node: ast.AST* = self._parse_type_string(pool, ctypedef_str, nm.ctx)
if inner_node is not None:
self.Gen.TypeGenCType.CTypedefResolveDepth += 1
inner_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, inner_node, imported_modules, from_imports, trans, depth + 1)
inner_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, inner_node, imported_modules, from_imports, trans, depth + 1)
self.Gen.TypeGenCType.CTypedefResolveDepth -= 1
self.Gen.TypeGenCType._ctypedef_pop_visiting()
if inner_ty is not None:
@@ -3135,7 +3135,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# 这些是跨模块通用的 C typedef 名,即使 from-import 查找失败也能解析
# 注意:from-import 的结构体名若未注册,get_struct_type 已返回 None,
# 此处 map_t_type 对结构体名也返回 None,由上层 declare_only 机制延迟到下一遍
mapped_ty_fallback: llvmlite.LLVMType* = self.map_t_type(pool, nm.id)
mapped_ty_fallback: mlirlite.LLVMType* = self.map_t_type(pool, nm.id)
if mapped_ty_fallback is not None:
return mapped_ty_fallback
# [阶段1a] from-import 别名反查(正常库分析):from t import CInt as XXX
@@ -3158,7 +3158,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# 用原始名重建节点递归解析(depth 守卫复用 resolve 上限)
orig_node_a: ast.AST* = self._parse_type_string(pool, oa_buf, nm.ctx)
if orig_node_a is not None:
alias_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, orig_node_a, imported_modules, from_imports, trans, depth + 1)
alias_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, orig_node_a, imported_modules, from_imports, trans, depth + 1)
if alias_ty is not None:
return alias_ty
# [builtins 最后匹配] 常规路径全部 miss 后的最终兜底:查
@@ -3168,7 +3168,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if btd_n is not None:
btd_node_n: ast.AST* = self._parse_type_string(pool, btd_n, nm.ctx)
if btd_node_n is not None:
btd_ty_n: llvmlite.LLVMType* = self.resolve_annotation_type(pool, btd_node_n, imported_modules, from_imports, trans, depth + 1)
btd_ty_n: mlirlite.LLVMType* = self.resolve_annotation_type(pool, btd_node_n, imported_modules, from_imports, trans, depth + 1)
if btd_ty_n is not None:
return btd_ty_n
# 库 typedef 兜底:stdint / w32.win32base 等库模块的裸 typedef
@@ -3181,7 +3181,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if lib_ts_n is not None:
lib_node_n: ast.AST* = self._parse_type_string(pool, lib_ts_n, nm.ctx)
if lib_node_n is not None:
lib_ty_n: llvmlite.LLVMType* = self.resolve_annotation_type(pool, lib_node_n, imported_modules, from_imports, trans, depth + 1)
lib_ty_n: mlirlite.LLVMType* = self.resolve_annotation_type(pool, lib_node_n, imported_modules, from_imports, trans, depth + 1)
if lib_ty_n is not None:
return lib_ty_n
# [REPL 会话] 归属模块已知(from_imports 解析出 sha1;或本模块自身 =
@@ -3203,7 +3203,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
and string.strcmp(trans.ModuleSha1, GenTypes.REPL_SESSION_SHA1) != 0:
own_sha_rn = trans.ModuleSha1
if own_sha_rn is not None:
ty_repl_n: llvmlite.LLVMType* = self._repl_opaque_class_ty(pool, own_sha_rn, nm.id)
ty_repl_n: mlirlite.LLVMType* = self._repl_opaque_class_ty(pool, own_sha_rn, nm.id)
if ty_repl_n is not None:
return ty_repl_n
return None
@@ -3254,7 +3254,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# 前缀、非已导入模块、非库 typedef ⇒ 原本必然返回 None,
# 故新增"扁平名 `外类_内类` 命中即返回"不会覆盖任何既有
# 成功路径(命名口径见 ClassGenDef._translate_nested_classdefs)。
nested_ty_q: llvmlite.LLVMType* = \
nested_ty_q: mlirlite.LLVMType* = \
self._resolve_nested_class_type(pool, val_name.id, at.attr, trans)
if nested_ty_q is not None:
return nested_ty_q
@@ -3270,19 +3270,19 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
inner_attr: ast.AST* = self._parse_type_string(pool, ctypedef_attr, ast.ASTCtx.Load)
if inner_attr is not None:
self.Gen.TypeGenCType.CTypedefResolveDepth += 1
inner_ty_attr: llvmlite.LLVMType* = self.resolve_annotation_type(pool, inner_attr, imported_modules, from_imports, trans, depth + 1)
inner_ty_attr: mlirlite.LLVMType* = self.resolve_annotation_type(pool, inner_attr, imported_modules, from_imports, trans, depth + 1)
self.Gen.TypeGenCType.CTypedefResolveDepth -= 1
self.Gen.TypeGenCType._ctypedef_pop_visiting()
if inner_ty_attr is not None:
return inner_ty_attr
# 先尝试内置类型映射(int 等)
mapped_ty: llvmlite.LLVMType* = self.map_t_type(pool, at.attr)
mapped_ty: mlirlite.LLVMType* = self.map_t_type(pool, at.attr)
if mapped_ty is not None:
return mapped_ty
# 模块限定类类型:Module.ClassName(命名空间隔离)
# SHA1 前缀形态优先用完整名 "{sha1}.{Class}" 精确命中定义侧
# struct(get_struct_type 类名回退可能命中跨模块同名类)
full_attr_ty: llvmlite.LLVMType* = None
full_attr_ty: mlirlite.LLVMType* = None
# mod_sha1_rv:把本分支解析出的"模块段 sha1"带到末尾(REPL 会话的
# "仅类型"占位兜底要用它;声明在此以覆盖下方 SHA1 前缀形态与枚举/
# typedef 尝试都在同一作用域)。
@@ -3327,7 +3327,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if mod_sha1_v is not None:
full_q_v: str = self._concat_sha1_class(pool, mod_sha1_v, at.attr)
if full_q_v is not None:
full_ty_v: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(full_q_v)
full_ty_v: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(full_q_v)
if full_ty_v is not None:
return full_ty_v
mod_entry_v: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(at.attr, mod_sha1_v)
@@ -3347,7 +3347,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if string.strcmp(mod_sha1_td, mod_sha1_v) != 0:
full_q_td: str = self._concat_sha1_class(pool, mod_sha1_td, at.attr)
if full_q_td is not None:
full_ty_td: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(full_q_td)
full_ty_td: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(full_q_td)
if full_ty_td is not None:
return full_ty_td
mod_entry_td: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(at.attr, mod_sha1_td)
@@ -3358,7 +3358,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# 模块名未登记(未编译/未扫描):同样不裸名回退
else:
# t/c 内置库限定:裸名回退合法(内置类名无跨模块冲突)
mod_struct_ty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(at.attr)
mod_struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(at.attr)
if mod_struct_ty is not None:
return mod_struct_ty
# 模块限定枚举类型:Module.EnumClass(如 fat32_types.FRESULT,
@@ -3375,7 +3375,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
mod_td_inner: ast.AST* = self._parse_type_string(pool, mod_td_str, at.ctx)
if mod_td_inner is not None:
self.Gen.TypeGenCType.CTypedefResolveDepth += 1
mod_td_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, mod_td_inner, imported_modules, from_imports, trans, depth + 1)
mod_td_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, mod_td_inner, imported_modules, from_imports, trans, depth + 1)
self.Gen.TypeGenCType.CTypedefResolveDepth -= 1
self.Gen.TypeGenCType._ctypedef_pop_visiting()
if mod_td_ty is not None:
@@ -3387,7 +3387,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# 不可解析被跳过)⇒ 用 opaque 具名类型占位(不写 StructTable ⇒
# 字段访问仍按"类未注册"明确报错)。批处理 trans.ReplCtx 恒 None。
if trans is not None and trans.ReplCtx is not None and mod_sha1_rv is not None:
ty_repl_a: llvmlite.LLVMType* = self._repl_opaque_class_ty(pool, mod_sha1_rv, at.attr)
ty_repl_a: mlirlite.LLVMType* = self._repl_opaque_class_ty(pool, mod_sha1_rv, at.attr)
if ty_repl_a is not None:
return ty_repl_a
return None
@@ -3395,7 +3395,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# at.value 是 Attribute 而非 Name,递归提取最终类名(at.attr)查结构体表
# find_struct 支持模块限定名回退,此处用最外层 attr(简单类名)即可
if at.value is not None and at.value.kind() == ast.ASTKind.Attribute:
nested_struct_ty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(at.attr)
nested_struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(at.attr)
if nested_struct_ty is not None:
return nested_struct_ty
# 嵌套模块限定的枚举类(fat32_types.FRESULT 三级名):查枚举基类型
@@ -3411,14 +3411,14 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
nested_inner: ast.AST* = self._parse_type_string(pool, nested_td_str, at.ctx)
if nested_inner is not None:
self.Gen.TypeGenCType.CTypedefResolveDepth += 1
nested_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, nested_inner, imported_modules, from_imports, trans, depth + 1)
nested_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, nested_inner, imported_modules, from_imports, trans, depth + 1)
self.Gen.TypeGenCType.CTypedefResolveDepth -= 1
self.Gen.TypeGenCType._ctypedef_pop_visiting()
if nested_ty is not None:
return nested_ty
else:
self.Gen.TypeGenCType._ctypedef_pop_visiting()
mapped_ty_na: llvmlite.LLVMType* = self.map_t_type(pool, at.attr)
mapped_ty_na: mlirlite.LLVMType* = self.map_t_type(pool, at.attr)
if mapped_ty_na is not None:
return mapped_ty_na
# 嵌套模块限定 typedef 兜底(w32.win32base.HANDLE = t.CTypedef =
@@ -3432,7 +3432,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if lib_td_na is not None:
td_node_na: ast.AST* = self._parse_type_string(pool, lib_td_na, at.ctx)
if td_node_na is not None:
td_ty_na: llvmlite.LLVMType* = self.resolve_annotation_type(pool, td_node_na, imported_modules, from_imports, trans, depth + 1)
td_ty_na: mlirlite.LLVMType* = self.resolve_annotation_type(pool, td_node_na, imported_modules, from_imports, trans, depth + 1)
if td_ty_na is not None:
return td_ty_na
return None
@@ -3476,8 +3476,8 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# 内置别名 void:t.CVoid 同义,无需 import t
other_is_cvoid = 1
if other_is_cvoid != 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
other_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, other_node, imported_modules, from_imports, trans, depth + 1)
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
other_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, other_node, imported_modules, from_imports, trans, depth + 1)
# 解析结果本身即 void(如 `typedef 不透明结构体 = void` 的那个名字,
# 或经 typedef 兜底解析出的 void)⇒ 与 CPtr 合并即 void* = i8*,
# 与上方 other_is_cvoid 分支同一结论(否则会拼出非法的 Ptr(void))。
@@ -3488,8 +3488,8 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# None 交由下方既有 `if other_ty is None:` 分支处理。
if other_ty is not None:
match other_ty:
case llvmlite.LLVMType.Void():
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
case mlirlite.LLVMType.Void():
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
case _:
pass
# 仅裸名(Name)场景验证解析结果必须是已注册 struct:
@@ -3554,7 +3554,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if other_nm_td.id is not None:
td_res_is_ptr: int = 0
match other_ty:
case llvmlite.LLVMType.Ptr(pointee_td):
case mlirlite.LLVMType.Ptr(pointee_td):
if self.Gen.StructGen.find_struct_by_type(pointee_td) is not None:
td_res_is_ptr = 1
else:
@@ -3562,7 +3562,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
case _:
td_res_is_ptr = 0
if td_res_is_ptr == 0:
td_alias_ty: llvmlite.LLVMType* = self.resolve_typedef_or_map(pool, other_nm_td.id, imported_modules, from_imports, trans)
td_alias_ty: mlirlite.LLVMType* = self.resolve_typedef_or_map(pool, other_nm_td.id, imported_modules, from_imports, trans)
if td_alias_ty is not None:
keep_other_ty = 1
if keep_other_ty == 0:
@@ -3582,9 +3582,9 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if other_nm.id is not None:
other_cls_nm = other_nm.id
if other_cls_nm is not None:
other_cls_ty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(other_cls_nm)
other_cls_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(other_cls_nm)
if other_cls_ty is not None:
return llvmlite.Ptr(pool, other_cls_ty)
return mlirlite.Ptr(pool, other_cls_ty)
# 类名未注册:可能是前向自我引用(如 json 的
# 'JsonValue' | t.CPtr 字段引用自身类,类体处理中
# 尚未注册)、或 Phase A-pre 依赖类延迟到下一遍注册、
@@ -3594,11 +3594,11 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# (定义侧随后原位填充)。无法确定类名/模块时,才退回
# Ptr(i8) 由 AnnotClassName 恢复 + 多遍注册收敛,禁止
# fail-fast(误杀合法前向引用)。
_fwd_ptr_ty: llvmlite.LLVMType* = self._forward_declare_ptr_from_node(
_fwd_ptr_ty: mlirlite.LLVMType* = self._forward_declare_ptr_from_node(
pool, other_node, imported_modules, from_imports)
if _fwd_ptr_ty is not None:
return _fwd_ptr_ty
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
# `X | t.CPtr` **恒追加恰好 1 层**(用户口径,与 rawptr[T]/t.CPtr[T] 下标形
# 以及 `_parse_type_string` 的 `T*` 反解析三处同源):
# T* ≡ rawptr[T] ≡ t.CPtr[T] ≡ T | t.CPtr
@@ -3614,7 +3614,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# Ptr(已注册 struct) ⇒ 误吸收把 `T*` 降成 AST*(应为 AST**),
# 现场 includes/_list.vp:54 `elem_ptr[0] = item` 被误判为"左值元素是对象
# AST(48 字节)、右值是指针"而 fail-fast。
return llvmlite.Ptr(pool, other_ty)
return mlirlite.Ptr(pool, other_ty)
# t.CPtr[...] 下标指针标记(普通 _is_cptr_marker 不识别 Subscript):
# X | t.CPtr[T] → 指针层级合并(对齐 TPC HandlesTypeMerge.py L864-884:
@@ -3629,31 +3629,31 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
cptr_sub_side = bop.right
cptr_other = bop.left
if cptr_sub_side is not None and cptr_other is not None:
cptr_sub_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, cptr_sub_side, imported_modules, from_imports, trans, depth + 1)
cptr_other_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, cptr_other, imported_modules, from_imports, trans, depth + 1)
cptr_sub_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, cptr_sub_side, imported_modules, from_imports, trans, depth + 1)
cptr_other_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, cptr_other, imported_modules, from_imports, trans, depth + 1)
if cptr_sub_ty is not None and cptr_other_ty is not None:
# 计算 CPtr 侧外层 Ptr 嵌套数(如 t.CPtr[t.CPtr]=i8** → 2 层)
cptr_level: int = 0
cur_lvl: llvmlite.LLVMType* = cptr_sub_ty
cur_lvl: mlirlite.LLVMType* = cptr_sub_ty
while cur_lvl is not None:
# 注意:不能在 case body 内直接更新 while 条件变量
# (cur_lvl = cur_lvl.Pointee)——自举编译出的 match 会把
# 赋值写到 subject 快照槽,while 条件仍读旧槽 → 死循环
# (gen2 编 FuncTest 卡死根因,gdb 反汇编 +3770-3819 确认)。
# 改法:case 绑定 pointee 到局部变量,match 外更新循环变量。
nxt_lvl: llvmlite.LLVMType* = None
nxt_lvl: mlirlite.LLVMType* = None
match cur_lvl:
case llvmlite.LLVMType.Ptr(pointee):
case mlirlite.LLVMType.Ptr(pointee):
cptr_level += 1
nxt_lvl = pointee
case _:
break
cur_lvl = nxt_lvl
# 结果 = 另一侧类型外包 N 层 Ptr
res_ty: llvmlite.LLVMType* = cptr_other_ty
res_ty: mlirlite.LLVMType* = cptr_other_ty
li2: int = 0
while li2 < cptr_level:
res_ty = llvmlite.Ptr(pool, res_ty)
res_ty = mlirlite.Ptr(pool, res_ty)
li2 += 1
return res_ty
@@ -3667,11 +3667,11 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# → `@g = global i8 <ptr>` 非法 IR(opt: got 'ptr' but expected 'i8')。
# 故标记侧**跳过**(既不参与竞争,也不进入解析)。
if self._is_tattr_marker(bop.left) == 0:
left_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, bop.left, imported_modules, from_imports, trans, depth + 1)
left_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, bop.left, imported_modules, from_imports, trans, depth + 1)
if left_ty is not None:
return left_ty
if self._is_tattr_marker(bop.right) == 0:
right_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, bop.right, imported_modules, from_imports, trans, depth + 1)
right_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, bop.right, imported_modules, from_imports, trans, depth + 1)
if right_ty is not None:
return right_ty
return None
@@ -3696,7 +3696,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# 完整签名的返回类型注册见 TypeGenErr.try_extract_callable_ret。
if sub.value.kind() == ast.ASTKind.Name \
and self._IsCallableSubscriptValue(sub.value) != 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
# 泛型类类型注解: list[int] → 查找已特化的 struct(value 是 Name 泛型类名)
if sub.value.kind() == ast.ASTKind.Name:
gen_nm: ast.Name* = ast.Name*(sub.value)
@@ -3720,7 +3720,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
cnt_arr0: ast.Constant* = ast.Constant*(count_node_arr)
if cnt_arr0.const_kind == ast.CONST_NONE:
self.Gen.TypeGenErr.fatal_type_error(count_node_arr, "内建定长数组构造子 'array' 的长度必须是正整型常量(>0),不允许 None(长度自动推导请改用 t.CArray[E])。正确示例:state: array[uint32, 4]")
elem_ty_arr: llvmlite.LLVMType* = self.resolve_annotation_type(pool, elem_node_arr, imported_modules, from_imports, trans, depth + 1)
elem_ty_arr: mlirlite.LLVMType* = self.resolve_annotation_type(pool, elem_node_arr, imported_modules, from_imports, trans, depth + 1)
if elem_ty_arr is None:
return None
count_arr: int = self.Gen.TypeGenCType._eval_const_int_expr(count_node_arr, pool, from_imports, imported_modules)
@@ -3728,17 +3728,17 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
self.Gen.TypeGenErr.fatal_type_error(count_node_arr, "内建定长数组构造子 'array' 的长度必须是整型常量表达式(字面量 / CDefine 常量名 / 常量算术表达式)。正确示例:state: array[uint8, MAX_LEN]")
if count_arr <= 0:
self.Gen.TypeGenErr.fatal_type_error(count_node_arr, "内建定长数组构造子 'array' 的长度必须为正数。正确示例:state: array[uint32, 4]")
return llvmlite.Array(pool, elem_ty_arr, count_arr)
return mlirlite.Array(pool, elem_ty_arr, count_arr)
# 裸名 CArray(from t import * 场景):与 t.CArray 语义等价——否则走泛型
# 模板查找失败 → 字段类型退化 Ptr(i8) → 默认值 List 字面量误走动态 list
# 构造(符号未生成 → 链接 undefined reference)。
if string.strcmp(gen_nm.id, "CArray") == 0 or string.strcmp(gen_nm.id, "rawarray") == 0:
# 单参数: CArray[elem_ty] → Ptr(elem_ty)(静态推导长度数组)
if sub.slice.kind() != ast.ASTKind.Tuple:
elem_n: llvmlite.LLVMType* = self.resolve_annotation_type(pool, sub.slice, imported_modules, from_imports, trans, depth + 1)
elem_n: mlirlite.LLVMType* = self.resolve_annotation_type(pool, sub.slice, imported_modules, from_imports, trans, depth + 1)
if elem_n is None:
return None
return llvmlite.Ptr(pool, elem_n)
return mlirlite.Ptr(pool, elem_n)
# 双参数: CArray[elem_ty, count] → [count x elem_ty]
tup_n: ast.Tuple* = ast.Tuple*(sub.slice)
if tup_n.elts is None or len(tup_n.elts) < 2:
@@ -3747,18 +3747,18 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
count_node_n: ast.AST* = tup_n.elts.get(1)
if elem_node_n is None or count_node_n is None:
return None
elem_ty_n: llvmlite.LLVMType* = self.resolve_annotation_type(pool, elem_node_n, imported_modules, from_imports, trans, depth + 1)
elem_ty_n: mlirlite.LLVMType* = self.resolve_annotation_type(pool, elem_node_n, imported_modules, from_imports, trans, depth + 1)
if elem_ty_n is None:
return None
# count=None → Ptr(elem)(等价单参)
if count_node_n.kind() == ast.ASTKind.Constant:
cnt_n: ast.Constant* = ast.Constant*(count_node_n)
if cnt_n.const_kind == ast.CONST_NONE:
return llvmlite.Ptr(pool, elem_ty_n)
return mlirlite.Ptr(pool, elem_ty_n)
count_n: int = self.Gen.TypeGenCType._eval_const_int_expr(count_node_n, pool, from_imports, imported_modules)
if self.Gen.TypeGenCType.ConstEvalOk == 0 or count_n <= 0:
return None
return llvmlite.Array(pool, elem_ty_n, count_n)
return mlirlite.Array(pool, elem_ty_n, count_n)
# rawptr[T] 内建裸指针:等价 t.CPtr[T] → Ptr(T)(T 自身可含指针层级)。
# 与 t.CPtr[T] 语义一致;不处理则泛型特化/builtins 兜底失败 →
# "函数返回类型解析失败:注解不可解析"。
@@ -3772,12 +3772,12 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# AST(48 字节)、右值是指针"而 fail-fast。
if string.strcmp(gen_nm.id, "rawptr") == 0:
if sub.slice.kind() != ast.ASTKind.Tuple:
rp_elem: llvmlite.LLVMType* = self.resolve_annotation_type(pool, sub.slice, imported_modules, from_imports, trans, depth + 1)
rp_elem: mlirlite.LLVMType* = self.resolve_annotation_type(pool, sub.slice, imported_modules, from_imports, trans, depth + 1)
if rp_elem is None:
return None
return llvmlite.Ptr(pool, rp_elem)
return mlirlite.Ptr(pool, rp_elem)
return None
gen_ty_nm: llvmlite.LLVMType* = self._resolve_generic_subscript_ty(pool, sub, gen_nm.id, trans,
gen_ty_nm: mlirlite.LLVMType* = self._resolve_generic_subscript_ty(pool, sub, gen_nm.id, trans,
imported_modules, from_imports, depth + 1)
if gen_ty_nm is not None:
return gen_ty_nm
@@ -3802,7 +3802,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
string.strcat(fb_str, "]")
fb_node: ast.AST* = self._parse_type_string(pool, fb_str, ast.ASTCtx.Load)
if fb_node is not None:
fb_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, fb_node, imported_modules, from_imports, trans, depth + 1)
fb_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, fb_node, imported_modules, from_imports, trans, depth + 1)
if fb_ty is not None:
return fb_ty
return None
@@ -3830,7 +3830,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if string.strcmp(arr_val_name.id, "t") != 0 and string.strcmp(arr_val_name.id, "c") != 0 \
and self.Gen.ImportsGen.is_module_imported(imported_modules, arr_val_name.id) == 0:
self.Gen.TypeGenErr.fatal_type_error(node, "t.Callable 模块未导入")
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
# 指针类型: t.CPtr[T] → Ptr(T)(T 自身可含指针层级):t.CPtr[t.CPtr] → i8**,
# t.CPtr[int] → i32*(DeclarationGenerator.py L1014-1016 文档化语法)。
# **恒追加 1 层,无例外**(与 rawptr[T] 分支同口径):`t.CPtr[T]` ≡ `T*`
@@ -3841,7 +3841,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if string.strcmp(arr_val_name.id, "t") != 0 and string.strcmp(arr_val_name.id, "c") != 0 \
and self.Gen.ImportsGen.is_module_imported(imported_modules, arr_val_name.id) == 0:
self.Gen.TypeGenErr.fatal_type_error(node, "t.CPtr 模块未导入")
inner_cptr_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, sub.slice, imported_modules, from_imports, trans, depth + 1)
inner_cptr_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, sub.slice, imported_modules, from_imports, trans, depth + 1)
if inner_cptr_ty is None:
# 元素类型依赖未就绪(如 t.CPtr[类]/rawptr[类] 中类尚未注册,
# rawptr[T] 经 builtins typedef 归一到本分支):优先**前向声明**
@@ -3849,12 +3849,12 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# X|t.CPtr 分支与 TPC);无法确定类名/模块时仍返回 None 交上层
# 多遍收敛,不在此 fatal 中断 Phase 1a 预注册(UINT 等只经
# CTypedef 动态表解析)。真实类型错误由 Phase A 收敛检查暴露。
_fwd_cptr_ty: llvmlite.LLVMType* = self._forward_declare_ptr_from_node(
_fwd_cptr_ty: mlirlite.LLVMType* = self._forward_declare_ptr_from_node(
pool, sub.slice, imported_modules, from_imports)
if _fwd_cptr_ty is not None:
return _fwd_cptr_ty
return None
return llvmlite.Ptr(pool, inner_cptr_ty)
return mlirlite.Ptr(pool, inner_cptr_ty)
if string.strcmp(arr_at.attr, "CArray") != 0:
self.Gen.TypeGenErr.fatal_type_error(node, "不支持的 Subscript 类型注解(仅支持 t.CArray / t.Callable)")
if string.strcmp(arr_val_name.id, "t") != 0 and string.strcmp(arr_val_name.id, "c") != 0 \
@@ -3863,11 +3863,11 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# 单参数形式: t.CArray[elem_ty] → Ptr(elem_ty)
# 相当于 t.CArray[elem_ty, None],表示静态推导长度数组
if sub.slice.kind() != ast.ASTKind.Tuple:
elem_ty_single: llvmlite.LLVMType* = self.resolve_annotation_type(pool, sub.slice, imported_modules, from_imports, trans, depth + 1)
elem_ty_single: mlirlite.LLVMType* = self.resolve_annotation_type(pool, sub.slice, imported_modules, from_imports, trans, depth + 1)
if elem_ty_single is None:
# 元素类型依赖未就绪(同 L1807 注释):返回 None 交多遍收敛
return None
return llvmlite.Ptr(pool, elem_ty_single)
return mlirlite.Ptr(pool, elem_ty_single)
# 双参数形式: t.CArray[elem_ty, count] → [count x elem_ty]
tup: ast.Tuple* = ast.Tuple*(sub.slice)
if tup.elts is None:
@@ -3881,7 +3881,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if elem_node is None or count_node is None:
self.Gen.TypeGenErr.fatal_type_error(node, "t.CArray Tuple 元素为 None")
# 递归解析元素类型
elem_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, elem_node, imported_modules, from_imports, trans, depth + 1)
elem_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, elem_node, imported_modules, from_imports, trans, depth + 1)
if elem_ty is None:
# 元素类型依赖未就绪(如 t.CArray[类, N] 中类尚未注册):返回 None 交上层多遍
# 收敛,不在此 fatal 中断 Phase 1a 预注册(UINT 等只经 CTypedef 动态表解析,
@@ -3896,7 +3896,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if count_node.kind() == ast.ASTKind.Constant:
cnt_cn: ast.Constant* = ast.Constant*(count_node)
if cnt_cn.const_kind == ast.CONST_NONE:
return llvmlite.Ptr(pool, elem_ty)
return mlirlite.Ptr(pool, elem_ty)
# 统一用 _eval_const_int_expr 计算常量整数表达式
# 支持 Constant(INT)、Name(CDefine)、BinOp(2*MAX 等算术/位运算)
# 传入 pool/from_imports/imported_modules 支持跨模块 CDefine 查找
@@ -3908,7 +3908,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
self.Gen.TypeGenErr.fatal_type_error(count_node, "t.CArray count 必须为正数")
# 创建 ArrayType(不包装 Ptr)
# 这样 build_alloca 会分配数组大小的空间,alloca 返回 [N x elem_ty]*
return llvmlite.Array(pool, elem_ty, count_val)
return mlirlite.Array(pool, elem_ty, count_val)
# 未知 AST kind:fail-fast,不宽容返回 None
self.Gen.TypeGenErr.fatal_type_error(node, "不支持的类型注解语法")
+27 -27
View File
@@ -1,6 +1,6 @@
import t, c
from stdint import *
import llvmlite
import mlirlite
import memhub
import string
import viperlib
@@ -212,7 +212,7 @@ class TypeSpec:
ElemBits: int # 元素槽位宽(元素语义三元组 1/3)
IsElemPtr: int # 元素是否为指针(1=是)(2/3)
DerefBase: int # 基址是否需二次解引用(1=是)(3/3)
Ty: llvmlite.LLVMType* # 解析结果缓存(可空)
Ty: mlirlite.LLVMType* # 解析结果缓存(可空)
# ============================================================
@@ -1087,16 +1087,16 @@ def SpecBitWidth(sp: TypeSpec*) -> int:
# ⚠️ 规避自举 match codegen 缺陷:`case` 体内直接更新外层 while 条件变量会把赋值
# 写进 subject 快照槽,while 条件读旧槽 ⇒ 死循环。故此处 `case` 只绑定局部 `nxt`,
# 循环变量在 match **外**更新。
def SpecTypePtrLevel(ty: llvmlite.LLVMType*) -> int:
def SpecTypePtrLevel(ty: mlirlite.LLVMType*) -> int:
"""计算指针层级,0=非指针,1=一级指针,2=二级指针…"""
if ty is None:
return 0
level: int = 0
cur: llvmlite.LLVMType* = ty
cur: mlirlite.LLVMType* = ty
while cur is not None:
nxt: llvmlite.LLVMType* = None
nxt: mlirlite.LLVMType* = None
match cur:
case llvmlite.LLVMType.Ptr(pointee):
case mlirlite.LLVMType.Ptr(pointee):
level += 1
nxt = pointee
case _:
@@ -1114,24 +1114,24 @@ def SpecTypePtrLevel(ty: llvmlite.LLVMType*) -> int:
# 副本一旦分叉会出现「同一类型在两处算出不同位宽」的隐蔽不一致。
# 非整数类型(指针/浮点/结构体等)返回 0 —— 0 是"非整数"的表态,不是兜底位宽。
# ============================================================
def SpecTypeBits(ty: llvmlite.LLVMType*) -> int:
def SpecTypeBits(ty: mlirlite.LLVMType*) -> int:
"""获取 LLVM 整数类型的位宽,非整数类型返回 0"""
if ty is None:
return 0
match ty:
case llvmlite.LLVMType.Int(bits):
case mlirlite.LLVMType.Int(bits):
return bits
case _:
return 0
# ============================================================
# SpecToLLVMText - TypeSpec → LLVM IR 类型文本(**逐字节对齐 llvmlite.TypePrint**)
# SpecToLLVMText - TypeSpec → LLVM IR 类型文本(**逐字节对齐 mlirlite.TypePrint**)
#
# 用途:作为 FuncEntry.Spec 的 LLVM 文本派生源(旧 FuncEntry.TypeStr 字符串生产者
# 已在 S4 删除),推进去字符串化(Debugger/_Type.md D14 起)。
#
# 对齐依据:`includes/llvmlite/__types.vp:395-511` 的 `_TypePrintDepth`,逐分支照搬:
# 对齐依据:`includes/mlirlite/__types.vp:395-511` 的 `_TypePrintDepth`,逐分支照搬:
# Int(bits) → "iN"(**无符号也是 iN** —— LLVM 文本层不分符号)
# Float(bits) → 16/32/64/128 → half/float/double/fp128;其它 → "float%x"(十六进制)
# Void → "void"
@@ -1266,7 +1266,7 @@ def _spec_llvm_text(sp: TypeSpec*, buf: str, buf_size: sizet,
# 只做**结构层**翻译:Int / Float / Void / Ptr / Array / Func / Struct。
# - 指针层级:由 Ptr 递归得到(NewTypePtr 内 PtrLevel = Elem.PtrLevel + 1)
# - 数组维度:取 Array.Count(元素语义三元组由 NewTypeArray 填)
# - 函数签名:Ret + 形参数组(沿 ParamNode 链表遍历;llvmlite **无按下标取参**)
# - 函数签名:Ret + 形参数组(沿 ParamNode 链表遍历;mlirlite **无按下标取参**)
# - 结构体:取结构体名;匿名结构体退化为无名 TS_STRUCT
#
# ⚠️ 两个**已知局限**(有意为之,避免臆造):
@@ -1274,39 +1274,39 @@ def _spec_llvm_text(sp: TypeSpec*, buf: str, buf_size: sizet,
# `TS_INT + TS_SIGN_SIGNED`(与 SpecBaseText 的 "iN" 编码口径一致,保证驻留键
# 不产生"同键不同义")。**无符号性必须由注解侧(符号性真源)覆盖**;
# 消费方在 S3 切读前**不要直接信任**本 spec 的 IsSigned。
# 2. 变参:`...` 不在 `LLVMType.Func` 上(只存在于 `llvmlite.Function.IsVarArg`)
# 2. 变参:`...` 不在 `LLVMType.Func` 上(只存在于 `mlirlite.Function.IsVarArg`)
# ⇒ 本转换器恒置 IsVarArg=0;带变参的签名需由函数对象侧补写。
#
# 本函数当前**无调用点**(S2 只入库;接线在后续步骤)。
# ============================================================
def SpecFromLLVMType(arena: TypeSpecArena | t.CPtr,
ty: llvmlite.LLVMType*) -> TypeSpec*:
ty: mlirlite.LLVMType*) -> TypeSpec*:
"""把已解析的 LLVM 类型翻译成 TypeSpec;不支持或为 None 时返回 None"""
if arena is None or ty is None:
return None
match ty:
case llvmlite.LLVMType.Int(bits):
case mlirlite.LLVMType.Int(bits):
if bits == 1:
return NewTypeSpec(arena, TS_BOOL, 1, TS_SIGN_UNSIGNED)
return NewTypeSpec(arena, TS_INT, bits, TS_SIGN_SIGNED)
case llvmlite.LLVMType.Float(bits):
case mlirlite.LLVMType.Float(bits):
return NewTypeSpec(arena, TS_FLOAT, bits, TS_SIGN_SIGNED)
case llvmlite.LLVMType.Void():
case mlirlite.LLVMType.Void():
return NewTypeSpec(arena, TS_VOID, 0, TS_SIGN_UNKNOWN)
case llvmlite.LLVMType.Ptr(pointee):
case mlirlite.LLVMType.Ptr(pointee):
return _spec_from_ptr(arena, pointee)
case llvmlite.LLVMType.Array(elem_ty, count):
case mlirlite.LLVMType.Array(elem_ty, count):
return _spec_from_array(arena, elem_ty, count)
case llvmlite.LLVMType.Func(ret, params, pcount):
case mlirlite.LLVMType.Func(ret, params, pcount):
return _spec_from_func(arena, ret, params, pcount)
case llvmlite.LLVMType.Struct(_, _, sname):
case mlirlite.LLVMType.Struct(_, _, sname):
return _spec_from_struct(arena, sname)
case _:
return None
def _spec_from_ptr(arena: TypeSpecArena | t.CPtr,
pointee: llvmlite.LLVMType*) -> TypeSpec*:
pointee: mlirlite.LLVMType*) -> TypeSpec*:
"""Ptr(pointee) → TypeSpec(PtrLevel/ElemBits/IsElemPtr 由 NewTypePtr 填)"""
inner: TypeSpec* = SpecFromLLVMType(arena, pointee)
if inner is None:
@@ -1315,7 +1315,7 @@ def _spec_from_ptr(arena: TypeSpecArena | t.CPtr,
def _spec_from_array(arena: TypeSpecArena | t.CPtr,
elem_ty: llvmlite.LLVMType*,
elem_ty: mlirlite.LLVMType*,
count: int) -> TypeSpec*:
"""[count x elem] → TypeSpec(ArrayCount/ElemBits/IsElemPtr 由 NewTypeArray 填)"""
inner: TypeSpec* = SpecFromLLVMType(arena, elem_ty)
@@ -1325,8 +1325,8 @@ def _spec_from_array(arena: TypeSpecArena | t.CPtr,
def _spec_from_func(arena: TypeSpecArena | t.CPtr,
ret: llvmlite.LLVMType*,
params: llvmlite.ParamNode*,
ret: mlirlite.LLVMType*,
params: mlirlite.ParamNode*,
pcount: int) -> TypeSpec*:
"""函数类型 → TypeSpec(形参沿 ParamNode 链表遍历;IsVarArg 恒 0,见上)"""
ret_s: TypeSpec* = SpecFromLLVMType(arena, ret)
@@ -1338,10 +1338,10 @@ def _spec_from_func(arena: TypeSpecArena | t.CPtr,
params_arr: sizet* = CompilerFactory.factory.PermPool.alloc(8 * pcount)
if params_arr is None:
return None
node: llvmlite.ParamNode* = params
node: mlirlite.ParamNode* = params
i: int = 0
while node is not None and i < pcount:
pty: llvmlite.LLVMType* = llvmlite.paramnode_get_ty(node)
pty: mlirlite.LLVMType* = mlirlite.paramnode_get_ty(node)
ps: TypeSpec* = SpecFromLLVMType(arena, pty)
if ps is None:
return None
@@ -1349,7 +1349,7 @@ def _spec_from_func(arena: TypeSpecArena | t.CPtr,
if slot is None:
return None
slot[0] = sizet(ps)
node = llvmlite.paramnode_get_next(node)
node = mlirlite.paramnode_get_next(node)
i += 1
return NewTypeFunc(arena, ret_s, params_arr, pcount, 0)
+155 -155
View File
@@ -6,7 +6,7 @@ import lib.core.Gen.Translator as HT
import t, c
from stdint import *
import ast
import llvmlite
import mlirlite
import memhub
import string
import stdlib
@@ -48,7 +48,7 @@ novirtual class VarGenMixin:
# ============================================================
def find_var(self, vars_ptr: GenTypes.VarEntry*,
var_count: int,
name: str) -> llvmlite.Value*:
name: str) -> mlirlite.Value*:
"""在变量表中按名称查找"""
if name is None or vars_ptr is None:
return None
@@ -265,7 +265,7 @@ novirtual class VarGenMixin:
def add_var(self, vars_ptr: GenTypes.VarEntry*,
var_count: int,
name: str,
alloca: llvmlite.Value*) -> int:
alloca: mlirlite.Value*) -> int:
"""添加变量到变量表"""
if name is None or alloca is None or vars_ptr is None:
return 1
@@ -302,11 +302,11 @@ novirtual class VarGenMixin:
# SpecFromLLVMType 不支持者)返回 None —— 后者是设计内的「不适用」,非兜底。
# 分配一律 PermPool 驻留 ⇒ 跨文件/跨 1b reset 安全。
# ============================================================
def _spec_of_var_alloca(self, alloca: llvmlite.Value*) -> TSpec.TypeSpec*:
def _spec_of_var_alloca(self, alloca: mlirlite.Value*) -> TSpec.TypeSpec*:
"""由 alloca 的值类型构造 TypeSpec,不适用/失败返回 None"""
if alloca is None or alloca.Ty is None:
return None
ty: llvmlite.LLVMType* = alloca.Ty
ty: mlirlite.LLVMType* = alloca.Ty
if self.Gen.ExprGenBase.is_ptr_type(ty) != 0:
ty = ty.Pointee
arena: TSpec.TypeSpecArena* = self.Gen.TypeGenBase.ensure_spec_arena()
@@ -317,29 +317,29 @@ novirtual class VarGenMixin:
# _alloca_at_entry - 在函数入口块生成 alloca(确保支配性)
# LLVM IR 要求指令支配所有使用点,故所有 alloca 须在函数入口块生成。
# 实现:临时切换 builder.CurBlock 到入口块,生成 alloca 后恢复。
def _alloca_at_entry(self, builder: llvmlite.IRBuilder*,
ty: llvmlite.LLVMType*) -> llvmlite.Value*:
def _alloca_at_entry(self, builder: mlirlite.IRBuilder*,
ty: mlirlite.LLVMType*) -> mlirlite.Value*:
"""在函数入口块生成 alloca,返回 alloca 值
使用 llvmlite.build_alloca_at_entry 在入口块终止指令之前插入 alloca,
使用 mlirlite.build_alloca_at_entry 在入口块终止指令之前插入 alloca,
确保所有 alloca 在入口块,避免支配性违规。
"""
if builder is None or ty is None:
return None
return llvmlite.build_alloca_at_entry(builder, ty)
return mlirlite.build_alloca_at_entry(builder, ty)
# get_or_create_var — 查找或创建变量 alloca(旧版兼容)
def get_or_create_var(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
builder: mlirlite.IRBuilder*,
vars_ptr: GenTypes.VarEntry*,
var_count: int,
name: str,
ty: llvmlite.LLVMType*) -> llvmlite.Value*:
ty: mlirlite.LLVMType*) -> mlirlite.Value*:
"""查找或创建变量 alloca"""
existing: llvmlite.Value* = self.find_var(vars_ptr, var_count, name)
existing: mlirlite.Value* = self.find_var(vars_ptr, var_count, name)
if existing is not None:
return existing
alloca: llvmlite.Value* = self._alloca_at_entry(builder, ty)
alloca: mlirlite.Value* = self._alloca_at_entry(builder, ty)
if alloca is None:
return None
if self.add_var(vars_ptr, var_count, name, alloca) != 0:
@@ -415,7 +415,7 @@ novirtual class VarGenMixin:
# ============================================================
def define_var(self, symtab: rawptr[GenTypes.SymbolTable],
name: str,
alloca: llvmlite.Value*) -> int:
alloca: mlirlite.Value*) -> int:
"""在当前作用域定义变量,返回 0 成功"""
if symtab is None or name is None or alloca is None:
return 1
@@ -432,7 +432,7 @@ novirtual class VarGenMixin:
# ============================================================
def define_module_var(self, symtab: rawptr[GenTypes.SymbolTable],
name: str,
alloca: llvmlite.Value*) -> int:
alloca: mlirlite.Value*) -> int:
"""在模块作用域定义变量,返回 0 成功"""
if symtab is None or name is None or alloca is None:
return 1
@@ -448,13 +448,13 @@ novirtual class VarGenMixin:
# lookup_var — 从当前作用域逐级向上查找变量
# ============================================================
def lookup_var(self, symtab: rawptr[GenTypes.SymbolTable],
name: str) -> llvmlite.Value*:
name: str) -> mlirlite.Value*:
"""从当前作用域逐级向上查找变量,返回 alloca 或 None"""
if symtab is None or name is None:
return None
scope: rawptr[GenTypes.Scope] = symtab.Current
while scope is not None:
result: llvmlite.Value* = self.find_var(scope.Vars, scope.VarCount, name)
result: mlirlite.Value* = self.find_var(scope.Vars, scope.VarCount, name)
if result is not None:
return result
scope = scope.Parent
@@ -464,7 +464,7 @@ novirtual class VarGenMixin:
# lookup_current — 仅在当前作用域查找变量
# ============================================================
def lookup_current(self, symtab: rawptr[GenTypes.SymbolTable],
name: str) -> llvmlite.Value*:
name: str) -> mlirlite.Value*:
"""仅在当前作用域查找变量"""
if symtab is None or name is None:
return None
@@ -477,7 +477,7 @@ novirtual class VarGenMixin:
# lookup_module_var — 在模块作用域查找变量
# ============================================================
def lookup_module_var(self, symtab: rawptr[GenTypes.SymbolTable],
name: str) -> llvmlite.Value*:
name: str) -> mlirlite.Value*:
"""在模块作用域查找变量"""
if symtab is None or name is None:
return None
@@ -509,13 +509,13 @@ novirtual class VarGenMixin:
# _lookup_through_match_scope — 穿越 match case 作用域查找变量
def _lookup_through_match_scope(self, symtab: rawptr[GenTypes.SymbolTable],
name: str) -> llvmlite.Value*:
name: str) -> mlirlite.Value*:
"""从当前作用域向上,仅穿越 SCOPE_MATCH 作用域查找变量 alloca"""
if symtab is None or name is None:
return None
scope: rawptr[GenTypes.Scope] = symtab.Current
while scope is not None:
result: llvmlite.Value* = self.find_var(scope.Vars, scope.VarCount, name)
result: mlirlite.Value* = self.find_var(scope.Vars, scope.VarCount, name)
if result is not None:
return result
if scope.Kind == SCOPE_MATCH:
@@ -529,18 +529,18 @@ novirtual class VarGenMixin:
# ============================================================
def get_or_create_sym(self, symtab: rawptr[GenTypes.SymbolTable],
pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
builder: mlirlite.IRBuilder*,
name: str,
ty: llvmlite.LLVMType*) -> llvmlite.Value*:
ty: mlirlite.LLVMType*) -> mlirlite.Value*:
"""查找或创建变量 alloca(在当前作用域)"""
existing: llvmlite.Value* = self.lookup_current(symtab, name)
existing: mlirlite.Value* = self.lookup_current(symtab, name)
if existing is not None:
return existing
# SCOPE_MATCH 隔离作用域对"赋值"必须透明:
existing = self._lookup_through_match_scope(symtab, name)
if existing is not None:
return existing
alloca: llvmlite.Value* = self._alloca_at_entry(builder, ty)
alloca: mlirlite.Value* = self._alloca_at_entry(builder, ty)
if alloca is None:
return None
if self.define_var(symtab, name, alloca) != 0:
@@ -598,16 +598,16 @@ novirtual class VarGenMixin:
# ---- repl_ctx_ptr — 取片段函数 ctx 形参的值(i8*) ----
def repl_ctx_ptr(self, trans: HT.Translator*,
ctx: rawptr[GenTypes.ReplCtx],
node: ast.AST*) -> llvmlite.Value*:
node: ast.AST*) -> mlirlite.Value*:
"""load 片段函数 ctx 形参(形参 alloca 由 FuncGenDef 建);失败 fail-fast"""
if trans is None or ctx is None or ctx.CtxParam is None:
return None
symtab: rawptr[GenTypes.SymbolTable] = trans.SymTab
param_alloca: llvmlite.Value* = self.lookup_var(symtab, ctx.CtxParam)
param_alloca: mlirlite.Value* = self.lookup_var(symtab, ctx.CtxParam)
if param_alloca is None or param_alloca.Ty is None or param_alloca.Ty.Pointee == 0:
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 片段函数缺少 ctx 形参 '{ctx.CtxParam}'(包裹模板与 M2 调用约定不一致)", "InternalCompilerError")
return None
return llvmlite.build_load(trans._cur_builder, param_alloca.Ty.Pointee, param_alloca)
return mlirlite.build_load(trans._cur_builder, param_alloca.Ty.Pointee, param_alloca)
# ---- repl_in_frag_entry_scope — 当前最近函数作用域是否就是**片段入口**函数 ----
#
@@ -631,7 +631,7 @@ novirtual class VarGenMixin:
return 0
if self.repl_in_frag_scope(trans.SymTab) == 0:
return 0
cur_nm: str = llvmlite.function_get_name(trans._cur_func)
cur_nm: str = mlirlite.function_get_name(trans._cur_func)
if cur_nm is None:
return 0
pfx: str = GenTypes.REPL_ENTRY_PREFIX
@@ -664,7 +664,7 @@ novirtual class VarGenMixin:
# 只允许可往返重建的集合:iN(N=1/8/16/32/64) / float / double / i8*。
# 其余 token(含 REPL_TY_PTR / REPL_TY_STRUCT)返回 None ⇒ 调用点明确报错。
def repl_func_ty(self, pool: memhub.MemBuddy*,
tag: int, bits: int) -> llvmlite.LLVMType*:
tag: int, bits: int) -> mlirlite.LLVMType*:
"""签名 token → LLVM 类型;不支持的 token 返回 None"""
if pool is None:
return None
@@ -673,7 +673,7 @@ novirtual class VarGenMixin:
if tag == GenTypes.REPL_TY_FLOAT:
return self.repl_scalar_ty(pool, bits, 1)
if tag == GenTypes.REPL_TY_STR:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
return None
# ---- repl_func_sig_label — 签名 token → 人类可读类型名(错误消息用) ----
@@ -700,14 +700,14 @@ novirtual class VarGenMixin:
# 守卫:调用方只在 trans.ReplCtx is not None 时调用;非 REPL 恒不进入。
def repl_try_session_func_call(self, trans: HT.Translator*,
pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
builder: mlirlite.IRBuilder*,
mod: mlirlite.LLVMModule*,
func_name: str,
cargs: list[ast.AST*]*,
can: int,
kw_count: int,
node: ast.AST*,
hit: t.CPtr) -> llvmlite.Value*:
hit: t.CPtr) -> mlirlite.Value*:
"""会话函数调用:命中返回 call 结果(void 函数返回 None 但 hit 已置 1)"""
if trans is None or trans.ReplCtx is None or pool is None or builder is None:
return None
@@ -729,17 +729,17 @@ novirtual class VarGenMixin:
if can != entry.ParamCount:
self.Gen.TypeGenErr.fatal_error( node, f"REPL: 会话函数 '{func_name}' 期待 {entry.ParamCount} 个位置实参,调用处给了 {can} 个(M3 不支持默认参数/缺省补全)", "TypeError")
return None
ctx_val: llvmlite.Value* = self.repl_ctx_ptr(trans, ctx, node)
ctx_val: mlirlite.Value* = self.repl_ctx_ptr(trans, ctx, node)
if ctx_val is None:
return None
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
# ① 槽内取函数地址:槽地址是 i8**(Ptr(i8*)),load 得 i8*
slot: llvmlite.Value* = self.repl_slot_ptr(pool, builder, ctx_val, entry.SlotOff, i8_ptr_ty)
slot: mlirlite.Value* = self.repl_slot_ptr(pool, builder, ctx_val, entry.SlotOff, i8_ptr_ty)
if slot is None:
self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话函数指针槽地址生成失败", "InternalCompilerError")
return None
fn_i8: llvmlite.Value* = llvmlite.build_load(builder, i8_ptr_ty, slot)
fn_i8: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty, slot)
if fn_i8 is None:
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的地址读取失败", "InternalCompilerError")
return None
@@ -750,16 +750,16 @@ novirtual class VarGenMixin:
string.memset(ptypes, 0, 8 * GenTypes.REPL_FUNC_PARAM_MAX)
ai_chk: int
for ai_chk in range(entry.ParamCount):
pty_chk: llvmlite.LLVMType* = self.repl_func_ty(pool, int(entry.ParamTags[ai_chk]), int(entry.ParamBits[ai_chk]))
pty_chk: mlirlite.LLVMType* = self.repl_func_ty(pool, int(entry.ParamTags[ai_chk]), int(entry.ParamBits[ai_chk]))
if pty_chk is None:
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 第 {ai_chk + 1} 个形参的类型 token 不受支持(M3 支持 iN/float/double/i8*)", "TypeError")
return None
pty_slot: str | t.CPtr = (str | t.CPtr)(uint64(ptypes) + ai_chk * 8)
pty_slot[0] = pty_chk
# ③ 实参:首实参 = 本片段 ctx,其后按签名类型逐个翻译并 coerce
head: llvmlite.Value* = ctx_val
head: mlirlite.Value* = ctx_val
head.Next = None
tail: llvmlite.Value* = head
tail: mlirlite.Value* = head
arg_count: int = 1
ai: int
for ai in range(entry.ParamCount):
@@ -768,12 +768,12 @@ novirtual class VarGenMixin:
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的第 {ai + 1} 个实参缺失", "SyntaxError")
return None
pty_slot2: str | t.CPtr = (str | t.CPtr)(uint64(ptypes) + ai * 8)
pty: llvmlite.LLVMType* = (llvmlite.LLVMType*)(pty_slot2[0])
arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, pty)
pty: mlirlite.LLVMType* = (mlirlite.LLVMType*)(pty_slot2[0])
arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, pty)
if arg_val is None:
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的第 {ai + 1} 个实参翻译失败", "TypeError")
return None
coerced: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, pty, arg, trans)
coerced: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, pty, arg, trans)
if coerced is None:
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的第 {ai + 1} 个实参与签名类型不兼容", "TypeError")
return None
@@ -781,47 +781,47 @@ novirtual class VarGenMixin:
tail.Next = coerced
tail = coerced
arg_count += 1
# ④ 函数类型:ret + (i8*, P1..Pn)(ret=void 时用 llvmlite.Void,
# ④ 函数类型:ret + (i8*, P1..Pn)(ret=void 时用 mlirlite.Void,
# build_call_indirect 返回 None ⇒ 宿主调用方按"void 调用"处理)
ret_ty: llvmlite.LLVMType* = llvmlite.Void(pool)
ret_ty: mlirlite.LLVMType* = mlirlite.Void(pool)
if entry.RetTag != GenTypes.REPL_TY_VOID:
ret_ty = self.repl_func_ty(pool, entry.RetTag, entry.RetBits)
if ret_ty is None:
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的返回类型 token 不受支持(M3 支持 void/iN/float/double/i8*)", "TypeError")
return None
# 形参链表节点是 llvmlite.ParamNode(new_param_node 返回 rawptr[ParamNode]、
# 形参链表节点是 mlirlite.ParamNode(new_param_node 返回 rawptr[ParamNode]、
# paramnode_set_next / Func 形参同为 rawptr[ParamNode])——原先误注解为 Function*。
fp_first: llvmlite.ParamNode* = None
fp_prev: llvmlite.ParamNode* = None
fp_first: mlirlite.ParamNode* = None
fp_prev: mlirlite.ParamNode* = None
pi: int
for pi in range(arg_count):
cur_ty: llvmlite.LLVMType* = i8_ptr_ty
cur_ty: mlirlite.LLVMType* = i8_ptr_ty
if pi > 0:
pty_slot3: str | t.CPtr = (str | t.CPtr)(uint64(ptypes) + (pi - 1) * 8)
cur_ty = (llvmlite.LLVMType*)(pty_slot3[0])
pn: llvmlite.ParamNode* = llvmlite.new_param_node(pool, cur_ty)
cur_ty = (mlirlite.LLVMType*)(pty_slot3[0])
pn: mlirlite.ParamNode* = mlirlite.new_param_node(pool, cur_ty)
if pn is not None:
if fp_first is None:
fp_first = pn
if fp_prev is not None:
llvmlite.paramnode_set_next(fp_prev, pn)
mlirlite.paramnode_set_next(fp_prev, pn)
fp_prev = pn
func_ty: llvmlite.LLVMType* = llvmlite.Func(pool, ret_ty, fp_first, arg_count)
func_ty: mlirlite.LLVMType* = mlirlite.Func(pool, ret_ty, fp_first, arg_count)
if func_ty is None:
return None
func_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, func_ty)
fn_typed: llvmlite.Value* = llvmlite.build_bitcast(builder, fn_i8, func_ptr_ty)
func_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, func_ty)
fn_typed: mlirlite.Value* = mlirlite.build_bitcast(builder, fn_i8, func_ptr_ty)
if fn_typed is None:
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的地址转换失败", "InternalCompilerError")
return None
return llvmlite.build_call_indirect(builder, fn_typed, head, arg_count, ret_ty)
return mlirlite.build_call_indirect(builder, fn_typed, head, arg_count, ret_ty)
# ---- repl_slot_ptr — 槽地址(ctx + off 的字节 GEP 后 bitcast 成 Ptr(val_ty)) ----
def repl_slot_ptr(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
ctx_val: llvmlite.Value*,
builder: mlirlite.IRBuilder*,
ctx_val: mlirlite.Value*,
off: int,
val_ty: llvmlite.LLVMType*) -> llvmlite.Value*:
val_ty: mlirlite.LLVMType*) -> mlirlite.Value*:
"""返回槽指针(Ptr(val_ty));参数不完整返回 None
用 i8 步长 GEP 做纯字节偏移(同 list_getitem_inline 的既有做法),
@@ -829,46 +829,46 @@ novirtual class VarGenMixin:
"""
if pool is None or builder is None or ctx_val is None or val_ty is None:
return None
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
target_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, val_ty)
off_val: llvmlite.Value* = llvmlite.const_int64(pool, t.CInt64T(off))
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
target_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, val_ty)
off_val: mlirlite.Value* = mlirlite.const_int64(pool, t.CInt64T(off))
if off_val is None:
return None
base: llvmlite.Value* = llvmlite.build_gep(builder, i8_ty, ctx_val, off_val)
base: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, ctx_val, off_val)
if base is None:
return None
# 同型时不发 bitcast:llvmlite 类型非 canonical(同类型不同实例地址不同),
# 同型时不发 bitcast:mlirlite 类型非 canonical(同类型不同实例地址不同),
# 而 LLVM 拒绝 `bitcast i8* %x to i8*`(同型 cast 非法)——val_ty 为 i8
# (char 会话变量)时目标恰是 i8*,必须直接返回 GEP 结果。
if base.Ty is not None and self.Gen.AssignGen._stg_ty_equal(pool, base.Ty, target_ptr_ty) != 0:
return base
return llvmlite.build_bitcast(builder, base, target_ptr_ty)
return mlirlite.build_bitcast(builder, base, target_ptr_ty)
# ---- repl_scalar_ty — 位宽 → LLVM 标量类型 ----
def repl_scalar_ty(self, pool: memhub.MemBuddy*,
bits: int, is_float: int) -> llvmlite.LLVMType*:
bits: int, is_float: int) -> mlirlite.LLVMType*:
"""按位宽还原 LLVM 标量类型;不支持的位宽返回 None"""
if is_float != 0:
if bits == 32:
return llvmlite.Float(pool)
return mlirlite.Float(pool)
if bits == 64:
return llvmlite.Double(pool)
return mlirlite.Double(pool)
return None
if bits == 1:
return llvmlite.Int1(pool)
return mlirlite.Int1(pool)
if bits == 8:
return llvmlite.Int8(pool)
return mlirlite.Int8(pool)
if bits == 16:
return llvmlite.Int16(pool)
return mlirlite.Int16(pool)
if bits == 32:
return llvmlite.Int32(pool)
return mlirlite.Int32(pool)
if bits == 64:
return llvmlite.Int64(pool)
return mlirlite.Int64(pool)
return None
# ---- repl_llvm_ty — 条目 → LLVM 值类型(结构体按名重解析) ----
def repl_llvm_ty(self, pool: memhub.MemBuddy*,
entry: rawptr[GenTypes.ReplVarEntry]) -> llvmlite.LLVMType*:
entry: rawptr[GenTypes.ReplVarEntry]) -> mlirlite.LLVMType*:
"""条目反推 LLVM 值类型;未定型/结构体类型不可解析返回 None
TyTag=STRUCT 时返回结构体**值**类型(内联存槽,槽类型即它本身)。
@@ -885,17 +885,17 @@ novirtual class VarGenMixin:
if entry.TyTag == GenTypes.REPL_TY_FLOAT:
return self.repl_scalar_ty(pool, entry.Bits, 1)
if entry.TyTag == GenTypes.REPL_TY_STR:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return mlirlite.Ptr(pool, mlirlite.Int8(pool))
if entry.TyTag == GenTypes.REPL_TY_PTR:
if entry.TyName is not None:
st: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(entry.TyName)
st: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(entry.TyName)
if st is None:
return None
return llvmlite.Ptr(pool, st)
ptee: llvmlite.LLVMType* = self.repl_scalar_ty(pool, entry.Bits, 0)
return mlirlite.Ptr(pool, st)
ptee: mlirlite.LLVMType* = self.repl_scalar_ty(pool, entry.Bits, 0)
if ptee is None:
ptee = llvmlite.Int8(pool)
return llvmlite.Ptr(pool, ptee)
ptee = mlirlite.Int8(pool)
return mlirlite.Ptr(pool, ptee)
if entry.TyTag == GenTypes.REPL_TY_STRUCT:
if entry.TyName is None:
return None
@@ -904,7 +904,7 @@ novirtual class VarGenMixin:
# ---- repl_slot_ty — 槽内存放的值类型 ----
def repl_slot_ty(self, pool: memhub.MemBuddy*,
entry: rawptr[GenTypes.ReplVarEntry]) -> llvmlite.LLVMType*:
entry: rawptr[GenTypes.ReplVarEntry]) -> mlirlite.LLVMType*:
"""槽内存放的值类型 = 条目的值类型本身(标量/指针/结构体值都内联在槽里)
结构体值另有体积约束:尺寸 > REPL_SLOT_SIZE 或对齐 > REPL_SLOT_SIZE 时
@@ -912,7 +912,7 @@ novirtual class VarGenMixin:
"""
if entry is None or pool is None:
return None
vt: llvmlite.LLVMType* = self.repl_llvm_ty(pool, entry)
vt: mlirlite.LLVMType* = self.repl_llvm_ty(pool, entry)
if vt is None:
return None
if entry.TyTag == GenTypes.REPL_TY_STRUCT:
@@ -924,7 +924,7 @@ novirtual class VarGenMixin:
return vt
# ---- repl_type_align / repl_type_size — 结构体值的尺寸/对齐(LLVM 标准布局) ----
def repl_type_align(self, ty: llvmlite.LLVMType*, depth: int = 0) -> int:
def repl_type_align(self, ty: mlirlite.LLVMType*, depth: int = 0) -> int:
"""类型自然对齐字节;未知类型返回 0(deep=守卫递归深度)"""
if ty is None or depth > 64:
return 0
@@ -946,30 +946,30 @@ novirtual class VarGenMixin:
return 8
if self.Gen.ExprGenBase.is_ptr_type(ty) != 0:
return 8
elem_ty: llvmlite.LLVMType* = None
elem_ty: mlirlite.LLVMType* = None
match ty:
case llvmlite.LLVMType.Array(elem_a, _cnt_a):
case mlirlite.LLVMType.Array(elem_a, _cnt_a):
elem_ty = elem_a
case _:
pass
if elem_ty is not None:
return self.repl_type_align(elem_ty, depth + 1)
fields: rawptr[llvmlite.ParamNode] = llvmlite.get_struct_fields(ty)
fields: rawptr[mlirlite.ParamNode] = mlirlite.get_struct_fields(ty)
if fields is None:
return 0
cur: rawptr[llvmlite.ParamNode] = fields
cur: rawptr[mlirlite.ParamNode] = fields
best: int = 1
while cur is not None:
fty: llvmlite.LLVMType* = llvmlite.paramnode_get_ty(cur)
fty: mlirlite.LLVMType* = mlirlite.paramnode_get_ty(cur)
fa: int = self.repl_type_align(fty, depth + 1)
if fa <= 0:
return 0
if fa > best:
best = fa
cur = llvmlite.paramnode_get_next(cur)
cur = mlirlite.paramnode_get_next(cur)
return best
def repl_type_size(self, ty: llvmlite.LLVMType*, depth: int = 0) -> int:
def repl_type_size(self, ty: mlirlite.LLVMType*, depth: int = 0) -> int:
"""类型字节尺寸(LLVM 标准布局:字段按自然对齐排布 + 尾填充);未知返回 0
用于结构体值的"能否放入槽"判定(标量/指针见 repl_scalar_ty)。
@@ -984,10 +984,10 @@ novirtual class VarGenMixin:
return fb // 8
if self.Gen.ExprGenBase.is_ptr_type(ty) != 0:
return 8
elem_ty: llvmlite.LLVMType* = None
elem_ty: mlirlite.LLVMType* = None
cnt: int = 0
match ty:
case llvmlite.LLVMType.Array(elem_s, cnt_s):
case mlirlite.LLVMType.Array(elem_s, cnt_s):
elem_ty = elem_s
cnt = cnt_s
case _:
@@ -997,17 +997,17 @@ novirtual class VarGenMixin:
if es <= 0 or cnt <= 0:
return 0
return es * cnt
fields: rawptr[llvmlite.ParamNode] = llvmlite.get_struct_fields(ty)
fields: rawptr[mlirlite.ParamNode] = mlirlite.get_struct_fields(ty)
if fields is None:
return 0
align_struct: int = self.repl_type_align(ty, depth + 1)
if align_struct <= 0:
return 0
cur: rawptr[llvmlite.ParamNode] = fields
cur: rawptr[mlirlite.ParamNode] = fields
off: int = 0
counted: int = 0
while cur is not None:
fty2: llvmlite.LLVMType* = llvmlite.paramnode_get_ty(cur)
fty2: mlirlite.LLVMType* = mlirlite.paramnode_get_ty(cur)
fsz: int = self.repl_type_size(fty2, depth + 1)
fa2: int = self.repl_type_align(fty2, depth + 1)
if fsz <= 0 or fa2 <= 0:
@@ -1017,7 +1017,7 @@ novirtual class VarGenMixin:
off += fa2 - rem
off += fsz
counted += 1
cur = llvmlite.paramnode_get_next(cur)
cur = mlirlite.paramnode_get_next(cur)
if counted <= 0:
return 0
rem2: int = off % align_struct
@@ -1028,7 +1028,7 @@ novirtual class VarGenMixin:
# ---- repl_seal — 首次定型(已定型则校验类型标签一致) ----
def repl_seal(self, trans: HT.Translator*,
entry: rawptr[GenTypes.ReplVarEntry],
val_ty: llvmlite.LLVMType*,
val_ty: mlirlite.LLVMType*,
node: ast.AST*) -> int:
"""按 val_ty 给条目定型;返回 0=成功(含幂等命中)/ 1=不支持或冲突(已 fail-fast)
@@ -1056,10 +1056,10 @@ novirtual class VarGenMixin:
tag = GenTypes.REPL_TY_FLOAT
bits = fb
elif self.Gen.ExprGenBase.is_ptr_type(val_ty) != 0:
ptee: llvmlite.LLVMType* = val_ty.Pointee
ptee: mlirlite.LLVMType* = val_ty.Pointee
pname: str = None
if ptee is not None:
pname = llvmlite.get_struct_name(ptee)
pname = mlirlite.get_struct_name(ptee)
if pname is not None:
tag = GenTypes.REPL_TY_PTR
bits = 64
@@ -1082,7 +1082,7 @@ novirtual class VarGenMixin:
else:
bits = 0
else:
sname: str = llvmlite.get_struct_name(val_ty)
sname: str = mlirlite.get_struct_name(val_ty)
if sname is not None:
# 结构体**值**:按声明类型内联在槽里(不做装箱)。
# 槽容量/对齐上限 = REPL_SLOT_SIZE(16 字节):结构体尺寸或对齐
@@ -1228,8 +1228,8 @@ novirtual class VarGenMixin:
# ---- repl_emit_result — 把本片段结果写入 ctx 结果区 ----
def repl_emit_result(self, trans: HT.Translator*,
ctx_val: llvmlite.Value*,
val: llvmlite.Value*,
ctx_val: mlirlite.Value*,
val: mlirlite.Value*,
tag: int, bits: int,
node: ast.AST* = None) -> int:
"""按 tag 把 val 写入 ctx 结果区(见 GenTypes 的 result_kind 表);0=成功
@@ -1245,13 +1245,13 @@ novirtual class VarGenMixin:
if trans is None or ctx_val is None or val is None:
return 1
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
builder: mlirlite.IRBuilder* = trans._cur_builder
if pool is None or builder is None:
return 1
i64_ty: llvmlite.LLVMType* = llvmlite.Int64(pool)
zero64: llvmlite.Value* = llvmlite.const_int64(pool, 0)
i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool)
zero64: mlirlite.Value* = mlirlite.const_int64(pool, 0)
if tag == GenTypes.REPL_TY_INT:
iv: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, val, i64_ty, node, trans)
iv: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, val, i64_ty, node, trans)
if iv is None:
return 1
if self._repl_store_res_i32(trans, ctx_val, GenTypes.REPL_RES_KIND_OFF,
@@ -1261,11 +1261,11 @@ novirtual class VarGenMixin:
return 1
return self._repl_store_res_i64(trans, ctx_val, GenTypes.REPL_RES_B_OFF, zero64)
if tag == GenTypes.REPL_TY_FLOAT:
dv: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, val, llvmlite.Double(pool), node, trans)
dv: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, val, mlirlite.Double(pool), node, trans)
if dv is None:
return 1
# double → i64 位模式(bitcast,不做数值转换):宿主按位重解释回 double
dbits: llvmlite.Value* = llvmlite.build_bitcast(builder, dv, i64_ty)
dbits: mlirlite.Value* = mlirlite.build_bitcast(builder, dv, i64_ty)
if dbits is None:
return 1
if self._repl_store_res_i32(trans, ctx_val, GenTypes.REPL_RES_KIND_OFF,
@@ -1275,16 +1275,16 @@ novirtual class VarGenMixin:
return 1
return self._repl_store_res_i64(trans, ctx_val, GenTypes.REPL_RES_B_OFF, zero64)
if tag == GenTypes.REPL_TY_STR or tag == GenTypes.REPL_TY_PTR:
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
pv: llvmlite.Value* = val
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
pv: mlirlite.Value* = val
if val.Ty is not None and self.Gen.ExprGenBase.is_ptr_type(val.Ty) != 0 \
and self.Gen.AssignGen._stg_ty_equal(pool, val.Ty, i8_ptr_ty) == 0:
# 已是指向 i8 的指针(str/bytes/t.CPtr)时跳过——LLVM 拒绝同型 bitcast
pv = llvmlite.build_bitcast(builder, val, i8_ptr_ty)
pv = mlirlite.build_bitcast(builder, val, i8_ptr_ty)
if pv is None:
return 1
# 指针 → i64(ptrtoint):宿主按整数读回后再 inttoptr 成地址
pbits: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, pv, i64_ty, node, trans)
pbits: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, pv, i64_ty, node, trans)
if pbits is None:
return 1
kind: int = GenTypes.REPL_RES_OBJ
@@ -1309,44 +1309,44 @@ novirtual class VarGenMixin:
# ---- _repl_store_res_i64 / _repl_store_res_i32 — 结果区某偏移写定宽常量/值 ----
def _repl_store_res_i64(self, trans: HT.Translator*,
ctx_val: llvmlite.Value*,
ctx_val: mlirlite.Value*,
off: int,
val: llvmlite.Value*) -> int:
val: mlirlite.Value*) -> int:
"""把 i64 值写到 ctx 结果区的 off 偏移(0=成功)"""
if trans is None or ctx_val is None or val is None:
return 1
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
slot: llvmlite.Value* = self.repl_slot_ptr(pool, builder, ctx_val, off, llvmlite.Int64(pool))
builder: mlirlite.IRBuilder* = trans._cur_builder
slot: mlirlite.Value* = self.repl_slot_ptr(pool, builder, ctx_val, off, mlirlite.Int64(pool))
if slot is None:
return 1
llvmlite.build_store(builder, val, slot)
mlirlite.build_store(builder, val, slot)
return 0
def _repl_store_res_i32(self, trans: HT.Translator*,
ctx_val: llvmlite.Value*,
ctx_val: mlirlite.Value*,
off: int,
val: int) -> int:
"""把 i32 常量写到 ctx 结果区的 off 偏移(kind / var_count 等,0=成功)"""
if trans is None or ctx_val is None:
return 1
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
builder: mlirlite.IRBuilder* = trans._cur_builder
if pool is None or builder is None:
return 1
slot: llvmlite.Value* = self.repl_slot_ptr(pool, builder, ctx_val, off, llvmlite.Int32(pool))
slot: mlirlite.Value* = self.repl_slot_ptr(pool, builder, ctx_val, off, mlirlite.Int32(pool))
if slot is None:
return 1
cv: llvmlite.Value* = llvmlite.const_int32(pool, val)
cv: mlirlite.Value* = mlirlite.const_int32(pool, val)
if cv is None:
return 1
llvmlite.build_store(builder, cv, slot)
mlirlite.build_store(builder, cv, slot)
return 0
# ---- repl_try_read — 会话变量读取(命中返回 load 值,未命中返回 None) ----
def repl_try_read(self, trans: HT.Translator*,
name: str,
node: ast.AST*) -> llvmlite.Value*:
node: ast.AST*) -> mlirlite.Value*:
"""REPL 会话变量读:命中返回槽内值(结构体返回盒子地址);否则 None
返回 None 表示"不是会话变量",调用方继续原有查找/报错路径。
@@ -1364,7 +1364,7 @@ novirtual class VarGenMixin:
"NameError")
return None
pool: memhub.MemBuddy* = trans.Pool
slot_ty: llvmlite.LLVMType* = self.repl_slot_ty(pool, entry)
slot_ty: mlirlite.LLVMType* = self.repl_slot_ty(pool, entry)
if slot_ty is None:
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量 '{name}' 的类型 "
@@ -1372,19 +1372,19 @@ novirtual class VarGenMixin:
f"(跨片段类型可见性属 M4)",
"NameError")
return None
ctx_val: llvmlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, node)
ctx_val: mlirlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, node)
if ctx_val is None:
return None
slot: llvmlite.Value* = self.repl_slot_ptr(pool, trans._cur_builder, ctx_val, entry.Offset, slot_ty)
slot: mlirlite.Value* = self.repl_slot_ptr(pool, trans._cur_builder, ctx_val, entry.Offset, slot_ty)
if slot is None:
self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话槽地址生成失败", "InternalCompilerError")
return None
return llvmlite.build_load(trans._cur_builder, slot_ty, slot)
return mlirlite.build_load(trans._cur_builder, slot_ty, slot)
# ---- repl_try_addr — 会话变量取址(c.Addr(x) → ctx 槽地址) ----
def repl_try_addr(self, trans: HT.Translator*,
name: str,
node: ast.AST*) -> llvmlite.Value*:
node: ast.AST*) -> mlirlite.Value*:
"""会话变量取址:返回槽地址(Ptr(值类型))
值只存一份(宿主持有的 ctx arena)且内联在槽里,故 c.Addr(x) 得到的
@@ -1404,16 +1404,16 @@ novirtual class VarGenMixin:
"NameError")
return None
pool: memhub.MemBuddy* = trans.Pool
slot_ty: llvmlite.LLVMType* = self.repl_slot_ty(pool, entry)
slot_ty: mlirlite.LLVMType* = self.repl_slot_ty(pool, entry)
if slot_ty is None:
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量 '{name}' 的类型在当前片段不可用(跨片段类型可见性属 M4)",
"NameError")
return None
ctx_val: llvmlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, node)
ctx_val: mlirlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, node)
if ctx_val is None:
return None
slot: llvmlite.Value* = self.repl_slot_ptr(pool, trans._cur_builder, ctx_val, entry.Offset, slot_ty)
slot: mlirlite.Value* = self.repl_slot_ptr(pool, trans._cur_builder, ctx_val, entry.Offset, slot_ty)
if slot is None:
self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话槽地址生成失败", "InternalCompilerError")
return None
@@ -1423,8 +1423,8 @@ novirtual class VarGenMixin:
# ---- repl_store_slot — 定型后的值写槽(并把该值写入结果区) ----
def repl_store_slot(self, trans: HT.Translator*,
entry: rawptr[GenTypes.ReplVarEntry],
ctx_val: llvmlite.Value*,
rhs_val: llvmlite.Value*,
ctx_val: mlirlite.Value*,
rhs_val: mlirlite.Value*,
node: ast.AST*) -> int:
"""coerce 到槽类型 → 写槽 → 写结果区;0=成功(失败已 fail-fast)
@@ -1434,15 +1434,15 @@ novirtual class VarGenMixin:
if trans is None or entry is None or ctx_val is None or rhs_val is None:
return 1
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
slot_ty: llvmlite.LLVMType* = self.repl_slot_ty(pool, entry)
builder: mlirlite.IRBuilder* = trans._cur_builder
slot_ty: mlirlite.LLVMType* = self.repl_slot_ty(pool, entry)
if slot_ty is None:
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量 '{entry.Name}' 的槽类型不可用"
f"(类型在当前片段不可解析,或结构体值体积超出槽容量)",
"TypeError")
return 1
store_val: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, slot_ty, node, trans)
store_val: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, slot_ty, node, trans)
if store_val is None:
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量 '{entry.Name}' 无法把右侧值转换为"
@@ -1455,22 +1455,22 @@ novirtual class VarGenMixin:
and self.Gen.AssignGen._stg_ty_equal(pool, store_val.Ty, slot_ty) == 0:
# 指针同型化(槽类型与右侧指针可能不是同一类型实例;位宽相同)。
# 同型(含两侧都是 i8*)时跳过——LLVM 拒绝同型 bitcast。
store_val = llvmlite.build_bitcast(builder, store_val, slot_ty)
store_val = mlirlite.build_bitcast(builder, store_val, slot_ty)
if store_val is None:
self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话槽指针同型化失败", "CastError")
return 1
slot: llvmlite.Value* = self.repl_slot_ptr(pool, builder, ctx_val, entry.Offset, slot_ty)
slot: mlirlite.Value* = self.repl_slot_ptr(pool, builder, ctx_val, entry.Offset, slot_ty)
if slot is None:
self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话槽写入失败", "InternalCompilerError")
return 1
llvmlite.build_store(builder, store_val, slot)
mlirlite.build_store(builder, store_val, slot)
self.repl_emit_result(trans, ctx_val, store_val, entry.TyTag, entry.Bits, node)
return 0
# ---- repl_try_assign — 会话变量赋值(命中返回 1) ----
def repl_try_assign(self, trans: HT.Translator*,
name: str,
rhs_val: llvmlite.Value*,
rhs_val: mlirlite.Value*,
rhs_node: ast.AST*,
node: ast.AST*) -> int:
"""REPL 会话变量赋值:命中(已登记 + 在**片段入口函数**本体)返回 1,否则 0
@@ -1492,7 +1492,7 @@ novirtual class VarGenMixin:
return 1
if self.repl_seal(trans, entry, rhs_val.Ty, rhs_node) != 0:
return 1
ctx_val: llvmlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, node)
ctx_val: mlirlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, node)
if ctx_val is None:
return 1
self.repl_store_slot(trans, entry, ctx_val, rhs_val, node)
@@ -1519,14 +1519,14 @@ novirtual class VarGenMixin:
if self.repl_in_frag_entry_scope(trans) == 0:
return 0
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
builder: mlirlite.IRBuilder* = trans._cur_builder
if annot_node is None:
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 的注解缺失", "SyntaxError")
return 1
# 与普通 AnnAssign 同口径:先注册泛型特化,避免 list[X] 退化为裸基类
# (裸 list* 会让后续 .get() 误分派并截断指针)
self.Gen.AssignGen._prespecialize_generic_annotation(trans, pool, annot_node)
annot_ty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, annot_node, trans._imported_modules, trans._from_imports, trans, 0)
annot_ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, annot_node, trans._imported_modules, trans._from_imports, trans, 0)
if annot_ty is None:
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量 '{name}' 的类型注解解析失败"
@@ -1538,17 +1538,17 @@ novirtual class VarGenMixin:
if value_node is None:
# 仅定型(x: int):不产生值;结果区本行由宿主清零 ⇒ 无结果
return 1
slot_ty: llvmlite.LLVMType* = self.repl_slot_ty(pool, entry)
slot_ty: mlirlite.LLVMType* = self.repl_slot_ty(pool, entry)
# 与普通 AnnAssign 四处同口径:翻译 RHS 前设置上下文(裸名泛型构造推断用)
trans.CurAssignAnnot = annot_node
trans.CurAssignNode = value_node
rhs_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, value_node, None, 0, trans, slot_ty)
rhs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, value_node, None, 0, trans, slot_ty)
trans.CurAssignAnnot = None
trans.CurAssignNode = None
if rhs_val is None:
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 的初值翻译失败", "TypeError")
return 1
ctx_val: llvmlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, node)
ctx_val: mlirlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, node)
if ctx_val is None:
return 1
self.repl_store_slot(trans, entry, ctx_val, rhs_val, node)
@@ -1573,20 +1573,20 @@ novirtual class VarGenMixin:
if self.repl_in_frag_entry_scope(trans) == 0:
return 0
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
builder: mlirlite.IRBuilder* = trans._cur_builder
if entry.TyTag == GenTypes.REPL_TY_STRUCT:
self.Gen.TypeGenErr.fatal_error(node,
f"REPL: 会话变量 '{name}' 是结构体值,不支持增强赋值",
"TypeError")
return 1
cur_val: llvmlite.Value* = self.repl_try_read(trans, name, node)
cur_val: mlirlite.Value* = self.repl_try_read(trans, name, node)
if cur_val is None:
return 1
rhs_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, rhs_node, None, 0, trans)
rhs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, rhs_node, None, 0, trans)
if rhs_val is None:
self.Gen.TypeGenErr.fatal_error(node, "REPL: 增强赋值右侧翻译失败", "TypeError")
return 1
result: llvmlite.Value* = self.Gen.AssignGen._apply_aug_op(pool, builder, op, cur_val, rhs_val, node, trans, node)
result: mlirlite.Value* = self.Gen.AssignGen._apply_aug_op(pool, builder, op, cur_val, rhs_val, node, trans, node)
if result is None:
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 的增强赋值运算失败 op={op}", "TypeError")
return 1
@@ -1604,12 +1604,12 @@ novirtual class VarGenMixin:
if trans is None or trans.ReplCtx is None or value_node is None:
return 1
pool: memhub.MemBuddy* = trans.Pool
builder: llvmlite.IRBuilder* = trans._cur_builder
val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, value_node, None, 0, trans)
builder: mlirlite.IRBuilder* = trans._cur_builder
val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, value_node, None, 0, trans)
if val is None or val.Ty is None:
self.Gen.TypeGenErr.fatal_error(value_node, "REPL: 表达式片段求值失败", "TypeError")
return 1
ctx_val: llvmlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, value_node)
ctx_val: mlirlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, value_node)
if ctx_val is None:
return 1
# 类型分类用宿主的影子条目(不占会话槽、不进表):每次先复位为未定型
-6
View File
@@ -453,12 +453,6 @@ def ResolveModuleToPath(includes_dirs: str, mod_name: str,
out_inc_dir: t.CPtr) -> int:
if includes_dirs is None or mod_name is None:
return 1
# MLIR 后端:模块名 "llvmlite" 重定向到 "mlirlite"(TransPyV 调用点零改动)。
# 重定向后的名字用于本次解析的路径段/相对路径,调用方拿到的 rel_path
# 即 "mlirlite/__init__.vp" ⇒ 下游模块身份/SHA1 全部随之一致。
mod_name = Config.alias_module_name(mod_name)
if mod_name is None:
return 1
mn_len: sizet = string.strlen(mod_name)
if mn_len == 0:
return 1
+20 -20
View File
@@ -4,7 +4,7 @@ import stdio
import stdlib
import string
import viperlib
import llvmlite
import mlirlite
import memhub
import ast
import w32.fileio as fileio
@@ -921,7 +921,7 @@ def ReplInitIncludesClasses(mb: memhub.MemBuddy*,
GenApi.set_temp_dir(vpi_dir)
GenApi.SetTempDir(vpi_dir)
GenApi.set_current_file_type(vpi_dir)
tmp_mod: llvmlite.LLVMModule* = llvmlite.new_module(_perm_pool, _REPL_INC_MOD_NAME)
tmp_mod: mlirlite.LLVMModule* = mlirlite.new_module(_perm_pool, _REPL_INC_MOD_NAME)
tr_inc: rawptr[HandlesTranslator.Translator] = _perm_pool.alloc(HandlesTranslator.Translator.__sizeof__())
if tmp_mod is None or tr_inc is None:
return 1
@@ -1901,7 +1901,7 @@ def _repl_sig_to_text(tag: int, bits: int, pc: int) -> str:
# 注册前校验(在 llc/加载之前):逐个提升函数从片段模型取签名,判
# ① EH 出参 ② 类型不受支持 ③ 首形参不是 ctx ④ 形参过多 ⑤ 模型里找不到函数
# ⑥ 重定义签名不一致 ⑦ 表容量不足。任一项失败 ⇒ 打印原因并返回 1(整片段不执行)。
def _repl_precheck_session_funcs(mod: llvmlite.LLVMModule*) -> int:
def _repl_precheck_session_funcs(mod: mlirlite.LLVMModule*) -> int:
if ReplLiftNameCount <= 0:
return 0
if ReplCtxObj is None or ReplCtxObj.FuncTable is None or ReplSigResult is None:
@@ -1999,7 +1999,7 @@ def _repl_entry_sig_text(e: rawptr[GenTypes.ReplFuncEntry]) -> str:
# 注册(DLL 加载成功后调用):GetProcAddress(裸名) → 写 ctx 函数指针槽 → 追加/更新表
# 返回 0=成功;1=失败(已打印;调用方按 ReplSavedFuncCount 回滚表水位后放弃本片段)
def _repl_register_session_funcs(h_lib: win32base.HANDLE, frag_no: int,
mod: llvmlite.LLVMModule*) -> int:
mod: mlirlite.LLVMModule*) -> int:
if ReplLiftNameCount <= 0:
return 0
if ReplCtxObj is None or ReplCtxObj.FuncTable is None or ReplCtxBuf is None:
@@ -2101,11 +2101,11 @@ def _repl_tag_text(tag: int, bits: int) -> str:
# LLVMType* → 打包 token(tag*1000 + bits);0=不支持。
# 支持集合与旧字符串版一致:i1/i8/i16/i32/i64、float/double、Ptr(Int8)(str/bytes/rawptr)。
def _repl_ty_ptr_token(ty: llvmlite.LLVMType*) -> int:
def _repl_ty_ptr_token(ty: mlirlite.LLVMType*) -> int:
if ty is None:
return 0
match ty:
case llvmlite.LLVMType.Int(bits):
case mlirlite.LLVMType.Int(bits):
if bits == 1:
return GenTypes.REPL_TY_INT * 1000 + 1
if bits == 8:
@@ -2117,15 +2117,15 @@ def _repl_ty_ptr_token(ty: llvmlite.LLVMType*) -> int:
if bits == 64:
return GenTypes.REPL_TY_INT * 1000 + 64
return 0
case llvmlite.LLVMType.Float(bits):
case mlirlite.LLVMType.Float(bits):
if bits == 32:
return GenTypes.REPL_TY_FLOAT * 1000 + 32
if bits == 64:
return GenTypes.REPL_TY_FLOAT * 1000 + 64
return 0
case llvmlite.LLVMType.Ptr(pointee):
case mlirlite.LLVMType.Ptr(pointee):
match pointee:
case llvmlite.LLVMType.Int(bits):
case mlirlite.LLVMType.Int(bits):
if bits == 8:
return GenTypes.REPL_TY_STR * 1000 + 8
return 0
@@ -2136,10 +2136,10 @@ def _repl_ty_ptr_token(ty: llvmlite.LLVMType*) -> int:
# 诊断用:LLVMType* → 可读名(不支持的签名报错打印用);无名字返回 "(unsupported)"
def _repl_ty_name(ty: llvmlite.LLVMType*) -> str:
def _repl_ty_name(ty: mlirlite.LLVMType*) -> str:
if ty is None:
return "(none)"
nm: str = llvmlite.get_struct_name(ty)
nm: str = mlirlite.get_struct_name(ty)
if nm is not None:
return nm
return "(unsupported)"
@@ -2150,7 +2150,7 @@ def _repl_ty_name(ty: llvmlite.LLVMType*) -> str:
# 返回码与旧实现逐字一致:
# 0=成功;1=模块里找不到该函数;2=类型不受支持;3=含 EH 出参(raise);
# 4=首形参不是 ctx;5=形参过多(> REPL_FUNC_PARAM_MAX)
def _repl_model_func_sig(mod: llvmlite.LLVMModule*, name: str,
def _repl_model_func_sig(mod: mlirlite.LLVMModule*, name: str,
out: rawptr[ReplSigOut]) -> int:
if name is None or out is None or mod is None:
return 1
@@ -2160,17 +2160,17 @@ def _repl_model_func_sig(mod: llvmlite.LLVMModule*, name: str,
out.EHTag = 0
out.Bad = 0
out.BadType = None
fn: llvmlite.Function* = GenApi.find_func_in_module(mod, name)
fn: mlirlite.Function* = GenApi.find_func_in_module(mod, name)
if fn is None:
return 1
# ① 返回类型
rt_ty: llvmlite.LLVMType* = llvmlite.function_get_ret_ty(fn)
rt_ty: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(fn)
is_void: int = 0
if rt_ty is None:
is_void = 1
else:
match rt_ty:
case llvmlite.LLVMType.Void():
case mlirlite.LLVMType.Void():
is_void = 1
case _:
is_void = 0
@@ -2187,10 +2187,10 @@ def _repl_model_func_sig(mod: llvmlite.LLVMModule*, name: str,
out.RetBits = rt % 1000
# ② 形参表:首形参 ctx(Ptr(Int8) + 名字 __repl_ctx__),其余为业务参数
pi: int = 0
p_cur: llvmlite.Param* = llvmlite.function_get_param_head(fn)
p_cur: mlirlite.Param* = mlirlite.function_get_param_head(fn)
while p_cur is not None:
p_ty: llvmlite.LLVMType* = llvmlite.param_get_ty(p_cur)
p_nm: str = llvmlite.param_get_name(p_cur)
p_ty: mlirlite.LLVMType* = mlirlite.param_get_ty(p_cur)
p_nm: str = mlirlite.param_get_name(p_cur)
# 参数名可能带/不带前导 '%'(打印端按需补 '%'),统一剥掉前导 '%'
bare_nm: str = p_nm
if bare_nm is not None and bare_nm[0] == '%':
@@ -2218,7 +2218,7 @@ def _repl_model_func_sig(mod: llvmlite.LLVMModule*, name: str,
ReplSigBits[out.ParamCount] = tk % 1000
out.ParamCount = out.ParamCount + 1
pi += 1
p_cur = llvmlite.param_get_next(p_cur)
p_cur = mlirlite.param_get_next(p_cur)
return 0
@@ -2447,7 +2447,7 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int:
if rc_tr != 0:
stdio.printf("片段 %s: 翻译失败\n", ReplNameBuf)
return 1
tr.dump_ir(ReplIrBuf, _REPL_IR_CAP, llvmlite.OUTPUT_FULL)
tr.dump_ir(ReplIrBuf, _REPL_IR_CAP, mlirlite.OUTPUT_FULL)
# ⑦' M4:本片段是否**定义**了会话前缀符号(`@"<session sha1>.…"` = 类方法/
# 构造/类全局)?是 ⇒ 其 import lib 必须产出并登记,供后续片段链接期解析
+3 -15
View File
@@ -24,7 +24,7 @@ import w32.win32base as w32base
import w32.fileio as fileio
import sys
import ast
import llvmlite
import mlirlite
import subprocess
import viperlib
import t, c
@@ -161,8 +161,7 @@ def main() -> int:
parser.add_argument("--show-args", None, argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Show all parsed arguments")
parser.add_argument("--repl", None, argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Start the interactive REPL (M2 session variables + M3 cross-fragment functions: fragment -> DLL -> call)")
parser.add_argument("--build-dir", None, argparse.STRING, 0, None, False, argparse.STORE, "Override project.vpj build_dir (default ./.tpv_build; relative paths resolve against the project dir)")
parser.add_argument("--no-llvmpeephole", None, argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Disable all local llvmlite peephole passes (T2 store/load forward & ret-zero, T3 no-op bitcast) in FunctionPrint serialization")
parser.add_argument("--backend", None, argparse.STRING, 0, None, False, argparse.STORE, "Emitter backend: llvm (default) | mlir. mlir redirects module 'llvmlite' to includes/mlirlite and inserts mlir-opt + mlir-translate before opt/llc")
parser.add_argument("--no-llvmpeephole", None, argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Disable all local mlirlite peephole passes (T2 store/load forward & ret-zero, T3 no-op bitcast) in FunctionPrint serialization")
parser.add_argument("--version", "-v", argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Show version and exit")
parser.add_argument("--help", "-h", argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Show help and exit")
@@ -325,7 +324,7 @@ Target: %s
# --no-llvmpeephole:关闭全部本地窥孔(T2/T3),FunctionPrint 直接序列化
if args.get_bool("no-llvmpeephole"):
llvmlite.G_PeepEnable = 0
mlirlite.G_PeepEnable = 0
log.info("--no-llvmpeephole 已启用:关闭 FunctionPrint 本地窥孔(RenumberSSA 保留)", "peep")
# === --repl 启动便利:未给 --project 时按 cwd → exe 同目录 查找 repl.vpj ===
@@ -370,17 +369,6 @@ Target: %s
proj_path = "../project.vpj"
if Config.Load_project_config(proj_path) == 0:
proj_loaded = 1
# === --backend: CLI 覆盖 project.vpj 的 options.backend(CLI 优先级最高)===
# 位置:工程配置加载之后(options.backend 已读入)、resolve_paths 之前
#(TempDir/OutputDir 的后端隔离后缀由此定型);非法值 fail-fast。
gb_backend: str = args.get_str("backend")
if gb_backend is not None:
if Config.set_backend(gb_backend) != 0:
log.error(f"非法的 --backend 值: '{gb_backend}'(只支持 llvm / mlir)", "backend")
argparse.release(args)
return 1
log.info(f"后端: {Config.BackendTarget}", "backend")
if proj_loaded == 1:
# 提取 project.vpj 所在目录,将相对路径解析为基于该目录的路径
proj_len: sizet = string.strlen(proj_path)
+28 -28
View File
@@ -2,7 +2,7 @@ import stdio
import t, c
import memhub
import stdlib
import llvmlite
import mlirlite
import string
@@ -44,13 +44,13 @@ def test_single_match() -> int:
"""Test 1: 单层 match(基线测试)"""
stdio.printf("--- Test 1: 单层 match LLVMType ---\n")
ty: rawptr[llvmlite.LLVMType] = llvmlite.Int32(_mbuddy)
ty: rawptr[mlirlite.LLVMType] = mlirlite.Int32(_mbuddy)
if ty is None:
stdio.printf("FAIL: Int32 returned None\n")
return 1
match ty:
case llvmlite.LLVMType.Int(bits):
case mlirlite.LLVMType.Int(bits):
stdio.printf("Int(%d) OK\n", bits)
if bits == 32:
stdio.printf("bits==32 OK\n")
@@ -69,14 +69,14 @@ def test_nested_match_other() -> int:
"""
stdio.printf("--- Test 2: 嵌套 match(case 块内 match 另一值)---\n")
ty_outer: rawptr[llvmlite.LLVMType] = llvmlite.Int32(_mbuddy)
ty_inner: rawptr[llvmlite.LLVMType] = llvmlite.Int8(_mbuddy)
ty_outer: rawptr[mlirlite.LLVMType] = mlirlite.Int32(_mbuddy)
ty_inner: rawptr[mlirlite.LLVMType] = mlirlite.Int8(_mbuddy)
match ty_outer:
case llvmlite.LLVMType.Int(bits):
case mlirlite.LLVMType.Int(bits):
# 在 Int 的 case 块内嵌套 match 另一个 REnum 值
match ty_inner:
case llvmlite.LLVMType.Int(inner_bits):
case mlirlite.LLVMType.Int(inner_bits):
stdio.printf("outer Int(%d), inner Int(%d) OK\n", bits, inner_bits)
if bits == 32 and inner_bits == 8:
stdio.printf("values OK\n")
@@ -99,14 +99,14 @@ def test_nested_match_pointee() -> int:
stdio.printf("--- Test 3: 嵌套 match pointee ---\n")
# 构造 Ptr(Int32) 类型
inner_ty: rawptr[llvmlite.LLVMType] = llvmlite.Int32(_mbuddy)
ptr_ty: rawptr[llvmlite.LLVMType] = llvmlite.Ptr(_mbuddy, inner_ty)
inner_ty: rawptr[mlirlite.LLVMType] = mlirlite.Int32(_mbuddy)
ptr_ty: rawptr[mlirlite.LLVMType] = mlirlite.Ptr(_mbuddy, inner_ty)
match ptr_ty:
case llvmlite.LLVMType.Ptr(pointee):
case mlirlite.LLVMType.Ptr(pointee):
# 在 Ptr 的 case 块内嵌套 match pointee
match pointee:
case llvmlite.LLVMType.Int(bits):
case mlirlite.LLVMType.Int(bits):
stdio.printf("Ptr(Int(%d)) OK\n", bits)
if bits == 32:
stdio.printf("pointee bits==32 OK\n")
@@ -130,28 +130,28 @@ def test_three_level_nested() -> int:
stdio.printf("--- Test 4: 3 层嵌套 match ---\n")
# 构造 Ptr(Ptr(Int32)) 类型
innermost: rawptr[llvmlite.LLVMType] = llvmlite.Int32(_mbuddy)
mid_ptr: rawptr[llvmlite.LLVMType] = llvmlite.Ptr(_mbuddy, innermost)
outer_ptr: rawptr[llvmlite.LLVMType] = llvmlite.Ptr(_mbuddy, mid_ptr)
innermost: rawptr[mlirlite.LLVMType] = mlirlite.Int32(_mbuddy)
mid_ptr: rawptr[mlirlite.LLVMType] = mlirlite.Ptr(_mbuddy, innermost)
outer_ptr: rawptr[mlirlite.LLVMType] = mlirlite.Ptr(_mbuddy, mid_ptr)
# 另一个值用于第 3 层 match
extra_ty: rawptr[llvmlite.LLVMType] = llvmlite.Int16(_mbuddy)
extra_ty: rawptr[mlirlite.LLVMType] = mlirlite.Int16(_mbuddy)
match outer_ptr:
case llvmlite.LLVMType.Ptr(p1):
case mlirlite.LLVMType.Ptr(p1):
# 第 2 层 match p1
match p1:
case llvmlite.LLVMType.Ptr(p2):
case mlirlite.LLVMType.Ptr(p2):
# 第 3 层 match p2
match p2:
case llvmlite.LLVMType.Int(bits):
case mlirlite.LLVMType.Int(bits):
stdio.printf("Ptr(Ptr(Int(%d))) OK\n", bits)
case _:
stdio.printf("level 3 default FAIL\n")
return 1
# 第 3 层 match 另一个值(验证 case 块内多次 match)
match extra_ty:
case llvmlite.LLVMType.Int(ebits):
case mlirlite.LLVMType.Int(ebits):
stdio.printf("extra Int(%d) in nested OK\n", ebits)
if ebits == 16:
stdio.printf("3-level values OK\n")
@@ -176,15 +176,15 @@ def test_nested_match_in_if() -> int:
"""
stdio.printf("--- Test 5: if 块内嵌套 match ---\n")
ty: rawptr[llvmlite.LLVMType] = llvmlite.Float(_mbuddy)
ty: rawptr[mlirlite.LLVMType] = mlirlite.Float(_mbuddy)
if ty is not None:
match ty:
case llvmlite.LLVMType.Float(bits):
case mlirlite.LLVMType.Float(bits):
# 在 Float 的 case 块内再 match
ty2: rawptr[llvmlite.LLVMType] = llvmlite.Double(_mbuddy)
ty2: rawptr[mlirlite.LLVMType] = mlirlite.Double(_mbuddy)
match ty2:
case llvmlite.LLVMType.Float(bits2):
case mlirlite.LLVMType.Float(bits2):
stdio.printf("Float(%d) + Double(%d) OK\n", bits, bits2)
if bits == 32 and bits2 == 64:
stdio.printf("float values OK\n")
@@ -209,16 +209,16 @@ def test_nested_match_mismatch() -> int:
stdio.printf("--- Test 6: 嵌套 match 不同变体(default 分支)---\n")
# 外层是 Int,内层是 Float - 验证内层 match 不会误匹配 Int
ty_outer: rawptr[llvmlite.LLVMType] = llvmlite.Int32(_mbuddy)
ty_inner: rawptr[llvmlite.LLVMType] = llvmlite.Float(_mbuddy)
ty_outer: rawptr[mlirlite.LLVMType] = mlirlite.Int32(_mbuddy)
ty_inner: rawptr[mlirlite.LLVMType] = mlirlite.Float(_mbuddy)
match ty_outer:
case llvmlite.LLVMType.Int(bits):
case mlirlite.LLVMType.Int(bits):
match ty_inner:
case llvmlite.LLVMType.Int(wrong_bits):
case mlirlite.LLVMType.Int(wrong_bits):
stdio.printf("FAIL: Float matched as Int(%d)\n", wrong_bits)
return 1
case llvmlite.LLVMType.Float(fbits):
case mlirlite.LLVMType.Float(fbits):
stdio.printf("outer Int(%d), inner Float(%d) OK\n", bits, fbits)
if bits == 32 and fbits == 32:
stdio.printf("mismatch values OK\n")
-1
View File
@@ -43,7 +43,6 @@
"options": {
"slice_level": 3,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}