## LLVM Codegen Refactoring (by ChatGPT5) - Split massive boxcall.rs into focused submodules: - strings.rs: String method optimizations (concat, length) - arrays.rs: Array operations (get, set, push, length) - maps.rs: Map operations (get, set, has, size) - fields.rs: getField/setField handling - invoke.rs: Tagged invoke implementation - marshal.rs: Helper functions for marshaling - Improved code organization and maintainability - No functional changes, pure refactoring ## Phase 15 Documentation Cleanup - Restructured phase-15 folder: - implementation/: Technical implementation docs - planning/: Planning and sequence docs - archive/: Redundant/old content - Removed duplicate content (80k→20k line reduction mentioned 5 times) - Converted all .txt files to .md for consistency - Fixed broken links in README.md - Removed redundant INDEX.md ## Phase 21: Database-Driven Development (New) - Revolutionary concept: Source code in SQLite instead of files - Instant refactoring with SQL transactions - Structured management of boxes, methods, dependencies - Technical design with security considerations - Vision: World's first DB-driven programming language 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
5.9 KiB
5.9 KiB
Phase 15 自己ホスティング実装戦略 - MIR→Cranelift→lld
Author: ChatGPT5 + Claude協議 Date: 2025-09-03 Version: 1.0
📋 概要
Nyash完全自己ホスティングを実現するための具体的実装戦略。 **「MIR→Craneliftで.o/.objを作る→lldでEXEを組む」**をNyashツールチェーンに内蔵する。
🎯 最終形(自己ホスト時の一発ボタン)
nyash build main.ny \
--backend=cranelift \
--target=x86_64-pc-windows-msvc # or x86_64-unknown-linux-gnu
内部処理フロー:
- frontend: AST→MIR13
- codegen: MIR→Cranelift→
.obj/.o - link:
lld-link(Win) /ld.lld(Linux)でEXE生成 - 依存ランタイム
nyashrtを自動リンク(静的/動的選択)
🏗️ 実装の芯(最小で美しいやつ)
1. コード生成ライブラリ(C ABIファサード)
// 最小限の美しいインターフェース
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 - 主要フラグ:
lld-link <objs...> nyashrt.lib /SUBSYSTEM:CONSOLE \
/OUT:a.exe /ENTRY:nyash_entry \
/LIBPATH:<sdk/lib> /MACHINE:X64
- MSVC互換が要る配布向けに
/fallback:link.exeオプションも用意可
Linux
- 既定:
ld.lld(開発でmold併用可)
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)
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生成失敗など |
| リンク失敗 | リンカ標準出力 | ファイル名/未解決シンボルを整形表示 |
診断オプション:
--emit=clif,asm,obj,link-cmd # 診断をファイル出力(再現しやすい)
💾 キャッシュ&クロスコンパイル
オブジェクトキャッシュ
hash(MIR, target, codegen_ver) → .obj/.oを再利用
クロスコンパイル
--target=<triple> # .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例
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 <obj> --target=<triple>がlldでEXEを作れる- Windows/Linuxそれぞれ"Hello, Box!"実行成功
--emit=clif,asmでダンプが落ちる- 失敗時のエラーメッセージがファイル名+未解決シンボルまで出る
nyash toolchain doctorでlld/SDK検出
📐 実装設計詳細
LinkerBox設計
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統合
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生成の"気持ちいい体験"が完成!