diff --git a/llvm/include/llvm/Support/Win64EH.h b/llvm/include/llvm/Support/Win64EH.h index e84fd6d72bedb..cf54f49286830 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 bb3492bec8aad..bd5cf354659b6 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 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 ae5ba6b13a1bd..5fdab0beb25ea 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 6a5f1430643d0..ad21f2673a641 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 b3bce9960772e..7676d88a82b5c 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 4c8c2b437069c..438ac6cc47885 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 4faf7daaa33ed..5ad4fba2bf6b4 100644 --- a/llvm/test/MC/AArch64/seh.s +++ b/llvm/test/MC/AArch64/seh.s @@ -54,7 +54,7 @@ // CHECK-NEXT: Function: func // CHECK-NEXT: ExceptionRecord: .xdata // CHECK-NEXT: ExceptionData { -// CHECK-NEXT: FunctionLength: 152 +// CHECK-NEXT: FunctionLength: 156 // CHECK: Prologue [ // CHECK-NEXT: 0xe76983 ; stp q9, q10, [sp, #-64]! // CHECK-NEXT: 0xe73d83 ; str q29, [sp, #-64]! @@ -70,6 +70,7 @@ // CHECK-NEXT: 0xe70008 ; str x0, [sp, #64] // CHECK-NEXT: 0xfc ; pacibsp // CHECK-NEXT: 0xec ; clear unwound to call +// CHECK-NEXT: 0xeb ; EC context // CHECK-NEXT: 0xea ; context // CHECK-NEXT: 0xe9 ; machine frame // CHECK-NEXT: 0xe8 ; trap frame @@ -95,8 +96,8 @@ // CHECK-NEXT: ] // CHECK-NEXT: EpilogueScopes [ // CHECK-NEXT: EpilogueScope { -// CHECK-NEXT: StartOffset: 36 -// CHECK-NEXT: EpilogueStartIndex: 68 +// CHECK-NEXT: StartOffset: 37 +// CHECK-NEXT: EpilogueStartIndex: 69 // CHECK-NEXT: Opcodes [ // CHECK-NEXT: 0x01 ; add sp, #16 // CHECK-NEXT: 0xe4 ; end @@ -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 ef77d4b2fd224..cf5c77cf107c3 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 0ffebe5834c48..fa5b31dd87b4b 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,