Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[AArch64] Implement assembler support for new SVE SEH unwind opcodes. #137895

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 2, 2025

Conversation

efriedma-quic
Copy link
Collaborator

In order to support the AArch64 ABI, Microsoft has extended the unwinder to support additional opcodes. (Updated documentation at https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling .)

First in a series of patches to support SVE on Windows.

@llvmbot
Copy link
Member

llvmbot commented Apr 29, 2025

@llvm/pr-subscribers-llvm-binary-utilities
@llvm/pr-subscribers-mc

@llvm/pr-subscribers-llvm-support

Author: Eli Friedman (efriedma-quic)

Changes

In order to support the AArch64 ABI, Microsoft has extended the unwinder to support additional opcodes. (Updated documentation at https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling .)

First in a series of patches to support SVE on Windows.


Full diff: https://github.com/llvm/llvm-project/pull/137895.diff

9 Files Affected:

  • (modified) llvm/include/llvm/Support/Win64EH.h (+3)
  • (modified) llvm/lib/MC/MCWin64EH.cpp (+39)
  • (modified) llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp (+57)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp (+9)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h (+6)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp (+14)
  • (modified) llvm/test/MC/AArch64/seh.s (+15-5)
  • (modified) llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp (+54-1)
  • (modified) llvm/tools/llvm-readobj/ARMWinEHPrinter.h (+8)
diff --git a/llvm/include/llvm/Support/Win64EH.h b/llvm/include/llvm/Support/Win64EH.h
index 8a9be15373917..ec3413b31ee4a 100644
--- a/llvm/include/llvm/Support/Win64EH.h
+++ b/llvm/include/llvm/Support/Win64EH.h
@@ -75,6 +75,9 @@ enum UnwindOpcodes {
   UOP_SaveAnyRegDPX,
   UOP_SaveAnyRegQX,
   UOP_SaveAnyRegQPX,
+  UOP_AllocZ,
+  UOP_SaveZReg,
+  UOP_SavePReg,
 
   // The following set of unwind opcodes is for ARM.  They are documented at
   // https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling
diff --git a/llvm/lib/MC/MCWin64EH.cpp b/llvm/lib/MC/MCWin64EH.cpp
index bd5cf354659b6..7021c3e31789b 100644
--- a/llvm/lib/MC/MCWin64EH.cpp
+++ b/llvm/lib/MC/MCWin64EH.cpp
@@ -421,6 +421,9 @@ static uint32_t ARM64CountOfUnwindCodes(ArrayRef<WinEH::Instruction> Insns) {
     case Win64EH::UOP_PACSignLR:
       Count += 1;
       break;
+    case Win64EH::UOP_AllocZ:
+      Count += 2;
+      break;
     case Win64EH::UOP_SaveAnyRegI:
     case Win64EH::UOP_SaveAnyRegIP:
     case Win64EH::UOP_SaveAnyRegD:
@@ -433,6 +436,8 @@ static uint32_t ARM64CountOfUnwindCodes(ArrayRef<WinEH::Instruction> Insns) {
     case Win64EH::UOP_SaveAnyRegDPX:
     case Win64EH::UOP_SaveAnyRegQX:
     case Win64EH::UOP_SaveAnyRegQPX:
+    case Win64EH::UOP_SaveZReg:
+    case Win64EH::UOP_SavePReg:
       Count += 3;
       break;
     }
@@ -640,6 +645,37 @@ static void ARM64EmitUnwindCode(MCStreamer &streamer,
     streamer.emitInt8(b);
     break;
   }
+  case Win64EH::UOP_AllocZ: {
+    b = 0xDF;
+    streamer.emitInt8(b);
+    b = inst.Offset;
+    streamer.emitInt8(b);
+    break;
+  }
+  case Win64EH::UOP_SaveZReg: {
+    assert(inst.Register >= 8 && inst.Register <= 23);
+    assert(inst.Offset < 256);
+    b = 0xE7;
+    streamer.emitInt8(b);
+    reg = inst.Register - 8;
+    b = ((inst.Offset & 0xC0) >> 1) | reg;
+    streamer.emitInt8(b);
+    b = 0xC0 | (inst.Offset & 0x3F);
+    streamer.emitInt8(b);
+    break;
+  }
+  case Win64EH::UOP_SavePReg: {
+    assert(inst.Register >= 4 && inst.Register <= 15);
+    assert(inst.Offset < 256);
+    b = 0xE7;
+    streamer.emitInt8(b);
+    reg = inst.Register - 4;
+    b = ((inst.Offset & 0xC0) >> 1) | 0x10 | reg;
+    streamer.emitInt8(b);
+    b = 0xC0 | (inst.Offset & 0x3F);
+    streamer.emitInt8(b);
+    break;
+  }
   }
 }
 
