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:
1 parent
1dcd29db9c
commit
7b3e814524
70 files changed
+5670
-5746
No files matched your search
@@ -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 +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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
@@ -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*,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+264
-264
File diff suppressed because it is too large.
Load diff
+473
-473
File diff suppressed because it is too large.
Load diff
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
@@ -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
@@ -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)
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 _:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)。
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
@@ -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
+270
-270
File diff suppressed because it is too large.
Load diff
@@ -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
@@ -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
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 拦截
|
||||
#
|
||||
|
||||
+199
-199
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 集合中"""
|
||||
|
||||
@@ -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,7 +1,7 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import mlirlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import mlirlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
|
||||
@@ -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,7 +1,7 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import mlirlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
|
||||
@@ -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, "不支持的类型注解语法")
|
||||
|
||||
@@ -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
@@ -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
|
||||
# 类型分类用宿主的影子条目(不占会话槽、不进表):每次先复位为未定型
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
"options": {
|
||||
"slice_level": 3,
|
||||
"sha1_slice_level": 1,
|
||||
"target": "llvm",
|
||||
"strict_mode": true
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user