# 機能設計書 89-clang-linker-wrapper

## 概要

本ドキュメントは、clang-linker-wrapperツールの機能設計について記述する。clang-linker-wrapperは、ホストリンカのラッパーとして動作し、オフロードコンパイルにおけるデバイスコードの抽出・リンク・ラッピングを行うツールである。

### 本機能の処理概要

clang-linker-wrapperは、リンカ入力ファイルから`.llvm.offloading`セクションに埋め込まれたデバイスオフロードコードを抽出し、デバイスリンクを実行してデバイスイメージを作成する。その後、ランタイム登録コードと共にオブジェクトファイルとしてラップし、ホストリンカに渡す。

**業務上の目的・背景**：OpenMP、CUDA、HIP、SYCLなどのオフロードプログラミングでは、コンパイル時に生成されたデバイスコードをリンク時に統合する必要がある。clang-linker-wrapperはこのプロセスを透過的に処理し、最終的な実行可能ファイルにデバイスイメージを埋め込む。

**機能の利用シーン**：
- OpenMPオフロードアプリケーションのリンク
- CUDA/HIPアプリケーションのリンク
- SYCLアプリケーションのリンク
- ヘテロジニアスコンピューティングの統合

**主要な処理内容**：
1. 入力ファイルからデバイスコードの抽出
2. ターゲットごとのデバイスリンク
3. fatbinary/hipfb形式へのバンドル
4. ランタイム登録コードでのラッピング
5. ホストリンカの実行

**関連システム・外部連携**：ホストリンカ、clang、fatbinary（CUDA）、clang-offload-bundler（AMDGPU）、clang-sycl-linker。

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

## 関連画面

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

## 機能種別

リンカラッパー / オフロードコード統合

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| --linker-path | string | Yes | ホストリンカのパス | - |
| --host-triple | string | No | ホストターゲットトリプル | - |
| -o | string | No | 出力ファイル名 | - |
| --cuda-path | string | No | CUDAインストールパス | - |
| --save-temps | bool | No | 一時ファイルを保存 | - |
| --dry-run | bool | No | コマンド表示のみ | - |
| --verbose | bool | No | 詳細出力 | - |
| --wrapper-jobs | string | No | 並列ジョブ数またはjobserver | - |
| --embed-bitcode | bool | No | ビットコードを埋め込み | - |
| --relocatable | bool | No | 再配置可能リンク | - |
| --override-image | string | No | オフロードイメージを上書き | - |
| --emit-fatbin-only | bool | No | fat binaryのみ出力 | - |
| --compress | bool | No | 出力を圧縮 | - |
| --Xoffload-linker | string | No | デバイスリンカへのオプション | - |
| --Xoffload-compiler | string | No | デバイスコンパイラへのオプション | - |

### 入力データソース

- オブジェクトファイル（.llvm.offloadingセクション含む）
- アーカイブファイル
- ライブラリ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 実行可能ファイル | file | デバイスイメージ埋め込み済み |
| fat binary | file | --emit-fatbin-only時 |

### 出力先

- -o オプションで指定されたファイル

## 処理フロー

### 処理シーケンス

