# 画面設計書 12-レジスタビュー

## 概要

本ドキュメントは、LLDB Curses GUIにおけるレジスタビューの画面設計を記述したものである。

### 本画面の処理概要

本画面は、現在のスタックフレームにおけるCPUレジスタの値を表示するウィンドウである。RegisterContextからレジスタセットを取得し、各レジスタの名前と値を階層的に表示する。

**業務上の目的・背景**：デバッグ時にCPUレジスタの状態を確認することは、低レベルのバグ調査やパフォーマンス分析において不可欠である。特にアセンブリレベルでのデバッグや、コンパイラ最適化の影響を調査する際に、レジスタの値を直接確認できることで、プログラムの実行状態を正確に把握できる。また、関数呼び出し規約の確認やABI準拠の検証にも使用される。

**画面へのアクセス方法**：
- F5キーを押してViewメニューを開き、「Registers」を選択
- または、Viewメニューから「Registers」をクリック

**主要な操作・処理内容**：
1. レジスタセット（General Purpose, Floating Point等）の一覧表示
2. 各レジスタセットを展開して個別レジスタの値を確認
3. 上下矢印キーでレジスタを選択
4. 左右矢印キーまたはスペースキーでレジスタセットの展開/折りたたみ
5. フォーマット変更キー（x/X/o/s/u/d/i/A/p/c/b/B/f）で表示形式を変更
6. Page Up/Page Downでページスクロール
7. tキーで型名の表示/非表示を切り替え

**画面遷移**：
- 遷移元：メインウィンドウ（F5 > View > Registers）
- 遷移先：F5 > View > Registersで再度選択するとウィンドウが閉じる（トグル動作）

**権限による表示制御**：特になし。デバッグ中のプロセスとスタックフレームが存在する場合にのみ内容が表示される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 8 | LLDB | 主機能 | RegistersWindowDelegateによるCPUレジスタ値表示。RegisterContextからのレジスタセット取得と表示 |
| 8 | LLDB | 補助機能 | x/X/o/s/u/d/i/A/p/c/b/B/fキーによるレジスタ値のフォーマット変更 |

## 画面種別

一覧（ツリー形式）

## URL/ルーティング

該当なし（Curses GUI内部のサブウィンドウとして表示）

## 入出力項目

本画面は表示専用であり、入力項目はない。キーボードショートカットによる表示形式の変更のみ。

## 表示項目

| 項目名 | 表示位置 | 説明 |
|--------|----------|------|
| タイトル | ウィンドウ上部 | "Registers" |
| レジスタセット名 | ツリーのルートレベル | General Purpose Registers, Floating Point Registers等 |
| レジスタ名 | ツリーの子レベル | rax, rbx, xmm0等の個別レジスタ名 |
| レジスタ値 | レジスタ名の右側 | 各レジスタの現在値（フォーマット変更可能） |
| 型名 | レジスタ名の前（オプション） | tキーでトグル表示 |

## イベント仕様

### 1-フォーマット変更キー押下

| キー | フォーマット | 説明 |
|------|-------------|------|
| x | Hex | 16進数（小文字） |
| X | HexUppercase | 16進数（大文字） |
| o | Octal | 8進数 |
| s | CString | C文字列 |
| u | Unsigned | 符号なし整数 |
| d | Decimal | 符号付き整数 |
| D | Default | デフォルトフォーマット |
| i | Instruction | 命令形式 |
| A | AddressInfo | アドレス情報 |
| p | Pointer | ポインタ |
| c | Char | 文字 |
| b | Binary | 2進数 |
| B | BytesWithASCII | バイト列（ASCII付き） |
| f | Float | 浮動小数点数 |

1. 選択中のレジスタに対して`valobj_sp->SetFormat(format)`を呼び出し
2. 画面を再描画して新しいフォーマットで表示

### 2-展開/折りたたみ操作

1. 右矢印キー：選択項目を展開（`m_selected_row->Expand()`）
2. 左矢印キー：折りたたみ、または親項目へ移動
3. スペースキー：展開/折りたたみをトグル

### 3-ナビゲーション操作

1. 上矢印キー：前の項目を選択
2. 下矢印キー：次の項目を選択
3. Page Up（,キー）：1ページ上へスクロール
4. Page Down（.キー）：1ページ下へスクロール

### 4-型名表示トグル

- tキー押下で`g_options.show_types`をトグル
- 型名の表示/非表示を切り替え

### 5-ヘルプ表示

- hキー押下で`window.CreateHelpSubwindow()`を呼び出し
- キーボードショートカットのヘルプを表示

## データベース更新仕様

該当なし（データベースを使用しないデバッガアプリケーション）

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|--------------|------|---------------|----------|
| MSG-001 | ヘルプ | Register window keyboard shortcuts: | hキー押下時のヘルプタイトル |

## 例外処理

| 例外条件 | 処理内容 |
|----------|----------|
| スタックフレームなし | 空のリストを表示（SetValues(empty_list)） |
| プロセスが実行中 | 更新をスキップしてtrueを返す |
| プロセスが終了済み | 空のリストで更新 |

## 備考

- ValueObjectListDelegateを継承し、レジスタをValueObjectとして扱う
- RegisterContextSPからレジスタセットを取得
- スタックIDが変わった場合のみレジスタリストを更新（パフォーマンス最適化）
- ソースウィンドウの左側にレジスタウィンドウを配置（HorizontalSplitPercentage）

---

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

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

### 推奨読解順序

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

