超備忘録:教科書どおりにCFGが出力できないときに使った手法


なんで、教科書どおりにoptが動かないんだぁぁぁ

Clang と llvm (というかopt)を使えば簡単にコールグラフやCFGが描画できる…って教科書には書いてあります。

教科書と言っているのは

とか

とかです。

書き方は以下の通りが一般的に記述されています。

$ clang -emit-llvm -S -o test.ll -c test.c
$ opt -dot-cfg test.ll

だが動かない。出力されている気配もない。
おまけに怒られる。

$ opt -dot-cfg test.ll
WARNING: You're attempting to print out a bitcode file.
This is inadvisable as it may cause display problems. If
you REALLY want to taste LLVM bitcode first-hand, you
can force output with the `-f' option.

救世主現わる

なぞすぎたのですが、以下の例を参考にやってみました。

コードと最終的なコマンドはここ↓のを使いました。

main1.cpp
static void D() { }
static void Y() { D(); }
static void X() { Y(); }
static void C() { D(); X(); }
static void B() { C(); }
static void S() { D(); }
static void P() { S(); }
static void O() { P(); }
static void N() { O(); }
static void M() { N(); }
static void G() { M(); }
static void A() { B(); G(); }

int main() {
  A();
}
$ clang++ -S -emit-llvm main1.cpp -o - | opt -analyze -dot-callgraph --callgraph-dot-filename-prefix=main
Cannot specify -analyze under new pass manager, either specify '-enable-new-pm=0', or use the corresponding new pass manager pass, e.g. '-passes=print<scalar-evolution>'. For a full list of passes, see the '--print-passes' flag.

うーん、もう一歩みたいだ…

そこでひと工夫、というかエラーの指示に従って作成。

$ clang++ -S -emit-llvm main1.cpp -o - | opt -enable-new-pm=0  -analyze -dot-callgraph --callgraph-dot-filename-prefix=test
Writing 'test.callgraph.dot'...
Printing analysis 'Print call graph to 'dot' file':
Pass::print not implemented for pass: 'Print call graph to 'dot' file'!

むむ、出力されたっぽい。

ためしに

$ dot -Tpng test.callgraph.dot > test.png

すると…、

でた。

これから詳しく調べますが、昔のようにはいかないのかもしれません。
備忘録なので、これ以上の事はつっこまない。以上。

調べてみて

かなーり昔は analyze コマンドがあったらしい。今はないけど。で、

今は、opt に -analyze を付けいないと解析してくれないみたい。
…ってのはわかった。