Skip to content
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

[AArch64][Windows] Add MC support for ec_context #69520

Merged
merged 2 commits into from
Nov 16, 2023
Merged

Conversation

bylaws
Copy link
Contributor

@bylaws bylaws commented Oct 18, 2023

ARM64EC uses the same CONTEXT structure as x86_64 as opposed to the regular ARM64 context, a new unwind opcode (MSFT_OP_EC_CONTEXT) is added to handle this.

(depends on #69515)

@llvmbot
Copy link
Collaborator

llvmbot commented Oct 18, 2023

@llvm/pr-subscribers-mc
@llvm/pr-subscribers-backend-aarch64
@llvm/pr-subscribers-llvm-support

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

Author: Billy Laws (bylaws)

Changes

ARM64EC uses the same CONTEXT structure as x86_64 as opposed to the regular ARM64 context, a new unwind opcode (MSFT_OP_EC_CONTEXT) is added to handle this.

(depends on #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 --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,

ARM64EC uses the same CONTEXT structure as x86_64, a new unwind opcode
is added to handle this [1].

[1]: https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling?view=msvc-170 (MSFT_OP_EC_CONTEXT)
@bylaws
Copy link
Contributor Author

bylaws commented Nov 13, 2023

cc: @mstorsjo @cjacek

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!

I don't remember offhand if there are more places that need to be updated when adding a new opcode, but I can't think of any at least, and this looks good.

@cjacek cjacek merged commit 825e4ae into llvm:main Nov 16, 2023
3 checks passed
sr-tream pushed a commit to sr-tream/llvm-project that referenced this pull request Nov 20, 2023
ARM64EC uses the same CONTEXT structure as x86_64 as opposed to the
regular ARM64 context, a new unwind MSFT_OP_EC_CONTEXT is added to
handle this.
zahiraam pushed a commit to zahiraam/llvm-project that referenced this pull request Nov 20, 2023
ARM64EC uses the same CONTEXT structure as x86_64 as opposed to the
regular ARM64 context, a new unwind MSFT_OP_EC_CONTEXT is added to
handle this.
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.

None yet

5 participants