[llvm] 0c52ab3 - [MC] [Win64EH] Fix the calculation of the end of epilogs

Martin Storsjö via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 8 13:04:54 PDT 2022


Author: Martin Storsjö
Date: 2022-08-08T23:03:17+03:00
New Revision: 0c52ab39688e8e107487b8cee00f509fe092f40a

URL: https://github.com/llvm/llvm-project/commit/0c52ab39688e8e107487b8cee00f509fe092f40a
DIFF: https://github.com/llvm/llvm-project/commit/0c52ab39688e8e107487b8cee00f509fe092f40a.diff

LOG: [MC] [Win64EH] Fix the calculation of the end of epilogs

Exclude the terminating end opcode from the epilog - it doesn't
correspond to an actual instruction that is included in the epilog
itself (within the .seh_startepilogue/.seh_endepilogue range).

In most (all?) cases, an epilog is followed by a matching terminating
instruction though (a ret or a branch to a tail call), but it's not
strictly within the .seh_startepilogue/.seh_endepilogue range.

This fixes a number of failed asserts in cases where the codegen
has incorrectly reoredered SEH opcodes so they don't match up
exactly with their instructions.

However this still just avoids failing the assertion; the root cause
of generating unexpected epilogs is still present (and fixing that is
a less obvious issue).

Differential Revision: https://reviews.llvm.org/D131393

Added: 
    llvm/test/MC/AArch64/seh-multi-epilog.s

Modified: 
    llvm/lib/MC/MCWin64EH.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/MC/MCWin64EH.cpp b/llvm/lib/MC/MCWin64EH.cpp
index 8f53ab1534cb7..ff1c1ad94e50f 100644
--- a/llvm/lib/MC/MCWin64EH.cpp
+++ b/llvm/lib/MC/MCWin64EH.cpp
@@ -997,7 +997,9 @@ static void ARM64FindSegmentsInFunction(MCStreamer &streamer,
     int64_t Offset = GetAbsDifference(streamer, Start, info->Begin);
     assert((Epilogs.size() == 0 || Offset >= Epilogs.back().End) &&
            "Epilogs should be monotonically ordered");
-    Epilogs.push_back({Start, Offset, Offset + (int64_t)Instrs.size() * 4});
+    // Exclue the end opcode from Instrs.size() when calculating the end of the
+    // epilog.
+    Epilogs.push_back({Start, Offset, Offset + (int64_t)(Instrs.size() - 1) * 4});
   }
 
   unsigned E = 0;

diff  --git a/llvm/test/MC/AArch64/seh-multi-epilog.s b/llvm/test/MC/AArch64/seh-multi-epilog.s
new file mode 100644
index 0000000000000..56cbcc558f571
--- /dev/null
+++ b/llvm/test/MC/AArch64/seh-multi-epilog.s
@@ -0,0 +1,62 @@
+// This test checks that we emit allow multiple consecutive epilogs without
+// triggering failed asserts.unwind info correctly for epilogs that:
+// RUN: llvm-mc -triple aarch64-pc-win32 -filetype=obj %s -o %t.o
+// RUN: llvm-readobj -u %t.o | FileCheck %s
+
+// CHECK-LABEL:UnwindInformation [
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: multi_epilog (0x0)
+// CHECK-NEXT:    ExceptionRecord: .xdata (0x0)
+// CHECK-NEXT:    ExceptionData {
+// CHECK-NEXT:      FunctionLength: 20
+// CHECK-NEXT:      Version: 0
+// CHECK-NEXT:      ExceptionData: No
+// CHECK-NEXT:      EpiloguePacked: No
+// CHECK-NEXT:      EpilogueScopes: 2
+// CHECK-NEXT:      ByteCodeLength: 4
+// CHECK-NEXT:      Prologue [
+// CHECK-NEXT:        0x81                ; stp x29, x30, [sp, #-16]!
+// CHECK-NEXT:        0xe4                ; end
+// CHECK-NEXT:      ]
+// CHECK-NEXT:      EpilogueScopes [
+// CHECK-NEXT:        EpilogueScope {
+// CHECK-NEXT:          StartOffset: 2
+// CHECK-NEXT:          EpilogueStartIndex: 0
+// CHECK-NEXT:          Opcodes [
+// CHECK-NEXT:            0x81                ; ldp x29, x30, [sp], #16
+// CHECK-NEXT:            0xe4                ; end
+// CHECK-NEXT:          ]
+// CHECK-NEXT:        }
+// CHECK-NEXT:        EpilogueScope {
+// CHECK-NEXT:          StartOffset: 3
+// CHECK-NEXT:          EpilogueStartIndex: 0
+// CHECK-NEXT:          Opcodes [
+// CHECK-NEXT:            0x81                ; ldp x29, x30, [sp], #16
+// CHECK-NEXT:            0xe4                ; end
+// CHECK-NEXT:          ]
+// CHECK-NEXT:        }
+// CHECK-NEXT:      ]
+// CHECK-NEXT:    }
+// CHECK-NEXT:  }
+// CHECK-NEXT:]
+
+	.text
+	.global	multi_epilog
+	.p2align	2
+	.seh_proc multi_epilog
+multi_epilog:
+	stp	x29, lr, [sp, #-16]!
+	.seh_save_fplr_x 16
+	.seh_endprologue
+        nop
+	.seh_startepilogue
+	ldp	x29, lr, [sp], #16
+	.seh_save_fplr_x 16
+	.seh_endepilogue
+	.seh_startepilogue
+	ldp	x29, lr, [sp], #16
+	.seh_save_fplr_x 16
+	.seh_endepilogue
+	ret
+	.seh_endfunclet
+	.seh_endproc


        


More information about the llvm-commits mailing list