diff options
| author | Matthias Braun <matze@braunis.de> | 2015-07-16 22:34:16 +0000 |
|---|---|---|
| committer | Matthias Braun <matze@braunis.de> | 2015-07-16 22:34:16 +0000 |
| commit | 3cd00c17396dd786d533ba71dafdcab9a7694804 (patch) | |
| tree | 98555ff515628864ac05b51daa9448347407f2a4 /llvm/test | |
| parent | 7e5de9c96beb1bb47a34d974c7939bf37c2c5605 (diff) | |
| download | bcm5719-llvm-3cd00c17396dd786d533ba71dafdcab9a7694804.tar.gz bcm5719-llvm-3cd00c17396dd786d533ba71dafdcab9a7694804.zip | |
Fix __builtin_setjmp in combination with sjlj exception handling.
llvm.eh.sjlj.setjmp was used as part of the SjLj exception handling
style but is also used in clang to implement __builtin_setjmp. The ARM
backend needs to output additional dispatch tables for the SjLj
exception handling style, these tables however can't be emitted if
llvm.eh.sjlj.setjmp is simply used for __builtin_setjmp and no actual
landing pad blocks exist.
To solve this issue a new llvm.eh.sjlj.setup_dispatch intrinsic is
introduced which is used instead of llvm.eh.sjlj.setjmp in the SjLj
exception handling lowering, so we can differentiate between the case
where we actually need to setup a dispatch table and the case where we
just need the __builtin_setjmp semantic.
Differential Revision: http://reviews.llvm.org/D9313
llvm-svn: 242481
Diffstat (limited to 'llvm/test')
| -rw-r--r-- | llvm/test/CodeGen/ARM/setjmp_longjmp.ll | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/llvm/test/CodeGen/ARM/setjmp_longjmp.ll b/llvm/test/CodeGen/ARM/setjmp_longjmp.ll new file mode 100644 index 00000000000..7100175a97a --- /dev/null +++ b/llvm/test/CodeGen/ARM/setjmp_longjmp.ll @@ -0,0 +1,113 @@ +; RUN: llc %s -o - | FileCheck %s +target triple = "armv7-apple-ios" + +declare i32 @llvm.eh.sjlj.setjmp(i8*) +declare void @llvm.eh.sjlj.longjmp(i8*) +@g = external global i32 + +declare void @may_throw() +declare i32 @__gxx_personality_sj0(...) +declare i8* @__cxa_begin_catch(i8*) +declare void @__cxa_end_catch() +declare i32 @llvm.eh.typeid.for(i8*) +declare i8* @llvm.frameaddress(i32) +declare i8* @llvm.stacksave() +@_ZTIPKc = external constant i8* + +; CHECK-LABEL: foobar +; +; setjmp sequence: +; CHECK: add [[PCREG:r[0-9]+]], pc, #8 +; CHECK-NEXT: str [[PCREG]], {{\[}}[[BUFREG:r[0-9]+]], #4] +; CHECK-NEXT: mov r0, #0 +; CHECK-NEXT: add pc, pc, #0 +; CHECK-NEXT: mov r0, #1 +; +; longjmp sequence: +; CHECK: ldr sp, [{{\s*}}[[BUFREG:r[0-9]+]], #8] +; CHECK-NEXT: ldr [[DESTREG:r[0-9]+]], {{\[}}[[BUFREG]], #4] +; CHECK-NEXT: ldr r7, {{\[}}[[BUFREG]]{{\]}} +; CHECK-NEXT: bx [[DESTREG]] +define void @foobar() { +entry: + %buf = alloca [5 x i8*], align 4 + %arraydecay = getelementptr inbounds [5 x i8*], [5 x i8*]* %buf, i32 0, i32 0 + %bufptr = bitcast i8** %arraydecay to i8* + ; Note: This is simplified, in reality you have to store the framepointer + + ; stackpointer in the buffer as well for this to be legal! + %setjmpres = call i32 @llvm.eh.sjlj.setjmp(i8* %bufptr) + %tobool = icmp ne i32 %setjmpres, 0 + br i1 %tobool, label %if.then, label %if.else + +if.then: + store volatile i32 1, i32* @g, align 4 + br label %if.end + +if.else: + store volatile i32 0, i32* @g, align 4 + call void @llvm.eh.sjlj.longjmp(i8* %bufptr) + unreachable + +if.end: + ret void +} + +; CHECK-LABEL: combine_sjlj_eh_and_setjmp_longjmp +; Check that we can mix sjlj exception handling with __builtin_setjmp +; and __builtin_longjmp. +; +; setjmp sequence: +; CHECK: add [[PCREG:r[0-9]+]], pc, #8 +; CHECK-NEXT: str [[PCREG]], {{\[}}[[BUFREG:r[0-9]+]], #4] +; CHECK-NEXT: mov r0, #0 +; CHECK-NEXT: add pc, pc, #0 +; CHECK-NEXT: mov r0, #1 +; +; longjmp sequence: +; CHECK: ldr sp, [{{\s*}}[[BUFREG:r[0-9]+]], #8] +; CHECK-NEXT: ldr [[DESTREG:r[0-9]+]], {{\[}}[[BUFREG]], #4] +; CHECK-NEXT: ldr r7, {{\[}}[[BUFREG]]{{\]}} +; CHECK-NEXT: bx [[DESTREG]] +define void @combine_sjlj_eh_and_setjmp_longjmp() personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) { +entry: + %buf = alloca [5 x i8*], align 4 + invoke void @may_throw() to label %try.cont unwind label %lpad + +lpad: + %0 = landingpad { i8*, i32 } catch i8* bitcast (i8** @_ZTIPKc to i8*) + %1 = extractvalue { i8*, i32 } %0, 1 + %2 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIPKc to i8*)) #3 + %matches = icmp eq i32 %1, %2 + br i1 %matches, label %catch, label %eh.resume + +catch: + %3 = extractvalue { i8*, i32 } %0, 0 + %4 = tail call i8* @__cxa_begin_catch(i8* %3) #3 + store volatile i32 0, i32* @g, align 4 + %5 = bitcast [5 x i8*]* %buf to i8* + %arraydecay = getelementptr inbounds [5 x i8*], [5 x i8*]* %buf, i64 0, i64 0 + %6 = tail call i8* @llvm.frameaddress(i32 0) + store i8* %6, i8** %arraydecay, align 16 + %7 = tail call i8* @llvm.stacksave() + %8 = getelementptr [5 x i8*], [5 x i8*]* %buf, i64 0, i64 2 + store i8* %7, i8** %8, align 16 + %9 = call i32 @llvm.eh.sjlj.setjmp(i8* %5) + %tobool = icmp eq i32 %9, 0 + br i1 %tobool, label %if.else, label %if.then + +if.then: + store volatile i32 2, i32* @g, align 4 + call void @__cxa_end_catch() #3 + br label %try.cont + +if.else: + store volatile i32 1, i32* @g, align 4 + call void @llvm.eh.sjlj.longjmp(i8* %5) + unreachable + +eh.resume: + resume { i8*, i32 } %0 + +try.cont: + ret void +} |

