$30 off During Our Annual Pro Sale. View Details »

Goのコンパイラをみてみよう 〜iotaを通じて〜 @MCCMMANCC 2019 / div...

kosui
December 22, 2019
300

Goのコンパイラをみてみよう 〜iotaを通じて〜 @MCCMMANCC 2019 / dive into go complier with iota

kosui

December 22, 2019
Tweet

Transcript

  1. ⽬次 1. iota とは 2. iota の不思議 3. Goコンパイラ gc

    の流れ 4. Goコンパイラ gc のコードを追ってみよう
  2. 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" )
  3. 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 )
  4. iota とは iota のカウンタは const が現れるとリセットされる const ( A int

    = iota // 0 B // 1 C // 2 ) const ( D int = iota // 3 ... ではなく 0 ! E // 1 F // 2 )
  5. 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 機械語を⽣成
  6. コンパイラの流れ: 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 機械語を⽣成
  7. コンパイラの流れ: 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 機械語を⽣成
  8. コンパイラの流れ: 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 機械語を⽣成
  9. コンパイラの流れ: 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 // ...
  10. コンパイラの流れ: 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 } ➡ この関数がどこから呼ばれているか調べれば良さそう
  11. カウンタをリセットする犯⼈ 犯⼈: 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 }