# 機能設計書 25-llvm-dis

## 概要

本ドキュメントは、LLVM llvm-disの機能設計について記述する。llvm-disは、LLVMビットコード（.bc形式）からLLVM アセンブリ言語（.ll形式）への変換を行う逆アセンブラツールである。

### 本機能の処理概要

llvm-disは、バイナリのLLVMビットコード形式を人間可読なIRテキスト形式に変換するツールである。llvm-asと対になるツールとして、IRの検査・デバッグ・学習目的で使用される。

**業務上の目的・背景**：コンパイラの最適化過程やコード生成を理解・デバッグするために、バイナリ形式のIRを人間が読める形式に変換する必要がある。llvm-disはこの変換を行い、開発者がIRを直接確認できるようにする。

**機能の利用シーン**：
- コンパイラ最適化の結果確認
- バイナリビットコードのデバッグ
- IRの学習・教育
- 異なるLLVMバージョン間でのIR互換性確認
- ThinLTOインデックスの確認

**主要な処理内容**：
1. コマンドライン引数の解析
2. ビットコードファイル（.bc）の読み込み
3. ビットコードのデコードとモジュール構築
4. オプションに応じたアノテーション追加
5. テキストIR（.ll）の出力

**関連システム・外部連携**：llvm-as（逆変換）、opt（最適化）、clang（コンパイラフロントエンド）

**権限による制御**：特になし。ファイルアクセス権限はOSに依存。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はコマンドラインツールであり、画面は存在しない |

## 機能種別

データ変換ツール / 逆アセンブラ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| input file(s) | string[] | No | 入力.bcファイル（デフォルト: stdin） | ファイル存在確認 |
| -o | string | No | 出力ファイル名 | - |
| -f | flag | No | ターミナルへの出力を許可 | - |
| --show-annotations | flag | No | 情報コメントを追加 | - |
| --materialize-metadata | flag | No | メタデータのみマテリアライズ | - |
| --disable-output | flag | No | 出力を無効化 | - |
| --set-importing | flag | No | モジュールインポートモードを模擬 | - |
| --print-thinlto-index-only | flag | No | ThinLTOインデックスのみ出力 | - |
| --color | flag | No | カラー出力 | - |

### 入力データソース

- 標準入力または.bcファイル
- LLVMビットコード形式

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| .llファイル | text | LLVM IR テキスト形式 |
| アノテーション | text | 使用回数・型情報等（オプション） |

### 出力先

- 標準出力または指定されたファイル
- 入力が`x.bc`の場合、デフォルト出力は`x.ll`

## 処理フロー

### 処理シーケンス

