# 機能設計書 117-llvm-ml

## 概要

本ドキュメントは、LLVMプロジェクトにおけるMASM互換アセンブラ「llvm-ml」の機能設計を記述する。

### 本機能の処理概要

llvm-mlは、Microsoft Macro Assembler（MASM）と互換性のあるアセンブラであり、llvm-mcをベースに構築されている。MASM構文のアセンブリソースコードを読み込み、オブジェクトファイルまたはアセンブリ出力を生成する。Windows環境でのアセンブリ開発をサポートするために設計されている。

**業務上の目的・背景**：Windows向けのソフトウェア開発において、MASMフォーマットのアセンブリコードは広く使用されている。LLVMツールチェーンでMASM互換のアセンブラを提供することで、既存のMASMコードをLLVMベースのビルドシステムに統合できる。これにより、クロスプラットフォーム開発やLLVMの最適化パイプラインとの連携が容易になる。

**機能の利用シーン**：
- MASMフォーマットのアセンブリソースのアセンブル
- Windows PE/COFF形式のオブジェクトファイル生成
- 32ビット（ml）および64ビット（ml64）アセンブリ
- レガシーMASMコードのLLVMツールチェーンへの移行

**主要な処理内容**：
1. コマンドライン引数の解析
2. ターゲットトリプルの決定（32ビット/64ビット）
3. ソースファイルの読み込み
4. MASM構文でのパース
5. オブジェクトファイルまたはアセンブリ出力の生成

**関連システム・外部連携**：LLVM MC（Machine Code）ライブラリ、MasmParser、MCStreamer

**権限による制御**：特になし。ファイルシステムへのアクセス権限のみ必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLI | 主機能 | コマンドラインインターフェースによる操作 |

## 機能種別

アセンブリ / コード生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| InputFilenames | string | Yes | 入力アセンブリファイル（.asmまたは-） | ファイル存在確認 |
| /Fo | string | No | 出力ファイル名 | パス妥当性確認 |
| /c | bool | No | アセンブルのみ（リンクなし） | - |
| /D | string[] | No | マクロ定義（name=value形式） | - |
| /I | string[] | No | インクルードパス | - |
| /safeseh | bool | No | SafeSEH有効化（32ビットのみ） | - |
| /Fo | string | No | 出力ファイルタイプ（obj/s/null） | - |
| /32 /64 | bool | No | ビット数指定 | - |

### 入力データソース

- MASMフォーマットのアセンブリソースファイル（.asm）
- 標準入力（-指定時）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ObjectFile | binary | COFF形式オブジェクトファイル |
| AssemblyFile | text | アセンブリ出力（-Fs指定時） |
| TokenStream | text | トークンストリーム（--as-lex指定時） |

### 出力先

- 指定されたファイル（/Foオプション）
- 入力ファイル名ベースの.objファイル（デフォルト）

## 処理フロー

### 処理シーケンス

