『低レイヤを知りたい人のための Cコンパイラ作成入門』感想

低レイヤを知りたい人のための Cコンパイラ作成入門

インターネット上で公開されている範囲については実装が終わりました。

github.com

内容について

非常によかったです。わかりやすかったです。僕は技術書の場合、だいたい冒頭だけ読んで、実装してみて、本の内容と比較するという読み方をしています。この本については、ある機能を実装するにあたって、「このへんは今はやらなくていいや」と割り切るのが上手いと感じました。実装していると「これもやらなきゃじゃん」「こうなってるほうがいいよなー」みたいな気持ちがどんどん生まれますが、実際にを読んでみると「これは後ででいいです」とバッサリ。これはCコンパイラを複数回作った経験とコンピューターサイエンスに関する体系的な知識があるがゆえにできているのかなーと思っています。

このコンテンツを読む前に期待している点としては、「言語実装に関する理解が深まること」と「アセンブリ機械語を生成するフェイズの知識が得られること」の2点でした。やってみた感じとしては、前者は特に深まったなーと思っています。tokenize, parse というフェイズごとに何をしているのかという点や実際のバイナリをつくるまでの過程というのが理解できました。

一方で後者は、いまだによくわかりません。吐くアセンブリの意味を正しく理解できているかというとあやしいし……。これはどちらかというと文章としての問題ではなく、読み手としてアセンブリと仲良くなる努力がまだ足りてないのかなーと思っています。どうにかしないとなー。いい教材みたいなのがあると助かります。fizzbuzzみたいなのを自分で書いてみるか。

これから

上記のアセンブリと仲良くなるっていうのと、あとはCで書くのがダルいので他言語で実装しなおすかもしれません。あるいはもうちょい自力ですすめるか。あと解析フェイズの理解が進んだせいで TaPL の言語実装が適当すぎることに気づいたのでそっちを直したくもなっています。どうしよう。

動いているようす

こんな感じになります。ちゃんと動いてますね。中間生成物のアセンブリもチラ見せ。

$ make test
bin/hkdcc -test
OK
./test.sh
0; => 0
42; => 42
1+2; => 3
1+10+2; => 13
3-1; => 2
23-12; => 11
3 - 1; => 2
70+2*5*5; => 120
4/2; => 2
5+6*7; => 47
5*(9-6); => 15
(3+5)/2; => 4
1; 2; => 2
a = 1; => 1
a = 1; a; => 1
a = 1; a + 1; => 2
a = b = 1; a + b; => 2
1 == 1; => 1
a = 1; 1 == a; => 1
a = 2; 1 == a; => 0
a = 2; a == 1; => 0
a = 2; a == a; => 1
a = 1 == 1; a; => 1
a = 0 == 1; a; => 0
1 != 1; => 0
2 != 1; => 1
OK
$ cat tmp.s
.intel_syntax noprefix
.global _main
_main:
  push rbp
  mov rbp, rsp
  sub rsp, 208
  push 2
  push 1
  pop rax
  pop rdi
  cmp rdi, rax
  setne al
  movzx rax, al
  push rax
  pop rax
  mov rsp, rbp
  pop rbp
  ret