# 機能設計書 24-バイナリダンパ

## 概要

本ドキュメントは、mrubyにおけるバイナリダンパ機能の設計を記述する。irepをmrubyバイナリ形式（.mrb）にシリアライズして出力する。

### 本機能の処理概要

バイナリダンパは、コンパイラで生成されたirep（命令列表現）をRite Binary Formatにシリアライズし、メモリバッファまたはファイルに出力する機能である。IREPセクション、デバッグセクション、ローカル変数セクションを順次書き出す。

**業務上の目的・背景**：mrubyのコンパイル結果をバイナリ形式で保存することで、次回実行時にソースコードの再コンパイルを省略できる。また、C関数としてバイナリを埋め込む形式（cfunc形式）での出力もサポートし、組み込みシステムへの統合を容易にする。

**機能の利用シーン**：mrbcコマンドでの.mrbファイル生成、C関数形式での出力（mrb_dump_irep_cfunc）、プログラムからのバイナリ保存。

**主要な処理内容**：
1. IREPセクションの書き出し（ヘッダ、命令列、プール、シンボル）
2. デバッグセクションの書き出し（ファイル名テーブル、行番号情報）
3. ローカル変数セクションの書き出し
4. バイナリヘッダとフッタの書き出し
5. メモリバッファへの出力（mrb_dump_irep）
6. ファイルへの出力（mrb_dump_irep_binary）
7. C関数形式での出力（mrb_dump_irep_cfunc）

**関連システム・外部連携**：コンパイラから生成されたirepを入力として受け取る。バイナリローダ（load.c）が読み込める形式で出力する。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はC APIおよびCLIツール経由で使用される |

## 機能種別

データ連携（irepのシリアライズ・出力）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| mrb | mrb_state* | Yes | mrubyインタプリタ状態 | NULLでないこと |
| irep | const mrb_irep* | Yes | ダンプ対象のirep | NULLでないこと |
| flags | uint8_t | Yes | ダンプフラグ | MRB_DUMP_DEBUG_INFO, MRB_DUMP_STATIC, MRB_DUMP_NO_LVAR |
| fp | FILE* | ファイル出力時Yes | 出力先ファイル | NULLでないこと |
| initname | const char* | cfunc時Yes | C配列名 | 空文字列でないこと |

### 入力データソース

- コンパイラから生成されたmrb_irep構造体

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| bin | uint8_t* | バイナリデータ（mrb_dump_irep） |
| bin_size | size_t | バイナリデータサイズ |
| result | int | 処理結果コード（MRB_DUMP_OK等） |

### 出力先

- メモリバッファ（呼び出し元がmrb_free()で解放）
- ファイル（FILE*経由）

## 処理フロー

### 処理シーケンス

```
1. サイズ計算フェーズ
   ├─ get_irep_record_size (再帰的にirep全体のサイズ計算)
   ├─ get_debug_record_size (デバッグセクションサイズ)
   ├─ get_filename_table_size (ファイル名テーブルサイズ)
   └─ get_lv_section_size (ローカル変数セクションサイズ)
2. メモリ確保
   └─ malloc_size = ヘッダ + IREPセクション + デバッグセクション + LVセクション + フッタ
3. 書き出しフェーズ
   ├─ write_section_irep
   │     └─ write_irep_record (再帰)
   │           ├─ write_irep_header
   │           ├─ write_iseq_block
   │           ├─ write_pool_block
   │           └─ write_syms_block
   ├─ write_section_debug (フラグ指定時)
   └─ write_section_lv (LV情報存在時)
4. ヘッダ・フッタ書き出し
   ├─ write_rite_binary_header
   └─ write_footer
```

### フローチャート

