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