# 機能設計書 60-llvm-cvtres

## 概要

本ドキュメントは、LLVMプロジェクトにおけるllvm-cvtresツールの機能設計を記述する。llvm-cvtresは、Windowsリソースファイル（.res）をCOFFオブジェクトファイル（.obj）に変換するツールである。

### 本機能の処理概要

llvm-cvtresは、Microsoft cvtres.exeのクロスプラットフォーム互換ツールとして、Windowsリソースファイル（.res）をCOFFオブジェクトファイルにシリアライズする。このツールは、Windowsリソースのコンパイルパイプラインにおける最終ステップを担う。

**業務上の目的・背景**：Windowsアプリケーション開発において、リソースファイルは以下のパイプラインで処理される。

```
.rc (スクリプト) ---(rc.exe/llvm-rc)---> .res (バイナリ) ---(cvtres.exe/llvm-cvtres)---> .obj (COFF)
```

従来のcvtres.exeはWindowsでのみ動作するため、クロスコンパイル環境やCI/CD環境で問題となる。llvm-cvtresは、Linux/macOS上でもWindowsリソースをCOFFに変換可能にする。

**機能の利用シーン**：
- Windows GUIアプリケーションのビルド
- クロスコンパイル環境でのWindowsリソース処理
- 複数の.resファイルを1つの.objに統合
- CI/CDパイプラインでのリソースコンパイル

**主要な処理内容**：
1. .resファイルの読み込みと検証
2. リソースエントリのパースとツリー構築
3. COFFオブジェクトファイルへの変換
4. 出力ファイルの書き込み

**関連システム・外部連携**：
- llvm-rc（.rcから.resへのコンパイル）との連携
- WindowsResourceライブラリとの連携

**権限による制御**：本ツールはファイルシステムへの読み書きアクセスを必要とする。

## 関連画面

本ツールはCLI（コマンドラインインターフェース）ツールであり、GUI画面は存在しない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| N/A | コマンドライン | 主画面 | 入力ファイル、オプションの指定 |

## 機能種別

ファイル変換 / リソース変換

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| InputFiles | list<string> | Yes | リソースファイル（.res）1つ以上 | ファイルが存在すること |
| /MACHINE: | string | No | ターゲットアーキテクチャ | ARM, ARM64, EBC, IA64, X64, X86 |
| /OUT: | string | No | 出力ファイル名 | - |
| /TIMESTAMP: | int | No | COFFヘッダのタイムスタンプ | 32ビット整数 |
| /VERBOSE | bool | No | 詳細出力モード | - |
| /HELP | bool | No | ヘルプ表示 | - |

### 入力データソース

- Windowsリソースファイル（.res）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ObjectFile | file | COFFオブジェクトファイル（.obj） |

### 出力先

- 指定された出力ファイル（デフォルト: 最初の入力ファイル名.obj）

## 処理フロー

### 処理シーケンス

