Pass crashes if test code doesn't contain any printf
The pass fails to instrument the test code if the test code doesn't
contain any call to printf
itself.
The stack trace of opt
when run on the raw clang-generated bitcode
(pre.bc
) is as follows:
Stack dump:
0. Program arguments: opt -load build/Yield/libYield.so -yield build/pre.bc -o build/post.bc
1. Running pass 'ayekat's test pass' on module 'build/pre.bc'.
LLVMSymbolizer: error reading file: No such file or directory
#0 0x00007f0649d90b1b llvm::sys::PrintStackTrace(llvm::raw_ostream&) (/usr/bin/../lib/libLLVM-7.so+0x8feb1b)
#1 0x00007f0649d8ef74 llvm::sys::RunSignalHandlers() (/usr/bin/../lib/libLLVM-7.so+0x8fcf74)
#2 0x00007f0649d8f0fe (/usr/bin/../lib/libLLVM-7.so+0x8fd0fe)
#3 0x00007f064915ce00 __restore_rt (/usr/bin/../lib/libc.so.6+0x37e00)
#4 0x00007f06469aaa54 llvm::Value::getType() const (build/Yield/libYield.so+0x10a54)
#5 0x00007f06469ab3fa llvm::LoadInst::LoadInst(llvm::Value*, char const*, bool, llvm::Instruction*) (build/Yield/libYield.so+0x113fa)
#6 0x00007f06469ac795 llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>::CreateLoad(llvm::Value*, llvm::Twine const&) (build/Yield/libYield.so+0x12795)
#7 0x00007f06469a9e97 (anonymous namespace)::Yield::insertGlobalCountIncrement(llvm::BasicBlock&) (build/Yield/libYield.so+0xfe97)
#8 0x00007f06469a9cab (anonymous namespace)::Yield::runOnFunction(llvm::Function&) (build/Yield/libYield.so+0xfcab)
#9 0x00007f06469a9aaf (anonymous namespace)::Yield::runOnModule(llvm::Module&) (build/Yield/libYield.so+0xfaaf)
#10 0x00007f0649e8a720 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/usr/bin/../lib/libLLVM-7.so+0x9f8720)
#11 0x0000561762ea5691 (opt+0x26691)
#12 0x00007f0649149223 __libc_start_main (/usr/bin/../lib/libc.so.6+0x24223)
#13 0x0000561762ea649e (opt+0x2749e)
make: *** [Makefile:37: build/post.bc] Segmentation fault (core dumped)
Need to find out why it fails at particularly that moment (notice it
fails on CreateLoad
, which IMHO has nothing to do with printing).
The only difference in the bytecode (before running our pass) is the following:
--- a/pre.bc
+++ b/pre.bc
@@ -4,6 +4,8 @@
target triple = "x86_64-pc-linux-gnu"
@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
+@.str.1 = private unnamed_addr constant [18 x i8] c"globalcount = %d\0D\00", align 1
+@globalcount = internal global i32 0, align 4
; Function Attrs: noinline nounwind optnone sspstrong uwtable
define dso_local i32 @main() #0 {
@@ -43,6 +45,8 @@
br label %3
; <label>:20: ; preds = %3
+ %21 = load i32, i32* @globalcount, align 4
+ %22 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.1, i32 0, i32 0), i32 %21)
ret i32 0
}
I initially suspected that the pass's own reference to printf
would be
causing this, but even after removing that part from the pass, opt
still crashes there.
Need to find out more about why this happens; all I've got is one very crazy suspicion: LLVM runs other optimisers—not just our pass—as well, and one of them notices that our code has no side-effects whatsoever, and ends up with an empty program, which is not supposed to happen.