mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-28 13:51:09 +00:00
[AArch64] Add asm directives for the remaining SEH unwind codes
Add support in llvm-readobj for displaying them and support in the asm parsser, AArch64TargetStreamer and MCWin64EH for emitting them. The directives for the remaining basic opcodes have names that match the opcode in the documentation. The directives for custom stack cases, that are named MSFT_OP_TRAP_FRAME, MSFT_OP_MACHINE_FRAME, MSFT_OP_CONTEXT and MSFT_OP_CLEAR_UNWOUND_TO_CALL, are given matching assembler directive names that fit into the rest of the opcode naming; .seh_trap_frame, .seh_context, .seh_clear_unwound_to_call The opcode MSFT_OP_MACHINE_FRAME is mapped to the existing opecode enum UOP_PushMachFrame that is used on x86_64, and also uses the corresponding existing x86_64 directive name .seh_pushframe. Differential Revision: https://reviews.llvm.org/D86889
This commit is contained in:
parent
06e7d50498
commit
5443644017
@ -38,12 +38,14 @@ enum UnwindOpcodes {
|
||||
// The following set of unwind opcodes is for ARM64. They are documented at
|
||||
// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
|
||||
UOP_AllocMedium,
|
||||
UOP_SaveR19R20X,
|
||||
UOP_SaveFPLRX,
|
||||
UOP_SaveFPLR,
|
||||
UOP_SaveReg,
|
||||
UOP_SaveRegX,
|
||||
UOP_SaveRegP,
|
||||
UOP_SaveRegPX,
|
||||
UOP_SaveLRPair,
|
||||
UOP_SaveFReg,
|
||||
UOP_SaveFRegX,
|
||||
UOP_SaveFRegP,
|
||||
@ -51,7 +53,11 @@ enum UnwindOpcodes {
|
||||
UOP_SetFP,
|
||||
UOP_AddFP,
|
||||
UOP_Nop,
|
||||
UOP_End
|
||||
UOP_End,
|
||||
UOP_SaveNext,
|
||||
UOP_TrapFrame,
|
||||
UOP_Context,
|
||||
UOP_ClearUnwoundToCall
|
||||
};
|
||||
|
||||
/// UnwindCode - This union describes a single operation in a function prolog,
|
||||
|
@ -280,6 +280,9 @@ ARM64CountOfUnwindCodes(const std::vector<WinEH::Instruction> &Insns) {
|
||||
case Win64EH::UOP_AllocLarge:
|
||||
Count += 4;
|
||||
break;
|
||||
case Win64EH::UOP_SaveR19R20X:
|
||||
Count += 1;
|
||||
break;
|
||||
case Win64EH::UOP_SaveFPLRX:
|
||||
Count += 1;
|
||||
break;
|
||||
@ -298,6 +301,9 @@ ARM64CountOfUnwindCodes(const std::vector<WinEH::Instruction> &Insns) {
|
||||
case Win64EH::UOP_SaveRegX:
|
||||
Count += 2;
|
||||
break;
|
||||
case Win64EH::UOP_SaveLRPair:
|
||||
Count += 2;
|
||||
break;
|
||||
case Win64EH::UOP_SaveFReg:
|
||||
Count += 2;
|
||||
break;
|
||||
@ -322,6 +328,21 @@ ARM64CountOfUnwindCodes(const std::vector<WinEH::Instruction> &Insns) {
|
||||
case Win64EH::UOP_End:
|
||||
Count += 1;
|
||||
break;
|
||||
case Win64EH::UOP_SaveNext:
|
||||
Count += 1;
|
||||
break;
|
||||
case Win64EH::UOP_TrapFrame:
|
||||
Count += 1;
|
||||
break;
|
||||
case Win64EH::UOP_PushMachFrame:
|
||||
Count += 1;
|
||||
break;
|
||||
case Win64EH::UOP_Context:
|
||||
Count += 1;
|
||||
break;
|
||||
case Win64EH::UOP_ClearUnwoundToCall:
|
||||
Count += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Count;
|
||||
@ -375,6 +396,11 @@ static void ARM64EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
|
||||
b = 0xE3;
|
||||
streamer.emitInt8(b);
|
||||
break;
|
||||
case Win64EH::UOP_SaveR19R20X:
|
||||
b = 0x20;
|
||||
b |= (inst.Offset >> 3) & 0x1F;
|
||||
streamer.emitInt8(b);
|
||||
break;
|
||||
case Win64EH::UOP_SaveFPLRX:
|
||||
b = 0x80;
|
||||
b |= ((inst.Offset - 1) >> 3) & 0x3F;
|
||||
@ -417,6 +443,16 @@ static void ARM64EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
|
||||
b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
|
||||
streamer.emitInt8(b);
|
||||
break;
|
||||
case Win64EH::UOP_SaveLRPair:
|
||||
assert(inst.Register >= 19 && "Saved reg must be >= 19");
|
||||
reg = inst.Register - 19;
|
||||
assert((reg % 2) == 0 && "Saved reg must be 19+2*X");
|
||||
reg /= 2;
|
||||
b = 0xD6 | ((reg & 0x7) >> 2);
|
||||
streamer.emitInt8(b);
|
||||
b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
|
||||
streamer.emitInt8(b);
|
||||
break;
|
||||
case Win64EH::UOP_SaveFReg:
|
||||
assert(inst.Register >= 8 && "Saved dreg must be >= 8");
|
||||
reg = inst.Register - 8;
|
||||
@ -453,6 +489,26 @@ static void ARM64EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
|
||||
b = 0xE4;
|
||||
streamer.emitInt8(b);
|
||||
break;
|
||||
case Win64EH::UOP_SaveNext:
|
||||
b = 0xE6;
|
||||
streamer.emitInt8(b);
|
||||
break;
|
||||
case Win64EH::UOP_TrapFrame:
|
||||
b = 0xE8;
|
||||
streamer.emitInt8(b);
|
||||
break;
|
||||
case Win64EH::UOP_PushMachFrame:
|
||||
b = 0xE9;
|
||||
streamer.emitInt8(b);
|
||||
break;
|
||||
case Win64EH::UOP_Context:
|
||||
b = 0xEA;
|
||||
streamer.emitInt8(b);
|
||||
break;
|
||||
case Win64EH::UOP_ClearUnwoundToCall:
|
||||
b = 0xEC;
|
||||
streamer.emitInt8(b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,12 +186,14 @@ private:
|
||||
|
||||
bool parseDirectiveSEHAllocStack(SMLoc L);
|
||||
bool parseDirectiveSEHPrologEnd(SMLoc L);
|
||||
bool parseDirectiveSEHSaveR19R20X(SMLoc L);
|
||||
bool parseDirectiveSEHSaveFPLR(SMLoc L);
|
||||
bool parseDirectiveSEHSaveFPLRX(SMLoc L);
|
||||
bool parseDirectiveSEHSaveReg(SMLoc L);
|
||||
bool parseDirectiveSEHSaveRegX(SMLoc L);
|
||||
bool parseDirectiveSEHSaveRegP(SMLoc L);
|
||||
bool parseDirectiveSEHSaveRegPX(SMLoc L);
|
||||
bool parseDirectiveSEHSaveLRPair(SMLoc L);
|
||||
bool parseDirectiveSEHSaveFReg(SMLoc L);
|
||||
bool parseDirectiveSEHSaveFRegX(SMLoc L);
|
||||
bool parseDirectiveSEHSaveFRegP(SMLoc L);
|
||||
@ -199,8 +201,13 @@ private:
|
||||
bool parseDirectiveSEHSetFP(SMLoc L);
|
||||
bool parseDirectiveSEHAddFP(SMLoc L);
|
||||
bool parseDirectiveSEHNop(SMLoc L);
|
||||
bool parseDirectiveSEHSaveNext(SMLoc L);
|
||||
bool parseDirectiveSEHEpilogStart(SMLoc L);
|
||||
bool parseDirectiveSEHEpilogEnd(SMLoc L);
|
||||
bool parseDirectiveSEHTrapFrame(SMLoc L);
|
||||
bool parseDirectiveSEHMachineFrame(SMLoc L);
|
||||
bool parseDirectiveSEHContext(SMLoc L);
|
||||
bool parseDirectiveSEHClearUnwoundToCall(SMLoc L);
|
||||
|
||||
bool validateInstruction(MCInst &Inst, SMLoc &IDLoc,
|
||||
SmallVectorImpl<SMLoc> &Loc);
|
||||
@ -5174,6 +5181,8 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
|
||||
parseDirectiveSEHAllocStack(Loc);
|
||||
else if (IDVal == ".seh_endprologue")
|
||||
parseDirectiveSEHPrologEnd(Loc);
|
||||
else if (IDVal == ".seh_save_r19r20_x")
|
||||
parseDirectiveSEHSaveR19R20X(Loc);
|
||||
else if (IDVal == ".seh_save_fplr")
|
||||
parseDirectiveSEHSaveFPLR(Loc);
|
||||
else if (IDVal == ".seh_save_fplr_x")
|
||||
@ -5186,6 +5195,8 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
|
||||
parseDirectiveSEHSaveRegP(Loc);
|
||||
else if (IDVal == ".seh_save_regp_x")
|
||||
parseDirectiveSEHSaveRegPX(Loc);
|
||||
else if (IDVal == ".seh_save_lrpair")
|
||||
parseDirectiveSEHSaveLRPair(Loc);
|
||||
else if (IDVal == ".seh_save_freg")
|
||||
parseDirectiveSEHSaveFReg(Loc);
|
||||
else if (IDVal == ".seh_save_freg_x")
|
||||
@ -5200,10 +5211,20 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
|
||||
parseDirectiveSEHAddFP(Loc);
|
||||
else if (IDVal == ".seh_nop")
|
||||
parseDirectiveSEHNop(Loc);
|
||||
else if (IDVal == ".seh_save_next")
|
||||
parseDirectiveSEHSaveNext(Loc);
|
||||
else if (IDVal == ".seh_startepilogue")
|
||||
parseDirectiveSEHEpilogStart(Loc);
|
||||
else if (IDVal == ".seh_endepilogue")
|
||||
parseDirectiveSEHEpilogEnd(Loc);
|
||||
else if (IDVal == ".seh_trap_frame")
|
||||
parseDirectiveSEHTrapFrame(Loc);
|
||||
else if (IDVal == ".seh_pushframe")
|
||||
parseDirectiveSEHMachineFrame(Loc);
|
||||
else if (IDVal == ".seh_context")
|
||||
parseDirectiveSEHContext(Loc);
|
||||
else if (IDVal == ".seh_clear_unwound_to_call")
|
||||
parseDirectiveSEHClearUnwoundToCall(Loc);
|
||||
else
|
||||
return true;
|
||||
} else
|
||||
@ -5645,6 +5666,16 @@ bool AArch64AsmParser::parseDirectiveSEHPrologEnd(SMLoc L) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// parseDirectiveSEHSaveR19R20X
|
||||
/// ::= .seh_save_r19r20_x
|
||||
bool AArch64AsmParser::parseDirectiveSEHSaveR19R20X(SMLoc L) {
|
||||
int64_t Offset;
|
||||
if (parseImmExpr(Offset))
|
||||
return true;
|
||||
getTargetStreamer().EmitARM64WinCFISaveR19R20X(Offset);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// parseDirectiveSEHSaveFPLR
|
||||
/// ::= .seh_save_fplr
|
||||
bool AArch64AsmParser::parseDirectiveSEHSaveFPLR(SMLoc L) {
|
||||
@ -5713,6 +5744,22 @@ bool AArch64AsmParser::parseDirectiveSEHSaveRegPX(SMLoc L) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// parseDirectiveSEHSaveLRPair
|
||||
/// ::= .seh_save_lrpair
|
||||
bool AArch64AsmParser::parseDirectiveSEHSaveLRPair(SMLoc L) {
|
||||
unsigned Reg;
|
||||
int64_t Offset;
|
||||
L = getLoc();
|
||||
if (parseRegisterInRange(Reg, AArch64::X0, AArch64::X19, AArch64::LR) ||
|
||||
parseComma() || parseImmExpr(Offset))
|
||||
return true;
|
||||
if (check(((Reg - 19) % 2 != 0), L,
|
||||
"expected register with even offset from x19"))
|
||||
return true;
|
||||
getTargetStreamer().EmitARM64WinCFISaveLRPair(Reg, Offset);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// parseDirectiveSEHSaveFReg
|
||||
/// ::= .seh_save_freg
|
||||
bool AArch64AsmParser::parseDirectiveSEHSaveFReg(SMLoc L) {
|
||||
@ -5785,6 +5832,13 @@ bool AArch64AsmParser::parseDirectiveSEHNop(SMLoc L) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// parseDirectiveSEHSaveNext
|
||||
/// ::= .seh_save_next
|
||||
bool AArch64AsmParser::parseDirectiveSEHSaveNext(SMLoc L) {
|
||||
getTargetStreamer().EmitARM64WinCFISaveNext();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// parseDirectiveSEHEpilogStart
|
||||
/// ::= .seh_startepilogue
|
||||
bool AArch64AsmParser::parseDirectiveSEHEpilogStart(SMLoc L) {
|
||||
@ -5799,6 +5853,34 @@ bool AArch64AsmParser::parseDirectiveSEHEpilogEnd(SMLoc L) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// parseDirectiveSEHTrapFrame
|
||||
/// ::= .seh_trap_frame
|
||||
bool AArch64AsmParser::parseDirectiveSEHTrapFrame(SMLoc L) {
|
||||
getTargetStreamer().EmitARM64WinCFITrapFrame();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// parseDirectiveSEHMachineFrame
|
||||
/// ::= .seh_pushframe
|
||||
bool AArch64AsmParser::parseDirectiveSEHMachineFrame(SMLoc L) {
|
||||
getTargetStreamer().EmitARM64WinCFIMachineFrame();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// parseDirectiveSEHContext
|
||||
/// ::= .seh_context
|
||||
bool AArch64AsmParser::parseDirectiveSEHContext(SMLoc L) {
|
||||
getTargetStreamer().EmitARM64WinCFIContext();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// parseDirectiveSEHClearUnwoundToCall
|
||||
/// ::= .seh_clear_unwound_to_call
|
||||
bool AArch64AsmParser::parseDirectiveSEHClearUnwoundToCall(SMLoc L) {
|
||||
getTargetStreamer().EmitARM64WinCFIClearUnwoundToCall();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
|
||||
AArch64MCExpr::VariantKind &ELFRefKind,
|
||||
|
@ -50,6 +50,9 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
|
||||
void EmitARM64WinCFIAllocStack(unsigned Size) override {
|
||||
OS << "\t.seh_stackalloc " << Size << "\n";
|
||||
}
|
||||
void EmitARM64WinCFISaveR19R20X(int Offset) override {
|
||||
OS << "\t.seh_save_r19r20_x " << Offset << "\n";
|
||||
}
|
||||
void EmitARM64WinCFISaveFPLR(int Offset) override {
|
||||
OS << "\t.seh_save_fplr " << Offset << "\n";
|
||||
}
|
||||
@ -68,6 +71,9 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
|
||||
void EmitARM64WinCFISaveRegPX(unsigned Reg, int Offset) override {
|
||||
OS << "\t.seh_save_regp_x x" << Reg << ", " << Offset << "\n";
|
||||
}
|
||||
void EmitARM64WinCFISaveLRPair(unsigned Reg, int Offset) override {
|
||||
OS << "\t.seh_save_lrpair x" << Reg << ", " << Offset << "\n";
|
||||
}
|
||||
void EmitARM64WinCFISaveFReg(unsigned Reg, int Offset) override {
|
||||
OS << "\t.seh_save_freg d" << Reg << ", " << Offset << "\n";
|
||||
}
|
||||
@ -85,9 +91,16 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
|
||||
OS << "\t.seh_add_fp " << Size << "\n";
|
||||
}
|
||||
void EmitARM64WinCFINop() override { OS << "\t.seh_nop\n"; }
|
||||
void EmitARM64WinCFISaveNext() override { OS << "\t.seh_save_next\n"; }
|
||||
void EmitARM64WinCFIPrologEnd() override { OS << "\t.seh_endprologue\n"; }
|
||||
void EmitARM64WinCFIEpilogStart() override { OS << "\t.seh_startepilogue\n"; }
|
||||
void EmitARM64WinCFIEpilogEnd() override { OS << "\t.seh_endepilogue\n"; }
|
||||
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 EmitARM64WinCFIClearUnwoundToCall() override {
|
||||
OS << "\t.seh_clear_unwound_to_call\n";
|
||||
}
|
||||
|
||||
public:
|
||||
AArch64TargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
|
||||
|
@ -37,12 +37,14 @@ public:
|
||||
virtual void emitInst(uint32_t Inst);
|
||||
|
||||
virtual void EmitARM64WinCFIAllocStack(unsigned Size) {}
|
||||
virtual void EmitARM64WinCFISaveR19R20X(int Offset) {}
|
||||
virtual void EmitARM64WinCFISaveFPLR(int Offset) {}
|
||||
virtual void EmitARM64WinCFISaveFPLRX(int Offset) {}
|
||||
virtual void EmitARM64WinCFISaveReg(unsigned Reg, int Offset) {}
|
||||
virtual void EmitARM64WinCFISaveRegX(unsigned Reg, int Offset) {}
|
||||
virtual void EmitARM64WinCFISaveRegP(unsigned Reg, int Offset) {}
|
||||
virtual void EmitARM64WinCFISaveRegPX(unsigned Reg, int Offset) {}
|
||||
virtual void EmitARM64WinCFISaveLRPair(unsigned Reg, int Offset) {}
|
||||
virtual void EmitARM64WinCFISaveFReg(unsigned Reg, int Offset) {}
|
||||
virtual void EmitARM64WinCFISaveFRegX(unsigned Reg, int Offset) {}
|
||||
virtual void EmitARM64WinCFISaveFRegP(unsigned Reg, int Offset) {}
|
||||
@ -50,9 +52,14 @@ public:
|
||||
virtual void EmitARM64WinCFISetFP() {}
|
||||
virtual void EmitARM64WinCFIAddFP(unsigned Size) {}
|
||||
virtual void EmitARM64WinCFINop() {}
|
||||
virtual void EmitARM64WinCFISaveNext() {}
|
||||
virtual void EmitARM64WinCFIPrologEnd() {}
|
||||
virtual void EmitARM64WinCFIEpilogStart() {}
|
||||
virtual void EmitARM64WinCFIEpilogEnd() {}
|
||||
virtual void EmitARM64WinCFITrapFrame() {}
|
||||
virtual void EmitARM64WinCFIMachineFrame() {}
|
||||
virtual void EmitARM64WinCFIContext() {}
|
||||
virtual void EmitARM64WinCFIClearUnwoundToCall() {}
|
||||
|
||||
private:
|
||||
std::unique_ptr<AssemblerConstantPools> ConstantPools;
|
||||
@ -82,12 +89,14 @@ public:
|
||||
// The unwind codes on ARM64 Windows are documented at
|
||||
// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
|
||||
void EmitARM64WinCFIAllocStack(unsigned Size) override;
|
||||
void EmitARM64WinCFISaveR19R20X(int Offset) override;
|
||||
void EmitARM64WinCFISaveFPLR(int Offset) override;
|
||||
void EmitARM64WinCFISaveFPLRX(int Offset) override;
|
||||
void EmitARM64WinCFISaveReg(unsigned Reg, int Offset) override;
|
||||
void EmitARM64WinCFISaveRegX(unsigned Reg, int Offset) override;
|
||||
void EmitARM64WinCFISaveRegP(unsigned Reg, int Offset) override;
|
||||
void EmitARM64WinCFISaveRegPX(unsigned Reg, int Offset) override;
|
||||
void EmitARM64WinCFISaveLRPair(unsigned Reg, int Offset) override;
|
||||
void EmitARM64WinCFISaveFReg(unsigned Reg, int Offset) override;
|
||||
void EmitARM64WinCFISaveFRegX(unsigned Reg, int Offset) override;
|
||||
void EmitARM64WinCFISaveFRegP(unsigned Reg, int Offset) override;
|
||||
@ -95,9 +104,15 @@ public:
|
||||
void EmitARM64WinCFISetFP() override;
|
||||
void EmitARM64WinCFIAddFP(unsigned Size) override;
|
||||
void EmitARM64WinCFINop() override;
|
||||
void EmitARM64WinCFISaveNext() override;
|
||||
void EmitARM64WinCFIPrologEnd() override;
|
||||
void EmitARM64WinCFIEpilogStart() override;
|
||||
void EmitARM64WinCFIEpilogEnd() override;
|
||||
void EmitARM64WinCFITrapFrame() override;
|
||||
void EmitARM64WinCFIMachineFrame() override;
|
||||
void EmitARM64WinCFIContext() override;
|
||||
void EmitARM64WinCFIClearUnwoundToCall() override;
|
||||
|
||||
private:
|
||||
void EmitARM64WinUnwindCode(unsigned UnwindCode, int Reg, int Offset);
|
||||
};
|
||||
|
@ -85,6 +85,10 @@ void AArch64TargetWinCOFFStreamer::EmitARM64WinCFIAllocStack(unsigned Size) {
|
||||
EmitARM64WinUnwindCode(Op, -1, Size);
|
||||
}
|
||||
|
||||
void AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveR19R20X(int Offset) {
|
||||
EmitARM64WinUnwindCode(Win64EH::UOP_SaveR19R20X, -1, Offset);
|
||||
}
|
||||
|
||||
void AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveFPLR(int Offset) {
|
||||
EmitARM64WinUnwindCode(Win64EH::UOP_SaveFPLR, -1, Offset);
|
||||
}
|
||||
@ -115,6 +119,11 @@ void AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveRegPX(unsigned Reg,
|
||||
EmitARM64WinUnwindCode(Win64EH::UOP_SaveRegPX, Reg, Offset);
|
||||
}
|
||||
|
||||
void AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveLRPair(unsigned Reg,
|
||||
int Offset) {
|
||||
EmitARM64WinUnwindCode(Win64EH::UOP_SaveLRPair, Reg, Offset);
|
||||
}
|
||||
|
||||
void AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveFReg(unsigned Reg,
|
||||
int Offset) {
|
||||
assert(Offset >= 0 && Offset <= 504 &&
|
||||
@ -150,6 +159,10 @@ void AArch64TargetWinCOFFStreamer::EmitARM64WinCFINop() {
|
||||
EmitARM64WinUnwindCode(Win64EH::UOP_Nop, -1, 0);
|
||||
}
|
||||
|
||||
void AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveNext() {
|
||||
EmitARM64WinUnwindCode(Win64EH::UOP_SaveNext, -1, 0);
|
||||
}
|
||||
|
||||
// The functions below handle opcodes that can end up in either a prolog or
|
||||
// an epilog, but not both.
|
||||
void AArch64TargetWinCOFFStreamer::EmitARM64WinCFIPrologEnd() {
|
||||
@ -188,6 +201,22 @@ void AArch64TargetWinCOFFStreamer::EmitARM64WinCFIEpilogEnd() {
|
||||
CurrentEpilog = nullptr;
|
||||
}
|
||||
|
||||
void AArch64TargetWinCOFFStreamer::EmitARM64WinCFITrapFrame() {
|
||||
EmitARM64WinUnwindCode(Win64EH::UOP_TrapFrame, -1, 0);
|
||||
}
|
||||
|
||||
void AArch64TargetWinCOFFStreamer::EmitARM64WinCFIMachineFrame() {
|
||||
EmitARM64WinUnwindCode(Win64EH::UOP_PushMachFrame, -1, 0);
|
||||
}
|
||||
|
||||
void AArch64TargetWinCOFFStreamer::EmitARM64WinCFIContext() {
|
||||
EmitARM64WinUnwindCode(Win64EH::UOP_Context, -1, 0);
|
||||
}
|
||||
|
||||
void AArch64TargetWinCOFFStreamer::EmitARM64WinCFIClearUnwoundToCall() {
|
||||
EmitARM64WinUnwindCode(Win64EH::UOP_ClearUnwoundToCall, -1, 0);
|
||||
}
|
||||
|
||||
MCWinCOFFStreamer *createAArch64WinCOFFStreamer(
|
||||
MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
|
||||
std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter,
|
||||
|
@ -20,7 +20,7 @@
|
||||
// CHECK-NEXT: }
|
||||
// CHECK: Section {
|
||||
// CHECK: Name: .xdata
|
||||
// CHECK: RawDataSize: 48
|
||||
// CHECK: RawDataSize: 56
|
||||
// CHECK: RelocationCount: 1
|
||||
// CHECK: Characteristics [
|
||||
// CHECK-NEXT: ALIGN_4BYTES
|
||||
@ -41,7 +41,7 @@
|
||||
|
||||
// CHECK-NEXT: Relocations [
|
||||
// CHECK-NEXT: Section (4) .xdata {
|
||||
// CHECK-NEXT: 0x24 IMAGE_REL_ARM64_ADDR32NB __C_specific_handler
|
||||
// CHECK-NEXT: 0x2C IMAGE_REL_ARM64_ADDR32NB __C_specific_handler
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Section (5) .pdata {
|
||||
// CHECK-NEXT: 0x0 IMAGE_REL_ARM64_ADDR32NB func
|
||||
@ -54,8 +54,12 @@
|
||||
// CHECK-NEXT: Function: func
|
||||
// CHECK-NEXT: ExceptionRecord: .xdata
|
||||
// CHECK-NEXT: ExceptionData {
|
||||
// CHECK-NEXT: FunctionLength: 72
|
||||
// CHECK-NEXT: FunctionLength: 100
|
||||
// CHECK: Prologue [
|
||||
// CHECK-NEXT: 0xec ; clear unwound to call
|
||||
// CHECK-NEXT: 0xea ; context
|
||||
// CHECK-NEXT: 0xe9 ; machine frame
|
||||
// CHECK-NEXT: 0xe8 ; trap frame
|
||||
// CHECK-NEXT: 0xe3 ; nop
|
||||
// CHECK-NEXT: 0xe202 ; add fp, sp, #16
|
||||
// CHECK-NEXT: 0xdd41 ; str d13, [sp, #8]
|
||||
@ -66,7 +70,10 @@
|
||||
// CHECK-NEXT: 0x46 ; stp x29, x30, [sp, #48]
|
||||
// CHECK-NEXT: 0xd141 ; str x24, [sp, #8]
|
||||
// CHECK-NEXT: 0xd483 ; str x23, [sp, #-32]!
|
||||
// CHECK-NEXT: 0xe6 ; save next
|
||||
// CHECK-NEXT: 0xc882 ; stp x21, x22, [sp, #16]
|
||||
// CHECK-NEXT: 0xd6c2 ; stp x25, lr, [sp, #16]
|
||||
// CHECK-NEXT: 0x24 ; stp x19, x20, [sp, #-32]!
|
||||
// CHECK-NEXT: 0xcc03 ; stp x19, x20, [sp, #-32]!
|
||||
// CHECK-NEXT: 0x83 ; stp x29, x30, [sp, #-32]!
|
||||
// CHECK-NEXT: 0xe1 ; mov fp, sp
|
||||
@ -75,8 +82,8 @@
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: EpilogueScopes [
|
||||
// CHECK-NEXT: EpilogueScope {
|
||||
// CHECK-NEXT: StartOffset: 16
|
||||
// CHECK-NEXT: EpilogueStartIndex: 25
|
||||
// CHECK-NEXT: StartOffset: 23
|
||||
// CHECK-NEXT: EpilogueStartIndex: 33
|
||||
// CHECK-NEXT: Opcodes [
|
||||
// CHECK-NEXT: 0x01 ; add sp, #16
|
||||
// CHECK-NEXT: 0xe4 ; end
|
||||
@ -108,8 +115,14 @@ func:
|
||||
.seh_save_fplr_x 32
|
||||
stp x19, x20, [sp, #-32]!
|
||||
.seh_save_regp_x x19, 32
|
||||
stp x19, x20, [sp, #-32]!
|
||||
.seh_save_r19r20_x 32
|
||||
stp x25, x30, [sp, #16]
|
||||
.seh_save_lrpair x25, 16
|
||||
stp x21, x22, [sp, #16]
|
||||
.seh_save_regp x21, 16
|
||||
stp x23, x24, [sp, #32]
|
||||
.seh_save_next
|
||||
str x23, [sp, #-32]!
|
||||
.seh_save_reg_x x23, 32
|
||||
str x24, [sp, #8]
|
||||
@ -130,6 +143,14 @@ func:
|
||||
.seh_add_fp 16
|
||||
nop
|
||||
.seh_nop
|
||||
nop
|
||||
.seh_trap_frame
|
||||
nop
|
||||
.seh_pushframe
|
||||
nop
|
||||
.seh_context
|
||||
nop
|
||||
.seh_clear_unwound_to_call
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
|
@ -167,6 +167,11 @@ const Decoder::RingEntry Decoder::Ring64[] = {
|
||||
{ 0xff, 0xe3, 1, &Decoder::opcode_nop },
|
||||
{ 0xff, 0xe4, 1, &Decoder::opcode_end },
|
||||
{ 0xff, 0xe5, 1, &Decoder::opcode_end_c },
|
||||
{ 0xff, 0xe6, 1, &Decoder::opcode_save_next },
|
||||
{ 0xff, 0xe8, 1, &Decoder::opcode_trap_frame },
|
||||
{ 0xff, 0xe9, 1, &Decoder::opcode_machine_frame },
|
||||
{ 0xff, 0xea, 1, &Decoder::opcode_context },
|
||||
{ 0xff, 0xec, 1, &Decoder::opcode_clear_unwound_to_call },
|
||||
};
|
||||
|
||||
void Decoder::printRegisters(const std::pair<uint16_t, uint32_t> &RegisterMask) {
|
||||
@ -776,6 +781,47 @@ bool Decoder::opcode_end_c(const uint8_t *OC, unsigned &Offset, unsigned Length,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Decoder::opcode_save_next(const uint8_t *OC, unsigned &Offset,
|
||||
unsigned Length, bool Prologue) {
|
||||
if (Prologue)
|
||||
SW.startLine() << format("0x%02x ; save next\n", OC[Offset]);
|
||||
else
|
||||
SW.startLine() << format("0x%02x ; restore next\n",
|
||||
OC[Offset]);
|
||||
++Offset;
|
||||
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]);
|
||||
++Offset;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Decoder::opcode_machine_frame(const uint8_t *OC, unsigned &Offset,
|
||||
unsigned Length, bool Prologue) {
|
||||
SW.startLine() << format("0x%02x ; machine frame\n",
|
||||
OC[Offset]);
|
||||
++Offset;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Decoder::opcode_context(const uint8_t *OC, unsigned &Offset,
|
||||
unsigned Length, bool Prologue) {
|
||||
SW.startLine() << format("0x%02x ; 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",
|
||||
OC[Offset]);
|
||||
++Offset;
|
||||
return false;
|
||||
}
|
||||
|
||||
void Decoder::decodeOpcodes(ArrayRef<uint8_t> Opcodes, unsigned Offset,
|
||||
bool Prologue) {
|
||||
assert((!Prologue || Offset == 0) && "prologue should always use offset 0");
|
||||
|
@ -120,6 +120,14 @@ class Decoder {
|
||||
bool Prologue);
|
||||
bool opcode_save_next(const uint8_t *Opcodes, unsigned &Offset,
|
||||
unsigned Length, bool Prologue);
|
||||
bool opcode_trap_frame(const uint8_t *Opcodes, unsigned &Offset,
|
||||
unsigned Length, bool Prologue);
|
||||
bool opcode_machine_frame(const uint8_t *Opcodes, unsigned &Offset,
|
||||
unsigned Length, bool Prologue);
|
||||
bool opcode_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);
|
||||
|
||||
void decodeOpcodes(ArrayRef<uint8_t> Opcodes, unsigned Offset,
|
||||
bool Prologue);
|
||||
|
Loading…
Reference in New Issue
Block a user