@@ -1004,6 +1040,9 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
     case Win64EH::UOP_SaveAnyRegDPX:
     case Win64EH::UOP_SaveAnyRegQX:
     case Win64EH::UOP_SaveAnyRegQPX:
+    case Win64EH::UOP_AllocZ:
+    case Win64EH::UOP_SaveZReg:
+    case Win64EH::UOP_SavePReg:
       // These are never canonical; they don't show up with the usual Arm64
       // calling convention.
       return false;
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index e178c5027571a..bcd5fde3b8e27 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -230,6 +230,9 @@ class AArch64AsmParser : public MCTargetAsmParser {
   bool parseDirectiveSEHClearUnwoundToCall(SMLoc L);
   bool parseDirectiveSEHPACSignLR(SMLoc L);
   bool parseDirectiveSEHSaveAnyReg(SMLoc L, bool Paired, bool Writeback);
+  bool parseDirectiveSEHAllocZ(SMLoc L);
+  bool parseDirectiveSEHSaveZReg(SMLoc L);
+  bool parseDirectiveSEHSavePReg(SMLoc L);
   bool parseDirectiveAeabiSubSectionHeader(SMLoc L);
   bool parseDirectiveAeabiAArch64Attr(SMLoc L);
 
@@ -7111,6 +7114,12 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
       parseDirectiveSEHSaveAnyReg(Loc, false, true);
     else if (IDVal == ".seh_save_any_reg_px")
       parseDirectiveSEHSaveAnyReg(Loc, true, true);
+    else if (IDVal == ".seh_allocz")
+      parseDirectiveSEHAllocZ(Loc);
+    else if (IDVal == ".seh_save_zreg")
+      parseDirectiveSEHSaveZReg(Loc);
+    else if (IDVal == ".seh_save_preg")
+      parseDirectiveSEHSavePReg(Loc);
     else
       return true;
   } else if (IsELF) {
@@ -7856,6 +7865,54 @@ bool AArch64AsmParser::parseDirectiveSEHSaveAnyReg(SMLoc L, bool Paired,
   return false;
 }
 
+/// parseDirectiveAllocZ
+/// ::= .seh_allocz
+bool AArch64AsmParser::parseDirectiveSEHAllocZ(SMLoc L) {
+  int64_t Offset;
+  if (parseImmExpr(Offset))
+    return true;
+  getTargetStreamer().emitARM64WinCFIAllocZ(Offset);
+  return false;
+}
+
+/// parseDirectiveSEHSaveZReg
+/// ::= .seh_save_zreg
+bool AArch64AsmParser::parseDirectiveSEHSaveZReg(SMLoc L) {
+  MCRegister RegNum;
+  StringRef Kind;
+  int64_t Offset;
+  ParseStatus Res =
+      tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
+  if (!Res.isSuccess())
+    return true;
+  if (check(RegNum < AArch64::Z8 || RegNum > AArch64::Z23, L,
+            "expected register in range z8 to z23"))
+    return true;
+  if (parseComma() || parseImmExpr(Offset))
+    return true;
+  getTargetStreamer().emitARM64WinCFISaveZReg(RegNum - AArch64::Z0, Offset);
+  return false;
+}
+
+/// parseDirectiveSEHSavePReg
+/// ::= .seh_save_preg
+bool AArch64AsmParser::parseDirectiveSEHSavePReg(SMLoc L) {
+  MCRegister RegNum;
+  StringRef Kind;
+  int64_t Offset;
+  ParseStatus Res =
+      tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
+  if (!Res.isSuccess())
+    return true;
+  if (check(RegNum < AArch64::P4 || RegNum > AArch64::P15, L,
+            "expected register in range p4 to p15"))
+    return true;
+  if (parseComma() || parseImmExpr(Offset))
+    return true;
+  getTargetStreamer().emitARM64WinCFISavePReg(RegNum - AArch64::P0, Offset);
+  return false;
+}
+
 bool AArch64AsmParser::parseDirectiveAeabiSubSectionHeader(SMLoc L) {
   // Expecting 3 AsmToken::Identifier after '.aeabi_subsection', a name and 2
   // parameters, e.g.: .aeabi_subsection (1)aeabi_feature_and_bits, (2)optional,
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
index b12a12436db81..cc607e863d190 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
@@ -150,6 +150,15 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
   void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset) override {
     OS << "\t.seh_save_any_reg_px\tq" << Reg << ", " << Offset << "\n";
   }
+  void emitARM64WinCFIAllocZ(int Offset) override {
+    OS << "\t.seh_allocz\t" << Offset << "\n";
+  }
+  void emitARM64WinCFISaveZReg(unsigned Reg, int Offset) override {
+    OS << "\t.seh_save_zreg\tz" << Reg << ", " << Offset << "\n";
+  }
+  void emitARM64WinCFISavePReg(unsigned Reg, int Offset) override {
+    OS << "\t.seh_save_preg\tp" << Reg << ", " << Offset << "\n";
+  }
 
   void emitAttribute(StringRef VendorName, unsigned Tag, unsigned Value,
                      std::string String) override {
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
index 43e099f919999..1427427b951a8 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
@@ -93,6 +93,9 @@ class AArch64TargetStreamer : public MCTargetStreamer {
   virtual void emitARM64WinCFISaveAnyRegDPX(unsigned Reg, int Offset) {}
   virtual void emitARM64WinCFISaveAnyRegQX(unsigned Reg, int Offset) {}
   virtual void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset) {}
+  virtual void emitARM64WinCFIAllocZ(int Offset) {}
+  virtual void emitARM64WinCFISaveZReg(unsigned Reg, int Offset) {}
+  virtual void emitARM64WinCFISavePReg(unsigned Reg, int Offset) {}
 
   /// Build attributes implementation
   virtual void
@@ -182,6 +185,9 @@ class AArch64TargetWinCOFFStreamer : public llvm::AArch64TargetStreamer {
   void emitARM64WinCFISaveAnyRegDPX(unsigned Reg, int Offset) override;
   void emitARM64WinCFISaveAnyRegQX(unsigned Reg, int Offset) override;
   void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset) override;
+  void emitARM64WinCFIAllocZ(int Offset) override;
+  void emitARM64WinCFISaveZReg(unsigned Reg, int Offset) override;
+  void emitARM64WinCFISavePReg(unsigned Reg, int Offset) override;
 
 private:
   void emitARM64WinUnwindCode(unsigned UnwindCode, int Reg, int Offset);
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp
index fb8a3e1215d90..c03bc386ae349 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp
@@ -284,6 +284,20 @@ void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveAnyRegQPX(unsigned Reg,
   emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegQPX, Reg, Offset);
 }
 
+void AArch64TargetWinCOFFStreamer::emitARM64WinCFIAllocZ(int Offset) {
+  emitARM64WinUnwindCode(Win64EH::UOP_AllocZ, 0, Offset);
+}
+
+void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveZReg(unsigned Reg,
+                                                           int Offset) {
+  emitARM64WinUnwindCode(Win64EH::UOP_SaveZReg, Reg, Offset);
+}
+
+void AArch64TargetWinCOFFStreamer::emitARM64WinCFISavePReg(unsigned Reg,
+                                                           int Offset) {
+  emitARM64WinUnwindCode(Win64EH::UOP_SavePReg, Reg, Offset);
+}
+
 MCStreamer *
 llvm::createAArch64WinCOFFStreamer(MCContext &Context,
                                    std::unique_ptr<MCAsmBackend> &&MAB,
diff --git a/llvm/test/MC/AArch64/seh.s b/llvm/test/MC/AArch64/seh.s
index 5ad4fba2bf6b4..93ba9ccfff80b 100644
--- a/llvm/test/MC/AArch64/seh.s
+++ b/llvm/test/MC/AArch64/seh.s
@@ -20,7 +20,7 @@
 // CHECK-NEXT:   }
 // CHECK:        Section {
 // CHECK:          Name: .xdata
-// CHECK:          RawDataSize: 92
+// CHECK:          RawDataSize: 100
 // CHECK:          RelocationCount: 1
 // CHECK:          Characteristics [
 // CHECK-NEXT:       ALIGN_4BYTES
@@ -41,7 +41,7 @@
 
 // CHECK-NEXT: Relocations [
 // CHECK-NEXT:   Section (4) .xdata {
-// CHECK-NEXT:     0x50 IMAGE_REL_ARM64_ADDR32NB __C_specific_handler
+// CHECK-NEXT:     0x58 IMAGE_REL_ARM64_ADDR32NB __C_specific_handler
 // CHECK-NEXT:   }
 // CHECK-NEXT:   Section (5) .pdata {
 // CHECK-NEXT:     0x0 IMAGE_REL_ARM64_ADDR32NB .text
@@ -54,8 +54,11 @@
 // CHECK-NEXT:     Function: func
 // CHECK-NEXT:     ExceptionRecord: .xdata
 // CHECK-NEXT:     ExceptionData {
-// CHECK-NEXT:       FunctionLength: 156
+// CHECK-NEXT:       FunctionLength: 172
 // CHECK:            Prologue [
+// CHECK-NEXT:         0xe712c3            ; str p10, [sp, #3, mul vl]
+// CHECK-NEXT:         0xe703c5            ; str z11, [sp, #5, mul vl]
+// CHECK-NEXT:         0xdf05              ; addvl sp, #-5
 // CHECK-NEXT:         0xe76983            ; stp q9, q10, [sp, #-64]!
 // CHECK-NEXT:         0xe73d83            ; str q29, [sp, #-64]!
 // CHECK-NEXT:         0xe76243            ; stp d2, d3, [sp, #-64]!
@@ -96,8 +99,8 @@
 // CHECK-NEXT:       ]
 // CHECK-NEXT:       EpilogueScopes [
 // CHECK-NEXT:         EpilogueScope {
-// CHECK-NEXT:           StartOffset: 37
-// CHECK-NEXT:           EpilogueStartIndex: 69
+// CHECK-NEXT:           StartOffset: 41
+// CHECK-NEXT:           EpilogueStartIndex: 77
 // CHECK-NEXT:           Opcodes [
 // CHECK-NEXT:             0x01                ; add sp, #16
 // CHECK-NEXT:             0xe4                ; end
@@ -193,6 +196,13 @@ func:
     .seh_save_any_reg_x q29, 64
     nop
     .seh_save_any_reg_px q9, 64
+    nop
+    .seh_allocz 5
+    nop
+    .seh_save_zreg z11, 5
+    nop
+    .seh_save_preg p6, 3
+    nop
     .seh_endprologue
     nop
     .seh_startepilogue
diff --git a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
index 08baa037eab27..62d9c6e559796 100644
--- a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
+++ b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
@@ -160,6 +160,7 @@ const Decoder::RingEntry Decoder::Ring64[] = {
     {0xfe, 0xda, 2, &Decoder::opcode_save_fregp_x},
     {0xfe, 0xdc, 2, &Decoder::opcode_save_freg},
     {0xff, 0xde, 2, &Decoder::opcode_save_freg_x},
+    {0xff, 0xdf, 2, &Decoder::opcode_alloc_z},
     {0xff, 0xe0, 4, &Decoder::opcode_alloc_l},
     {0xff, 0xe1, 1, &Decoder::opcode_setfp},
     {0xff, 0xe2, 2, &Decoder::opcode_addfp},
@@ -167,7 +168,7 @@ const Decoder::RingEntry Decoder::Ring64[] = {
     {0xff, 0xe4, 1, &Decoder::opcode_end},
     {0xff, 0xe5, 1, &Decoder::opcode_end_c},
     {0xff, 0xe6, 1, &Decoder::opcode_save_next},
-    {0xff, 0xe7, 3, &Decoder::opcode_save_any_reg},
+    {0xff, 0xe7, 3, &Decoder::opcode_e7},
     {0xff, 0xe8, 1, &Decoder::opcode_trap_frame},
     {0xff, 0xe9, 1, &Decoder::opcode_machine_frame},
     {0xff, 0xea, 1, &Decoder::opcode_context},
@@ -805,6 +806,16 @@ bool Decoder::opcode_save_freg_x(const uint8_t *OC, unsigned &Offset,
   return false;
 }
 
+bool Decoder::opcode_alloc_z(const uint8_t *OC, unsigned &Offset,
+                             unsigned Length, bool Prologue) {
+  unsigned Off = OC[Offset + 1];
+  SW.startLine() << format("0x%02x%02x              ; addvl sp, #%d\n",
+                           OC[Offset], OC[Offset + 1],
+                           Prologue ? -(int)Off : (int)Off);
+  Offset += 2;
+  return false;
+}
+
 bool Decoder::opcode_alloc_l(const uint8_t *OC, unsigned &Offset,
                              unsigned Length, bool Prologue) {
   unsigned Off =
@@ -871,6 +882,24 @@ bool Decoder::opcode_save_next(const uint8_t *OC, unsigned &Offset,
   return false;
 }
 
+bool Decoder::opcode_e7(const uint8_t *OC, unsigned &Offset, unsigned Length,
+                        bool Prologue) {
+  // The e7 opcode has unusual decoding rules; write out the logic.
+  if ((OC[Offset + 1] & 0x80) == 0x80) {
+    SW.getOStream() << "reserved encoding\n";
+    Offset += 3;
+    return false;
+  }
+
+  if ((OC[Offset + 2] & 0xC0) == 0xC0) {
+    if ((OC[Offset + 1] & 0x10) == 0)
+      return opcode_save_zreg(OC, Offset, Length, Prologue);
+    return opcode_save_preg(OC, Offset, Length, Prologue);
+  }
+
+  return opcode_save_any_reg(OC, Offset, Length, Prologue);
+}
+
 bool Decoder::opcode_save_any_reg(const uint8_t *OC, unsigned &Offset,
                                   unsigned Length, bool Prologue) {
   // Whether the instruction has writeback
@@ -948,6 +977,30 @@ bool Decoder::opcode_save_any_reg(const uint8_t *OC, unsigned &Offset,
   return false;
 }
 
+bool Decoder::opcode_save_zreg(const uint8_t *OC, unsigned &Offset,
+                               unsigned Length, bool Prologue) {
+  uint32_t Reg = (OC[Offset + 1] & 0x0F) + 8;
+  uint32_t Off = ((OC[Offset + 1] & 0x60) << 1) | (OC[Offset + 2] & 0x3F);
+  SW.startLine() << format(
+      "0x%02x%02x%02x            ; %s z%u, [sp, #%u, mul vl]\n", OC[Offset],
+      OC[Offset + 1], OC[Offset + 2],
+      static_cast<const char *>(Prologue ? "str" : "ldr"), Reg, Off);
+  Offset += 3;
+  return false;
+}
+
+bool Decoder::opcode_save_preg(const uint8_t *OC, unsigned &Offset,
+                               unsigned Length, bool Prologue) {
+  uint32_t Reg = (OC[Offset + 1] & 0x0F) + 8;
+  uint32_t Off = ((OC[Offset + 1] & 0x60) << 1) | (OC[Offset + 2] & 0x3F);
+  SW.startLine() << format(
+      "0x%02x%02x%02x            ; %s p%u, [sp, #%u, mul vl]\n", OC[Offset],
+      OC[Offset + 1], OC[Offset + 2],
+      static_cast<const char *>(Prologue ? "str" : "ldr"), Reg, Off);
+  Offset += 3;
+  return false;
+}
+
 bool Decoder::opcode_trap_frame(const uint8_t *OC, unsigned &Offset,
                                 unsigned Length, bool Prologue) {
   SW.startLine() << format("0x%02x                ; trap frame\n", OC[Offset]);
diff --git a/llvm/tools/llvm-readobj/ARMWinEHPrinter.h b/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
index fa5b31dd87b4b..b412c4a8ae231 100644
--- a/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
+++ b/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
@@ -107,6 +107,8 @@ class Decoder {
                         unsigned Length, bool Prologue);
   bool opcode_save_freg_x(const uint8_t *Opcodes, unsigned &Offset,
                           unsigned Length, bool Prologue);
+  bool opcode_alloc_z(const uint8_t *Opcodes, unsigned &Offset, unsigned Length,
+                      bool Prologue);
   bool opcode_alloc_l(const uint8_t *Opcodes, unsigned &Offset, unsigned Length,
                       bool Prologue);
   bool opcode_setfp(const uint8_t *Opcodes, unsigned &Offset, unsigned Length,
@@ -121,6 +123,12 @@ class Decoder {
                     bool Prologue);
   bool opcode_save_next(const uint8_t *Opcodes, unsigned &Offset,
                         unsigned Length, bool Prologue);
+  bool opcode_e7(const uint8_t *Opcodes, unsigned &Offset, unsigned Length,
+                 bool Prologue);
+  bool opcode_save_zreg(const uint8_t *Opcodes, unsigned &Offset,
+                        unsigned Length, bool Prologue);
+  bool opcode_save_preg(const uint8_t *Opcodes, unsigned &Offset,
+                        unsigned Length, bool Prologue);
   bool opcode_save_any_reg(const uint8_t *Opcodes, unsigned &Offset,
                            unsigned Length, bool Prologue);
   bool opcode_trap_frame(const uint8_t *Opcodes, unsigned &Offset,

In order to support the AArch64 ABI, Microsoft has extended the unwinder
to support additional opcodes. (Updated documentation at
https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling .)

First in a series of patches to support SVE on Windows.
@efriedma-quic efriedma-quic force-pushed the aarch64-seh-sve-asm-v2 branch from 9171163 to b244f02 Compare April 30, 2025 00:57
Copy link
Contributor

@dpaoliello dpaoliello left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, other than the test failure.

@pmsjt any concerns?

Copy link
Member

@mstorsjo mstorsjo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@efriedma-quic efriedma-quic merged commit 312d6b4 into llvm:main May 2, 2025
11 checks passed
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
…llvm#137895)

In order to support the AArch64 ABI, Microsoft has extended the unwinder
to support additional opcodes. (Updated documentation at
https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling .)

First in a series of patches to support SVE on Windows.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
…llvm#137895)

In order to support the AArch64 ABI, Microsoft has extended the unwinder
to support additional opcodes. (Updated documentation at
https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling .)

First in a series of patches to support SVE on Windows.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
…llvm#137895)

In order to support the AArch64 ABI, Microsoft has extended the unwinder
to support additional opcodes. (Updated documentation at
https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling .)

First in a series of patches to support SVE on Windows.
GeorgeARM pushed a commit to GeorgeARM/llvm-project that referenced this pull request May 7, 2025
…llvm#137895)

In order to support the AArch64 ABI, Microsoft has extended the unwinder
to support additional opcodes. (Updated documentation at
https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling .)

First in a series of patches to support SVE on Windows.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants