# 機能設計書 90-clang-sycl-linker

## 概要

本ドキュメントは、clang-sycl-linkerツールの機能設計について記述する。clang-sycl-linkerは、SYCLデバイスイメージをリンクするためのユーティリティであり、LLVMビットコードのリンク、デバイスライブラリとの統合、SPIR-Vコード生成、AOTコンパイルを実行する。

### 本機能の処理概要

clang-sycl-linkerは、SYCLデバイスコードのリンクに必要な複雑な一連のステップを実行する。これには、LLVMビットコードファイルのリンク、SYCLデバイスライブラリとの結合、SPIR-Vバックエンドを使用したSPIR-Vコード生成、およびIntel CPU/GPU向けのAOTコンパイルが含まれる。

**業務上の目的・背景**：SYCLはヘテロジニアスコンピューティングのための標準規格であり、単一ソースからCPU、GPU、FPGAなど様々なデバイス向けのコードを生成できる。clang-sycl-linkerは、複数のデバイスコードファイルを統合し、ターゲットデバイス向けの実行可能なイメージを生成する役割を担う。

**機能の利用シーン**：
- SYCLアプリケーションのデバイスコードリンク
- Intel GPU向けAOTコンパイル（ocloc経由）
- Intel CPU向けAOTコンパイル（opencl-aot経由）
- SPIR-Vバイナリの生成

**主要な処理内容**：
1. 入力LLVMビットコードファイルのリンク
2. SYCLデバイスライブラリのリンク
3. SPIR-Vコード生成
4. AOTコンパイル（Intel CPU/GPU向け）
5. オフロードバイナリの出力

**関連システム・外部連携**：clang-linker-wrapper、ocloc（Intel GPU）、opencl-aot（Intel CPU）、SPIR-Vバックエンド。

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

## 関連画面

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

## 機能種別

デバイスコードリンカ / SYCL

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| 入力ファイル | string list | Yes | LLVMビットコードファイル | bitcode形式 |
| -o | string | Yes | 出力ファイル名 | - |
| -triple | string | Yes | ターゲットトリプル | - |
| -arch | string | No | アーキテクチャ | AOT必須 |
| -library-path | string | No | ライブラリパス | - |
| -device-libs | string list | No | デバイスライブラリファイル | - |
| --save-temps | bool | No | 一時ファイルを保存 | - |
| --dry-run | bool | No | コマンド表示のみ | - |
| --verbose | bool | No | 詳細出力 | - |
| --print-linked-module | bool | No | リンク後モジュールを表示 | - |
| --spirv-dump-device-code | string | No | SPIR-V出力ディレクトリ | - |
| --opencl-aot-options | string | No | opencl-aotへのオプション | - |
| --ocloc-options | string | No | oclocへのオプション | - |

### 入力データソース

- LLVMビットコードファイル（.bc）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| オフロードバイナリ | file | SPIR-V/AOT結果を含むオフロード形式 |

### 出力先

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

## 処理フロー

### 処理シーケンス

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

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

3. 入力ファイルの取得
   └─ getInput() - ビットコードファイルの検証と収集

4. SYCLリンク実行
   └─ runSYCLLink()

5. デバイスコードリンク
   └─ linkDeviceCode()
   └─ 入力ファイルをLLVM Linkerでリンク
   └─ SYCLデバイスライブラリをリンク（LinkOnlyNeeded）

6. シンボルテーブル生成
   └─ カーネル関数（SPIR_KERNEL等）を収集

7. SPIR-Vコード生成
   └─ runSPIRVCodeGen()
   └─ SPIR-Vバックエンドを使用

8. AOTコンパイル（Intel向け）
   └─ runAOTCompile()
   └─ Intel GPU: ocloc
   └─ Intel CPU: opencl-aot

9. オフロードバイナリ出力
   └─ OffloadBinary::write()

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

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[InitLLVM/ターゲット初期化]
    B --> C[コマンドライン解析]
    C --> D{-o指定あり?}
    D -->|No| E[エラー終了]
    D -->|Yes| F{-triple指定あり?}
    F -->|No| E
    F -->|Yes| G[getInput]
    G --> H[runSYCLLink]
    H --> I[linkDeviceCode]
    I --> J[入力ファイルリンク]
    J --> K[getSYCLDeviceLibs]
    K --> L[デバイスライブラリリンク]
    L --> M{print-linked-module?}
    M -->|Yes| N[モジュール出力]
    M -->|No| O[シンボルテーブル生成]
    N --> O
    O --> P[runSPIRVCodeGen]
    P --> Q{IsIntelOffloadArch?}
    Q -->|Yes| R[runAOTCompile]
    Q -->|No| S[SPIR-V出力]
    R --> T{Intel GPU?}
    T -->|Yes| U[ocloc]
    T -->|No| V[opencl-aot]
    U --> W[OffloadBinary::write]
    V --> W
    S --> W
    W --> X{--save-temps?}
    X -->|No| Y[一時ファイル削除]
    X -->|Yes| Z[終了]
    Y --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 出力ファイル必須 | -o オプション必須 | 常時 |
| BR-02 | トリプル必須 | -triple オプション必須 | 常時 |
| BR-03 | AOTアーキテクチャ必須 | AOTコンパイル時は-arch必須 | Intel向けAOT |
| BR-04 | ビットコード入力のみ | 入力はLLVMビットコード形式のみ | 常時 |

### サポートするカーネル種別

| 呼び出し規約 | 説明 |
|-------------|------|
| SPIR_KERNEL | SPIR カーネル |
| AMDGPU_KERNEL | AMDGPU カーネル |
| PTX_Kernel | PTX カーネル |

### AOTコンパイルターゲット

| ターゲット | ツール | 説明 |
|-----------|--------|------|
| Intel GPU | ocloc | Intel Graphics Compute Runtime |
| Intel CPU | opencl-aot | Intel OpenCL CPU Runtime |

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | 設定エラー | -o未指定 | オプションを指定 |
| 1 | 設定エラー | -triple未指定 | オプションを指定 |
| 1 | 入力エラー | ビットコード以外の入力 | 入力形式を確認 |
| 1 | リンクエラー | IRリンク失敗 | コードを確認 |
| 1 | AOTエラー | -archが未指定（Intel向け） | オプションを指定 |
| 1 | AOTエラー | ocloc/opencl-aot失敗 | ツールインストールを確認 |

### リトライ仕様

リトライは行わない。

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

該当なし。

## パフォーマンス要件

- TimeTraceによるプロファイリングサポート
- LinkOnlyNeededフラグでデバイスライブラリの最小限リンク

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

- 外部プログラム実行（ocloc、opencl-aot）
- 一時ファイルの作成と削除

## 備考

- 現時点ではLLVMビットコード入力のみサポート（SPIR-V入力は将来対応予定）
- AOTコンパイルなしの場合はSPIR-Vファイルを出力
- clang-linker-wrapperから呼び出される設計

---

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

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

### 推奨読解順序

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

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

**主要処理フロー**:
1. **569-575行目**: InitLLVM、ターゲット初期化
2. **580-585行目**: コマンドライン解析
3. **601-603行目**: グローバルフラグ設定
4. **605-610行目**: 出力ファイル、トリプル必須チェック
5. **624-626行目**: 入力ファイル取得
6. **629-630行目**: SYCLリンク実行
7. **633-636行目**: 一時ファイルクリーンアップ

#### Step 2: デバイスコードリンクを理解する

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

**主要処理フロー**:
- **251-313行目**: linkDeviceCode関数全体
- **257-266行目**: 入力ファイルのリンク
- **269-284行目**: SYCLデバイスライブラリのリンク

#### Step 3: SPIR-Vコード生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ClangSYCLLinker.cpp | `clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp` | runSPIRVCodeGen関数 |

**主要処理フロー**:
- **319-375行目**: runSPIRVCodeGen関数全体
- **335-339行目**: SPIR-Vターゲット取得
- **362-368行目**: コード生成パス実行

