# 機能設計書 88-clang-offload-bundler

## 概要

本ドキュメントは、clang-offload-bundlerツールの機能設計について記述する。clang-offload-bundlerは、異なるターゲット向けの複数の入力ファイルを1つのファイルにバンドルしたり、バンドルされたファイルを複数のターゲット向けファイルにアンバンドルするツールである。

### 本機能の処理概要

clang-offload-bundlerは、CUDA、HIP、OpenMPなどのヘテロジニアス（異種混合）コンピューティング環境において、ホストコードとデバイスコードを1つのファイルにまとめる。これにより、複数のGPUアーキテクチャ向けのバイナリを統合的に管理できる。

**業務上の目的・背景**：GPUプログラミングでは、ホストCPU向けのコードと複数のGPUアーキテクチャ向けのコードが生成される。これらを別々に管理するのは煩雑であるため、1つのファイルにバンドルして配布・デプロイを簡素化する。

**機能の利用シーン**：
- CUDAアプリケーションのマルチアーキテクチャビルド
- HIPアプリケーションの複数GPU対応
- OpenMPオフロードコンパイル
- デバイスライブラリの配布

**主要な処理内容**：
1. 複数の入力ファイルをターゲット情報と共にバンドル
2. バンドルファイルを各ターゲット向けファイルにアンバンドル
3. バンドルIDの一覧表示
4. アーカイブファイルのアンバンドル

**関連システム・外部連携**：llvm-objcopy（バイナリ操作）、Clang Driver。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLIツール | 主画面 | コマンドライン実行 |

## 機能種別

バイナリ操作 / ヘテロジニアスコンパイル支援

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -input | string list | Yes* | 入力ファイル（複数可） | - |
| -output | string list | Yes | 出力ファイル（複数可） | - |
| -targets | string list | Yes | ターゲット指定（カンマ区切り） | offload-kind-triple形式 |
| -type | string | Yes | ファイルタイプ | i/ii/cui/hipi/d/ll/bc/s/o/a/gch/ast |
| -unbundle | bool | No | アンバンドルモード | - |
| -list | bool | No | バンドルID一覧表示 | - |
| -allow-missing-bundles | bool | No | 欠落バンドルで空ファイル作成 | - |
| -bundle-align | int | No | バイナリのアライメント（デフォルト: 1） | 正整数 |
| -check-input-archive | bool | No | アーカイブのTargetIDルール検証 | - |
| -hip-openmp-compatible | bool | No | HIPとOpenMPを互換扱い | - |
| -compress | bool | No | 出力を圧縮 | - |
| -compression-level | int | No | 圧縮レベル | - |
| -verbose | bool | No | デバッグ情報表示 | - |
| -### | bool | No | 外部コマンドを表示のみ | - |

*注: -listモードでは1つの入力ファイルが必須

### 入力データソース

- 入力ファイル（各ターゲット向けのオブジェクト/アセンブリ/LLVM IR等）
- バンドルファイル（アンバンドル時）

### サポートするファイルタイプ

| タイプ | 説明 |
|-------|------|
| i | cpp-output（プリプロセス済みC） |
| ii | c++-cpp-output（プリプロセス済みC++） |
| cui | cuda-cpp-output |
| hipi | hip-cpp-output |
| d | dependency（依存関係） |
| ll | llvm（テキストIR） |
| bc | llvm-bc（バイナリIR） |
| s | assembler（アセンブリ） |
| o | object（オブジェクトファイル） |
| a | archive（アーカイブ、アンバンドル専用） |
| gch | precompiled-header |
| ast | clang AST file |

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| バンドルファイル | file | バンドルモード時の出力 |
| アンバンドルファイル | file list | アンバンドルモード時の出力 |
| バンドルID一覧 | stdout | -listモード時 |

### 出力先

- 指定されたファイルパス
- 標準出力（-listモード時）

## 処理フロー

### 処理シーケンス

