Slide 1

Slide 1 text

Cコンパイラ作成入門 2025/04/12 PHPカンファレンス小田原2025 From $this to *this — A Journey Down the Stack 低レイヤを知りたいPHPerのための 長谷川 智希 @tomzoh

Slide 2

Slide 2 text

௕୩઒ஐر ͸͕ͤΘ ͱ΋͖ @tomzoh http://www.dgcircus.com デジタルサーカス株式会社 副団長CTO ॴଐ ٕज़ΧϯϑΝϨϯεओ࠻ دߘɾஶॻ 来たれ!PHPer!We are hiring! 𝕏

Slide 3

Slide 3 text

௕୩઒ஐر ͸͕ͤΘ ͱ΋͖ @tomzoh ٕज़ΧϯϑΝϨϯεӡӦࢀՃ ֤छϓϩάϥϜ։ൃ   $16 ϨτϩήʔϜػ ిࢠ޻࡞  Ϗʔϧ αοΧʔ؍ઓ ϨϯλϧΧʔτϨʔε ʜ ϥΠϑϫʔΫ 𝕏

Slide 4

Slide 4 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラ作成入門 4 From $this to *this — A Journey Down the Stack 低レイヤを知りたいPHPerのための

Slide 5

Slide 5 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 なぜCコンパイラか • ここ数年、低レイヤ大好き 5

Slide 6

Slide 6 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 なぜCコンパイラか • ここ数年、低レイヤ大好き • CPU, エミュレータ, コンパイラ, ハードウェア, … 5

Slide 7

Slide 7 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 なぜCコンパイラか • ここ数年、低レイヤ大好き • CPU, エミュレータ, コンパイラ, ハードウェア, … • どれも楽しいけど今日はコンパイラの話 5

Slide 8

Slide 8 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 なぜCコンパイラか • ここ数年、低レイヤ大好き • CPU, エミュレータ, コンパイラ, ハードウェア, … • どれも楽しいけど今日はコンパイラの話 • コンパイラは実はシンプル 5

Slide 9

Slide 9 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 なぜCコンパイラか • ここ数年、低レイヤ大好き • CPU, エミュレータ, コンパイラ, ハードウェア, … • どれも楽しいけど今日はコンパイラの話 • コンパイラは実はシンプル • 実行環境の実装を含まない 5

Slide 10

Slide 10 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 なぜCコンパイラか • ここ数年、低レイヤ大好き • CPU, エミュレータ, コンパイラ, ハードウェア, … • どれも楽しいけど今日はコンパイラの話 • コンパイラは実はシンプル • 実行環境の実装を含まない • CPU, エミュレータ, インタプリタは実行環境 5

Slide 11

Slide 11 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 なぜCコンパイラか • ここ数年、低レイヤ大好き • CPU, エミュレータ, コンパイラ, ハードウェア, … • どれも楽しいけど今日はコンパイラの話 • コンパイラは実はシンプル • 実行環境の実装を含まない • CPU, エミュレータ, インタプリタは実行環境 • テキスト to テキストのコンバータ 5

Slide 12

Slide 12 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 なぜCコンパイラか • ここ数年、低レイヤ大好き • CPU, エミュレータ, コンパイラ, ハードウェア, … • どれも楽しいけど今日はコンパイラの話 • コンパイラは実はシンプル • 実行環境の実装を含まない • CPU, エミュレータ, インタプリタは実行環境 • テキスト to テキストのコンバータ • CPU, OS, プログラミング言語実装といった低レイヤぽい要素はキッチリ含む 5

Slide 13

Slide 13 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 なぜCコンパイラか • ここ数年、低レイヤ大好き • CPU, エミュレータ, コンパイラ, ハードウェア, … • どれも楽しいけど今日はコンパイラの話 • コンパイラは実はシンプル • 実行環境の実装を含まない • CPU, エミュレータ, インタプリタは実行環境 • テキスト to テキストのコンバータ • CPU, OS, プログラミング言語実装といった低レイヤぽい要素はキッチリ含む • 低レイヤを知るのにコンパイラはうってつけの教材 5

Slide 14

Slide 14 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 前提知識 6

Slide 15

Slide 15 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラの動作 7

Slide 16

Slide 16 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラの動作 • みなさんも一度くらいやったことありそうな Hello, World 7

Slide 17

Slide 17 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラの動作 • みなさんも一度くらいやったことありそうな Hello, World • gcc hello.c → a.out 7

Slide 18

Slide 18 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラの動作 • みなさんも一度くらいやったことありそうな Hello, World • gcc hello.c → a.out • gcc Cコンパイラ 7

Slide 19

Slide 19 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラの動作 • みなさんも一度くらいやったことありそうな Hello, World • gcc hello.c → a.out • gcc Cコンパイラ • hello.c C言語のソースコード(ファイル) 7

Slide 20

Slide 20 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラの動作 • みなさんも一度くらいやったことありそうな Hello, World • gcc hello.c → a.out • gcc Cコンパイラ • hello.c C言語のソースコード(ファイル) • a.out 実行ファイル 7

Slide 21

Slide 21 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラの動作 • みなさんも一度くらいやったことありそうな Hello, World • gcc hello.c → a.out • gcc Cコンパイラ • hello.c C言語のソースコード(ファイル) • a.out 実行ファイル • CコンパイラがC言語のソースコードを実行ファイルに変換している様に見える 7

Slide 22

Slide 22 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラの動作 • みなさんも一度くらいやったことありそうな Hello, World • gcc hello.c → a.out • gcc Cコンパイラ • hello.c C言語のソースコード(ファイル) • a.out 実行ファイル • CコンパイラがC言語のソースコードを実行ファイルに変換している様に見える • 実は2段階で変換している 7

Slide 23

Slide 23 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラの動作 • みなさんも一度くらいやったことありそうな Hello, World • gcc hello.c → a.out • gcc Cコンパイラ • hello.c C言語のソースコード(ファイル) • a.out 実行ファイル • CコンパイラがC言語のソースコードを実行ファイルに変換している様に見える • 実は2段階で変換している • コンパイラ: C言語のソースコード → アセンブリ言語のソースコード 7

Slide 24

Slide 24 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラの動作 • みなさんも一度くらいやったことありそうな Hello, World • gcc hello.c → a.out • gcc Cコンパイラ • hello.c C言語のソースコード(ファイル) • a.out 実行ファイル • CコンパイラがC言語のソースコードを実行ファイルに変換している様に見える • 実は2段階で変換している • コンパイラ: C言語のソースコード → アセンブリ言語のソースコード • アセンブラ: アセンブリ言語のソースコード → 機械語(マシン語)の実行ファイル 7

Slide 25

Slide 25 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 機械語(マシン語) 8

Slide 26

Slide 26 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 機械語(マシン語) • CPUで直接実行できる唯一の言語 8

Slide 27

Slide 27 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 機械語(マシン語) • CPUで直接実行できる唯一の言語 • Intel CPUの機械語, Apple Siliconの機械語 のようにCPUごとに仕様が違う 8

Slide 28

Slide 28 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 機械語(マシン語) • CPUで直接実行できる唯一の言語 • Intel CPUの機械語, Apple Siliconの機械語 のようにCPUごとに仕様が違う • 言語と言うにはめちゃんこシンプルなモノ 8

Slide 29

Slide 29 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 機械語(マシン語) • CPUで直接実行できる唯一の言語 • Intel CPUの機械語, Apple Siliconの機械語 のようにCPUごとに仕様が違う • 言語と言うにはめちゃんこシンプルなモノ • if(){} とか while(){} みたいなのは無い 8

Slide 30

Slide 30 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 機械語(マシン語) • CPUで直接実行できる唯一の言語 • Intel CPUの機械語, Apple Siliconの機械語 のようにCPUごとに仕様が違う • 言語と言うにはめちゃんこシンプルなモノ • if(){} とか while(){} みたいなのは無い • 条件付きジャンプ(goto)が制御構造のメイン 8

Slide 31

Slide 31 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 機械語(マシン語) • CPUで直接実行できる唯一の言語 • Intel CPUの機械語, Apple Siliconの機械語 のようにCPUごとに仕様が違う • 言語と言うにはめちゃんこシンプルなモノ • if(){} とか while(){} みたいなのは無い • 条件付きジャンプ(goto)が制御構造のメイン • レジスタという変数のようなものを持っている 8

Slide 32

Slide 32 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 機械語(マシン語) • CPUで直接実行できる唯一の言語 • Intel CPUの機械語, Apple Siliconの機械語 のようにCPUごとに仕様が違う • 言語と言うにはめちゃんこシンプルなモノ • if(){} とか while(){} みたいなのは無い • 条件付きジャンプ(goto)が制御構造のメイン • レジスタという変数のようなものを持っている • 今日の話で重要なのは rax レジスタ 8

Slide 33

Slide 33 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 機械語(マシン語) • CPUで直接実行できる唯一の言語 • Intel CPUの機械語, Apple Siliconの機械語 のようにCPUごとに仕様が違う • 言語と言うにはめちゃんこシンプルなモノ • if(){} とか while(){} みたいなのは無い • 条件付きジャンプ(goto)が制御構造のメイン • レジスタという変数のようなものを持っている • 今日の話で重要なのは rax レジスタ • (LinuxやmacOSでは)コマンドの実行が終了した時にraxレジスタの内容が コマンドの終了コードになる 8

Slide 34

Slide 34 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 機械語(マシン語) • CPUで直接実行できる唯一の言語 • Intel CPUの機械語, Apple Siliconの機械語 のようにCPUごとに仕様が違う • 言語と言うにはめちゃんこシンプルなモノ • if(){} とか while(){} みたいなのは無い • 条件付きジャンプ(goto)が制御構造のメイン • レジスタという変数のようなものを持っている • 今日の話で重要なのは rax レジスタ • (LinuxやmacOSでは)コマンドの実行が終了した時にraxレジスタの内容が コマンドの終了コードになる • 「0が正常終了、0以外が異常終了」のやつ 8

Slide 35

Slide 35 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 今回作るコンパイラ 9

Slide 36

Slide 36 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 今回作るコンパイラ 9 実行ファイル アセンブリ言語の ソースコード C言語の ソースコード

Slide 37

Slide 37 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 今回作るコンパイラ 9 実行ファイル アセンブリ言語の ソースコード C言語の ソースコード • C言語のソースコードからアセンブリ言語のソースコードに変換するCコンパイラ

Slide 38

Slide 38 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 今回作るコンパイラ 9 実行ファイル アセンブリ言語の ソースコード C言語の ソースコード • C言語のソースコードからアセンブリ言語のソースコードに変換するCコンパイラ • アセンブラ部分は既存のものを使用する

Slide 39

Slide 39 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 今回作るコンパイラ 9 実行ファイル アセンブリ言語の ソースコード C言語の ソースコード • C言語のソースコードからアセンブリ言語のソースコードに変換するCコンパイラ • アセンブラ部分は既存のものを使用する • とてもよくできたCコンパイラ作成入門ドキュメント

Slide 40

Slide 40 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 今回作るコンパイラ 9 実行ファイル アセンブリ言語の ソースコード C言語の ソースコード • C言語のソースコードからアセンブリ言語のソースコードに変換するCコンパイラ • アセンブラ部分は既存のものを使用する • とてもよくできたCコンパイラ作成入門ドキュメント 低レイヤを知りたい人のためのCコンパイラ作成入門 / Rui Ueyamaさん https://www.sigbus.info/compilerbook

Slide 41

Slide 41 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 今回作るコンパイラ 9 実行ファイル アセンブリ言語の ソースコード C言語の ソースコード • C言語のソースコードからアセンブリ言語のソースコードに変換するCコンパイラ • アセンブラ部分は既存のものを使用する • とてもよくできたCコンパイラ作成入門ドキュメント 低レイヤを知りたい人のためのCコンパイラ作成入門 / Rui Ueyamaさん https://www.sigbus.info/compilerbook • だけどC言語でC言語のコンパイラを作るテキストなんだよね〜

Slide 42

Slide 42 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 今回作るコンパイラ 9 実行ファイル アセンブリ言語の ソースコード C言語の ソースコード • C言語のソースコードからアセンブリ言語のソースコードに変換するCコンパイラ • アセンブラ部分は既存のものを使用する • とてもよくできたCコンパイラ作成入門ドキュメント 低レイヤを知りたい人のためのCコンパイラ作成入門 / Rui Ueyamaさん https://www.sigbus.info/compilerbook • だけどC言語でC言語のコンパイラを作るテキストなんだよね〜 • C言語…PHPerの我々にはややハードルが高い

Slide 43

Slide 43 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 今回作るコンパイラ 9 実行ファイル アセンブリ言語の ソースコード C言語の ソースコード • C言語のソースコードからアセンブリ言語のソースコードに変換するCコンパイラ • アセンブラ部分は既存のものを使用する • とてもよくできたCコンパイラ作成入門ドキュメント 低レイヤを知りたい人のためのCコンパイラ作成入門 / Rui Ueyamaさん https://www.sigbus.info/compilerbook • だけどC言語でC言語のコンパイラを作るテキストなんだよね〜 • C言語…PHPerの我々にはややハードルが高い • のでPHPでやる

Slide 44

Slide 44 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 PHPで作るCコンパイラ実装 10

Slide 45

Slide 45 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 PHPで作るCコンパイラ実装 • GitHubでソースコード公開してます 10

Slide 46

Slide 46 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 PHPで作るCコンパイラ実装 • GitHubでソースコード公開してます • hasegawa-tomoki/pcc https://github.com/hasegawa-tomoki/pcc 10

Slide 47

Slide 47 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 PHPで作るCコンパイラ実装 • GitHubでソースコード公開してます • hasegawa-tomoki/pcc https://github.com/hasegawa-tomoki/pcc • 実装済みの機能は /ctests/TestCase/*.c を見て頂けると… 10

Slide 48

Slide 48 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 PHPで作るCコンパイラ実装 • GitHubでソースコード公開してます • hasegawa-tomoki/pcc https://github.com/hasegawa-tomoki/pcc • 実装済みの機能は /ctests/TestCase/*.c を見て頂けると… 10 alignof.c arith.c cast.c compat.c complit.c const.c constexpr.c control.c decl.c enum.c extern.c function.c initializer.c literal.c pointer.c sizeof.c string.c struct.c typedef.c union.c usualconv.c variable.c

Slide 49

Slide 49 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 PHPで作るCコンパイラ実装 • GitHubでソースコード公開してます • hasegawa-tomoki/pcc https://github.com/hasegawa-tomoki/pcc • 実装済みの機能は /ctests/TestCase/*.c を見て頂けると… • ひととおりの変数・関数定義、制御構造は実装済み 10 alignof.c arith.c cast.c compat.c complit.c const.c constexpr.c control.c decl.c enum.c extern.c function.c initializer.c literal.c pointer.c sizeof.c string.c struct.c typedef.c union.c usualconv.c variable.c

Slide 50

Slide 50 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 PHPで作るCコンパイラ実装 • GitHubでソースコード公開してます • hasegawa-tomoki/pcc https://github.com/hasegawa-tomoki/pcc • 実装済みの機能は /ctests/TestCase/*.c を見て頂けると… • ひととおりの変数・関数定義、制御構造は実装済み • 今は float あたりの実装中(つらい) 10 alignof.c arith.c cast.c compat.c complit.c const.c constexpr.c control.c decl.c enum.c extern.c function.c initializer.c literal.c pointer.c sizeof.c string.c struct.c typedef.c union.c usualconv.c variable.c

Slide 51

Slide 51 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 PHPで作るCコンパイラ実装 • GitHubでソースコード公開してます • hasegawa-tomoki/pcc https://github.com/hasegawa-tomoki/pcc • 実装済みの機能は /ctests/TestCase/*.c を見て頂けると… • ひととおりの変数・関数定義、制御構造は実装済み • 今は float あたりの実装中(つらい) • #include 的なのとかマクロとかがこの先にある 10 alignof.c arith.c cast.c compat.c complit.c const.c constexpr.c control.c decl.c enum.c extern.c function.c initializer.c literal.c pointer.c sizeof.c string.c struct.c typedef.c union.c usualconv.c variable.c

Slide 52

Slide 52 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラ作成入門 11 From $this to *this — A Journey Down the Stack 低レイヤを知りたいPHPerのための

Slide 53

Slide 53 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 言語仕様を効率的に実装する工夫 • 今回のCコンパイラは3つの役割にわけてソースコードをコンパイルする 12

Slide 54

Slide 54 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 言語仕様を効率的に実装する工夫 • 今回のCコンパイラは3つの役割にわけてソースコードをコンパイルする • トークナイザ 12

Slide 55

Slide 55 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 言語仕様を効率的に実装する工夫 • 今回のCコンパイラは3つの役割にわけてソースコードをコンパイルする • トークナイザ • パーサ 12

Slide 56

Slide 56 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 言語仕様を効率的に実装する工夫 • 今回のCコンパイラは3つの役割にわけてソースコードをコンパイルする • トークナイザ • パーサ • コードジェネレータ 12

Slide 57

Slide 57 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 言語仕様を効率的に実装する工夫 • 今回のCコンパイラは3つの役割にわけてソースコードをコンパイルする • トークナイザ • パーサ • コードジェネレータ • 世の中のコンパイラはだいたいこの3つの役割で実現されている 12

Slide 58

Slide 58 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 言語仕様を効率的に実装する工夫 • 今回のCコンパイラは3つの役割にわけてソースコードをコンパイルする • トークナイザ • パーサ • コードジェネレータ • 世の中のコンパイラはだいたいこの3つの役割で実現されている • 加減乗除の式を与えられて 計算結果を終了コードとして返す コマンドを作るコンパイラ を作ってみる 12

Slide 59

Slide 59 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 言語仕様を効率的に実装する工夫 • 今回のCコンパイラは3つの役割にわけてソースコードをコンパイルする • トークナイザ • パーサ • コードジェネレータ • 世の中のコンパイラはだいたいこの3つの役割で実現されている • 加減乗除の式を与えられて 計算結果を終了コードとして返す コマンドを作るコンパイラ を作ってみる 12 ➜ php pcc.php "1 + 5 - 2" > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 4

Slide 60

Slide 60 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 トークナイザ 13

Slide 61

Slide 61 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 トークナイザ • ソースコードを分割してトークン化する 13

Slide 62

Slide 62 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 トークナイザ • ソースコードを分割してトークン化する • トークナイズ 13

Slide 63

Slide 63 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 トークナイザ • ソースコードを分割してトークン化する • トークナイズ • 字句解析 13

Slide 64

Slide 64 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 トークナイザ • ソースコードを分割してトークン化する • トークナイズ • 字句解析 • トークンの種類 13

Slide 65

Slide 65 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 トークナイザ • ソースコードを分割してトークン化する • トークナイズ • 字句解析 • トークンの種類 識別子 変数名 関数名 13

Slide 66

Slide 66 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 トークナイザ • ソースコードを分割してトークン化する • トークナイズ • 字句解析 • トークンの種類 識別子 変数名 関数名 記号 != <= += ++ ( ) … 13

Slide 67

Slide 67 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 トークナイザ • ソースコードを分割してトークン化する • トークナイズ • 字句解析 • トークンの種類 識別子 変数名 関数名 記号 != <= += ++ ( ) … キーワード return if else … 13

Slide 68

Slide 68 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 トークナイザ • ソースコードを分割してトークン化する • トークナイズ • 字句解析 • トークンの種類 識別子 変数名 関数名 記号 != <= += ++ ( ) … キーワード return if else … 文字列, 数字 "Hello, World" 30 0xff 1.06e2 … 13

Slide 69

Slide 69 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 トークナイズ例 14

Slide 70

Slide 70 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 トークナイズ例 14 int main(void){ for (int i = 0; i <= 100; i++){ int FizzBuzz = i % 15; int Fizz = i % 3; int Buzz = i % 5; if (i % 15 == 0 && i != 0){ printf("FizzBuzz: %d\n", i); } else if (i % 3 == 0 && i != 0){ printf("Fizz: %d\n", i); } else if (i % 5 == 0 && i != 0){ printf("Buzz: %d\n", i); } else { printf("i: %d\n", i); } } return 0; }

Slide 71

Slide 71 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 トークナイズ例 14 int main(void){ for (int i = 0; i <= 100; i++){ int FizzBuzz = i % 15; int Fizz = i % 3; int Buzz = i % 5; if (i % 15 == 0 && i != 0){ printf("FizzBuzz: %d\n", i); } else if (i % 3 == 0 && i != 0){ printf("Fizz: %d\n", i); } else if (i % 5 == 0 && i != 0){ printf("Buzz: %d\n", i); } else { printf("i: %d\n", i); } } return 0; }

Slide 72

