phase15: add Cranelift AOT design, LinkerBox spec, and smoke skeleton docs (handoff)
This commit is contained in:
57
docs/backend-cranelift-aot-design.md
Normal file
57
docs/backend-cranelift-aot-design.md
Normal file
@ -0,0 +1,57 @@
|
||||
Cranelift AOT Box: 設計ノートと obj 出力 PoC(Phase 15 準備)
|
||||
|
||||
目的
|
||||
- Nyash → MIR → Cranelift AOT(C ABI)→ オブジェクト(.o/.obj)→ リンク → EXE の最小パイプラインを確立する前準備。
|
||||
- 本ブランチでは「設計と仕様の確定(ドキュメント化)」のみを行い、実装は別ブランチ `phase-15/self-host-aot-cranelift` で着手する。
|
||||
|
||||
対象範囲(P0)
|
||||
- PoC として `ny_main`(i64 → i64 返し)を定義する最小オブジェクトを Cranelift で生成できること。
|
||||
- 生成物を NyRT(`crates/nyrt`)と静的リンクして実行可能ファイルを作成できること。
|
||||
- 実行結果として `Result: 42` 等の既知の値確認を行うこと。
|
||||
|
||||
アーキテクチャ概要
|
||||
- CraneliftAotBox(本ドキュメントの主題)
|
||||
- 役割: MIR から Cranelift IR(CLIF)を生成し、`cranelift-object` でオブジェクトを出力する。
|
||||
- 出力: ターゲット環境に応じた COFF/ELF/Mach-O(`cranelift-object` の既定に従う)。
|
||||
- シグネチャ: PoC は `ny_main: () -> i64`(将来的には引数の受け渡しや NyRT 呼び出しを拡張)。
|
||||
- LinkerBox(別タスク、別文書で仕様化)
|
||||
- 役割: 生成された `.o/.obj` を NyRT(`libnyrt.a`/`nyrt.lib`)とリンクして EXE を作る。
|
||||
- Windows は `link.exe`/`lld-link`、Linux は `cc` 経由を想定(詳細は LinkerBox 仕様にて)。
|
||||
|
||||
ABI / 連携
|
||||
- エントリ: `ny_main` を EXE から呼び出す形。NyRT 側が `main()` 内から `ny_main()` を適切に呼び出して結果を表示(または検証)する想定。
|
||||
- ランタイム: PoC 段階では NyRT の最低限(起動/終了)に依存。将来的に checkpoint や GC バリアなどの外部関数を `extern "C"` で参照可能にする。
|
||||
|
||||
PoC 受入基準(P0)
|
||||
- `.o/.obj` に `ny_main` シンボルが定義されている。
|
||||
- `libnyrt.a`/`nyrt.lib` とリンクして実行可能ファイルが作成できる。
|
||||
- 実行すると標準出力に既知の値(例: `Result: 42`)が出力される。
|
||||
|
||||
想定コマンド(リンク例)
|
||||
- Linux: `cc -o app ny_main.o target/release/libnyrt.a -ldl -lpthread`
|
||||
- Windows (MSVC): `link ny_main.obj nyrt.lib /OUT:app.exe`
|
||||
- 実行時設定: 実行ファイルと同じディレクトリに `nyash.toml` を配置することでプラグイン解決を容易にする(NyRT は exe 直下→CWD の順で探索)。
|
||||
|
||||
CLI/ツール統合(案)
|
||||
- バックエンドキー: `--backend cranelift-aot`
|
||||
- PoC フラグ: `--poc-const N`(`ny_main` が `N` を返す単機能)
|
||||
- 補助スクリプト(設計のみ、本ブランチでは作成しない):
|
||||
- `tools/aot_smoke_cranelift.sh apps/APP/main.nyash -o app`
|
||||
- 流れ: Nyash → MIR → CraneliftAotBox → `.o` → LinkerBox/cc → `app`
|
||||
|
||||
ロードマップ
|
||||
- P0: PoC スタブ `ny_main` 定数返し、リンク/実行確認。
|
||||
- P1: 最小 MIR(`const_i64`/`add_i64`/`ret`)のマッピング。
|
||||
- P2: NyRT チェックポイント呼び出しなど最小の外部関数連携。
|
||||
- P3: Plugin 経由の I/O など実用的な呼び出しの一部導入。
|
||||
|
||||
既知のリスクと対策
|
||||
- プラットフォーム ABI 差異: 既定の呼出規約を使用し、まず Linux で動作確認。
|
||||
- オブジェクト形式差: `cranelift-object` の既定に寄り添う。必要に応じてターゲット指定を導入。
|
||||
- 重複実装の懸念: 既存のオブジェクトビルダ(JIT/emit系)の再利用・抽象化を検討。
|
||||
|
||||
実装方針(別ブランチで実施)
|
||||
- フィーチャ: `cranelift-aot = ["dep:cranelift-object"]`
|
||||
- モジュール: `src/backend/cranelift/aot_box.rs` を追加し、PoC 用 `compile_stub_ny_main_i64` を提供。
|
||||
- CLI 統合: `--backend cranelift-aot` と PoC フラグの導入(PoC 期間は一時的)。
|
||||
|
||||
55
docs/handoff/phase-15-handoff.md
Normal file
55
docs/handoff/phase-15-handoff.md
Normal file
@ -0,0 +1,55 @@
|
||||
Phase 15 — Self-Hosting (Cranelift AOT) 引き継ぎメモ
|
||||
|
||||
概要(2025-09-05)
|
||||
- 目的: Nyash → MIR → Cranelift AOT → オブジェクト → リンク → EXE の最小パイプライン確立に向けた準備(設計/仕様/スモーク雛形)。
|
||||
- 実装は別ブランチ `phase-15/self-host-aot-cranelift` で着手予定。現状はドキュメントと雛形スクリプトまで整備。
|
||||
|
||||
このブランチで完了したこと
|
||||
- Cranelift AOT 設計とインタフェース草案のドキュメント追加:
|
||||
- docs/backend-cranelift-aot-design.md
|
||||
- docs/interfaces/cranelift-aot-box.md
|
||||
- LinkerBox 仕様とAOTスモーク仕様(擬似出力)
|
||||
- docs/interfaces/linker-box.md
|
||||
- docs/tests/aot_smoke_cranelift.md
|
||||
- Phase 15 集約README
|
||||
- docs/phase-15/README.md
|
||||
- スモーク雛形(DRYRUN既定。CLIF_SMOKE_RUN=1で実行)
|
||||
- tools/aot_smoke_cranelift.sh(Unix/WSL)
|
||||
- tools/aot_smoke_cranelift.ps1(Windows)
|
||||
|
||||
次にやること(別ブランチで実装)
|
||||
1) ブランチ作成: `git switch -c phase-15/self-host-aot-cranelift`
|
||||
2) CraneliftAotBox(PoC)
|
||||
- `src/backend/cranelift/aot_box.rs` を追加
|
||||
- `compile_stub_ny_main_i64(val, out_obj)` で `.o/.obj` を出力
|
||||
- Cargo feature: `cranelift-aot = ["dep:cranelift-object"]`
|
||||
3) LinkerBox(Windows優先)
|
||||
- `.o/.obj` + NyRT(`libnyrt.a`/`nyrt.lib`)で EXE を生成
|
||||
- 環境変数: `NYASH_LINKER`/`NYASH_LINK_FLAGS`/`NYASH_LINK_VERBOSE`
|
||||
4) CLI 統合(PoC)
|
||||
- `--backend cranelift-aot` と `--poc-const N`
|
||||
5) スモーク
|
||||
- apps/ny-hello → emit → link → run → `Result: 42` を確認
|
||||
- 既存スクリプト雛形を “実行” モードで動くよう配線
|
||||
|
||||
運用メモ(Codex 非同期 2本)
|
||||
- 2本起動: `CODEX_MAX_CONCURRENT=2 CODEX_DEDUP=1 ./tools/codex-keep-two.sh codex "<Task A>" "<Task B>"`
|
||||
- 1本起動: `CODEX_ASYNC_DETACH=1 ./tools/codex-async-notify.sh "<task>" codex`
|
||||
- ログ: `~/.codex-async-work/logs/`
|
||||
|
||||
スモーク雛形の使い方(DRYRUN)
|
||||
- Unix/WSL: `./tools/aot_smoke_cranelift.sh release`
|
||||
- Windows: `pwsh -File tools/aot_smoke_cranelift.ps1 -Mode release`
|
||||
- 実行モード: `CLIF_SMOKE_RUN=1` を付与(AOT実装が入った後に使用)
|
||||
|
||||
参考リンク
|
||||
- docs/phase-15/README.md(全体像)
|
||||
- docs/backend-cranelift-aot-design.md(AOT設計)
|
||||
- docs/interfaces/cranelift-aot-box.md(CraneliftAotBox API案)
|
||||
- docs/interfaces/linker-box.md(LinkerBox仕様)
|
||||
- docs/tests/aot_smoke_cranelift.md(スモーク仕様と擬似出力)
|
||||
|
||||
補足(メモリ/GC)
|
||||
- P0/P1(定数返し/整数演算)では追加のメモリ系Boxは不要。
|
||||
- P2以降で配列/文字列の生成・更新をAOTから行う場合、NyRTに最小のC ABI(roots/barrier/alloc系)を追加予定(docsに設計案を後続追記)。
|
||||
|
||||
57
docs/interfaces/cranelift-aot-box.md
Normal file
57
docs/interfaces/cranelift-aot-box.md
Normal file
@ -0,0 +1,57 @@
|
||||
CraneliftAotBox インタフェース草案(Phase 15 準備)
|
||||
|
||||
前提
|
||||
- 本ブランチでは「仕様化(ドキュメント)」のみ行い、実装は別ブランチ `phase-15/self-host-aot-cranelift` で行う。
|
||||
- Cargo フィーチャ: `cranelift-aot = ["dep:cranelift-object"]` を追加し、同フィーチャ時のみ AOT モジュールを有効化する。
|
||||
|
||||
モジュール構成(案)
|
||||
- パス: `src/backend/cranelift/aot_box.rs`
|
||||
- 依存: `cranelift-object`(オブジェクト出力)、既存のオブジェクトビルダ/ヘルパを再利用可能なら抽象化して流用。
|
||||
|
||||
公開型(案)
|
||||
- `pub struct CraneliftAotConfig {`
|
||||
- `pub opt_level: u8` // 0..3 程度(実装は後続)
|
||||
- `pub target: Option<String>` // target triple 等(未指定でホスト)
|
||||
`}`
|
||||
|
||||
- `pub struct CraneliftAotBox {`
|
||||
- `obj: <object builder>`
|
||||
- `cfg: CraneliftAotConfig`
|
||||
`}`
|
||||
|
||||
- `#[derive(Debug)] pub enum CraneliftAotError {`
|
||||
- `Codegen(String)`, `IO(String)`
|
||||
`}`
|
||||
|
||||
主要メソッド(案)
|
||||
- `impl CraneliftAotBox {`
|
||||
- `pub fn new(cfg: CraneliftAotConfig) -> Result<Self, CraneliftAotError>`
|
||||
- `pub fn compile_stub_ny_main_i64(&mut self, val: i64, out_obj: impl AsRef<Path>) -> Result<(), CraneliftAotError>`
|
||||
- 役割: PoC。`ny_main` 関数を定義し、即値 `val` を返すオブジェクトを生成。
|
||||
- `pub fn compile_mir_to_obj(&mut self, mir: MirModule, out_obj: impl AsRef<Path>) -> Result<(), CraneliftAotError>`
|
||||
- 役割: P1〜。最小 MIR(`const_i64`/`add_i64`/`ret`)から CLIF を組み立てて出力。
|
||||
`}`
|
||||
|
||||
使用例(PoC フロー)
|
||||
1) NyRT ビルド: `cargo build -p nyrt --release`
|
||||
2) オブジェクト出力(CLIイメージ):
|
||||
- `nyash --backend cranelift-aot --poc-const 42 apps/hello/main.nyash -o ny_main.o`
|
||||
3) リンク:
|
||||
- Linux: `cc -o app ny_main.o target/release/libnyrt.a -ldl -lpthread`
|
||||
- Windows: `link ny_main.obj nyrt.lib /OUT:app.exe`
|
||||
4) 実行: `./app` → `Result: 42` を確認。
|
||||
|
||||
エラーモデル(案)
|
||||
- 環境・設定: フィーチャ未有効や未対応ターゲット → 分かりやすいメッセージ。
|
||||
- 生成・出力: `CraneliftAotError::Codegen(_)`/`CraneliftAotError::IO(_)` で大別。
|
||||
|
||||
補助スクリプトの仕様(設計のみ)
|
||||
- ファイル: `tools/aot_smoke_cranelift.sh`
|
||||
- 目的: `.o/.obj` を生成→リンク→実行して PoC を自動検証。
|
||||
- 主要引数: `apps/APP/main.nyash -o app`、必要に応じ `--const` を透過的に渡す。
|
||||
|
||||
今後の拡張(非ブロッキング)
|
||||
- NyRT の外部関数呼び出し(checkpoint など)の導入。
|
||||
- MIR 命令カバレッジの拡大、BoxCall/Plugin 経由の I/O。
|
||||
- ターゲットトリプルとオブジェクト形式の明示的制御。
|
||||
|
||||
48
docs/interfaces/linker-box.md
Normal file
48
docs/interfaces/linker-box.md
Normal file
@ -0,0 +1,48 @@
|
||||
LinkerBox 仕様(Phase 15 準備 / Windows優先)
|
||||
|
||||
目的
|
||||
- AOT 生成されたオブジェクト(`.o/.obj`)を NyRT とリンクして実行可能ファイルを得る統一レイヤ。
|
||||
- 初期実装は「外部リンカー呼び出し」(MSVC `link.exe` または `lld-link`、Unix は `cc`)で動作し、将来的に lld 内蔵連携へ置換可能な設計とする。
|
||||
|
||||
前提/エントリポイント
|
||||
- 既定のエントリポイントは NyRT 側の `main()`(`crates/nyrt` に実装)。
|
||||
- AOT 側は `ny_main`(想定: `() -> i64`)を定義し、NyRT の `main()` が `ny_main()` を呼び出す。
|
||||
- よって通常は `/ENTRY:` 指定は不要(NyRT をリンクしない特殊構成でのみ上書き可能とする)。
|
||||
|
||||
入力と出力
|
||||
- 入力: 一つ以上のオブジェクト(`.obj`/`.o`)、追加ライブラリ群、ライブラリ検索パス。
|
||||
- 既定ライブラリ: NyRT(Windows: `nyrt.lib`、Unix: `libnyrt.a`)。
|
||||
- 出力: 実行ファイル(Windows: `*.exe`、Unix: 実行ビット付きバイナリ)。
|
||||
|
||||
環境変数(LinkerBox が解釈)
|
||||
- `NYASH_LINKER`: 使用リンカーを強制。`link` | `lld-link` | `cc`(未指定は OS/環境から自動推定)
|
||||
- `NYASH_LINK_FLAGS`: 追加フラグ(空白区切り)。
|
||||
- `NYASH_LINK_VERBOSE=1`: 実コマンドラインを表示。
|
||||
- `NYASH_LINK_ENTRY=<symbol>`: エントリポイントを明示的に指定(既定は未指定で NyRT の `main` を使用)。
|
||||
- `NYASH_LINK_OUT=<path>`: 出力先を明示的に指定(CLI引数 `-o` が優先)。
|
||||
|
||||
Windows(MSVC / lld-link)
|
||||
- 既定探索順: `link.exe` → `lld-link`。
|
||||
- 代表フラグ:
|
||||
- `link.exe`: `/OUT:<exe>` `/SUBSYSTEM:CONSOLE`(既定) `/LIBPATH:<dir>` `nyrt.lib` 他
|
||||
- `lld-link`: `-OUT:<exe>` `-SUBSYSTEM:CONSOLE` `-LIBPATH:<dir>` `nyrt.lib`
|
||||
- `PATH`/`LIB`/`LIBPATH` の整合に注意(Developer Command Prompt を推奨)。
|
||||
|
||||
Unix(参考)
|
||||
- 代表フラグ: `cc -o <exe> <objs...> <lib paths> -L... -lnyrt -ldl -lpthread`
|
||||
- 既定のオブジェクト形式/ターゲットはホストに従う。
|
||||
|
||||
CLI API(想定)
|
||||
- `nyash --linker link|lld-link|cc --libpath <dir> --lib nyrt [--entry nyash_main] -o app <objs...>`
|
||||
- AOT パスでは内部的に LinkerBox を呼び出し、上記環境変数も透過的に反映する。
|
||||
|
||||
エラー方針
|
||||
- ツールチェーン未検出(リンカー不在): わかりやすい対処案を表示(MSVC のセットアップ/lld の導入)。
|
||||
- 未解決シンボル: `ny_main`/NyRT 関連の欠落を優先表示。
|
||||
- 引数/パスのクォート: 空白を含むパスは安全にクォートして実行。
|
||||
|
||||
将来拡張
|
||||
- 内蔵 lld を採用した一体化(外部プロセス呼び出しからの置換)。
|
||||
- ターゲットトリプルの明示指定とクロスリンク(フェーズ後半)。
|
||||
- 追加ランタイムやプラグイン静的リンクのオプション化。
|
||||
|
||||
32
docs/phase-15/README.md
Normal file
32
docs/phase-15/README.md
Normal file
@ -0,0 +1,32 @@
|
||||
Phase 15 — Self-Hosting (Cranelift AOT) 準備メモ
|
||||
|
||||
目的
|
||||
- Nyash → MIR → Cranelift AOT(C ABI)→ オブジェクト → リンク → EXE の最小パイプライン確立。
|
||||
- 本ブランチでは「影響小・再現性高い」準備(設計/仕様/スモーク雛形)に限定し、実装は別ブランチで行う。
|
||||
|
||||
現状ステータス(このブランチ)
|
||||
- 設計ノート: docs/backend-cranelift-aot-design.md
|
||||
- インタフェース草案: docs/interfaces/cranelift-aot-box.md
|
||||
- LinkerBox 仕様: docs/interfaces/linker-box.md
|
||||
- AOTスモーク仕様(擬似出力): docs/tests/aot_smoke_cranelift.md
|
||||
- スモーク雛形(DRYRUN 既定):
|
||||
- tools/aot_smoke_cranelift.sh(Unix/WSL)
|
||||
- tools/aot_smoke_cranelift.ps1(Windows)
|
||||
|
||||
ハンドオフ
|
||||
- 引き継ぎの全体像と運用メモは docs/handoff/phase-15-handoff.md を参照。
|
||||
|
||||
次ブランチで実装する項目(phase-15/self-host-aot-cranelift)
|
||||
- CraneliftAotBox: `compile_stub_ny_main_i64` → `.o/.obj` を出力。
|
||||
- LinkerBox: `.o/.obj` + NyRT(libnyrt)で EXE にリンク(Windows優先)。
|
||||
- CLI統合: `--backend cranelift-aot` と PoC フラグ(`--poc-const`)。
|
||||
- スモーク実行: apps/ny-hello → EXE 生成・起動確認。
|
||||
|
||||
合否基準(P0)
|
||||
- `ny_main` を定義するオブジェクトを生成できる。
|
||||
- NyRT とリンクして EXE を生成できる。
|
||||
- 実行し、既知の値(例: `Result: 42`)を出力。
|
||||
|
||||
補足
|
||||
- Windowsを先行サポートし、Linux/macOS は後続対応。
|
||||
- 実出力やビルドログは `tools/codex-async-notify.sh` のログ参照運用を継続。
|
||||
75
docs/tests/aot_smoke_cranelift.md
Normal file
75
docs/tests/aot_smoke_cranelift.md
Normal file
@ -0,0 +1,75 @@
|
||||
# Cranelift AOT Smoke (Windows‑first)
|
||||
|
||||
Purpose
|
||||
- Validate the Cranelift‑based AOT pipeline end‑to‑end:
|
||||
1) Build `nyash` with `cranelift-jit` feature.
|
||||
2) Emit an object via `NYASH_AOT_OBJECT_OUT` while running `--backend cranelift`.
|
||||
3) Link the object with NyRT into a runnable binary (via LinkerBox or helper scripts).
|
||||
4) Run the binary and assert output.
|
||||
|
||||
Prerequisites
|
||||
- Build flags: `cargo build --release --features cranelift-jit`
|
||||
- Windows:
|
||||
- Prefer MSVC `link.exe` (Developer Command Prompt or properly set env).
|
||||
- Fallback: `lld-link` in `PATH`.
|
||||
- PowerShell available for `tools/aot_smoke_cranelift.ps1`.
|
||||
- Unix (optional): system linker (`ld`), or `lld`/`mold`, and `tools/aot_smoke_cranelift.sh`.
|
||||
|
||||
Environment toggles
|
||||
- `NYASH_CLIF_ARRAY_SMOKE=1`: run array smoke (simple Result check).
|
||||
- `NYASH_CLIF_ARRAY_RET_SMOKE=1`: run “return value” array smoke.
|
||||
- `NYASH_CLIF_ECHO_SMOKE=1`: run echo smoke (stdin → stdout).
|
||||
- `NYASH_CLIF_VINVOKE_SMOKE=1`: run variable‑length invoke smoke (plugins required).
|
||||
- `NYASH_CLIF_VINVOKE_RET_SMOKE=1`: run vinvoke return/size smokes (plugins required).
|
||||
- `NYASH_DISABLE_PLUGINS=1`: disable plugin‑dependent smokes.
|
||||
- `NYASH_LINK_VERBOSE=1`: print final link command.
|
||||
|
||||
Pseudo run
|
||||
- Script: `tools/aot_smoke_cranelift.sh` / `tools/aot_smoke_cranelift.ps1`
|
||||
- Typical invocation: `./tools/aot_smoke_cranelift.sh release`
|
||||
|
||||
Pseudo output (example)
|
||||
```
|
||||
[clif-aot-smoke] building nyash (release, feature=cranelift-jit)...
|
||||
[clif-aot-smoke] emitting object via --backend cranelift ...
|
||||
[clif-aot-smoke] OK: object generated: /ABS/path/target/aot_objects/core_smoke.obj (1536 bytes)
|
||||
|
||||
[clif-aot-smoke][win] linking app_clif.exe using link.exe
|
||||
[clif-aot-smoke][win] entry=nyash_main subsystem=CONSOLE runtime=nyrt.lib
|
||||
[clif-aot-smoke] running app_clif.exe ...
|
||||
[clif-aot-smoke] output: Result: 3
|
||||
[clif-aot-smoke] OK: core smoke passed
|
||||
|
||||
[clif-aot-smoke] skipping array smoke (set NYASH_CLIF_ARRAY_SMOKE=1 to enable)
|
||||
[clif-aot-smoke] skipping echo smoke (set NYASH_CLIF_ECHO_SMOKE=1 to enable)
|
||||
[clif-aot-smoke] skipping vinvoke smokes (set NYASH_CLIF_VINVOKE_SMOKE=1 / NYASH_CLIF_VINVOKE_RET_SMOKE=1)
|
||||
```
|
||||
|
||||
What the script does (intended)
|
||||
- Build:
|
||||
- `cargo build --release --features cranelift-jit`
|
||||
- Emit object:
|
||||
- Ensure stable output dir: `mkdir -p target/aot_objects`
|
||||
- `NYASH_AOT_OBJECT_OUT="$PWD/target/aot_objects/core_smoke.obj" ./target/release/nyash --backend cranelift apps/hello/main.nyash > /dev/null || true`
|
||||
- Validate file exists and non‑zero size.
|
||||
- Link:
|
||||
- Windows: PowerShell `tools/aot_smoke_cranelift.ps1 -Mode release`
|
||||
- Unix: `tools/aot_smoke_cranelift.sh release`
|
||||
- Run and verify:
|
||||
- `./app_clif[.exe]` → expect a line including `Result:`.
|
||||
|
||||
Windows specifics
|
||||
- Prefer MSVC `link.exe`; auto‑fallback to `lld-link` if present.
|
||||
- If neither available, fail with a helpful message to open a Developer Command Prompt or install LLVM lld.
|
||||
- Use `.obj` extension for emitted object; still accept `.o` if emitted by a GNU toolchain.
|
||||
|
||||
Exit codes
|
||||
- 0: all enabled smokes passed
|
||||
- 1: object missing/empty, or unexpected program output
|
||||
- 2: toolchain missing (no Cranelift build or no linker)
|
||||
|
||||
Future alignment with LinkerBox
|
||||
- This smoke is the acceptance test for LinkerBox’s AOT path on Cranelift:
|
||||
- Same entrypoint (`nyash_main`), runtime linkage (`nyrt.lib`/`libnyrt.a`), and CLI env (`NYASH_LINKER`, `NYASH_LINK_FLAGS`, `NYASH_LINK_VERBOSE`).
|
||||
- When LinkerBox becomes default, keep CLI stable and swap implementation behind it.
|
||||
|
||||
88
tools/aot_smoke_cranelift.ps1
Normal file
88
tools/aot_smoke_cranelift.ps1
Normal file
@ -0,0 +1,88 @@
|
||||
<#
|
||||
AOT smoke (Cranelift) — DRYRUN skeleton (Windows-first)
|
||||
Usage:
|
||||
pwsh -File tools/aot_smoke_cranelift.ps1 [-Mode release|debug]
|
||||
Env:
|
||||
CLIF_SMOKE_RUN=1 # actually execute steps (default: dry-run only)
|
||||
NYASH_LINK_VERBOSE=1 # echo link commands (when run)
|
||||
NYASH_DISABLE_PLUGINS=1 # plugin-dependent smokes off
|
||||
Notes:
|
||||
- This script mirrors docs/tests/aot_smoke_cranelift.md pseudo flow.
|
||||
- PoC: emits commands; real execution requires Cranelift AOT path to be implemented.
|
||||
#>
|
||||
|
||||
param(
|
||||
[ValidateSet('release','debug')]
|
||||
[string]$Mode = 'release'
|
||||
)
|
||||
|
||||
$Run = [int]([Environment]::GetEnvironmentVariable('CLIF_SMOKE_RUN') ?? '0')
|
||||
|
||||
function Banner($msg) { Write-Host "`n[clif-aot-smoke] $msg" }
|
||||
function Info($msg) { Write-Host "[clif-aot-smoke] $msg" }
|
||||
|
||||
$Root = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path
|
||||
$Target = Join-Path $Root 'target'
|
||||
$ObjDir = Join-Path $Target 'aot_objects'
|
||||
New-Item -ItemType Directory -Force -Path $ObjDir | Out-Null
|
||||
$ObjOut = Join-Path $ObjDir 'core_smoke.obj'
|
||||
$NyashBin = Join-Path (Join-Path $Target $Mode) 'nyash.exe'
|
||||
$ExeOut = Join-Path $Target 'app_clif.exe'
|
||||
|
||||
Banner "Cranelift AOT Smoke (mode=$Mode, dry-run=$([bool](-not ($Run -eq 1))))"
|
||||
|
||||
# 1) Build nyash with cranelift
|
||||
Banner "building nyash (features=cranelift-jit)"
|
||||
if ($Run -eq 1) {
|
||||
& cargo build --% --$Mode --features cranelift-jit
|
||||
} else {
|
||||
Info "DRYRUN: cargo build --$Mode --features cranelift-jit"
|
||||
}
|
||||
|
||||
# 2) Emit object via backend=cranelift (PoC path)
|
||||
Banner "emitting object via --backend cranelift (PoC)"
|
||||
if ($Run -eq 1) {
|
||||
if (-not (Test-Path $NyashBin)) { throw "nyash not found: $NyashBin" }
|
||||
$env:NYASH_AOT_OBJECT_OUT = $ObjOut
|
||||
& $NyashBin --backend cranelift apps/hello/main.nyash | Out-Null
|
||||
if (-not (Test-Path $ObjOut)) { throw "object not generated: $ObjOut" }
|
||||
$size = (Get-Item $ObjOut).Length
|
||||
Info "OK: object generated: $ObjOut ($size bytes)"
|
||||
} else {
|
||||
Info "DRYRUN: NYASH_AOT_OBJECT_OUT=$ObjOut $NyashBin --backend cranelift apps/hello/main.nyash"
|
||||
New-Item -ItemType File -Force -Path $ObjOut | Out-Null
|
||||
}
|
||||
|
||||
# 3) Link (Windows-first)
|
||||
Banner "linking app (Windows-first)"
|
||||
if ($Run -eq 1) {
|
||||
$link = Get-Command link -ErrorAction SilentlyContinue
|
||||
$lld = Get-Command lld-link -ErrorAction SilentlyContinue
|
||||
if ($link) {
|
||||
Info "using MSVC link.exe"
|
||||
& link /OUT:$ExeOut $ObjOut nyrt.lib
|
||||
} elseif ($lld) {
|
||||
Info "using lld-link"
|
||||
& lld-link -OUT:$ExeOut $ObjOut nyrt.lib
|
||||
} else {
|
||||
throw "no Windows linker found (link.exe/lld-link)"
|
||||
}
|
||||
} else {
|
||||
Info "DRYRUN: link /OUT:$ExeOut $ObjOut nyrt.lib (or lld-link)"
|
||||
}
|
||||
|
||||
# 4) Run and verify
|
||||
Banner "run and verify output"
|
||||
if ($Run -eq 1) {
|
||||
if (-not (Test-Path $ExeOut)) { throw "no output binary: $ExeOut" }
|
||||
$out = & $ExeOut 2>&1
|
||||
$out | Write-Host
|
||||
if ($out -notmatch 'Result:') { throw "unexpected output" }
|
||||
Info "OK: smoke passed"
|
||||
} else {
|
||||
Info "DRYRUN: $ExeOut → expect a line including: 'Result:'"
|
||||
Info "DRYRUN complete"
|
||||
}
|
||||
|
||||
exit 0
|
||||
|
||||
117
tools/aot_smoke_cranelift.sh
Normal file
117
tools/aot_smoke_cranelift.sh
Normal file
@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env bash
|
||||
# AOT smoke (Cranelift) — DRYRUN skeleton (Windows-first)
|
||||
#
|
||||
# Usage:
|
||||
# ./tools/aot_smoke_cranelift.sh [release|debug]
|
||||
# Env:
|
||||
# CLIF_SMOKE_RUN=1 # actually execute steps (default: dry-run only)
|
||||
# CODEX_NOTIFY_TAIL=100 # for CI/logging callers (optional)
|
||||
# NYASH_LINK_VERBOSE=1 # echo link commands (when run)
|
||||
# NYASH_DISABLE_PLUGINS=1 # plugin-dependent smokes off
|
||||
# NYASH_CLIF_* # feature toggles (see docs/tests/aot_smoke_cranelift.md)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
MODE=${1:-release}
|
||||
case "$MODE" in
|
||||
release|debug) : ;;
|
||||
*) echo "Usage: $0 [release|debug]" >&2; exit 2;;
|
||||
esac
|
||||
|
||||
RUN=${CLIF_SMOKE_RUN:-0}
|
||||
ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
TARGET_DIR="$ROOT_DIR/target"
|
||||
OBJ_DIR="$TARGET_DIR/aot_objects"
|
||||
EXE_WIN="$TARGET_DIR/app_clif.exe"
|
||||
EXE_NIX="$TARGET_DIR/app_clif"
|
||||
|
||||
banner() { printf '\n[clif-aot-smoke] %s\n' "$*"; }
|
||||
info() { printf '[clif-aot-smoke] %s\n' "$*"; }
|
||||
skip() { printf '[clif-aot-smoke] skipping %s (enable env to run)\n' "$*"; }
|
||||
|
||||
banner "Cranelift AOT Smoke (mode=$MODE, dry-run=$([ "$RUN" = 1 ] && echo off || echo on))"
|
||||
|
||||
mkdir -p "$OBJ_DIR"
|
||||
OBJ_OUT="$OBJ_DIR/core_smoke.$([ "$(uname -s)" = "Windows_NT" ] && echo obj || echo o)"
|
||||
NYASH_BIN="$ROOT_DIR/target/$MODE/nyash"
|
||||
|
||||
# 1) Build nyash with cranelift
|
||||
banner "building nyash (features=cranelift-jit)"
|
||||
if [ "$RUN" = 1 ]; then
|
||||
cargo build --$MODE --features cranelift-jit
|
||||
else
|
||||
info "DRYRUN: cargo build --$MODE --features cranelift-jit"
|
||||
fi
|
||||
|
||||
# 2) Emit object via backend=cranelift (PoC path; may be stub until implemented)
|
||||
banner "emitting object via --backend cranelift (PoC)"
|
||||
if [ "$RUN" = 1 ]; then
|
||||
if [ ! -x "$NYASH_BIN" ]; then
|
||||
echo "nyash binary not found: $NYASH_BIN" >&2; exit 2
|
||||
fi
|
||||
NYASH_AOT_OBJECT_OUT="$OBJ_OUT" "$NYASH_BIN" --backend cranelift apps/hello/main.nyash || true
|
||||
if [ ! -s "$OBJ_OUT" ]; then
|
||||
echo "object not generated (expected PoC path)." >&2; exit 1
|
||||
fi
|
||||
info "OK: object generated: $OBJ_OUT ($(stat -c%s "$OBJ_OUT" 2>/dev/null || wc -c <"$OBJ_OUT")) bytes)"
|
||||
else
|
||||
info "DRYRUN: NYASH_AOT_OBJECT_OUT=\"$OBJ_OUT\" $NYASH_BIN --backend cranelift apps/hello/main.nyash"
|
||||
info "DRYRUN: touch $OBJ_OUT (pretend non-empty)"
|
||||
fi
|
||||
|
||||
# 3) Link (Windows-first). In DRYRUN, just print the command.
|
||||
banner "linking app (Windows-first)"
|
||||
if [ "$RUN" = 1 ]; then
|
||||
case "$(uname -s)" in
|
||||
MINGW*|MSYS*|CYGWIN*|Windows_NT)
|
||||
if command -v link >/dev/null 2>&1; then
|
||||
info "using MSVC link.exe"
|
||||
link /OUT:"$EXE_WIN" "$OBJ_OUT" nyrt.lib || { echo "link failed" >&2; exit 1; }
|
||||
OUT_BIN="$EXE_WIN"
|
||||
elif command -v lld-link >/dev/null 2>&1; then
|
||||
info "using lld-link"
|
||||
lld-link -OUT:"$EXE_WIN" "$OBJ_OUT" nyrt.lib || { echo "lld-link failed" >&2; exit 1; }
|
||||
OUT_BIN="$EXE_WIN"
|
||||
else
|
||||
echo "no Windows linker found (link.exe/lld-link)" >&2; exit 2
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if command -v cc >/dev/null 2>&1; then
|
||||
cc -o "$EXE_NIX" "$OBJ_OUT" "$TARGET_DIR/release/libnyrt.a" -ldl -lpthread || { echo "cc link failed" >&2; exit 1; }
|
||||
OUT_BIN="$EXE_NIX"
|
||||
else
|
||||
echo "no cc found for Unix link" >&2; exit 2
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
else
|
||||
case "$(uname -s)" in
|
||||
MINGW*|MSYS*|CYGWIN*|Windows_NT)
|
||||
info "DRYRUN: link /OUT:$EXE_WIN $OBJ_OUT nyrt.lib (or lld-link)"
|
||||
;;
|
||||
*)
|
||||
info "DRYRUN: cc -o $EXE_NIX $OBJ_OUT target/release/libnyrt.a -ldl -lpthread"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# 4) Run and verify
|
||||
banner "run and verify output"
|
||||
if [ "$RUN" = 1 ]; then
|
||||
if [ -z "${OUT_BIN:-}" ] || [ ! -x "$OUT_BIN" ]; then
|
||||
echo "no output binary to run" >&2; exit 1
|
||||
fi
|
||||
set +e
|
||||
OUTPUT="$($OUT_BIN 2>&1)"; RC=$?
|
||||
set -e
|
||||
echo "$OUTPUT"
|
||||
echo "$OUTPUT" | grep -q "Result:" || { echo "unexpected output" >&2; exit 1; }
|
||||
info "OK: smoke passed"
|
||||
else
|
||||
info "DRYRUN: ./app_clif[.exe] → expect a line including: 'Result: 3' or 'Result: 42'"
|
||||
info "DRYRUN complete"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user