[llvm-dev] setjmp/longjmp and volatile stores, but non-volatile loads

Jonas Maebe via llvm-dev llvm-dev at lists.llvm.org
Wed Dec 21 12:02:08 PST 2016


On 21/12/16 19:54, Reid Kleckner wrote:
> On Sun, Dec 18, 2016 at 11:58 PM, Jonas Maebe <jonas-devlists at watlock.be
> <mailto:jonas-devlists at watlock.be>> wrote:
>
>     Actually, there's another —even more fundamental— problem: the longjmp
>     will always restore the non-volatile registers to the contents they had
>     at the start of the try-block, which is not what LLVM expects when
>     entering an SEH-based landing pad.
>
> The SjLjEHPrepare pass tries to deal with this by demoting all values
> live across EH edges to the stack. This should also eliminate those phis
> from landingpad blocks. Check
> out TargetPassConfig::addPassesToHandleExceptions() and make sure you
> run that pass.

Thanks for the suggestion! Unfortunately,
1) it also inserts calls to _Unwind_SjLj_Register/_Unwind_SjLj_Unregister
2) it still inserts phis, and also the equivalent for memory-based 
synchronisation in landingpads:

Lj15:
   %tmp.6.1.reg2mem.0 = phi i32 [ %reg.1_66, %Lj47 ], [ %reg.1_66, %Lj46 
], [ %reg.1_66, %Lj45 ], [ %reg.1_66, %Lj44 ], [ %reg.1_66, %Lj43 ], [ 
%reg.1_66, %Lj42 ], [ %reg.1_66, %Lj41 ], [ %reg.1_66, %Lj40 ], [ 
%reg.1_66, %Lj32 ], [ %reg.1_66, %Lj38 ], [ %reg.1_6
6, %Lj37 ], [ %reg.1_66, %Lj36 ], [ %reg.1_66, %Lj35 ], [ %reg.1_66, 
%Lj34 ], [ %reg.1_66, %Lj31 ], [ %tmp.6.0, %Lj29 ], [ %tmp.6.0, %Lj28 ], 
[ %tmp.6.0, %Lj27 ], [ %tmp.6.0, %Lj26 ], [ %tmp.6.0, %Lj25 ], [ 
%tmp.6.0, %Lj22 ], [ %tmp.6.0, %Lj20 ]
   %reg.1_116 = landingpad %"typ.PROGRAM.$llvmstruct$d00000004i32"
           catch i8* null
   %exception_gep = getelementptr { i8*, i32, [4 x i32], i8*, i8*, [5 x 
i8*] }, { i8*, i32, [4 x i32], i8*, i8*, [5 x i8*] }* %fn_context, i64 
0, i32 2, i64 0
   %exn_val = load volatile i32, i32* %exception_gep, align 4
   %exn_selector_gep = getelementptr { i8*, i32, [4 x i32], i8*, i8*, [5 
x i8*] }, { i8*, i32, [4 x i32], i8*, i8*, [5 x i8*] }* %fn_context, i64 
0, i32 2, i64 1
   %exn_selector_val = load volatile i32, i32* %exn_selector_gep, align 4
   br label %Lj13

; label where our setjmp branches to
Lj13:                                             ; preds = %0, %Lj15
   %tmp.6.2 = phi i32 [ 0, %0 ], [ %tmp.6.1.reg2mem.0, %Lj15 ]


Additionally, if you just run that pass in opt in addition to -O1 
(-sjljehprepare -O1), then calling llc on the result will fail with an 
assert:

Assertion failed: (MI.isEHLabel() && "expected EH_LABEL"), function 
EmitSjLjDispatchBlock, file 
/Data/imacdev/llvm/lib/Target/X86/X86ISelLowering.cpp, line 25273.

That's with trunk at 290046; with 3.9 I get errors about invalid relocation 
calculations instead. So it seems like this pass cannot be used in 
isolation.

I've posted the full unoptimized code for the test module at 
http://pastebin.com/PztgYGnF (although to run it after compiling, you'd 
need more).


Jonas


More information about the llvm-dev mailing list