# 機能設計書：llvm-extract

## 1. 機能概要

### 1.1 機能名
llvm-extract - LLVMモジュールから特定の関数/グローバル変数を抽出するツール

### 1.2 機能説明
llvm-extractは、LLVMモジュールから指定した関数、グローバル変数、エイリアス、基本ブロックを抽出して新しいモジュールを作成するユーティリティです。主に変換のデバッグに使用され、モジュールを特定の要素のみを含む最小限の形式に変換します。

### 1.3 関連する画面/API
- CLI（コマンドラインインターフェース）
- 入力：.bcファイル（ビットコード）または.llファイル（LLVM IR）
- 出力：抽出されたモジュールファイル

---

## 2. 入出力設計

### 2.1 入力
| 項目 | 型 | 必須 | 説明 |
|------|-----|------|------|
| input file | ファイルパス | No | 入力ビットコードファイル（デフォルト: 標準入力 "-"） |
| -func | 文字列 | No | 抽出する関数名 |
| -rfunc | 正規表現 | No | 抽出する関数名（正規表現） |
| -glob | 文字列 | No | 抽出するグローバル変数名 |
| -rglob | 正規表現 | No | 抽出するグローバル変数名（正規表現） |
| -alias | 文字列 | No | 抽出するエイリアス名 |
| -ralias | 正規表現 | No | 抽出するエイリアス名（正規表現） |
| -bb | function:bb | No | 抽出する基本ブロック |

### 2.2 出力
| 項目 | 型 | 説明 |
|------|-----|------|
| output file | ファイル | 抽出されたビットコードまたはアセンブリ |
| exit code | 整数 | 0: 成功、1: エラー |

### 2.3 コマンドラインオプション
| オプション | 説明 |
|-----------|------|
| -o | 出力ファイル名を指定（デフォルト: 標準出力 "-"） |
| -f | ターミナルへのバイナリ出力を許可 |
| -S | LLVM IRアセンブリとして出力 |
| -delete | 指定されたグローバル値をモジュールから削除 |
| -keep-const-init | 定数の初期化子を保持 |
| -recursive | 呼び出されるすべての関数を再帰的に抽出 |

---

## 3. 処理フロー

### 3.1 基本フロー

```
[開始]
   │
   ▼
[コマンドライン引数解析]
   │
   ▼
[入力モジュール読み込み] ←─── getLazyIRFileModule()
   │
   ▼
[抽出対象のグローバル値収集]
   │
   ├─► エイリアス収集 (-alias, -ralias)
   │
   ├─► グローバル変数収集 (-glob, -rglob)
   │
   ├─► 関数収集 (-func, -rfunc)
   │
   └─► 基本ブロック収集 (-bb)
   │
   ▼
[再帰抽出処理（-recursive）]
   │
   ▼
[グローバル値のマテリアライズ]
   │
   ▼
[ExtractGVPass実行]
   │
   ▼
[基本ブロック抽出（-bb指定時）]
   │
   ▼
[クリーンアップパス実行]
   │
   ▼
[出力ファイル書き込み]
   │
   ▼
[終了]
```

### 3.2 グローバル値収集処理

```
グローバル値収集
   │
   ├─► 名前指定 (-func, -glob, -alias)
   │         │
   │         ▼
   │    [M->getFunction() / getNamedGlobal() / getNamedAlias()]
   │         │
   │         ├─► 見つかった → GVsに追加
   │         │
   │         └─► 見つからない → エラー終了
   │
   └─► 正規表現指定 (-rfunc, -rglob, -ralias)
             │
             ▼
        [Regex構築・検証]
             │
             ▼
        [モジュール内のすべての対象をイテレート]
             │
             ├─► マッチ → GVsに追加
             │
             └─► マッチなし → エラー終了
```

### 3.3 再帰抽出処理

