Assertion failure in llc when using exception handling

Hi,

I’m trying to compile an llvm program which makes use of exception handling. While compiling the code with llc i get the following assertion failure

llc: FunctionLoweringInfo.cpp:163: void llvm::FunctionLoweringInfo::clear(): Assertion `CatchInfoFound.size() == CatchInfoLost.size() && “Not all catch info was assigned to a landing pad!”’ failed.
0 llc 0x0000000000d5d23f
1 llc 0x0000000000d5f026
2 libpthread.so.0 0x00007f47688d38f0
3 libc.so.6 0x00007f4767bc3a75 gsignal + 53
4 libc.so.6 0x00007f4767bc75c0 abort + 384
5 libc.so.6 0x00007f4767bbc941 __assert_fail + 241
6 llc 0x00000000008a5a19 llvm::FunctionLoweringInfo::clear() + 1353
7 llc 0x00000000009364de llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) + 3102
8 llc 0x0000000000ce828f llvm::FPPassManager::runOnFunction(llvm::Function&) + 671
9 llc 0x0000000000ce834b llvm::FPPassManager::runOnModule(llvm::Module&) + 75
10 llc 0x0000000000ce7d84 llvm::MPPassManager::runOnModule(llvm::Module&) + 564
11 llc 0x0000000000ce7ee0 llvm::PassManagerImpl::run(llvm::Module&) + 160
12 llc 0x0000000000565941 main + 3009
13 libc.so.6 0x00007f4767baec4d __libc_start_main + 253
14 llc 0x0000000000563849
Stack dump:
0. Program arguments: llc b.bc

  1. Running pass ‘Function Pass Manager’ on module ‘b.bc’.
  2. Running pass ‘X86 DAG->DAG Instruction Selection’ on function ‘@main
    Aborted

I only get this error when the b.bc file is generated with opt -O3. The program compiles and executes just fine with opt -O2. I was able to find out the minimum number of optimization passes that cause this crash. They are

opt -inline -jump-threading -instcombine -licm -loop-unswitch -o b.bc a.bc

I’m attaching the original unoptimized file a.bc.gz and the optimized version b.bc.gz. I apologize for sending in such large files, but I just couldn’t reproduce this problem with smaller programs. By putting some debug statements in llc I was able to narrow the problem in b.bc down to following lines of code

Unwind.i74.i.i: ; preds = %normal44.i79.i.i
%153 = call i8* @llvm.eh.exception() ; <i8*> [#uses=2]
%154 = call i32 (i8*, i8*, …)* @llvm.eh.selector(i8* %153, i8* bitcast (i32 (…)* @__gxx_personality_v0 to i8*),
i8* null) ; [#uses=0]
invoke void @_Unwind_Resume_or_Rethrow(i8* %153)
to label %.noexc83.i.i unwind label %lpad51.preheader.i.i

lpad51.preheader.i.i: ; preds = %Unwind.i74.i.i, %Unwind.i61.i.i
%155 = icmp eq i8* %58, null ; [#uses=1]
%156 = bitcast i8* %61 to %File* ; <%File*> [#uses=1]
br i1 %155, label %Unwind.loopexit.us-lcssa.us.i.i, label %normal31.i.i.i

Unwind.loopexit.us-lcssa.us.i.i: ; preds = %lpad51.preheader.i.i
%157 = call i8* @llvm.eh.exception() ; <i8*> [#uses=2]
%158 = call i32 (i8*, i8*, …)* @llvm.eh.selector(i8* %157, i8* bitcast (i32 (…)* @__gxx_personality_v0 to i8*), i8* null) ; [#uses=0]
br label %Unwind.i.i

The Unwind.loopexit.us-lcssa.us.i.i landing pad gets added to CatchInfoLost but not to CatchInfoFound which causes the assertion to fail. I have also attached the output from bugpoint -run-llc b.bc

Is there something wrong with the original ll code I am generating?

I will be glad to provide more information.

Thanks,
Shivram

a.bc.gz (53.9 KB)

b.bc.gz (12.2 KB)

bugpoint-reduced-simplified.bc (1.16 KB)

Hi Shivram,

I'm trying to compile an llvm program which makes use of exception
handling. While compiling the code with llc i get the following
assertion failure

an unfortunate weakness of the code generators is that they require calls to
eh.selector to be in a landing pad (landing pad = where an invoke unwinds
to). They can also handle some simple cases when the selector call is outside
the landing pad. In practice, as long as the original call to eh.selector that
you generate is in a landing pad, and at the start of the landing pad (just
after the eh.exception call and any phi nodes) it is intended that the current
logic is good enough to handle any situations caused by optimization. Was the
original call at the start of a landing pad?

By the way, there are various ways of fixing this codegen problem. But since
there is a plan to redesign exception handling in LLVM, it seems pointless to
spend much time on it.

Ciao,

Duncan.

Forgot to reply all.

Duncan suggested that I put the selector call before the store but that didn’t help. I get the same assertion failure.

Hi Shivram,

        lpad: ; preds = %return7
           %46 = call i8* @llvm.eh.exception() ; <i8*> [#uses=2]
           store i8* %46, i8** %22
           %47 = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %46, i8*
        bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* null) ; <i32>
        [#uses=0]

    try putting eh.selector call before the store.

Tried. The optimized code looks a little different now but I'm getting
the same assert failure in llc.

please open a bugreport.

Best wishes,

Duncan.

PS: Fixing this propoerly in the code generator is a lot of work. The reason
it is a lot of work (rather than trivial, like in gcc) is due to the design of
exception handling in LLVM.
PPS: Please don't forget to send replies to the mailing list.

Is the plan still as specified in
http://www.nondot.org/sabre/LLVMNotes/ExceptionHandlingChanges.txt?
Is there a particular person or persons considered highly likely to
work on it at a roughly known time?

(I wish I had the time and knowledge to knock it out myself...)

I have been putting off implementing exception handling in my front
end, and would like to know whether to continue putting it off.

Also, a more general question: is exception handling (in the
hardware/OS) more or less universally supported across LLVM target
platforms?