summaryrefslogtreecommitdiff
path: root/README.ja.md
blob: d3503fc64364431c808b5bc7dd319df683a77114 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# Simple

[English](README.md) | 日本語 | [翻訳について](docs/japanese-translation.md)

この文書は [Simple の README](README.md) の日本語訳です。

Sea of Nodes コンパイラ中間表現(IR)を紹介する Simple

このリポジトリは、Sea of Nodes コンパイラ IR を実演するためのものです。

Sea of Nodes は、HotSpot の C2 コンパイラ、Google の V8 コンパイラ、
Sun/Oracle の Graal コンパイラで使われる中核的な IR です。

SoN IR の紹介が目的なので、実装する*言語*そのものの重要性は高くありません。
C や Java に似た、機能がずっと少ない非常に単純な言語を使います。
Simple は強い型付けを持つオブジェクト指向言語で、*クロージャ*ではなく*関数*が第一級の値です。
オブジェクト参照はポインタであり、型システムによって null ポインタ例外を禁止します。
配列にもいずれ範囲チェックが導入されると考えられ、その場合 Simple は完全に安全な言語になります。
Simple の構文は最小限で、再帰下降パーサーで解析できます。

実用システムでは Sea of Nodes を機械語生成に使いますが、
この実演ではバックエンドの実装は難しく、重要性も比較的低くなります。
このリポジトリは x86-64、RISC-V、ARM64 を対象に事前(AOT)コンパイルを行いますが、
JIT コンパイルも視野に入れています。

このリポジトリは、どの意味でも完全な言語を目指してはいません。
そのため、バックエンドは SoN IR を直接解釈する Java の評価器から始まります
(第8章で初めて導入します)。コード生成は第19章で初めて登場します。

## 各章

以下は大まかな計画であり、変更されることがあります。

各章は自己完結した完全な実装です。Simple 言語の一部を完全に実装し、
前の章で作成したものをすべて含みます。また、各章には Sea of Nodes
中間表現の関連する側面について詳しい解説を付けます。

Simple 言語のスタイルは、C または Java のサブセットに倣っています。

* [第1章](docs/chapter01/README.ja.md):整数リテラルを返すスクリプト。引数を受け取らず、整数値を1つ返す空の関数。`return` 文。
* [第2章](docs/chapter02/README.ja.md):定数を使う加算、減算、乗算、除算などの単純な二項算術演算。ピープホール最適化と単純な定数畳み込み。
* [第3章](docs/chapter03/README.ja.md):ローカル変数と代入文。右辺での読み取り、SSA、ローカル変数が定数の場合の追加のピープホール最適化。
* [第4章](docs/chapter04/README.ja.md):`arg` という名前の、定数ではない外部入力変数。定数と `arg` を使う二項演算と比較演算。ゼロ以外の値は真とみなします。代数的簡約によるピープホール最適化。
* [第5章](docs/chapter05/README.ja.md):`if` 文。制御フローグラフ(CFG)の構築。
* [第6章](docs/chapter06/README.ja.md):実行されない制御フローに対するピープホール最適化。
* [第7章](docs/chapter07/README.ja.md):`while` 文。ループ構造と先行的な Phi の導入。
* [第8章](docs/chapter08/README.ja.md):ループ構造の続き。必要時の Phi の生成、`break` 文と `continue` 文。
* [第9章](docs/chapter09/README.ja.md):大域的値番号付け。不動点に達するまでのピープホール最適化の反復。ワークリスト。
* [第10章](docs/chapter10/README.ja.md):ユーザー定義の構造体、ポインタ、null 解析。SSA で表す単一のメモリ値。ロード、ストア、実行可能な評価器。
* [第11章](docs/chapter11/README.ja.md):同値類によるエイリアス解析。`MemMerge`、`MemPhi`、`BulkMemPhi` による必要時のメモリ分割。
* [第12章](docs/chapter12/README.ja.md):参照フィールド、前方参照、再帰的な構造体。
* [第13章](docs/chapter13/README.ja.md):大域的コード移動とスケジューリング。
* [第14章](docs/chapter14/README.ja.md):数値型。浮動小数点数、狭い整数型、範囲、`f32` への丸め。
* [第15章](docs/chapter15/README.ja.md):静的な長さを持つ一次元配列型。配列のロードとストア。
* [第16章](docs/chapter16/README.ja.md):コンストラクタ。
* [第17a章](docs/chapter17a/README.ja.md):束縛の可変性、参照の権限、深い読み取り専用ビュー。
* [第17b章](docs/chapter17b/README.ja.md):糖衣構文。`var`、`val`、`x+=y`、`for(init; test; next) body`。
* [第18章](docs/chapter18/README.ja.md):関数と呼び出し。
* [第19章](docs/chapter19/README.ja.md):命令選択と移植可能なコンパイル。
* [第20章](docs/chapter20/README.ja.md):グラフ彩色によるレジスタ割り当て。
* [第21章](docs/chapter21/README.ja.md):命令エンコーディングと ELF。
* [第22章](docs/chapter22/README.ja.md):Simple の Hello, World!
* [第23章](docs/chapter23/README.ja.md):メソッドと型の再検討。
* [第24章](docs/chapter24/README.ja.md):連鎖した条件分岐と SCCP。
* 第25章:モジュール、分割コンパイル、不完全な型を使う SSA の構築。

## 章をまたぐビルド

任意で使える[対話的なグラフビューア(英語)](graph/README.md)は `graph/` で共有しています。
第1〜25章では、章のディレクトリで `make view` を実行して起動します。

[デバッグ用プリンタ(英語)](print/README.md)は `print/` で共有しています。
第2章で必要なのは1行の式形式だけです。共通の `BaseNode` が、プリンタとビューアの両方に
ノードの同一性とエッジへのアクセスを提供します。IR が拡張されるにつれて、
各章のアダプタが意味に関する詳細を追加します。

[命令エンコーダ(英語)](isa/README.md)は、第21〜25章の x86-64、ARM、RISC-V の
バイト出力処理と、ARM/RISC-V のテスト用評価器を共有します。
機械命令ノードの選択、レジスタ割り当て、コード配置は各章に残ります。
共通層は具体的なオペランドを受け取り、バイト列を書き出します。

最上位の Makefile は、各章の `tests`、`tags`(または `tag`)、`release`、`lib` ターゲットを実行します。
新しく取得したチェックアウトでは、まず `make lib`、続いて `make tests` を実行してください。

CI は Linux と JDK 21 で `make lib tests CTAGS=` を実行します。
Make のターゲットは、それらを使うテストの実行前に、第25章のネイティブランタイムと
`sys` ライブラリもビルドします。Maven の Java ビルドだけでは、これらの前提となる成果物は生成されません。

[章へのバックポート一覧(英語)](docs/chapter-backports.md)には、提案された小さな修正と
各章のテスト・レビューワークフローを記録しています。大規模なアーキテクチャ変更は、そこで別に管理します。
第10〜14章は現在、メモリ全体、必要時のエイリアス分割、参照、GCM、数値型の順に構成されています。
このメモリ表現は第25章まで引き継がれています。

メモリに関する章だけをビルドしてテストするには、次を実行します。

```sh
make lib tests release CHAPTERS="chapter10 chapter11 chapter12"
```

ルートの Maven リアクターはすべての章を含みます。
第10〜14章には、共通の `graph` と `print` モジュールに依存する、移植可能な IDEA モジュール記述子があります。
Make と直線的な履歴を作るワークフローは、番号付きの章ディレクトリを検出します。