```
-recursive処理
   │
   ▼
[ワークキューに関数を追加]
   │
   ▼
[while キューが空でない]
   │
   ├─► 関数をマテリアライズ
   │
   ├─► 全基本ブロックを走査
   │
   ├─► 全命令を走査
   │
   └─► CallBase命令を検出
         │
         ▼
   [呼び出し先関数を取得]
         │
         ├─► 宣言のみ → スキップ
         │
         ├─► 既に追加済み → スキップ
         │
         └─► 新規 → GVsに追加、キューに追加
```

---

## 4. データ構造

### 4.1 主要なデータ構造

```cpp
// 抽出対象のグローバル値セット（重複排除）
SetVector<GlobalValue *> GVs;

// 基本ブロックマッピング（関数→基本ブロック名リスト）
SmallVector<std::pair<Function *, SmallVector<StringRef, 16>>, 2> BBMap;

// 基本ブロックグループ
std::vector<std::vector<BasicBlock *>> GroupOfBBs;
```

### 4.2 正規表現マッチング
```cpp
Regex RegEx(PatternString);
if (!RegEx.isValid(Error)) { /* エラー処理 */ }
for (auto &GV : M->globals()) {
    if (RegEx.match(GV.getName())) {
        GVs.insert(&GV);
    }
}
```

---

## 5. パス構成

### 5.1 抽出パス
```cpp
PM.addPass(ExtractGVPass(Gvs, DeleteFn, KeepConstInit));
```
- `Gvs`: 抽出/削除対象のグローバル値リスト
- `DeleteFn`: trueなら指定グローバル値を削除、falseなら抽出
- `KeepConstInit`: 定数の初期化子を保持

### 5.2 基本ブロック抽出パス
```cpp
PM.addPass(BlockExtractorPass(std::move(GroupOfBBs), true));
```

### 5.3 クリーンアップパス
```cpp
PM.addPass(GlobalDCEPass());           // 到達不能グローバル削除
PM.addPass(StripDeadDebugInfoPass());  // 不要デバッグ情報削除
PM.addPass(StripDeadPrototypesPass()); // 不要プロトタイプ削除
PM.addPass(StripDeadCGProfilePass());  // 不要CGプロファイル削除
```

---

## 6. エラーハンドリング

### 6.1 エラーケース
| エラー | 原因 | 対応 |
|--------|------|------|
| 入力ファイル読み込み失敗 | 不正なIRファイル | エラーメッセージ出力、終了コード1 |
| 関数未検出 | 指定関数がモジュールに存在しない | エラーメッセージ出力、終了コード1 |
| グローバル変数未検出 | 指定グローバル変数が存在しない | エラーメッセージ出力、終了コード1 |
| エイリアス未検出 | 指定エイリアスが存在しない | エラーメッセージ出力、終了コード1 |
| 基本ブロック未検出 | 指定基本ブロックが存在しない | エラーメッセージ出力、終了コード1 |
| 不正な正規表現 | 正規表現構文エラー | エラーメッセージ出力 |
| 出力ファイルオープン失敗 | パーミッション等 | エラーメッセージ出力、終了コード1 |

### 6.2 ExitOnError
```cpp
ExitOnError ExitOnErr(std::string(*argv) + ": error reading input: ");
ExitOnErr(F->materialize());  // マテリアライズ失敗時に自動終了
```

---

## 7. 技術仕様

### 7.1 遅延ロード
- `getLazyIRFileModule()`を使用して必要な部分のみロード
- 選択されたグローバル値のみマテリアライズ

### 7.2 マテリアライズ処理
```cpp
// 抽出モード: 指定されたGVをマテリアライズ
for (size_t i = 0, e = GVs.size(); i != e; ++i)
    Materialize(*GVs[i]);

// 削除モード: 指定されたGV以外をマテリアライズ
SmallPtrSet<GlobalValue *, 8> GVSet(llvm::from_range, GVs);
for (auto &F : *M) {
    if (!GVSet.count(&F))
        Materialize(F);
}
```