Slide 72 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 トークナイズ例 14 int main(void){ for (int i = 0; i <= 100; i++){ int FizzBuzz = i % 15; int Fizz = i % 3; int Buzz = i % 5; if (i % 15 == 0 && i != 0){ printf("FizzBuzz: %d\n", i); } else if (i % 3 == 0 && i != 0){ printf("Fizz: %d\n", i); } else if (i % 5 == 0 && i != 0){ printf("Buzz: %d\n", i); } else { printf("i: %d\n", i); } } return 0; } KEYWORD int IDENT main RSV ( KEYWORD for KEYWORD int IDENT i NUM 0 RSV ) RSV ( RSV = RSV ; IDENT i NUM 100 RSV <= RSV ; IDENT i RSV ++ RSV ) RSV { KEYWORD void ※ 図は雰囲気です。実際のトークン列とは異なります。

Slide 73

Slide 73 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 パーサ 15

Slide 74

Slide 74 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 パーサ • トークン列から抽象構文木(abstract syntax tree / AST)を作る 15

Slide 75

Slide 75 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 パーサ • トークン列から抽象構文木(abstract syntax tree / AST)を作る • 構文解析 15

Slide 76

Slide 76 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 パーサ • トークン列から抽象構文木(abstract syntax tree / AST)を作る • 構文解析 15 KEYWORD for KEYWORD int IDENT i NUM 0 RSV ( RSV = RSV ; IDENT i NUM 100 RSV <= RSV ; IDENT i RSV ++ RSV ) RSV {

Slide 77

Slide 77 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 パーサ • トークン列から抽象構文木(abstract syntax tree / AST)を作る • 構文解析 15 /%@'03 /%@"44*(/ /%@7"3J /%@/6. JOJU /%@-& DPOE /%@7"3J /%@/6. /%@"44 JOD KEYWORD for KEYWORD int IDENT i NUM 0 RSV ( RSV = RSV ; IDENT i NUM 100 RSV <= RSV ; IDENT i RSV ++ RSV ) RSV { ※ 図は雰囲気です。実際のトークン列/ASTとは異なります。

Slide 78

Slide 78 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 コードジェネレータ 16

Slide 79

Slide 79 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 コードジェネレータ • ASTからアセンブリ言語のソース コードを作る 16

Slide 80

Slide 80 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 コードジェネレータ • ASTからアセンブリ言語のソース コードを作る • ASTのノードタイプごとにアセン ブリ言語に変換していく 16

Slide 81

Slide 81 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 コードジェネレータ • ASTからアセンブリ言語のソース コードを作る • ASTのノードタイプごとにアセン ブリ言語に変換していく 16 .file 1 "-" .local .L..0 .align 1 .data .L..0: .byte 72 ; H .byte 101 ; e .byte 108 ; l .byte 108 ; l .byte 111 ; o .byte 44 ; , .byte 32 ; .byte 87 ; W .byte 111 ; o .byte 114 ; r .byte 108 ; l .byte 100 ; d .byte 46 ; . .byte 0 ; \0 .globl main .text main: push %rbp mov %rsp, %rbp sub $0, %rsp .loc 1 43 lea .L..0(%rip), %rax push %rax pop %rdi mov $0, %rax call printf .L.return.main: mov %rbp, %rsp pop %rbp ret アセンブリ言語のソースコード

Slide 82

Slide 82 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 コードジェネレータ • ASTからアセンブリ言語のソース コードを作る • ASTのノードタイプごとにアセン ブリ言語に変換していく • printf() の羅列 16 .file 1 "-" .local .L..0 .align 1 .data .L..0: .byte 72 ; H .byte 101 ; e .byte 108 ; l .byte 108 ; l .byte 111 ; o .byte 44 ; , .byte 32 ; .byte 87 ; W .byte 111 ; o .byte 114 ; r .byte 108 ; l .byte 100 ; d .byte 46 ; . .byte 0 ; \0 .globl main .text main: push %rbp mov %rsp, %rbp sub $0, %rsp .loc 1 43 lea .L..0(%rip), %rax push %rax pop %rdi mov $0, %rax call printf .L.return.main: mov %rbp, %rsp pop %rbp ret アセンブリ言語のソースコード

Slide 83

Slide 83 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ここまでのまとめ 17 #include int main(){ printf("Hello, World."); } C言語のソースコード • C言語のソースコードをCコンパイラでコンパ イルしてアセンブリ言語のソースコードを作る 実行ファイル アセンブリ言語の ソースコード C言語の ソースコード

Slide 84

Slide 84 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ここまでのまとめ 17 コンパイル #include int main(){ printf("Hello, World."); } C言語のソースコード • C言語のソースコードをCコンパイラでコンパ イルしてアセンブリ言語のソースコードを作る 実行ファイル アセンブリ言語の ソースコード C言語の ソースコード

Slide 85

Slide 85 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ここまでのまとめ 17 コンパイル #include int main(){ printf("Hello, World."); } C言語のソースコード .file 1 "-" .local .L..0 .align 1 .data .L..0: .byte 72 ; H .byte 101 ; e .byte 108 ; l .byte 108 ; l .byte 111 ; o .byte 44 ; , .byte 32 ; .byte 87 ; W .byte 111 ; o .byte 114 ; r .byte 108 ; l .byte 100 ; d .byte 46 ; . .byte 0 ; \0 .globl main .text main: push %rbp mov %rsp, %rbp sub $0, %rsp .loc 1 43 lea .L..0(%rip), %rax push %rax pop %rdi mov $0, %rax call printf .L.return.main: mov %rbp, %rsp pop %rbp ret アセンブリ言語のソースコード • C言語のソースコードをCコンパイラでコンパ イルしてアセンブリ言語のソースコードを作る 実行ファイル アセンブリ言語の ソースコード C言語の ソースコード

Slide 86

Slide 86 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ここまでのまとめ 17 コンパイル #include int main(){ printf("Hello, World."); } C言語のソースコード .file 1 "-" .local .L..0 .align 1 .data .L..0: .byte 72 ; H .byte 101 ; e .byte 108 ; l .byte 108 ; l .byte 111 ; o .byte 44 ; , .byte 32 ; .byte 87 ; W .byte 111 ; o .byte 114 ; r .byte 108 ; l .byte 100 ; d .byte 46 ; . .byte 0 ; \0 .globl main .text main: push %rbp mov %rsp, %rbp sub $0, %rsp .loc 1 43 lea .L..0(%rip), %rax push %rax pop %rdi mov $0, %rax call printf .L.return.main: mov %rbp, %rsp pop %rbp ret アセンブリ言語のソースコード • C言語のソースコードをCコンパイラでコンパ イルしてアセンブリ言語のソースコードを作る • Cコンパイラはトークナイザ, パーサ, コードジ ェネレータの3機能で構成する 実行ファイル アセンブリ言語の ソースコード C言語の ソースコード

Slide 87

Slide 87 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 言語仕様と生成規則 • コンパイラを作るにはトークナイザ、パーサ、コードジェネレータを作れば良い 18

Slide 88

Slide 88 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 言語仕様と生成規則 • コンパイラを作るにはトークナイザ、パーサ、コードジェネレータを作れば良い • トークナイザとコードジェネレータは比較的単純 18

Slide 89

Slide 89 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 言語仕様と生成規則 • コンパイラを作るにはトークナイザ、パーサ、コードジェネレータを作れば良い • トークナイザとコードジェネレータは比較的単純 • パーサは言語仕様そのものであり複雑なのでうかつに作ると言語仕様の拡張・変更に対 応できなくなったりする 18

Slide 90

Slide 90 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 言語仕様と生成規則 • コンパイラを作るにはトークナイザ、パーサ、コードジェネレータを作れば良い • トークナイザとコードジェネレータは比較的単純 • パーサは言語仕様そのものであり複雑なのでうかつに作ると言語仕様の拡張・変更に対 応できなくなったりする • そもそも言語仕様をどう定義する? 18

Slide 91

Slide 91 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 言語仕様と生成規則 • コンパイラを作るにはトークナイザ、パーサ、コードジェネレータを作れば良い • トークナイザとコードジェネレータは比較的単純 • パーサは言語仕様そのものであり複雑なのでうかつに作ると言語仕様の拡張・変更に対 応できなくなったりする • そもそも言語仕様をどう定義する? • 生成規則を使うと良い 18

Slide 92

Slide 92 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 プログラム言語仕様の定義 19

Slide 93

Slide 93 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 EBNF • プログラム言語の生成規則を記述するための記法 EBNF (Extended Backus-Naur form) 20

Slide 94

Slide 94 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 EBNF • プログラム言語の生成規則を記述するための記法 EBNF (Extended Backus-Naur form) 20 expr = num ("+" num | "-" num)* numは数値を表す記号

Slide 95

Slide 95 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 EBNF • プログラム言語の生成規則を記述するための記法 EBNF (Extended Backus-Naur form) 20 expr は num から始まって "+" num または "-" num が0回以上続く expr = num ("+" num | "-" num)* numは数値を表す記号

Slide 96

Slide 96 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 EBNF • プログラム言語の生成規則を記述するための記法 EBNF (Extended Backus-Naur form) 20 expr は num から始まって "+" num または "-" num が0回以上続く expr = num ("+" num | "-" num)* numは数値を表す記号 1 1 + 5 1 + 5 - 2

Slide 97

Slide 97 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 演算の優先順位の表現 21

Slide 98

Slide 98 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 演算の優先順位の表現 21 expr = mul ("+" mul | "-" mul)* mul = num ("*" num | "/" num)*

Slide 99

Slide 99 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 演算の優先順位の表現 21 expr = mul ("+" mul | "-" mul)* mul = num ("*" num | "/" num)* expr を処理するには先に mul を処理する必要がある

Slide 100

Slide 100 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 演算の優先順位の表現 21 expr = mul ("+" mul | "-" mul)* mul = num ("*" num | "/" num)* expr を処理するには先に mul を処理する必要がある ➡ 四則演算の優先順位を表現できた

Slide 101

Slide 101 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 演算の優先順位の表現 21 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" expr = mul ("+" mul | "-" mul)* mul = num ("*" num | "/" num)* expr を処理するには先に mul を処理する必要がある ➡ 四則演算の優先順位を表現できた

Slide 102

Slide 102 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 演算の優先順位の表現 21 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" • 上記で num だったところが primary になった expr = mul ("+" mul | "-" mul)* mul = num ("*" num | "/" num)* expr を処理するには先に mul を処理する必要がある ➡ 四則演算の優先順位を表現できた

Slide 103

Slide 103 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 演算の優先順位の表現 21 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" • 上記で num だったところが primary になった • primary は num or カッコで括られた expr expr = mul ("+" mul | "-" mul)* mul = num ("*" num | "/" num)* expr を処理するには先に mul を処理する必要がある ➡ 四則演算の優先順位を表現できた

Slide 104

Slide 104 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 演算の優先順位の表現 21 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" • 上記で num だったところが primary になった • primary は num or カッコで括られた expr expr = mul ("+" mul | "-" mul)* mul = num ("*" num | "/" num)* expr を処理するには先に mul を処理する必要がある ➡ 四則演算の優先順位を表現できた ➡ カッコの優先順位を表現できた

Slide 105

Slide 105 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 もうちょっと育ったEBNF 22 program = stmt* stmt = "return" expr ";" | "if" "(" expr ")" stmt ("else" stmt)? | "{" compound-stmt | expr-stmt compound-stmt = stmt* "}" expr-stmt = expr? ";" expr = assign assign = equality ("=" assign)? equality = relational ("==" relational | "!=" relational)* relational = add ("<" add | "<=" add | ">" add | ">=" add)* add = mul ("+" mul | "-" mul)* mul = unary ("*" unary | "/" unary)* unary = ("+" | "-") unary | primary primary = "(" expr ")" | ident | number

Slide 106

Slide 106 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 もうちょっと育ったEBNF 22 program = stmt* stmt = "return" expr ";" | "if" "(" expr ")" stmt ("else" stmt)? | "{" compound-stmt | expr-stmt compound-stmt = stmt* "}" expr-stmt = expr? ";" expr = assign assign = equality ("=" assign)? equality = relational ("==" relational | "!=" relational)* relational = add ("<" add | "<=" add | ">" add | ">=" add)* add = mul ("+" mul | "-" mul)* mul = unary ("*" unary | "/" unary)* unary = ("+" | "-") unary | primary primary = "(" expr ")" | ident | number EBNFで言語仕様がすべて表現できる(誇張を含みます)

Slide 107

Slide 107 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 EBNFベースのパーサ実装 23

Slide 108

Slide 108 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ENBFの実装方針 24

Slide 109

Slide 109 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ENBFの実装方針 • EBNFに出てくるワード(非終端記号)を関数1つにマップしていくとパーサが作りやすい 24

Slide 110

Slide 110 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ENBFの実装方針 • EBNFに出てくるワード(非終端記号)を関数1つにマップしていくとパーサが作りやすい 24 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")"

Slide 111

Slide 111 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ENBFの実装方針 • EBNFに出てくるワード(非終端記号)を関数1つにマップしていくとパーサが作りやすい 24 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" • この場合、expr(), mul(), primary(), num() を作る

Slide 112

Slide 112 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ENBFの実装方針 • EBNFに出てくるワード(非終端記号)を関数1つにマップしていくとパーサが作りやすい 24 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" • この場合、expr(), mul(), primary(), num() を作る • それぞれ Node のインスタンスを返す

Slide 113

Slide 113 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ENBFの実装方針 • EBNFに出てくるワード(非終端記号)を関数1つにマップしていくとパーサが作りやすい 24 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" • この場合、expr(), mul(), primary(), num() を作る • それぞれ Node のインスタンスを返す • 一番上の Node (expr) をコードジェネレータに渡す

Slide 114

Slide 114 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 primary() $this->tokenizer トークン列を保持 consume('(') カーソルの場所が ( ならカーソルを進めてtrueを 返す ( でなければfalseを返して何もしない expect(')') カーソルの場所が ) ならカーソルを進める ) でなければエラー newNodeNum(int $num) ノードタイプ ND_NUM のノードを作る 25 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" public function primary(): Node { if ($this->tokenizer->consume('(')){ $node = $this->expr(); $this->tokenizer->expect(')'); return $node; } return Node::newNodeNum( $this->tokenizer->expectNumber()); } expectNumber() カーソルの場所が数値なら数値を返す 数値でなければエラー NodeKind::ND_NUM val = 10

Slide 115

Slide 115 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 primary() $this->tokenizer トークン列を保持 consume('(') カーソルの場所が ( ならカーソルを進めてtrueを 返す ( でなければfalseを返して何もしない expect(')') カーソルの場所が ) ならカーソルを進める ) でなければエラー newNodeNum(int $num) ノードタイプ ND_NUM のノードを作る 25 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" public function primary(): Node { if ($this->tokenizer->consume('(')){ $node = $this->expr(); $this->tokenizer->expect(')'); return $node; } return Node::newNodeNum( $this->tokenizer->expectNumber()); } expectNumber() カーソルの場所が数値なら数値を返す 数値でなければエラー NodeKind::ND_NUM val = 10

Slide 116

Slide 116 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 primary() $this->tokenizer トークン列を保持 consume('(') カーソルの場所が ( ならカーソルを進めてtrueを 返す ( でなければfalseを返して何もしない expect(')') カーソルの場所が ) ならカーソルを進める ) でなければエラー newNodeNum(int $num) ノードタイプ ND_NUM のノードを作る 25 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" public function primary(): Node { if ($this->tokenizer->consume('(')){ $node = $this->expr(); $this->tokenizer->expect(')'); return $node; } return Node::newNodeNum( $this->tokenizer->expectNumber()); } expectNumber() カーソルの場所が数値なら数値を返す 数値でなければエラー NodeKind::ND_NUM val = 10

Slide 117

Slide 117 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 mul() 26 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" public function mul(): Node { $node = $this->primary(); for (;;){ if ($this->tokenizer->consume('*')){ $node = Node::newNode( NodeKind::ND_MUL, $node, $this->primary()); } elseif ($this->tokenizer->consume('/')){ $node = Node::newNode( NodeKind::ND_DIV, $node, $this->primary()); } else { return $node; } } }

Slide 118

Slide 118 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 mul() • primary からはじまる 26 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" public function mul(): Node { $node = $this->primary(); for (;;){ if ($this->tokenizer->consume('*')){ $node = Node::newNode( NodeKind::ND_MUL, $node, $this->primary()); } elseif ($this->tokenizer->consume('/')){ $node = Node::newNode( NodeKind::ND_DIV, $node, $this->primary()); } else { return $node; } } }

Slide 119

Slide 119 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 mul() • primary からはじまる • "*" primary か "/" primary を 0回以上繰り返す 26 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" public function mul(): Node { $node = $this->primary(); for (;;){ if ($this->tokenizer->consume('*')){ $node = Node::newNode( NodeKind::ND_MUL, $node, $this->primary()); } elseif ($this->tokenizer->consume('/')){ $node = Node::newNode( NodeKind::ND_DIV, $node, $this->primary()); } else { return $node; } } }

Slide 120

Slide 120 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 mul() • primary からはじまる • "*" primary か "/" primary を 0回以上繰り返す 26 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" public function mul(): Node { $node = $this->primary(); for (;;){ if ($this->tokenizer->consume('*')){ $node = Node::newNode( NodeKind::ND_MUL, $node, $this->primary()); } elseif ($this->tokenizer->consume('/')){ $node = Node::newNode( NodeKind::ND_DIV, $node, $this->primary()); } else { return $node; } } } public static function newNode( NodeKind $nodeKind, Node $lhs, Node $rhs): Node

Slide 121

Slide 121 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 mul() • primary からはじまる • "*" primary か "/" primary を 0回以上繰り返す 26 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" public function mul(): Node { $node = $this->primary(); for (;;){ if ($this->tokenizer->consume('*')){ $node = Node::newNode( NodeKind::ND_MUL, $node, $this->primary()); } elseif ($this->tokenizer->consume('/')){ $node = Node::newNode( NodeKind::ND_DIV, $node, $this->primary()); } else { return $node; } } } public static function newNode( NodeKind $nodeKind, Node $lhs, Node $rhs): Node NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs 10 * 3

Slide 122

Slide 122 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 expr() 27 public function expr(): Node { $node = $this->mul(); for (;;){ if ($this->tokenizer->consume('+')){ $node = Node::newNode(NodeKind::ND_ADD, $node, $this->mul()); } elseif ($this->tokenizer->consume('-')){ $node = Node::newNode(NodeKind::ND_SUB, $node, $this->mul()); } else { return $node; } } } expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")"

Slide 123

Slide 123 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 expr() • mul からはじまる 27 public function expr(): Node { $node = $this->mul(); for (;;){ if ($this->tokenizer->consume('+')){ $node = Node::newNode(NodeKind::ND_ADD, $node, $this->mul()); } elseif ($this->tokenizer->consume('-')){ $node = Node::newNode(NodeKind::ND_SUB, $node, $this->mul()); } else { return $node; } } } expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")"

Slide 124

Slide 124 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 expr() • mul からはじまる • "+" mul か "-" mul を 0回以上繰り返す 27 public function expr(): Node { $node = $this->mul(); for (;;){ if ($this->tokenizer->consume('+')){ $node = Node::newNode(NodeKind::ND_ADD, $node, $this->mul()); } elseif ($this->tokenizer->consume('-')){ $node = Node::newNode(NodeKind::ND_SUB, $node, $this->mul()); } else { return $node; } } } expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")"

Slide 125

Slide 125 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 expr() • mul からはじまる • "+" mul か "-" mul を 0回以上繰り返す • これで四則演算ができるパーサが 完成 27 public function expr(): Node { $node = $this->mul(); for (;;){ if ($this->tokenizer->consume('+')){ $node = Node::newNode(NodeKind::ND_ADD, $node, $this->mul()); } elseif ($this->tokenizer->consume('-')){ $node = Node::newNode(NodeKind::ND_SUB, $node, $this->mul()); } else { return $node; } } } expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")"

Slide 126

Slide 126 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 expr() • mul からはじまる • "+" mul か "-" mul を 0回以上繰り返す • これで四則演算ができるパーサが 完成 27 public function expr(): Node { $node = $this->mul(); for (;;){ if ($this->tokenizer->consume('+')){ $node = Node::newNode(NodeKind::ND_ADD, $node, $this->mul()); } elseif ($this->tokenizer->consume('-')){ $node = Node::newNode(NodeKind::ND_SUB, $node, $this->mul()); } else { return $node; } } } expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs NodeKind::ND_ADD NodeKind::ND_NUM val = 3 lhs rhs

Slide 127

Slide 127 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 expr() • mul からはじまる • "+" mul か "-" mul を 0回以上繰り返す • これで四則演算ができるパーサが 完成 27 public function expr(): Node { $node = $this->mul(); for (;;){ if ($this->tokenizer->consume('+')){ $node = Node::newNode(NodeKind::ND_ADD, $node, $this->mul()); } elseif ($this->tokenizer->consume('-')){ $node = Node::newNode(NodeKind::ND_SUB, $node, $this->mul()); } else { return $node; } } } expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs NodeKind::ND_ADD NodeKind::ND_NUM val = 3 lhs rhs 10 * 3 + 3

Slide 128

Slide 128 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 コードジェネレータの実装 28

Slide 129

Slide 129 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 コードジェネレータの実装 29 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")"

Slide 130

Slide 130 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 コードジェネレータの実装 29 public static function main( int $argc = null, array $argv = null): int { if ($argc != 2) { printf("引数の個数が正しくありません\n"); return 1; } $tokenizer = new Tokenizer($argv[1]); $tokenizer->tokenize(); $parser = new Ast\Parser($tokenizer); $node = $parser->expr(); printf(".globl main\n"); printf("main:\n"); self::gen($node); printf(" pop %%rax\n"); printf(" ret\n"); return 0; } expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")"

Slide 131

Slide 131 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 コードジェネレータの実装 ① トークナイザ ソースコードをトークン化する 29 public static function main( int $argc = null, array $argv = null): int { if ($argc != 2) { printf("引数の個数が正しくありません\n"); return 1; } $tokenizer = new Tokenizer($argv[1]); $tokenizer->tokenize(); $parser = new Ast\Parser($tokenizer); $node = $parser->expr(); printf(".globl main\n"); printf("main:\n"); self::gen($node); printf(" pop %%rax\n"); printf(" ret\n"); return 0; } expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" 1

Slide 132

Slide 132 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 コードジェネレータの実装 ① トークナイザ ソースコードをトークン化する ② パーサ トークン列を expr としてパースする 29 public static function main( int $argc = null, array $argv = null): int { if ($argc != 2) { printf("引数の個数が正しくありません\n"); return 1; } $tokenizer = new Tokenizer($argv[1]); $tokenizer->tokenize(); $parser = new Ast\Parser($tokenizer); $node = $parser->expr(); printf(".globl main\n"); printf("main:\n"); self::gen($node); printf(" pop %%rax\n"); printf(" ret\n"); return 0; } expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" 2

Slide 133

Slide 133 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 コードジェネレータの実装 ① トークナイザ ソースコードをトークン化する ② パーサ トークン列を expr としてパースする ③ コードジェネレータ 29 public static function main( int $argc = null, array $argv = null): int { if ($argc != 2) { printf("引数の個数が正しくありません\n"); return 1; } $tokenizer = new Tokenizer($argv[1]); $tokenizer->tokenize(); $parser = new Ast\Parser($tokenizer); $node = $parser->expr(); printf(".globl main\n"); printf("main:\n"); self::gen($node); printf(" pop %%rax\n"); printf(" ret\n"); return 0; } expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" 3

Slide 134

Slide 134 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 コードジェネレータの実装 ① トークナイザ ソースコードをトークン化する ② パーサ トークン列を expr としてパースする ③ コードジェネレータ ④ exprノードからアセンブリ言語を作る 29 public static function main( int $argc = null, array $argv = null): int { if ($argc != 2) { printf("引数の個数が正しくありません\n"); return 1; } $tokenizer = new Tokenizer($argv[1]); $tokenizer->tokenize(); $parser = new Ast\Parser($tokenizer); $node = $parser->expr(); printf(".globl main\n"); printf("main:\n"); self::gen($node); printf(" pop %%rax\n"); printf(" ret\n"); return 0; } expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" 3 4

Slide 135

Slide 135 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 gen($node) 30 public static function gen(Node $node): void { if ($node->kind == NodeKind::ND_NUM) { printf(" push \$%d\n", $node->val); return; } self::gen($node->lhs); self::gen($node->rhs); printf(" pop %%rdi\n"); printf(" pop %%rax\n"); switch ($node->kind){ case NodeKind::ND_ADD: printf(" add %%rax, %%rdi\n"); break; case NodeKind::ND_SUB: printf(" sub %%rax, %%rdi\n"); break; case NodeKind::ND_MUL: printf(" imul %%rax, %%rdi\n"); break; case NodeKind::ND_DIV: printf(" cqo\n"); printf(" idiv %%rdi\n"); break; } printf(" push %%rax\n"); }

Slide 136

Slide 136 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 gen($node) • ノードをアセンブリ言語に変換 30 public static function gen(Node $node): void { if ($node->kind == NodeKind::ND_NUM) { printf(" push \$%d\n", $node->val); return; } self::gen($node->lhs); self::gen($node->rhs); printf(" pop %%rdi\n"); printf(" pop %%rax\n"); switch ($node->kind){ case NodeKind::ND_ADD: printf(" add %%rax, %%rdi\n"); break; case NodeKind::ND_SUB: printf(" sub %%rax, %%rdi\n"); break; case NodeKind::ND_MUL: printf(" imul %%rax, %%rdi\n"); break; case NodeKind::ND_DIV: printf(" cqo\n"); printf(" idiv %%rdi\n"); break; } printf(" push %%rax\n"); }

Slide 137

Slide 137 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 gen($node) • ノードをアセンブリ言語に変換 • push / pop 30 public static function gen(Node $node): void { if ($node->kind == NodeKind::ND_NUM) { printf(" push \$%d\n", $node->val); return; } self::gen($node->lhs); self::gen($node->rhs); printf(" pop %%rdi\n"); printf(" pop %%rax\n"); switch ($node->kind){ case NodeKind::ND_ADD: printf(" add %%rax, %%rdi\n"); break; case NodeKind::ND_SUB: printf(" sub %%rax, %%rdi\n"); break; case NodeKind::ND_MUL: printf(" imul %%rax, %%rdi\n"); break; case NodeKind::ND_DIV: printf(" cqo\n"); printf(" idiv %%rdi\n"); break; } printf(" push %%rax\n"); }

Slide 138

Slide 138 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 gen($node) • ノードをアセンブリ言語に変換 • push / pop • スタックに値を積む / 取り出す 30 public static function gen(Node $node): void { if ($node->kind == NodeKind::ND_NUM) { printf(" push \$%d\n", $node->val); return; } self::gen($node->lhs); self::gen($node->rhs); printf(" pop %%rdi\n"); printf(" pop %%rax\n"); switch ($node->kind){ case NodeKind::ND_ADD: printf(" add %%rax, %%rdi\n"); break; case NodeKind::ND_SUB: printf(" sub %%rax, %%rdi\n"); break; case NodeKind::ND_MUL: printf(" imul %%rax, %%rdi\n"); break; case NodeKind::ND_DIV: printf(" cqo\n"); printf(" idiv %%rdi\n"); break; } printf(" push %%rax\n"); }

Slide 139

Slide 139 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 gen($node) • ノードをアセンブリ言語に変換 • push / pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 30 public static function gen(Node $node): void { if ($node->kind == NodeKind::ND_NUM) { printf(" push \$%d\n", $node->val); return; } self::gen($node->lhs); self::gen($node->rhs); printf(" pop %%rdi\n"); printf(" pop %%rax\n"); switch ($node->kind){ case NodeKind::ND_ADD: printf(" add %%rax, %%rdi\n"); break; case NodeKind::ND_SUB: printf(" sub %%rax, %%rdi\n"); break; case NodeKind::ND_MUL: printf(" imul %%rax, %%rdi\n"); break; case NodeKind::ND_DIV: printf(" cqo\n"); printf(" idiv %%rdi\n"); break; } printf(" push %%rax\n"); }

Slide 140

Slide 140 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 gen($node) • ノードをアセンブリ言語に変換 • push / pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 30 public static function gen(Node $node): void { if ($node->kind == NodeKind::ND_NUM) { printf(" push \$%d\n", $node->val); return; } self::gen($node->lhs); self::gen($node->rhs); printf(" pop %%rdi\n"); printf(" pop %%rax\n"); switch ($node->kind){ case NodeKind::ND_ADD: printf(" add %%rax, %%rdi\n"); break; case NodeKind::ND_SUB: printf(" sub %%rax, %%rdi\n"); break; case NodeKind::ND_MUL: printf(" imul %%rax, %%rdi\n"); break; case NodeKind::ND_DIV: printf(" cqo\n"); printf(" idiv %%rdi\n"); break; } printf(" push %%rax\n"); } NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs 10 * 3

Slide 141

Slide 141 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 gen($node) • ノードをアセンブリ言語に変換 • push / pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 30 public static function gen(Node $node): void { if ($node->kind == NodeKind::ND_NUM) { printf(" push \$%d\n", $node->val); return; } self::gen($node->lhs); self::gen($node->rhs); printf(" pop %%rdi\n"); printf(" pop %%rax\n"); switch ($node->kind){ case NodeKind::ND_ADD: printf(" add %%rax, %%rdi\n"); break; case NodeKind::ND_SUB: printf(" sub %%rax, %%rdi\n"); break; case NodeKind::ND_MUL: printf(" imul %%rax, %%rdi\n"); break; case NodeKind::ND_DIV: printf(" cqo\n"); printf(" idiv %%rdi\n"); break; } printf(" push %%rax\n"); } NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs 10 * 3

Slide 142

Slide 142 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 gen($node) • ノードをアセンブリ言語に変換 • push / pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 30 public static function gen(Node $node): void { if ($node->kind == NodeKind::ND_NUM) { printf(" push \$%d\n", $node->val); return; } self::gen($node->lhs); self::gen($node->rhs); printf(" pop %%rdi\n"); printf(" pop %%rax\n"); switch ($node->kind){ case NodeKind::ND_ADD: printf(" add %%rax, %%rdi\n"); break; case NodeKind::ND_SUB: printf(" sub %%rax, %%rdi\n"); break; case NodeKind::ND_MUL: printf(" imul %%rax, %%rdi\n"); break; case NodeKind::ND_DIV: printf(" cqo\n"); printf(" idiv %%rdi\n"); break; } printf(" push %%rax\n"); } NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs 10 * 3 加減乗除ノード

Slide 143

Slide 143 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 gen($node) • ノードをアセンブリ言語に変換 • push / pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 30 public static function gen(Node $node): void { if ($node->kind == NodeKind::ND_NUM) { printf(" push \$%d\n", $node->val); return; } self::gen($node->lhs); self::gen($node->rhs); printf(" pop %%rdi\n"); printf(" pop %%rax\n"); switch ($node->kind){ case NodeKind::ND_ADD: printf(" add %%rax, %%rdi\n"); break; case NodeKind::ND_SUB: printf(" sub %%rax, %%rdi\n"); break; case NodeKind::ND_MUL: printf(" imul %%rax, %%rdi\n"); break; case NodeKind::ND_DIV: printf(" cqo\n"); printf(" idiv %%rdi\n"); break; } printf(" push %%rax\n"); } NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs 10 * 3 加減乗除ノード lhsの処理

Slide 144

Slide 144 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 gen($node) • ノードをアセンブリ言語に変換 • push / pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 30 public static function gen(Node $node): void { if ($node->kind == NodeKind::ND_NUM) { printf(" push \$%d\n", $node->val); return; } self::gen($node->lhs); self::gen($node->rhs); printf(" pop %%rdi\n"); printf(" pop %%rax\n"); switch ($node->kind){ case NodeKind::ND_ADD: printf(" add %%rax, %%rdi\n"); break; case NodeKind::ND_SUB: printf(" sub %%rax, %%rdi\n"); break; case NodeKind::ND_MUL: printf(" imul %%rax, %%rdi\n"); break; case NodeKind::ND_DIV: printf(" cqo\n"); printf(" idiv %%rdi\n"); break; } printf(" push %%rax\n"); } 数字ノード NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs 10 * 3 加減乗除ノード lhsの処理

Slide 145

Slide 145 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 gen($node) • ノードをアセンブリ言語に変換 • push / pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 30 public static function gen(Node $node): void { if ($node->kind == NodeKind::ND_NUM) { printf(" push \$%d\n", $node->val); return; } self::gen($node->lhs); self::gen($node->rhs); printf(" pop %%rdi\n"); printf(" pop %%rax\n"); switch ($node->kind){ case NodeKind::ND_ADD: printf(" add %%rax, %%rdi\n"); break; case NodeKind::ND_SUB: printf(" sub %%rax, %%rdi\n"); break; case NodeKind::ND_MUL: printf(" imul %%rax, %%rdi\n"); break; case NodeKind::ND_DIV: printf(" cqo\n"); printf(" idiv %%rdi\n"); break; } printf(" push %%rax\n"); } 数字ノード NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs 10 * 3 加減乗除ノード 定数をスタックに乗せる lhsの処理

Slide 146

Slide 146 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 gen($node) • ノードをアセンブリ言語に変換 • push / pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 30 public static function gen(Node $node): void { if ($node->kind == NodeKind::ND_NUM) { printf(" push \$%d\n", $node->val); return; } self::gen($node->lhs); self::gen($node->rhs); printf(" pop %%rdi\n"); printf(" pop %%rax\n"); switch ($node->kind){ case NodeKind::ND_ADD: printf(" add %%rax, %%rdi\n"); break; case NodeKind::ND_SUB: printf(" sub %%rax, %%rdi\n"); break; case NodeKind::ND_MUL: printf(" imul %%rax, %%rdi\n"); break; case NodeKind::ND_DIV: printf(" cqo\n"); printf(" idiv %%rdi\n"); break; } printf(" push %%rax\n"); } NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs 10 * 3 加減乗除ノード lhsの処理

Slide 147

Slide 147 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 gen($node) • ノードをアセンブリ言語に変換 • push / pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 30 public static function gen(Node $node): void { if ($node->kind == NodeKind::ND_NUM) { printf(" push \$%d\n", $node->val); return; } self::gen($node->lhs); self::gen($node->rhs); printf(" pop %%rdi\n"); printf(" pop %%rax\n"); switch ($node->kind){ case NodeKind::ND_ADD: printf(" add %%rax, %%rdi\n"); break; case NodeKind::ND_SUB: printf(" sub %%rax, %%rdi\n"); break; case NodeKind::ND_MUL: printf(" imul %%rax, %%rdi\n"); break; case NodeKind::ND_DIV: printf(" cqo\n"); printf(" idiv %%rdi\n"); break; } printf(" push %%rax\n"); } NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs 10 * 3 加減乗除ノード rhsの処理

Slide 148

Slide 148 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 gen($node) • ノードをアセンブリ言語に変換 • push / pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 30 public static function gen(Node $node): void { if ($node->kind == NodeKind::ND_NUM) { printf(" push \$%d\n", $node->val); return; } self::gen($node->lhs); self::gen($node->rhs); printf(" pop %%rdi\n"); printf(" pop %%rax\n"); switch ($node->kind){ case NodeKind::ND_ADD: printf(" add %%rax, %%rdi\n"); break; case NodeKind::ND_SUB: printf(" sub %%rax, %%rdi\n"); break; case NodeKind::ND_MUL: printf(" imul %%rax, %%rdi\n"); break; case NodeKind::ND_DIV: printf(" cqo\n"); printf(" idiv %%rdi\n"); break; } printf(" push %%rax\n"); } NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs 10 * 3 加減乗除ノード スタックから値を 2つ取り出す

Slide 149

Slide 149 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 gen($node) • ノードをアセンブリ言語に変換 • push / pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 30 public static function gen(Node $node): void { if ($node->kind == NodeKind::ND_NUM) { printf(" push \$%d\n", $node->val); return; } self::gen($node->lhs); self::gen($node->rhs); printf(" pop %%rdi\n"); printf(" pop %%rax\n"); switch ($node->kind){ case NodeKind::ND_ADD: printf(" add %%rax, %%rdi\n"); break; case NodeKind::ND_SUB: printf(" sub %%rax, %%rdi\n"); break; case NodeKind::ND_MUL: printf(" imul %%rax, %%rdi\n"); break; case NodeKind::ND_DIV: printf(" cqo\n"); printf(" idiv %%rdi\n"); break; } printf(" push %%rax\n"); } NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs 10 * 3 加減乗除ノード 2つの値を使って 演算する

Slide 150

Slide 150 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 gen($node) • ノードをアセンブリ言語に変換 • push / pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 30 public static function gen(Node $node): void { if ($node->kind == NodeKind::ND_NUM) { printf(" push \$%d\n", $node->val); return; } self::gen($node->lhs); self::gen($node->rhs); printf(" pop %%rdi\n"); printf(" pop %%rax\n"); switch ($node->kind){ case NodeKind::ND_ADD: printf(" add %%rax, %%rdi\n"); break; case NodeKind::ND_SUB: printf(" sub %%rax, %%rdi\n"); break; case NodeKind::ND_MUL: printf(" imul %%rax, %%rdi\n"); break; case NodeKind::ND_DIV: printf(" cqo\n"); printf(" idiv %%rdi\n"); break; } printf(" push %%rax\n"); } NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs 10 * 3 加減乗除ノード 計算結果(raxレジスタ)の値を スタックに乗せる

Slide 151

Slide 151 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 一連の処理 ① トークナイザ ソースコードをトークン化する ② パーサ トークン列を expr としてパースする ③ コードジェネレータ ④ exprノードからアセンブリ言語を作る 31 public static function main( int $argc = null, array $argv = null): int { if ($argc != 2) { printf("引数の個数が正しくありません\n"); return 1; } $tokenizer = new Tokenizer($argv[1]); $tokenizer->tokenize(); $parser = new Ast\Parser($tokenizer); $node = $parser->expr(); printf(".globl main\n"); printf("main:\n"); self::gen($node); printf(" pop %%rax\n"); printf(" ret\n"); return 0; } expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" 3 4

Slide 152

Slide 152 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 一連の処理 ① トークナイザ ソースコードをトークン化する ② パーサ トークン列を expr としてパースする ③ コードジェネレータ ④ exprノードからアセンブリ言語を作る • 生成されたアセンブリ言語では最後に exprノードの結果をスタックに積んでる 31 public static function main( int $argc = null, array $argv = null): int { if ($argc != 2) { printf("引数の個数が正しくありません\n"); return 1; } $tokenizer = new Tokenizer($argv[1]); $tokenizer->tokenize(); $parser = new Ast\Parser($tokenizer); $node = $parser->expr(); printf(".globl main\n"); printf("main:\n"); self::gen($node); printf(" pop %%rax\n"); printf(" ret\n"); return 0; } expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" 3 4

Slide 153

Slide 153 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 一連の処理 ① トークナイザ ソースコードをトークン化する ② パーサ トークン列を expr としてパースする ③ コードジェネレータ ④ exprノードからアセンブリ言語を作る • 生成されたアセンブリ言語では最後に exprノードの結果をスタックに積んでる ⑤ スタックから値を1つ取り出して rax レジスタに入れて終了 31 public static function main( int $argc = null, array $argv = null): int { if ($argc != 2) { printf("引数の個数が正しくありません\n"); return 1; } $tokenizer = new Tokenizer($argv[1]); $tokenizer->tokenize(); $parser = new Ast\Parser($tokenizer); $node = $parser->expr(); printf(".globl main\n"); printf("main:\n"); self::gen($node); printf(" pop %%rax\n"); printf(" ret\n"); return 0; } expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" 3 5 4

Slide 154

Slide 154 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ここまでのあらすじ 32 10 * 3 ソースコード NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs AST .globl main main: push $10 push $3 pop %rdi pop %rax imul %rax, %rdi push %rax pop %rax ret コンパイル結果 NUM 3 RSV * NUM 10 EOF トークン列 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" EBNF

Slide 155

Slide 155 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ここまでのあらすじ EBNFで定義された言語仕様をもとに 32 10 * 3 ソースコード NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs AST .globl main main: push $10 push $3 pop %rdi pop %rax imul %rax, %rdi push %rax pop %rax ret コンパイル結果 NUM 3 RSV * NUM 10 EOF トークン列 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" EBNF

Slide 156

Slide 156 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ここまでのあらすじ EBNFで定義された言語仕様をもとに トークナイザがソースコードをトークン列化 32 10 * 3 ソースコード NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs AST .globl main main: push $10 push $3 pop %rdi pop %rax imul %rax, %rdi push %rax pop %rax ret コンパイル結果 NUM 3 RSV * NUM 10 EOF トークン列 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" EBNF

Slide 157

Slide 157 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ここまでのあらすじ EBNFで定義された言語仕様をもとに トークナイザがソースコードをトークン列化 パーサがAST化して 32 10 * 3 ソースコード NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs AST .globl main main: push $10 push $3 pop %rdi pop %rax imul %rax, %rdi push %rax pop %rax ret コンパイル結果 NUM 3 RSV * NUM 10 EOF トークン列 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" EBNF

Slide 158

Slide 158 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ここまでのあらすじ EBNFで定義された言語仕様をもとに トークナイザがソースコードをトークン列化 パーサがAST化して コードジェネレータがアセンブリ言語ソース化した 32 10 * 3 ソースコード NodeKind::ND_MUL NodeKind::ND_NUM NodeKind::ND_NUM val = 10 val = 3 lhs rhs AST .globl main main: push $10 push $3 pop %rdi pop %rax imul %rax, %rdi push %rax pop %rax ret コンパイル結果 NUM 3 RSV * NUM 10 EOF トークン列 expr = mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" EBNF

Slide 159

Slide 159 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラのゴール • EBNFを少しずつ大きくしていけばCコンパイラは育っていく 33

Slide 160

Slide 160 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラのゴール • EBNFを少しずつ大きくしていけばCコンパイラは育っていく • コンパイラを育てていけばそのうち自分自身をコンパイルできる様になる 33

Slide 161

Slide 161 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラのゴール • EBNFを少しずつ大きくしていけばCコンパイラは育っていく • コンパイラを育てていけばそのうち自分自身をコンパイルできる様になる • セルフホストという 33

Slide 162

Slide 162 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラのゴール • EBNFを少しずつ大きくしていけばCコンパイラは育っていく • コンパイラを育てていけばそのうち自分自身をコンパイルできる様になる • セルフホストという • (趣味の)コンパイラの到達点 33

Slide 163

Slide 163 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラのゴール • EBNFを少しずつ大きくしていけばCコンパイラは育っていく • コンパイラを育てていけばそのうち自分自身をコンパイルできる様になる • セルフホストという • (趣味の)コンパイラの到達点 • 今回はPHPで書いてるのでセルフホストには至らない 33

Slide 164

Slide 164 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラのゴール • EBNFを少しずつ大きくしていけばCコンパイラは育っていく • コンパイラを育てていけばそのうち自分自身をコンパイルできる様になる • セルフホストという • (趣味の)コンパイラの到達点 • 今回はPHPで書いてるのでセルフホストには至らない • …PHPはCで書かれている訳で… 33

Slide 165

Slide 165 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラのゴール • EBNFを少しずつ大きくしていけばCコンパイラは育っていく • コンパイラを育てていけばそのうち自分自身をコンパイルできる様になる • セルフホストという • (趣味の)コンパイラの到達点 • 今回はPHPで書いてるのでセルフホストには至らない • …PHPはCで書かれている訳で… • これでPHPのソースをコンパイル出来たら面白いかも…? 33

Slide 166

Slide 166 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラのゴール • EBNFを少しずつ大きくしていけばCコンパイラは育っていく • コンパイラを育てていけばそのうち自分自身をコンパイルできる様になる • セルフホストという • (趣味の)コンパイラの到達点 • 今回はPHPで書いてるのでセルフホストには至らない • …PHPはCで書かれている訳で… • これでPHPのソースをコンパイル出来たら面白いかも…? • 「PHPでコンパイルしたPHPでCコンパイラを動かして…」の無限ループ 33

Slide 167

Slide 167 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 セルフホストまでの道 34

Slide 168

Slide 168 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 セルフホストまでの道 • chibiccのリポジトリでは合計316コミットある 34

Slide 169

Slide 169 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 セルフホストまでの道 • chibiccのリポジトリでは合計316コミットある 34 90d1f7f Make struct member access to work with `=` and `?:` 982041f Update README b35d148 Add __attribute__((aligned(N)) for struct declaration 44bea4c Add __attribute__((packed)) 395308c redefinition 2ed3fda Add test/thirdparty/cpython.sh 0a5d08c Complete stdatomic.h d69a11d Add _Atomic and atomic ++, -- and op= operators 80ea9d4 Add atomic_exchange ca27455 Add atomic_compare_exchange fb49370 Add scripts to test third-party apps 469f159 Add -Xlinker option d1bc9a4 Add -Wl, option c8df787 Add -L option 4e5de36 Add -shared option 1e9b6dd Add -static option f10bceb [GNU] Add #include_next a6c6622 [GNU] Add "#pragma once" d48d9e5 Add include guard optimization c0f0614 Cache file search results 86785fc Add -fpic and -fPIC options c3edffb Add -MMD option 7aa72e4 Add -MQ option fb5cfe5 Add -MD option db850f3 Add -MT option 57c1d4e Add -MP option 95d5a46 Add -MF option d0c4667 Add -M option f694413 Use hashmap for keyword lookup 655954e Use hashmap for block-scope lookup 30520e5 Use hashmap for macro name lookup 0aad326 Add string hashmap f0c98e0 [GNU] Treat labels-as-values as compile-time constant 4f165ec [GNU] Support labels-as-values 3d5550e [GNU] Support array range designator d90c73b [GNU] Support case ranges e0bf168 Add long double d56dd2f Recognize .a and .so files 8d130ab Emit size and type for symbols c32f0e2 Add -s option bc25279 Add -l option b0109a3 Do not define __STDC_NO_VLA__ 2fa8f48 Support sizeof(typename) where typename is a VLA 07f9010 Add pointer arithmetic for VLA e8667af Add sizeof() for VLA 77275c5 Add alloca() 4064871 Make -E to imply -xc ee0a951 Add -x option 8f5ff07 Add -include option b377284 Add thread-local variable 6d344ed Add -fcommon and -fno-common flags 85e46b1 Add tentative definition 1b99bad Add offsetof 11fc259 Add -idirafter option 6a2dc5a Use __attribute__((format(print, ...))) to find programming errors e5f4ca9 Do not emit static inline functions if referenced by no one 31087f8 Handle inline functions as static functions a253516 Add basic "asm" statement e28a612 [GNU] Add ?: operator with omitted operand aee7891 [GNU] Allow sizeof() 1faab48 Add _Generic 1433b40 [GNU] Add __builtin_types_compatible_p 7d80a51 Add typeof 007e526 [GNU] Support GCC-style variadic macro 74ec9f6 Ignore #pragma 083c275 [GNU] Handle ,##__VA_ARG__ 3381448 Add __VA_OPT__ 3a10c8a [GNU] Add __BASE_FILE__ macro 922604a [GNU] Add __TIMESTAMP__ macro aaf20fb [GNU] Add line marker directive c61c0d0 Add #line 37998be Improve error message for multibyte characters 95eb5b0 Handle struct designator for anonymous struct member 31dc1df Add union designated initializer 67f5834 Add struct designated initializer 691c4fa [GNU] Allow to omit "=" in designated initializers 835cd24 Allow array designators to initialize incomplete arrays c618c3b Add array designated initializer 2b2fa25 Skip UTF-8 BOM markers 2382777 Allow to concatenate regular string literals with L/u/U string literals adb8b98 [GNU] Accept $ as an identifier character 0e5d250 Allow multibyte UTF-8 character in identifier e4491b8 Define __STDC_UTF_{16,32}__ macros 6adba75 Add UTF-32 string literal initializer 36230e0 Add UTF-16 string literal initializer cae061a Add wide string literal c467ee6 Add UTF-32 string literal 9cabe1f Add UTF-16 string literal 57b21fe Add UTF-8 string literal 2dac3af Add UTF-32 character literal 454618c Add UTF-16 character literal a57c661 Accept multibyte character as wide character literal c31886a Add \u and \U escape sequences 74bcec5 Canonicalize newline character 0e77f3d [GNU] Add __COUNTER__ macro e27417f Add __DATE__ and __TIME__ macros c3075b3 Add anonymous struct and union 9c36dd7 Make "main" to implicitly return 0 5257ee0 Make an array of at least 16 bytes long to have alignment of at least 16 bytes 2c91da5 Turn on -Wall compiler flag and fix compiler warnings b1fdddf Ignore -O, -W and -g and other flags 2bdc6b8 Write to an in-memory buffer before writing to an actual output file c302a96 Do not allow to obtain an address of a bitfield 17ea802 Handle zero-width bitfield member 54c2b3b Handle op=-style assignments to bitfields 441a89b Support global struct bitfield initializer cc852fe Add bitfield be8b6f6 Add -U option fc69f5c Add -D option 3f2c2d5 Tokenize numeric tokens as pp-numbers e0b5da3 Dereferencing a function shouldn't do anything 603de50 Add va_copy() b6d3cd0 Allow variadic function to take more than 6 parameters d7bad96 Allow to define a function returning a struct c72df1c Allow to call a fucntion returning a struct d63b1f4 Allow struct argument 5e0f8c4 Allow struct parameter 9021f7f Support passed-on-stack parameters b29f052 Support passed-on-stack arguments 12a9e75 Self-host: including preprocessor, chibicc can compile itself 5322ea8 Add va_arg() 7cbfd11 Add stdarg.h, stdbool.h, stddef.h, stdalign.h and float.h 7746e4e Recognize wide character literal ab4f1e1 Concatenate adjacent string literals 82ba010 [GNU] Add __FUNCTION__ ba6b4b6 Add __func__ dc01f94 Add __VA_ARGS__ 6f17071 Add __FILE__ and __LINE__ 5f5a850 Add predefine macros such as __STDC__ e7fdc2e Add #error a939a7a Add default include paths a1dd621 Add -I option d85fc4f Add #include <...> b33fe0e Support line continuation 8075582 Preserve newline and space during macro expansion a8d76ad Replace remaining identifiers with 0 in macro constexpr 5cb2f89 Add defined() macro operator 769b5a0 Use chibicc's preprocessor for all tests 8f561ae Add macro token-pasting operator (##) 8f6f792 Add macro stringizing operator (#) 1313fc6 Do not expand a token more than once for the same funclike macro c7d7ce0 Allow parenthesized expressions as macro arguments dd4306c Allow empty macro arguments b9ad3e4 Add multi-arity funclike #define dec3b3f Add zero-arity funclike #define 1f80f58 Add #ifdef and #ifndef acce002 Do not expand a token more than once for the same objlike macro 2651448 Expand macros in the #if and #elif argument context 9ad60e4 Add #undef 97d33ad Add objlike #define e7a1857 Add #elif c6e81d2 Add #else aa570f3 Skip nested #if in a skipped #if-clause bf6ff92 Add #if and #endif d138864 Add -E option ec149f6 Skip extra tokens after `#include "..."` d367510 Add #include "..." 146c7b3 Add the null directive 1e1ea39 Add a do-nothing preprocessor 8b726b5 Run "ld" unless -c is given b833cd0 Accept multiple input files 140b433 Run "as" command unless -S is given f3d9613 Split cc1 from compiler driver 53e8103 Add usual arithmetic conversion for function pointer c5953ba Decay a function to a pointer in the func param context d06a8ac Add function pointer 5d15431 Add stage2 build 9bf9612 Add "long double" as an alias for "double" ffea421 Add flonum constant expression e452cf7 Support variadic function with floating-point parameters 8b14859 Implement default argument promotion for float c6b3056 Allow to define a function that takes/returns flonums 8ec1ebf Allow to call a function that takes/returns flonums 0ce1093 Handle flonum for if, while, do, !, ?:, || and && 83f76eb Add flonum +, -, * and / cf9ceec Add flonum ==, !=, < and <= 29de46a Add "float" and "double" local variables and casts 1e57f72 Add floating-point constant 1fad259 Allow to omit parameter name in function declaration 93d1277 Ignore "static" and "const" in array-dimensions b773554 Ignore const, volatile, auto, register, restrict or _Noreturn. 7ba6fe8 Handle unsigned types in the constant expression 6880a39 When comparing two pointers, treat them as unsigned 8b8f3de Use long or ulong instead of int for some expressions aaf1045 Add U, L and LL suffixes 34ab83b Add unsigned integral types 3f59ce7 Add `signed` keyword 197689a Check the number of function arguments 754a24f Add va_start to support variadic functions 58fc861 Allow to call a variadic function dcd4579 Handle a function returning bool, char or short 6a0ed71 Align stack frame to 16 byte boundaries ee252e6 Add do ... while eb85527 Add static global variables 30b3e21 Add return that doesn't take any value 127056d Add compound literals 319772b Add static local variables 310a87e [GNU] Allow a variable as an operand of _Alignof 9df5178 Add _Alignof and _Alignas 2764745 Handle extern declarations in a block 006a45c Add extern 157356c Align global variables 7a1f816 Accept `void` as a parameter list cd688a8 Allow to initialize struct flexible array member 824543b Add flexible array member 3d216e3 Emit uninitialized global data to .bss instead of .data fde464c Allow extraneous comma at the end of enum or initializer list a58958c Allow extraneous braces for scalar initializer efa0f33 Allow parentheses in initializers to be omitted 1eae5ae Handle union initializers for global variable eeb62b6 Add struct initializer for global variable bbfe3f4 Add global initializer for scalar and string 483b194 Handle union initializers for local variables aca19dd Allow to initialize a struct with other struct e9d2c46 Handle struct initializers for local variables 5b95533 Allow to omit array length if an initializer is given 0d71737 Add string literal initializer a754732 Skip excess initializer elements ae0a37d Initialize excess array elements with zero 22dd560 Support local variable initializers 79f5de2 Add constant expression 447ee09 Add ?: operator d0c0cb7 Add <<, >>, <<= and >>= 044d9ae Add switch-case 3c83dfd Add continue statement b3047f2 Add break statement a4be55b Resolve conflict between labels and typedefs 6116cae Add goto and labeled statement 61a1055 Add a notion of an incomplete struct type 7963221 Decay an array to a pointer in the func param context 29ed294 Add a notion of an incomplete array type f30f781 Add && and || 8644006 Add &, |, ^, &=, |= and ^= daa7398 Add % and %= 46a96d6 Add ~ operator 6b88bcb Add ! operator 7df934d Add hexadecimal, octal and binary number literals e8ca48c Add post ++ and -- 47f1937 Add pre ++ and -- 01a94c0 Add +=, -=, *= and /= a4fea2b Allow for-loops to define local variables 736232f Support file-scope functions 48ba265 Add enum aa0accc Add character literal 44bba96 Add _Bool type fdc80bc Handle function argument type conversion 818352a Handle return type conversion 9e211cb Report an error on undefined/undeclared functions 8b430a6 Implement usual arithmetic conversion cfc4fa9 Add type cast cb81a37 Use 32 bit registers for char, short and int 67543ea Make sizeof to accept not only an expression but also a typename a6b82da Add typedef f46370e Add `long long` as an alias for `long` 287906a Handle complex type declarations correctly 8c3503b Add void type 74e3acc Add function declaration a817b23 Add nested type declarators 9d48eef Add short type 43c2f08 Add long type 5831eda Change size of int from 8 to 4 bef0543 Add struct assignment 11e3841 Add union f0a018a Add -> operator e1e831e Support struct tags dfec115 Align local variables 9443e4b Align struct members f814033 Add struct e6307ad Add comma operator 1c91d19 Emit .file and .loc assembler directives 6647ad9 Precompute line number for each token cd832a3 Rewrite tests in shell script in C ca8b243 Handle block scope 6c0a429 Add line and block comments a0388ba Add -o and --help options 7b8528f Refactor -- no functionality change d9ea597 Read code from a file instead of argv[1] 9dae234 [GNU] Add statement expression c2cc1d3 Add \x 699d2b7 Add \ ad7749f Add \a, \b, \t, \n \v, \f, \r and \e 35a0bcd Refactoring: Add a utility function 4cedda2 Add string literal be38d63 Add char type a4d3223 Add global variables 0b76634 Merge Function with Var 3e55caf Add sizeof 648646b Add [] operator 3ce1b2d Add arrays of arrays 8b6395d Add one dimensional arrays aacc0cf Support function definition up to 6 parameters 6cb4220 Support zero-arity function definition 964b1d2 Support function call with up to 6 arguments 30a3992 Support zero-arity function calls b4e82cf Add keyword "int" and make variable definition mandatory a6bc4ab Make pointer arithmetic work 863e2b8 Add unary & and * 3d86277 Add a representative node to each Node to improve error messages 5b142b1 Add LICENSE and README.md 1f3eb34 Add "while" statement f5d480f Add "for" statement 72b8415 Add "if" statement ff8912c Add null statement 18ac283 Add { ... } 6cc1c1f Add "return" statement 482c26b Support multi-letter local variables 1f9f3ad Support single-letter local variables 76cae0a Accept multiple statements separated by semicolons 725badf Split main.c into multiple small files 25b4b85 Add ==, !=, <= and >= operators bf9ab52 Add unary plus and minus 84cfcaf Add *, / and () cc5a6d9 Improve error message a1ab0ff Add a tokenizer to allow space characters between tokens bf7081f Add + and - operators 0522e2d Compile an integer to an exectuable that exits with the given number

Slide 170

Slide 170 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 セルフホストまでの道 • chibiccのリポジトリでは合計316コミットある • pccは138コミットまで進んでる 34 90d1f7f Make struct member access to work with `=` and `?:` 982041f Update README b35d148 Add __attribute__((aligned(N)) for struct declaration 44bea4c Add __attribute__((packed)) 395308c redefinition 2ed3fda Add test/thirdparty/cpython.sh 0a5d08c Complete stdatomic.h d69a11d Add _Atomic and atomic ++, -- and op= operators 80ea9d4 Add atomic_exchange ca27455 Add atomic_compare_exchange fb49370 Add scripts to test third-party apps 469f159 Add -Xlinker option d1bc9a4 Add -Wl, option c8df787 Add -L option 4e5de36 Add -shared option 1e9b6dd Add -static option f10bceb [GNU] Add #include_next a6c6622 [GNU] Add "#pragma once" d48d9e5 Add include guard optimization c0f0614 Cache file search results 86785fc Add -fpic and -fPIC options c3edffb Add -MMD option 7aa72e4 Add -MQ option fb5cfe5 Add -MD option db850f3 Add -MT option 57c1d4e Add -MP option 95d5a46 Add -MF option d0c4667 Add -M option f694413 Use hashmap for keyword lookup 655954e Use hashmap for block-scope lookup 30520e5 Use hashmap for macro name lookup 0aad326 Add string hashmap f0c98e0 [GNU] Treat labels-as-values as compile-time constant 4f165ec [GNU] Support labels-as-values 3d5550e [GNU] Support array range designator d90c73b [GNU] Support case ranges e0bf168 Add long double d56dd2f Recognize .a and .so files 8d130ab Emit size and type for symbols c32f0e2 Add -s option bc25279 Add -l option b0109a3 Do not define __STDC_NO_VLA__ 2fa8f48 Support sizeof(typename) where typename is a VLA 07f9010 Add pointer arithmetic for VLA e8667af Add sizeof() for VLA 77275c5 Add alloca() 4064871 Make -E to imply -xc ee0a951 Add -x option 8f5ff07 Add -include option b377284 Add thread-local variable 6d344ed Add -fcommon and -fno-common flags 85e46b1 Add tentative definition 1b99bad Add offsetof 11fc259 Add -idirafter option 6a2dc5a Use __attribute__((format(print, ...))) to find programming errors e5f4ca9 Do not emit static inline functions if referenced by no one 31087f8 Handle inline functions as static functions a253516 Add basic "asm" statement e28a612 [GNU] Add ?: operator with omitted operand aee7891 [GNU] Allow sizeof() 1faab48 Add _Generic 1433b40 [GNU] Add __builtin_types_compatible_p 7d80a51 Add typeof 007e526 [GNU] Support GCC-style variadic macro 74ec9f6 Ignore #pragma 083c275 [GNU] Handle ,##__VA_ARG__ 3381448 Add __VA_OPT__ 3a10c8a [GNU] Add __BASE_FILE__ macro 922604a [GNU] Add __TIMESTAMP__ macro aaf20fb [GNU] Add line marker directive c61c0d0 Add #line 37998be Improve error message for multibyte characters 95eb5b0 Handle struct designator for anonymous struct member 31dc1df Add union designated initializer 67f5834 Add struct designated initializer 691c4fa [GNU] Allow to omit "=" in designated initializers 835cd24 Allow array designators to initialize incomplete arrays c618c3b Add array designated initializer 2b2fa25 Skip UTF-8 BOM markers 2382777 Allow to concatenate regular string literals with L/u/U string literals adb8b98 [GNU] Accept $ as an identifier character 0e5d250 Allow multibyte UTF-8 character in identifier e4491b8 Define __STDC_UTF_{16,32}__ macros 6adba75 Add UTF-32 string literal initializer 36230e0 Add UTF-16 string literal initializer cae061a Add wide string literal c467ee6 Add UTF-32 string literal 9cabe1f Add UTF-16 string literal 57b21fe Add UTF-8 string literal 2dac3af Add UTF-32 character literal 454618c Add UTF-16 character literal a57c661 Accept multibyte character as wide character literal c31886a Add \u and \U escape sequences 74bcec5 Canonicalize newline character 0e77f3d [GNU] Add __COUNTER__ macro e27417f Add __DATE__ and __TIME__ macros c3075b3 Add anonymous struct and union 9c36dd7 Make "main" to implicitly return 0 5257ee0 Make an array of at least 16 bytes long to have alignment of at least 16 bytes 2c91da5 Turn on -Wall compiler flag and fix compiler warnings b1fdddf Ignore -O, -W and -g and other flags 2bdc6b8 Write to an in-memory buffer before writing to an actual output file c302a96 Do not allow to obtain an address of a bitfield 17ea802 Handle zero-width bitfield member 54c2b3b Handle op=-style assignments to bitfields 441a89b Support global struct bitfield initializer cc852fe Add bitfield be8b6f6 Add -U option fc69f5c Add -D option 3f2c2d5 Tokenize numeric tokens as pp-numbers e0b5da3 Dereferencing a function shouldn't do anything 603de50 Add va_copy() b6d3cd0 Allow variadic function to take more than 6 parameters d7bad96 Allow to define a function returning a struct c72df1c Allow to call a fucntion returning a struct d63b1f4 Allow struct argument 5e0f8c4 Allow struct parameter 9021f7f Support passed-on-stack parameters b29f052 Support passed-on-stack arguments 12a9e75 Self-host: including preprocessor, chibicc can compile itself 5322ea8 Add va_arg() 7cbfd11 Add stdarg.h, stdbool.h, stddef.h, stdalign.h and float.h 7746e4e Recognize wide character literal ab4f1e1 Concatenate adjacent string literals 82ba010 [GNU] Add __FUNCTION__ ba6b4b6 Add __func__ dc01f94 Add __VA_ARGS__ 6f17071 Add __FILE__ and __LINE__ 5f5a850 Add predefine macros such as __STDC__ e7fdc2e Add #error a939a7a Add default include paths a1dd621 Add -I option d85fc4f Add #include <...> b33fe0e Support line continuation 8075582 Preserve newline and space during macro expansion a8d76ad Replace remaining identifiers with 0 in macro constexpr 5cb2f89 Add defined() macro operator 769b5a0 Use chibicc's preprocessor for all tests 8f561ae Add macro token-pasting operator (##) 8f6f792 Add macro stringizing operator (#) 1313fc6 Do not expand a token more than once for the same funclike macro c7d7ce0 Allow parenthesized expressions as macro arguments dd4306c Allow empty macro arguments b9ad3e4 Add multi-arity funclike #define dec3b3f Add zero-arity funclike #define 1f80f58 Add #ifdef and #ifndef acce002 Do not expand a token more than once for the same objlike macro 2651448 Expand macros in the #if and #elif argument context 9ad60e4 Add #undef 97d33ad Add objlike #define e7a1857 Add #elif c6e81d2 Add #else aa570f3 Skip nested #if in a skipped #if-clause bf6ff92 Add #if and #endif d138864 Add -E option ec149f6 Skip extra tokens after `#include "..."` d367510 Add #include "..." 146c7b3 Add the null directive 1e1ea39 Add a do-nothing preprocessor 8b726b5 Run "ld" unless -c is given b833cd0 Accept multiple input files 140b433 Run "as" command unless -S is given f3d9613 Split cc1 from compiler driver 53e8103 Add usual arithmetic conversion for function pointer c5953ba Decay a function to a pointer in the func param context d06a8ac Add function pointer 5d15431 Add stage2 build 9bf9612 Add "long double" as an alias for "double" ffea421 Add flonum constant expression e452cf7 Support variadic function with floating-point parameters 8b14859 Implement default argument promotion for float c6b3056 Allow to define a function that takes/returns flonums 8ec1ebf Allow to call a function that takes/returns flonums 0ce1093 Handle flonum for if, while, do, !, ?:, || and && 83f76eb Add flonum +, -, * and / cf9ceec Add flonum ==, !=, < and <= 29de46a Add "float" and "double" local variables and casts 1e57f72 Add floating-point constant 1fad259 Allow to omit parameter name in function declaration 93d1277 Ignore "static" and "const" in array-dimensions b773554 Ignore const, volatile, auto, register, restrict or _Noreturn. 7ba6fe8 Handle unsigned types in the constant expression 6880a39 When comparing two pointers, treat them as unsigned 8b8f3de Use long or ulong instead of int for some expressions aaf1045 Add U, L and LL suffixes 34ab83b Add unsigned integral types 3f59ce7 Add `signed` keyword 197689a Check the number of function arguments 754a24f Add va_start to support variadic functions 58fc861 Allow to call a variadic function dcd4579 Handle a function returning bool, char or short 6a0ed71 Align stack frame to 16 byte boundaries ee252e6 Add do ... while eb85527 Add static global variables 30b3e21 Add return that doesn't take any value 127056d Add compound literals 319772b Add static local variables 310a87e [GNU] Allow a variable as an operand of _Alignof 9df5178 Add _Alignof and _Alignas 2764745 Handle extern declarations in a block 006a45c Add extern 157356c Align global variables 7a1f816 Accept `void` as a parameter list cd688a8 Allow to initialize struct flexible array member 824543b Add flexible array member 3d216e3 Emit uninitialized global data to .bss instead of .data fde464c Allow extraneous comma at the end of enum or initializer list a58958c Allow extraneous braces for scalar initializer efa0f33 Allow parentheses in initializers to be omitted 1eae5ae Handle union initializers for global variable eeb62b6 Add struct initializer for global variable bbfe3f4 Add global initializer for scalar and string 483b194 Handle union initializers for local variables aca19dd Allow to initialize a struct with other struct e9d2c46 Handle struct initializers for local variables 5b95533 Allow to omit array length if an initializer is given 0d71737 Add string literal initializer a754732 Skip excess initializer elements ae0a37d Initialize excess array elements with zero 22dd560 Support local variable initializers 79f5de2 Add constant expression 447ee09 Add ?: operator d0c0cb7 Add <<, >>, <<= and >>= 044d9ae Add switch-case 3c83dfd Add continue statement b3047f2 Add break statement a4be55b Resolve conflict between labels and typedefs 6116cae Add goto and labeled statement 61a1055 Add a notion of an incomplete struct type 7963221 Decay an array to a pointer in the func param context 29ed294 Add a notion of an incomplete array type f30f781 Add && and || 8644006 Add &, |, ^, &=, |= and ^= daa7398 Add % and %= 46a96d6 Add ~ operator 6b88bcb Add ! operator 7df934d Add hexadecimal, octal and binary number literals e8ca48c Add post ++ and -- 47f1937 Add pre ++ and -- 01a94c0 Add +=, -=, *= and /= a4fea2b Allow for-loops to define local variables 736232f Support file-scope functions 48ba265 Add enum aa0accc Add character literal 44bba96 Add _Bool type fdc80bc Handle function argument type conversion 818352a Handle return type conversion 9e211cb Report an error on undefined/undeclared functions 8b430a6 Implement usual arithmetic conversion cfc4fa9 Add type cast cb81a37 Use 32 bit registers for char, short and int 67543ea Make sizeof to accept not only an expression but also a typename a6b82da Add typedef f46370e Add `long long` as an alias for `long` 287906a Handle complex type declarations correctly 8c3503b Add void type 74e3acc Add function declaration a817b23 Add nested type declarators 9d48eef Add short type 43c2f08 Add long type 5831eda Change size of int from 8 to 4 bef0543 Add struct assignment 11e3841 Add union f0a018a Add -> operator e1e831e Support struct tags dfec115 Align local variables 9443e4b Align struct members f814033 Add struct e6307ad Add comma operator 1c91d19 Emit .file and .loc assembler directives 6647ad9 Precompute line number for each token cd832a3 Rewrite tests in shell script in C ca8b243 Handle block scope 6c0a429 Add line and block comments a0388ba Add -o and --help options 7b8528f Refactor -- no functionality change d9ea597 Read code from a file instead of argv[1] 9dae234 [GNU] Add statement expression c2cc1d3 Add \x 699d2b7 Add \ ad7749f Add \a, \b, \t, \n \v, \f, \r and \e 35a0bcd Refactoring: Add a utility function 4cedda2 Add string literal be38d63 Add char type a4d3223 Add global variables 0b76634 Merge Function with Var 3e55caf Add sizeof 648646b Add [] operator 3ce1b2d Add arrays of arrays 8b6395d Add one dimensional arrays aacc0cf Support function definition up to 6 parameters 6cb4220 Support zero-arity function definition 964b1d2 Support function call with up to 6 arguments 30a3992 Support zero-arity function calls b4e82cf Add keyword "int" and make variable definition mandatory a6bc4ab Make pointer arithmetic work 863e2b8 Add unary & and * 3d86277 Add a representative node to each Node to improve error messages 5b142b1 Add LICENSE and README.md 1f3eb34 Add "while" statement f5d480f Add "for" statement 72b8415 Add "if" statement ff8912c Add null statement 18ac283 Add { ... } 6cc1c1f Add "return" statement 482c26b Support multi-letter local variables 1f9f3ad Support single-letter local variables 76cae0a Accept multiple statements separated by semicolons 725badf Split main.c into multiple small files 25b4b85 Add ==, !=, <= and >= operators bf9ab52 Add unary plus and minus 84cfcaf Add *, / and () cc5a6d9 Improve error message a1ab0ff Add a tokenizer to allow space characters between tokens bf7081f Add + and - operators 0522e2d Compile an integer to an exectuable that exits with the given number イマココ 138/316

Slide 171

Slide 171 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 セルフホストまでの道 • chibiccのリポジトリでは合計316コミットある • pccは138コミットまで進んでる • 196コミットでchibiccとしてはセルフホストできる模様 34 90d1f7f Make struct member access to work with `=` and `?:` 982041f Update README b35d148 Add __attribute__((aligned(N)) for struct declaration 44bea4c Add __attribute__((packed)) 395308c redefinition 2ed3fda Add test/thirdparty/cpython.sh 0a5d08c Complete stdatomic.h d69a11d Add _Atomic and atomic ++, -- and op= operators 80ea9d4 Add atomic_exchange ca27455 Add atomic_compare_exchange fb49370 Add scripts to test third-party apps 469f159 Add -Xlinker option d1bc9a4 Add -Wl, option c8df787 Add -L option 4e5de36 Add -shared option 1e9b6dd Add -static option f10bceb [GNU] Add #include_next a6c6622 [GNU] Add "#pragma once" d48d9e5 Add include guard optimization c0f0614 Cache file search results 86785fc Add -fpic and -fPIC options c3edffb Add -MMD option 7aa72e4 Add -MQ option fb5cfe5 Add -MD option db850f3 Add -MT option 57c1d4e Add -MP option 95d5a46 Add -MF option d0c4667 Add -M option f694413 Use hashmap for keyword lookup 655954e Use hashmap for block-scope lookup 30520e5 Use hashmap for macro name lookup 0aad326 Add string hashmap f0c98e0 [GNU] Treat labels-as-values as compile-time constant 4f165ec [GNU] Support labels-as-values 3d5550e [GNU] Support array range designator d90c73b [GNU] Support case ranges e0bf168 Add long double d56dd2f Recognize .a and .so files 8d130ab Emit size and type for symbols c32f0e2 Add -s option bc25279 Add -l option b0109a3 Do not define __STDC_NO_VLA__ 2fa8f48 Support sizeof(typename) where typename is a VLA 07f9010 Add pointer arithmetic for VLA e8667af Add sizeof() for VLA 77275c5 Add alloca() 4064871 Make -E to imply -xc ee0a951 Add -x option 8f5ff07 Add -include option b377284 Add thread-local variable 6d344ed Add -fcommon and -fno-common flags 85e46b1 Add tentative definition 1b99bad Add offsetof 11fc259 Add -idirafter option 6a2dc5a Use __attribute__((format(print, ...))) to find programming errors e5f4ca9 Do not emit static inline functions if referenced by no one 31087f8 Handle inline functions as static functions a253516 Add basic "asm" statement e28a612 [GNU] Add ?: operator with omitted operand aee7891 [GNU] Allow sizeof() 1faab48 Add _Generic 1433b40 [GNU] Add __builtin_types_compatible_p 7d80a51 Add typeof 007e526 [GNU] Support GCC-style variadic macro 74ec9f6 Ignore #pragma 083c275 [GNU] Handle ,##__VA_ARG__ 3381448 Add __VA_OPT__ 3a10c8a [GNU] Add __BASE_FILE__ macro 922604a [GNU] Add __TIMESTAMP__ macro aaf20fb [GNU] Add line marker directive c61c0d0 Add #line 37998be Improve error message for multibyte characters 95eb5b0 Handle struct designator for anonymous struct member 31dc1df Add union designated initializer 67f5834 Add struct designated initializer 691c4fa [GNU] Allow to omit "=" in designated initializers 835cd24 Allow array designators to initialize incomplete arrays c618c3b Add array designated initializer 2b2fa25 Skip UTF-8 BOM markers 2382777 Allow to concatenate regular string literals with L/u/U string literals adb8b98 [GNU] Accept $ as an identifier character 0e5d250 Allow multibyte UTF-8 character in identifier e4491b8 Define __STDC_UTF_{16,32}__ macros 6adba75 Add UTF-32 string literal initializer 36230e0 Add UTF-16 string literal initializer cae061a Add wide string literal c467ee6 Add UTF-32 string literal 9cabe1f Add UTF-16 string literal 57b21fe Add UTF-8 string literal 2dac3af Add UTF-32 character literal 454618c Add UTF-16 character literal a57c661 Accept multibyte character as wide character literal c31886a Add \u and \U escape sequences 74bcec5 Canonicalize newline character 0e77f3d [GNU] Add __COUNTER__ macro e27417f Add __DATE__ and __TIME__ macros c3075b3 Add anonymous struct and union 9c36dd7 Make "main" to implicitly return 0 5257ee0 Make an array of at least 16 bytes long to have alignment of at least 16 bytes 2c91da5 Turn on -Wall compiler flag and fix compiler warnings b1fdddf Ignore -O, -W and -g and other flags 2bdc6b8 Write to an in-memory buffer before writing to an actual output file c302a96 Do not allow to obtain an address of a bitfield 17ea802 Handle zero-width bitfield member 54c2b3b Handle op=-style assignments to bitfields 441a89b Support global struct bitfield initializer cc852fe Add bitfield be8b6f6 Add -U option fc69f5c Add -D option 3f2c2d5 Tokenize numeric tokens as pp-numbers e0b5da3 Dereferencing a function shouldn't do anything 603de50 Add va_copy() b6d3cd0 Allow variadic function to take more than 6 parameters d7bad96 Allow to define a function returning a struct c72df1c Allow to call a fucntion returning a struct d63b1f4 Allow struct argument 5e0f8c4 Allow struct parameter 9021f7f Support passed-on-stack parameters b29f052 Support passed-on-stack arguments 12a9e75 Self-host: including preprocessor, chibicc can compile itself 5322ea8 Add va_arg() 7cbfd11 Add stdarg.h, stdbool.h, stddef.h, stdalign.h and float.h 7746e4e Recognize wide character literal ab4f1e1 Concatenate adjacent string literals 82ba010 [GNU] Add __FUNCTION__ ba6b4b6 Add __func__ dc01f94 Add __VA_ARGS__ 6f17071 Add __FILE__ and __LINE__ 5f5a850 Add predefine macros such as __STDC__ e7fdc2e Add #error a939a7a Add default include paths a1dd621 Add -I option d85fc4f Add #include <...> b33fe0e Support line continuation 8075582 Preserve newline and space during macro expansion a8d76ad Replace remaining identifiers with 0 in macro constexpr 5cb2f89 Add defined() macro operator 769b5a0 Use chibicc's preprocessor for all tests 8f561ae Add macro token-pasting operator (##) 8f6f792 Add macro stringizing operator (#) 1313fc6 Do not expand a token more than once for the same funclike macro c7d7ce0 Allow parenthesized expressions as macro arguments dd4306c Allow empty macro arguments b9ad3e4 Add multi-arity funclike #define dec3b3f Add zero-arity funclike #define 1f80f58 Add #ifdef and #ifndef acce002 Do not expand a token more than once for the same objlike macro 2651448 Expand macros in the #if and #elif argument context 9ad60e4 Add #undef 97d33ad Add objlike #define e7a1857 Add #elif c6e81d2 Add #else aa570f3 Skip nested #if in a skipped #if-clause bf6ff92 Add #if and #endif d138864 Add -E option ec149f6 Skip extra tokens after `#include "..."` d367510 Add #include "..." 146c7b3 Add the null directive 1e1ea39 Add a do-nothing preprocessor 8b726b5 Run "ld" unless -c is given b833cd0 Accept multiple input files 140b433 Run "as" command unless -S is given f3d9613 Split cc1 from compiler driver 53e8103 Add usual arithmetic conversion for function pointer c5953ba Decay a function to a pointer in the func param context d06a8ac Add function pointer 5d15431 Add stage2 build 9bf9612 Add "long double" as an alias for "double" ffea421 Add flonum constant expression e452cf7 Support variadic function with floating-point parameters 8b14859 Implement default argument promotion for float c6b3056 Allow to define a function that takes/returns flonums 8ec1ebf Allow to call a function that takes/returns flonums 0ce1093 Handle flonum for if, while, do, !, ?:, || and && 83f76eb Add flonum +, -, * and / cf9ceec Add flonum ==, !=, < and <= 29de46a Add "float" and "double" local variables and casts 1e57f72 Add floating-point constant 1fad259 Allow to omit parameter name in function declaration 93d1277 Ignore "static" and "const" in array-dimensions b773554 Ignore const, volatile, auto, register, restrict or _Noreturn. 7ba6fe8 Handle unsigned types in the constant expression 6880a39 When comparing two pointers, treat them as unsigned 8b8f3de Use long or ulong instead of int for some expressions aaf1045 Add U, L and LL suffixes 34ab83b Add unsigned integral types 3f59ce7 Add `signed` keyword 197689a Check the number of function arguments 754a24f Add va_start to support variadic functions 58fc861 Allow to call a variadic function dcd4579 Handle a function returning bool, char or short 6a0ed71 Align stack frame to 16 byte boundaries ee252e6 Add do ... while eb85527 Add static global variables 30b3e21 Add return that doesn't take any value 127056d Add compound literals 319772b Add static local variables 310a87e [GNU] Allow a variable as an operand of _Alignof 9df5178 Add _Alignof and _Alignas 2764745 Handle extern declarations in a block 006a45c Add extern 157356c Align global variables 7a1f816 Accept `void` as a parameter list cd688a8 Allow to initialize struct flexible array member 824543b Add flexible array member 3d216e3 Emit uninitialized global data to .bss instead of .data fde464c Allow extraneous comma at the end of enum or initializer list a58958c Allow extraneous braces for scalar initializer efa0f33 Allow parentheses in initializers to be omitted 1eae5ae Handle union initializers for global variable eeb62b6 Add struct initializer for global variable bbfe3f4 Add global initializer for scalar and string 483b194 Handle union initializers for local variables aca19dd Allow to initialize a struct with other struct e9d2c46 Handle struct initializers for local variables 5b95533 Allow to omit array length if an initializer is given 0d71737 Add string literal initializer a754732 Skip excess initializer elements ae0a37d Initialize excess array elements with zero 22dd560 Support local variable initializers 79f5de2 Add constant expression 447ee09 Add ?: operator d0c0cb7 Add <<, >>, <<= and >>= 044d9ae Add switch-case 3c83dfd Add continue statement b3047f2 Add break statement a4be55b Resolve conflict between labels and typedefs 6116cae Add goto and labeled statement 61a1055 Add a notion of an incomplete struct type 7963221 Decay an array to a pointer in the func param context 29ed294 Add a notion of an incomplete array type f30f781 Add && and || 8644006 Add &, |, ^, &=, |= and ^= daa7398 Add % and %= 46a96d6 Add ~ operator 6b88bcb Add ! operator 7df934d Add hexadecimal, octal and binary number literals e8ca48c Add post ++ and -- 47f1937 Add pre ++ and -- 01a94c0 Add +=, -=, *= and /= a4fea2b Allow for-loops to define local variables 736232f Support file-scope functions 48ba265 Add enum aa0accc Add character literal 44bba96 Add _Bool type fdc80bc Handle function argument type conversion 818352a Handle return type conversion 9e211cb Report an error on undefined/undeclared functions 8b430a6 Implement usual arithmetic conversion cfc4fa9 Add type cast cb81a37 Use 32 bit registers for char, short and int 67543ea Make sizeof to accept not only an expression but also a typename a6b82da Add typedef f46370e Add `long long` as an alias for `long` 287906a Handle complex type declarations correctly 8c3503b Add void type 74e3acc Add function declaration a817b23 Add nested type declarators 9d48eef Add short type 43c2f08 Add long type 5831eda Change size of int from 8 to 4 bef0543 Add struct assignment 11e3841 Add union f0a018a Add -> operator e1e831e Support struct tags dfec115 Align local variables 9443e4b Align struct members f814033 Add struct e6307ad Add comma operator 1c91d19 Emit .file and .loc assembler directives 6647ad9 Precompute line number for each token cd832a3 Rewrite tests in shell script in C ca8b243 Handle block scope 6c0a429 Add line and block comments a0388ba Add -o and --help options 7b8528f Refactor -- no functionality change d9ea597 Read code from a file instead of argv[1] 9dae234 [GNU] Add statement expression c2cc1d3 Add \x 699d2b7 Add \ ad7749f Add \a, \b, \t, \n \v, \f, \r and \e 35a0bcd Refactoring: Add a utility function 4cedda2 Add string literal be38d63 Add char type a4d3223 Add global variables 0b76634 Merge Function with Var 3e55caf Add sizeof 648646b Add [] operator 3ce1b2d Add arrays of arrays 8b6395d Add one dimensional arrays aacc0cf Support function definition up to 6 parameters 6cb4220 Support zero-arity function definition 964b1d2 Support function call with up to 6 arguments 30a3992 Support zero-arity function calls b4e82cf Add keyword "int" and make variable definition mandatory a6bc4ab Make pointer arithmetic work 863e2b8 Add unary & and * 3d86277 Add a representative node to each Node to improve error messages 5b142b1 Add LICENSE and README.md 1f3eb34 Add "while" statement f5d480f Add "for" statement 72b8415 Add "if" statement ff8912c Add null statement 18ac283 Add { ... } 6cc1c1f Add "return" statement 482c26b Support multi-letter local variables 1f9f3ad Support single-letter local variables 76cae0a Accept multiple statements separated by semicolons 725badf Split main.c into multiple small files 25b4b85 Add ==, !=, <= and >= operators bf9ab52 Add unary plus and minus 84cfcaf Add *, / and () cc5a6d9 Improve error message a1ab0ff Add a tokenizer to allow space characters between tokens bf7081f Add + and - operators 0522e2d Compile an integer to an exectuable that exits with the given number chibicc セルフホスト 196/316 イマココ 138/316

Slide 172

Slide 172 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 セルフホストまでの道 • chibiccのリポジトリでは合計316コミットある • pccは138コミットまで進んでる • 196コミットでchibiccとしてはセルフホストできる模様 • 意外と近いな… 34 90d1f7f Make struct member access to work with `=` and `?:` 982041f Update README b35d148 Add __attribute__((aligned(N)) for struct declaration 44bea4c Add __attribute__((packed)) 395308c redefinition 2ed3fda Add test/thirdparty/cpython.sh 0a5d08c Complete stdatomic.h d69a11d Add _Atomic and atomic ++, -- and op= operators 80ea9d4 Add atomic_exchange ca27455 Add atomic_compare_exchange fb49370 Add scripts to test third-party apps 469f159 Add -Xlinker option d1bc9a4 Add -Wl, option c8df787 Add -L option 4e5de36 Add -shared option 1e9b6dd Add -static option f10bceb [GNU] Add #include_next a6c6622 [GNU] Add "#pragma once" d48d9e5 Add include guard optimization c0f0614 Cache file search results 86785fc Add -fpic and -fPIC options c3edffb Add -MMD option 7aa72e4 Add -MQ option fb5cfe5 Add -MD option db850f3 Add -MT option 57c1d4e Add -MP option 95d5a46 Add -MF option d0c4667 Add -M option f694413 Use hashmap for keyword lookup 655954e Use hashmap for block-scope lookup 30520e5 Use hashmap for macro name lookup 0aad326 Add string hashmap f0c98e0 [GNU] Treat labels-as-values as compile-time constant 4f165ec [GNU] Support labels-as-values 3d5550e [GNU] Support array range designator d90c73b [GNU] Support case ranges e0bf168 Add long double d56dd2f Recognize .a and .so files 8d130ab Emit size and type for symbols c32f0e2 Add -s option bc25279 Add -l option b0109a3 Do not define __STDC_NO_VLA__ 2fa8f48 Support sizeof(typename) where typename is a VLA 07f9010 Add pointer arithmetic for VLA e8667af Add sizeof() for VLA 77275c5 Add alloca() 4064871 Make -E to imply -xc ee0a951 Add -x option 8f5ff07 Add -include option b377284 Add thread-local variable 6d344ed Add -fcommon and -fno-common flags 85e46b1 Add tentative definition 1b99bad Add offsetof 11fc259 Add -idirafter option 6a2dc5a Use __attribute__((format(print, ...))) to find programming errors e5f4ca9 Do not emit static inline functions if referenced by no one 31087f8 Handle inline functions as static functions a253516 Add basic "asm" statement e28a612 [GNU] Add ?: operator with omitted operand aee7891 [GNU] Allow sizeof() 1faab48 Add _Generic 1433b40 [GNU] Add __builtin_types_compatible_p 7d80a51 Add typeof 007e526 [GNU] Support GCC-style variadic macro 74ec9f6 Ignore #pragma 083c275 [GNU] Handle ,##__VA_ARG__ 3381448 Add __VA_OPT__ 3a10c8a [GNU] Add __BASE_FILE__ macro 922604a [GNU] Add __TIMESTAMP__ macro aaf20fb [GNU] Add line marker directive c61c0d0 Add #line 37998be Improve error message for multibyte characters 95eb5b0 Handle struct designator for anonymous struct member 31dc1df Add union designated initializer 67f5834 Add struct designated initializer 691c4fa [GNU] Allow to omit "=" in designated initializers 835cd24 Allow array designators to initialize incomplete arrays c618c3b Add array designated initializer 2b2fa25 Skip UTF-8 BOM markers 2382777 Allow to concatenate regular string literals with L/u/U string literals adb8b98 [GNU] Accept $ as an identifier character 0e5d250 Allow multibyte UTF-8 character in identifier e4491b8 Define __STDC_UTF_{16,32}__ macros 6adba75 Add UTF-32 string literal initializer 36230e0 Add UTF-16 string literal initializer cae061a Add wide string literal c467ee6 Add UTF-32 string literal 9cabe1f Add UTF-16 string literal 57b21fe Add UTF-8 string literal 2dac3af Add UTF-32 character literal 454618c Add UTF-16 character literal a57c661 Accept multibyte character as wide character literal c31886a Add \u and \U escape sequences 74bcec5 Canonicalize newline character 0e77f3d [GNU] Add __COUNTER__ macro e27417f Add __DATE__ and __TIME__ macros c3075b3 Add anonymous struct and union 9c36dd7 Make "main" to implicitly return 0 5257ee0 Make an array of at least 16 bytes long to have alignment of at least 16 bytes 2c91da5 Turn on -Wall compiler flag and fix compiler warnings b1fdddf Ignore -O, -W and -g and other flags 2bdc6b8 Write to an in-memory buffer before writing to an actual output file c302a96 Do not allow to obtain an address of a bitfield 17ea802 Handle zero-width bitfield member 54c2b3b Handle op=-style assignments to bitfields 441a89b Support global struct bitfield initializer cc852fe Add bitfield be8b6f6 Add -U option fc69f5c Add -D option 3f2c2d5 Tokenize numeric tokens as pp-numbers e0b5da3 Dereferencing a function shouldn't do anything 603de50 Add va_copy() b6d3cd0 Allow variadic function to take more than 6 parameters d7bad96 Allow to define a function returning a struct c72df1c Allow to call a fucntion returning a struct d63b1f4 Allow struct argument 5e0f8c4 Allow struct parameter 9021f7f Support passed-on-stack parameters b29f052 Support passed-on-stack arguments 12a9e75 Self-host: including preprocessor, chibicc can compile itself 5322ea8 Add va_arg() 7cbfd11 Add stdarg.h, stdbool.h, stddef.h, stdalign.h and float.h 7746e4e Recognize wide character literal ab4f1e1 Concatenate adjacent string literals 82ba010 [GNU] Add __FUNCTION__ ba6b4b6 Add __func__ dc01f94 Add __VA_ARGS__ 6f17071 Add __FILE__ and __LINE__ 5f5a850 Add predefine macros such as __STDC__ e7fdc2e Add #error a939a7a Add default include paths a1dd621 Add -I option d85fc4f Add #include <...> b33fe0e Support line continuation 8075582 Preserve newline and space during macro expansion a8d76ad Replace remaining identifiers with 0 in macro constexpr 5cb2f89 Add defined() macro operator 769b5a0 Use chibicc's preprocessor for all tests 8f561ae Add macro token-pasting operator (##) 8f6f792 Add macro stringizing operator (#) 1313fc6 Do not expand a token more than once for the same funclike macro c7d7ce0 Allow parenthesized expressions as macro arguments dd4306c Allow empty macro arguments b9ad3e4 Add multi-arity funclike #define dec3b3f Add zero-arity funclike #define 1f80f58 Add #ifdef and #ifndef acce002 Do not expand a token more than once for the same objlike macro 2651448 Expand macros in the #if and #elif argument context 9ad60e4 Add #undef 97d33ad Add objlike #define e7a1857 Add #elif c6e81d2 Add #else aa570f3 Skip nested #if in a skipped #if-clause bf6ff92 Add #if and #endif d138864 Add -E option ec149f6 Skip extra tokens after `#include "..."` d367510 Add #include "..." 146c7b3 Add the null directive 1e1ea39 Add a do-nothing preprocessor 8b726b5 Run "ld" unless -c is given b833cd0 Accept multiple input files 140b433 Run "as" command unless -S is given f3d9613 Split cc1 from compiler driver 53e8103 Add usual arithmetic conversion for function pointer c5953ba Decay a function to a pointer in the func param context d06a8ac Add function pointer 5d15431 Add stage2 build 9bf9612 Add "long double" as an alias for "double" ffea421 Add flonum constant expression e452cf7 Support variadic function with floating-point parameters 8b14859 Implement default argument promotion for float c6b3056 Allow to define a function that takes/returns flonums 8ec1ebf Allow to call a function that takes/returns flonums 0ce1093 Handle flonum for if, while, do, !, ?:, || and && 83f76eb Add flonum +, -, * and / cf9ceec Add flonum ==, !=, < and <= 29de46a Add "float" and "double" local variables and casts 1e57f72 Add floating-point constant 1fad259 Allow to omit parameter name in function declaration 93d1277 Ignore "static" and "const" in array-dimensions b773554 Ignore const, volatile, auto, register, restrict or _Noreturn. 7ba6fe8 Handle unsigned types in the constant expression 6880a39 When comparing two pointers, treat them as unsigned 8b8f3de Use long or ulong instead of int for some expressions aaf1045 Add U, L and LL suffixes 34ab83b Add unsigned integral types 3f59ce7 Add `signed` keyword 197689a Check the number of function arguments 754a24f Add va_start to support variadic functions 58fc861 Allow to call a variadic function dcd4579 Handle a function returning bool, char or short 6a0ed71 Align stack frame to 16 byte boundaries ee252e6 Add do ... while eb85527 Add static global variables 30b3e21 Add return that doesn't take any value 127056d Add compound literals 319772b Add static local variables 310a87e [GNU] Allow a variable as an operand of _Alignof 9df5178 Add _Alignof and _Alignas 2764745 Handle extern declarations in a block 006a45c Add extern 157356c Align global variables 7a1f816 Accept `void` as a parameter list cd688a8 Allow to initialize struct flexible array member 824543b Add flexible array member 3d216e3 Emit uninitialized global data to .bss instead of .data fde464c Allow extraneous comma at the end of enum or initializer list a58958c Allow extraneous braces for scalar initializer efa0f33 Allow parentheses in initializers to be omitted 1eae5ae Handle union initializers for global variable eeb62b6 Add struct initializer for global variable bbfe3f4 Add global initializer for scalar and string 483b194 Handle union initializers for local variables aca19dd Allow to initialize a struct with other struct e9d2c46 Handle struct initializers for local variables 5b95533 Allow to omit array length if an initializer is given 0d71737 Add string literal initializer a754732 Skip excess initializer elements ae0a37d Initialize excess array elements with zero 22dd560 Support local variable initializers 79f5de2 Add constant expression 447ee09 Add ?: operator d0c0cb7 Add <<, >>, <<= and >>= 044d9ae Add switch-case 3c83dfd Add continue statement b3047f2 Add break statement a4be55b Resolve conflict between labels and typedefs 6116cae Add goto and labeled statement 61a1055 Add a notion of an incomplete struct type 7963221 Decay an array to a pointer in the func param context 29ed294 Add a notion of an incomplete array type f30f781 Add && and || 8644006 Add &, |, ^, &=, |= and ^= daa7398 Add % and %= 46a96d6 Add ~ operator 6b88bcb Add ! operator 7df934d Add hexadecimal, octal and binary number literals e8ca48c Add post ++ and -- 47f1937 Add pre ++ and -- 01a94c0 Add +=, -=, *= and /= a4fea2b Allow for-loops to define local variables 736232f Support file-scope functions 48ba265 Add enum aa0accc Add character literal 44bba96 Add _Bool type fdc80bc Handle function argument type conversion 818352a Handle return type conversion 9e211cb Report an error on undefined/undeclared functions 8b430a6 Implement usual arithmetic conversion cfc4fa9 Add type cast cb81a37 Use 32 bit registers for char, short and int 67543ea Make sizeof to accept not only an expression but also a typename a6b82da Add typedef f46370e Add `long long` as an alias for `long` 287906a Handle complex type declarations correctly 8c3503b Add void type 74e3acc Add function declaration a817b23 Add nested type declarators 9d48eef Add short type 43c2f08 Add long type 5831eda Change size of int from 8 to 4 bef0543 Add struct assignment 11e3841 Add union f0a018a Add -> operator e1e831e Support struct tags dfec115 Align local variables 9443e4b Align struct members f814033 Add struct e6307ad Add comma operator 1c91d19 Emit .file and .loc assembler directives 6647ad9 Precompute line number for each token cd832a3 Rewrite tests in shell script in C ca8b243 Handle block scope 6c0a429 Add line and block comments a0388ba Add -o and --help options 7b8528f Refactor -- no functionality change d9ea597 Read code from a file instead of argv[1] 9dae234 [GNU] Add statement expression c2cc1d3 Add \x 699d2b7 Add \ ad7749f Add \a, \b, \t, \n \v, \f, \r and \e 35a0bcd Refactoring: Add a utility function 4cedda2 Add string literal be38d63 Add char type a4d3223 Add global variables 0b76634 Merge Function with Var 3e55caf Add sizeof 648646b Add [] operator 3ce1b2d Add arrays of arrays 8b6395d Add one dimensional arrays aacc0cf Support function definition up to 6 parameters 6cb4220 Support zero-arity function definition 964b1d2 Support function call with up to 6 arguments 30a3992 Support zero-arity function calls b4e82cf Add keyword "int" and make variable definition mandatory a6bc4ab Make pointer arithmetic work 863e2b8 Add unary & and * 3d86277 Add a representative node to each Node to improve error messages 5b142b1 Add LICENSE and README.md 1f3eb34 Add "while" statement f5d480f Add "for" statement 72b8415 Add "if" statement ff8912c Add null statement 18ac283 Add { ... } 6cc1c1f Add "return" statement 482c26b Support multi-letter local variables 1f9f3ad Support single-letter local variables 76cae0a Accept multiple statements separated by semicolons 725badf Split main.c into multiple small files 25b4b85 Add ==, !=, <= and >= operators bf9ab52 Add unary plus and minus 84cfcaf Add *, / and () cc5a6d9 Improve error message a1ab0ff Add a tokenizer to allow space characters between tokens bf7081f Add + and - operators 0522e2d Compile an integer to an exectuable that exits with the given number chibicc セルフホスト 196/316 イマココ 138/316

Slide 173

Slide 173 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 セルフホストまでの道 • chibiccのリポジトリでは合計316コミットある • pccは138コミットまで進んでる • 196コミットでchibiccとしてはセルフホストできる模様 • 意外と近いな… • chibiccのフォーク fuhsnn/slimcc ではPHPを コンパイルできるらしい (Rui Ueyamaさん情報) • https://github.com/fuhsnn/slimcc 34 90d1f7f Make struct member access to work with `=` and `?:` 982041f Update README b35d148 Add __attribute__((aligned(N)) for struct declaration 44bea4c Add __attribute__((packed)) 395308c redefinition 2ed3fda Add test/thirdparty/cpython.sh 0a5d08c Complete stdatomic.h d69a11d Add _Atomic and atomic ++, -- and op= operators 80ea9d4 Add atomic_exchange ca27455 Add atomic_compare_exchange fb49370 Add scripts to test third-party apps 469f159 Add -Xlinker option d1bc9a4 Add -Wl, option c8df787 Add -L option 4e5de36 Add -shared option 1e9b6dd Add -static option f10bceb [GNU] Add #include_next a6c6622 [GNU] Add "#pragma once" d48d9e5 Add include guard optimization c0f0614 Cache file search results 86785fc Add -fpic and -fPIC options c3edffb Add -MMD option 7aa72e4 Add -MQ option fb5cfe5 Add -MD option db850f3 Add -MT option 57c1d4e Add -MP option 95d5a46 Add -MF option d0c4667 Add -M option f694413 Use hashmap for keyword lookup 655954e Use hashmap for block-scope lookup 30520e5 Use hashmap for macro name lookup 0aad326 Add string hashmap f0c98e0 [GNU] Treat labels-as-values as compile-time constant 4f165ec [GNU] Support labels-as-values 3d5550e [GNU] Support array range designator d90c73b [GNU] Support case ranges e0bf168 Add long double d56dd2f Recognize .a and .so files 8d130ab Emit size and type for symbols c32f0e2 Add -s option bc25279 Add -l option b0109a3 Do not define __STDC_NO_VLA__ 2fa8f48 Support sizeof(typename) where typename is a VLA 07f9010 Add pointer arithmetic for VLA e8667af Add sizeof() for VLA 77275c5 Add alloca() 4064871 Make -E to imply -xc ee0a951 Add -x option 8f5ff07 Add -include option b377284 Add thread-local variable 6d344ed Add -fcommon and -fno-common flags 85e46b1 Add tentative definition 1b99bad Add offsetof 11fc259 Add -idirafter option 6a2dc5a Use __attribute__((format(print, ...))) to find programming errors e5f4ca9 Do not emit static inline functions if referenced by no one 31087f8 Handle inline functions as static functions a253516 Add basic "asm" statement e28a612 [GNU] Add ?: operator with omitted operand aee7891 [GNU] Allow sizeof() 1faab48 Add _Generic 1433b40 [GNU] Add __builtin_types_compatible_p 7d80a51 Add typeof 007e526 [GNU] Support GCC-style variadic macro 74ec9f6 Ignore #pragma 083c275 [GNU] Handle ,##__VA_ARG__ 3381448 Add __VA_OPT__ 3a10c8a [GNU] Add __BASE_FILE__ macro 922604a [GNU] Add __TIMESTAMP__ macro aaf20fb [GNU] Add line marker directive c61c0d0 Add #line 37998be Improve error message for multibyte characters 95eb5b0 Handle struct designator for anonymous struct member 31dc1df Add union designated initializer 67f5834 Add struct designated initializer 691c4fa [GNU] Allow to omit "=" in designated initializers 835cd24 Allow array designators to initialize incomplete arrays c618c3b Add array designated initializer 2b2fa25 Skip UTF-8 BOM markers 2382777 Allow to concatenate regular string literals with L/u/U string literals adb8b98 [GNU] Accept $ as an identifier character 0e5d250 Allow multibyte UTF-8 character in identifier e4491b8 Define __STDC_UTF_{16,32}__ macros 6adba75 Add UTF-32 string literal initializer 36230e0 Add UTF-16 string literal initializer cae061a Add wide string literal c467ee6 Add UTF-32 string literal 9cabe1f Add UTF-16 string literal 57b21fe Add UTF-8 string literal 2dac3af Add UTF-32 character literal 454618c Add UTF-16 character literal a57c661 Accept multibyte character as wide character literal c31886a Add \u and \U escape sequences 74bcec5 Canonicalize newline character 0e77f3d [GNU] Add __COUNTER__ macro e27417f Add __DATE__ and __TIME__ macros c3075b3 Add anonymous struct and union 9c36dd7 Make "main" to implicitly return 0 5257ee0 Make an array of at least 16 bytes long to have alignment of at least 16 bytes 2c91da5 Turn on -Wall compiler flag and fix compiler warnings b1fdddf Ignore -O, -W and -g and other flags 2bdc6b8 Write to an in-memory buffer before writing to an actual output file c302a96 Do not allow to obtain an address of a bitfield 17ea802 Handle zero-width bitfield member 54c2b3b Handle op=-style assignments to bitfields 441a89b Support global struct bitfield initializer cc852fe Add bitfield be8b6f6 Add -U option fc69f5c Add -D option 3f2c2d5 Tokenize numeric tokens as pp-numbers e0b5da3 Dereferencing a function shouldn't do anything 603de50 Add va_copy() b6d3cd0 Allow variadic function to take more than 6 parameters d7bad96 Allow to define a function returning a struct c72df1c Allow to call a fucntion returning a struct d63b1f4 Allow struct argument 5e0f8c4 Allow struct parameter 9021f7f Support passed-on-stack parameters b29f052 Support passed-on-stack arguments 12a9e75 Self-host: including preprocessor, chibicc can compile itself 5322ea8 Add va_arg() 7cbfd11 Add stdarg.h, stdbool.h, stddef.h, stdalign.h and float.h 7746e4e Recognize wide character literal ab4f1e1 Concatenate adjacent string literals 82ba010 [GNU] Add __FUNCTION__ ba6b4b6 Add __func__ dc01f94 Add __VA_ARGS__ 6f17071 Add __FILE__ and __LINE__ 5f5a850 Add predefine macros such as __STDC__ e7fdc2e Add #error a939a7a Add default include paths a1dd621 Add -I option d85fc4f Add #include <...> b33fe0e Support line continuation 8075582 Preserve newline and space during macro expansion a8d76ad Replace remaining identifiers with 0 in macro constexpr 5cb2f89 Add defined() macro operator 769b5a0 Use chibicc's preprocessor for all tests 8f561ae Add macro token-pasting operator (##) 8f6f792 Add macro stringizing operator (#) 1313fc6 Do not expand a token more than once for the same funclike macro c7d7ce0 Allow parenthesized expressions as macro arguments dd4306c Allow empty macro arguments b9ad3e4 Add multi-arity funclike #define dec3b3f Add zero-arity funclike #define 1f80f58 Add #ifdef and #ifndef acce002 Do not expand a token more than once for the same objlike macro 2651448 Expand macros in the #if and #elif argument context 9ad60e4 Add #undef 97d33ad Add objlike #define e7a1857 Add #elif c6e81d2 Add #else aa570f3 Skip nested #if in a skipped #if-clause bf6ff92 Add #if and #endif d138864 Add -E option ec149f6 Skip extra tokens after `#include "..."` d367510 Add #include "..." 146c7b3 Add the null directive 1e1ea39 Add a do-nothing preprocessor 8b726b5 Run "ld" unless -c is given b833cd0 Accept multiple input files 140b433 Run "as" command unless -S is given f3d9613 Split cc1 from compiler driver 53e8103 Add usual arithmetic conversion for function pointer c5953ba Decay a function to a pointer in the func param context d06a8ac Add function pointer 5d15431 Add stage2 build 9bf9612 Add "long double" as an alias for "double" ffea421 Add flonum constant expression e452cf7 Support variadic function with floating-point parameters 8b14859 Implement default argument promotion for float c6b3056 Allow to define a function that takes/returns flonums 8ec1ebf Allow to call a function that takes/returns flonums 0ce1093 Handle flonum for if, while, do, !, ?:, || and && 83f76eb Add flonum +, -, * and / cf9ceec Add flonum ==, !=, < and <= 29de46a Add "float" and "double" local variables and casts 1e57f72 Add floating-point constant 1fad259 Allow to omit parameter name in function declaration 93d1277 Ignore "static" and "const" in array-dimensions b773554 Ignore const, volatile, auto, register, restrict or _Noreturn. 7ba6fe8 Handle unsigned types in the constant expression 6880a39 When comparing two pointers, treat them as unsigned 8b8f3de Use long or ulong instead of int for some expressions aaf1045 Add U, L and LL suffixes 34ab83b Add unsigned integral types 3f59ce7 Add `signed` keyword 197689a Check the number of function arguments 754a24f Add va_start to support variadic functions 58fc861 Allow to call a variadic function dcd4579 Handle a function returning bool, char or short 6a0ed71 Align stack frame to 16 byte boundaries ee252e6 Add do ... while eb85527 Add static global variables 30b3e21 Add return that doesn't take any value 127056d Add compound literals 319772b Add static local variables 310a87e [GNU] Allow a variable as an operand of _Alignof 9df5178 Add _Alignof and _Alignas 2764745 Handle extern declarations in a block 006a45c Add extern 157356c Align global variables 7a1f816 Accept `void` as a parameter list cd688a8 Allow to initialize struct flexible array member 824543b Add flexible array member 3d216e3 Emit uninitialized global data to .bss instead of .data fde464c Allow extraneous comma at the end of enum or initializer list a58958c Allow extraneous braces for scalar initializer efa0f33 Allow parentheses in initializers to be omitted 1eae5ae Handle union initializers for global variable eeb62b6 Add struct initializer for global variable bbfe3f4 Add global initializer for scalar and string 483b194 Handle union initializers for local variables aca19dd Allow to initialize a struct with other struct e9d2c46 Handle struct initializers for local variables 5b95533 Allow to omit array length if an initializer is given 0d71737 Add string literal initializer a754732 Skip excess initializer elements ae0a37d Initialize excess array elements with zero 22dd560 Support local variable initializers 79f5de2 Add constant expression 447ee09 Add ?: operator d0c0cb7 Add <<, >>, <<= and >>= 044d9ae Add switch-case 3c83dfd Add continue statement b3047f2 Add break statement a4be55b Resolve conflict between labels and typedefs 6116cae Add goto and labeled statement 61a1055 Add a notion of an incomplete struct type 7963221 Decay an array to a pointer in the func param context 29ed294 Add a notion of an incomplete array type f30f781 Add && and || 8644006 Add &, |, ^, &=, |= and ^= daa7398 Add % and %= 46a96d6 Add ~ operator 6b88bcb Add ! operator 7df934d Add hexadecimal, octal and binary number literals e8ca48c Add post ++ and -- 47f1937 Add pre ++ and -- 01a94c0 Add +=, -=, *= and /= a4fea2b Allow for-loops to define local variables 736232f Support file-scope functions 48ba265 Add enum aa0accc Add character literal 44bba96 Add _Bool type fdc80bc Handle function argument type conversion 818352a Handle return type conversion 9e211cb Report an error on undefined/undeclared functions 8b430a6 Implement usual arithmetic conversion cfc4fa9 Add type cast cb81a37 Use 32 bit registers for char, short and int 67543ea Make sizeof to accept not only an expression but also a typename a6b82da Add typedef f46370e Add `long long` as an alias for `long` 287906a Handle complex type declarations correctly 8c3503b Add void type 74e3acc Add function declaration a817b23 Add nested type declarators 9d48eef Add short type 43c2f08 Add long type 5831eda Change size of int from 8 to 4 bef0543 Add struct assignment 11e3841 Add union f0a018a Add -> operator e1e831e Support struct tags dfec115 Align local variables 9443e4b Align struct members f814033 Add struct e6307ad Add comma operator 1c91d19 Emit .file and .loc assembler directives 6647ad9 Precompute line number for each token cd832a3 Rewrite tests in shell script in C ca8b243 Handle block scope 6c0a429 Add line and block comments a0388ba Add -o and --help options 7b8528f Refactor -- no functionality change d9ea597 Read code from a file instead of argv[1] 9dae234 [GNU] Add statement expression c2cc1d3 Add \x 699d2b7 Add \ ad7749f Add \a, \b, \t, \n \v, \f, \r and \e 35a0bcd Refactoring: Add a utility function 4cedda2 Add string literal be38d63 Add char type a4d3223 Add global variables 0b76634 Merge Function with Var 3e55caf Add sizeof 648646b Add [] operator 3ce1b2d Add arrays of arrays 8b6395d Add one dimensional arrays aacc0cf Support function definition up to 6 parameters 6cb4220 Support zero-arity function definition 964b1d2 Support function call with up to 6 arguments 30a3992 Support zero-arity function calls b4e82cf Add keyword "int" and make variable definition mandatory a6bc4ab Make pointer arithmetic work 863e2b8 Add unary & and * 3d86277 Add a representative node to each Node to improve error messages 5b142b1 Add LICENSE and README.md 1f3eb34 Add "while" statement f5d480f Add "for" statement 72b8415 Add "if" statement ff8912c Add null statement 18ac283 Add { ... } 6cc1c1f Add "return" statement 482c26b Support multi-letter local variables 1f9f3ad Support single-letter local variables 76cae0a Accept multiple statements separated by semicolons 725badf Split main.c into multiple small files 25b4b85 Add ==, !=, <= and >= operators bf9ab52 Add unary plus and minus 84cfcaf Add *, / and () cc5a6d9 Improve error message a1ab0ff Add a tokenizer to allow space characters between tokens bf7081f Add + and - operators 0522e2d Compile an integer to an exectuable that exits with the given number chibicc セルフホスト 196/316 イマココ 138/316

Slide 174

Slide 174 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 セルフホストまでの道 • chibiccのリポジトリでは合計316コミットある • pccは138コミットまで進んでる • 196コミットでchibiccとしてはセルフホストできる模様 • 意外と近いな… • chibiccのフォーク fuhsnn/slimcc ではPHPを コンパイルできるらしい (Rui Ueyamaさん情報) • https://github.com/fuhsnn/slimcc • chibiccの316コミットにさらに564コミット積んでるんすけど… 34 90d1f7f Make struct member access to work with `=` and `?:` 982041f Update README b35d148 Add __attribute__((aligned(N)) for struct declaration 44bea4c Add __attribute__((packed)) 395308c redefinition 2ed3fda Add test/thirdparty/cpython.sh 0a5d08c Complete stdatomic.h d69a11d Add _Atomic and atomic ++, -- and op= operators 80ea9d4 Add atomic_exchange ca27455 Add atomic_compare_exchange fb49370 Add scripts to test third-party apps 469f159 Add -Xlinker option d1bc9a4 Add -Wl, option c8df787 Add -L option 4e5de36 Add -shared option 1e9b6dd Add -static option f10bceb [GNU] Add #include_next a6c6622 [GNU] Add "#pragma once" d48d9e5 Add include guard optimization c0f0614 Cache file search results 86785fc Add -fpic and -fPIC options c3edffb Add -MMD option 7aa72e4 Add -MQ option fb5cfe5 Add -MD option db850f3 Add -MT option 57c1d4e Add -MP option 95d5a46 Add -MF option d0c4667 Add -M option f694413 Use hashmap for keyword lookup 655954e Use hashmap for block-scope lookup 30520e5 Use hashmap for macro name lookup 0aad326 Add string hashmap f0c98e0 [GNU] Treat labels-as-values as compile-time constant 4f165ec [GNU] Support labels-as-values 3d5550e [GNU] Support array range designator d90c73b [GNU] Support case ranges e0bf168 Add long double d56dd2f Recognize .a and .so files 8d130ab Emit size and type for symbols c32f0e2 Add -s option bc25279 Add -l option b0109a3 Do not define __STDC_NO_VLA__ 2fa8f48 Support sizeof(typename) where typename is a VLA 07f9010 Add pointer arithmetic for VLA e8667af Add sizeof() for VLA 77275c5 Add alloca() 4064871 Make -E to imply -xc ee0a951 Add -x option 8f5ff07 Add -include option b377284 Add thread-local variable 6d344ed Add -fcommon and -fno-common flags 85e46b1 Add tentative definition 1b99bad Add offsetof 11fc259 Add -idirafter option 6a2dc5a Use __attribute__((format(print, ...))) to find programming errors e5f4ca9 Do not emit static inline functions if referenced by no one 31087f8 Handle inline functions as static functions a253516 Add basic "asm" statement e28a612 [GNU] Add ?: operator with omitted operand aee7891 [GNU] Allow sizeof() 1faab48 Add _Generic 1433b40 [GNU] Add __builtin_types_compatible_p 7d80a51 Add typeof 007e526 [GNU] Support GCC-style variadic macro 74ec9f6 Ignore #pragma 083c275 [GNU] Handle ,##__VA_ARG__ 3381448 Add __VA_OPT__ 3a10c8a [GNU] Add __BASE_FILE__ macro 922604a [GNU] Add __TIMESTAMP__ macro aaf20fb [GNU] Add line marker directive c61c0d0 Add #line 37998be Improve error message for multibyte characters 95eb5b0 Handle struct designator for anonymous struct member 31dc1df Add union designated initializer 67f5834 Add struct designated initializer 691c4fa [GNU] Allow to omit "=" in designated initializers 835cd24 Allow array designators to initialize incomplete arrays c618c3b Add array designated initializer 2b2fa25 Skip UTF-8 BOM markers 2382777 Allow to concatenate regular string literals with L/u/U string literals adb8b98 [GNU] Accept $ as an identifier character 0e5d250 Allow multibyte UTF-8 character in identifier e4491b8 Define __STDC_UTF_{16,32}__ macros 6adba75 Add UTF-32 string literal initializer 36230e0 Add UTF-16 string literal initializer cae061a Add wide string literal c467ee6 Add UTF-32 string literal 9cabe1f Add UTF-16 string literal 57b21fe Add UTF-8 string literal 2dac3af Add UTF-32 character literal 454618c Add UTF-16 character literal a57c661 Accept multibyte character as wide character literal c31886a Add \u and \U escape sequences 74bcec5 Canonicalize newline character 0e77f3d [GNU] Add __COUNTER__ macro e27417f Add __DATE__ and __TIME__ macros c3075b3 Add anonymous struct and union 9c36dd7 Make "main" to implicitly return 0 5257ee0 Make an array of at least 16 bytes long to have alignment of at least 16 bytes 2c91da5 Turn on -Wall compiler flag and fix compiler warnings b1fdddf Ignore -O, -W and -g and other flags 2bdc6b8 Write to an in-memory buffer before writing to an actual output file c302a96 Do not allow to obtain an address of a bitfield 17ea802 Handle zero-width bitfield member 54c2b3b Handle op=-style assignments to bitfields 441a89b Support global struct bitfield initializer cc852fe Add bitfield be8b6f6 Add -U option fc69f5c Add -D option 3f2c2d5 Tokenize numeric tokens as pp-numbers e0b5da3 Dereferencing a function shouldn't do anything 603de50 Add va_copy() b6d3cd0 Allow variadic function to take more than 6 parameters d7bad96 Allow to define a function returning a struct c72df1c Allow to call a fucntion returning a struct d63b1f4 Allow struct argument 5e0f8c4 Allow struct parameter 9021f7f Support passed-on-stack parameters b29f052 Support passed-on-stack arguments 12a9e75 Self-host: including preprocessor, chibicc can compile itself 5322ea8 Add va_arg() 7cbfd11 Add stdarg.h, stdbool.h, stddef.h, stdalign.h and float.h 7746e4e Recognize wide character literal ab4f1e1 Concatenate adjacent string literals 82ba010 [GNU] Add __FUNCTION__ ba6b4b6 Add __func__ dc01f94 Add __VA_ARGS__ 6f17071 Add __FILE__ and __LINE__ 5f5a850 Add predefine macros such as __STDC__ e7fdc2e Add #error a939a7a Add default include paths a1dd621 Add -I option d85fc4f Add #include <...> b33fe0e Support line continuation 8075582 Preserve newline and space during macro expansion a8d76ad Replace remaining identifiers with 0 in macro constexpr 5cb2f89 Add defined() macro operator 769b5a0 Use chibicc's preprocessor for all tests 8f561ae Add macro token-pasting operator (##) 8f6f792 Add macro stringizing operator (#) 1313fc6 Do not expand a token more than once for the same funclike macro c7d7ce0 Allow parenthesized expressions as macro arguments dd4306c Allow empty macro arguments b9ad3e4 Add multi-arity funclike #define dec3b3f Add zero-arity funclike #define 1f80f58 Add #ifdef and #ifndef acce002 Do not expand a token more than once for the same objlike macro 2651448 Expand macros in the #if and #elif argument context 9ad60e4 Add #undef 97d33ad Add objlike #define e7a1857 Add #elif c6e81d2 Add #else aa570f3 Skip nested #if in a skipped #if-clause bf6ff92 Add #if and #endif d138864 Add -E option ec149f6 Skip extra tokens after `#include "..."` d367510 Add #include "..." 146c7b3 Add the null directive 1e1ea39 Add a do-nothing preprocessor 8b726b5 Run "ld" unless -c is given b833cd0 Accept multiple input files 140b433 Run "as" command unless -S is given f3d9613 Split cc1 from compiler driver 53e8103 Add usual arithmetic conversion for function pointer c5953ba Decay a function to a pointer in the func param context d06a8ac Add function pointer 5d15431 Add stage2 build 9bf9612 Add "long double" as an alias for "double" ffea421 Add flonum constant expression e452cf7 Support variadic function with floating-point parameters 8b14859 Implement default argument promotion for float c6b3056 Allow to define a function that takes/returns flonums 8ec1ebf Allow to call a function that takes/returns flonums 0ce1093 Handle flonum for if, while, do, !, ?:, || and && 83f76eb Add flonum +, -, * and / cf9ceec Add flonum ==, !=, < and <= 29de46a Add "float" and "double" local variables and casts 1e57f72 Add floating-point constant 1fad259 Allow to omit parameter name in function declaration 93d1277 Ignore "static" and "const" in array-dimensions b773554 Ignore const, volatile, auto, register, restrict or _Noreturn. 7ba6fe8 Handle unsigned types in the constant expression 6880a39 When comparing two pointers, treat them as unsigned 8b8f3de Use long or ulong instead of int for some expressions aaf1045 Add U, L and LL suffixes 34ab83b Add unsigned integral types 3f59ce7 Add `signed` keyword 197689a Check the number of function arguments 754a24f Add va_start to support variadic functions 58fc861 Allow to call a variadic function dcd4579 Handle a function returning bool, char or short 6a0ed71 Align stack frame to 16 byte boundaries ee252e6 Add do ... while eb85527 Add static global variables 30b3e21 Add return that doesn't take any value 127056d Add compound literals 319772b Add static local variables 310a87e [GNU] Allow a variable as an operand of _Alignof 9df5178 Add _Alignof and _Alignas 2764745 Handle extern declarations in a block 006a45c Add extern 157356c Align global variables 7a1f816 Accept `void` as a parameter list cd688a8 Allow to initialize struct flexible array member 824543b Add flexible array member 3d216e3 Emit uninitialized global data to .bss instead of .data fde464c Allow extraneous comma at the end of enum or initializer list a58958c Allow extraneous braces for scalar initializer efa0f33 Allow parentheses in initializers to be omitted 1eae5ae Handle union initializers for global variable eeb62b6 Add struct initializer for global variable bbfe3f4 Add global initializer for scalar and string 483b194 Handle union initializers for local variables aca19dd Allow to initialize a struct with other struct e9d2c46 Handle struct initializers for local variables 5b95533 Allow to omit array length if an initializer is given 0d71737 Add string literal initializer a754732 Skip excess initializer elements ae0a37d Initialize excess array elements with zero 22dd560 Support local variable initializers 79f5de2 Add constant expression 447ee09 Add ?: operator d0c0cb7 Add <<, >>, <<= and >>= 044d9ae Add switch-case 3c83dfd Add continue statement b3047f2 Add break statement a4be55b Resolve conflict between labels and typedefs 6116cae Add goto and labeled statement 61a1055 Add a notion of an incomplete struct type 7963221 Decay an array to a pointer in the func param context 29ed294 Add a notion of an incomplete array type f30f781 Add && and || 8644006 Add &, |, ^, &=, |= and ^= daa7398 Add % and %= 46a96d6 Add ~ operator 6b88bcb Add ! operator 7df934d Add hexadecimal, octal and binary number literals e8ca48c Add post ++ and -- 47f1937 Add pre ++ and -- 01a94c0 Add +=, -=, *= and /= a4fea2b Allow for-loops to define local variables 736232f Support file-scope functions 48ba265 Add enum aa0accc Add character literal 44bba96 Add _Bool type fdc80bc Handle function argument type conversion 818352a Handle return type conversion 9e211cb Report an error on undefined/undeclared functions 8b430a6 Implement usual arithmetic conversion cfc4fa9 Add type cast cb81a37 Use 32 bit registers for char, short and int 67543ea Make sizeof to accept not only an expression but also a typename a6b82da Add typedef f46370e Add `long long` as an alias for `long` 287906a Handle complex type declarations correctly 8c3503b Add void type 74e3acc Add function declaration a817b23 Add nested type declarators 9d48eef Add short type 43c2f08 Add long type 5831eda Change size of int from 8 to 4 bef0543 Add struct assignment 11e3841 Add union f0a018a Add -> operator e1e831e Support struct tags dfec115 Align local variables 9443e4b Align struct members f814033 Add struct e6307ad Add comma operator 1c91d19 Emit .file and .loc assembler directives 6647ad9 Precompute line number for each token cd832a3 Rewrite tests in shell script in C ca8b243 Handle block scope 6c0a429 Add line and block comments a0388ba Add -o and --help options 7b8528f Refactor -- no functionality change d9ea597 Read code from a file instead of argv[1] 9dae234 [GNU] Add statement expression c2cc1d3 Add \x 699d2b7 Add \ ad7749f Add \a, \b, \t, \n \v, \f, \r and \e 35a0bcd Refactoring: Add a utility function 4cedda2 Add string literal be38d63 Add char type a4d3223 Add global variables 0b76634 Merge Function with Var 3e55caf Add sizeof 648646b Add [] operator 3ce1b2d Add arrays of arrays 8b6395d Add one dimensional arrays aacc0cf Support function definition up to 6 parameters 6cb4220 Support zero-arity function definition 964b1d2 Support function call with up to 6 arguments 30a3992 Support zero-arity function calls b4e82cf Add keyword "int" and make variable definition mandatory a6bc4ab Make pointer arithmetic work 863e2b8 Add unary & and * 3d86277 Add a representative node to each Node to improve error messages 5b142b1 Add LICENSE and README.md 1f3eb34 Add "while" statement f5d480f Add "for" statement 72b8415 Add "if" statement ff8912c Add null statement 18ac283 Add { ... } 6cc1c1f Add "return" statement 482c26b Support multi-letter local variables 1f9f3ad Support single-letter local variables 76cae0a Accept multiple statements separated by semicolons 725badf Split main.c into multiple small files 25b4b85 Add ==, !=, <= and >= operators bf9ab52 Add unary plus and minus 84cfcaf Add *, / and () cc5a6d9 Improve error message a1ab0ff Add a tokenizer to allow space characters between tokens bf7081f Add + and - operators 0522e2d Compile an integer to an exectuable that exits with the given number chibicc セルフホスト 196/316 イマココ 138/316

Slide 175

Slide 175 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 セルフホストまでの道 • chibiccのリポジトリでは合計316コミットある • pccは138コミットまで進んでる • 196コミットでchibiccとしてはセルフホストできる模様 • 意外と近いな… • chibiccのフォーク fuhsnn/slimcc ではPHPを コンパイルできるらしい (Rui Ueyamaさん情報) • https://github.com/fuhsnn/slimcc • chibiccの316コミットにさらに564コミット積んでるんすけど… • どのコミットでPHPコンパイルできるかわからないけど… 34 90d1f7f Make struct member access to work with `=` and `?:` 982041f Update README b35d148 Add __attribute__((aligned(N)) for struct declaration 44bea4c Add __attribute__((packed)) 395308c redefinition 2ed3fda Add test/thirdparty/cpython.sh 0a5d08c Complete stdatomic.h d69a11d Add _Atomic and atomic ++, -- and op= operators 80ea9d4 Add atomic_exchange ca27455 Add atomic_compare_exchange fb49370 Add scripts to test third-party apps 469f159 Add -Xlinker option d1bc9a4 Add -Wl, option c8df787 Add -L option 4e5de36 Add -shared option 1e9b6dd Add -static option f10bceb [GNU] Add #include_next a6c6622 [GNU] Add "#pragma once" d48d9e5 Add include guard optimization c0f0614 Cache file search results 86785fc Add -fpic and -fPIC options c3edffb Add -MMD option 7aa72e4 Add -MQ option fb5cfe5 Add -MD option db850f3 Add -MT option 57c1d4e Add -MP option 95d5a46 Add -MF option d0c4667 Add -M option f694413 Use hashmap for keyword lookup 655954e Use hashmap for block-scope lookup 30520e5 Use hashmap for macro name lookup 0aad326 Add string hashmap f0c98e0 [GNU] Treat labels-as-values as compile-time constant 4f165ec [GNU] Support labels-as-values 3d5550e [GNU] Support array range designator d90c73b [GNU] Support case ranges e0bf168 Add long double d56dd2f Recognize .a and .so files 8d130ab Emit size and type for symbols c32f0e2 Add -s option bc25279 Add -l option b0109a3 Do not define __STDC_NO_VLA__ 2fa8f48 Support sizeof(typename) where typename is a VLA 07f9010 Add pointer arithmetic for VLA e8667af Add sizeof() for VLA 77275c5 Add alloca() 4064871 Make -E to imply -xc ee0a951 Add -x option 8f5ff07 Add -include option b377284 Add thread-local variable 6d344ed Add -fcommon and -fno-common flags 85e46b1 Add tentative definition 1b99bad Add offsetof 11fc259 Add -idirafter option 6a2dc5a Use __attribute__((format(print, ...))) to find programming errors e5f4ca9 Do not emit static inline functions if referenced by no one 31087f8 Handle inline functions as static functions a253516 Add basic "asm" statement e28a612 [GNU] Add ?: operator with omitted operand aee7891 [GNU] Allow sizeof() 1faab48 Add _Generic 1433b40 [GNU] Add __builtin_types_compatible_p 7d80a51 Add typeof 007e526 [GNU] Support GCC-style variadic macro 74ec9f6 Ignore #pragma 083c275 [GNU] Handle ,##__VA_ARG__ 3381448 Add __VA_OPT__ 3a10c8a [GNU] Add __BASE_FILE__ macro 922604a [GNU] Add __TIMESTAMP__ macro aaf20fb [GNU] Add line marker directive c61c0d0 Add #line 37998be Improve error message for multibyte characters 95eb5b0 Handle struct designator for anonymous struct member 31dc1df Add union designated initializer 67f5834 Add struct designated initializer 691c4fa [GNU] Allow to omit "=" in designated initializers 835cd24 Allow array designators to initialize incomplete arrays c618c3b Add array designated initializer 2b2fa25 Skip UTF-8 BOM markers 2382777 Allow to concatenate regular string literals with L/u/U string literals adb8b98 [GNU] Accept $ as an identifier character 0e5d250 Allow multibyte UTF-8 character in identifier e4491b8 Define __STDC_UTF_{16,32}__ macros 6adba75 Add UTF-32 string literal initializer 36230e0 Add UTF-16 string literal initializer cae061a Add wide string literal c467ee6 Add UTF-32 string literal 9cabe1f Add UTF-16 string literal 57b21fe Add UTF-8 string literal 2dac3af Add UTF-32 character literal 454618c Add UTF-16 character literal a57c661 Accept multibyte character as wide character literal c31886a Add \u and \U escape sequences 74bcec5 Canonicalize newline character 0e77f3d [GNU] Add __COUNTER__ macro e27417f Add __DATE__ and __TIME__ macros c3075b3 Add anonymous struct and union 9c36dd7 Make "main" to implicitly return 0 5257ee0 Make an array of at least 16 bytes long to have alignment of at least 16 bytes 2c91da5 Turn on -Wall compiler flag and fix compiler warnings b1fdddf Ignore -O, -W and -g and other flags 2bdc6b8 Write to an in-memory buffer before writing to an actual output file c302a96 Do not allow to obtain an address of a bitfield 17ea802 Handle zero-width bitfield member 54c2b3b Handle op=-style assignments to bitfields 441a89b Support global struct bitfield initializer cc852fe Add bitfield be8b6f6 Add -U option fc69f5c Add -D option 3f2c2d5 Tokenize numeric tokens as pp-numbers e0b5da3 Dereferencing a function shouldn't do anything 603de50 Add va_copy() b6d3cd0 Allow variadic function to take more than 6 parameters d7bad96 Allow to define a function returning a struct c72df1c Allow to call a fucntion returning a struct d63b1f4 Allow struct argument 5e0f8c4 Allow struct parameter 9021f7f Support passed-on-stack parameters b29f052 Support passed-on-stack arguments 12a9e75 Self-host: including preprocessor, chibicc can compile itself 5322ea8 Add va_arg() 7cbfd11 Add stdarg.h, stdbool.h, stddef.h, stdalign.h and float.h 7746e4e Recognize wide character literal ab4f1e1 Concatenate adjacent string literals 82ba010 [GNU] Add __FUNCTION__ ba6b4b6 Add __func__ dc01f94 Add __VA_ARGS__ 6f17071 Add __FILE__ and __LINE__ 5f5a850 Add predefine macros such as __STDC__ e7fdc2e Add #error a939a7a Add default include paths a1dd621 Add -I option d85fc4f Add #include <...> b33fe0e Support line continuation 8075582 Preserve newline and space during macro expansion a8d76ad Replace remaining identifiers with 0 in macro constexpr 5cb2f89 Add defined() macro operator 769b5a0 Use chibicc's preprocessor for all tests 8f561ae Add macro token-pasting operator (##) 8f6f792 Add macro stringizing operator (#) 1313fc6 Do not expand a token more than once for the same funclike macro c7d7ce0 Allow parenthesized expressions as macro arguments dd4306c Allow empty macro arguments b9ad3e4 Add multi-arity funclike #define dec3b3f Add zero-arity funclike #define 1f80f58 Add #ifdef and #ifndef acce002 Do not expand a token more than once for the same objlike macro 2651448 Expand macros in the #if and #elif argument context 9ad60e4 Add #undef 97d33ad Add objlike #define e7a1857 Add #elif c6e81d2 Add #else aa570f3 Skip nested #if in a skipped #if-clause bf6ff92 Add #if and #endif d138864 Add -E option ec149f6 Skip extra tokens after `#include "..."` d367510 Add #include "..." 146c7b3 Add the null directive 1e1ea39 Add a do-nothing preprocessor 8b726b5 Run "ld" unless -c is given b833cd0 Accept multiple input files 140b433 Run "as" command unless -S is given f3d9613 Split cc1 from compiler driver 53e8103 Add usual arithmetic conversion for function pointer c5953ba Decay a function to a pointer in the func param context d06a8ac Add function pointer 5d15431 Add stage2 build 9bf9612 Add "long double" as an alias for "double" ffea421 Add flonum constant expression e452cf7 Support variadic function with floating-point parameters 8b14859 Implement default argument promotion for float c6b3056 Allow to define a function that takes/returns flonums 8ec1ebf Allow to call a function that takes/returns flonums 0ce1093 Handle flonum for if, while, do, !, ?:, || and && 83f76eb Add flonum +, -, * and / cf9ceec Add flonum ==, !=, < and <= 29de46a Add "float" and "double" local variables and casts 1e57f72 Add floating-point constant 1fad259 Allow to omit parameter name in function declaration 93d1277 Ignore "static" and "const" in array-dimensions b773554 Ignore const, volatile, auto, register, restrict or _Noreturn. 7ba6fe8 Handle unsigned types in the constant expression 6880a39 When comparing two pointers, treat them as unsigned 8b8f3de Use long or ulong instead of int for some expressions aaf1045 Add U, L and LL suffixes 34ab83b Add unsigned integral types 3f59ce7 Add `signed` keyword 197689a Check the number of function arguments 754a24f Add va_start to support variadic functions 58fc861 Allow to call a variadic function dcd4579 Handle a function returning bool, char or short 6a0ed71 Align stack frame to 16 byte boundaries ee252e6 Add do ... while eb85527 Add static global variables 30b3e21 Add return that doesn't take any value 127056d Add compound literals 319772b Add static local variables 310a87e [GNU] Allow a variable as an operand of _Alignof 9df5178 Add _Alignof and _Alignas 2764745 Handle extern declarations in a block 006a45c Add extern 157356c Align global variables 7a1f816 Accept `void` as a parameter list cd688a8 Allow to initialize struct flexible array member 824543b Add flexible array member 3d216e3 Emit uninitialized global data to .bss instead of .data fde464c Allow extraneous comma at the end of enum or initializer list a58958c Allow extraneous braces for scalar initializer efa0f33 Allow parentheses in initializers to be omitted 1eae5ae Handle union initializers for global variable eeb62b6 Add struct initializer for global variable bbfe3f4 Add global initializer for scalar and string 483b194 Handle union initializers for local variables aca19dd Allow to initialize a struct with other struct e9d2c46 Handle struct initializers for local variables 5b95533 Allow to omit array length if an initializer is given 0d71737 Add string literal initializer a754732 Skip excess initializer elements ae0a37d Initialize excess array elements with zero 22dd560 Support local variable initializers 79f5de2 Add constant expression 447ee09 Add ?: operator d0c0cb7 Add <<, >>, <<= and >>= 044d9ae Add switch-case 3c83dfd Add continue statement b3047f2 Add break statement a4be55b Resolve conflict between labels and typedefs 6116cae Add goto and labeled statement 61a1055 Add a notion of an incomplete struct type 7963221 Decay an array to a pointer in the func param context 29ed294 Add a notion of an incomplete array type f30f781 Add && and || 8644006 Add &, |, ^, &=, |= and ^= daa7398 Add % and %= 46a96d6 Add ~ operator 6b88bcb Add ! operator 7df934d Add hexadecimal, octal and binary number literals e8ca48c Add post ++ and -- 47f1937 Add pre ++ and -- 01a94c0 Add +=, -=, *= and /= a4fea2b Allow for-loops to define local variables 736232f Support file-scope functions 48ba265 Add enum aa0accc Add character literal 44bba96 Add _Bool type fdc80bc Handle function argument type conversion 818352a Handle return type conversion 9e211cb Report an error on undefined/undeclared functions 8b430a6 Implement usual arithmetic conversion cfc4fa9 Add type cast cb81a37 Use 32 bit registers for char, short and int 67543ea Make sizeof to accept not only an expression but also a typename a6b82da Add typedef f46370e Add `long long` as an alias for `long` 287906a Handle complex type declarations correctly 8c3503b Add void type 74e3acc Add function declaration a817b23 Add nested type declarators 9d48eef Add short type 43c2f08 Add long type 5831eda Change size of int from 8 to 4 bef0543 Add struct assignment 11e3841 Add union f0a018a Add -> operator e1e831e Support struct tags dfec115 Align local variables 9443e4b Align struct members f814033 Add struct e6307ad Add comma operator 1c91d19 Emit .file and .loc assembler directives 6647ad9 Precompute line number for each token cd832a3 Rewrite tests in shell script in C ca8b243 Handle block scope 6c0a429 Add line and block comments a0388ba Add -o and --help options 7b8528f Refactor -- no functionality change d9ea597 Read code from a file instead of argv[1] 9dae234 [GNU] Add statement expression c2cc1d3 Add \x 699d2b7 Add \ ad7749f Add \a, \b, \t, \n \v, \f, \r and \e 35a0bcd Refactoring: Add a utility function 4cedda2 Add string literal be38d63 Add char type a4d3223 Add global variables 0b76634 Merge Function with Var 3e55caf Add sizeof 648646b Add [] operator 3ce1b2d Add arrays of arrays 8b6395d Add one dimensional arrays aacc0cf Support function definition up to 6 parameters 6cb4220 Support zero-arity function definition 964b1d2 Support function call with up to 6 arguments 30a3992 Support zero-arity function calls b4e82cf Add keyword "int" and make variable definition mandatory a6bc4ab Make pointer arithmetic work 863e2b8 Add unary & and * 3d86277 Add a representative node to each Node to improve error messages 5b142b1 Add LICENSE and README.md 1f3eb34 Add "while" statement f5d480f Add "for" statement 72b8415 Add "if" statement ff8912c Add null statement 18ac283 Add { ... } 6cc1c1f Add "return" statement 482c26b Support multi-letter local variables 1f9f3ad Support single-letter local variables 76cae0a Accept multiple statements separated by semicolons 725badf Split main.c into multiple small files 25b4b85 Add ==, !=, <= and >= operators bf9ab52 Add unary plus and minus 84cfcaf Add *, / and () cc5a6d9 Improve error message a1ab0ff Add a tokenizer to allow space characters between tokens bf7081f Add + and - operators 0522e2d Compile an integer to an exectuable that exits with the given number chibicc セルフホスト 196/316 イマココ 138/316

Slide 176

Slide 176 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 セルフホストまでの道 • chibiccのリポジトリでは合計316コミットある • pccは138コミットまで進んでる • 196コミットでchibiccとしてはセルフホストできる模様 • 意外と近いな… • chibiccのフォーク fuhsnn/slimcc ではPHPを コンパイルできるらしい (Rui Ueyamaさん情報) • https://github.com/fuhsnn/slimcc • chibiccの316コミットにさらに564コミット積んでるんすけど… • どのコミットでPHPコンパイルできるかわからないけど… • やるんすか…?自分…ライフワーク級だな… 34 90d1f7f Make struct member access to work with `=` and `?:` 982041f Update README b35d148 Add __attribute__((aligned(N)) for struct declaration 44bea4c Add __attribute__((packed)) 395308c redefinition 2ed3fda Add test/thirdparty/cpython.sh 0a5d08c Complete stdatomic.h d69a11d Add _Atomic and atomic ++, -- and op= operators 80ea9d4 Add atomic_exchange ca27455 Add atomic_compare_exchange fb49370 Add scripts to test third-party apps 469f159 Add -Xlinker option d1bc9a4 Add -Wl, option c8df787 Add -L option 4e5de36 Add -shared option 1e9b6dd Add -static option f10bceb [GNU] Add #include_next a6c6622 [GNU] Add "#pragma once" d48d9e5 Add include guard optimization c0f0614 Cache file search results 86785fc Add -fpic and -fPIC options c3edffb Add -MMD option 7aa72e4 Add -MQ option fb5cfe5 Add -MD option db850f3 Add -MT option 57c1d4e Add -MP option 95d5a46 Add -MF option d0c4667 Add -M option f694413 Use hashmap for keyword lookup 655954e Use hashmap for block-scope lookup 30520e5 Use hashmap for macro name lookup 0aad326 Add string hashmap f0c98e0 [GNU] Treat labels-as-values as compile-time constant 4f165ec [GNU] Support labels-as-values 3d5550e [GNU] Support array range designator d90c73b [GNU] Support case ranges e0bf168 Add long double d56dd2f Recognize .a and .so files 8d130ab Emit size and type for symbols c32f0e2 Add -s option bc25279 Add -l option b0109a3 Do not define __STDC_NO_VLA__ 2fa8f48 Support sizeof(typename) where typename is a VLA 07f9010 Add pointer arithmetic for VLA e8667af Add sizeof() for VLA 77275c5 Add alloca() 4064871 Make -E to imply -xc ee0a951 Add -x option 8f5ff07 Add -include option b377284 Add thread-local variable 6d344ed Add -fcommon and -fno-common flags 85e46b1 Add tentative definition 1b99bad Add offsetof 11fc259 Add -idirafter option 6a2dc5a Use __attribute__((format(print, ...))) to find programming errors e5f4ca9 Do not emit static inline functions if referenced by no one 31087f8 Handle inline functions as static functions a253516 Add basic "asm" statement e28a612 [GNU] Add ?: operator with omitted operand aee7891 [GNU] Allow sizeof() 1faab48 Add _Generic 1433b40 [GNU] Add __builtin_types_compatible_p 7d80a51 Add typeof 007e526 [GNU] Support GCC-style variadic macro 74ec9f6 Ignore #pragma 083c275 [GNU] Handle ,##__VA_ARG__ 3381448 Add __VA_OPT__ 3a10c8a [GNU] Add __BASE_FILE__ macro 922604a [GNU] Add __TIMESTAMP__ macro aaf20fb [GNU] Add line marker directive c61c0d0 Add #line 37998be Improve error message for multibyte characters 95eb5b0 Handle struct designator for anonymous struct member 31dc1df Add union designated initializer 67f5834 Add struct designated initializer 691c4fa [GNU] Allow to omit "=" in designated initializers 835cd24 Allow array designators to initialize incomplete arrays c618c3b Add array designated initializer 2b2fa25 Skip UTF-8 BOM markers 2382777 Allow to concatenate regular string literals with L/u/U string literals adb8b98 [GNU] Accept $ as an identifier character 0e5d250 Allow multibyte UTF-8 character in identifier e4491b8 Define __STDC_UTF_{16,32}__ macros 6adba75 Add UTF-32 string literal initializer 36230e0 Add UTF-16 string literal initializer cae061a Add wide string literal c467ee6 Add UTF-32 string literal 9cabe1f Add UTF-16 string literal 57b21fe Add UTF-8 string literal 2dac3af Add UTF-32 character literal 454618c Add UTF-16 character literal a57c661 Accept multibyte character as wide character literal c31886a Add \u and \U escape sequences 74bcec5 Canonicalize newline character 0e77f3d [GNU] Add __COUNTER__ macro e27417f Add __DATE__ and __TIME__ macros c3075b3 Add anonymous struct and union 9c36dd7 Make "main" to implicitly return 0 5257ee0 Make an array of at least 16 bytes long to have alignment of at least 16 bytes 2c91da5 Turn on -Wall compiler flag and fix compiler warnings b1fdddf Ignore -O, -W and -g and other flags 2bdc6b8 Write to an in-memory buffer before writing to an actual output file c302a96 Do not allow to obtain an address of a bitfield 17ea802 Handle zero-width bitfield member 54c2b3b Handle op=-style assignments to bitfields 441a89b Support global struct bitfield initializer cc852fe Add bitfield be8b6f6 Add -U option fc69f5c Add -D option 3f2c2d5 Tokenize numeric tokens as pp-numbers e0b5da3 Dereferencing a function shouldn't do anything 603de50 Add va_copy() b6d3cd0 Allow variadic function to take more than 6 parameters d7bad96 Allow to define a function returning a struct c72df1c Allow to call a fucntion returning a struct d63b1f4 Allow struct argument 5e0f8c4 Allow struct parameter 9021f7f Support passed-on-stack parameters b29f052 Support passed-on-stack arguments 12a9e75 Self-host: including preprocessor, chibicc can compile itself 5322ea8 Add va_arg() 7cbfd11 Add stdarg.h, stdbool.h, stddef.h, stdalign.h and float.h 7746e4e Recognize wide character literal ab4f1e1 Concatenate adjacent string literals 82ba010 [GNU] Add __FUNCTION__ ba6b4b6 Add __func__ dc01f94 Add __VA_ARGS__ 6f17071 Add __FILE__ and __LINE__ 5f5a850 Add predefine macros such as __STDC__ e7fdc2e Add #error a939a7a Add default include paths a1dd621 Add -I option d85fc4f Add #include <...> b33fe0e Support line continuation 8075582 Preserve newline and space during macro expansion a8d76ad Replace remaining identifiers with 0 in macro constexpr 5cb2f89 Add defined() macro operator 769b5a0 Use chibicc's preprocessor for all tests 8f561ae Add macro token-pasting operator (##) 8f6f792 Add macro stringizing operator (#) 1313fc6 Do not expand a token more than once for the same funclike macro c7d7ce0 Allow parenthesized expressions as macro arguments dd4306c Allow empty macro arguments b9ad3e4 Add multi-arity funclike #define dec3b3f Add zero-arity funclike #define 1f80f58 Add #ifdef and #ifndef acce002 Do not expand a token more than once for the same objlike macro 2651448 Expand macros in the #if and #elif argument context 9ad60e4 Add #undef 97d33ad Add objlike #define e7a1857 Add #elif c6e81d2 Add #else aa570f3 Skip nested #if in a skipped #if-clause bf6ff92 Add #if and #endif d138864 Add -E option ec149f6 Skip extra tokens after `#include "..."` d367510 Add #include "..." 146c7b3 Add the null directive 1e1ea39 Add a do-nothing preprocessor 8b726b5 Run "ld" unless -c is given b833cd0 Accept multiple input files 140b433 Run "as" command unless -S is given f3d9613 Split cc1 from compiler driver 53e8103 Add usual arithmetic conversion for function pointer c5953ba Decay a function to a pointer in the func param context d06a8ac Add function pointer 5d15431 Add stage2 build 9bf9612 Add "long double" as an alias for "double" ffea421 Add flonum constant expression e452cf7 Support variadic function with floating-point parameters 8b14859 Implement default argument promotion for float c6b3056 Allow to define a function that takes/returns flonums 8ec1ebf Allow to call a function that takes/returns flonums 0ce1093 Handle flonum for if, while, do, !, ?:, || and && 83f76eb Add flonum +, -, * and / cf9ceec Add flonum ==, !=, < and <= 29de46a Add "float" and "double" local variables and casts 1e57f72 Add floating-point constant 1fad259 Allow to omit parameter name in function declaration 93d1277 Ignore "static" and "const" in array-dimensions b773554 Ignore const, volatile, auto, register, restrict or _Noreturn. 7ba6fe8 Handle unsigned types in the constant expression 6880a39 When comparing two pointers, treat them as unsigned 8b8f3de Use long or ulong instead of int for some expressions aaf1045 Add U, L and LL suffixes 34ab83b Add unsigned integral types 3f59ce7 Add `signed` keyword 197689a Check the number of function arguments 754a24f Add va_start to support variadic functions 58fc861 Allow to call a variadic function dcd4579 Handle a function returning bool, char or short 6a0ed71 Align stack frame to 16 byte boundaries ee252e6 Add do ... while eb85527 Add static global variables 30b3e21 Add return that doesn't take any value 127056d Add compound literals 319772b Add static local variables 310a87e [GNU] Allow a variable as an operand of _Alignof 9df5178 Add _Alignof and _Alignas 2764745 Handle extern declarations in a block 006a45c Add extern 157356c Align global variables 7a1f816 Accept `void` as a parameter list cd688a8 Allow to initialize struct flexible array member 824543b Add flexible array member 3d216e3 Emit uninitialized global data to .bss instead of .data fde464c Allow extraneous comma at the end of enum or initializer list a58958c Allow extraneous braces for scalar initializer efa0f33 Allow parentheses in initializers to be omitted 1eae5ae Handle union initializers for global variable eeb62b6 Add struct initializer for global variable bbfe3f4 Add global initializer for scalar and string 483b194 Handle union initializers for local variables aca19dd Allow to initialize a struct with other struct e9d2c46 Handle struct initializers for local variables 5b95533 Allow to omit array length if an initializer is given 0d71737 Add string literal initializer a754732 Skip excess initializer elements ae0a37d Initialize excess array elements with zero 22dd560 Support local variable initializers 79f5de2 Add constant expression 447ee09 Add ?: operator d0c0cb7 Add <<, >>, <<= and >>= 044d9ae Add switch-case 3c83dfd Add continue statement b3047f2 Add break statement a4be55b Resolve conflict between labels and typedefs 6116cae Add goto and labeled statement 61a1055 Add a notion of an incomplete struct type 7963221 Decay an array to a pointer in the func param context 29ed294 Add a notion of an incomplete array type f30f781 Add && and || 8644006 Add &, |, ^, &=, |= and ^= daa7398 Add % and %= 46a96d6 Add ~ operator 6b88bcb Add ! operator 7df934d Add hexadecimal, octal and binary number literals e8ca48c Add post ++ and -- 47f1937 Add pre ++ and -- 01a94c0 Add +=, -=, *= and /= a4fea2b Allow for-loops to define local variables 736232f Support file-scope functions 48ba265 Add enum aa0accc Add character literal 44bba96 Add _Bool type fdc80bc Handle function argument type conversion 818352a Handle return type conversion 9e211cb Report an error on undefined/undeclared functions 8b430a6 Implement usual arithmetic conversion cfc4fa9 Add type cast cb81a37 Use 32 bit registers for char, short and int 67543ea Make sizeof to accept not only an expression but also a typename a6b82da Add typedef f46370e Add `long long` as an alias for `long` 287906a Handle complex type declarations correctly 8c3503b Add void type 74e3acc Add function declaration a817b23 Add nested type declarators 9d48eef Add short type 43c2f08 Add long type 5831eda Change size of int from 8 to 4 bef0543 Add struct assignment 11e3841 Add union f0a018a Add -> operator e1e831e Support struct tags dfec115 Align local variables 9443e4b Align struct members f814033 Add struct e6307ad Add comma operator 1c91d19 Emit .file and .loc assembler directives 6647ad9 Precompute line number for each token cd832a3 Rewrite tests in shell script in C ca8b243 Handle block scope 6c0a429 Add line and block comments a0388ba Add -o and --help options 7b8528f Refactor -- no functionality change d9ea597 Read code from a file instead of argv[1] 9dae234 [GNU] Add statement expression c2cc1d3 Add \x 699d2b7 Add \ ad7749f Add \a, \b, \t, \n \v, \f, \r and \e 35a0bcd Refactoring: Add a utility function 4cedda2 Add string literal be38d63 Add char type a4d3223 Add global variables 0b76634 Merge Function with Var 3e55caf Add sizeof 648646b Add [] operator 3ce1b2d Add arrays of arrays 8b6395d Add one dimensional arrays aacc0cf Support function definition up to 6 parameters 6cb4220 Support zero-arity function definition 964b1d2 Support function call with up to 6 arguments 30a3992 Support zero-arity function calls b4e82cf Add keyword "int" and make variable definition mandatory a6bc4ab Make pointer arithmetic work 863e2b8 Add unary & and * 3d86277 Add a representative node to each Node to improve error messages 5b142b1 Add LICENSE and README.md 1f3eb34 Add "while" statement f5d480f Add "for" statement 72b8415 Add "if" statement ff8912c Add null statement 18ac283 Add { ... } 6cc1c1f Add "return" statement 482c26b Support multi-letter local variables 1f9f3ad Support single-letter local variables 76cae0a Accept multiple statements separated by semicolons 725badf Split main.c into multiple small files 25b4b85 Add ==, !=, <= and >= operators bf9ab52 Add unary plus and minus 84cfcaf Add *, / and () cc5a6d9 Improve error message a1ab0ff Add a tokenizer to allow space characters between tokens bf7081f Add + and - operators 0522e2d Compile an integer to an exectuable that exits with the given number chibicc セルフホスト 196/316 イマココ 138/316

Slide 177

Slide 177 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 まとめ 35

Slide 178

Slide 178 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 まとめ 36 長谷川 智希 @tomzoh

Slide 179

Slide 179 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 まとめ • Cコンパイラを書くとプログラム言語がどのように解釈されて、 CPUでどのように実行されるかが理解できる 36 長谷川 智希 @tomzoh

Slide 180

Slide 180 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 まとめ • Cコンパイラを書くとプログラム言語がどのように解釈されて、 CPUでどのように実行されるかが理解できる • Cコンパイラは難しくない 36 長谷川 智希 @tomzoh

Slide 181

Slide 181 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 まとめ • Cコンパイラを書くとプログラム言語がどのように解釈されて、 CPUでどのように実行されるかが理解できる • Cコンパイラは難しくない • ゼロから書くのは難しいかもだけど、低レイヤを知りたい人のためのC コンパイラ作成入門を読んだり、chibiccのコミットを追えばだいぶハー ドルは下がる 36 長谷川 智希 @tomzoh

Slide 182

Slide 182 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 まとめ • Cコンパイラを書くとプログラム言語がどのように解釈されて、 CPUでどのように実行されるかが理解できる • Cコンパイラは難しくない • ゼロから書くのは難しいかもだけど、低レイヤを知りたい人のためのC コンパイラ作成入門を読んだり、chibiccのコミットを追えばだいぶハー ドルは下がる • コンパイラがわかればインタープリタも共通部分多いのでわかる 36 長谷川 智希 @tomzoh

Slide 183

Slide 183 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 まとめ • Cコンパイラを書くとプログラム言語がどのように解釈されて、 CPUでどのように実行されるかが理解できる • Cコンパイラは難しくない • ゼロから書くのは難しいかもだけど、低レイヤを知りたい人のためのC コンパイラ作成入門を読んだり、chibiccのコミットを追えばだいぶハー ドルは下がる • コンパイラがわかればインタープリタも共通部分多いのでわかる • CPUで機械語がどう実行されるかも気になりません? 36 長谷川 智希 @tomzoh

Slide 184

Slide 184 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 まとめ • Cコンパイラを書くとプログラム言語がどのように解釈されて、 CPUでどのように実行されるかが理解できる • Cコンパイラは難しくない • ゼロから書くのは難しいかもだけど、低レイヤを知りたい人のためのC コンパイラ作成入門を読んだり、chibiccのコミットを追えばだいぶハー ドルは下がる • コンパイラがわかればインタープリタも共通部分多いのでわかる • CPUで機械語がどう実行されるかも気になりません? • エミュレータは真逆で実行環境だけがあるのでまた別の味がありますよ 36 長谷川 智希 @tomzoh

Slide 185

Slide 185 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 まとめ • Cコンパイラを書くとプログラム言語がどのように解釈されて、 CPUでどのように実行されるかが理解できる • Cコンパイラは難しくない • ゼロから書くのは難しいかもだけど、低レイヤを知りたい人のためのC コンパイラ作成入門を読んだり、chibiccのコミットを追えばだいぶハー ドルは下がる • コンパイラがわかればインタープリタも共通部分多いのでわかる • CPUで機械語がどう実行されるかも気になりません? • エミュレータは真逆で実行環境だけがあるのでまた別の味がありますよ • 今日のトークをきっかけにみなさんが低レイヤを楽しめるように なったら嬉しく思います! 36 長谷川 智希 @tomzoh

Slide 186

Slide 186 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 37

Slide 187

Slide 187 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 37

Slide 188

Slide 188 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 コンパイラ 37

Slide 189

Slide 189 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 コンパイラ みんなもつくって 37

Slide 190

Slide 190 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 コンパイラ みんなもつくって たのしもう 37

Slide 191

Slide 191 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 まとめ • Cコンパイラを書くとプログラム言語がどのように解釈されて、 CPUでどのように実行されるかが理解できる • Cコンパイラは難しくない • ゼロから書くのは難しいかもだけど、低レイヤを知りたい人のためのC コンパイラ作成入門を読んだり、chibiccのコミットを追えばだいぶハー ドルは下がる • コンパイラがわかればインタープリタも共通部分多いのでわかる • CPUで機械語がどう実行されるかも気になりません? • エミュレータは真逆で実行環境だけがあるのでまた別の味がありますよ • 今日のトークをきっかけにみなさんが低レイヤを楽しめるように なったら嬉しく思います! 38 長谷川 智希 @tomzoh

Slide 192

Slide 192 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 おまけ 時間があったら… 39

Slide 193

Slide 193 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 アセンブラ・アセンブル 40 機械語(マシン語)のバイナリ 000000 7f 45 4c 46 02 01 01 00 000008 00 00 00 00 00 00 00 00 000010 03 00 3e 00 01 00 00 00 000018 60 10 00 00 00 00 00 00 000020 40 00 00 00 00 00 00 00 000028 e8 39 00 00 00 00 00 00 000030 00 00 00 00 40 00 38 00 000038 0d 00 40 00 24 00 23 00 000040 06 00 00 00 04 00 00 00 000048 40 00 00 00 00 00 00 00 アセンブル アセンブラで アセンブリ言語のソースコードをアセンブルして 機械語(マシン語)のバイナリを作る 実行ファイル アセンブリ言語の ソースコード C言語の ソースコード .file 1 "-" .local .L..0 .align 1 .data .L..0: .byte 72 ; H .byte 101 ; e .byte 108 ; l .byte 108 ; l .byte 111 ; o .byte 44 ; , .byte 32 ; .byte 87 ; W .byte 111 ; o .byte 114 ; r .byte 108 ; l .byte 100 ; d .byte 46 ; . .byte 0 ; \0 .globl main .text main: push %rbp mov %rsp, %rbp sub $0, %rsp .loc 1 43 .loc 1 43 .loc 1 43 .loc 1 43 .loc 1 43 lea .L..0(%rip), %rax push %rax pop %rdi mov $0, %rax call printf .L.return.main: mov %rbp, %rsp pop %rbp ret アセンブリ言語のソースコード

Slide 194

Slide 194 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 機械語(マシン語) • CだろうがGoだろうがRustだろうがすべて最終的には機械語に変換される • この特徴はコンパイラ型言語の特徴 • 世の中の言語にはコンパイラ型言語とインタプリタ型言語がある • PHP Conference Japan 2023で詳しく話をしているので興味ある方はどうぞ (YouTubeにもあります。タイトルで検索してみて) 41

Slide 195

Slide 195 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インクリメンタルな開発 42

Slide 196

Slide 196 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インクリメンタルな開発 • 最初からすべての言語機能を作るのは難しい 42

Slide 197

Slide 197 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インクリメンタルな開発 • 最初からすべての言語機能を作るのは難しい • 難易度的な問題とモチベーション的な問題 42

Slide 198

Slide 198 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インクリメンタルな開発 • 最初からすべての言語機能を作るのは難しい • 難易度的な問題とモチベーション的な問題 • 少しずつ機能を作っていく 42

Slide 199

Slide 199 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インクリメンタルな開発 • 最初からすべての言語機能を作るのは難しい • 難易度的な問題とモチベーション的な問題 • 少しずつ機能を作っていく • テストコードもいっしょに作っていく 42

Slide 200

Slide 200 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インクリメンタルな開発 • 最初からすべての言語機能を作るのは難しい • 難易度的な問題とモチベーション的な問題 • 少しずつ機能を作っていく • テストコードもいっしょに作っていく • テキストの実装 chibicc を見る時に: 42

Slide 201

Slide 201 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インクリメンタルな開発 • 最初からすべての言語機能を作るのは難しい • 難易度的な問題とモチベーション的な問題 • 少しずつ機能を作っていく • テストコードもいっしょに作っていく • テキストの実装 chibicc を見る時に: • 「このコミットで何を作っているか」がわかる 42

Slide 202

Slide 202 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インクリメンタルな開発 • 最初からすべての言語機能を作るのは難しい • 難易度的な問題とモチベーション的な問題 • 少しずつ機能を作っていく • テストコードもいっしょに作っていく • テキストの実装 chibicc を見る時に: • 「このコミットで何を作っているか」がわかる • C言語の細かい仕様がわかる 42

Slide 203

Slide 203 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インクリメンタルな開発 • 最初からすべての言語機能を作るのは難しい • 難易度的な問題とモチベーション的な問題 • 少しずつ機能を作っていく • テストコードもいっしょに作っていく • テキストの実装 chibicc を見る時に: • 「このコミットで何を作っているか」がわかる • C言語の細かい仕様がわかる • リファクタリング時に: 42

Slide 204

Slide 204 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インクリメンタルな開発 • 最初からすべての言語機能を作るのは難しい • 難易度的な問題とモチベーション的な問題 • 少しずつ機能を作っていく • テストコードもいっしょに作っていく • テキストの実装 chibicc を見る時に: • 「このコミットで何を作っているか」がわかる • C言語の細かい仕様がわかる • リファクタリング時に: • ふつうに便利 42

Slide 205

Slide 205 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: 最初のコンパイラ 43

Slide 206

Slide 206 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: 最初のコンパイラ • 極限までシンプルなCコンパイラ 43

Slide 207

Slide 207 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: 最初のコンパイラ • 極限までシンプルなCコンパイラ 43 ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 コンパイラ

Slide 208

Slide 208 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: 最初のコンパイラ • 極限までシンプルなCコンパイラ • 実装する機能は整数だけ 43 ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 コンパイラ

Slide 209

Slide 209 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: 最初のコンパイラ • 極限までシンプルなCコンパイラ • 実装する機能は整数だけ • 入力された整数をそのまま出力する 43 ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 コンパイラ

Slide 210

Slide 210 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: 最初のコンパイラ • 極限までシンプルなCコンパイラ • 実装する機能は整数だけ • 入力された整数をそのまま出力する • 引数としてソースコードを受け取り、 アセンブリ言語のソースコードを出力する 43 ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 コンパイラ ソースコード

Slide 211

Slide 211 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: 最初のコンパイラ • 極限までシンプルなCコンパイラ • 実装する機能は整数だけ • 入力された整数をそのまま出力する • 引数としてソースコードを受け取り、 アセンブリ言語のソースコードを出力する • アセンブリ言語のソースコードをアセンブルして できた実行ファイルは 終了コードとしてソースコードの整数をそのまま返す 43 ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 コンパイラ ソースコード アセンブル

Slide 212

Slide 212 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: 最初のコンパイラ • 極限までシンプルなCコンパイラ • 実装する機能は整数だけ • 入力された整数をそのまま出力する • 引数としてソースコードを受け取り、 アセンブリ言語のソースコードを出力する • アセンブリ言語のソースコードをアセンブルして できた実行ファイルは 終了コードとしてソースコードの整数をそのまま返す 43 ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 コンパイラ ソースコード 実行ファイル アセンブル

Slide 213

Slide 213 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: 最初のコンパイラ • 極限までシンプルなCコンパイラ • 実装する機能は整数だけ • 入力された整数をそのまま出力する • 引数としてソースコードを受け取り、 アセンブリ言語のソースコードを出力する • アセンブリ言語のソースコードをアセンブルして できた実行ファイルは 終了コードとしてソースコードの整数をそのまま返す 43 ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 コンパイラ ソースコード 終了コード 実行ファイル アセンブル

Slide 214

Slide 214 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 出力すべきアセンブリ言語のソースコード 44

Slide 215

Slide 215 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 出力すべきアセンブリ言語のソースコード 44

Slide 216

Slide 216 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 出力すべきアセンブリ言語のソースコード 44 実行ファイル

Slide 217

Slide 217 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 出力すべきアセンブリ言語のソースコード 44 アセンブリ言語の ソースコード 実行ファイル

Slide 218

Slide 218 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 .globl main main: mov %rax, $42 ret ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 出力すべきアセンブリ言語のソースコード 44 アセンブリ言語の ソースコード 実行ファイル

Slide 219

Slide 219 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 .globl main main: mov %rax, $42 ret ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 出力すべきアセンブリ言語のソースコード • アセンブリ言語のコードで42のところを動的に出力す れば「整数だけ実装されたCコンパイラ」になる 44 アセンブリ言語の ソースコード 実行ファイル

Slide 220

Slide 220 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 .globl main main: mov %rax, $42 ret ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 出力すべきアセンブリ言語のソースコード • アセンブリ言語のコードで42のところを動的に出力す れば「整数だけ実装されたCコンパイラ」になる • レジスタ 44 アセンブリ言語の ソースコード 実行ファイル

Slide 221

Slide 221 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 .globl main main: mov %rax, $42 ret ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 出力すべきアセンブリ言語のソースコード • アセンブリ言語のコードで42のところを動的に出力す れば「整数だけ実装されたCコンパイラ」になる • レジスタ • CPUが持っている変数みたいなもの 44 アセンブリ言語の ソースコード 実行ファイル

Slide 222

Slide 222 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 .globl main main: mov %rax, $42 ret ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 出力すべきアセンブリ言語のソースコード • アセンブリ言語のコードで42のところを動的に出力す れば「整数だけ実装されたCコンパイラ」になる • レジスタ • CPUが持っている変数みたいなもの • mov %rax, $42 = raxレジスタに42を入れる 44 アセンブリ言語の ソースコード 実行ファイル

Slide 223

Slide 223 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 .globl main main: mov %rax, $42 ret ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 出力すべきアセンブリ言語のソースコード • アセンブリ言語のコードで42のところを動的に出力す れば「整数だけ実装されたCコンパイラ」になる • レジスタ • CPUが持っている変数みたいなもの • mov %rax, $42 = raxレジスタに42を入れる • Linuxではプログラム実行が終わった時のrax レジスタの中身が実行ファイルの終了コードに なる (macOSも同じ) 44 アセンブリ言語の ソースコード 実行ファイル

Slide 224

Slide 224 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 .globl main main: mov %rax, $42 ret ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 出力すべきアセンブリ言語のソースコード • アセンブリ言語のコードで42のところを動的に出力す れば「整数だけ実装されたCコンパイラ」になる • レジスタ • CPUが持っている変数みたいなもの • mov %rax, $42 = raxレジスタに42を入れる • Linuxではプログラム実行が終わった時のrax レジスタの中身が実行ファイルの終了コードに なる (macOSも同じ) • = raxレジスタに 42 を入れて ret すれば良い 44 アセンブリ言語の ソースコード 実行ファイル

Slide 225

Slide 225 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 .globl main main: mov %rax, $42 ret ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 出力すべきアセンブリ言語のソースコード • アセンブリ言語のコードで42のところを動的に出力す れば「整数だけ実装されたCコンパイラ」になる • レジスタ • CPUが持っている変数みたいなもの • mov %rax, $42 = raxレジスタに42を入れる • Linuxではプログラム実行が終わった時のrax レジスタの中身が実行ファイルの終了コードに なる (macOSも同じ) • = raxレジスタに 42 を入れて ret すれば良い 44 アセンブリ言語の ソースコード 実行ファイル

Slide 226

Slide 226 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: PHPでの実装 45

Slide 227

Slide 227 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: PHPでの実装 45 return main($argc, $argv); function main(int $argc = null, array $argv = null): int { if ($argc != 2) { printf("引数の個数が正しくありません\n"); return 1; } printf(".globl main\n"); printf("main:\n"); printf(" mov %%rax, \$%d\n", intval($argv[1])); printf(" ret\n"); return 0; }

Slide 228

Slide 228 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: PHPでの実装 • めちゃシンプル 45 return main($argc, $argv); function main(int $argc = null, array $argv = null): int { if ($argc != 2) { printf("引数の個数が正しくありません\n"); return 1; } printf(".globl main\n"); printf("main:\n"); printf(" mov %%rax, \$%d\n", intval($argv[1])); printf(" ret\n"); return 0; }

Slide 229

Slide 229 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: PHPでの実装 • めちゃシンプル • ほぼ printf() 45 return main($argc, $argv); function main(int $argc = null, array $argv = null): int { if ($argc != 2) { printf("引数の個数が正しくありません\n"); return 1; } printf(".globl main\n"); printf("main:\n"); printf(" mov %%rax, \$%d\n", intval($argv[1])); printf(" ret\n"); return 0; }

Slide 230

Slide 230 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: PHPでの実装 • めちゃシンプル • ほぼ printf() • ソースコードとして 42 を与えれば… 45 return main($argc, $argv); function main(int $argc = null, array $argv = null): int { if ($argc != 2) { printf("引数の個数が正しくありません\n"); return 1; } printf(".globl main\n"); printf("main:\n"); printf(" mov %%rax, \$%d\n", intval($argv[1])); printf(" ret\n"); return 0; }

Slide 231

Slide 231 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: PHPでの実装 • めちゃシンプル • ほぼ printf() • ソースコードとして 42 を与えれば… 45 return main($argc, $argv); function main(int $argc = null, array $argv = null): int { if ($argc != 2) { printf("引数の個数が正しくありません\n"); return 1; } printf(".globl main\n"); printf("main:\n"); printf(" mov %%rax, \$%d\n", intval($argv[1])); printf(" ret\n"); return 0; } .globl main main: mov %rax, $42 ret • ↑が出力される

Slide 232

Slide 232 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: テストコード 46

Slide 233

Slide 233 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: テストコード • このテキスト、テストコードが付いてくる 46

Slide 234

Slide 234 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: テストコード • このテキスト、テストコードが付いてくる 46 #!/bin/bash assert() { expected="$1" input="$2" php pcc.php "$input" > tmp.s cc -o tmp tmp.s ./tmp actual="$?" if [ "$actual" = "$expected" ]; then echo "$input => $actual" else echo "$input => $expected expected, but got $actual" exit 1 fi } assert 0 0 assert 42 42 echo OK

Slide 235

Slide 235 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: テストコード • このテキスト、テストコードが付いてくる • シェルスクリプトで assert() を定義 46 #!/bin/bash assert() { expected="$1" input="$2" php pcc.php "$input" > tmp.s cc -o tmp tmp.s ./tmp actual="$?" if [ "$actual" = "$expected" ]; then echo "$input => $actual" else echo "$input => $expected expected, but got $actual" exit 1 fi } assert 0 0 assert 42 42 echo OK

Slide 236

Slide 236 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: テストコード • このテキスト、テストコードが付いてくる • シェルスクリプトで assert() を定義 • 引数を2つとる 46 #!/bin/bash assert() { expected="$1" input="$2" php pcc.php "$input" > tmp.s cc -o tmp tmp.s ./tmp actual="$?" if [ "$actual" = "$expected" ]; then echo "$input => $actual" else echo "$input => $expected expected, but got $actual" exit 1 fi } assert 0 0 assert 42 42 echo OK

Slide 237

Slide 237 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: テストコード • このテキスト、テストコードが付いてくる • シェルスクリプトで assert() を定義 • 引数を2つとる • 1つめは期待する値(expected) 46 #!/bin/bash assert() { expected="$1" input="$2" php pcc.php "$input" > tmp.s cc -o tmp tmp.s ./tmp actual="$?" if [ "$actual" = "$expected" ]; then echo "$input => $actual" else echo "$input => $expected expected, but got $actual" exit 1 fi } assert 0 0 assert 42 42 echo OK

Slide 238

Slide 238 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: テストコード • このテキスト、テストコードが付いてくる • シェルスクリプトで assert() を定義 • 引数を2つとる • 1つめは期待する値(expected) • 2つめはソースコード 46 #!/bin/bash assert() { expected="$1" input="$2" php pcc.php "$input" > tmp.s cc -o tmp tmp.s ./tmp actual="$?" if [ "$actual" = "$expected" ]; then echo "$input => $actual" else echo "$input => $expected expected, but got $actual" exit 1 fi } assert 0 0 assert 42 42 echo OK

Slide 239

Slide 239 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: テストコード • このテキスト、テストコードが付いてくる • シェルスクリプトで assert() を定義 • 引数を2つとる • 1つめは期待する値(expected) • 2つめはソースコード • ソースコードをコンパイル・実行して期待する値と 比較する 46 #!/bin/bash assert() { expected="$1" input="$2" php pcc.php "$input" > tmp.s cc -o tmp tmp.s ./tmp actual="$?" if [ "$actual" = "$expected" ]; then echo "$input => $actual" else echo "$input => $expected expected, but got $actual" exit 1 fi } assert 0 0 assert 42 42 echo OK

Slide 240

Slide 240 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: テストコード • このテキスト、テストコードが付いてくる • シェルスクリプトで assert() を定義 • 引数を2つとる • 1つめは期待する値(expected) • 2つめはソースコード • ソースコードをコンパイル・実行して期待する値と 比較する • テストケースとして 0 と 42 をコンパイルして 実行、期待する値と比較している 46 #!/bin/bash assert() { expected="$1" input="$2" php pcc.php "$input" > tmp.s cc -o tmp tmp.s ./tmp actual="$?" if [ "$actual" = "$expected" ]; then echo "$input => $actual" else echo "$input => $expected expected, but got $actual" exit 1 fi } assert 0 0 assert 42 42 echo OK

Slide 241

Slide 241 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 • STEP1で整数だけ扱えるコンパイラができた 47

Slide 242

Slide 242 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 • STEP1で整数だけ扱えるコンパイラができた • STEP2として加減算を実装する 47

Slide 243

Slide 243 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 • STEP1で整数だけ扱えるコンパイラができた • STEP2として加減算を実装する • php pcc.php '1+5-2' > addsub.s 47

Slide 244

Slide 244 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 • STEP1で整数だけ扱えるコンパイラができた • STEP2として加減算を実装する • php pcc.php '1+5-2' > addsub.s • アセンブリ言語に add, sub がある 47

Slide 245

Slide 245 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 • STEP1で整数だけ扱えるコンパイラができた • STEP2として加減算を実装する • php pcc.php '1+5-2' > addsub.s • アセンブリ言語に add, sub がある • raxレジスタに指定した値を足す/引く 47

Slide 246

Slide 246 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 • STEP1で整数だけ扱えるコンパイラができた • STEP2として加減算を実装する • php pcc.php '1+5-2' > addsub.s • アセンブリ言語に add, sub がある • raxレジスタに指定した値を足す/引く • 1 + 5 - 2 ならアセンブリ言語でこうなる: 47

Slide 247

Slide 247 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 • STEP1で整数だけ扱えるコンパイラができた • STEP2として加減算を実装する • php pcc.php '1+5-2' > addsub.s • アセンブリ言語に add, sub がある • raxレジスタに指定した値を足す/引く • 1 + 5 - 2 ならアセンブリ言語でこうなる: 47 .globl main main: mov %rax, $1 add %rax, $5 sub %rax, $2 ret

Slide 248

Slide 248 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 • STEP1で整数だけ扱えるコンパイラができた • STEP2として加減算を実装する • php pcc.php '1+5-2' > addsub.s • アセンブリ言語に add, sub がある • raxレジスタに指定した値を足す/引く • 1 + 5 - 2 ならアセンブリ言語でこうなる: • raxレジスタに 1 を入れる 47 .globl main main: mov %rax, $1 add %rax, $5 sub %rax, $2 ret

Slide 249

Slide 249 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 • STEP1で整数だけ扱えるコンパイラができた • STEP2として加減算を実装する • php pcc.php '1+5-2' > addsub.s • アセンブリ言語に add, sub がある • raxレジスタに指定した値を足す/引く • 1 + 5 - 2 ならアセンブリ言語でこうなる: • raxレジスタに 1 を入れる • raxレジスタに 5 を足す 47 .globl main main: mov %rax, $1 add %rax, $5 sub %rax, $2 ret

Slide 250

Slide 250 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 • STEP1で整数だけ扱えるコンパイラができた • STEP2として加減算を実装する • php pcc.php '1+5-2' > addsub.s • アセンブリ言語に add, sub がある • raxレジスタに指定した値を足す/引く • 1 + 5 - 2 ならアセンブリ言語でこうなる: • raxレジスタに 1 を入れる • raxレジスタに 5 を足す • raxレジスタから 2 を引く 47 .globl main main: mov %rax, $1 add %rax, $5 sub %rax, $2 ret

Slide 251

Slide 251 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 • STEP1で整数だけ扱えるコンパイラができた • STEP2として加減算を実装する • php pcc.php '1+5-2' > addsub.s • アセンブリ言語に add, sub がある • raxレジスタに指定した値を足す/引く • 1 + 5 - 2 ならアセンブリ言語でこうなる: • raxレジスタに 1 を入れる • raxレジスタに 5 を足す • raxレジスタから 2 を引く • プログラム終了 (→ 終了コードとして 1 + 5 - 2 の計算結果 4 が返る) 47 .globl main main: mov %rax, $1 add %rax, $5 sub %rax, $2 ret

Slide 252

Slide 252 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 48

Slide 253

Slide 253 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 48 [$number, $string] = extLeadNumber($argv[1]); printf(" mov %%rax, \$%d\n", $number); while(strlen($string)){ if (str_starts_with($string, '+')){ $string = substr($string, 1); [$number, $string] = extLeadNumber($string); printf(" add %%rax, \$%d\n", $number); continue; } if (str_starts_with($string, '-')){ $string = substr($string, 1); [$number, $string] = extLeadNumber($string); printf(" sub %%rax, \$%d\n", $number); continue; } fprintf(STDERR, "予期しない文字です: %s\n", $string); return 1; } printf(" ret\n");

Slide 254

Slide 254 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 • 与えられたソースコードを前から順に 見て処理していく 48 [$number, $string] = extLeadNumber($argv[1]); printf(" mov %%rax, \$%d\n", $number); while(strlen($string)){ if (str_starts_with($string, '+')){ $string = substr($string, 1); [$number, $string] = extLeadNumber($string); printf(" add %%rax, \$%d\n", $number); continue; } if (str_starts_with($string, '-')){ $string = substr($string, 1); [$number, $string] = extLeadNumber($string); printf(" sub %%rax, \$%d\n", $number); continue; } fprintf(STDERR, "予期しない文字です: %s\n", $string); return 1; } printf(" ret\n");

Slide 255

Slide 255 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 • 与えられたソースコードを前から順に 見て処理していく 48 [$number, $string] = extLeadNumber($argv[1]); printf(" mov %%rax, \$%d\n", $number); while(strlen($string)){ if (str_starts_with($string, '+')){ $string = substr($string, 1); [$number, $string] = extLeadNumber($string); printf(" add %%rax, \$%d\n", $number); continue; } if (str_starts_with($string, '-')){ $string = substr($string, 1); [$number, $string] = extLeadNumber($string); printf(" sub %%rax, \$%d\n", $number); continue; } fprintf(STDERR, "予期しない文字です: %s\n", $string); return 1; } printf(" ret\n"); .globl main main: mov %rax, $1 add %rax, $5 sub %rax, $2 ret

Slide 256

Slide 256 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 • 与えられたソースコードを前から順に 見て処理していく • ソースコード先頭の数字と残りの文 字列を取得 48 [$number, $string] = extLeadNumber($argv[1]); printf(" mov %%rax, \$%d\n", $number); while(strlen($string)){ if (str_starts_with($string, '+')){ $string = substr($string, 1); [$number, $string] = extLeadNumber($string); printf(" add %%rax, \$%d\n", $number); continue; } if (str_starts_with($string, '-')){ $string = substr($string, 1); [$number, $string] = extLeadNumber($string); printf(" sub %%rax, \$%d\n", $number); continue; } fprintf(STDERR, "予期しない文字です: %s\n", $string); return 1; } printf(" ret\n"); .globl main main: mov %rax, $1 add %rax, $5 sub %rax, $2 ret

Slide 257

Slide 257 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 • 与えられたソースコードを前から順に 見て処理していく • ソースコード先頭の数字と残りの文 字列を取得 • 数字をraxレジスタに入れるコードを 出力 48 [$number, $string] = extLeadNumber($argv[1]); printf(" mov %%rax, \$%d\n", $number); while(strlen($string)){ if (str_starts_with($string, '+')){ $string = substr($string, 1); [$number, $string] = extLeadNumber($string); printf(" add %%rax, \$%d\n", $number); continue; } if (str_starts_with($string, '-')){ $string = substr($string, 1); [$number, $string] = extLeadNumber($string); printf(" sub %%rax, \$%d\n", $number); continue; } fprintf(STDERR, "予期しない文字です: %s\n", $string); return 1; } printf(" ret\n"); .globl main main: mov %rax, $1 add %rax, $5 sub %rax, $2 ret

Slide 258

Slide 258 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 • 与えられたソースコードを前から順に 見て処理していく • ソースコード先頭の数字と残りの文 字列を取得 • 数字をraxレジスタに入れるコードを 出力 • "+" 数字や、"-" 数字 を繰り返す add %rax, $[数字] sub %rax, $[数字] 48 [$number, $string] = extLeadNumber($argv[1]); printf(" mov %%rax, \$%d\n", $number); while(strlen($string)){ if (str_starts_with($string, '+')){ $string = substr($string, 1); [$number, $string] = extLeadNumber($string); printf(" add %%rax, \$%d\n", $number); continue; } if (str_starts_with($string, '-')){ $string = substr($string, 1); [$number, $string] = extLeadNumber($string); printf(" sub %%rax, \$%d\n", $number); continue; } fprintf(STDERR, "予期しない文字です: %s\n", $string); return 1; } printf(" ret\n"); .globl main main: mov %rax, $1 add %rax, $5 sub %rax, $2 ret

Slide 259

Slide 259 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 • 与えられたソースコードを前から順に 見て処理していく • ソースコード先頭の数字と残りの文 字列を取得 • 数字をraxレジスタに入れるコードを 出力 • "+" 数字や、"-" 数字 を繰り返す add %rax, $[数字] sub %rax, $[数字] • ret を出力 48 [$number, $string] = extLeadNumber($argv[1]); printf(" mov %%rax, \$%d\n", $number); while(strlen($string)){ if (str_starts_with($string, '+')){ $string = substr($string, 1); [$number, $string] = extLeadNumber($string); printf(" add %%rax, \$%d\n", $number); continue; } if (str_starts_with($string, '-')){ $string = substr($string, 1); [$number, $string] = extLeadNumber($string); printf(" sub %%rax, \$%d\n", $number); continue; } fprintf(STDERR, "予期しない文字です: %s\n", $string); return 1; } printf(" ret\n"); .globl main main: mov %rax, $1 add %rax, $5 sub %rax, $2 ret

Slide 260

Slide 260 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: テストコード 49 #!/bin/bash : assert 0 0 assert 42 42 assert 21 "5+20-4" echo OK

Slide 261

Slide 261 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: テストコード • 実装した加減算をテストケースに追加 49 #!/bin/bash : assert 0 0 assert 42 42 assert 21 "5+20-4" echo OK

Slide 262

Slide 262 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: テストコード • 実装した加減算をテストケースに追加 • 整数と加減算を処理できるCコンパイラが完成 49 #!/bin/bash : assert 0 0 assert 42 42 assert 21 "5+20-4" echo OK

Slide 263

Slide 263 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 言語仕様を効率的に実装する工夫 • 今回のCコンパイラは3つの役割にわけてソースコードをコンパイルする • 3つの役割 • トークナイザ • パーサ • コードジェネレータ • 世の中のコンパイラはだいたいこの3つの役割で実現されている • 複雑性の分離, モジュール性の向上 • プログラム言語ぽいのはトークナイザとパーサ • インタプリタ言語でもトークナイザとパーサはたいてい持ってる • 細かく工程が分かれていたり最適化のための工程があったりすることも 50

Slide 264

Slide 264 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: 最初のコンパイラ 51 ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 ➜ pcc 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42

Slide 265

Slide 265 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: 最初のコンパイラ • php pcc.php ってなってて「コンパイラぽくない」と思いました…? 51 ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 ➜ pcc 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42

Slide 266

Slide 266 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: 最初のコンパイラ • php pcc.php ってなってて「コンパイラぽくない」と思いました…? • pcc.phpの1行目に #!/usr/bin/php とか書いて mv pcc.php pcc して chmod 755 pcc するとそれっぽい…? 51 ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 ➜ pcc 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42

Slide 267

Slide 267 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 プログラム言語っぽさ 52

Slide 268

Slide 268 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 プログラム言語っぽさ • 「プログラム言語ぽいのはトークナイザとパーサ」 52

Slide 269

Slide 269 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 プログラム言語っぽさ • 「プログラム言語ぽいのはトークナイザとパーサ」 • = 言語仕様を実装しているのはトークナイザとパーサ 52

Slide 270

Slide 270 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 プログラム言語っぽさ • 「プログラム言語ぽいのはトークナイザとパーサ」 • = 言語仕様を実装しているのはトークナイザとパーサ • コードジェネレータはCPUに依存する 52

Slide 271

Slide 271 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 プログラム言語っぽさ • 「プログラム言語ぽいのはトークナイザとパーサ」 • = 言語仕様を実装しているのはトークナイザとパーサ • コードジェネレータはCPUに依存する • Intel用コードジェネレータ, Apple Silicon用コードジェネレータ, … のように 差し替えると別のCPU用のコンパイラになる 52

Slide 272

Slide 272 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 プログラム言語っぽさ • 「プログラム言語ぽいのはトークナイザとパーサ」 • = 言語仕様を実装しているのはトークナイザとパーサ • コードジェネレータはCPUに依存する • Intel用コードジェネレータ, Apple Silicon用コードジェネレータ, … のように 差し替えると別のCPU用のコンパイラになる • トークナイザとパーサの実装はCPUの知識が無くても何とかなる 52

Slide 273

Slide 273 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 プログラム言語っぽさ • 「プログラム言語ぽいのはトークナイザとパーサ」 • = 言語仕様を実装しているのはトークナイザとパーサ • コードジェネレータはCPUに依存する • Intel用コードジェネレータ, Apple Silicon用コードジェネレータ, … のように 差し替えると別のCPU用のコンパイラになる • トークナイザとパーサの実装はCPUの知識が無くても何とかなる • ので、CPUに詳しくない方は、まずはコードジェネレータのところは「そういうもん」と思っ てそのまま写しちゃっても良いのでは 52

Slide 274

Slide 274 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 プログラム言語っぽさ • 「プログラム言語ぽいのはトークナイザとパーサ」 • = 言語仕様を実装しているのはトークナイザとパーサ • コードジェネレータはCPUに依存する • Intel用コードジェネレータ, Apple Silicon用コードジェネレータ, … のように 差し替えると別のCPU用のコンパイラになる • トークナイザとパーサの実装はCPUの知識が無くても何とかなる • ので、CPUに詳しくない方は、まずはコードジェネレータのところは「そういうもん」と思っ てそのまま写しちゃっても良いのでは • それでも十分プログラム言語づくりっぽい面白さは味わえる 52

Slide 275

Slide 275 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インタープリタ型言語 53

Slide 276

Slide 276 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インタープリタ型言語 • トークナイズしてパースしたあとそのままASTを実行するプログラム言語もある 53

Slide 277

Slide 277 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インタープリタ型言語 • トークナイズしてパースしたあとそのままASTを実行するプログラム言語もある • トークナイザ + パーサ + VM 53

Slide 278

Slide 278 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インタープリタ型言語 • トークナイズしてパースしたあとそのままASTを実行するプログラム言語もある • トークナイザ + パーサ + VM • VM: 実行環境 53

Slide 279

Slide 279 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インタープリタ型言語 • トークナイズしてパースしたあとそのままASTを実行するプログラム言語もある • トークナイザ + パーサ + VM • VM: 実行環境 • 機械語で書かれたプログラムなことが多い 53

Slide 280

Slide 280 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インタープリタ型言語 • トークナイズしてパースしたあとそのままASTを実行するプログラム言語もある • トークナイザ + パーサ + VM • VM: 実行環境 • 機械語で書かれたプログラムなことが多い • インタープリタ型言語 53

Slide 281

Slide 281 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インタープリタ型言語 • トークナイズしてパースしたあとそのままASTを実行するプログラム言語もある • トークナイザ + パーサ + VM • VM: 実行環境 • 機械語で書かれたプログラムなことが多い • インタープリタ型言語 • Python, Ruby, … 53

Slide 282

Slide 282 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インタープリタ型言語 • トークナイズしてパースしたあとそのままASTを実行するプログラム言語もある • トークナイザ + パーサ + VM • VM: 実行環境 • 機械語で書かれたプログラムなことが多い • インタープリタ型言語 • Python, Ruby, … • 我らがPHPも、もちろんこの範疇 53

Slide 283

Slide 283 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インタープリタ型言語 • トークナイズしてパースしたあとそのままASTを実行するプログラム言語もある • トークナイザ + パーサ + VM • VM: 実行環境 • 機械語で書かれたプログラムなことが多い • インタープリタ型言語 • Python, Ruby, … • 我らがPHPも、もちろんこの範疇 • 「嘘だ!PHPもコンパイルするでしょ!JITコンパイラとかあるし!」 53

Slide 284

Slide 284 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インタープリタ型言語 • トークナイズしてパースしたあとそのままASTを実行するプログラム言語もある • トークナイザ + パーサ + VM • VM: 実行環境 • 機械語で書かれたプログラムなことが多い • インタープリタ型言語 • Python, Ruby, … • 我らがPHPも、もちろんこの範疇 • 「嘘だ!PHPもコンパイルするでしょ!JITコンパイラとかあるし!」 • トークナイザ + パーサ + コンパイラ(バイトコード化) + VM 53

Slide 285

Slide 285 text

長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 最適化 • 素直にコンパイルされたアセンブリ言語のソース • push → push → pop → pop みたいなところがある • ここは結果として rdi レジスタや rax レジスタに 値を設定したいだけなので mov %rdi, $3 とか mov %rax, $10 とかすれば良く、 メモリアクセスが不要になって高速化する • こいういうのがコンパイラの最適化 54 .globl main main: push $10 push $3 pop %rdi pop %rax imul %rax, %rdi push %rax pop %rax ret コンパイル結果