普段アセンブリコードを眺めるときは、最初に覚えた方法であることと、たいてい同時に実行して確認しているのもあって、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
には、c
、c++
、objective-c
、objective-c++
、go
、ada
、f77
、などなどが指定できる。
ところで、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