Files
hakorune/docs/phases/phase-11/MIR_TO_LLVM_CONVERSION_PLAN.md

5.6 KiB
Raw Blame History

MIR→LLVM変換計画

Date: 2025-08-31
Status: Draft

📊 変換マッピング概要

Core-15命令のLLVM IR対応第三案・Box統一

1. 基本演算(5)

// Const
MIR::Const(i64)  LLVMConstInt(i64_type, val)
MIR::Const(f64)  LLVMConstReal(f64_type, val)
MIR::Const(bool)  LLVMConstInt(i1_type, val)
MIR::Const(string)  @nyash_string_new(ptr, len)

// UnaryOp
MIR::UnaryOp(Neg, x)  LLVMBuildNeg(x) / LLVMBuildFNeg(x)
MIR::UnaryOp(Not, x)  LLVMBuildNot(x)

// BinOp
MIR::BinOp(Add, a, b)  LLVMBuildAdd(a, b) / LLVMBuildFAdd(a, b)
MIR::BinOp(Sub, a, b)  LLVMBuildSub(a, b) / LLVMBuildFSub(a, b)
// 注: Box型の場合は@nyash_box_add等のランタイム呼び出し

// Compare
MIR::Compare(Eq, a, b)  LLVMBuildICmp(EQ, a, b) / LLVMBuildFCmp(OEQ, a, b)
MIR::Compare(Lt, a, b)  LLVMBuildICmp(SLT, a, b) / LLVMBuildFCmp(OLT, a, b)

// TypeOp
MIR::TypeOp(Check, val, type)  @nyash_type_check(val, type_id)
MIR::TypeOp(Cast, val, type)  @nyash_type_cast(val, type_id)

2. メモリ(2)

// Load
MIR::Load(local_id)  LLVMBuildLoad(local_ptr[local_id])

// Store
MIR::Store(local_id, val)  LLVMBuildStore(val, local_ptr[local_id])

3. 制御(4)

// Branch
MIR::Branch(cond, then_bb, else_bb)  LLVMBuildCondBr(cond, then_bb, else_bb)

// Jump
MIR::Jump(bb)  LLVMBuildBr(bb)

// Return
MIR::Return(val)  LLVMBuildRet(val)
MIR::Return(None)  LLVMBuildRetVoid()

// Phi
MIR::Phi([(bb1, val1), (bb2, val2)])  {
    phi = LLVMBuildPhi(type)
    LLVMAddIncoming(phi, [val1, val2], [bb1, bb2])
}

4. Box操作(3)

// NewBox
MIR::NewBox(type_name, args)  @nyash_box_new(type_id, args_ptr, args_len)

// BoxCall注釈活用・名前/スロット両対応)
MIR::BoxCall(obj, method, args)  {
    if annotations.inline_hint {
        // インライン展開候補
        LLVMSetInlineHint(call)
    }
    if annotations.method_id { /* vtableスロット解決 */ } 
    else { @nyash_box_call_by_name(obj, method_name, args) }
}
// PluginInvoke は BoxCall に統一Optimizerで正規化

5. 配列BoxCallに統一

// Arrayは BoxCall("get"/"set") で表現
// Lowering方針は2段階:
//  (A) 安全パス: @nyash_array_get/@nyash_array_set を呼ぶ(ランタイム側で境界/バリア)
//  (B) 型特化: 注釈/型情報が十分な場合に inline 化bounds check + GEP + load/store + write barrier

6. 外部呼び出し(1)

// ExternCall
MIR::ExternCall("env.console.log", args)  @nyash_console_log(args)
MIR::ExternCall("env.gc.collect", [])  @nyash_gc_collect()
MIR::ExternCall("env.runtime.checkpoint", [])  @nyash_safepoint()

🎯 注釈システムの活用

1. 最適化ヒント

pub struct OptimizationHints {
    pub inline: Option<InlineHint>,      // always/never/hint
    pub pure: bool,                      // 副作用なし
    pub no_escape: bool,                 // エスケープしない
    pub hot: bool,                       // ホットパス
    pub cold: bool,                      // コールドパス
}

2. GCヒント

pub struct GcHint {
    pub no_barrier: bool,        // バリア不要(新規オブジェクトへの書き込み等)
    pub immortal: bool,          // 不死オブジェクト(定数等)
    pub thread_local: bool,      // スレッドローカル並列GCで重要
}

3. 型情報ヒント

pub struct TypeHint {
    pub concrete_type: Option<String>,   // 具体的な型が判明
    pub never_null: bool,               // NULL不可
    pub value_range: Option<(i64, i64)>, // 値の範囲
}

🔧 LLVM属性の活用

関数属性

; 純粋関数
define i64 @add(i64 %a, i64 %b) #0 {
  %result = add i64 %a, %b
  ret i64 %result
}
attributes #0 = { nounwind readnone speculatable }

; GC セーフポイント
define void @long_loop() gc "nyash-gc" {
  ; ループバックエッジにセーフポイント
  call void @llvm.experimental.gc.statepoint(...)
}

メモリ属性

; Box用アドレス空間1
%box_ptr = addrspace(1)* %obj

; TBAAType-Based Alias Analysis
!0 = !{!"nyash.box"}
!1 = !{!"nyash.integer", !0}
!2 = !{!"nyash.string", !0}

📈 段階的実装計画

Phase 1: 基本変換1週間

  • inkwell セットアップ
  • 基本演算・メモリ・制御の変換
  • 最小限の実行可能コード生成

Phase 2: Box統合1週間

  • NewBox/BoxCall実装PluginInvokeはOptimizerでBoxCallに正規化
  • ランタイム経由の安全パスby-name/slot
  • 基本的なGCバリア安全パスはランタイム関数内で処理

Phase 3: 最適化1週間

  • 注釈システム統合
  • インライン展開
  • エスケープ解析

Phase 4: 高度な最適化1週間

  • 脱箱化Box → プリミティブ)
  • TBAA統合
  • ベクトル化ヒント

🎨 コード例

// MIR
function add(a: Box, b: Box) -> Box {
    %1 = Load $a
    %2 = Load $b
    %3 = BoxCall(%1, "add", [%2])
    Return %3
}

// LLVM IR最適化前・安全パス
define i8* @add(i8* %a, i8* %b) {
    %1 = call i8* @nyash_box_call(i8* %a, i8* @.str.add, i8** %b, i64 1)
    ret i8* %1
}

// LLVM IR最適化後 - IntegerBox特化
define i64 @add(i64 %a, i64 %b) {
    %1 = add i64 %a, %b
    ret i64 %1
}

🚀 期待される効果

  1. 実行速度: 2-3倍高速化
  2. メモリ使用量: 脱箱化で50%削減
  3. バイナリサイズ: 最適化で30%削減
  4. ビルド時間: Cranelift比で50%削減