Files
hakorune/docs/development/runtime/NUMERIC_ABI.md
nyash-codex 864a94d013 feat(phase-21.8+25): Complete imports resolution + Ring0/Ring1 numeric ABI design
Phase 21.8 完了 (imports resolution):
-  using nyash.core.numeric.matrix_i64 as MatI64 完全対応
-  hakorune_emit_mir.sh で imports 抽出・MirBuilder に配線
-  MatI64/IntArrayCore の静的参照解決が安定動作
-  matmul_core ベンチ MIR 生成成功 (VM/LLVM 両対応)

Phase 25 設計完了 (Ring0/Ring1 + numeric ABI):
- 🎯 Ring0/Ring1 責務分離を明文化 (Rust Freeze Policy 具体化)
- 🎯 Call/ExternCall 明確な分離設計
  - Call: Ring1 Hako 関数 (numeric core 等)
  - ExternCall: Ring0 intrinsic (rt_mem_* 等の FFI のみ)
- 🎯 BoxCall → Call 変換方針確定 (AotPrep で実施)
- 🎯 MatI64.mul_naive を NyNumericMatI64.mul_naive に分離
  (System Hakorune subset で完全実装済み)

実装:
-  AotPrepNumericCoreBox 診断パス実装 (NYASH_AOT_NUMERIC_CORE=1)
-  numeric ABI ドキュメント整備 (NUMERIC_ABI.md)
-  System Hakorune subset 定義 (system-hakorune-subset.md)
-  IntArrayCore/MatI64 仕様固定 (lang/src/runtime/numeric/README.md)
-  ENV_VARS.md に NYASH_AOT_NUMERIC_CORE トグル追記

今後のタスク:
- BoxCall(MatI64) → Call(NyNumericMatI64) 変換実装 (opt-in)
- IntArrayCore の numeric core 整備
- matmul_core スモークテスト (NYASH_AOT_NUMERIC_CORE=0/1 両対応)

🎉 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 20:19:00 +09:00

7.5 KiB
Raw Blame History

Numeric ABI (IntArrayCore / MatI64) — Design Stage

Status: design-stage; Phase 25 scope; no behaviour change yet.

Purpose

  • Define a minimal, stable numeric ABI for IntArrayCore / MatI64 that:
    • 実装としては Ring1 Hakorune の通常関数(Call)として表現でき、
    • 必要に応じて Ring0 Rust / C 側からも同じシグネチャで呼び出せる(将来の FFI/ExternCall 連携の基礎になる)。
  • Keep all box-specific knowledge in Ring1:
    • Box/Handle/Core の構造ptr/len/rows/cols/stride 等)。
    • 行列積などの数値アルゴリズム本体。
    • 境界チェックと FailFast ポリシー。
  • Allow Ring0/LLVM to treat numeric calls as:
    • 通常の関数呼び出し(Call @ny_numeric_*)として扱えるようにし、
    • 必要な場合のみ、既存の ExternCall/FFI 構造の上に同じ関数群を載せ替えられるようにするPhase 25 では必須ではない)。

Related docs:

  • Phase 25 roadmap: docs/development/roadmap/phases/phase-25/README.md
  • Ring1 numeric runtime layout: lang/src/runtime/numeric/README.md
  • System Hakorune subset (runtime/numeric 用記法): docs/development/runtime/system-hakorune-subset.md

Conventions

  • Types / encoding
    • Numeric ABI 関数のシグネチャは i64 と Handle実体は i64×N のみを使う。
    • IntArrayHandle / MatI64Handle は「i64×N の値」として表現される:
      • C 側イメージ(概念):
        • typedef struct { int64_t *ptr; int64_t len; } ny_intarray_handle;
        • typedef struct { int64_t *ptr; int64_t rows; int64_t cols; int64_t stride; } ny_mat_i64_handle;
      • MIR では「複数の i64 をまとめた値」として Call の引数/戻り値に現れる。
  • 命名
    • Ring1/Hakorune 側では、ny_numeric_intarray_* / ny_numeric_mat_i64_* 系の関数名(またはそれに相当するモジュール+メソッド名)で実装する。
    • C/Rust 側から直接呼びたい場合は、同じ名前でシンボルをエクスポートする(必要になったタイミングで ExternCall に載せ替え可能)。
  • FailFast
    • numeric ABI では、事前条件違反(負の長さ、境界外 index、dims 不整合)は すべてバグ扱い とし、FailFast で扱う。
    • 「エラーコードを返して上層で if」するスタイルは禁止AGENTS.md の対処療法禁止に準拠)。

ABI Surface — IntArrayCore (i64 1D)

Conceptual handle:

  • IntArrayHandle: 実体は「ptr: i64 + len: i64」等で構成される Core 構造体を指す値。
  • Box レベル仕様は lang/src/runtime/numeric/README.md の IntArrayCore セクションを参照。

