Slide 1

Slide 1 text

Goのコンパイラをみてみよう 〜iotaを通じて〜 MCC 2013年⼊部 株式会社ディー・エヌ・エー 岩佐幸翠

Slide 2

Slide 2 text

⾃⼰紹介 岩佐 幸翠 (@uniuniunicode) 農⼯⼤ 修⼠課程(情報⼯学)を今年春に卒業 株式会社ディー・エヌ・エー タクシー配⾞アプリ「MOV」のチームに所属 GAE・Go・TypeScriptをやっています

Slide 3

Slide 3 text

突然ですが 皆さんの好きな⾔語はなんですか Go Ruby Python TypeScript C++ Java Kotlin Swift Haskell etc...

Slide 4

Slide 4 text

今⽇伝えたいこと コンパイラのコードを読む⾯⽩さ コンパイラのコードを読むことで、普段何気なく使っている⾔語機能がどのように実装さ れているか知ることができる

Slide 5

Slide 5 text

コンパイラに興味を持ったきっかけ Goの⾔語機能の⼀つ「iota」の不思議な仕様が気になった でも、既存のドキュメントやブログには詳しい話は書かれていない ➡ ⾃分でコンパイラのコードを読んで調べてみよう!

Slide 6

Slide 6 text

⽬次 1. iota とは 2. iota の不思議 3. Goコンパイラ gc の流れ 4. Goコンパイラ gc のコードを追ってみよう

Slide 7

Slide 7 text

Goの定数の宣⾔ Goでは以下のように定数を宣⾔する // 1 つの定数を宣⾔ const Answer int = 42 // 複数の定数を宣⾔ const ( BadRequest = 400 Unauthorized = 401 Forbidden = 403 NotFound = 404 ) const ( Alice = "alice" // "alice" Bob // "bob"... ではなく "alice" Charlie // "alice" )

Slide 8

Slide 8 text

iota とは 定数に連番を割り振る機能 type Direction int // Direction の型をint へalias // iota 無し const ( Up Direction = 0 Down = 1 Left = 2 Right = 3 // いちいち書くのつらい... ) // iota 有り const ( Up Direction = iota // 0 Down // 1 Left // 2 Right // 3 )

Slide 9

Slide 9 text