### 7.3 基本ブロック名指定
- セミコロン区切りで複数指定可能
- 無名基本ブロックは`%`プレフィックスで指定
- 例: `--bb=f:bb1;bb2`, `--bb=f:%1`

---

## 8. 制約事項

### 8.1 入力制約
- 有効なLLVM IRまたはビットコードファイルが必要
- 指定された要素がモジュールに存在する必要がある

### 8.2 処理制約
- 正規表現マッチは少なくとも1つの要素にマッチする必要がある
- 削除モード時はGlobalDCEパスは実行されない

### 8.3 基本ブロック抽出の制約
- 複数基本ブロック指定時、最初のブロックが他のブロックを支配する必要がある

---

## 9. 非機能要件

### 9.1 パフォーマンス
- 遅延ロードによるメモリ効率化
- 必要なグローバル値のみマテリアライズ

### 9.2 互換性
- LLVM IRとビットコード両方に対応
- 正規表現による柔軟な選択

---

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

### 10.1 エントリーポイント
- **ファイル**: `llvm/tools/llvm-extract/llvm-extract.cpp`
- **関数**: `main()` (132-426行目)

### 10.2 重要な関数・セクション
| 処理 | 行番号 | 説明 |
|--------|--------|------|
| main() | 132-426 | エントリーポイント |
| エイリアス収集 | 151-183 | -alias, -raliasの処理 |
| グローバル変数収集 | 185-216 | -glob, -rglobの処理 |
| 関数収集 | 218-250 | -func, -rfuncの処理 |
| 基本ブロック収集 | 252-269 | -bbの処理 |
| 再帰抽出 | 274-299 | -recursiveの処理 |
| マテリアライズ | 301-314 | グローバル値のマテリアライズ |
| ExtractGVPass | 316-339 | グローバル値抽出パス実行 |
| 基本ブロック抽出 | 341-381 | BlockExtractorPass実行 |
| クリーンアップ | 383-420 | 各種クリーンアップパス実行 |

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

```
main()
├── cl::ParseCommandLineOptions()           [137行目]
├── getLazyIRFileModule()                   [141行目]
├── [グローバル値収集]
│   ├── M->getNamedAlias()                  [153行目]
│   ├── Regex マッチング (エイリアス)        [162-183行目]
│   ├── M->getNamedGlobal()                 [187行目]
│   ├── Regex マッチング (グローバル)        [197-216行目]
│   ├── M->getFunction()                    [220行目]
│   └── Regex マッチング (関数)             [229-250行目]
├── [基本ブロック収集]                       [253-269行目]
├── [-recursive処理]                        [274-299行目]
│   ├── F->materialize()                    [284行目]
│   └── CB->getCalledFunction()             [290行目]
├── [マテリアライズ]
│   ├── GV.materialize()                    [301行目]
│   └── SmallPtrSet 判定                    [309行目]
├── [ExtractGVPass]
│   ├── PassBuilder 初期化                   [323-329行目]
│   ├── ExtractGVPass()                     [332行目]
│   └── M->materializeAll()                 [338行目]
├── [BlockExtractorPass]（-bb指定時）        [343-381行目]
│   └── BlockExtractorPass()                [379行目]
└── [クリーンアップ]
    ├── GlobalDCEPass()                     [401行目]
    ├── StripDeadDebugInfoPass()            [402行目]
    ├── StripDeadPrototypesPass()           [403行目]
    ├── StripDeadCGProfilePass()            [404行目]
    ├── PrintModulePass() / BitcodeWriterPass() [413-418行目]
    └── PM.run()                            [420行目]
```

### 10.4 データフロー図