#### Step 4: AOTコンパイルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ClangSYCLLinker.cpp | `clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp` | runAOTCompile関連関数 |

**主要処理フロー**:
- **451-461行目**: runAOTCompile関数（振り分け）
- **385-403行目**: runAOTCompileIntelCPU関数
- **413-443行目**: runAOTCompileIntelGPU関数

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

```
main (ClangSYCLLinker.cpp:569)
    │
    ├─ InitLLVM / InitializeAllTargets等
    │
    ├─ OptTable::parseArgs
    │
    ├─ getInput (ClangSYCLLinker.cpp:184)
    │      └─ identify_magic (bitcode検証)
    │
    └─ runSYCLLink (ClangSYCLLinker.cpp:474)
           │
           ├─ linkDeviceCode (ClangSYCLLinker.cpp:251)
           │      │
           │      ├─ getBitcodeModule (各入力ファイル)
           │      │
           │      ├─ Linker::linkInModule
           │      │
           │      ├─ getSYCLDeviceLibs (ClangSYCLLinker.cpp:221)
           │      │
           │      └─ Linker::linkInModule (LinkOnlyNeeded)
           │
           ├─ シンボルテーブル生成
           │      └─ isKernel (ClangSYCLLinker.cpp:464)
           │
           ├─ runSPIRVCodeGen (ClangSYCLLinker.cpp:319)
           │      │
           │      ├─ parseIRFile
           │      │
           │      ├─ TargetRegistry::lookupTarget
           │      │
           │      ├─ Target::createTargetMachine
           │      │
           │      └─ PassManager::run (CodeGen)
           │
           ├─ runAOTCompile (ClangSYCLLinker.cpp:451)
           │      │
           │      ├─ IsIntelGPUOffloadArch
           │      │      └─ runAOTCompileIntelGPU
           │      │             └─ ocloc
           │      │
           │      └─ IsIntelCPUOffloadArch
           │             └─ runAOTCompileIntelCPU
           │                    └─ opencl-aot
           │
           └─ OffloadBinary::write
```

### データフロー図

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

入力ビットコード ─────────┐
（.bc ファイル群）        │
                          │
-device-libs ─────────────┼─▶ linkDeviceCode
                          │         │
-library-path ────────────┘         ▼
                             Linker::linkInModule
                                     │
                                     ▼
                             リンク済みビットコード
                                     │
                    ┌────────────────┼────────────────┐
                    │                │                │
                    ▼                ▼                ▼
             シンボル収集    SPIR-V生成      モジュール表示
             (カーネル)     (runSPIRVCodeGen)  (--print-linked-module)
                    │                │
                    │                ▼
                    │         .spv ファイル
                    │                │
                    │                ▼
                    │        {IsIntelOffloadArch?}
                    │                │
                    │    ┌───────────┼───────────┐
                    │    │                       │
                    │    ▼                       ▼
                    │  ocloc                  そのまま
                    │  または                    │
                    │  opencl-aot                │
                    │    │                       │
                    │    ▼                       │
                    │  .out ファイル             │
                    │    │                       │
                    │    └───────────┬───────────┘
                    │                │
                    └────────────────┼────────────────┘
                                     │
                                     ▼
                          OffloadBinary::write
                                     │
                                     ▼
                             オフロードバイナリ
                               (-o 出力)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ClangSYCLLinker.cpp | `clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp` | ソース | mainエントリーポイント |
| SYCLLinkOpts.inc | (生成ファイル) | 生成 | オプション定義 |
| OffloadBinary.h | `llvm/include/llvm/Object/OffloadBinary.h` | ヘッダ | オフロードバイナリ形式 |
| OffloadArch.h | `clang/include/clang/Basic/OffloadArch.h` | ヘッダ | オフロードアーキテクチャ定義 |
| Linker.h | `llvm/include/llvm/Linker/Linker.h` | ヘッダ | LLVMリンカAPI |
