Upgrade to Pro — share decks privately, control downloads, hide ads and more …

低レイヤを知りたいPHPerのためのCコンパイラ作成入門 / Building a C Com...

低レイヤを知りたいPHPerのためのCコンパイラ作成入門 / Building a C Compiler for PHPers Who Want to Dive into Low-Level Programming

PHPカンファレンス小田原2025の資料です

参照:
低レイヤを知りたい人のためのCコンパイラ作成入門 / Rui Ueyamaさん
https://www.sigbus.info/compilerbook

hasegawa-tomoki/pcc
https://github.com/hasegawa-tomoki/pcc

fuhsnn/slimcc
https://github.com/fuhsnn/slimcc

HASEGAWA Tomoki

April 12, 2025
Tweet

More Decks by HASEGAWA Tomoki

Other Decks in Technology

Transcript

  1. Cコンパイラ作成入門 2025/04/12 PHPカンファレンス小田原2025 From $this to *this — A Journey

    Down the Stack 低レイヤを知りたいPHPerのための 長谷川 智希 @tomzoh
  2. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 なぜCコンパイラか • ここ数年、低レイヤ大好き • CPU, エミュレータ, コンパイラ,

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

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

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

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

    ハードウェア, … • どれも楽しいけど今日はコンパイラの話 • コンパイラは実はシンプル • 実行環境の実装を含まない • CPU, エミュレータ, インタプリタは実行環境 • テキスト to テキストのコンバータ • CPU, OS, プログラミング言語実装といった低レイヤぽい要素はキッチリ含む • 低レイヤを知るのにコンパイラはうってつけの教材 5
  7. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラの動作 • みなさんも一度くらいやったことありそうな Hello, World • gcc

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

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

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

    hello.c → a.out • gcc Cコンパイラ • hello.c C言語のソースコード(ファイル) • a.out 実行ファイル • CコンパイラがC言語のソースコードを実行ファイルに変換している様に見える • 実は2段階で変換している • コンパイラ: C言語のソースコード → アセンブリ言語のソースコード • アセンブラ: アセンブリ言語のソースコード → 機械語(マシン語)の実行ファイル 7
  11. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 機械語(マシン語) • CPUで直接実行できる唯一の言語 • Intel CPUの機械語, Apple

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

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

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

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

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

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

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

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

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

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

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

    • C言語のソースコードからアセンブリ言語のソースコードに変換するCコンパイラ • アセンブラ部分は既存のものを使用する • とてもよくできたCコンパイラ作成入門ドキュメント 低レイヤを知りたい人のためのCコンパイラ作成入門 / Rui Ueyamaさん https://www.sigbus.info/compilerbook • だけどC言語でC言語のコンパイラを作るテキストなんだよね〜 • C言語…PHPerの我々にはややハードルが高い • のでPHPでやる
  23. 長谷川智希 @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
  24. 長谷川智希 @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
  25. 長谷川智希 @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
  26. 長谷川智希 @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
  27. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 言語仕様を効率的に実装する工夫 • 今回のCコンパイラは3つの役割にわけてソースコードをコンパイルする • トークナイザ • パーサ

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

    • コードジェネレータ • 世の中のコンパイラはだいたいこの3つの役割で実現されている • 加減乗除の式を与えられて 計算結果を終了コードとして返す コマンドを作るコンパイラ を作ってみる 12 ➜ php pcc.php "1 + 5 - 2" > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 4
  29. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 トークナイザ • ソースコードを分割してトークン化する • トークナイズ • 字句解析

    • トークンの種類 識別子 変数名 関数名 記号 != <= += ++ ( ) … キーワード return if else … 文字列, 数字 "Hello, World" 30 0xff 1.06e2 … 13
  30. 長谷川智希 @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; }
  31. 長谷川智希 @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; }
  32. 長谷川智希 @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 ※ 図は雰囲気です。実際のトークン列とは異なります。
  33. 長谷川智希 @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 {
  34. 長谷川智希 @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とは異なります。
  35. 長谷川智希 @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 アセンブリ言語のソースコード
  36. 長谷川智希 @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 アセンブリ言語のソースコード
  37. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ここまでのまとめ 17 #include <stdio.h> int main(){ printf("Hello,

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

    printf("Hello, World."); } C言語のソースコード • C言語のソースコードをCコンパイラでコンパ イルしてアセンブリ言語のソースコードを作る 実行ファイル アセンブリ言語の ソースコード C言語の ソースコード
  39. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ここまでのまとめ 17 コンパイル #include <stdio.h> 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言語の ソースコード
  40. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ここまでのまとめ 17 コンパイル #include <stdio.h> 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言語の ソースコード
  41. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 EBNF • プログラム言語の生成規則を記述するための記法 EBNF (Extended Backus-Naur form)

    20 expr は num から始まって "+" num または "-" num が0回以上続く expr = num ("+" num | "-" num)* numは数値を表す記号
  42. 長谷川智希 @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
  43. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 演算の優先順位の表現 21 expr = mul ("+" mul

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

    | "-" mul)* mul = num ("*" num | "/" num)* expr を処理するには先に mul を処理する必要がある ➡ 四則演算の優先順位を表現できた
  45. 長谷川智希 @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 を処理する必要がある ➡ 四則演算の優先順位を表現できた
  46. 長谷川智希 @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 を処理する必要がある ➡ 四則演算の優先順位を表現できた
  47. 長谷川智希 @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 を処理する必要がある ➡ 四則演算の優先順位を表現できた
  48. 長谷川智希 @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 を処理する必要がある ➡ 四則演算の優先順位を表現できた ➡ カッコの優先順位を表現できた
  49. 長谷川智希 @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
  50. 長谷川智希 @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で言語仕様がすべて表現できる(誇張を含みます)
  51. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 ENBFの実装方針 • EBNFに出てくるワード(非終端記号)を関数1つにマップしていくとパーサが作りやすい 24 expr = mul

    ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" • この場合、expr(), mul(), primary(), num() を作る • それぞれ Node のインスタンスを返す
  52. 長谷川智希 @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) をコードジェネレータに渡す
  53. 長谷川智希 @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
  54. 長谷川智希 @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
  55. 長谷川智希 @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
  56. 長谷川智希 @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; } } }
  57. 長谷川智希 @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; } } }
  58. 長谷川智希 @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; } } }
  59. 長谷川智希 @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
  60. 長谷川智希 @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
  61. 長谷川智希 @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 ")"
  62. 長谷川智希 @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 ")"
  63. 長谷川智希 @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 ")"
  64. 長谷川智希 @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 ")"
  65. 長谷川智希 @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
  66. 長谷川智希 @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
  67. 長谷川智希 @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 ")"
  68. 長谷川智希 @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
  69. 長谷川智希 @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
  70. 長谷川智希 @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
  71. 長谷川智希 @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
  72. 長谷川智希 @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"); }
  73. 長谷川智希 @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"); }
  74. 長谷川智希 @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"); }
  75. 長谷川智希 @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"); }
  76. 長谷川智希 @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"); }
  77. 長谷川智希 @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
  78. 長谷川智希 @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
  79. 長谷川智希 @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 加減乗除ノード
  80. 長谷川智希 @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の処理
  81. 長谷川智希 @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の処理
  82. 長谷川智希 @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の処理
  83. 長谷川智希 @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の処理
  84. 長谷川智希 @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の処理
  85. 長谷川智希 @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つ取り出す
  86. 長谷川智希 @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つの値を使って 演算する
  87. 長谷川智希 @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レジスタ)の値を スタックに乗せる
  88. 長谷川智希 @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
  89. 長谷川智希 @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
  90. 長谷川智希 @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
  91. 長谷川智希 @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
  92. 長谷川智希 @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
  93. 長谷川智希 @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
  94. 長谷川智希 @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
  95. 長谷川智希 @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
  96. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 Cコンパイラのゴール • EBNFを少しずつ大きくしていけばCコンパイラは育っていく • コンパイラを育てていけばそのうち自分自身をコンパイルできる様になる • セルフホストという

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

    • (趣味の)コンパイラの到達点 • 今回はPHPで書いてるのでセルフホストには至らない • …PHPはCで書かれている訳で… • これでPHPのソースをコンパイル出来たら面白いかも…? • 「PHPでコンパイルしたPHPでCコンパイラを動かして…」の無限ループ 33
  98. 長谷川智希 @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(<function type>) 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<dir> 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<hexadecimal-sequence> 699d2b7 Add \<octal-sequence> 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
  99. 長谷川智希 @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(<function type>) 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<dir> 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<hexadecimal-sequence> 699d2b7 Add \<octal-sequence> 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
  100. 長谷川智希 @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(<function type>) 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<dir> 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<hexadecimal-sequence> 699d2b7 Add \<octal-sequence> 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
  101. 長谷川智希 @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(<function type>) 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<dir> 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<hexadecimal-sequence> 699d2b7 Add \<octal-sequence> 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
  102. 長谷川智希 @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(<function type>) 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<dir> 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<hexadecimal-sequence> 699d2b7 Add \<octal-sequence> 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
  103. 長谷川智希 @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(<function type>) 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<dir> 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<hexadecimal-sequence> 699d2b7 Add \<octal-sequence> 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
  104. 長谷川智希 @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(<function type>) 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<dir> 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<hexadecimal-sequence> 699d2b7 Add \<octal-sequence> 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
  105. 長谷川智希 @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(<function type>) 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<dir> 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<hexadecimal-sequence> 699d2b7 Add \<octal-sequence> 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
  106. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 まとめ • Cコンパイラを書くとプログラム言語がどのように解釈されて、 CPUでどのように実行されるかが理解できる • Cコンパイラは難しくない •

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

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

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

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

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

    ゼロから書くのは難しいかもだけど、低レイヤを知りたい人のためのC コンパイラ作成入門を読んだり、chibiccのコミットを追えばだいぶハー ドルは下がる • コンパイラがわかればインタープリタも共通部分多いのでわかる • CPUで機械語がどう実行されるかも気になりません? • エミュレータは真逆で実行環境だけがあるのでまた別の味がありますよ • 今日のトークをきっかけにみなさんが低レイヤを楽しめるように なったら嬉しく思います! 38 長谷川 智希 @tomzoh
  112. 長谷川智希 @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 アセンブリ言語のソースコード
  113. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 インクリメンタルな開発 • 最初からすべての言語機能を作るのは難しい • 難易度的な問題とモチベーション的な問題 • 少しずつ機能を作っていく

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

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

    • テストコードもいっしょに作っていく • テキストの実装 chibicc を見る時に: • 「このコミットで何を作っているか」がわかる • C言語の細かい仕様がわかる • リファクタリング時に: • ふつうに便利 42
  116. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP1: 最初のコンパイラ • 極限までシンプルなCコンパイラ • 実装する機能は整数だけ •

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

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

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

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

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

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

    cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 出力すべきアセンブリ言語のソースコード 44 アセンブリ言語の ソースコード 実行ファイル
  123. 長谷川智希 @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 アセンブリ言語の ソースコード 実行ファイル
  124. 長谷川智希 @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 アセンブリ言語の ソースコード 実行ファイル
  125. 長谷川智希 @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 アセンブリ言語の ソースコード 実行ファイル
  126. 長谷川智希 @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 アセンブリ言語の ソースコード 実行ファイル
  127. 長谷川智希 @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 アセンブリ言語の ソースコード 実行ファイル
  128. 長谷川智希 @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 アセンブリ言語の ソースコード 実行ファイル
  129. 長谷川智希 @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 アセンブリ言語の ソースコード 実行ファイル
  130. 長谷川智希 @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 アセンブリ言語の ソースコード 実行ファイル
  131. 長谷川智希 @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; }
  132. 長谷川智希 @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; }
  133. 長谷川智希 @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; }
  134. 長谷川智希 @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; }
  135. 長谷川智希 @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 • ↑が出力される
  136. 長谷川智希 @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
  137. 長谷川智希 @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
  138. 長谷川智希 @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
  139. 長谷川智希 @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
  140. 長谷川智希 @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
  141. 長谷川智希 @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
  142. 長谷川智希 @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
  143. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 STEP2: 加減算の実装 • STEP1で整数だけ扱えるコンパイラができた • STEP2として加減算を実装する •

    php pcc.php '1+5-2' > addsub.s • アセンブリ言語に add, sub がある • raxレジスタに指定した値を足す/引く • 1 + 5 - 2 ならアセンブリ言語でこうなる: 47
  144. 長谷川智希 @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
  145. 長谷川智希 @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
  146. 長谷川智希 @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
  147. 長谷川智希 @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
  148. 長谷川智希 @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
  149. 長谷川智希 @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");
  150. 長谷川智希 @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");
  151. 長谷川智希 @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
  152. 長谷川智希 @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
  153. 長谷川智希 @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
  154. 長谷川智希 @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
  155. 長谷川智希 @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
  156. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 言語仕様を効率的に実装する工夫 • 今回のCコンパイラは3つの役割にわけてソースコードをコンパイルする • 3つの役割 • トークナイザ

    • パーサ • コードジェネレータ • 世の中のコンパイラはだいたいこの3つの役割で実現されている • 複雑性の分離, モジュール性の向上 • プログラム言語ぽいのはトークナイザとパーサ • インタプリタ言語でもトークナイザとパーサはたいてい持ってる • 細かく工程が分かれていたり最適化のための工程があったりすることも 50
  157. 長谷川智希 @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
  158. 長谷川智希 @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
  159. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 プログラム言語っぽさ • 「プログラム言語ぽいのはトークナイザとパーサ」 • = 言語仕様を実装しているのはトークナイザとパーサ •

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

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

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

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

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

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

    + VM • VM: 実行環境 • 機械語で書かれたプログラムなことが多い • インタープリタ型言語 • Python, Ruby, … • 我らがPHPも、もちろんこの範疇 • 「嘘だ!PHPもコンパイルするでしょ!JITコンパイラとかあるし!」 • トークナイザ + パーサ + コンパイラ(バイトコード化) + VM 53
  166. 長谷川智希 @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 コンパイル結果