```
1. コマンドライン解析
   └─ cl::ParseCommandLineOptions

2. 設定値の収集
   └─ OffloadBundlerConfigに設定を格納

3. llvm-objcopyの検索
   └─ sys::findProgramByName

4. 入出力ファイルの検証
   └─ -inputs/-inputの排他チェック
   └─ -outputs/-outputの排他チェック

5. モード判定
   └─ -list: バンドルID一覧表示
   └─ -unbundle: アンバンドルモード
   └─ その他: バンドルモード

6. ターゲットの検証
   └─ offload-kind-triple形式チェック
   └─ ホストターゲットの確認
   └─ TargetID競合チェック

7. 処理実行
   └─ Bundler.BundleFiles() または
   └─ Bundler.UnbundleFiles() または
   └─ Bundler.UnbundleArchive()
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[コマンドライン解析]
    B --> C[OffloadBundlerConfig設定]
    C --> D[llvm-objcopy検索]
    D --> E{見つかった?}
    E -->|No| F[エラー終了]
    E -->|Yes| G[入出力ファイル検証]
    G --> H{検証OK?}
    H -->|No| F
    H -->|Yes| I{-list?}
    I -->|Yes| J[ListBundleIDsInFile]
    J --> Z[終了]
    I -->|No| K[ターゲット検証]
    K --> L{検証OK?}
    L -->|No| F
    L -->|Yes| M{-unbundle?}
    M -->|Yes| N{type=a?}
    N -->|Yes| O[UnbundleArchive]
    N -->|No| P[UnbundleFiles]
    M -->|No| Q{type=a?}
    Q -->|Yes| F
    Q -->|No| R[BundleFiles]
    O --> Z
    P --> Z
    R --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | ホストターゲット必須 | バンドル時はホストターゲットが1つ必須 | バンドルモード（HIPのみの場合を除く） |
| BR-02 | 入出力数一致 | バンドル時は入力数=ターゲット数、アンバンドル時は出力数=ターゲット数 | 常時 |
| BR-03 | アーカイブ制限 | アーカイブ(-type=a)はアンバンドル専用 | 常時 |
| BR-04 | ターゲット形式 | `<offload kind>-<target triple>[-<target id>]`形式 | 常時 |
| BR-05 | TargetID競合禁止 | 同一offload-kind-tripleで競合するTargetIDは不可 | 常時 |
| BR-06 | -listモード制限 | 1入力、出力なし、ターゲットなし | -listモード |

### オフロード種別

| 種別 | 説明 |
|------|------|
| host | ホストCPU向け |
| openmp | OpenMPオフロード |
| hip | HIP (ROCm) |
| hipv4 | HIP version 4 |
| cuda | CUDA |

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | 設定エラー | llvm-objcopyが見つからない | PATHを確認 |
| 1 | 入力エラー | -inputsと-input両方指定 | 一方のみ使用 |
| 1 | 入力エラー | -unbundleと-list両方指定 | 一方のみ使用 |
| 1 | 検証エラー | ターゲット形式が不正 | 形式を確認 |
| 1 | 検証エラー | ホストターゲット数が不正 | 1つのホストを指定 |
| 1 | 検証エラー | TargetIDが競合 | 競合を解消 |

### リトライ仕様

リトライは行わない。

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

該当なし。

## パフォーマンス要件

- 圧縮オプションでファイルサイズを削減可能
- -compression-levelで圧縮率を調整可能

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

- llvm-objcopyの外部プロセス実行
- ファイルの読み書き権限

## 備考

- -inputsと-outputsは非推奨（-inputと-outputを使用）
- HIPのみの場合はホストターゲットなしでも可
- -hip-openmp-compatibleでHIPとOpenMPを互換扱い可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ClangOffloadBundler.cpp | `clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp` | main関数と全体フロー |

**主要処理フロー**:
1. **63-163行目**: コマンドライン引数定義とパース
2. **169-195行目**: OffloadBundlerConfigへの設定値格納
3. **220-230行目**: llvm-objcopyの検索
4. **232-262行目**: 入出力ファイルの検証と非推奨オプション処理
5. **264-287行目**: -listモードの処理
6. **289-340行目**: バンドル/アンバンドル条件チェック
7. **342-424行目**: ターゲット検証とTargetID処理
8. **426-433行目**: バンドル/アンバンドル実行

#### Step 2: オプション定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ClangOffloadBundler.cpp | `clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp` | cl::opt定義 |

**主要オプション**:
- **71-76行目**: -input オプション
- **81-86行目**: -output オプション
- **91-94行目**: -targets オプション
- **95-111行目**: -type オプション（サポートタイプ一覧）
- **112-147行目**: 各種フラグオプション

#### Step 3: ターゲット検証を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ClangOffloadBundler.cpp | `clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp` | ターゲット検証ループ |

**主要処理フロー**:
- **342-396行目**: ターゲット検証ループ
- **352-365行目**: ターゲット形式チェック
- **367-382行目**: OffloadTargetInfoでの検証
- **384-395行目**: TargetID収集とホストカウント
- **400-410行目**: TargetID競合チェック

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

```
main (ClangOffloadBundler.cpp:63)
    │
    ├─ cl::ParseCommandLineOptions
    │
    ├─ sys::findProgramByName("llvm-objcopy")
    │
    ├─ OffloadBundlerConfig設定
    │
    ├─ 入出力ファイル検証
    │
    ├─ -listモード
    │      └─ OffloadBundler::ListBundleIDsInFile
    │
    ├─ ターゲット検証ループ
    │      │
    │      ├─ checkOffloadBundleID
    │      │
    │      ├─ OffloadTargetInfo
    │      │      ├─ isOffloadKindValid
    │      │      └─ isTripleValid
    │      │
    │      └─ getConflictTargetIDCombination
    │
    └─ OffloadBundler
           │
           ├─ BundleFiles (バンドルモード)
           │
           ├─ UnbundleFiles (アンバンドルモード)
           │
           └─ UnbundleArchive (アーカイブアンバンドル)
```

### データフロー図

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

-input file1 ───────────┐
                        │
-input file2 ───────────┼─▶ OffloadBundlerConfig
                        │            │
-targets target1,... ───┤            ▼
                        │    ターゲット検証
-type <type> ───────────┤            │
                        │            ▼
-unbundle / -list ──────┘   OffloadBundler
                                     │
                    ┌────────────────┼────────────────┐
                    │                │                │
                    ▼                ▼                ▼
             BundleFiles      UnbundleFiles    ListBundleIDsInFile
                    │                │                │
                    ▼                ▼                ▼
            バンドルファイル   各ターゲット       バンドルID
              (-output)       ファイル群           一覧
                             (-output複数)       (stdout)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ClangOffloadBundler.cpp | `clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp` | ソース | mainエントリーポイント |
| OffloadBundler.h | `clang/include/clang/Driver/OffloadBundler.h` | ヘッダ | OffloadBundler API |
| OffloadBundler.cpp | `clang/lib/Driver/OffloadBundler.cpp` | ソース | バンドル/アンバンドル実装 |
| TargetID.h | `clang/include/clang/Basic/TargetID.h` | ヘッダ | TargetID関連 |
| Cuda.h | `clang/include/clang/Basic/Cuda.h` | ヘッダ | CUDA関連定義 |
