# Phase 15 自己ホスティング実装戦略 - MIR→Cranelift→lld Author: ChatGPT5 + Claude協議 Date: 2025-09-03 Version: 1.0 ## 📋 概要 Nyash完全自己ホスティングを実現するための具体的実装戦略。 **「MIR→Craneliftで.o/.objを作る→lldでEXEを組む」**をNyashツールチェーンに内蔵する。 ## 🎯 最終形(自己ホスト時の一発ボタン) ```bash nyash build main.ny \ --backend=cranelift \ --target=x86_64-pc-windows-msvc # or x86_64-unknown-linux-gnu ``` 内部処理フロー: 1. **frontend**: AST→MIR13 2. **codegen**: MIR→Cranelift→`.obj/.o` 3. **link**: `lld-link`(Win) / `ld.lld`(Linux)でEXE生成 4. 依存ランタイム`nyashrt`を自動リンク(静的/動的選択) ## 🏗️ 実装の芯(最小で美しいやつ) ### 1. コード生成ライブラリ(C ABIファサード) ```c // 最小限の美しいインターフェース ny_mir_to_obj(mir_bin, target_triple) -> obj_bytes ny_mir_jit_entry(mir_bin) -> exit_code // 開発用 ny_free_buf(buffer) // メモリ解放 // エラーハンドリング // 例外は戻り値+NyErr(unwind禁止) ``` 実装のポイント: - 返却メモリは`ny_free_buf`で解放 - 例外は戻り値+NyErrで統一(unwind禁止) - C ABIで安定した境界を作る ### 2. リンカー・ラッパ(プラットフォーム別) #### Windows - 既定: `lld-link` - 主要フラグ: ```bash lld-link nyashrt.lib /SUBSYSTEM:CONSOLE \ /OUT:a.exe /ENTRY:nyash_entry \ /LIBPATH: /MACHINE:X64 ``` - MSVC互換が要る配布向けに`/fallback:link.exe`オプションも用意可 #### Linux - 既定: `ld.lld`(開発で`mold`併用可) ```bash ld.lld -o a.out main.o -L. -lnyashrt -lc -lm -pthread \ --gc-sections --icf=all ``` #### macOS(将来) - 日常は`ld64.lld`、配布はXcodeの`ld64` + コード署名(要Entitlements) ### 3. 同梱/検出戦略 **優先順**: 埋め込み`lld` → システム`lld` → 代替(mold/link.exe/ld64) ```bash nyash toolchain doctor # 検出&パス設定 --linker=lld|mold|link.exe|ld64 # 明示上書き ``` ### 4. ランタイム同梱 - `nyashrt`を**static(.a/.lib)**と**shared(.so/.dll)**両用意 - 既定は**static**(配布が楽)、`--shared-rt`で動的リンクに切替 - Windowsは**PDB生成**、Linuxは`-g`/`-Wl,--build-id`でデバッグ容易に ## 🔧 エラー整合(ビルド失敗をわかりやすく) | エラー種別 | 戻り値 | 説明・対処 | |----------|-------|-----------| | `ny_mir_to_obj`失敗 | `NYCG_ERR_*` | ターゲット不一致/CLIF生成失敗など | | リンク失敗 | リンカ標準出力 | ファイル名/未解決シンボルを整形表示 | 診断オプション: ```bash --emit=clif,asm,obj,link-cmd # 診断をファイル出力(再現しやすい) ``` ## 💾 キャッシュ&クロスコンパイル ### オブジェクトキャッシュ `hash(MIR, target, codegen_ver)` → `.obj/.o`を再利用 ### クロスコンパイル ```bash --target= # .obj/.oとリンク器/SDKを切替 ``` - Win用: `x86_64-pc-windows-msvc`(`lld-link` + MSVCライブラリ) - Linux: `x86_64-unknown-linux-gnu`(`ld.lld` + glibc) **Zig toolchain**を併用するとクロス用のCRT/SDKが楽(内部はlld) ## 🎨 使いやすいCLI例 ```bash nyash build main.ny --backend=cranelift --release nyash build main.ny --emit=obj,asm,clif # 解析用 nyash run main.ny --backend=cranelift # JITで即実行 nyash toolchain doctor # lld/SDK検出 ``` ## ⚡ 地味に効く最適化スイッチ ### リンカ最適化 - `ld.lld`: `--gc-sections --icf=all`(不要コード除去&同一関数折りたたみ) ### Cranelift最適化 - `opt_level=speed` - TypedArrayの**bounds-check併合**をLowerで実装 ### 実行時最適化 - 起動時CPUIDで**関数ポインタ切替**(AVX2/512の専用小関数) ## ✅ 最初の"動くまで"チェックリスト - [ ] `ny_mir_to_obj`(C ABI)で`.o/.obj`を返せる - [ ] `nyash link --target=`が`lld`でEXEを作れる - [ ] Windows/Linuxそれぞれ"Hello, Box!"実行成功 - [ ] `--emit=clif,asm`でダンプが落ちる - [ ] 失敗時のエラーメッセージが**ファイル名+未解決シンボル**まで出る - [ ] `nyash toolchain doctor`でlld/SDK検出 ## 📐 実装設計詳細 ### LinkerBox設計 ```nyash box LinkerBox { init { platform, linker_path, libraries, flags } link(objects, output_path) { local cmd = me.build_link_command(objects, output_path) local result = me.execute_linker(cmd) if result.exit_code != 0 { me.format_link_error(result.stderr) } return result } detect_linker() { // 優先順: 内蔵lld → システムlld → 代替 if me.has_embedded_lld() { return me.extract_embedded_lld() } return me.find_system_linker() } } ``` ### CraneliftBox統合 ```nyash box CraneliftBox { init { target_triple, opt_level } compile(mir) { // MIR13 → Cranelift IR → Object local module = me.create_module() for inst in mir.instructions { me.lower_instruction(module, inst) } return module.compile() } } ``` ## 🌟 まとめ - **Yes**: CraneliftでEXEにするには**内部でlldを叩く機能を埋め込む**のが正攻法 - 仕組みは**MIR→Cranelift .o/.obj → lld** - C ABIファサード経由でcodegenを呼び、リンカは**内蔵ドライバ**で統一 - これで**自己ホスト→即EXE生成**の"気持ちいい体験"が完成! ## 🔗 関連ドキュメント - [Phase 15メインドキュメント](README.md) - [C ABI境界設計](../phase-12/c-abi-spec.md) - [MIR 13命令セット](../../reference/mir/INSTRUCTION_SET.md) - [Cranelift統合](../phase-10/)