```mermaid
flowchart TD
    A[mrb_dump_irep呼び出し] --> B[サイズ計算]
    B --> C[メモリ確保]
    C --> D[write_section_irep]
    D --> E{DEBUG_INFO?}
    E -->|Yes| F[write_section_debug]
    E -->|No| G{LV定義あり?}
    F --> G
    G -->|Yes| H[write_section_lv]
    G -->|No| I[write_footer]
    H --> I
    I --> J[write_rite_binary_header]
    J --> K[完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | デバッグ情報出力 | MRB_DUMP_DEBUG_INFOフラグ設定時のみデバッグセクション出力 | flags確認 |
| BR-02 | LV情報出力 | MRB_DUMP_NO_LVARフラグ未設定かつLV定義ありの場合のみ出力 | flags確認 |
| BR-03 | INT64分岐 | 64bit整数がINT32範囲内ならINT32として出力 | プール書き出し時 |
| BR-04 | 浮動小数点LE | floatはIEEE754リトルエンディアンで出力 | dump_float |

### 計算ロジック

- バイナリサイズ = ヘッダ + IREPセクション + デバッグセクション + LVセクション + フッタ
- 全サイズはビッグエンディアンで格納

## データベース操作仕様

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| MRB_DUMP_INVALID_IREP | irep不正 | irepがNULL | 有効なirepを指定 |
| MRB_DUMP_INVALID_ARGUMENT | 引数不正 | mrb/fp/initnameがNULL | 有効な引数を指定 |
| MRB_DUMP_WRITE_FAULT | 書き込み失敗 | fwrite/fprintf失敗 | ディスク空き容量確認 |
| MRB_DUMP_GENERAL_FAILURE | 一般エラー | mrbがNULL | - |

### リトライ仕様

リトライは不要。エラー時はメモリ解放して終了。

## トランザクション仕様

エラー発生時はmallocされたバッファを解放し、*bin = NULLに設定する。

## パフォーマンス要件

- サイズ計算とデータ書き出しの2パス方式により、メモリ確保を1回で完了
- GCアリーナの保存・復帰でプール処理時のGC負荷を軽減

## セキュリティ考慮事項

- mrb_assert_int_fitによる整数オーバーフロー防止
- cfunc形式ではstatic修飾子の選択が可能（MRB_DUMP_STATICフラグ）

## 備考

- cfunc形式出力（mrb_dump_irep_cfunc）はuint8_t配列としてバイナリを出力する
- MRB_NO_STDIO定義時はファイル出力関数とcfunc出力関数は無効化される

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | dump.h | `include/mruby/dump.h` | rite_binary_header, rite_section_header等のバイナリフォーマット構造体 |

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | dump.c | `src/dump.c` | mrb_dump_irep（819-895行目）: メモリバッファへのダンプ |
| 2-2 | dump.c | `src/dump.c` | mrb_dump_irep_binary（913-932行目）: ファイルへのダンプ |
| 2-3 | dump.c | `src/dump.c` | mrb_dump_irep_cfunc（950-996行目）: C関数形式出力 |

**主要処理フロー**:
1. **819-895行目**: サイズ計算→メモリ確保→セクション書き出し→ヘッダ/フッタ書き出し

#### Step 3: 各セクション書き出し

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | dump.c | `src/dump.c` | write_irep_header（45-56行目）: irepヘッダ書き出し |
| 3-2 | dump.c | `src/dump.c` | write_iseq_block（82-95行目）: 命令列書き出し |
| 3-3 | dump.c | `src/dump.c` | write_pool_block（209-277行目）: プール書き出し |
| 3-4 | dump.c | `src/dump.c` | write_syms_block（316-340行目）: シンボル書き出し |

### プログラム呼び出し階層図

```
mrb_dump_irep (公開API)
    │
    ├─ get_irep_record_size (サイズ計算)
    ├─ get_filename_table_size (デバッグサイズ計算)
    ├─ get_debug_record_size
    ├─ create_lv_sym_table
    ├─ get_lv_section_size
    │
    ├─ write_section_irep
    │     └─ write_irep_record (再帰)
    │           ├─ write_irep_header
    │           ├─ write_iseq_block
    │           ├─ write_pool_block
    │           └─ write_syms_block
    │
    ├─ write_section_debug
    │     └─ write_debug_record (再帰)
    │
    ├─ write_section_lv
    │     ├─ write_lv_sym_table
    │     └─ write_lv_record (再帰)
    │
    ├─ write_footer
    └─ write_rite_binary_header
```

### データフロー図

```
[入力]                     [処理]                         [出力]

mrb_irep*           ───▶ サイズ計算            ───▶ malloc_size
                           │
                      ───▶ write_section_irep   ───▶ uint8_t[] (IREP)
                      ───▶ write_section_debug  ───▶ uint8_t[] (DBG)
                      ───▶ write_section_lv     ───▶ uint8_t[] (LVAR)
                      ───▶ write_footer         ───▶ uint8_t[] (END)
                      ───▶ write_binary_header  ───▶ uint8_t[] (RITE)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dump.c | `src/dump.c` | ソース | バイナリダンパの実装本体 |
| dump.h | `include/mruby/dump.h` | ヘッダ | バイナリフォーマット定義 |
| load.c | `src/load.c` | ソース | バイナリローダ（対となる入力機能） |
| irep.h | `include/mruby/irep.h` | ヘッダ | irep構造体定義 |
| debug.h | `include/mruby/debug.h` | ヘッダ | デバッグ情報構造体定義 |
| endian.h | `include/mruby/endian.h` | ヘッダ | エンディアン判定（float出力時） |