iota とは iota のカウンタは const が現れるとリセットされる const ( A int = iota // 0 B // 1 C // 2 ) const ( D int = iota // 3 ... ではなく 0 ! E // 1 F // 2 )

Slide 10

Slide 10 text

iota とは 演算を含めることもできる const ( mono int = iota + 1 // 1 di // 2 tri // 3 tetra // 4 )

Slide 11

Slide 11 text

iota のまとめ 定数を宣⾔する時、連番を⽣成してくれる const が出現する度にカウンタが0に戻る ➡ つまり iota は状態を持っている iota クイズ iota とは... 1. 定数である 2. 関数である 3. マクロである 4. オブジェクトである

Slide 12

Slide 12 text

iota クイズのこたえ iota とは... 定数である 関数である マクロである オブジェクトである これマジ?

Slide 13

Slide 13 text

iota の不思議 なぜ定数であるはずの iota から、どんどん連番が出てくるのか? どうやって const が出現する度に0にリセットする⽅法を実現しているのか?

Slide 14

Slide 14 text

Goのコンパイラのコードを読んで iotaの不思議を解き明かしましょう! 「定数の宣⾔」と iota が、コンパイラにどのように扱われるのかを追います

Slide 15

Slide 15 text

Goコンパイラ gc の流れ Goコンパイラにも複数あるが、今回はそのうちの1つ gc の話 今⽇話すのは以下⿊字のみ 1. syntax パッケージ 1.1 ソースコードから字句リストへ 1.2 字句リストを構造化する 2. gc パッケージ 2.1 構造化されたソースコードからASTを⽣成 2.2 型チェック 2.3 SSA(中間表現)へ変換 3. ssa パッケージ 3.1 SSAを最適化する 3.2 機械語を⽣成

Slide 16

Slide 16 text

Goコンパイラ gc の流れ ASTとは プログラムの構⽂構造を⽊構造で表現したもの gc では型チェックのために使われる

Slide 17

Slide 17 text

コンパイラの流れ: 1.1 ソースコードから字句リストへ分割 1. syntax パッケージ 1.1 ソースコードから字句リストへ 1.2 字句リストを構造化する 2. gc パッケージ 2.1 構造化されたソースコードからASTを⽣成 2.2 型チェック 2.3 SSA(中間表現)へ変換 3. ssa パッケージ 3.1 SSAを最適化する 3.2 機械語を⽣成

Slide 18

Slide 18 text

コンパイラの流れ: 1.1 ソースコードから字句リストへ分割 ファイルごとに、ソースコードを左から右へ線形に解析し、 最⼩の意味単位(トークン)ごとに分割する ➡ ここはiotaとは関係なさそう

Slide 19

Slide 19 text

コンパイラの流れ: 1.2 字句リストを構造化する 1. syntax パッケージ 1.2 字句リストを構造化する 1.1 ソースコードから字句リストへ 2. gc パッケージ 2.1 構造化されたソースコードからASTを⽣成 2.2 型チェック 2.3 SSA(中間表現)へ変換 3. ssa パッケージ 3.1 SSAを最適化する 3.2 機械語を⽣成

Slide 20

Slide 20 text

コンパイラの流れ: 1.2 字句リストを構造化する ASTへの変換がしやすいように前処理

Slide 21

Slide 21 text

コンパイラの流れ: 2. 構造化されたソースコードからASTを⽣成 2. gc パッケージ 2.1 構造化されたソースコードからASTを⽣成 1. syntax パッケージ 1.1 ソースコードを字句リストへ分割 1.2 字句リストを構造化する 2.2 型チェック 2.3 SSA(中間表現)へ変換 3. ssa パッケージ 3.1 SSAを最適化する 3.2 機械語を⽣成

Slide 22

Slide 22 text

コンパイラの流れ: 2. 構造化されたソースコードからASTを⽣成 File 構造体の declList に格納されていた importDecl , funcDecl , constDecl , varDecl を、それぞれASTのノードを表す構造体 Node へ変換する type Node struct { // Tree structure. // Generic recursive walks should follow these fields. Left *Node Right *Node Ninit Nodes Nbody Nodes List Nodes Rlist Nodes // ...

Slide 23

Slide 23 text

コンパイラの流れ: 2. 構造化されたソースコードからASTを⽣成 なんと、 Node 構造体は、⾊々な⽤途の値を格納してしまう XOffset というプロパティを持 っている // Various. Usually an offset into a struct. // ... Xoffset int64 また、 Node 構造体が持つ SetIota 関数は XOffset にiotaの値を代⼊する func (n *Node) SetIota(x int64) { n.Xoffset = x } ➡ この関数がどこから呼ばれているか調べれば良さそう

Slide 24

Slide 24 text

カウンタをリセットする犯⼈ 犯⼈: declList 内のconstDeclをASTに変換する処理 最後に処理したconstDeclとGroupが違う場合はiotaのカウンタがリセットされる type constState struct { group *syntax.Group // 最後にNode へ変換されたconstDecl のGroup // ... iota int64 } func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []*Node { // 最後に処理したConstSpec と今処理しているConstSpec の // Group が異なる場合はiota のカウンタをリセットする if decl.Group == nil || decl.Group != cs.group { *cs = constState{ group: decl.Group, } } // ... cs.iota++ return nn }

Slide 25

Slide 25 text

まとめ iota iota は定数だけど連番を返したりリセットされたりする iota のカウントを進める処理・リセットする処理はASTの⽣成時に⾏われる iota のロジックはコンパイラのコードにめちゃくちゃゴリゴリ実装されている やっていくぞ Goのコンパイラのコードはわりときれいで読みやすいのでおすすめ コンパイラのコードを読んで、すぐに何かに役に⽴つことはないけれど、 技術的関⼼を持って⾃分の知⾒を広げることは楽しい