```
1. 初期化
   └─ InitLLVMでLLVM初期化
   └─ コマンドライン引数解析

2. 入力ファイル処理（複数ファイル対応）
   └─ 各ファイルについて以下を実行

3. ビットコード読み込み
   └─ MemoryBuffer::getFileOrSTDIN()
   └─ getBitcodeFileContents()

4. モジュールマテリアライズ
   └─ getLazyModule()
   └─ materializeMetadata() または materializeAll()

5. ThinLTOインデックス取得（存在する場合）
   └─ getLTOInfo()
   └─ getSummary()

6. 出力ファイル名決定
   └─ 指定なしの場合は推論

7. IR出力
   └─ Module::print()（アノテーター付き）
   └─ Index::print()（存在する場合）
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[InitLLVM]
    B --> C[コマンドライン解析]
    C --> D[入力ファイルリスト取得]
    D --> E{ファイルあり?}
    E -->|No| F[stdin追加]
    F --> G[ファイルループ開始]
    E -->|Yes| G
    G --> H[LLVMContext作成]
    H --> I[MemoryBuffer読み込み]
    I --> J[getBitcodeFileContents]
    J --> K{複数モジュール?}
    K --> L[モジュールループ]
    L --> M{print-thinlto-only?}
    M -->|Yes| N[インデックスのみ処理]
    M -->|No| O[getLazyModule]
    O --> P{materialize-metadata?}
    P -->|Yes| Q[materializeMetadata]
    P -->|No| R[materializeAll]
    Q --> S[出力処理]
    R --> S
    N --> S
    S --> T[Module::print]
    T --> U[Index::print]
    U --> V{次のファイル?}
    V -->|Yes| G
    V -->|No| W[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 出力ファイル名推論 | 入力が`x.bc`の場合、出力は`x.ll` | -oオプション未指定時 |
| BR-002 | 複数入力制限 | 複数入力時は-oオプション使用不可 | 複数ファイル時 |
| BR-003 | マルチモジュール | 複数モジュールは`.0.ll`, `.1.ll`等で出力 | マルチモジュールbc時 |

### 計算ロジック

特になし。デコードと出力のみ。

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | File Error | 入力ファイル読み込み失敗 | ファイルパス確認 |
| 1 | Bitcode Error | ビットコードデコード失敗 | 有効なbcファイルか確認 |
| 1 | Output Error | 出力ファイル作成失敗 | パーミッション確認 |

### リトライ仕様

エラー時は終了コード1で終了。リトライは呼び出し元の責任。

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

該当なし（ファイル変換ツール）

## パフォーマンス要件

- マテリアライズはレイジーロードで最適化可能
- メタデータのみのマテリアライズオプションで高速化

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

- ファイル出力はOSの権限システムに従う
- 入力ビットコードの妥当性チェック

## 備考

- llvm-asと対になるツール（.ll → .bc変換）
- ThinLTOインデックスもサポート
- 複数入力ファイル対応

---

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

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

### 推奨読解順序

#### Step 1: メインソースを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | llvm-dis.cpp | `llvm/tools/llvm-dis/llvm-dis.cpp` | ツール全体の実装 |

**主要処理フロー**:
- **55-92行目**: コマンドラインオプション定義
- **94-100行目**: printDebugLoc() - デバッグ位置出力
- **102-145行目**: CommentWriter - アノテーション出力クラス
- **147-168行目**: LLVMDisDiagnosticHandler - 診断ハンドラ
- **173-280行目**: main()関数 - メイン処理フロー

**読解のコツ**: CommentWriterはAssemblyAnnotationWriterを継承し、--show-annotationsオプション時にIR出力にコメントを追加する。

#### Step 2: main関数の詳細を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | llvm-dis.cpp | `llvm/tools/llvm-dis/llvm-dis.cpp` | main関数の処理フロー |

**主要処理フロー**:
- **173-179行目**: 初期化とコマンドライン解析
- **181-187行目**: 入力ファイルの検証（複数入力時の-o制限）
- **189-277行目**: 各入力ファイルのループ処理
- **192-194行目**: LLVMContextと診断ハンドラ設定
- **196-202行目**: MemoryBuffer読み込み
- **204行目**: ビットコードファイル内容取得
- **211-223行目**: モジュールのマテリアライズ処理
- **225-228行目**: ThinLTOインデックス取得
- **230-249行目**: 出力ファイル名決定
- **264-272行目**: IR出力

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

```
main()
    │
    ├─ InitLLVM()
    │
    ├─ cl::ParseCommandLineOptions()
    │
    └─ for each InputFilename
           │
           ├─ LLVMContext()
           │
           ├─ MemoryBuffer::getFileOrSTDIN()
           │
           ├─ getBitcodeFileContents()
           │
           └─ for each BitcodeModule
                  │
                  ├─ getLazyModule()
                  │
                  ├─ materializeMetadata() または
                  │  materializeAll()
                  │
                  ├─ getSummary()（ThinLTO時）
                  │
                  └─ Module::print()
```

### データフロー図

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

.bcファイル/stdin ────────▶ MemoryBuffer
                                   │
                                   ▼
                           getBitcodeFileContents()
                                   │
                                   ▼
                           BitcodeModule[]
                                   │
                                   ▼
                           getLazyModule()
                                   │
                                   ▼
                           materializeAll()
                                   │
                                   ▼
                           Module*
                                   │
                                   ▼
                           Module::print() ──────────▶ .llファイル/stdout
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| llvm-dis.cpp | `llvm/tools/llvm-dis/llvm-dis.cpp` | ソース | メイン実装 |
| CMakeLists.txt | `llvm/tools/llvm-dis/CMakeLists.txt` | ビルド設定 | ビルドスクリプト |
| BitcodeReader.h | `llvm/include/llvm/Bitcode/BitcodeReader.h` | ヘッダ | ビットコード読み込みAPI |
| Module.h | `llvm/include/llvm/IR/Module.h` | ヘッダ | Module定義 |
| AssemblyAnnotationWriter.h | `llvm/include/llvm/IR/AssemblyAnnotationWriter.h` | ヘッダ | アノテーションAPI |
| LLVMContext.h | `llvm/include/llvm/IR/LLVMContext.h` | ヘッダ | Context定義 |
| ModuleSummaryIndex.h | `llvm/include/llvm/IR/ModuleSummaryIndex.h` | ヘッダ | ThinLTOインデックス |