Functions (proposal; Phase 25 scope):

  • ny_numeric_intarray_new(len: i64) -> IntArrayHandle

    • Allocate zero-initialized buffer of length len.
    • Preconditions:
      • len >= 0
      • len が i64 範囲内であり、len * sizeof(i64) の計算がオーバーフローしない。
    • Failure:
      • OOM / 明らかな誤りは FailFast戻り値でのエラー表現は行わない
  • ny_numeric_intarray_free(a: IntArrayHandle)

    • Free underlying Core.
    • Double-free / invalid handle は未定義動作とし、所有権設計Ring1 側)で防ぐ。
  • ny_numeric_intarray_len(a: IntArrayHandle) -> i64

    • Return current logical length.
    • Used mainly for assertions / diagnostics;通常は Box 側で長さを保持しない方向に寄せる。
  • ny_numeric_intarray_get(a: IntArrayHandle, idx: i64) -> i64

    • Load a[idx].
    • Preconditions:
      • 0 <= idx < len(a).
    • Failure:
      • Precondition violated → FailFast例外 or プロセス終了; 実際の実装は後続フェーズで決定)。
  • ny_numeric_intarray_set(a: IntArrayHandle, idx: i64, v: i64)

    • Store v into a[idx].
    • Preconditions:
      • 0 <= idx < len(a).
    • Failure:
      • Precondition violated → FailFast。

Mapping to MIRPhase 25 の基本方針):

  • BoxCall: BoxCall(IntArrayCore, "get_unchecked", [arr, idx])
    • AotPrep: 数値コア関数への通常 Call に書き換え(例: Call NyNumericIntArray.get(arr_handle, idx))。
    • LLVM/VM: どちらも同じ Call を実行するだけで numeric ABI に到達する。

ABI Surface — MatI64 (i64 2D matrix)

Conceptual handle:

  • MatI64Handle: 「ptr, rows, cols, stride」を持つ Core 構造を指す値。
  • Box レベル仕様は lang/src/runtime/numeric/README.md の MatI64 セクションを参照。

Functions (proposal; Phase 25 scope):

  • ny_numeric_mat_i64_new(rows: i64, cols: i64) -> MatI64Handle

    • Allocate zero-initialized rows x cols matrix, rowmajor。
    • Preconditions:
      • rows >= 0, cols >= 0.
      • rows * cols が i64 範囲内であり、rows * cols * sizeof(i64) がオーバーフローしない。
  • ny_numeric_mat_i64_free(m: MatI64Handle)

    • Free underlying matrix Core所有権は Box 側で管理)。
  • ny_numeric_mat_i64_dims(m: MatI64Handle) -> (rows: i64, cols: i64)

    • Return matrix dimensions行数・列数
  • ny_numeric_mat_i64_get(m: MatI64Handle, row: i64, col: i64) -> i64

    • Load element at (row, col).
    • Preconditions:
      • 0 <= row < rows(m), 0 <= col < cols(m).
  • ny_numeric_mat_i64_set(m: MatI64Handle, row: i64, col: i64, v: i64)

    • Store v into (row, col).
    • Preconditions:
      • 同上。
  • ny_numeric_mat_i64_mul_naive(a: MatI64Handle, b: MatI64Handle, n: i64) -> MatI64Handle

    • Naive O(n³) matrix multiplication for n x n matrices.
    • Preconditions:
      • rows(a) == cols(a) == rows(b) == cols(b) == n.
      • n >= 0
    • Failure:
      • 上記条件を満たさない場合は FailFast。ベンチマークバグを隠さない。

Mapping to MIRPhase 25 の基本方針):

  • BoxCall: BoxCall(MatI64, "mul_naive", [a, b])
    • AotPrep: Call NyNumericMatI64.mul_naive(a_handle, b_handle, n) のような numeric core 関数呼び出しに書き換え。
    • LLVM/VM: どちらも同じ Call を実行するだけで numeric ABI に到達する。

BoxCall / Call / ExternCall の役割分担

  • Initial MIR:
    • BoxCall(MatI64, "new", [rows, cols])
    • BoxCall(MatI64, "mul_naive", [a, b])
  • AotPrep (Ring1):
    • これらを numeric core 関数への Call に変換するBoxCall を LLVM まで持ち込まない)。
    • Box 名やメソッド名ベースの一時的 if ではなく、「Box 型ID + メソッドID → numeric core 関数 ID」テーブル化を目指す。
  • Ring0 / LLVM:
    • Call @ny_numeric_* を普通の関数呼び出しとして扱う。
    • 低レベルのメモリアクセスや OS 連携が必要な場合のみ、既存の ExternCall(例: rt_mem_alloc_i64を使う。numeric ABI 自体は必須では ExternCall に依存しない。

Relation to other docs

  • Phase 25 roadmap:
    • Numeric ABI の設計方針Ring0/Ring1 分離、Call/ExternCall のみ、FailFastを高レベルで説明。
    • このファイルは、そのうち IntArrayCore / MatI64 に関わる ABI 面のみを詳細化する。
  • lang/src/runtime/numeric/README.md:
    • IntArrayCore / MatI64 の Box レベル API(フィールド・メソッド契約)を定義。
    • Numeric ABI はその下で動く「Core/Handle レベル」の境界として扱う。
  • docs/development/runtime/system-hakorune-subset.md:
    • Numeric ABI の実装を記述する際に使う Hakorune 言語機能の subset を規定。
    • ループ/FailFast/Box/Handle パターンなど、実装スタイルを制約する。