[llvm] [AArch64][Windows] Add MC support for ec_context (PR #69520)

via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 18 14:11:57 PDT 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

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

Author: Billy Laws (bylaws)

<details>
<summary>Changes</summary>

ARM64EC uses the same CONTEXT structure as x86_64 as opposed to the regular ARM64 context, a [new unwind opcode](https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling?view=msvc-170) (MSFT_OP_EC_CONTEXT) is added to handle this.

(depends on https://github.com/llvm/llvm-project/pull/69515)

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


9 Files Affected:

- (modified) llvm/include/llvm/Support/Win64EH.h (+1) 
- (modified) llvm/lib/MC/MCWin64EH.cpp (+9) 
- (modified) llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp (+10) 
- (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp (+1) 
- (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h (+2) 
- (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp (+4) 
- (modified) llvm/test/MC/AArch64/seh.s (+3) 
- (modified) llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp (+8) 
- (modified) llvm/tools/llvm-readobj/ARMWinEHPrinter.h (+2) 


``````````diff
diff --git a/llvm/include/llvm/Support/Win64EH.h b/llvm/include/llvm/Support/Win64EH.h
index e84fd6d72bedbeb..cf54f49286830ab 100644
--- a/llvm/include/llvm/Support/Win64EH.h
+++ b/llvm/include/llvm/Support/Win64EH.h
@@ -60,6 +60,7 @@ enum UnwindOpcodes {
   UOP_SaveNext,
   UOP_TrapFrame,
   UOP_Context,
+  UOP_ECContext,
   UOP_ClearUnwoundToCall,
   UOP_PACSignLR,
   UOP_SaveAnyRegI,
diff --git a/llvm/lib/MC/MCWin64EH.cpp b/llvm/lib/MC/MCWin64EH.cpp
index bb3492bec8aad8a..bd5cf354659b67b 100644
--- a/llvm/lib/MC/MCWin64EH.cpp
+++ b/llvm/lib/MC/MCWin64EH.cpp
@@ -318,6 +318,7 @@ static void checkARM64Instructions(MCStreamer &Streamer,
     case Win64EH::UOP_TrapFrame:
     case Win64EH::UOP_PushMachFrame:
     case Win64EH::UOP_Context:
+    case Win64EH::UOP_ECContext:
     case Win64EH::UOP_ClearUnwoundToCall:
       // Can't reason about these opcodes and how they map to actual
       // instructions.
@@ -411,6 +412,9 @@ static uint32_t ARM64CountOfUnwindCodes(ArrayRef<WinEH::Instruction> Insns) {
     case Win64EH::UOP_Context:
       Count += 1;
       break;
+    case Win64EH::UOP_ECContext:
+      Count += 1;
+      break;
     case Win64EH::UOP_ClearUnwoundToCall:
       Count += 1;
       break;
@@ -593,6 +597,10 @@ static void ARM64EmitUnwindCode(MCStreamer &streamer,
     b = 0xEA;
     streamer.emitInt8(b);
     break;
+  case Win64EH::UOP_ECContext:
+    b = 0xEB;
+    streamer.emitInt8(b);
+    break;
   case Win64EH::UOP_ClearUnwoundToCall:
     b = 0xEC;
     streamer.emitInt8(b);
@@ -1010,6 +1018,7 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
       return false;
     case Win64EH::UOP_TrapFrame:
     case Win64EH::UOP_Context:
+    case Win64EH::UOP_ECContext:
     case Win64EH::UOP_ClearUnwoundToCall:
     case Win64EH::UOP_PushMachFrame:
       // These are special opcodes that aren't normally generated.
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index ae5ba6b13a1bd74..5fdab0beb25ea23 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -223,6 +223,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
   bool parseDirectiveSEHTrapFrame(SMLoc L);
   bool parseDirectiveSEHMachineFrame(SMLoc L);
   bool parseDirectiveSEHContext(SMLoc L);
+  bool parseDirectiveSEHECContext(SMLoc L);
   bool parseDirectiveSEHClearUnwoundToCall(SMLoc L);
   bool parseDirectiveSEHPACSignLR(SMLoc L);
   bool parseDirectiveSEHSaveAnyReg(SMLoc L, bool Paired, bool Writeback);
@@ -6712,6 +6713,8 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
       parseDirectiveSEHMachineFrame(Loc);
     else if (IDVal == ".seh_context")
       parseDirectiveSEHContext(Loc);
+    else if (IDVal == ".seh_ec_context")
+      parseDirectiveSEHECContext(Loc);
     else if (IDVal == ".seh_clear_unwound_to_call")
       parseDirectiveSEHClearUnwoundToCall(Loc);
     else if (IDVal == ".seh_pac_sign_lr")
@@ -7376,6 +7379,13 @@ bool AArch64AsmParser::parseDirectiveSEHContext(SMLoc L) {
   return false;
 }
 
+/// parseDirectiveSEHECContext
+/// ::= .seh_ec_context
+bool AArch64AsmParser::parseDirectiveSEHECContext(SMLoc L) {
+  getTargetStreamer().emitARM64WinCFIECContext();
+  return false;
+}
+
 /// parseDirectiveSEHClearUnwoundToCall
 /// ::= .seh_clear_unwound_to_call
 bool AArch64AsmParser::parseDirectiveSEHClearUnwoundToCall(SMLoc L) {
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
index 6a5f1430643d092..ad21f2673a64128 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
@@ -104,6 +104,7 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
   void emitARM64WinCFITrapFrame() override { OS << "\t.seh_trap_frame\n"; }
   void emitARM64WinCFIMachineFrame() override { OS << "\t.seh_pushframe\n"; }
   void emitARM64WinCFIContext() override { OS << "\t.seh_context\n"; }
+  void emitARM64WinCFIECContext() override { OS << "\t.seh_ec_context\n"; }
   void emitARM64WinCFIClearUnwoundToCall() override {
     OS << "\t.seh_clear_unwound_to_call\n";
   }
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
index b3bce9960772eb9..7676d88a82b5c78 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
@@ -66,6 +66,7 @@ class AArch64TargetStreamer : public MCTargetStreamer {
   virtual void emitARM64WinCFITrapFrame() {}
   virtual void emitARM64WinCFIMachineFrame() {}
   virtual void emitARM64WinCFIContext() {}
+  virtual void emitARM64WinCFIECContext() {}
   virtual void emitARM64WinCFIClearUnwoundToCall() {}
   virtual void emitARM64WinCFIPACSignLR() {}
   virtual void emitARM64WinCFISaveAnyRegI(unsigned Reg, int Offset) {}
@@ -132,6 +133,7 @@ class AArch64TargetWinCOFFStreamer : public llvm::AArch64TargetStreamer {
   void emitARM64WinCFITrapFrame() override;
   void emitARM64WinCFIMachineFrame() override;
   void emitARM64WinCFIContext() override;
+  void emitARM64WinCFIECContext() override;
   void emitARM64WinCFIClearUnwoundToCall() override;
   void emitARM64WinCFIPACSignLR() override;
   void emitARM64WinCFISaveAnyRegI(unsigned Reg, int Offset) override;
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp
index 4c8c2b437069cd5..438ac6cc47885ed 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp
@@ -219,6 +219,10 @@ void AArch64TargetWinCOFFStreamer::emitARM64WinCFIContext() {
   emitARM64WinUnwindCode(Win64EH::UOP_Context, -1, 0);
 }
 
+void AArch64TargetWinCOFFStreamer::emitARM64WinCFIECContext() {
+  emitARM64WinUnwindCode(Win64EH::UOP_ECContext, -1, 0);
+}
+
 void AArch64TargetWinCOFFStreamer::emitARM64WinCFIClearUnwoundToCall() {
   emitARM64WinUnwindCode(Win64EH::UOP_ClearUnwoundToCall, -1, 0);
 }
diff --git a/llvm/test/MC/AArch64/seh.s b/llvm/test/MC/AArch64/seh.s
index 4faf7daaa33eddc..dc10d9df7e24c57 100644
--- a/llvm/test/MC/AArch64/seh.s
+++ b/llvm/test/MC/AArch64/seh.s
@@ -71,6 +71,7 @@
 // CHECK-NEXT:         0xfc                ; pacibsp
 // CHECK-NEXT:         0xec                ; clear unwound to call
 // CHECK-NEXT:         0xea                ; context
+// CHECK-NEXT:         0xeb                ; EC context
 // CHECK-NEXT:         0xe9                ; machine frame
 // CHECK-NEXT:         0xe8                ; trap frame
 // CHECK-NEXT:         0xe3                ; nop
@@ -163,6 +164,8 @@ func:
     nop
     .seh_context
     nop
+    .seh_ec_context
+    nop
     .seh_clear_unwound_to_call
     pacibsp
     .seh_pac_sign_lr
diff --git a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
index ef77d4b2fd224bd..cf5c77cf107c36f 100644
--- a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
+++ b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
@@ -171,6 +171,7 @@ const Decoder::RingEntry Decoder::Ring64[] = {
     {0xff, 0xe8, 1, &Decoder::opcode_trap_frame},
     {0xff, 0xe9, 1, &Decoder::opcode_machine_frame},
     {0xff, 0xea, 1, &Decoder::opcode_context},
+    {0xff, 0xeb, 1, &Decoder::opcode_ec_context},
     {0xff, 0xec, 1, &Decoder::opcode_clear_unwound_to_call},
     {0xff, 0xfc, 1, &Decoder::opcode_pac_sign_lr},
 };
@@ -969,6 +970,13 @@ bool Decoder::opcode_context(const uint8_t *OC, unsigned &Offset,
   return false;
 }
 
+bool Decoder::opcode_ec_context(const uint8_t *OC, unsigned &Offset,
+                                unsigned Length, bool Prologue) {
+  SW.startLine() << format("0x%02x                ; EC context\n", OC[Offset]);
+  ++Offset;
+  return false;
+}
+
 bool Decoder::opcode_clear_unwound_to_call(const uint8_t *OC, unsigned &Offset,
                                            unsigned Length, bool Prologue) {
   SW.startLine() << format("0x%02x                ; clear unwound to call\n",
diff --git a/llvm/tools/llvm-readobj/ARMWinEHPrinter.h b/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
index 0ffebe5834c480b..fa5b31dd87b4b43 100644
--- a/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
+++ b/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
@@ -129,6 +129,8 @@ class Decoder {
                             unsigned Length, bool Prologue);
   bool opcode_context(const uint8_t *Opcodes, unsigned &Offset, unsigned Length,
                       bool Prologue);
+  bool opcode_ec_context(const uint8_t *Opcodes, unsigned &Offset,
+                         unsigned Length, bool Prologue);
   bool opcode_clear_unwound_to_call(const uint8_t *Opcodes, unsigned &Offset,
                                     unsigned Length, bool Prologue);
   bool opcode_pac_sign_lr(const uint8_t *Opcodes, unsigned &Offset,

``````````

</details>


https://github.com/llvm/llvm-project/pull/69520


More information about the llvm-commits mailing list