```
1. 初期化
   └─ InitLLVM、ターゲット初期化

2. コマンドライン解析
   └─ OptTable::parseArgs

3. デバイス入力の抽出
   └─ getDeviceInput()
   └─ 入力ファイルから.llvm.offloadingセクションを抽出

4. デバイスファイルのリンクとラッピング
   └─ linkAndWrapDeviceFiles()
   └─ ターゲットごとに並列処理

5. デバイスリンク
   └─ linkDevice() → generic::clang()
   └─ nvptx/amdgcn/spirv64等のターゲット対応

6. バンドル処理
   └─ bundleLinkedOutput()
   └─ OpenMP: bundleOpenMP()
   └─ CUDA: bundleCuda() → nvptx::fatbinary()
   └─ HIP: bundleHIP() → amdgcn::fatbinary()
   └─ SYCL: bundleSYCL()

7. ラッピング
   └─ wrapDeviceImages()
   └─ offloading::wrapOpenMPBinaries/wrapCudaBinary/wrapHIPBinary/wrapSYCLBinaries

8. ホストリンカ実行
   └─ runLinker()
   └─ ラップされたイメージをリンカに渡す

9. クリーンアップ
   └─ 一時ファイルの削除（--save-temps以外）
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[InitLLVM/ターゲット初期化]
    B --> C[コマンドライン解析]
    C --> D[getDeviceInput]
    D --> E{デバイスコードあり?}
    E -->|No| F[ホストリンカのみ実行]
    E -->|Yes| G[linkAndWrapDeviceFiles]
    G --> H[parallelForEach: ターゲットごと]
    H --> I[getLinkerArgs]
    I --> J[writeOffloadFile]
    J --> K[linkDevice]
    K --> L{ターゲット種別}
    L --> M[generic::clang]
    M --> N{OffloadKind}
    N -->|OpenMP| O[bundleOpenMP]
    N -->|CUDA| P[nvptx::fatbinary]
    N -->|HIP| Q[amdgcn::fatbinary]
    N -->|SYCL| R[bundleSYCL]
    O --> S{emit-fatbin-only?}
    P --> S
    Q --> S
    R --> S
    S -->|Yes| T[直接出力]
    S -->|No| U[wrapDeviceImages]
    U --> V[compileModule]
    V --> W[runLinker]
    T --> Z[終了]
    F --> Z
    W --> X{relocatable?}
    X -->|Yes| Y[relocateOffloadSection]
    X -->|No| Z
    Y --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | linker-path必須 | ホストリンカパスを指定必須 | 常時 |
| BR-02 | SYCLリンク制限 | SYCLは他のオフロード種別との混合不可 | SYCL使用時 |
| BR-03 | TargetID互換性 | 互換性のあるターゲットIDをまとめてリンク | 常時 |
| BR-04 | whole-archive処理 | --whole-archiveと--no-whole-archiveで抽出制御 | アーカイブ入力時 |

### サポートターゲット

| ターゲット | リンク方法 | バンドル形式 |
|-----------|-----------|-------------|
| nvptx/nvptx64 | generic::clang | fatbinary |
| amdgcn | generic::clang | hipfb (clang-offload-bundler) |
| x86/x86_64/aarch64等 | generic::clang | - |
| spirv64 | generic::clang | - |

### サポートオフロード種別

| 種別 | ラッパー関数 |
|------|-------------|
| OpenMP | offloading::wrapOpenMPBinaries |
| CUDA | offloading::wrapCudaBinary |
| HIP | offloading::wrapHIPBinary |
| SYCL | offloading::wrapSYCLBinaries |

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | 設定エラー | linker-path未指定 | オプションを指定 |
| 1 | リンクエラー | デバイスリンク失敗 | コードを確認 |
| 1 | ターゲットエラー | 未サポートターゲット | サポートターゲットを使用 |
| 1 | 互換性エラー | SYCLと他オフロード種別の混合 | 分離してビルド |

### リトライ仕様

リトライは行わない。

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

該当なし。

## パフォーマンス要件

- parallelForEachによる並列デバイスリンク
- --wrapper-jobsで並列度を制御可能
- --wrapper-time-traceでプロファイリング可能

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

- 外部プログラム実行（ホストリンカ、clang、fatbinary等）
- 一時ファイルの作成と削除

## 備考

- --save-tempsで一時ファイルを保存可能
- --dry-runでコマンド確認のみ
- --verboseで詳細出力
- TimeTraceによるプロファイリングサポート

---

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

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

### 推奨読解順序

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

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

**主要処理フロー**:
1. **1260-1266行目**: InitLLVM、ターゲット初期化
2. **1271-1276行目**: コマンドライン解析
3. **1309-1312行目**: グローバルフラグ設定
4. **1350-1352行目**: デバイス入力の抽出
5. **1360-1363行目**: デバイスファイルのリンクとラッピング
6. **1366-1368行目**: ホストリンカ実行
7. **1379-1382行目**: 一時ファイルクリーンアップ

#### Step 2: デバイス入力の抽出を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ClangLinkerWrapper.cpp | `clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp` | getDeviceInput関数 |

**主要処理フロー**:
- **1138-1256行目**: getDeviceInput関数全体
- **1158-1199行目**: 入力ファイルからのOffloadBinary抽出
- **1202-1219行目**: オブジェクトファイルの処理
- **1228-1249行目**: アーカイブファイルの処理

#### Step 3: デバイスリンクを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ClangLinkerWrapper.cpp | `clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp` | linkDevice, generic::clang関数 |

**主要処理フロー**:
- **589-611行目**: linkDevice関数（ターゲット振り分け）
- **468-586行目**: generic::clang関数（汎用デバイスリンク）

#### Step 4: バンドルとラッピングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ClangLinkerWrapper.cpp | `clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp` | bundleLinkedOutput, wrapDeviceImages関数 |

**主要処理フロー**:
- **841-858行目**: bundleLinkedOutput関数
- **375-408行目**: nvptx::fatbinary関数
- **411-466行目**: amdgcn::fatbinary関数
- **691-757行目**: wrapDeviceImages関数

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

```
main (ClangLinkerWrapper.cpp:1260)
    │
    ├─ InitLLVM / InitializeAllTargets等
    │
    ├─ OptTable::parseArgs
    │
    ├─ getDeviceInput (ClangLinkerWrapper.cpp:1138)
    │      │
    │      ├─ extractOffloadBinaries
    │      │
    │      └─ ファイル分類（Object/Archive）
    │
    ├─ linkAndWrapDeviceFiles (ClangLinkerWrapper.cpp:954)
    │      │
    │      ├─ handleOverrideImages
    │      │
    │      ├─ parallelForEachError
    │      │      │
    │      │      ├─ getLinkerArgs (ClangLinkerWrapper.cpp:861)
    │      │      │
    │      │      ├─ writeOffloadFile
    │      │      │
    │      │      └─ linkDevice (ClangLinkerWrapper.cpp:589)
    │      │             │
    │      │             └─ generic::clang (ClangLinkerWrapper.cpp:468)
    │      │                    └─ executeCommands
    │      │
    │      ├─ bundleLinkedOutput (ClangLinkerWrapper.cpp:841)
    │      │      │
    │      │      ├─ bundleOpenMP
    │      │      │
    │      │      ├─ bundleCuda
    │      │      │      └─ nvptx::fatbinary
    │      │      │
    │      │      ├─ bundleHIP
    │      │      │      └─ amdgcn::fatbinary
    │      │      │
    │      │      └─ bundleSYCL
    │      │
    │      └─ wrapDeviceImages (ClangLinkerWrapper.cpp:691)
    │             │
    │             ├─ offloading::wrapOpenMPBinaries
    │             ├─ offloading::wrapCudaBinary
    │             ├─ offloading::wrapHIPBinary
    │             └─ offloading::wrapSYCLBinaries
    │                    │
    │                    └─ compileModule
    │
    └─ runLinker (ClangLinkerWrapper.cpp:339)
           │
           ├─ executeCommands (ホストリンカ)
           │
           └─ relocateOffloadSection (relocatable時)
