diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2017-06-27 16:43:30 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2017-06-27 16:43:30 +0000 |
commit | 028508266b5be8367ae92a96ce81097dd729d313 (patch) | |
tree | 0eaf02b190b465c7085ccd5f96cf34270763a986 /gnu | |
parent | 4bddd9481bb95030bf007bca37aae2807413caab (diff) |
trapsleds for clang, similar to the change on gas side.
Also from Todd Mortimer
tested by espie
Diffstat (limited to 'gnu')
-rw-r--r-- | gnu/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp | 176 |
1 files changed, 102 insertions, 74 deletions
diff --git a/gnu/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/gnu/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index 135c32bf8c3..250afed034f 100644 --- a/gnu/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/gnu/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -21,7 +21,7 @@ #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSectionMachO.h" -#include "llvm/Support/CommandLine.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MachO.h" @@ -43,8 +43,11 @@ static unsigned getFixupKindLog2Size(unsigned Kind) { return 1; case FK_PCRel_4: case X86::reloc_riprel_4byte: + case X86::reloc_riprel_4byte_relax: + case X86::reloc_riprel_4byte_relax_rex: case X86::reloc_riprel_4byte_movq_load: case X86::reloc_signed_4byte: + case X86::reloc_signed_4byte_relax: case X86::reloc_global_offset_table: case FK_SecRel_4: case FK_Data_4: @@ -72,12 +75,13 @@ class X86AsmBackend : public MCAsmBackend { const uint64_t MaxNopLength; public: X86AsmBackend(const Target &T, StringRef CPU) - : MCAsmBackend(), CPU(CPU), MaxNopLength(CPU == "slm" ? 7 : 15) { + : MCAsmBackend(), CPU(CPU), + MaxNopLength((CPU == "slm") ? 7 : 15) { HasNopl = CPU != "generic" && CPU != "i386" && CPU != "i486" && CPU != "i586" && CPU != "pentium" && CPU != "pentium-mmx" && CPU != "i686" && CPU != "k6" && CPU != "k6-2" && CPU != "k6-3" && CPU != "geode" && CPU != "winchip-c6" && CPU != "winchip2" && - CPU != "c3" && CPU != "c3-2"; + CPU != "c3" && CPU != "c3-2" && CPU != "lakemont"; } unsigned getNumFixupKinds() const override { @@ -86,10 +90,14 @@ public: const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { const static MCFixupKindInfo Infos[X86::NumTargetFixupKinds] = { - { "reloc_riprel_4byte", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel }, - { "reloc_riprel_4byte_movq_load", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel}, - { "reloc_signed_4byte", 0, 4 * 8, 0}, - { "reloc_global_offset_table", 0, 4 * 8, 0} + {"reloc_riprel_4byte", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, + {"reloc_riprel_4byte_movq_load", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, + {"reloc_riprel_4byte_relax", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, + {"reloc_riprel_4byte_relax_rex", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, + {"reloc_signed_4byte", 0, 32, 0}, + {"reloc_signed_4byte_relax", 0, 32, 0}, + {"reloc_global_offset_table", 0, 32, 0}, + {"reloc_global_offset_table8", 0, 64, 0}, }; if (Kind < FirstTargetFixupKind) @@ -124,38 +132,57 @@ public: const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const override; - void relaxInstruction(const MCInst &Inst, MCInst &Res) const override; + void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, + MCInst &Res) const override; bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; }; } // end anonymous namespace -static unsigned getRelaxedOpcodeBranch(unsigned Op) { +static unsigned getRelaxedOpcodeBranch(const MCInst &Inst, bool is16BitMode) { + unsigned Op = Inst.getOpcode(); switch (Op) { default: return Op; - - case X86::JAE_1: return X86::JAE_4; - case X86::JA_1: return X86::JA_4; - case X86::JBE_1: return X86::JBE_4; - case X86::JB_1: return X86::JB_4; - case X86::JE_1: return X86::JE_4; - case X86::JGE_1: return X86::JGE_4; - case X86::JG_1: return X86::JG_4; - case X86::JLE_1: return X86::JLE_4; - case X86::JL_1: return X86::JL_4; - case X86::JMP_1: return X86::JMP_4; - case X86::JNE_1: return X86::JNE_4; - case X86::JNO_1: return X86::JNO_4; - case X86::JNP_1: return X86::JNP_4; - case X86::JNS_1: return X86::JNS_4; - case X86::JO_1: return X86::JO_4; - case X86::JP_1: return X86::JP_4; - case X86::JS_1: return X86::JS_4; + case X86::JAE_1: + return (is16BitMode) ? X86::JAE_2 : X86::JAE_4; + case X86::JA_1: + return (is16BitMode) ? X86::JA_2 : X86::JA_4; + case X86::JBE_1: + return (is16BitMode) ? X86::JBE_2 : X86::JBE_4; + case X86::JB_1: + return (is16BitMode) ? X86::JB_2 : X86::JB_4; + case X86::JE_1: + return (is16BitMode) ? X86::JE_2 : X86::JE_4; + case X86::JGE_1: + return (is16BitMode) ? X86::JGE_2 : X86::JGE_4; + case X86::JG_1: + return (is16BitMode) ? X86::JG_2 : X86::JG_4; + case X86::JLE_1: + return (is16BitMode) ? X86::JLE_2 : X86::JLE_4; + case X86::JL_1: + return (is16BitMode) ? X86::JL_2 : X86::JL_4; + case X86::JMP_1: + return (is16BitMode) ? X86::JMP_2 : X86::JMP_4; + case X86::JNE_1: + return (is16BitMode) ? X86::JNE_2 : X86::JNE_4; + case X86::JNO_1: + return (is16BitMode) ? X86::JNO_2 : X86::JNO_4; + case X86::JNP_1: + return (is16BitMode) ? X86::JNP_2 : X86::JNP_4; + case X86::JNS_1: + return (is16BitMode) ? X86::JNS_2 : X86::JNS_4; + case X86::JO_1: + return (is16BitMode) ? X86::JO_2 : X86::JO_4; + case X86::JP_1: + return (is16BitMode) ? X86::JP_2 : X86::JP_4; + case X86::JS_1: + return (is16BitMode) ? X86::JS_2 : X86::JS_4; } } -static unsigned getRelaxedOpcodeArith(unsigned Op) { +static unsigned getRelaxedOpcodeArith(const MCInst &Inst) { + unsigned Op = Inst.getOpcode(); switch (Op) { default: return Op; @@ -239,20 +266,20 @@ static unsigned getRelaxedOpcodeArith(unsigned Op) { } } -static unsigned getRelaxedOpcode(unsigned Op) { - unsigned R = getRelaxedOpcodeArith(Op); - if (R != Op) +static unsigned getRelaxedOpcode(const MCInst &Inst, bool is16BitMode) { + unsigned R = getRelaxedOpcodeArith(Inst); + if (R != Inst.getOpcode()) return R; - return getRelaxedOpcodeBranch(Op); + return getRelaxedOpcodeBranch(Inst, is16BitMode); } bool X86AsmBackend::mayNeedRelaxation(const MCInst &Inst) const { - // Branches can always be relaxed. - if (getRelaxedOpcodeBranch(Inst.getOpcode()) != Inst.getOpcode()) + // Branches can always be relaxed in either mode. + if (getRelaxedOpcodeBranch(Inst, false) != Inst.getOpcode()) return true; // Check if this instruction is ever relaxable. - if (getRelaxedOpcodeArith(Inst.getOpcode()) == Inst.getOpcode()) + if (getRelaxedOpcodeArith(Inst) == Inst.getOpcode()) return false; @@ -275,9 +302,12 @@ bool X86AsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, // FIXME: Can tblgen help at all here to verify there aren't other instructions // we can relax? -void X86AsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const { +void X86AsmBackend::relaxInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI, + MCInst &Res) const { // The only relaxations X86 does is from a 1byte pcrel to a 4byte pcrel. - unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode()); + bool is16BitMode = STI.getFeatureBits()[X86::Mode16Bit]; + unsigned RelaxedOp = getRelaxedOpcode(Inst, is16BitMode); if (RelaxedOp == Inst.getOpcode()) { SmallString<256> Tmp; @@ -295,28 +325,6 @@ void X86AsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const { /// bytes. /// \return - true on success, false on failure bool X86AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { - static const uint8_t Nops[10][10] = { - // nop - {0x90}, - // xchg %ax,%ax - {0x66, 0x90}, - // nopl (%[re]ax) - {0x0f, 0x1f, 0x00}, - // nopl 0(%[re]ax) - {0x0f, 0x1f, 0x40, 0x00}, - // nopl 0(%[re]ax,%[re]ax,1) - {0x0f, 0x1f, 0x44, 0x00, 0x00}, - // nopw 0(%[re]ax,%[re]ax,1) - {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00}, - // nopl 0L(%[re]ax) - {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00}, - // nopl 0L(%[re]ax,%[re]ax,1) - {0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, - // nopw 0L(%[re]ax,%[re]ax,1) - {0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, - // nopw %cs:0L(%[re]ax,%[re]ax,1) - {0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, - }; // This CPU doesn't support long nops. If needed add more. // FIXME: Can we get this from the subtarget somehow? @@ -327,16 +335,22 @@ bool X86AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { return true; } - // 15 is the longest single nop instruction. Emit as many 15-byte nops as - // needed, then emit a nop of the remaining length. + // Write 1 or 2 byte NOP sequences, or a longer trapsled, until + // we have written Count bytes do { - const uint8_t ThisNopLength = (uint8_t) std::min(Count, MaxNopLength); - const uint8_t Prefixes = ThisNopLength <= 10 ? 0 : ThisNopLength - 10; - for (uint8_t i = 0; i < Prefixes; i++) - OW->write8(0x66); - const uint8_t Rest = ThisNopLength - Prefixes; - for (uint8_t i = 0; i < Rest; i++) - OW->write8(Nops[Rest - 1][i]); + const uint8_t ThisNopLength = (uint8_t) std::min(Count, (uint64_t)127); + switch (ThisNopLength) { + case 0: break; + case 1: OW->write8(0x90); + break; + case 2: OW->write8(0x66); + OW->write8(0x90); + break; + default: OW->write8(0xEB); + OW->write8(ThisNopLength - 2); + for(uint8_t i = 2; i < ThisNopLength; ++i) + OW->write8(0xCC); + } Count -= ThisNopLength; } while (Count != 0); @@ -405,6 +419,14 @@ public: , Is64Bit(is64Bit) { } + Optional<MCFixupKind> getFixupKind(StringRef Name) const override { + return StringSwitch<Optional<MCFixupKind>>(Name) + .Case("dir32", FK_Data_4) + .Case("secrel32", FK_SecRel_4) + .Case("secidx", FK_SecRel_2) + .Default(MCAsmBackend::getFixupKind(Name)); + } + MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override { return createX86WinCOFFObjectWriter(OS, Is64Bit); } @@ -508,8 +530,12 @@ protected: // .cfi_def_cfa_register %rbp // HasFP = true; - assert(MRI.getLLVMRegNum(Inst.getRegister(), true) == - (Is64Bit ? X86::RBP : X86::EBP) && "Invalid frame pointer!"); + + // If the frame pointer is other than esp/rsp, we do not have a way to + // generate a compact unwinding representation, so bail out. + if (MRI.getLLVMRegNum(Inst.getRegister(), true) != + (Is64Bit ? X86::RBP : X86::EBP)) + return 0; // Reset the counts. memset(SavedRegs, 0, sizeof(SavedRegs)); @@ -799,11 +825,12 @@ public: MCAsmBackend *llvm::createX86_32AsmBackend(const Target &T, const MCRegisterInfo &MRI, const Triple &TheTriple, - StringRef CPU) { + StringRef CPU, + const MCTargetOptions &Options) { if (TheTriple.isOSBinFormatMachO()) return new DarwinX86_32AsmBackend(T, MRI, CPU); - if (TheTriple.isOSWindows() && !TheTriple.isOSBinFormatELF()) + if (TheTriple.isOSWindows() && TheTriple.isOSBinFormatCOFF()) return new WindowsX86AsmBackend(T, false, CPU); uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); @@ -817,7 +844,8 @@ MCAsmBackend *llvm::createX86_32AsmBackend(const Target &T, MCAsmBackend *llvm::createX86_64AsmBackend(const Target &T, const MCRegisterInfo &MRI, const Triple &TheTriple, - StringRef CPU) { + StringRef CPU, + const MCTargetOptions &Options) { if (TheTriple.isOSBinFormatMachO()) { MachO::CPUSubTypeX86 CS = StringSwitch<MachO::CPUSubTypeX86>(TheTriple.getArchName()) @@ -826,7 +854,7 @@ MCAsmBackend *llvm::createX86_64AsmBackend(const Target &T, return new DarwinX86_64AsmBackend(T, MRI, CPU, CS); } - if (TheTriple.isOSWindows() && !TheTriple.isOSBinFormatELF()) + if (TheTriple.isOSWindows() && TheTriple.isOSBinFormatCOFF()) return new WindowsX86AsmBackend(T, true, CPU); uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); |