LLVM本体にデバッグログを入れる
2021-10-01
TechLLVMのエラーメッセージはあまり親切でない。Rustの異常な親切さに慣れてきたのでそう思うのかもしれないが。
例えばllvm-disの出したエラーがこれ:
Assertion failed: (InitVal->getType() == getValueType() && "Initializer type must match GlobalVariable type"), function setInitializer, file /Users/yhara/research/llvm-12.0.1.src/lib/IR/Globals.cpp, line 405.
型が違うことはなんとか分かるが、せめて何と何だったのかくらいは教えてくれないとデバッグのしようがない。
まあ不正なデータでも食わせない限りLLVMのエラーを見ることはないかもしれないが、LLVMを使った処理系を書いていると不正なデータが生成されてしまったりするのである。
ということでllvm-disにデバッグログを入れてみた。ありがたいことにファイル名と行番号が出ているので、そこにコードを足す。
if (InitVal->getType() != getValueType()) {
InitVal->getType()->print(dbgs());
getValueType()->print(dbgs());
}
assert(InitVal->getType() == getValueType() &&
"Initializer type must match GlobalVariable type");
LLVMの作法は全然わかっていないが、Type
についてはprint
というメソッドで調べられるようだ。dbgsは何らかのIOだと思うが、--debug
オプションを付けないと表示されないので注意。
この状態で改めて実行してみるとこうなった。(コンパイル方法については一つ前の記事を参照)
$ ./bin/llvm-dis --debug ~/proj/shiika/examples/a.sk.bc
Args: ./bin/llvm-dis --debug /Users/yhara/proj/shiika/examples/a.sk.bc
%"Meta:A"**%"Meta:A"*Assertion failed: (InitVal->getType() == getValueType() && "Initializer type must match GlobalVariable type"), function setInitializer, file /Users/yhara/research/llvm-12.0.1.src/lib/IR/Globals.cpp, line 405.
改行がなくて分かりづらいが、
InitVal->getType()
が%"Meta:A"**
で、getValueType()
が%"Meta:A"*
であることが分かった。これでなんとかデバッグが続けられそうだ。
おまけ
ちなみにどんな原因でこのエラーが出ていたかというと、これが原因だった。
- let null = self.llvm_type(ty).ptr_type(AddressSpace::Generic).const_null();
+ let null = self.llvm_type(ty).into_pointer_type().const_null();
上は%"Meta:A"** null
で、下は%"Meta:A"* null
になる。(と思う)
同じコードで生成した.llではどっちも
@"::A" = global %"Meta:A"* null
になるのが不思議だが。