# 帳票設計書 14-FlangOmpReport

## 概要

本ドキュメントは、FlangコンパイラのプラグインであるFlangOmpReportが生成するOpenMP構文レポートの設計仕様を定義する。このプラグインはFortranソースコードを解析し、使用されているOpenMP構文とクローズをYAML形式で出力する。

### 本帳票の処理概要

FlangOmpReportは、Fortranソースコード内のOpenMPディレクティブ（`!$omp`で始まる構文）を解析し、構文名、使用されているクローズ、およびソースコード上の位置情報をYAML形式で出力するレポートである。

**業務上の目的・背景**：高性能計算（HPC）やマルチスレッドプログラミングにおいて、OpenMPは広く使用されている並列化API規格である。大規模なFortranコードベースでOpenMPの使用状況を把握することは、性能最適化やコードレビューにおいて重要である。本レポートは、OpenMPディレクティブの使用状況を自動的に収集し、分析可能な形式で提供する。

**帳票の利用シーン**：
- コードベース全体のOpenMP使用状況の調査
- 並列化戦略の分析とドキュメンテーション
- OpenMP移行プロジェクトでの進捗追跡
- 静的解析ツールへの入力データ生成

**主要な出力内容**：
1. ソースファイル名
2. OpenMP構文の出現行番号
3. OpenMP構文名（parallel, do, sections等）
4. 使用されているクローズのリスト（各クローズの詳細情報付き）

**帳票の出力タイミング**：Flangコンパイラに`-plugin flang-omp-report`オプションを指定してFortranソースファイルをコンパイルした際に出力される。

**帳票の利用者**：HPCアプリケーション開発者、性能エンジニア、コード品質アナリスト

## 帳票種別

解析レポート / コード品質レポート

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | コマンドライン | N/A | `flang -fc1 -load lib/flangOmpReport.so -plugin flang-omp-report -fopenmp {source.f90}` |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | YAML |
| 用紙サイズ | N/A |
| 向き | N/A |
| ファイル名 | `{入力ファイル名}.yaml` |
| 出力方法 | ファイル出力 |
| 文字コード | UTF-8 |

### YAML出力設定

| 項目 | 内容 |
|-----|------|
| YAMLバージョン | 1.2（LLVMのYAMLパーサー準拠） |
| シーケンス形式 | ブロックスタイル |
| マッピング形式 | ブロックスタイル |

## 帳票レイアウト

### レイアウト概要

出力されるYAMLは以下の構造を持つ。

```yaml
---
- file: "/path/to/source.f90"
  line: 10
  construct: "parallel"
  clauses:
    - clause: "num_threads"
      details: "4"
    - clause: "default"
      details: "type=shared;"
- file: "/path/to/source.f90"
  line: 15
  construct: "do"
  clauses:
    - clause: "schedule"
      details: "type=static;modifier=simd;"
...
```

### レコード構造

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | file | ソースファイルのパス | SourcePosition::path | 文字列 |
| 2 | line | ディレクティブの行番号 | SourcePosition::line | 整数 |
| 3 | construct | OpenMP構文名 | OpenMPConstruct/OpenMPDeclarativeConstruct | 小文字文字列 |
| 4 | clauses | クローズのリスト | OmpClause | 配列 |

### クローズ構造

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | clause | クローズ名 | OmpClause | 小文字文字列 |
| 2 | details | クローズの詳細情報 | 各クローズのパラメータ | `key=value;`形式 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| OpenMP有効化 | `-fopenmp`オプション | Yes |
| プラグイン読み込み | `-load lib/flangOmpReport.so` | Yes |
| プラグイン有効化 | `-plugin flang-omp-report` | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | クローズ名 | 昇順（std::sort） |

### 改ページ条件

N/A（YAMLファイル出力）

## データベース参照仕様

### 参照テーブル一覧

本帳票はデータベースを使用せず、パース木から情報を取得する。

| データソース | 用途 | 取得方法 |
|-------------|------|---------|
| Parse Tree | OpenMP構文の抽出 | Walk関数によるトラバース |
| OpenMPConstruct | 実行構文の情報 | Visitor Pattern |
| OpenMPDeclarativeConstruct | 宣言構文の情報 | Visitor Pattern |
| SourcePosition | 位置情報 | allCooked().GetSourcePositionRange() |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| - | - | - | 計算項目なし（文字列変換のみ） |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[Fortranソース読み込み] --> B[パース木構築]
    B --> C[OpenMPCounterVisitor作成]
    C --> D[Walk関数でトラバース]
    D --> E{OpenMP構文?}
    E -->|Yes| F[Pre関数でスタックにプッシュ]
    F --> G[クローズ情報収集]
    G --> H[Post関数でLogRecord作成]
    H --> I[constructClausesに追加]
    E -->|No| D
    I --> D
    D --> J[トラバース完了]
    J --> K[YAMLファイル出力]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| パースエラー | Fortranソースの文法エラー | Flangのエラーメッセージ | ソースコードの修正 |
| プラグイン読み込み失敗 | ライブラリパス不正 | シェルエラー | パスの確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | ソースファイル内のOpenMP構文数に比例 |
| 目標出力時間 | パース時間に依存（通常数秒以内） |
| 同時出力数上限 | 1ファイル |

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

- 出力YAMLにはソースファイルの絶対パスが含まれる
- クローズ詳細には変数名等のソースコード情報が含まれる場合がある

## 備考