```
入力ファイル (.bc/.ll)
         │
         ▼
    ┌─────────────────────┐
    │ getLazyIRFileModule │ ← 遅延ロード
    └─────────────────────┘
         │
         ▼ Module (遅延)
    ┌─────────────────────┐
    │ グローバル値収集     │
    │                     │
    │ ├─ -alias/-ralias   │
    │ ├─ -glob/-rglob     │
    │ ├─ -func/-rfunc     │
    │ └─ -bb              │
    └─────────────────────┘
         │
         ▼ SetVector<GlobalValue*>
    ┌─────────────────────┐
    │ -recursive処理      │ ← 呼び出し先関数を追加
    │ (CallBase走査)      │
    └─────────────────────┘
         │
         ▼
    ┌─────────────────────┐
    │ マテリアライズ       │
    │ GV.materialize()    │
    └─────────────────────┘
         │
         ▼
    ┌─────────────────────┐
    │ ExtractGVPass       │ ← グローバル値抽出/削除
    └─────────────────────┘
         │
         ▼
    ┌─────────────────────┐
    │ BlockExtractorPass  │ ← 基本ブロック抽出（オプション）
    └─────────────────────┘
         │
         ▼
    ┌─────────────────────┐
    │ クリーンアップパス   │
    │ ├─ GlobalDCEPass    │
    │ ├─ StripDeadDebugInfo│
    │ ├─ StripDeadPrototypes│
    │ └─ StripDeadCGProfile│
    └─────────────────────┘
         │
         ▼
    ┌─────────────────────┐
    │ PrintModulePass     │ ← -S指定時
    │ BitcodeWriterPass   │ ← バイナリ出力
    └─────────────────────┘
         │
         ▼
      出力ファイル
```

### 10.5 関連ファイル一覧

| ファイルパス | 役割 |
|-------------|------|
| llvm/tools/llvm-extract/llvm-extract.cpp | メインソースファイル（427行） |
| llvm/include/llvm/Transforms/IPO/ExtractGV.h | ExtractGVPass定義 |
| llvm/include/llvm/Transforms/IPO/BlockExtractor.h | BlockExtractorPass定義 |
| llvm/include/llvm/Transforms/IPO/GlobalDCE.h | GlobalDCEPass定義 |
| llvm/include/llvm/Transforms/IPO/StripDeadPrototypes.h | StripDeadPrototypesPass定義 |
| llvm/include/llvm/Transforms/IPO/StripSymbols.h | StripDeadDebugInfoPass定義 |
| llvm/include/llvm/Bitcode/BitcodeWriterPass.h | BitcodeWriterPass定義 |
| llvm/include/llvm/IRReader/IRReader.h | IR読み込みAPI |
| llvm/include/llvm/Support/Regex.h | 正規表現サポート |

---

## 11. 使用例

### 11.1 関数の抽出
```bash
llvm-extract -func=main input.bc -o extracted.bc
```

### 11.2 複数関数の抽出
```bash
llvm-extract -func=foo -func=bar input.bc -o extracted.bc
```

### 11.3 正規表現で関数を抽出
```bash
llvm-extract -rfunc='test.*' input.bc -o extracted.bc
```

### 11.4 グローバル変数の抽出
```bash
llvm-extract -glob=global_data input.bc -o extracted.bc
```

### 11.5 エイリアスの抽出
```bash
llvm-extract -alias=my_alias input.bc -o extracted.bc
```

### 11.6 基本ブロックの抽出
```bash
llvm-extract -bb=main:entry;loop input.bc -o extracted.bc
```

### 11.7 再帰的抽出
```bash
llvm-extract -func=main -recursive input.bc -o extracted.bc
```

### 11.8 指定要素の削除
```bash
llvm-extract -func=unused_func -delete input.bc -o cleaned.bc
```

### 11.9 アセンブリ出力
```bash
llvm-extract -func=main -S input.bc -o extracted.ll
```

---

## 12. 改訂履歴

| 版数 | 日付 | 変更内容 | 担当者 |
|------|------|----------|--------|
| 1.0 | 2026-02-01 | 初版作成 | llvm-extract機能設計書生成 |
