1; RUN: llc %s -o - | FileCheck %s 2target triple = "armv7-apple-ios" 3 4declare i32 @llvm.eh.sjlj.setjmp(i8*) 5declare void @llvm.eh.sjlj.longjmp(i8*) 6@g = external global i32 7 8declare void @may_throw() 9declare i32 @__gxx_personality_sj0(...) 10declare i8* @__cxa_begin_catch(i8*) 11declare void @__cxa_end_catch() 12declare i32 @llvm.eh.typeid.for(i8*) 13declare i8* @llvm.frameaddress(i32) 14declare i8* @llvm.stacksave() 15@_ZTIPKc = external constant i8* 16 17; CHECK-LABEL: foobar 18; 19; setjmp sequence: 20; CHECK: add [[PCREG:r[0-9]+]], pc, #8 21; CHECK-NEXT: str [[PCREG]], {{\[}}[[BUFREG:r[0-9]+]], #4] 22; CHECK-NEXT: mov r0, #0 23; CHECK-NEXT: add pc, pc, #0 24; CHECK-NEXT: mov r0, #1 25; 26; longjmp sequence: 27; CHECK: ldr sp, [{{\s*}}[[BUFREG:r[0-9]+]], #8] 28; CHECK-NEXT: ldr [[DESTREG:r[0-9]+]], {{\[}}[[BUFREG]], #4] 29; CHECK-NEXT: ldr r7, {{\[}}[[BUFREG]]{{\]}} 30; CHECK-NEXT: bx [[DESTREG]] 31define void @foobar() { 32entry: 33 %buf = alloca [5 x i8*], align 4 34 %arraydecay = getelementptr inbounds [5 x i8*], [5 x i8*]* %buf, i32 0, i32 0 35 %bufptr = bitcast i8** %arraydecay to i8* 36 ; Note: This is simplified, in reality you have to store the framepointer + 37 ; stackpointer in the buffer as well for this to be legal! 38 %setjmpres = call i32 @llvm.eh.sjlj.setjmp(i8* %bufptr) 39 %tobool = icmp ne i32 %setjmpres, 0 40 br i1 %tobool, label %if.then, label %if.else 41 42if.then: 43 store volatile i32 1, i32* @g, align 4 44 br label %if.end 45 46if.else: 47 store volatile i32 0, i32* @g, align 4 48 call void @llvm.eh.sjlj.longjmp(i8* %bufptr) 49 unreachable 50 51if.end: 52 ret void 53} 54 55; CHECK-LABEL: combine_sjlj_eh_and_setjmp_longjmp 56; Check that we can mix sjlj exception handling with __builtin_setjmp 57; and __builtin_longjmp. 58; 59; setjmp sequence: 60; CHECK: add [[PCREG:r[0-9]+]], pc, #8 61; CHECK-NEXT: str [[PCREG]], {{\[}}[[BUFREG:r[0-9]+]], #4] 62; CHECK-NEXT: mov r0, #0 63; CHECK-NEXT: add pc, pc, #0 64; CHECK-NEXT: mov r0, #1 65; 66; longjmp sequence: 67; CHECK: ldr sp, [{{\s*}}[[BUFREG:r[0-9]+]], #8] 68; CHECK-NEXT: ldr [[DESTREG:r[0-9]+]], {{\[}}[[BUFREG]], #4] 69; CHECK-NEXT: ldr r7, {{\[}}[[BUFREG]]{{\]}} 70; CHECK-NEXT: bx [[DESTREG]] 71define void @combine_sjlj_eh_and_setjmp_longjmp() personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) { 72entry: 73 %buf = alloca [5 x i8*], align 4 74 invoke void @may_throw() to label %try.cont unwind label %lpad 75 76lpad: 77 %0 = landingpad { i8*, i32 } catch i8* bitcast (i8** @_ZTIPKc to i8*) 78 %1 = extractvalue { i8*, i32 } %0, 1 79 %2 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIPKc to i8*)) #3 80 %matches = icmp eq i32 %1, %2 81 br i1 %matches, label %catch, label %eh.resume 82 83catch: 84 %3 = extractvalue { i8*, i32 } %0, 0 85 %4 = tail call i8* @__cxa_begin_catch(i8* %3) #3 86 store volatile i32 0, i32* @g, align 4 87 %5 = bitcast [5 x i8*]* %buf to i8* 88 %arraydecay = getelementptr inbounds [5 x i8*], [5 x i8*]* %buf, i64 0, i64 0 89 %6 = tail call i8* @llvm.frameaddress(i32 0) 90 store i8* %6, i8** %arraydecay, align 16 91 %7 = tail call i8* @llvm.stacksave() 92 %8 = getelementptr [5 x i8*], [5 x i8*]* %buf, i64 0, i64 2 93 store i8* %7, i8** %8, align 16 94 %9 = call i32 @llvm.eh.sjlj.setjmp(i8* %5) 95 %tobool = icmp eq i32 %9, 0 96 br i1 %tobool, label %if.else, label %if.then 97 98if.then: 99 store volatile i32 2, i32* @g, align 4 100 call void @__cxa_end_catch() #3 101 br label %try.cont 102 103if.else: 104 store volatile i32 1, i32* @g, align 4 105 call void @llvm.eh.sjlj.longjmp(i8* %5) 106 unreachable 107 108eh.resume: 109 resume { i8*, i32 } %0 110 111try.cont: 112 ret void 113} 114