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

Goコンパイラを作ってGoをもっと理解する / Build a Go compiler to ...

Avatar for ikura-hamu ikura-hamu
October 28, 2026

Goコンパイラを作ってGoをもっと理解する / Build a Go compiler to better understand Go

コンパイラつくろう

Go Conference 2026 で採択していただいてインフルエンザで発表できず、Go Connect #18 で発表させていただいた内容です。

プロポーザル: https://ikura-hamu.work/blog/260924_go-conference-26-proposal/

Avatar for ikura-hamu

ikura-hamu

October 28, 2026

More Decks by ikura-hamu

Other Decks in Programming

Transcript

  1. ikura-hamu / いくら・はむ 東京科学大学デジタル創作同好会 traP 修士 1 年 @ikura-hamu @ikura_hamu

    go run go.ikura-hamu.work/card@latest 2 / 31 Goコンパイラを作ってGoをもっと理解する
  2. Go Far, Go Together 今年の Go Conference のテーマは「Go Far, Go

    Together」です。 今日の僕の目標は、Go コンパイラ自作に取り組む仲間を増やすことです。 3 / 31 Goコンパイラを作ってGoをもっと理解する
  3. コンパイラとは 「ある言語で書かれたプログラムを、より低級な(コンピュータで実行可能な形式に近 い)表現に書き直すプログラム」をコンパイラと呼ぶ。 例 TypeScriptの JavaScriptの tsc プログラム プログラム Go

    コンパイラで Go のプログラムを 実行可能なバイナリに変換する TypeScript コンパイラで TypeScript のプログラムを JavaScript に変換する 5 / 31 Goコンパイラを作ってGoをもっと理解する
  4. ooo ができること Go のプログラム(の一部)を x86_64 形式のアセンブリに変換する。 プログラム (Go) func add(a

    int, b int) int { return a + b } コンパイラ プログラム (アセンブリ) _add: push rbp mov rbp, rsp mov rax, [rbp + 1 * 8 + 8] push rax mov rax, [rbp + 2 * 8 + 8] push rax mov rax, rbp sub rax, 8   7 / 31 Goコンパイラを作ってGoをもっと理解する
  5. ooo はセルフホストが可能 セルフホスト: コンパイラが自身のプログラ ムをコンパイルできること ooo はセルフホストできる。 ooo の プログラム

    (Go) Go コンパイラ ooo2.s ooo1 Assembler Linker (第2世代) (第1世代) 内容が⼀致 ooo2 (第2世代) ooo3.s (第3世代) 8 / 31 Goコンパイラを作ってGoをもっと理解する
  6. セルフホストの様子 ooo の プログラム (Go) Go コンパイラ ooo2.s ooo1 Assembler

    Linker (第2世代) (第1世代) 内容が⼀致 ooo2 2 (第 世代) ooo3.s 3 (第 世代) 9 / 31 Goコンパイラを作ってGoをもっと理解する
  7. セルフホスト ooo のプログラムで使っている機能だけを実装すればよい。 しかし、ooo が対応する機能だけで ooo を書く必要がある。 ooo の プログラム

    (Go) Go コンパイラ ooo2.s ooo1 1 Assembler Linker (第2世代) (第 世代) 内容が⼀致 ooo2 2 (第 世代) ooo3.s (第3世代) 11 / 31 Goコンパイラを作ってGoをもっと理解する
  8. 開発効率と実装コストのトレードオフ 減らす 少ない 簡単 🤩 悪い 不便 😱 🤔 コンパイラが

    対応する機能 実装量 実装の難しさ 実装の効率 便利さ 増やす 多い 難しい 😱 ⾼い 便利 🤩 12 / 31 Goコンパイラを作ってGoをもっと理解する
  9. どこまで実装するのか?(byte 型) 実装の難しさ は 1 バイトだが、ooo の他の型は 8 の倍数バイトで、アドレスの計算が煩雑に なる

    s := "Hello, world" byte // s[0] のようにアクセスすると // byte 型が得られる fmt.Printf("%[1]v, %[1]T\n", s[0]) // → 72, uint8 使わない場合の回避方法 // s[0:1] のように始点と終点を指定すると // string 型が得られる fmt.Printf("%[1]v, %[1]T\n", s[0:1]) // → H, string でインデックスを指定すると byte になるが、スライスで取ると string とし 実装しない て容易に扱える 容易な代替手法があるため。 string 13 / 31 Goコンパイラを作ってGoをもっと理解する
  10. どこまで実装するか?(スライス型) 実装の難しさ 動的な長さの配列を扱うには、ヒープ領 域を上手く管理する必要がある 使わない場合の回避方法 0x1000 slice 0x1008 0x1010 capacity

    length 内部配列の先頭アド レス 固定長の配列や連結リストを使う。前者は 実装する 柔軟性に欠け、後者はランダムアクセスで メモリ効率が悪いが簡単な実装を の計算量が増加する。 用いることで対応できる。 14 / 31 Goコンパイラを作ってGoをもっと理解する
  11. エスケープ解析 スコープの外でも参照される変数を検出し、ヒープに配置する func main() { var a *int a =

    f() // ... } func f() *int { b := 1 // スコープ外で参照されている! return &b // ローカル変数のポインタを返す } 18 / 31 Goコンパイラを作ってGoをもっと理解する
  12. composite literal スライスや構造体、mapなどのリテラルは、 typex intposition struct { 全て同一の「composite literal」という構 }

    y int pos := position{1, 2} 文として扱われている。 全く異なるように見える二つの記述は、実 list0: :=1, []int{ は仕様では同じ構文として扱われている。 1:2: 2,3, } 21 / 31 Goコンパイラを作ってGoをもっと理解する
  13. 組み込みの print と println Go では、標準エラー出力に文字を出力するようになっている。 Function Behavior print println

    prints all arguments; formatting of arguments is implementation-specific like print but prints spaces between arguments and a newline at the end Implementation restriction: print and println need not accept arbitrary argument types, but printing of boolean, numeric, and string types must be supported. [1] しかし、仕様では どこに出力するかは規定されていない、実装依存 ! (builtin package の go doc は writes the result to standard error. と記述している。) 22 / 31 Goコンパイラを作ってGoをもっと理解する
  14. ooo ではどうなっているか? と println は 標準出力 に文字を出力する。 ooo はパッケージの import

    を実装しておらず、組み込み関数の範囲で標準出力に文 字を出す手段が必要だった。 アセンブリで print 関数を実装しておき、ooo はこの print を利用するコードを生成 print .global _print _print: push rbp mov rbp, rsp mov rax, [rbp + 24] # str.len push rax mov rax, [rbp + 16] # str.str push rax   23 / 31 Goコンパイラを作ってGoをもっと理解する
  15. Go コンパイラ自作を始めるには? コンパイラづくりを始める前にやるべきこと 1. ゴールを決める 2. コンパイルのターゲットを決める 3. AI ルールを決める

    ゴール コンパイルの ターゲット AI ルール 作る前に決める 実装 25 / 31 Goコンパイラを作ってGoをもっと理解する
  16. 1. ゴールを決める セルフホスト (ooo はこれ) ある Go 機能を実装できるまで ある 標準ライブラリ・OSS

    をコンパイルできるまで 飽きるまで 期限を決めてそこまで ゴール コンパイルの ターゲット AI ルール 作る前に決める 実装 26 / 31 Goコンパイラを作ってGoをもっと理解する
  17. 2. コンパイルのターゲットを決める x86_64 アセンブリ(ooo はこれ) Plan 9 アセンブリ LLVM WebAssembly

    他の言語 ゴール コンパイルの ターゲット AI ルール 作る前に決める 実装 27 / 31 Goコンパイラを作ってGoをもっと理解する
  18. 3. AI ルールを決める 全部禁止 補完だけ(ooo はほぼこれ) チャットで相談は OK ゴール コンパイルの

    ターゲット AI ルール 作る前に決める 実装 28 / 31 Goコンパイラを作ってGoをもっと理解する
  19. wooo(うおおお) WebAssembly Toy Go Compiler 1. ゴール セルフホスト goroutine GC

    2. ターゲット WebAssembly text format 3. AI ルール 補完だけ 29 / 31 Goコンパイラを作ってGoをもっと理解する
  20. まとめ セルフホストできる Go コンパイラ ooo を作った Go コンパイラを作るには、Go 特有の課題があ った

    Go コンパイラを作ることで、Go の仕様に詳しく なることができる ikura-hamu は、自作 Go コンパイラ仲間を増や したい 30 / 31 Goコンパイラを作ってGoをもっと理解する