```
1. オプション解析
   └─ CvtResOptTableでパース
2. マシンタイプ決定
   ├─ /MACHINE:指定あり: 指定値を使用
   └─ 未指定: X64をデフォルト使用
3. 入力ファイル検証
   └─ 各ファイルのマジックナンバーを確認
4. リソースパース
   └─ WindowsResourceParserで各ファイルを解析
5. 重複チェック
   └─ 同じリソースが複数存在する場合はエラー
6. COFF出力
   └─ writeWindowsResourceCOFFでオブジェクト生成
7. ファイル書き込み
   └─ FileOutputBufferで出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[オプション解析]
    B --> C{/HELP?}
    C -->|Yes| D[ヘルプ表示]
    D --> E[終了]
    C -->|No| F{入力ファイルあり?}
    F -->|No| G[エラー: No input file]
    G --> E
    F -->|Yes| H{/MACHINE指定?}
    H -->|Yes| I[指定アーキテクチャ使用]
    H -->|No| J[X64をデフォルト使用]
    I --> K[各.resファイル処理]
    J --> K
    K --> L{マジック検証}
    L -->|NG| M[エラー: unrecognized format]
    M --> E
    L -->|OK| N[WindowsResourceParser.parse]
    N --> O{重複あり?}
    O -->|Yes| P[エラー出力]
    P --> E
    O -->|No| Q[writeWindowsResourceCOFF]
    Q --> R[FileOutputBuffer書き込み]
    R --> S{/VERBOSE?}
    S -->|Yes| T[Raw Data出力]
    S -->|No| E
    T --> E
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | デフォルトアーキテクチャ | マシン未指定時はX64を使用 | /MACHINE未指定時 |
| BR-02 | 出力ファイル名推論 | 入力ファイルの拡張子を.objに変更 | /OUT未指定時 |
| BR-03 | タイムスタンプ | 未指定時は現在時刻を使用 | /TIMESTAMP未指定時 |
| BR-04 | ファイル形式検証 | file_magicでwindows_resourceを確認 | 常時 |
| BR-05 | 重複リソースエラー | 同一リソースが複数存在する場合エラー | 常時 |

### 計算ロジック

タイムスタンプ取得：
- getTime()関数で現在時刻を取得
- time_tが32ビット範囲外の場合はUINT32_MAXを返す

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

本ツールはデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | 入力エラー | 入力ファイルが指定されていない | ファイルを指定 |
| 1 | 入力エラー | ファイルが開けない | ファイルパスを確認 |
| 1 | 形式エラー | .resファイルでない | 正しいリソースファイルを使用 |
| 1 | アーキテクチャエラー | 未サポートのマシンタイプ | サポートするアーキテクチャを指定 |
| 1 | タイムスタンプエラー | 無効な数値 | 32ビット整数を指定 |
| 1 | 重複エラー | リソースが重複 | 重複を解消 |

### リトライ仕様

リトライ処理は実装されていない。

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

該当なし（ファイル入出力処理）。

## パフォーマンス要件

ビルド時間に影響するため、合理的な速度での処理が期待される。

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

- 入力ファイルのマジックナンバー検証を実施
- タイムスタンプは任意指定可能（再現可能ビルド用）

## 備考

- Microsoft cvtres.exe互換
- サポートアーキテクチャ: ARM, ARM64, EBC, IA64, X64（デフォルト）, X86
- /DEFINE:, /FOLDDUPS:, /NOLOGO, /READONLY は未実装（互換性のため受け付ける）

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

リソース変換に使用される主要なデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | WindowsResource.h | `llvm/include/llvm/Object/WindowsResource.h` | WindowsResource、WindowsResourceParserクラス定義 |
| 1-2 | WindowsMachineFlag.h | `llvm/include/llvm/Object/WindowsMachineFlag.h` | マシンタイプ定義 |

**読解のコツ**: WindowsResourceがリソースファイルを表し、WindowsResourceParserがリソースをツリー構造に解析する。TreeNodeがリソースの階層構造を表す。

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

処理の起点となるmain関数を読み解く。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | llvm-cvtres.cpp | `llvm/tools/llvm-cvtres/llvm-cvtres.cpp` | main関数（115-232行目） |

**主要処理フロー**:
1. **115-126行目**: InitLLVM初期化とオプション解析、ヘルプ表示
2. **128-142行目**: マシンタイプの決定（デフォルトX64）
3. **144-148行目**: 入力ファイル取得と検証
4. **150-167行目**: 出力ファイル名とタイムスタンプの決定
5. **172-202行目**: 各.resファイルのパース処理
6. **208-218行目**: COFF出力と書き込み
7. **220-229行目**: VERBOSE時のデバッグ出力

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Opts.td | `llvm/tools/llvm-cvtres/Opts.td` | TableGen形式のオプション定義 |

**主要オプション**:
- **7行目**: MACHINE - ターゲットアーキテクチャ
- **9行目**: OUT - 出力ファイル
- **11行目**: VERBOSE - 詳細出力
- **18-19行目**: TIMESTAMP - タイムスタンプ指定

#### Step 4: リソースパース処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | llvm-cvtres.cpp | `llvm/tools/llvm-cvtres/llvm-cvtres.cpp` | ファイル読み込みループ（174-202行目） |

**主要処理**:
- **175-177行目**: MemoryBuffer::getFileOrSTDINでファイル読み込み
- **178-180行目**: identify_magicでファイル形式検証
- **181-183行目**: WindowsResource::createWindowsResourceでリソース生成
- **199行目**: Parser.parse()でリソースをツリーに追加

#### Step 5: COFF出力処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | llvm-cvtres.cpp | `llvm/tools/llvm-cvtres/llvm-cvtres.cpp` | COFF生成（208-218行目） |
| 5-2 | WindowsResource.cpp | `llvm/lib/Object/WindowsResource.cpp` | writeWindowsResourceCOFF実装 |

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

```
main()
    |
    +-- InitLLVM()
    +-- CvtResOptTable::ParseArgs()
    |
    +-- [/MACHINE指定時]
    |       +-- getMachineType()
    |
    +-- [各入力ファイル]
    |       +-- MemoryBuffer::getFileOrSTDIN()
    |       +-- identify_magic()
    |       +-- WindowsResource::createWindowsResource()
    |       |
    |       +-- [VERBOSE]
    |       |       +-- RF->getHeadEntry()
    |       |       +-- Entry.moveNext() [ループ]
    |       |
    |       +-- WindowsResourceParser::parse()
    |
    +-- [VERBOSE]
    |       +-- Parser.printTree()
    |
    +-- writeWindowsResourceCOFF()
    +-- FileOutputBuffer::create()
    +-- FileBuffer->commit()
    |
    +-- [VERBOSE]
            +-- ScopedPrinter::printBinaryBlock()
```

### データフロー図

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

.resファイル     --> MemoryBuffer::getFile()
                         |
                         v
                  identify_magic()
                         |
                         v
                  WindowsResource
                         |
                         v
                  WindowsResourceParser
                         |
                         +-- parse() [リソースをツリーに追加]
                         |
                         v
                  Parser (ツリー構造)
                         |
                         v
                  writeWindowsResourceCOFF()
                         |
                         v
                  MemoryBuffer (COFFデータ)
                         |
                         v
                  FileOutputBuffer     --> .objファイル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| llvm-cvtres.cpp | `llvm/tools/llvm-cvtres/llvm-cvtres.cpp` | ソース | メインエントリーポイント |
| Opts.td | `llvm/tools/llvm-cvtres/Opts.td` | TableGen | オプション定義 |
| CMakeLists.txt | `llvm/tools/llvm-cvtres/CMakeLists.txt` | ビルド設定 | ビルド構成の定義 |
| WindowsResource.h | `llvm/include/llvm/Object/WindowsResource.h` | ヘッダー | リソースクラス定義 |
| WindowsResource.cpp | `llvm/lib/Object/WindowsResource.cpp` | ソース | リソース処理実装 |
| WindowsMachineFlag.h | `llvm/include/llvm/Object/WindowsMachineFlag.h` | ヘッダー | マシンタイプ定義 |
| Magic.h | `llvm/include/llvm/BinaryFormat/Magic.h` | ヘッダー | ファイルマジック定義 |
