微妙に便利なgccのオプション

普段アセンブリコードを眺めるときは、最初に覚えた方法であることと、たいてい同時に実行して確認しているのもあって、objdumpを使っている。

が、コンパイル結果のアセンブリコードを見たいだけなら-Sで十分である。

$ cat "double add(double x, double y) {return x + y;}" > add.c
$ gcc -S -O2 -c add.c
$ ls
add.c add.s
$ cat add.s
; ...
add:
.LFB0:
    .cfi_startproc
    addsd   %xmm1, %xmm0
    ret
    .cfi_endproc
; ...

そんなことは皆知っているのだが、GCC-を渡すと標準入力から入力を受け取ることもできる。

$ cat "double add(double x, double y) {return x + y;}" | gcc -S -O2 -c - -o add.s

このとき、出力ファイル名を指定しないと-.oみたいなファイルができて面倒なことになるので注意だ(消そうとしてrm -.oとかするとそういうオプションだと思われてエラーになるが、rm ./-.oとすると消せる)。

普段GCCは拡張子で言語を判断しているようなのだが、標準入力からコードを渡すと言語が判定できないと怒られる。 その場合 -x LANGUAGEとして言語を指定できる。LANGUAGEには、cc++objective-cobjective-c++goadaf77、などなどが指定できる。

ところで、gccで何らかのオプションをつけた時にどのようなマクロが定義されるかなどに興味のある人は多いだろう[要出典]GCCにはプリプロセッサデバッグするための機能があり、-dMとするとdefineされているものを全てダンプしてくれる。

これを使えば、例えばSIMD命令が使えるはずのCPUで__AVX2__のようなマクロが指定されるかどうか調べることができる。

$ gcc -O2 -march=native -mtune=native -dM
gcc: fatal error: no input files
compilation terminated.

おっと、そもそも入力ファイルがないと怒られてしまった。 こういう時の-だ。プリプロセッサだけ見たいのでファイルの内容なんぞどうでもよいのだから、/dev/nullをリダイレクトすればよいだろう。gccが混乱しないように-xcだけつけて……

$ gcc -O2 -march=native -mtune=native -dM -xc - < /dev/null
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status

おっと、mainがなかったのでリンクエラーになってしまった。どうやら存在しないファイルをちゃんとコンパイルしようとしてしまっている。 こういうときはプリプロセッサだけしか実行しないオプション、-Eの出番だ。普段はプリプロセッサマクロのデバッグに使うが、こういう時にも使える。

$ gcc -O2 -march=native -mtune=native -dM -E -xc - < /dev/null
# ...

あとは、想定している命令セットが検出されたかどうか、grepでもすればよい。

$ gcc -O2 -march=native -mtune=native -dM -E -xc - < /dev/null | grep AVX
#define __AVX__ 1
#define __AVX2__ 1