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

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

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

PHP Conference Japan 2025の資料です

Avatar for HASEGAWA Tomoki

HASEGAWA Tomoki

June 28, 2025
Tweet

More Decks by HASEGAWA Tomoki

Other Decks in Technology

Transcript

  1. Cコンパイラ作成入門 完全版 2025/06/28 PHPカンファレンス 2025 From $this to *this —

    A Journey Down the Stack 低レイヤを知りたいPHPerのための 長谷川 智希 @tomzoh
  2. ௕୩઒ஐر ͸͕ͤΘ ͱ΋͖ @tomzoh ٕज़ΧϯϑΝϨϯεӡӦࢀՃ ֤छϓϩάϥϜ։ൃ   $16 ϨτϩήʔϜػ

    ిࢠ޻࡞  Ϗʔϧ αοΧʔ؍ઓ ϨϯλϧΧʔτϨʔε  ΩϟϯϐϯάΧʔʜ ϥΠϑϫʔΫ 𝕏
  3. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 なぜCコンパイラか • ここ数年、低レイヤ大好き • CPU, エミュレータ,

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

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

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

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

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

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

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

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

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

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

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

    Apple Siliconの機械語 のようにCPUごとに仕様が違う • 言語と言うにはめちゃんこシンプルなモノ • データを保存する場所はレジスタ(CPU内蔵の変数的なもの)とメモリだけ 8
  15. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 機械語(マシン語) • CPUで直接実行できる唯一の言語 • Intel CPUの機械語,

    Apple Siliconの機械語 のようにCPUごとに仕様が違う • 言語と言うにはめちゃんこシンプルなモノ • データを保存する場所はレジスタ(CPU内蔵の変数的なもの)とメモリだけ • 命令はすべて1命令で完結するシンプルなものだけ 8
  16. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 機械語(マシン語) • CPUで直接実行できる唯一の言語 • Intel CPUの機械語,

    Apple Siliconの機械語 のようにCPUごとに仕様が違う • 言語と言うにはめちゃんこシンプルなモノ • データを保存する場所はレジスタ(CPU内蔵の変数的なもの)とメモリだけ • 命令はすべて1命令で完結するシンプルなものだけ • メモリの読み書き 8
  17. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 機械語(マシン語) • CPUで直接実行できる唯一の言語 • Intel CPUの機械語,

    Apple Siliconの機械語 のようにCPUごとに仕様が違う • 言語と言うにはめちゃんこシンプルなモノ • データを保存する場所はレジスタ(CPU内蔵の変数的なもの)とメモリだけ • 命令はすべて1命令で完結するシンプルなものだけ • メモリの読み書き • レジスタ or/and メモリ間での演算・比較 8
  18. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 機械語(マシン語) • CPUで直接実行できる唯一の言語 • Intel CPUの機械語,

    Apple Siliconの機械語 のようにCPUごとに仕様が違う • 言語と言うにはめちゃんこシンプルなモノ • データを保存する場所はレジスタ(CPU内蔵の変数的なもの)とメモリだけ • 命令はすべて1命令で完結するシンプルなものだけ • メモリの読み書き • レジスタ or/and メモリ間での演算・比較 • 無条件ジャンプ(goto), 条件付きジャンプ 8
  19. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 機械語(マシン語) • CPUで直接実行できる唯一の言語 • Intel CPUの機械語,

    Apple Siliconの機械語 のようにCPUごとに仕様が違う • 言語と言うにはめちゃんこシンプルなモノ • データを保存する場所はレジスタ(CPU内蔵の変数的なもの)とメモリだけ • 命令はすべて1命令で完結するシンプルなものだけ • メモリの読み書き • レジスタ or/and メモリ間での演算・比較 • 無条件ジャンプ(goto), 条件付きジャンプ • if(){} とか while(){} みたいな複雑な命令は無い 8
  20. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 機械語(マシン語) • CPUで直接実行できる唯一の言語 • Intel CPUの機械語,

    Apple Siliconの機械語 のようにCPUごとに仕様が違う • 言語と言うにはめちゃんこシンプルなモノ • データを保存する場所はレジスタ(CPU内蔵の変数的なもの)とメモリだけ • 命令はすべて1命令で完結するシンプルなものだけ • メモリの読み書き • レジスタ or/and メモリ間での演算・比較 • 無条件ジャンプ(goto), 条件付きジャンプ • if(){} とか while(){} みたいな複雑な命令は無い • シンプルな命令の組み合わせで実施する 8
  21. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 シンプルさ故の難しさ • 機械語にはシンプルな命令しか無い • レジスタの数が限られる •

    スタックに入れたり出したり • メモリを書いたり読んだり 9 int main(){ int a = 0; if (a == 0){ a = 1; } else { a = 2; } } C言語
  22. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 シンプルさ故の難しさ • 機械語にはシンプルな命令しか無い • レジスタの数が限られる •

    スタックに入れたり出したり • メモリを書いたり読んだり 9 mov $4, %rcx lea -4(%rbp), %rdi mov $0, %al rep stosb lea -4(%rbp), %rax push %rax mov $0, %rax pop %rdi mov %eax, (%rdi) mov $0, %rax push %rax lea -4(%rbp), %rax mov (%rax), %eax pop %rdi cmp %edi, %eax sete %al movzb %al, %rax cmp $0, %eax je .L.else.1 lea -4(%rbp), %rax push %rax mov $1, %rax pop %rdi mov %eax, (%rdi) jmp .L.end.1 .L.else.1: lea -4(%rbp), %rax push %rax mov $2, %rax pop %rdi mov %eax, (%rdi) .L.end.1: mov $0, %rax .L.return.main: mov %rbp, %rsp pop %rbp ret アセンブリ言語 int main(){ int a = 0; if (a == 0){ a = 1; } else { a = 2; } } C言語
  23. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 シンプルさ故の難しさ • 機械語にはシンプルな命令しか無い • レジスタの数が限られる •

    スタックに入れたり出したり • メモリを書いたり読んだり 9 mov $4, %rcx lea -4(%rbp), %rdi mov $0, %al rep stosb lea -4(%rbp), %rax push %rax mov $0, %rax pop %rdi mov %eax, (%rdi) mov $0, %rax push %rax lea -4(%rbp), %rax mov (%rax), %eax pop %rdi cmp %edi, %eax sete %al movzb %al, %rax cmp $0, %eax je .L.else.1 lea -4(%rbp), %rax push %rax mov $1, %rax pop %rdi mov %eax, (%rdi) jmp .L.end.1 .L.else.1: lea -4(%rbp), %rax push %rax mov $2, %rax pop %rdi mov %eax, (%rdi) .L.end.1: mov $0, %rax .L.return.main: mov %rbp, %rsp pop %rbp ret アセンブリ言語 int main(){ int a = 0; if (a == 0){ a = 1; } else { a = 2; } } C言語
  24. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 シンプルさ故の難しさ • 機械語にはシンプルな命令しか無い • レジスタの数が限られる •

    スタックに入れたり出したり • メモリを書いたり読んだり 9 mov $4, %rcx lea -4(%rbp), %rdi mov $0, %al rep stosb lea -4(%rbp), %rax push %rax mov $0, %rax pop %rdi mov %eax, (%rdi) mov $0, %rax push %rax lea -4(%rbp), %rax mov (%rax), %eax pop %rdi cmp %edi, %eax sete %al movzb %al, %rax cmp $0, %eax je .L.else.1 lea -4(%rbp), %rax push %rax mov $1, %rax pop %rdi mov %eax, (%rdi) jmp .L.end.1 .L.else.1: lea -4(%rbp), %rax push %rax mov $2, %rax pop %rdi mov %eax, (%rdi) .L.end.1: mov $0, %rax .L.return.main: mov %rbp, %rsp pop %rbp ret アセンブリ言語 int main(){ int a = 0; if (a == 0){ a = 1; } else { a = 2; } } C言語 JG
  25. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 シンプルさ故の難しさ • 機械語にはシンプルな命令しか無い • レジスタの数が限られる •

    スタックに入れたり出したり • メモリを書いたり読んだり 9 mov $4, %rcx lea -4(%rbp), %rdi mov $0, %al rep stosb lea -4(%rbp), %rax push %rax mov $0, %rax pop %rdi mov %eax, (%rdi) mov $0, %rax push %rax lea -4(%rbp), %rax mov (%rax), %eax pop %rdi cmp %edi, %eax sete %al movzb %al, %rax cmp $0, %eax je .L.else.1 lea -4(%rbp), %rax push %rax mov $1, %rax pop %rdi mov %eax, (%rdi) jmp .L.end.1 .L.else.1: lea -4(%rbp), %rax push %rax mov $2, %rax pop %rdi mov %eax, (%rdi) .L.end.1: mov $0, %rax .L.return.main: mov %rbp, %rsp pop %rbp ret アセンブリ言語 int main(){ int a = 0; if (a == 0){ a = 1; } else { a = 2; } } C言語 JG
  26. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 シンプルさ故の難しさ • 機械語にはシンプルな命令しか無い • レジスタの数が限られる •

    スタックに入れたり出したり • メモリを書いたり読んだり 9 mov $4, %rcx lea -4(%rbp), %rdi mov $0, %al rep stosb lea -4(%rbp), %rax push %rax mov $0, %rax pop %rdi mov %eax, (%rdi) mov $0, %rax push %rax lea -4(%rbp), %rax mov (%rax), %eax pop %rdi cmp %edi, %eax sete %al movzb %al, %rax cmp $0, %eax je .L.else.1 lea -4(%rbp), %rax push %rax mov $1, %rax pop %rdi mov %eax, (%rdi) jmp .L.end.1 .L.else.1: lea -4(%rbp), %rax push %rax mov $2, %rax pop %rdi mov %eax, (%rdi) .L.end.1: mov $0, %rax .L.return.main: mov %rbp, %rsp pop %rbp ret アセンブリ言語 int main(){ int a = 0; if (a == 0){ a = 1; } else { a = 2; } } C言語 JG UIFO
  27. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 シンプルさ故の難しさ • 機械語にはシンプルな命令しか無い • レジスタの数が限られる •

    スタックに入れたり出したり • メモリを書いたり読んだり 9 mov $4, %rcx lea -4(%rbp), %rdi mov $0, %al rep stosb lea -4(%rbp), %rax push %rax mov $0, %rax pop %rdi mov %eax, (%rdi) mov $0, %rax push %rax lea -4(%rbp), %rax mov (%rax), %eax pop %rdi cmp %edi, %eax sete %al movzb %al, %rax cmp $0, %eax je .L.else.1 lea -4(%rbp), %rax push %rax mov $1, %rax pop %rdi mov %eax, (%rdi) jmp .L.end.1 .L.else.1: lea -4(%rbp), %rax push %rax mov $2, %rax pop %rdi mov %eax, (%rdi) .L.end.1: mov $0, %rax .L.return.main: mov %rbp, %rsp pop %rbp ret アセンブリ言語 int main(){ int a = 0; if (a == 0){ a = 1; } else { a = 2; } } C言語 JG UIFO
  28. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 シンプルさ故の難しさ • 機械語にはシンプルな命令しか無い • レジスタの数が限られる •

    スタックに入れたり出したり • メモリを書いたり読んだり 9 mov $4, %rcx lea -4(%rbp), %rdi mov $0, %al rep stosb lea -4(%rbp), %rax push %rax mov $0, %rax pop %rdi mov %eax, (%rdi) mov $0, %rax push %rax lea -4(%rbp), %rax mov (%rax), %eax pop %rdi cmp %edi, %eax sete %al movzb %al, %rax cmp $0, %eax je .L.else.1 lea -4(%rbp), %rax push %rax mov $1, %rax pop %rdi mov %eax, (%rdi) jmp .L.end.1 .L.else.1: lea -4(%rbp), %rax push %rax mov $2, %rax pop %rdi mov %eax, (%rdi) .L.end.1: mov $0, %rax .L.return.main: mov %rbp, %rsp pop %rbp ret アセンブリ言語 int main(){ int a = 0; if (a == 0){ a = 1; } else { a = 2; } } C言語 JG UIFO FMTF
  29. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 シンプルさ故の難しさ • 機械語にはシンプルな命令しか無い • レジスタの数が限られる •

    スタックに入れたり出したり • メモリを書いたり読んだり • ファミコン時代はこんなのを 人間が直書きしてたのだ… 9 mov $4, %rcx lea -4(%rbp), %rdi mov $0, %al rep stosb lea -4(%rbp), %rax push %rax mov $0, %rax pop %rdi mov %eax, (%rdi) mov $0, %rax push %rax lea -4(%rbp), %rax mov (%rax), %eax pop %rdi cmp %edi, %eax sete %al movzb %al, %rax cmp $0, %eax je .L.else.1 lea -4(%rbp), %rax push %rax mov $1, %rax pop %rdi mov %eax, (%rdi) jmp .L.end.1 .L.else.1: lea -4(%rbp), %rax push %rax mov $2, %rax pop %rdi mov %eax, (%rdi) .L.end.1: mov $0, %rax .L.return.main: mov %rbp, %rsp pop %rbp ret アセンブリ言語 int main(){ int a = 0; if (a == 0){ a = 1; } else { a = 2; } } C言語 JG UIFO FMTF
  30. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 シンプルさ故の難しさ • 機械語にはシンプルな命令しか無い • レジスタの数が限られる •

    スタックに入れたり出したり • メモリを書いたり読んだり • ファミコン時代はこんなのを 人間が直書きしてたのだ… • Cコンパイラ作ってるとA++なんだな〜感がある 9 mov $4, %rcx lea -4(%rbp), %rdi mov $0, %al rep stosb lea -4(%rbp), %rax push %rax mov $0, %rax pop %rdi mov %eax, (%rdi) mov $0, %rax push %rax lea -4(%rbp), %rax mov (%rax), %eax pop %rdi cmp %edi, %eax sete %al movzb %al, %rax cmp $0, %eax je .L.else.1 lea -4(%rbp), %rax push %rax mov $1, %rax pop %rdi mov %eax, (%rdi) jmp .L.end.1 .L.else.1: lea -4(%rbp), %rax push %rax mov $2, %rax pop %rdi mov %eax, (%rdi) .L.end.1: mov $0, %rax .L.return.main: mov %rbp, %rsp pop %rbp ret アセンブリ言語 int main(){ int a = 0; if (a == 0){ a = 1; } else { a = 2; } } C言語 JG UIFO FMTF
  31. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 シンプルさ故の難しさ • 機械語にはシンプルな命令しか無い • レジスタの数が限られる •

    スタックに入れたり出したり • メモリを書いたり読んだり • ファミコン時代はこんなのを 人間が直書きしてたのだ… • Cコンパイラ作ってるとA++なんだな〜感がある • C言語が突然ポッとうまれたのではなく、 みんながアセンブラ書いてるという時代背景のもとで プログラミングを効率的にするために作られた感 9 mov $4, %rcx lea -4(%rbp), %rdi mov $0, %al rep stosb lea -4(%rbp), %rax push %rax mov $0, %rax pop %rdi mov %eax, (%rdi) mov $0, %rax push %rax lea -4(%rbp), %rax mov (%rax), %eax pop %rdi cmp %edi, %eax sete %al movzb %al, %rax cmp $0, %eax je .L.else.1 lea -4(%rbp), %rax push %rax mov $1, %rax pop %rdi mov %eax, (%rdi) jmp .L.end.1 .L.else.1: lea -4(%rbp), %rax push %rax mov $2, %rax pop %rdi mov %eax, (%rdi) .L.end.1: mov $0, %rax .L.return.main: mov %rbp, %rsp pop %rbp ret アセンブリ言語 int main(){ int a = 0; if (a == 0){ a = 1; } else { a = 2; } } C言語 JG UIFO FMTF
  32. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 シンプルさ故の難しさ • 機械語にはシンプルな命令しか無い • レジスタの数が限られる •

    スタックに入れたり出したり • メモリを書いたり読んだり • ファミコン時代はこんなのを 人間が直書きしてたのだ… • Cコンパイラ作ってるとA++なんだな〜感がある • C言語が突然ポッとうまれたのではなく、 みんながアセンブラ書いてるという時代背景のもとで プログラミングを効率的にするために作られた感 • 現代: 「構造体とかポインタとか難しいな…」 9 mov $4, %rcx lea -4(%rbp), %rdi mov $0, %al rep stosb lea -4(%rbp), %rax push %rax mov $0, %rax pop %rdi mov %eax, (%rdi) mov $0, %rax push %rax lea -4(%rbp), %rax mov (%rax), %eax pop %rdi cmp %edi, %eax sete %al movzb %al, %rax cmp $0, %eax je .L.else.1 lea -4(%rbp), %rax push %rax mov $1, %rax pop %rdi mov %eax, (%rdi) jmp .L.end.1 .L.else.1: lea -4(%rbp), %rax push %rax mov $2, %rax pop %rdi mov %eax, (%rdi) .L.end.1: mov $0, %rax .L.return.main: mov %rbp, %rsp pop %rbp ret アセンブリ言語 int main(){ int a = 0; if (a == 0){ a = 1; } else { a = 2; } } C言語 JG UIFO FMTF
  33. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 シンプルさ故の難しさ • 機械語にはシンプルな命令しか無い • レジスタの数が限られる •

    スタックに入れたり出したり • メモリを書いたり読んだり • ファミコン時代はこんなのを 人間が直書きしてたのだ… • Cコンパイラ作ってるとA++なんだな〜感がある • C言語が突然ポッとうまれたのではなく、 みんながアセンブラ書いてるという時代背景のもとで プログラミングを効率的にするために作られた感 • 現代: 「構造体とかポインタとか難しいな…」 • 当時: 「メモリアクセスがこんな楽に書けるなんて神…!」 9 mov $4, %rcx lea -4(%rbp), %rdi mov $0, %al rep stosb lea -4(%rbp), %rax push %rax mov $0, %rax pop %rdi mov %eax, (%rdi) mov $0, %rax push %rax lea -4(%rbp), %rax mov (%rax), %eax pop %rdi cmp %edi, %eax sete %al movzb %al, %rax cmp $0, %eax je .L.else.1 lea -4(%rbp), %rax push %rax mov $1, %rax pop %rdi mov %eax, (%rdi) jmp .L.end.1 .L.else.1: lea -4(%rbp), %rax push %rax mov $2, %rax pop %rdi mov %eax, (%rdi) .L.end.1: mov $0, %rax .L.return.main: mov %rbp, %rsp pop %rbp ret アセンブリ言語 int main(){ int a = 0; if (a == 0){ a = 1; } else { a = 2; } } C言語 JG UIFO FMTF
  34. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 今回作るコンパイラ 10 機械語の バイナリ アセンブリ言語の ソースコード

    C言語の ソースコード • C言語のソースコードからアセンブリ言語のソースコードに変換するCコンパイラ
  35. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 今回作るコンパイラ 10 機械語の バイナリ アセンブリ言語の ソースコード

    C言語の ソースコード • C言語のソースコードからアセンブリ言語のソースコードに変換するCコンパイラ • アセンブリ言語のソースコードから機械語のバイナリに変換するアセンブラは既存のものを使用する
  36. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 今回作るコンパイラ 10 機械語の バイナリ アセンブリ言語の ソースコード

    C言語の ソースコード • C言語のソースコードからアセンブリ言語のソースコードに変換するCコンパイラ • アセンブリ言語のソースコードから機械語のバイナリに変換するアセンブラは既存のものを使用する • 世の中にはとてもよくできたCコンパイラ作成入門ドキュメントがある
  37. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 今回作るコンパイラ 10 機械語の バイナリ アセンブリ言語の ソースコード

    C言語の ソースコード • C言語のソースコードからアセンブリ言語のソースコードに変換するCコンパイラ • アセンブリ言語のソースコードから機械語のバイナリに変換するアセンブラは既存のものを使用する • 世の中にはとてもよくできたCコンパイラ作成入門ドキュメントがある 低レイヤを知りたい人のためのCコンパイラ作成入門 / Rui Ueyamaさん https://www.sigbus.info/compilerbook
  38. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 今回作るコンパイラ 10 機械語の バイナリ アセンブリ言語の ソースコード

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

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

    C言語の ソースコード • C言語のソースコードからアセンブリ言語のソースコードに変換するCコンパイラ • アセンブリ言語のソースコードから機械語のバイナリに変換するアセンブラは既存のものを使用する • 世の中にはとてもよくできたCコンパイラ作成入門ドキュメントがある 低レイヤを知りたい人のためのCコンパイラ作成入門 / Rui Ueyamaさん https://www.sigbus.info/compilerbook • だけどC言語でC言語のコンパイラを作るテキストなんだよね〜 • C言語…PHPerの我々にはややハードルが高い • のでPHPでやる
  41. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 アセンブラ・アセンブル 11 アセンブラで アセンブリ言語のソースコードをアセンブルして 機械語(マシン語)のバイナリを作る 機械語の

    バイナリ アセンブリ言語の ソースコード 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 アセンブリ言語のソースコード
  42. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 アセンブラ・アセンブル 11 アセンブル アセンブラで アセンブリ言語のソースコードをアセンブルして 機械語(マシン語)のバイナリを作る

    機械語の バイナリ アセンブリ言語の ソースコード 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 アセンブリ言語のソースコード
  43. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 アセンブラ・アセンブル 11 機械語(マシン語)のバイナリ 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 アセンブリ言語のソースコード
  44. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 コンパイラ型言語 • コンパイラ型言語: C, Go, Rust,

    … • 仕様は違えどすべて最終的には機械語に変換される • この特徴はコンパイラ型言語の特徴 12
  45. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 コンパイラ型言語 • コンパイラ型言語: C, Go, Rust,

    … • 仕様は違えどすべて最終的には機械語に変換される • この特徴はコンパイラ型言語の特徴 • 世の中の言語にはコンパイラ型言語とインタプリタ型言語がある 12
  46. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 コンパイラ型言語 • コンパイラ型言語: C, Go, Rust,

    … • 仕様は違えどすべて最終的には機械語に変換される • この特徴はコンパイラ型言語の特徴 • 世の中の言語にはコンパイラ型言語とインタプリタ型言語がある 12
  47. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 コンパイラ型言語 • コンパイラ型言語: C, Go, Rust,

    … • 仕様は違えどすべて最終的には機械語に変換される • この特徴はコンパイラ型言語の特徴 • 世の中の言語にはコンパイラ型言語とインタプリタ型言語がある • PHP Conference Japan 2023で詳しく話をしています 12
  48. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 コンパイラ型言語 • コンパイラ型言語: C, Go, Rust,

    … • 仕様は違えどすべて最終的には機械語に変換される • この特徴はコンパイラ型言語の特徴 • 世の中の言語にはコンパイラ型言語とインタプリタ型言語がある • PHP Conference Japan 2023で詳しく話をしています • 資料公開しています 12
  49. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 コンパイラ型言語 • コンパイラ型言語: C, Go, Rust,

    … • 仕様は違えどすべて最終的には機械語に変換される • この特徴はコンパイラ型言語の特徴 • 世の中の言語にはコンパイラ型言語とインタプリタ型言語がある • PHP Conference Japan 2023で詳しく話をしています • 資料公開しています • YouTubeにもあります タイトルで検索してみて 12
  50. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 コンパイラ型言語 • コンパイラ型言語: C, Go, Rust,

    … • 仕様は違えどすべて最終的には機械語に変換される • この特徴はコンパイラ型言語の特徴 • 世の中の言語にはコンパイラ型言語とインタプリタ型言語がある • PHP Conference Japan 2023で詳しく話をしています • 資料公開しています • YouTubeにもあります タイトルで検索してみて • この話の最新版を7月の関西でします 12
  51. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 インタープリタ型言語 • Python, Ruby, PHP… •

    ソースコードをパースしたあと(機械語に変換せず)そのまま実行する • VM / VirtualMachine: 実行環境 13
  52. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 インタープリタ型言語 • Python, Ruby, PHP… •

    ソースコードをパースしたあと(機械語に変換せず)そのまま実行する • VM / VirtualMachine: 実行環境 • ソースコードをパースした結果(ASTとかバイトコードとか)を実行するプログラム 13
  53. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 インタープリタ型言語 • Python, Ruby, PHP… •

    ソースコードをパースしたあと(機械語に変換せず)そのまま実行する • VM / VirtualMachine: 実行環境 • ソースコードをパースした結果(ASTとかバイトコードとか)を実行するプログラム • 機械語で書かれたプログラムなことが多い 13
  54. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 インタープリタ型言語 • Python, Ruby, PHP… •

    ソースコードをパースしたあと(機械語に変換せず)そのまま実行する • VM / VirtualMachine: 実行環境 • ソースコードをパースした結果(ASTとかバイトコードとか)を実行するプログラム • 機械語で書かれたプログラムなことが多い • CPUで直接実行されるのではなくVMで実行される 13
  55. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 インタープリタ型言語 • Python, Ruby, PHP… •

    ソースコードをパースしたあと(機械語に変換せず)そのまま実行する • VM / VirtualMachine: 実行環境 • ソースコードをパースした結果(ASTとかバイトコードとか)を実行するプログラム • 機械語で書かれたプログラムなことが多い • CPUで直接実行されるのではなくVMで実行される • 「嘘だ!PHPもコンパイルするでしょ!JITコンパイラとかあるし!」 13
  56. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 インタープリタ型言語 • Python, Ruby, PHP… •

    ソースコードをパースしたあと(機械語に変換せず)そのまま実行する • VM / VirtualMachine: 実行環境 • ソースコードをパースした結果(ASTとかバイトコードとか)を実行するプログラム • 機械語で書かれたプログラムなことが多い • CPUで直接実行されるのではなくVMで実行される • 「嘘だ!PHPもコンパイルするでしょ!JITコンパイラとかあるし!」 • ソースコード → opcode: コンパイラ的動作 13
  57. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 インタープリタ型言語 • Python, Ruby, PHP… •

    ソースコードをパースしたあと(機械語に変換せず)そのまま実行する • VM / VirtualMachine: 実行環境 • ソースコードをパースした結果(ASTとかバイトコードとか)を実行するプログラム • 機械語で書かれたプログラムなことが多い • CPUで直接実行されるのではなくVMで実行される • 「嘘だ!PHPもコンパイルするでしょ!JITコンパイラとかあるし!」 • ソースコード → opcode: コンパイラ的動作 • opcode → VM: インタプリタ的動作 13
  58. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 インタープリタ型言語 • Python, Ruby, PHP… •

    ソースコードをパースしたあと(機械語に変換せず)そのまま実行する • VM / VirtualMachine: 実行環境 • ソースコードをパースした結果(ASTとかバイトコードとか)を実行するプログラム • 機械語で書かれたプログラムなことが多い • CPUで直接実行されるのではなくVMで実行される • 「嘘だ!PHPもコンパイルするでしょ!JITコンパイラとかあるし!」 • ソースコード → opcode: コンパイラ的動作 • opcode → VM: インタプリタ的動作 • 現代は「コンパイラ型/インタープリタ型」とばっくり切り分けられないことも 13
  59. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 PHPで作るCコンパイラ実装 • GitHubでソースコード公開してます • hasegawa-tomoki/pcc https://github.com/hasegawa-tomoki/pcc

    • 実装済みの機能は /ctests/test/*.c を見て頂けると… 14 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 ཁ࠷৽Խ
  60. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 PHPで作るCコンパイラ実装 • GitHubでソースコード公開してます • hasegawa-tomoki/pcc https://github.com/hasegawa-tomoki/pcc

    • 実装済みの機能は /ctests/test/*.c を見て頂けると… • ひととおりの変数・関数定義、制御構造は実装済み 14 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 ཁ࠷৽Խ
  61. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 PHPで作るCコンパイラ実装 • GitHubでソースコード公開してます • hasegawa-tomoki/pcc https://github.com/hasegawa-tomoki/pcc

    • 実装済みの機能は /ctests/test/*.c を見て頂けると… • ひととおりの変数・関数定義、制御構造は実装済み • fl oatの実装まで自分でやって、それ以降をAIに実装してもらってる 14 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 ཁ࠷৽Խ
  62. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 PHPで作るCコンパイラ実装 • GitHubでソースコード公開してます • hasegawa-tomoki/pcc https://github.com/hasegawa-tomoki/pcc

    • 実装済みの機能は /ctests/test/*.c を見て頂けると… • ひととおりの変数・関数定義、制御構造は実装済み • fl oatの実装まで自分でやって、それ以降をAIに実装してもらってる • 今はプリプロセッサ系を作っている 14 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 ཁ࠷৽Խ
  63. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 インクリメンタルな開発 • Cコンパイラ、とても高度なので最初からすべての機能を作るのは難しい • 難易度的な問題とモチベーション的な問題 •

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

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

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

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

    低レイヤを知りたい人のためのCコンパイラ作成入門では インクリメンタルに開発を進める • 少しずつ機能を作っていく • テストコードもいっしょに作っていく • テストコードがとても便利 • 実装時: 「このコミットで何を作っているか」がわかる, C言語の細かい仕様がわかる • リファクタリング時: ふつうに便利 • AI開発的な観点: 正しい実装ができたかの担保に便利 16
  68. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 プログラム実行と終了コード • C言語というと Hello World が最初のプログラムの感じがある

    • けど、画面に文字を表示するって実は結構たいへん • 最初のうちは終了コードを出力に使う • PHPでも exit(0) とかするアレ 17
  69. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 プログラム実行と終了コード • C言語というと Hello World が最初のプログラムの感じがある

    • けど、画面に文字を表示するって実は結構たいへん • 最初のうちは終了コードを出力に使う • PHPでも exit(0) とかするアレ • 終了コードはシェルで $? で参照できる 17
  70. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 プログラム実行と終了コード • C言語というと Hello World が最初のプログラムの感じがある

    • けど、画面に文字を表示するって実は結構たいへん • 最初のうちは終了コードを出力に使う • PHPでも exit(0) とかするアレ • 終了コードはシェルで $? で参照できる 17 ➜ cat the-anser.php <?php exit(42); ➜ php the-anser.php ➜ echo $? 42
  71. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 STEP1: 最初のコンパイラ • 極限までシンプルなCコンパイラ • 実装する機能は整数だけ

    • 整数を(終了コードとして)出力する実行ファイルを作る • exit(42); よりもっとシンプルな形 • 引数としてC言語(みたいなの)のソースコードを受け取り、 アセンブリ言語のソースコードを出力するCコンパイラ
  72. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 STEP1: 最初のコンパイラ • 極限までシンプルなCコンパイラ • 実装する機能は整数だけ

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    ret ➜ php pcc.php 42 > tmp.s ➜ cc -o tmp tmp.s ➜ ./tmp ➜ echo $? 42 出力すべきアセンブリ言語のソースコード • アセンブリ言語のコードで42のところを動的に出力す れば「整数だけ実装されたCコンパイラ」になる • レジスタ • %rax というのが rax レジスタのこと • CPUが持っている変数みたいなもの • プログラム実行が終わった時の rax レジスタの 中身が実行ファイルの終了コードになる (LinuxやmacOSでは) • rax レジスタに 42 を入れて ret すれば良い • mov $42, %rax = rax レジスタに42を入れる 19 アセンブリ言語の ソースコード 42 を出力する 実行ファイル
  90. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 STEP1: PHPでの実装 20 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; }
  91. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 STEP1: PHPでの実装 • めちゃシンプル 20 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; }
  92. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 STEP1: PHPでの実装 • めちゃシンプル • ほぼ

    printf() 20 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; }
  93. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 STEP1: PHPでの実装 • めちゃシンプル • ほぼ

    printf() 20 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 • ↑を出力する
  94. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 STEP1: PHPでの実装 • めちゃシンプル • ほぼ

    printf() 20 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 • ↑を出力する • これが第一歩目のCコンパイラ
  95. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 STEP1: テストコード • このテキスト、テストコードが付いてくる 21 #!/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
  96. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 STEP1: テストコード • このテキスト、テストコードが付いてくる • シェルスクリプトで

    assert() を定義 21 #!/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
  97. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 STEP1: テストコード • このテキスト、テストコードが付いてくる • シェルスクリプトで

    assert() を定義 • 引数を2つとる 21 #!/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
  98. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 STEP1: テストコード • このテキスト、テストコードが付いてくる • シェルスクリプトで

    assert() を定義 • 引数を2つとる • 1つめは期待する値(expected) 21 #!/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
  99. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 STEP1: テストコード • このテキスト、テストコードが付いてくる • シェルスクリプトで

    assert() を定義 • 引数を2つとる • 1つめは期待する値(expected) • 2つめはソースコード 21 #!/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
  100. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 STEP1: テストコード • このテキスト、テストコードが付いてくる • シェルスクリプトで

    assert() を定義 • 引数を2つとる • 1つめは期待する値(expected) • 2つめはソースコード • ソースコードをコンパイル・実行して期待する値と 比較する 21 #!/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
  101. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 STEP1: テストコード • このテキスト、テストコードが付いてくる • シェルスクリプトで

    assert() を定義 • 引数を2つとる • 1つめは期待する値(expected) • 2つめはソースコード • ソースコードをコンパイル・実行して期待する値と 比較する • テストケースとして 0 と 42 をコンパイルして 実行、期待する値と比較している 21 #!/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
  102. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 STEP2: 加減算の実装 • STEP1で整数だけ扱えるコンパイラができた • STEP2として加減算を実装する

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

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

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

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

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

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

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

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

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

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

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

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

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

    ソースコード先頭の数字と残りの文 字列を取得 • 数字を rax レジスタに入れるコード を出力 • "+" 数字や、"-" 数字 を繰り返す add %rax, $[数字] sub %rax, $[数字] • ret を出力 23 [$number, $string] = extLeadNumber($argv[1]); printf(" mov\$%d%%rax\n", $number); while(strlen($string)){ if (str_starts_with($string, '+')){ $string = substr($string, 1); [$number, $string] = extLeadNumber($string); printf(" add\$%d, %%rax\n", $number); continue; } if (str_starts_with($string, '-')){ $string = substr($string, 1); [$number, $string] = extLeadNumber($string); printf(" sub \$%d, %%rax\n", $number); continue; } fprintf(STDERR, "予期しない文字です: %s\n", $string); return 1; } printf(" ret\n"); .globl main main: mov $1, %rax add $5, %rax sub $2, %rax ret 1 + 5 - 2
  116. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 テキストベースのパーサの限界 • 加減算ではソースコードを文字列として扱い、 先頭から1文字ずつ見てアセンブリ言語のソースコードに 変換していった •

    1 + 5 - 2 • 数字や記号が入ってくる順番とアセンブリ言語として書き出す 順番が同じだった • カッコ () や乗除が入ってくるとそうはいかなくなる 26 .globl main main: mov $1, %rax add $5, %rax sub $2, %rax ret
  117. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 テキストベースのパーサの限界 • 加減算ではソースコードを文字列として扱い、 先頭から1文字ずつ見てアセンブリ言語のソースコードに 変換していった •

    1 + 5 - 2 • 数字や記号が入ってくる順番とアセンブリ言語として書き出す 順番が同じだった • カッコ () や乗除が入ってくるとそうはいかなくなる • 5 + 6 * 7 26 .globl main main: mov $1, %rax add $5, %rax sub $2, %rax ret
  118. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 テキストベースのパーサの限界 • 加減算ではソースコードを文字列として扱い、 先頭から1文字ずつ見てアセンブリ言語のソースコードに 変換していった •

    1 + 5 - 2 • 数字や記号が入ってくる順番とアセンブリ言語として書き出す 順番が同じだった • カッコ () や乗除が入ってくるとそうはいかなくなる • 5 + 6 * 7 26 .globl main main: mov $1, %rax add $5, %rax sub $2, %rax ret .globl main main: mov $6, %rax imul $7, %rax add $5, %rax ret
  119. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 プログラム言語っぽさ • トークナイザ → パーサ →

    コードジェネレータ • プログラム言語ぽいのはトークナイザとパーサ • = 言語仕様を実装しているのはトークナイザとパーサ 28
  120. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 プログラム言語っぽさ • トークナイザ → パーサ →

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

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

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

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

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

    字句解析 • トークンの種類 識別子 変数名 関数名 記号 != <= += ++ ( ) … キーワード return if else … 文字列, 数字 "Hello, World" 30 0xff 1.06e2 … 29
  126. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 トークナイズ例 30 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; }
  127. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 トークナイズ例 30 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; }
  128. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 トークナイズ例 30 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; } ※ 図は雰囲気です。実際のトークン列とは異なります。 キーワード int 識別子 main 記号 ( キーワード void 記号 ) 記号 { キーワード for 記号 ( キーワード int 識別子 i 記号 = 文字列・数字 0 記号 ; 識別子 i 記号 <= 文字列・数字 100 記号 ; 識別子 i 記号 ++ 記号 ; 記号 )
  129. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 パーサ • トークン列から抽象構文木(abstract syntax tree /

    AST)を作る • 構文解析 • 出現順 → 処理すべき順 の変換 31 キーワード for 記号 ( キーワード int 識別子 i 記号 = 文字列・数字 0 記号 ; 識別子 i 記号 <= 文字列・数字 100 記号 ; 識別子 i 記号 ++ 記号 ; 記号 )
  130. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 パーサ • トークン列から抽象構文木(abstract syntax tree /

    AST)を作る • 構文解析 • 出現順 → 処理すべき順 の変換 31 /%@'03 /%@"44*(/ /%@7"3J /%@/6. JOJU /%@-& DPOE /%@7"3J /%@/6. /%@" JOD ※ 図は雰囲気です。実際のトークン列/ASTとは異なります。 キーワード for 記号 ( キーワード int 識別子 i 記号 = 文字列・数字 0 記号 ; 識別子 i 記号 <= 文字列・数字 100 記号 ; 識別子 i 記号 ++ 記号 ; 記号 )
  131. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 コードジェネレータ • ASTからアセンブリ言語のソース コードを作る • ASTのノードタイプごとにアセン

    ブリ言語に変換していく • 処理すべき順に整理されているの で淡々と処理する感じになる 32 .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 アセンブリ言語のソースコード
  132. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 コードジェネレータ • ASTからアセンブリ言語のソース コードを作る • ASTのノードタイプごとにアセン

    ブリ言語に変換していく • 処理すべき順に整理されているの で淡々と処理する感じになる • printf() の羅列 32 .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 アセンブリ言語のソースコード
  133. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 ここまでのまとめ 33 #include <stdio.h> int main(){

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

    main(){ printf("Hello, World."); } C言語のソースコード • C言語のソースコードをCコンパイラでコンパ イルしてアセンブリ言語のソースコードを作る 実行ファイル アセンブリ言語の ソースコード C言語の ソースコード
  135. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 ここまでのまとめ 33 コンパイル #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言語の ソースコード
  136. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 ここまでのまとめ 33 コンパイル #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言語の ソースコード
  137. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 言語仕様と生成規則 • コンパイラを作るにはトークナイザ、パーサ、コードジェネレータを作れば良い • トークナイザとコードジェネレータは比較的単純 •

    パーサは言語仕様そのものであり複雑なのでうかつに作ると言語仕様の拡張・変更に対 応できなくなったりする • そもそも言語仕様をどう定義する? • 生成規則を使うと良い 34
  138. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 EBNF • プログラム言語の生成規則を記述するための記法 EBNF (Extended Backus-Naur

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

    form) 36 expr は num から始まって "+" num または "-" num が0回以上続く expr = num ("+" num | "-" num)* numは数値を表す記号 1 1 + 5 1 + 5 - 2
  140. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 演算の優先順位の表現 37 expr = mul ("+"

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

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

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

    mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" • 上記で num だったところが primary になった expr = mul ("+" mul | "-" mul)* mul = num ("*" num | "/" num)* expr を処理するには先に mul を処理する必要がある ➡ 四則演算の優先順位を表現できた
  144. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 演算の優先順位の表現 37 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 を処理する必要がある ➡ 四則演算の優先順位を表現できた
  145. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 演算の優先順位の表現 37 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 を処理する必要がある ➡ 四則演算の優先順位を表現できた ➡ カッコの優先順位を表現できた
  146. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 もうちょっと育ったEBNF 38 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
  147. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 もうちょっと育ったEBNF 38 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で言語仕様がすべて表現できる(誇張を含みます)
  148. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 ENBFの実装方針 • EBNFに出てくるワード(非終端記号)を関数1つにマップしていくとパーサが作りやすい 40 expr =

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

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

    mul ("+" mul | "-" mul)* mul = primary ("*" primary | "/" primary)* primary = num | "(" expr ")" • この場合、expr(), mul(), primary(), num() を作る • それぞれ Node のインスタンスを返す • 一番上の Node (expr) をコードジェネレータに渡す /%@'03 /%@"44*(/ /%@7"3J /%@/6. JOJU /%
  151. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 primary() $this->tokenizer トークン列を保持 consume('(') カーソルの場所が (

    ならカーソルを進めてtrueを 返す ( でなければ false を返して何もしない expect(')') カーソルの場所が ) ならカーソルを進める ) でなければエラー newNodeNum(int $num) ノードタイプ ND_NUM のノードを作る 41 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
  152. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 primary() $this->tokenizer トークン列を保持 consume('(') カーソルの場所が (

    ならカーソルを進めてtrueを 返す ( でなければ false を返して何もしない expect(')') カーソルの場所が ) ならカーソルを進める ) でなければエラー newNodeNum(int $num) ノードタイプ ND_NUM のノードを作る 41 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
  153. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 primary() $this->tokenizer トークン列を保持 consume('(') カーソルの場所が (

    ならカーソルを進めてtrueを 返す ( でなければ false を返して何もしない expect(')') カーソルの場所が ) ならカーソルを進める ) でなければエラー newNodeNum(int $num) ノードタイプ ND_NUM のノードを作る 41 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
  154. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 mul() 42 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; } } }
  155. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 mul() • primary からはじまる 42 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; } } }
  156. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 mul() • primary からはじまる • "*"

    primary か "/" primary を 0回以上繰り返す 42 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; } } }
  157. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 mul() • primary からはじまる • "*"

    primary か "/" primary を 0回以上繰り返す 42 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
  158. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 mul() • primary からはじまる • "*"

    primary か "/" primary を 0回以上繰り返す 42 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
  159. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 expr() 43 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 ")"
  160. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 expr() • mul からはじまる 43 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 ")"
  161. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 expr() • mul からはじまる • "+"

    mul か "-" mul を 0回以上繰り返す 43 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 ")"
  162. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 expr() • mul からはじまる • "+"

    mul か "-" mul を 0回以上繰り返す • これで四則演算ができるパーサが 完成 43 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 ")"
  163. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 expr() • mul からはじまる • "+"

    mul か "-" mul を 0回以上繰り返す • これで四則演算ができるパーサが 完成 43 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
  164. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 expr() • mul からはじまる • "+"

    mul か "-" mul を 0回以上繰り返す • これで四則演算ができるパーサが 完成 43 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
  165. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 コードジェネレータの実装 45 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 ")"
  166. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 コードジェネレータの実装 ① トークナイザ ソースコードをトークン化する 45 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
  167. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 コードジェネレータの実装 ① トークナイザ ソースコードをトークン化する ② パーサ

    トークン列を expr としてパースする 45 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
  168. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 コードジェネレータの実装 ① トークナイザ ソースコードをトークン化する ② パーサ

    トークン列を expr としてパースする ③ コードジェネレータ 45 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
  169. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 コードジェネレータの実装 ① トークナイザ ソースコードをトークン化する ② パーサ

    トークン列を expr としてパースする ③ コードジェネレータ ④ exprノードからアセンブリ言語を作る 45 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
  170. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 gen($node) 46 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"); }
  171. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 gen($node) • ノードをアセンブリ言語に変換 46 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"); }
  172. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 gen($node) • ノードをアセンブリ言語に変換 • push /

    pop 46 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"); }
  173. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 gen($node) • ノードをアセンブリ言語に変換 • push /

    pop • スタックに値を積む / 取り出す 46 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"); }
  174. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 gen($node) • ノードをアセンブリ言語に変換 • push /

    pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 46 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"); }
  175. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 gen($node) • ノードをアセンブリ言語に変換 • push /

    pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 46 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
  176. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 gen($node) • ノードをアセンブリ言語に変換 • push /

    pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 46 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
  177. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 gen($node) • ノードをアセンブリ言語に変換 • push /

    pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 46 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 加減乗除ノード
  178. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 gen($node) • ノードをアセンブリ言語に変換 • push /

    pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 46 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の処理
  179. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 gen($node) • ノードをアセンブリ言語に変換 • push /

    pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 46 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の処理
  180. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 gen($node) • ノードをアセンブリ言語に変換 • push /

    pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 46 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の処理
  181. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 gen($node) • ノードをアセンブリ言語に変換 • push /

    pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 46 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の処理
  182. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 gen($node) • ノードをアセンブリ言語に変換 • push /

    pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 46 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の処理
  183. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 gen($node) • ノードをアセンブリ言語に変換 • push /

    pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 46 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つ取り出す
  184. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 gen($node) • ノードをアセンブリ言語に変換 • push /

    pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 46 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つの値を使って 演算する
  185. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 gen($node) • ノードをアセンブリ言語に変換 • push /

    pop • スタックに値を積む / 取り出す • 機械語では処理の切れ目でスタック経由で 値を受け渡しすることが多い 46 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レジスタ)の値を スタックに乗せる
  186. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 一連の処理 ① トークナイザ ソースコードをトークン化する ② パーサ

    トークン列を expr としてパースする ③ コードジェネレータ ④ exprノードからアセンブリ言語を作る 47 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
  187. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 一連の処理 ① トークナイザ ソースコードをトークン化する ② パーサ

    トークン列を expr としてパースする ③ コードジェネレータ ④ exprノードからアセンブリ言語を作る • 生成されたアセンブリ言語では最後に exprノードの結果をスタックに積んでる 47 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
  188. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 一連の処理 ① トークナイザ ソースコードをトークン化する ② パーサ

    トークン列を expr としてパースする ③ コードジェネレータ ④ exprノードからアセンブリ言語を作る • 生成されたアセンブリ言語では最後に exprノードの結果をスタックに積んでる ⑤ スタックから値を1つ取り出して rax レジスタに入れて終了 47 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
  189. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 ここまでのあらすじ 48 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
  190. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 ここまでのあらすじ EBNFで定義された言語仕様をもとに 48 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
  191. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 ここまでのあらすじ EBNFで定義された言語仕様をもとに トークナイザがソースコードをトークン列化 48 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
  192. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 ここまでのあらすじ EBNFで定義された言語仕様をもとに トークナイザがソースコードをトークン列化 パーサがAST化して 48 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
  193. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 ここまでのあらすじ EBNFで定義された言語仕様をもとに トークナイザがソースコードをトークン列化 パーサがAST化して コードジェネレータがアセンブリ言語ソース化した 48

    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
  194. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 最適化 • 素直にコンパイルされたアセンブリ言語のソース • push →

    push → pop → pop みたいなところがある 49 .globl main main: push $10 push $3 pop %rdi pop %rax imul %rax, %rdi push %rax pop %rax ret コンパイル結果
  195. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 最適化 • 素直にコンパイルされたアセンブリ言語のソース • push →

    push → pop → pop みたいなところがある 49 .globl main main: push $10 push $3 pop %rdi pop %rax imul %rax, %rdi push %rax pop %rax ret コンパイル結果
  196. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 最適化 • 素直にコンパイルされたアセンブリ言語のソース • push →

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

    push → pop → pop みたいなところがある • ここは結果として rdi レジスタや rax レジスタに 値を設定したいだけなので mov $3, %rdi とか mov $10, %rax とかすれば良く、 メモリアクセスが不要になって高速化する • こいういうのがコンパイラの最適化 49 .globl main main: push $10 push $3 pop %rdi pop %rax imul %rax, %rdi push %rax pop %rax ret コンパイル結果
  198. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 Cコンパイラのゴール • EBNFを少しずつ大きくしていけばCコンパイラは育っていく • コンパイラを育てていけばそのうち自分自身をコンパイルできる様になる •

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

    セルフホストという • (趣味の)コンパイラの到達点 • 今回はPHPで書いてるのでセルフホストには至らない • …PHPはCで書かれている訳で… • これでPHPのソースをコンパイル出来たら面白いかも…? • 「PHPで作ったCコンパイラでコンパイルしたPHPでCコンパイラを動かして…」の 無限ループ 50
  200. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 セルフホストまでの道 • chibiccのリポジトリでは合計316コミットある 51 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
  201. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 セルフホストまでの道 • chibiccのリポジトリでは合計316コミットある • pccは4月時点で138コミットまで進んでた 51

    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 4月 138/316
  202. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 セルフホストまでの道 • chibiccのリポジトリでは合計316コミットある • pccは4月時点で138コミットまで進んでた •

    196コミットでchibiccとしてはセルフホストできる模様 51 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 4月 138/316
  203. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 セルフホストまでの道 • chibiccのリポジトリでは合計316コミットある • pccは4月時点で138コミットまで進んでた •

    196コミットでchibiccとしてはセルフホストできる模様 • 今はAIの力を借りてここらへんまできました 51 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 4月 138/316 イマココ ???/316
  204. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 セルフホストまでの道 • chibiccのリポジトリでは合計316コミットある • pccは4月時点で138コミットまで進んでた •

    196コミットでchibiccとしてはセルフホストできる模様 • 今はAIの力を借りてここらへんまできました • chibiccのフォーク fuhsnn/slimcc ではPHPを コンパイルできるらしい (Rui Ueyamaさん情報) • https://github.com/fuhsnn/slimcc 51 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 4月 138/316 イマココ ???/316
  205. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 セルフホストまでの道 • chibiccのリポジトリでは合計316コミットある • pccは4月時点で138コミットまで進んでた •

    196コミットでchibiccとしてはセルフホストできる模様 • 今はAIの力を借りてここらへんまできました • chibiccのフォーク fuhsnn/slimcc ではPHPを コンパイルできるらしい (Rui Ueyamaさん情報) • https://github.com/fuhsnn/slimcc • chibiccの316コミットにさらに564コミット積んでるんすけど… 51 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 4月 138/316 イマココ ???/316
  206. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 セルフホストまでの道 • chibiccのリポジトリでは合計316コミットある • pccは4月時点で138コミットまで進んでた •

    196コミットでchibiccとしてはセルフホストできる模様 • 今はAIの力を借りてここらへんまできました • chibiccのフォーク fuhsnn/slimcc ではPHPを コンパイルできるらしい (Rui Ueyamaさん情報) • https://github.com/fuhsnn/slimcc • chibiccの316コミットにさらに564コミット積んでるんすけど… • どのコミットでPHPコンパイルできるかわからないけど… 51 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 4月 138/316 イマココ ???/316
  207. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 セルフホストまでの道 • chibiccのリポジトリでは合計316コミットある • pccは4月時点で138コミットまで進んでた •

    196コミットでchibiccとしてはセルフホストできる模様 • 今はAIの力を借りてここらへんまできました • chibiccのフォーク fuhsnn/slimcc ではPHPを コンパイルできるらしい (Rui Ueyamaさん情報) • https://github.com/fuhsnn/slimcc • chibiccの316コミットにさらに564コミット積んでるんすけど… • どのコミットでPHPコンパイルできるかわからないけど… • やるんすか…?自分…ライフワーク級だな… 51 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 4月 138/316 イマココ ???/316
  208. 長谷川智希 @tomzoh 低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 まとめ • Cコンパイラを書くとプログラム言語がどのように解釈されて、 CPUでどのように実行されるかが理解できる • Cコンパイラは難しくない

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

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

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

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

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

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