Files
hakorune/docs/reference/abi/ffi_calling_convention_min.md

67 lines
3.4 KiB
Markdown
Raw Normal View History

# Nyash FFI Calling Convention (Handle-First, TLV, v0)
目的: 10.5c の指針に沿って、JIT/AOT/VM 共通の最小・実用的な呼び出し規約を短文化。a0/a1/a2 は Handle-First を前提とし、戻りは TLV で統一。
## 要点TL;DR
- Handle-First: a0 は常に `nyash.handle.of(receiver)`i64。他の引数は TLV でエンコード。
- 引数TLV: String/Integer はプリミティブ化、それ以外は Handle(tag=8)。
- 戻りTLV: i64/f64/bool/string/bytes/handle をサポート。`returns_result` 指定時は Result 形状VMが尊重
- by-name 経路: 型名未確定時は `*_invoke_by_name_*` シムで実行時解決(任意、推奨)。
- Strict 原則: Strict 時は JIT 実行を停止VM=仕様の唯一の基準。AOT 生成のみ許可。
## シム関数(最小)
```c
// 受け手は a0i64: handleで指定。a1/a2 は任意引数のプレースホルダ。
extern "C" long long nyash_plugin_invoke3_i64(
long long type_id,
long long method_id,
long long argc, // 受け手を含む総数(>=1
long long a0, // receiver: nyash.handle.of(...)
long long a1,
long long a2
);
extern "C" double nyash_plugin_invoke3_f64(
long long type_id,
long long method_id,
long long argc,
long long a0,
long long a1,
long long a2
);
// by-name型名未確定時に利用可能最小シム
// 実装済み: getattr/call の i64系
extern "C" long long nyash_plugin_invoke_name_getattr_i64(long long argc, long long a0, long long a1, long long a2);
extern "C" long long nyash_plugin_invoke_name_call_i64(long long argc, long long a0, long long a1, long long a2);
```
## 引数の規約TLV
- a0 は常に受け手のハンドルi64。レシーバは TLV には含めず、直接 a0 から解決。
- a1/a2 は必要に応じて TLV バッファへ詰める最大2引数の最小シム。将来拡張で可変長
- エンコード方針VM/nyrt共通
- StringBox → TLV string(tag=6)
- IntegerBox → TLV i64(tag=3)
- BufferBox → TLV bytes(tag=7)nyrtシムが自動検出
- それ以外の Box → TLV handle(tag=8, payload: type_id:u32 + instance_id:u32)
- i64/f64/bool 等の即値 → 対応する TLV プリミティブ
## 戻り値の規約TLV
- 戻り TLV の先頭タグにより分岐し、必要ならネイティブへデコード:
- tag=3 → i64、tag=5 → f64`*_i64`/`*_f64` 経由)
- tag=6 → string、tag=7 → bytes
- tag=8 → handletype_id/instance_id を登録し BoxRef 構築)
- `returns_result` のメソッドは、VM で Ok/Err を Result に包むAOT も同等方針)。
## N引数サポート暫定
- `*_invoke3_*` は a1/a2 までの即値/ハンドルを直積み、3引数目以降はレガシーVM引数位置3..NからTLVに詰めることで対応開発向け
- ネイティブEXEAOTでのN引数の完全化は将来の `*_invokeN_*` で対応予定。
## Lowerer の前提Handle-First
- `emit_plugin_invoke(type_id, method_id, argc, has_ret)` を一本化。a0 は常に `nyash.handle.of(receiver)` を積む。
- 受け手箱名が未確定な場面は by-name シムを使用可(最適化は後段)。
## メモ
- TLV タグの例: 1=Bool, 3=I64, 5=F64, 6=String, 7=Bytes, 8=Handle。
- 既存詳細は `docs/papers/nyash-unified-lifecycle/technical-details.md` 参照。