From 33c49c0c82a5878f8f9d71e3f1710eddfdbebfeb Mon Sep 17 00:00:00 2001 From: Mandeep Singh Grang Date: Wed, 16 Jan 2019 19:52:59 +0000 Subject: [COFF, ARM64] Implement support for SEH extensions __try/__except/__finally Summary: This patch supports MS SEH extensions __try/__except/__finally. The intrinsics localescape and localrecover are responsible for communicating escaped static allocas from the try block to the handler. We need to preserve frame pointers for SEH. So we create a new function/property HasLocalEscape. Reviewers: rnk, compnerd, mstorsjo, TomTan, efriedma, ssijaric Reviewed By: rnk, efriedma Subscribers: smeenai, jrmuizel, alex, majnemer, ssijaric, ehsan, dmajor, kristina, javed.absar, kristof.beyls, chrib, llvm-commits Differential Revision: https://reviews.llvm.org/D53540 llvm-svn: 351370 --- llvm/test/CodeGen/AArch64/seh-finally.ll | 67 ++++++++++++++++++++++++++++ llvm/test/CodeGen/AArch64/seh-localescape.ll | 30 +++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 llvm/test/CodeGen/AArch64/seh-finally.ll create mode 100644 llvm/test/CodeGen/AArch64/seh-localescape.ll (limited to 'llvm/test/CodeGen/AArch64') diff --git a/llvm/test/CodeGen/AArch64/seh-finally.ll b/llvm/test/CodeGen/AArch64/seh-finally.ll new file mode 100644 index 00000000000..3cbbd03385c --- /dev/null +++ b/llvm/test/CodeGen/AArch64/seh-finally.ll @@ -0,0 +1,67 @@ +; RUN: llc -mtriple arm64-windows -o - %s | FileCheck %s + +; Function Attrs: noinline optnone uwtable +define dso_local i32 @foo() { +entry: +; CHECK-LABEL: foo +; CHECK: orr w8, wzr, #0x1 +; CHECK: mov w0, wzr +; CHECK: mov x1, x29 +; CHECK: .set .Lfoo$frame_escape_0, -4 +; CHECK: stur w8, [x29, #-4] +; CHECK: bl "?fin$0@0@foo@@" +; CHECK: ldur w0, [x29, #-4] + + %count = alloca i32, align 4 + call void (...) @llvm.localescape(i32* %count) + store i32 0, i32* %count, align 4 + %0 = load i32, i32* %count, align 4 + %add = add nsw i32 %0, 1 + store i32 %add, i32* %count, align 4 + %1 = call i8* @llvm.localaddress() + call void @"?fin$0@0@foo@@"(i8 0, i8* %1) + %2 = load i32, i32* %count, align 4 + ret i32 %2 +} + +define internal void @"?fin$0@0@foo@@"(i8 %abnormal_termination, i8* %frame_pointer) { +entry: +; CHECK-LABEL: @"?fin$0@0@foo@@" +; CHECK: sub sp, sp, #16 +; CHECK: str x1, [sp, #8] +; CHECK: strb w0, [sp, #7] +; CHECK: movz x8, #:abs_g1_s:.Lfoo$frame_escape_0 +; CHECK: movk x8, #:abs_g0_nc:.Lfoo$frame_escape_0 +; CHECK: add x8, x1, x8 +; CHECK: ldr w9, [x8] +; CHECK: add w9, w9, #1 +; CHECK: str w9, [x8] + + %frame_pointer.addr = alloca i8*, align 8 + %abnormal_termination.addr = alloca i8, align 1 + %0 = call i8* @llvm.localrecover(i8* bitcast (i32 ()* @foo to i8*), i8* %frame_pointer, i32 0) + %count = bitcast i8* %0 to i32* + store i8* %frame_pointer, i8** %frame_pointer.addr, align 8 + store i8 %abnormal_termination, i8* %abnormal_termination.addr, align 1 + %1 = zext i8 %abnormal_termination to i32 + %cmp = icmp eq i32 %1, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + %2 = load i32, i32* %count, align 4 + %add = add nsw i32 %2, 1 + store i32 %add, i32* %count, align 4 + br label %if.end + +if.end: ; preds = %if.then, %entry + ret void +} + +; Function Attrs: nounwind readnone +declare i8* @llvm.localrecover(i8*, i8*, i32) + +; Function Attrs: nounwind readnone +declare i8* @llvm.localaddress() + +; Function Attrs: nounwind +declare void @llvm.localescape(...) diff --git a/llvm/test/CodeGen/AArch64/seh-localescape.ll b/llvm/test/CodeGen/AArch64/seh-localescape.ll new file mode 100644 index 00000000000..0a1675014f6 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/seh-localescape.ll @@ -0,0 +1,30 @@ +; RUN: llc -mtriple arm64-windows %s -o - | FileCheck %s + +; Function Attrs: noinline nounwind optnone uwtable +define dso_local i32 @foo() { +entry: +; CHECK-LABEL: foo +; CHECK: .set .Lfoo$frame_escape_0, -4 + + %count = alloca i32, align 4 + call void (...) @llvm.localescape(i32* %count) + ret i32 0 +} + +define internal i32 @"?filt$0@0@foo@@"(i8* %exception_pointers, i8* %frame_pointer) { +entry: +; CHECK-LABEL: @"?filt$0@0@foo@@" +; CHECK: movz x8, #:abs_g1_s:.Lfoo$frame_escape_0 +; CHECK: movk x8, #:abs_g0_nc:.Lfoo$frame_escape_0 + + %0 = call i8* @llvm.localrecover(i8* bitcast (i32 ()* @foo to i8*), i8* %frame_pointer, i32 0) + %count = bitcast i8* %0 to i32* + %1 = load i32, i32* %count, align 4 + ret i32 %1 +} + +; Function Attrs: nounwind readnone +declare i8* @llvm.localrecover(i8*, i8*, i32) #2 + +; Function Attrs: nounwind +declare void @llvm.localescape(...) #3 -- cgit v1.2.3