- サポートするOpenMP構文は`OpenMPConstruct`および`OpenMPDeclarativeConstruct`
- クローズ名は小文字に正規化される（`normalize_clause_name`関数）
- 構文名も小文字に正規化される（`normalize_construct_name`関数）
- ネストしたOpenMP構文はスタックで管理される

---

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

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

### 推奨読解順序

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

まず、レポート出力に使用されるデータ構造を把握することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | FlangOmpReportVisitor.h | `flang/examples/FlangOmpReport/FlangOmpReportVisitor.h` | ClauseInfo構造体（24-32行目）とLogRecord構造体（37-42行目）を確認 |
| 1-2 | FlangOmpReportVisitor.h | `flang/examples/FlangOmpReport/FlangOmpReportVisitor.h` | OpenMPCounterVisitor構造体（49-89行目）を確認 |

**読解のコツ**:
- `ClauseInfo`はクローズ名と詳細情報のペア
- `LogRecord`はファイル、行、構文名、クローズ配列を保持
- `OmpWrapperType`はOpenMPConstruct/OpenMPDeclarativeConstructのvariant

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

処理の起点となる関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | FlangOmpReport.cpp | `flang/examples/FlangOmpReport/FlangOmpReport.cpp` | FlangOmpReportクラス（51-68行目）とexecuteAction()メソッド |

**主要処理フロー**:
1. **52-59行目**: executeAction()でパース木をWalk
2. **62-66行目**: YAML出力ストリームを作成し、constructClausesを出力

#### Step 3: Visitorパターンを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FlangOmpReportVisitor.cpp | `flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp` | Pre(OpenMPConstruct)（101-105行目）でスタックにプッシュ |
| 3-2 | FlangOmpReportVisitor.cpp | `flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp` | Post(OmpClause)（181-184行目）でクローズ情報収集 |
| 3-3 | FlangOmpReportVisitor.cpp | `flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp` | PostConstructsCommon（113-127行目）でLogRecord作成 |

**主要処理フロー**:
- **31-35行目**: normalize_construct_name()で構文名を小文字化
- **36-52行目**: normalize_clause_name()でクローズ名を解析・正規化
- **113-127行目**: PostConstructsCommon()でクローズをソートしLogRecord生成

#### Step 4: YAMLマッピングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | FlangOmpReport.cpp | `flang/examples/FlangOmpReport/FlangOmpReport.cpp` | MappingTraits<ClauseInfo>（34-39行目）でYAML出力形式定義 |
| 4-2 | FlangOmpReport.cpp | `flang/examples/FlangOmpReport/FlangOmpReport.cpp` | MappingTraits<LogRecord>（40-47行目）でYAML出力形式定義 |

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

```
FlangOmpReport::executeAction (FlangOmpReport.cpp:52)
    │
    ├─ OpenMPCounterVisitor作成 (FlangOmpReport.cpp:55-56)
    │
    ├─ Walk (FlangOmpReport.cpp:59)
    │      │
    │      ├─ Pre(OpenMPConstruct) (FlangOmpReportVisitor.cpp:101)
    │      │      └─ スタックにプッシュ
    │      │
    │      ├─ Post(OmpClause) (FlangOmpReportVisitor.cpp:181)
    │      │      └─ normalize_clause_name (FlangOmpReportVisitor.cpp:36)
    │      │             └─ PostClauseCommon (FlangOmpReportVisitor.cpp:185)
    │      │
    │      ├─ Post(各種クローズ詳細)
    │      │      └─ clauseDetails += "key=value;"
    │      │
    │      └─ Post(OpenMPConstruct) (FlangOmpReportVisitor.cpp:110)
    │             └─ PostConstructsCommon (FlangOmpReportVisitor.cpp:113)
    │                    ├─ std::sort (クローズをソート)
    │                    ├─ getLocation (位置情報取得)
    │                    ├─ getName (構文名取得)
    │                    └─ LogRecord作成・追加
    │
    └─ llvm::yaml::Output (FlangOmpReport.cpp:64-66)
           └─ YAML出力
```

### データフロー図

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

Fortranソース ──────────▶ パース木構築 ─────────────────┐
                              │                         │
                              ▼                         │
                        Walk(parse tree)                │
                              │                         │
OpenMPConstruct ──────▶ Pre()でスタックプッシュ ────────┤
                              │                         │
OmpClause ────────────▶ Post()でクローズ収集 ──────────┤
                              │                         ▼
                        PostConstructsCommon() ─────▶ LogRecord
                              │                         │
                              ▼                         │
                        constructClauses ───────────────┤
                              │                         │
                              └─────────────────────▶ YAML出力 ──▶ .yaml
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| FlangOmpReport.cpp | `flang/examples/FlangOmpReport/FlangOmpReport.cpp` | ソース | プラグインメイン |
| FlangOmpReportVisitor.h | `flang/examples/FlangOmpReport/FlangOmpReportVisitor.h` | ヘッダー | Visitor定義 |
| FlangOmpReportVisitor.cpp | `flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp` | ソース | Visitor実装 |
| FrontendPluginRegistry.h | `flang/include/flang/Frontend/FrontendPluginRegistry.h` | ヘッダー | プラグイン登録 |
| parse-tree-visitor.h | `flang/include/flang/Parser/parse-tree-visitor.h` | ヘッダー | Visitorベース |
| parse-tree.h | `flang/include/flang/Parser/parse-tree.h` | ヘッダー | パース木定義 |
| parsing.h | `flang/include/flang/Parser/parsing.h` | ヘッダー | パーサーインターフェース |