まず、ValueObjectListDelegateの基底クラスとレジスタのデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | IOHandlerCursesGUI.cpp | `lldb/source/Core/IOHandlerCursesGUI.cpp` | 行5540-5548: ValueObjectListDelegateクラスの定義 |
| 1-2 | IOHandlerCursesGUI.cpp | `lldb/source/Core/IOHandlerCursesGUI.cpp` | 行5550-5558: SetValues()メソッドによるValueObjectListの設定 |
| 1-3 | IOHandlerCursesGUI.cpp | `lldb/source/Core/IOHandlerCursesGUI.cpp` | 行5597-5626: キーボードショートカットヘルプの定義 |

**読解のコツ**: ValueObjectListDelegateはValueObjectのリストを階層的に表示する汎用クラス。レジスタ、変数など様々なデータの表示に使用される。

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

RegistersWindowDelegateがどこで生成されるかを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | IOHandlerCursesGUI.cpp | `lldb/source/Core/IOHandlerCursesGUI.cpp` | 行6648-6677: eMenuID_ViewRegistersのメニューハンドラ |

**主要処理フロー**:
1. **行6649-6653**: 既存のRegistersウィンドウとSourceウィンドウを検索
2. **行6655-6669**: 既存ウィンドウがあれば削除、なければ作成（トグル動作）
3. **行6673-6676**: 新規ウィンドウ作成とRegisterWindowDelegateの設定

#### Step 3: RegistersWindowDelegateクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | IOHandlerCursesGUI.cpp | `lldb/source/Core/IOHandlerCursesGUI.cpp` | 行5969-6015: RegistersWindowDelegateクラス全体 |

**主要処理フロー**:
- **行5971-5972**: コンストラクタ - Debugger参照を保持
- **行5976-5978**: WindowDelegateGetHelpText() - ヘルプテキストを返す
- **行5980-6010**: WindowDelegateDraw() - 描画処理
  - **行5981-5983**: 現在のExecutionContextとStackFrameを取得
  - **行5986-5997**: スタックIDが変わった場合にレジスタリストを更新
  - **行5989-5996**: RegisterContextからレジスタセットを取得しValueObjectListに追加
  - **行5999-6007**: フレームがない場合の処理（プロセス実行中or終了）

#### Step 4: フォーマット変更処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | IOHandlerCursesGUI.cpp | `lldb/source/Core/IOHandlerCursesGUI.cpp` | 行5628-5650: WindowDelegateHandleChar()でのフォーマット変更 |
| 4-2 | IOHandlerCursesGUI.cpp | `lldb/source/Core/IOHandlerCursesGUI.cpp` | 行5737-5769: FormatForChar()メソッド |

**主要処理フロー**:
- **行5644-5650**: フォーマットキー押下時にvalobj_sp->SetFormat()を呼び出し
- **行5737-5769**: キー文字からFormatへの変換

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

```
ApplicationDelegate::MenuActionResult() [eMenuID_ViewRegisters]
    |
    +-- FindSubWindow("Registers") [既存ウィンドウチェック]
    |
    +-- [既存ウィンドウあり] RemoveSubWindow() [削除]
    |
    +-- [既存ウィンドウなし]
            |
            +-- HorizontalSplitPercentage() [レイアウト計算]
            |
            +-- CreateSubWindow("Registers", ...) [ウィンドウ作成]
            |
            +-- new RegistersWindowDelegate(m_debugger)
                    |
                    +-- ValueObjectListDelegate() [基底クラス初期化]

[描画時]
RegistersWindowDelegate::WindowDelegateDraw()
    |
    +-- GetExecutionContext()
    |
    +-- GetFramePtr()
    |
    +-- [スタックID変更時]
            |
            +-- frame->GetRegisterContext()
            |
            +-- reg_ctx->GetRegisterSetCount()
            |
            +-- ValueObjectRegisterSet::Create() [各セット]
            |
            +-- SetValues(value_list)
    |
    +-- ValueObjectListDelegate::WindowDelegateDraw() [親クラスの描画]

[キー入力時]
ValueObjectListDelegate::WindowDelegateHandleChar()
    |
    +-- [フォーマットキー] FormatForChar() --> valobj_sp->SetFormat()
    |
    +-- [矢印キー] ナビゲーション処理
    |
    +-- [スペースキー] Expand() / Unexpand()
    |
    +-- [tキー] g_options.show_types トグル
    |
    +-- [hキー] CreateHelpSubwindow()
```

### データフロー図

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

StackFrame -----------------> RegistersWindowDelegate -----------> レジスタ表示
    |                               |
    +-- GetRegisterContext()        |
            |                       |
            +-- GetRegisterSetCount()
            |                       |
            +-- ValueObjectRegisterSet::Create()
                    |
                    +-- SetValues()  -----------------> ValueObjectList
                                                              |
                                                              v
                                                        画面描画

ユーザー入力 --------------> WindowDelegateHandleChar() -------> 状態変更
(フォーマットキー/ナビ)           |
                                  +-- SetFormat() [フォーマット変更]
                                  +-- Expand()/Unexpand() [展開/折りたたみ]
                                  +-- show_types トグル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| IOHandlerCursesGUI.cpp | `lldb/source/Core/IOHandlerCursesGUI.cpp` | ソース | RegistersWindowDelegate実装（行5969-6015）、ValueObjectListDelegate基底クラス（行5540-5769） |
| RegisterContext.h | `lldb/include/lldb/Target/RegisterContext.h` | ヘッダー | RegisterContextSPインターフェース、GetRegisterSetCount()等 |
| ValueObjectRegisterSet.h | `lldb/include/lldb/Core/ValueObjectRegisterSet.h` | ヘッダー | ValueObjectRegisterSet::Create()の定義 |
| ValueObject.h | `lldb/include/lldb/Core/ValueObject.h` | ヘッダー | SetFormat()、GetValueAsCString()等のインターフェース |
| StackFrame.h | `lldb/include/lldb/Target/StackFrame.h` | ヘッダー | GetRegisterContext()、GetStackID()等 |
