-
Notifications
You must be signed in to change notification settings - Fork 10.8k
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
Conversation
@llvm/pr-subscribers-mc @llvm/pr-subscribers-llvm-binary-utilities Author: Billy Laws (bylaws) ChangesARM64EC 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:
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)
There was a problem hiding this 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.
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.
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.
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)