```
1. 初期化処理
   ├─ ターゲット情報初期化
   └─ オプション解析
2. ターゲット決定
   ├─ プログラム名からビット数推測（ml64 → 64ビット）
   └─ オプションからトリプル構築
3. ソースファイル読み込み
   └─ MemoryBuffer取得
4. MC環境構築
   ├─ MCContext作成
   ├─ MCAsmInfo作成
   └─ MCSubtargetInfo作成
5. 出力先決定
   ├─ ファイルタイプ判定（obj/s/null）
   └─ ToolOutputFile作成
6. ストリーマー設定
   ├─ アセンブリモード → AsmStreamer
   ├─ オブジェクトモード → ObjectStreamer
   └─ nullモード → NullStreamer
7. アセンブル実行
   ├─ --as-lex → AsLexInput（トークン出力）
   └─ 通常 → AssembleInput（パース・コード生成）
8. COFF固有処理
   └─ @feat.00シンボル出力（SafeSEH対応）
9. 終了処理
   └─ 出力ファイル確定
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[ターゲット初期化]
    B --> C[コマンドライン解析]
    C --> D[トリプル決定]
    D --> E{プログラム名=ml64?}
    E -->|Yes| F[64ビットモード]
    E -->|No| G[32ビットモード]
    F --> H[ソースファイル読み込み]
    G --> H
    H --> I{読み込み成功?}
    I -->|No| J[エラー終了]
    I -->|Yes| K[MC環境構築]
    K --> L{ファイルタイプ?}
    L -->|s| M[AsmStreamer作成]
    L -->|obj| N[ObjectStreamer作成]
    L -->|null| O[NullStreamer作成]
    M --> P[出力ファイル作成]
    N --> P
    O --> P
    P --> Q{--as-lex?}
    Q -->|Yes| R[AsLexInput]
    Q -->|No| S[AssembleInput]
    R --> T{COFF形式?}
    S --> T
    T -->|Yes| U[@feat.00シンボル出力]
    T -->|No| V[結果判定]
    U --> V
    V --> W{成功?}
    W -->|Yes| X[出力ファイル確定]
    W -->|No| Y[エラー終了]
    X --> Z[正常終了]
    J --> AA[終了 code=1]
    Y --> AA
    Z --> AB[終了 code=0]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | ビット数推測 | プログラム名がml64の場合は64ビット、それ以外は32ビット | 起動時 |
| BR-002 | SafeSEH制限 | /safesehは32ビットX86のみ有効 | /safeseh指定時 |
| BR-003 | MASM構文 | 整数リテラル、基数、浮動小数点、文字列をMASM形式で解析 | パース時 |
| BR-004 | @feat.00シンボル | COFF出力時に機能フラグシンボルを生成 | COFF形式時 |
| BR-005 | デフォルト出力 | 出力ファイル未指定時は入力ファイル名.obj | 起動時 |

### 計算ロジック

- @feat.00フラグ計算：SafeSEH有効時は0x3（0x2 | 0x1）、無効時は0x2

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

該当なし（ファイルベースのツール）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ファイルエラー | 入力ファイルが開けない | エラーメッセージ出力後終了 |
| - | パースエラー | アセンブリ構文エラー | 行番号付きエラー出力 |
| - | ターゲットエラー | サポートされていないターゲット | エラーメッセージ出力後終了 |
| - | マクロエラー | マクロ定義が不正 | エラーメッセージ出力後終了 |

### リトライ仕様

リトライ処理なし

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

該当なし

## パフォーマンス要件

特に規定なし

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

- SafeSEH（Structured Exception Handler）対応
- 入力ファイルの検証

## 備考

- Microsoft MASMとの互換性を目指す
- llvm-mcをベースに構築
- Windows PE/COFF形式に特化

---

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

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

### 推奨読解順序

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

MCContext、MCAsmInfo、MCStreamerがアセンブラの主要コンポーネント。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | MCContext.h | `llvm/include/MC/MCContext.h` | アセンブラコンテキストのインターフェース |
| 1-2 | MCAsmInfo.h | `llvm/include/MC/MCAsmInfo.h` | アセンブリ情報の保持 |

**読解のコツ**: MCContextがシンボル管理、MCAsmInfoがターゲット固有のアセンブリ構文情報を保持。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | llvm-ml.cpp | `llvm/tools/llvm-ml/llvm-ml.cpp` | llvm_ml_main関数（192-446行目） |

**主要処理フロー**:
1. **196-199行目**: ターゲット初期化（InitializeAllTargetInfos等）
2. **201-205行目**: オプション解析
3. **274行目**: GetTriple呼び出しでトリプル決定
4. **288-294行目**: ソースファイル読み込み
5. **319-340行目**: MC環境構築
6. **369-414行目**: ストリーマー作成（ファイルタイプ別）
7. **434-440行目**: アセンブル実行

#### Step 3: トリプル決定ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | llvm-ml.cpp | `llvm/tools/llvm-ml/llvm-ml.cpp` | GetTriple関数（84-98行目） |

**トリプル決定処理フロー**:
- **86行目**: デフォルトビット数は"32"
- **88-90行目**: プログラム名がml64で終わる場合は"64"
- **92-97行目**: ビット数に応じてトリプル文字列生成（i386/x86_64-pc-windows）

#### Step 4: アセンブル処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | llvm-ml.cpp | `llvm/tools/llvm-ml/llvm-ml.cpp` | AssembleInput関数（130-190行目） |

**AssembleInput処理フロー**:
- **135-156行目**: タイムスタンプ処理（UTCオプション対応）
- **158-159行目**: createMCMasmParser呼び出し
- **169-174行目**: MASM固有のLexer設定（setLexMasmIntegers等）
- **176-185行目**: マクロ定義処理（/Dオプション）
- **187行目**: Parser.Run()でパース実行

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

```
llvm_ml_main()
    │
    ├─ InitializeAllTargetInfos/MCs/AsmParsers/Disassemblers
    │
    ├─ MLOptTable::ParseArgs
    │
    ├─ GetTriple()
    │      └─ プログラム名/オプションからトリプル決定
    │
    ├─ MemoryBuffer::getFileOrSTDIN
    │
    ├─ TheTarget->createMCRegInfo/MCAsmInfo/MCSubtargetInfo
    │
    ├─ MCContext作成
    │
    ├─ ストリーマー作成
    │      ├─ FileType="s" → createAsmStreamer
    │      ├─ FileType="obj" → createMCObjectStreamer
    │      └─ FileType="null" → createNullStreamer
    │
    ├─ COFF処理
    │      └─ @feat.00シンボル生成
    │
    └─ アセンブル実行
           ├─ --as-lex → AsLexInput()
           └─ 通常 → AssembleInput()
                         │
                         ├─ createMCMasmParser()
                         ├─ createMCAsmParser()
                         ├─ defineMacro()
                         └─ Parser.Run()
```

### データフロー図

```
入力アセンブリ(.asm)
       │
       ▼
MemoryBuffer::getFileOrSTDIN
       │
       ▼
    SourceMgr
       │
       ├──▶ AsLexInput (--as-lex)
       │        │
       │        ▼
       │    AsmLexer
       │        │
       │        ▼
       │    トークンストリーム出力
       │
       └──▶ AssembleInput
                │
                ▼
           MasmParser
                │
                ├─ タイムスタンプ設定
                ├─ マクロ定義
                └─ Parser.Run()
                       │
                       ▼
                  MCStreamer
                       │
           ┌───────────┼───────────┐
           ▼           ▼           ▼
       AsmStreamer  ObjStreamer  NullStreamer
           │           │           │
           ▼           ▼           ▼
        .s出力      .obj出力    出力なし
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| llvm-ml.cpp | `llvm/tools/llvm-ml/` | ソース | メイン処理 |
| Opts.td | `llvm/tools/llvm-ml/` | テーブルジェン | オプション定義 |
| MCAsmInfo.h | `llvm/include/MC/` | ヘッダ | アセンブリ情報 |
| MCContext.h | `llvm/include/MC/` | ヘッダ | コンテキスト管理 |
| MCStreamer.h | `llvm/include/MC/` | ヘッダ | ストリーマーインターフェース |
| AsmLexer.h | `llvm/include/MC/MCParser/` | ヘッダ | レキサー |
| CMakeLists.txt | `llvm/tools/llvm-ml/` | 設定 | ビルド設定 |