```

### データフロー図

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

入力オブジェクト ───────┐
（.llvm.offloadingあり）│
                        │
アーカイブ ─────────────┼─▶ getDeviceInput
                        │         │
ライブラリ ─────────────┘         ▼
                           extractOffloadBinaries
                                  │
                                  ▼
                           OffloadFile群
                                  │
              ┌───────────────────┼───────────────────┐
              │                   │                   │
              ▼                   ▼                   ▼
         Target 1            Target 2           Target N
              │                   │                   │
              ▼                   ▼                   ▼
        linkDevice           linkDevice          linkDevice
              │                   │                   │
              └───────────────────┼───────────────────┘
                                  │
                    ┌─────────────┼─────────────┐
                    │             │             │
                    ▼             ▼             ▼
              OpenMP         CUDA/HIP         SYCL
                    │             │             │
                    ▼             ▼             ▼
            bundleOpenMP    fatbinary     bundleSYCL
                    │             │             │
                    └─────────────┼─────────────┘
                                  │
                                  ▼
                          wrapDeviceImages
                                  │
                                  ▼
                           compileModule
                                  │
                                  ▼
                         ラップオブジェクト
                                  │
                                  ▼
                            runLinker
                                  │
                                  ▼
                            実行可能ファイル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ClangLinkerWrapper.cpp | `clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp` | ソース | mainエントリーポイント |
| LinkerWrapperOpts.inc | (生成ファイル) | 生成 | オプション定義 |
| OffloadWrapper.h | `llvm/include/llvm/Frontend/Offloading/OffloadWrapper.h` | ヘッダ | ラッピングAPI |
| OffloadBinary.h | `llvm/include/llvm/Object/OffloadBinary.h` | ヘッダ | オフロードバイナリ |
| Utility.h | `llvm/include/llvm/Frontend/Offloading/Utility.h` | ヘッダ | オフロードユーティリティ |
