[PATCH] D131394: [RFC] [MC] [Win64EH] Check that ARM64 prologs and epilogs have the right matching number of instructions

Martin Storsjö via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 8 06:05:13 PDT 2022


mstorsjo created this revision.
mstorsjo added reviewers: zzheng, efriedma.
Herald added subscribers: hiraditya, kristof.beyls.
Herald added a project: All.
mstorsjo requested review of this revision.
Herald added a project: LLVM.

This matches what was done for the ARM implementation (where getting
the instruction sizes right is even more tricky, and hence needed
tighter testing).

This currently does expose some cases of incorrect reorderings of
SEH opcodes.

This exposes the root cause of the failures reported in
https://reviews.llvm.org/D130049#3704064. It shouldn't be applied
as is until that root cause has been fixed. (It also triggers
a failure in the `CodeGen/AArch64/wineh5.mir` testcase, which has
got SEH opcodes that don't exactly match the expanded `MOVi64imm`
pseudoinstruction.)


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131394

Files:
  llvm/lib/MC/MCWin64EH.cpp
  llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp


Index: llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp
===================================================================
--- llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp
+++ llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp
@@ -202,6 +202,8 @@
   WinEH::Instruction Inst =
       WinEH::Instruction(Win64EH::UOP_End, /*Label=*/nullptr, -1, 0);
   CurFrame->EpilogMap[CurrentEpilog].Instructions.push_back(Inst);
+  MCSymbol *Label = S.emitCFILabel();
+  CurFrame->EpilogMap[CurrentEpilog].End = Label;
   CurrentEpilog = nullptr;
 }
 
Index: llvm/lib/MC/MCWin64EH.cpp
===================================================================
--- llvm/lib/MC/MCWin64EH.cpp
+++ llvm/lib/MC/MCWin64EH.cpp
@@ -299,6 +299,43 @@
   return *MaybeDiff;
 }
 
+static void checkARM64Instructions(MCStreamer &Streamer,
+                                   ArrayRef<WinEH::Instruction> Insns,
+                                   const MCSymbol *Begin, const MCSymbol *End,
+                                   StringRef Name, StringRef Type) {
+  if (!End)
+    return;
+  Optional<int64_t> MaybeDistance =
+      GetOptionalAbsDifference(Streamer, End, Begin);
+  if (!MaybeDistance)
+    return;
+  uint32_t Distance = (uint32_t)*MaybeDistance;
+
+  for (const auto &I : Insns) {
+    switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
+    default:
+      break;
+    case Win64EH::UOP_TrapFrame:
+    case Win64EH::UOP_PushMachFrame:
+    case Win64EH::UOP_Context:
+    case Win64EH::UOP_ClearUnwoundToCall:
+      // Can't reason about these opcodes and how they map to actual
+      // instructions.
+      return;
+    }
+  }
+  // Exclude the end opcode which doesn't map to an instruction.
+  uint32_t InstructionBytes = 4 * (Insns.size() - 1);
+  if (Distance != InstructionBytes) {
+    Streamer.getContext().reportError(
+        SMLoc(), "Incorrect size for " + Name + " " + Type + ": " +
+                     Twine(Distance) +
+                     " bytes of instructions in range, but .seh directives "
+                     "corresponding to " +
+                     Twine(InstructionBytes) + " bytes\n");
+  }
+}
+
 static uint32_t ARM64CountOfUnwindCodes(ArrayRef<WinEH::Instruction> Insns) {
   uint32_t Count = 0;
   for (const auto &I : Insns) {
@@ -984,6 +1021,10 @@
 static void ARM64FindSegmentsInFunction(MCStreamer &streamer,
                                         WinEH::FrameInfo *info,
                                         int64_t RawFuncLength) {
+  if (info->PrologEnd)
+    checkARM64Instructions(streamer, info->Instructions, info->Begin,
+                           info->PrologEnd, info->Function->getName(),
+                           "prologue");
   struct EpilogStartEnd {
     MCSymbol *Start;
     int64_t Offset;
@@ -995,6 +1036,8 @@
     MCSymbol *Start = I.first;
     auto &Instrs = I.second.Instructions;
     int64_t Offset = GetAbsDifference(streamer, Start, info->Begin);
+    checkARM64Instructions(streamer, Instrs, Start, I.second.End,
+                           info->Function->getName(), "epilogue");
     assert((Epilogs.size() == 0 || Offset >= Epilogs.back().End) &&
            "Epilogs should be monotonically ordered");
     // Exclue the end opcode from Instrs.size() when calculating the end of the


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D131394.450778.patch
Type: text/x-patch
Size: 3312 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220808/cce6538c/attachment.bin>


More information about the llvm-commits mailing list