diff options
Diffstat (limited to 'contrib/llvm/lib/Target/AArch64/MCTargetDesc')
16 files changed, 265 insertions, 134 deletions
diff --git a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h index 3e5ef4df4706..62644ab2f457 100644 --- a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h +++ b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h @@ -213,7 +213,8 @@ static inline uint64_t ror(uint64_t elt, unsigned size) { static inline bool processLogicalImmediate(uint64_t Imm, unsigned RegSize, uint64_t &Encoding) { if (Imm == 0ULL || Imm == ~0ULL || - (RegSize != 64 && (Imm >> RegSize != 0 || Imm == ~0U))) + (RegSize != 64 && + (Imm >> RegSize != 0 || Imm == (~0ULL >> (64 - RegSize))))) return false; // First, determine the element size. @@ -753,6 +754,67 @@ static inline uint64_t decodeAdvSIMDModImmType12(uint8_t Imm) { return (EncVal << 32) | EncVal; } +/// Returns true if Imm is the concatenation of a repeating pattern of type T. +template <typename T> +static inline bool isSVEMaskOfIdenticalElements(int64_t Imm) { + union { + int64_t Whole; + T Parts[sizeof(int64_t)/sizeof(T)]; + } Vec { Imm }; + + return all_of(Vec.Parts, [Vec](T Elem) { return Elem == Vec.Parts[0]; }); +} + +/// Returns true if Imm is valid for CPY/DUP. +template <typename T> +static inline bool isSVECpyImm(int64_t Imm) { + bool IsImm8 = int8_t(Imm) == Imm; + bool IsImm16 = int16_t(Imm & ~0xff) == Imm; + + if (std::is_same<int8_t, typename std::make_signed<T>::type>::value) + return IsImm8 || uint8_t(Imm) == Imm; + + if (std::is_same<int16_t, typename std::make_signed<T>::type>::value) + return IsImm8 || IsImm16 || uint16_t(Imm & ~0xff) == Imm; + + return IsImm8 || IsImm16; +} + +/// Returns true if Imm is valid for ADD/SUB. +template <typename T> +static inline bool isSVEAddSubImm(int64_t Imm) { + bool IsInt8t = + std::is_same<int8_t, typename std::make_signed<T>::type>::value; + return uint8_t(Imm) == Imm || (!IsInt8t && uint16_t(Imm & ~0xff) == Imm); +} + +/// Return true if Imm is valid for DUPM and has no single CPY/DUP equivalent. +static inline bool isSVEMoveMaskPreferredLogicalImmediate(int64_t Imm) { + union { + int64_t D; + int32_t S[2]; + int16_t H[4]; + int8_t B[8]; + } Vec = { Imm }; + + if (isSVECpyImm<int64_t>(Vec.D)) + return false; + + if (isSVEMaskOfIdenticalElements<int32_t>(Imm) && + isSVECpyImm<int32_t>(Vec.S[0])) + return false; + + if (isSVEMaskOfIdenticalElements<int16_t>(Imm) && + isSVECpyImm<int16_t>(Vec.H[0])) + return false; + + if (isSVEMaskOfIdenticalElements<int8_t>(Imm) && + isSVECpyImm<int8_t>(Vec.B[0])) + return false; + + return isLogicalImmediate(Vec.D, 64); +} + inline static bool isAnyMOVZMovAlias(uint64_t Value, int RegWidth) { for (int Shift = 0; Shift <= RegWidth - 16; Shift += 16) if ((Value & ~(0xffffULL << Shift)) == 0) diff --git a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp index 4d1d3fd57353..856946555198 100644 --- a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp +++ b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp @@ -33,11 +33,9 @@ class AArch64AsmBackend : public MCAsmBackend { Triple TheTriple; public: - bool IsLittleEndian; - -public: AArch64AsmBackend(const Target &T, const Triple &TT, bool IsLittleEndian) - : MCAsmBackend(), TheTriple(TT), IsLittleEndian(IsLittleEndian) {} + : MCAsmBackend(IsLittleEndian ? support::little : support::big), + TheTriple(TT) {} unsigned getNumFixupKinds() const override { return AArch64::NumTargetFixupKinds; @@ -75,15 +73,17 @@ public: void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef<char> Data, - uint64_t Value, bool IsResolved) const override; + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override; - bool mayNeedRelaxation(const MCInst &Inst) const override; + bool mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const override; bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const override; void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, MCInst &Res) const override; - bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; + bool writeNopData(raw_ostream &OS, uint64_t Count) const override; void HandleAssemblerFlag(MCAssemblerFlag Flag) {} @@ -97,7 +97,7 @@ public: } // end anonymous namespace -/// \brief The number of bytes the fixup may change. +/// The number of bytes the fixup may change. static unsigned getFixupKindNumBytes(unsigned Kind) { switch (Kind) { default: @@ -248,7 +248,7 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, /// getFixupKindContainereSizeInBytes - The number of bytes of the /// container involved in big endian or 0 if the item is little endian unsigned AArch64AsmBackend::getFixupKindContainereSizeInBytes(unsigned Kind) const { - if (IsLittleEndian) + if (Endian == support::little) return 0; switch (Kind) { @@ -287,7 +287,8 @@ unsigned AArch64AsmBackend::getFixupKindContainereSizeInBytes(unsigned Kind) con void AArch64AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef<char> Data, uint64_t Value, - bool IsResolved) const { + bool IsResolved, + const MCSubtargetInfo *STI) const { unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); if (!Value) return; // Doesn't change encoding. @@ -323,7 +324,8 @@ void AArch64AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, } } -bool AArch64AsmBackend::mayNeedRelaxation(const MCInst &Inst) const { +bool AArch64AsmBackend::mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const { return false; } @@ -344,16 +346,16 @@ void AArch64AsmBackend::relaxInstruction(const MCInst &Inst, llvm_unreachable("AArch64AsmBackend::relaxInstruction() unimplemented"); } -bool AArch64AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { +bool AArch64AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { // If the count is not 4-byte aligned, we must be writing data into the text // section (otherwise we have unaligned instructions, and thus have far // bigger problems), so just write zeros instead. - OW->WriteZeros(Count % 4); + OS.write_zeros(Count % 4); // We are properly aligned, so write NOPs as requested. Count /= 4; for (uint64_t i = 0; i != Count; ++i) - OW->write32(0xd503201f); + support::endian::write<uint32_t>(OS, 0xd503201f, Endian); return true; } @@ -381,20 +383,20 @@ namespace { namespace CU { -/// \brief Compact unwind encoding values. +/// Compact unwind encoding values. enum CompactUnwindEncodings { - /// \brief A "frameless" leaf function, where no non-volatile registers are + /// A "frameless" leaf function, where no non-volatile registers are /// saved. The return remains in LR throughout the function. UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, - /// \brief No compact unwind encoding available. Instead the low 23-bits of + /// No compact unwind encoding available. Instead the low 23-bits of /// the compact unwind encoding is the offset of the DWARF FDE in the /// __eh_frame section. This mode is never used in object files. It is only /// generated by the linker in final linked images, which have only DWARF info /// for a function. UNWIND_ARM64_MODE_DWARF = 0x03000000, - /// \brief This is a standard arm64 prologue where FP/LR are immediately + /// This is a standard arm64 prologue where FP/LR are immediately /// pushed on the stack, then SP is copied to FP. If there are any /// non-volatile register saved, they are copied into the stack fame in pairs /// in a contiguous ranger right below the saved FP/LR pair. Any subset of the @@ -402,7 +404,7 @@ enum CompactUnwindEncodings { /// in register number order. UNWIND_ARM64_MODE_FRAME = 0x04000000, - /// \brief Frame register pair encodings. + /// Frame register pair encodings. UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001, UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002, UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004, @@ -420,7 +422,7 @@ enum CompactUnwindEncodings { class DarwinAArch64AsmBackend : public AArch64AsmBackend { const MCRegisterInfo &MRI; - /// \brief Encode compact unwind stack adjustment for frameless functions. + /// Encode compact unwind stack adjustment for frameless functions. /// See UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK in compact_unwind_encoding.h. /// The stack size always needs to be 16 byte aligned. uint32_t encodeStackAdjustment(uint32_t StackSize) const { @@ -432,13 +434,13 @@ public: const MCRegisterInfo &MRI) : AArch64AsmBackend(T, TT, /*IsLittleEndian*/ true), MRI(MRI) {} - std::unique_ptr<MCObjectWriter> - createObjectWriter(raw_pwrite_stream &OS) const override { - return createAArch64MachObjectWriter(OS, MachO::CPU_TYPE_ARM64, + std::unique_ptr<MCObjectTargetWriter> + createObjectTargetWriter() const override { + return createAArch64MachObjectWriter(MachO::CPU_TYPE_ARM64, MachO::CPU_SUBTYPE_ARM64_ALL); } - /// \brief Generate the compact unwind encoding from the CFI directives. + /// Generate the compact unwind encoding from the CFI directives. uint32_t generateCompactUnwindEncoding( ArrayRef<MCCFIInstruction> Instrs) const override { if (Instrs.empty()) @@ -457,9 +459,17 @@ public: return CU::UNWIND_ARM64_MODE_DWARF; case MCCFIInstruction::OpDefCfa: { // Defines a frame pointer. - assert(getXRegFromWReg(MRI.getLLVMRegNum(Inst.getRegister(), true)) == - AArch64::FP && - "Invalid frame pointer!"); + unsigned XReg = + getXRegFromWReg(MRI.getLLVMRegNum(Inst.getRegister(), true)); + + // Other CFA registers than FP are not supported by compact unwind. + // Fallback on DWARF. + // FIXME: When opt-remarks are supported in MC, add a remark to notify + // the user. + if (XReg != AArch64::FP) + return CU::UNWIND_ARM64_MODE_DWARF; + + assert(XReg == AArch64::FP && "Invalid frame pointer!"); assert(i + 2 < e && "Insufficient CFI instructions to define a frame!"); const MCCFIInstruction &LRPush = Instrs[++i]; @@ -583,9 +593,9 @@ public: : AArch64AsmBackend(T, TT, IsLittleEndian), OSABI(OSABI), IsILP32(IsILP32) {} - std::unique_ptr<MCObjectWriter> - createObjectWriter(raw_pwrite_stream &OS) const override { - return createAArch64ELFObjectWriter(OS, OSABI, IsLittleEndian, IsILP32); + std::unique_ptr<MCObjectTargetWriter> + createObjectTargetWriter() const override { + return createAArch64ELFObjectWriter(OSABI, IsILP32); } }; @@ -597,9 +607,9 @@ public: COFFAArch64AsmBackend(const Target &T, const Triple &TheTriple) : AArch64AsmBackend(T, TheTriple, /*IsLittleEndian*/ true) {} - std::unique_ptr<MCObjectWriter> - createObjectWriter(raw_pwrite_stream &OS) const override { - return createAArch64WinCOFFObjectWriter(OS); + std::unique_ptr<MCObjectTargetWriter> + createObjectTargetWriter() const override { + return createAArch64WinCOFFObjectWriter(); } }; } diff --git a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp index 2d90e67960f8..a11e396217af 100644 --- a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp +++ b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp @@ -31,7 +31,7 @@ namespace { class AArch64ELFObjectWriter : public MCELFObjectTargetWriter { public: - AArch64ELFObjectWriter(uint8_t OSABI, bool IsLittleEndian, bool IsILP32); + AArch64ELFObjectWriter(uint8_t OSABI, bool IsILP32); ~AArch64ELFObjectWriter() override = default; @@ -43,9 +43,7 @@ protected: } // end anonymous namespace -AArch64ELFObjectWriter::AArch64ELFObjectWriter(uint8_t OSABI, - bool IsLittleEndian, - bool IsILP32) +AArch64ELFObjectWriter::AArch64ELFObjectWriter(uint8_t OSABI, bool IsILP32) : MCELFObjectTargetWriter(/*Is64Bit*/ true, OSABI, ELF::EM_AARCH64, /*HasRelocationAddend*/ true), IsILP32(IsILP32) {} @@ -429,10 +427,7 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx, llvm_unreachable("Unimplemented fixup -> relocation"); } -std::unique_ptr<MCObjectWriter> -llvm::createAArch64ELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI, - bool IsLittleEndian, bool IsILP32) { - auto MOTW = - llvm::make_unique<AArch64ELFObjectWriter>(OSABI, IsLittleEndian, IsILP32); - return createELFObjectWriter(std::move(MOTW), OS, IsLittleEndian); +std::unique_ptr<MCObjectTargetWriter> +llvm::createAArch64ELFObjectWriter(uint8_t OSABI, bool IsILP32) { + return llvm::make_unique<AArch64ELFObjectWriter>(OSABI, IsILP32); } diff --git a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp index 8ee627d50df2..c0ef8b670286 100644 --- a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp +++ b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp @@ -27,6 +27,7 @@ #include "llvm/MC/MCELFStreamer.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -87,9 +88,10 @@ public: friend class AArch64TargetELFStreamer; AArch64ELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter) - : MCELFStreamer(Context, std::move(TAB), OS, std::move(Emitter)), + : MCELFStreamer(Context, std::move(TAB), std::move(OW), + std::move(Emitter)), MappingSymbolCounter(0), LastEMS(EMS_None) {} void ChangeSection(MCSection *Section, const MCExpr *Subsection) override { @@ -209,11 +211,11 @@ MCTargetStreamer *createAArch64AsmTargetStreamer(MCStreamer &S, MCELFStreamer *createAArch64ELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter, bool RelaxAll) { - AArch64ELFStreamer *S = - new AArch64ELFStreamer(Context, std::move(TAB), OS, std::move(Emitter)); + AArch64ELFStreamer *S = new AArch64ELFStreamer( + Context, std::move(TAB), std::move(OW), std::move(Emitter)); if (RelaxAll) S->getAssembler().setRelaxAll(true); return S; diff --git a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.h b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.h index 19b188aa1c61..d5b009ec30d1 100644 --- a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.h +++ b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.h @@ -20,7 +20,7 @@ namespace llvm { MCELFStreamer *createAArch64ELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter, bool RelaxAll); } diff --git a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp index 12b5a27b7699..ebb49121c1bf 100644 --- a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp +++ b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp @@ -101,7 +101,7 @@ AArch64MCAsmInfoELF::AArch64MCAsmInfoELF(const Triple &T) { HasIdentDirective = true; } -AArch64MCAsmInfoCOFF::AArch64MCAsmInfoCOFF() { +AArch64MCAsmInfoMicrosoftCOFF::AArch64MCAsmInfoMicrosoftCOFF() { PrivateGlobalPrefix = ".L"; PrivateLabelPrefix = ".L"; @@ -112,14 +112,23 @@ AArch64MCAsmInfoCOFF::AArch64MCAsmInfoCOFF() { AlignmentIsInBytes = false; SupportsDebugInformation = true; CodePointerSize = 8; -} -AArch64MCAsmInfoMicrosoftCOFF::AArch64MCAsmInfoMicrosoftCOFF() { CommentString = ";"; ExceptionsType = ExceptionHandling::WinEH; } AArch64MCAsmInfoGNUCOFF::AArch64MCAsmInfoGNUCOFF() { + PrivateGlobalPrefix = ".L"; + PrivateLabelPrefix = ".L"; + + Data16bitsDirective = "\t.hword\t"; + Data32bitsDirective = "\t.word\t"; + Data64bitsDirective = "\t.xword\t"; + + AlignmentIsInBytes = false; + SupportsDebugInformation = true; + CodePointerSize = 8; + CommentString = "//"; ExceptionsType = ExceptionHandling::DwarfCFI; } diff --git a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h index afde87b40929..e8570b1c2887 100644 --- a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h +++ b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h @@ -34,15 +34,11 @@ struct AArch64MCAsmInfoELF : public MCAsmInfoELF { explicit AArch64MCAsmInfoELF(const Triple &T); }; -struct AArch64MCAsmInfoCOFF : public MCAsmInfoCOFF { - explicit AArch64MCAsmInfoCOFF(); -}; - -struct AArch64MCAsmInfoMicrosoftCOFF : public AArch64MCAsmInfoCOFF { +struct AArch64MCAsmInfoMicrosoftCOFF : public MCAsmInfoMicrosoft { explicit AArch64MCAsmInfoMicrosoftCOFF(); }; -struct AArch64MCAsmInfoGNUCOFF : public AArch64MCAsmInfoCOFF { +struct AArch64MCAsmInfoGNUCOFF : public MCAsmInfoGNUCOFF { explicit AArch64MCAsmInfoGNUCOFF(); }; diff --git a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp index 33698d2b8c38..41cad48f7aea 100644 --- a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp +++ b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp @@ -163,6 +163,13 @@ public: SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + uint32_t getImm8OptLsl(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + uint32_t getSVEIncDecImm(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + unsigned fixMOVZ(const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const; @@ -276,7 +283,8 @@ AArch64MCCodeEmitter::getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx, if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) { AArch64MCExpr::VariantKind RefKind = A64E->getKind(); if (RefKind == AArch64MCExpr::VK_TPREL_HI12 || - RefKind == AArch64MCExpr::VK_DTPREL_HI12) + RefKind == AArch64MCExpr::VK_DTPREL_HI12 || + RefKind == AArch64MCExpr::VK_SECREL_HI12) ShiftVal = 12; } return ShiftVal == 0 ? 0 : (1 << ShiftVal); @@ -508,6 +516,34 @@ AArch64MCCodeEmitter::getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx, return MO.getImm() - 8; } +uint32_t +AArch64MCCodeEmitter::getImm8OptLsl(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + // Test shift + auto ShiftOpnd = MI.getOperand(OpIdx + 1).getImm(); + assert(AArch64_AM::getShiftType(ShiftOpnd) == AArch64_AM::LSL && + "Unexpected shift type for imm8_opt_lsl immediate."); + + unsigned ShiftVal = AArch64_AM::getShiftValue(ShiftOpnd); + assert((ShiftVal == 0 || ShiftVal == 8) && + "Unexpected shift value for imm8_opt_lsl immediate."); + + // Test immediate + auto Immediate = MI.getOperand(OpIdx).getImm(); + return (Immediate & 0xff) | (ShiftVal == 0 ? 0 : (1 << ShiftVal)); +} + +uint32_t +AArch64MCCodeEmitter::getSVEIncDecImm(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpIdx); + assert(MO.isImm() && "Expected an immediate value!"); + // Normalize 1-16 range to 0-15. + return MO.getImm() - 1; +} + /// getMoveVecShifterOpValue - Return the encoded value for the vector move /// shifter (MSL). uint32_t AArch64MCCodeEmitter::getMoveVecShifterOpValue( @@ -571,7 +607,7 @@ void AArch64MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, } uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI); - support::endian::Writer<support::little>(OS).write<uint32_t>(Binary); + support::endian::write<uint32_t>(OS, Binary, support::little); ++MCNumEmitted; // Keep track of the # of mi's emitted. } diff --git a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp index f606d272bcb0..cd937935ddbf 100644 --- a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp +++ b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp @@ -70,6 +70,8 @@ StringRef AArch64MCExpr::getVariantKindName() const { case VK_GOTTPREL_G0_NC: return ":gottprel_g0_nc:"; case VK_TLSDESC: return ""; case VK_TLSDESC_PAGE: return ":tlsdesc:"; + case VK_SECREL_LO12: return ":secrel_lo12:"; + case VK_SECREL_HI12: return ":secrel_hi12:"; default: llvm_unreachable("Invalid ELF symbol kind"); } diff --git a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h index 3dbf0f84a665..b6bf254d3835 100644 --- a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h +++ b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h @@ -35,6 +35,7 @@ public: VK_GOTTPREL = 0x005, VK_TPREL = 0x006, VK_TLSDESC = 0x007, + VK_SECREL = 0x008, VK_SymLocBits = 0x00f, // Variants specifying which part of the final address calculation is @@ -98,6 +99,8 @@ public: VK_TPREL_LO12_NC = VK_TPREL | VK_PAGEOFF | VK_NC, VK_TLSDESC_LO12 = VK_TLSDESC | VK_PAGEOFF, VK_TLSDESC_PAGE = VK_TLSDESC | VK_PAGE, + VK_SECREL_LO12 = VK_SECREL | VK_PAGEOFF, + VK_SECREL_HI12 = VK_SECREL | VK_HI12, VK_INVALID = 0xfff }; diff --git a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp index c3458d625b83..4ceda7e122f4 100644 --- a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp +++ b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp @@ -20,6 +20,7 @@ #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -103,36 +104,61 @@ static MCInstPrinter *createAArch64MCInstPrinter(const Triple &T, static MCStreamer *createELFStreamer(const Triple &T, MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> &&OW, std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll) { - return createAArch64ELFStreamer(Ctx, std::move(TAB), OS, std::move(Emitter), - RelaxAll); + return createAArch64ELFStreamer(Ctx, std::move(TAB), std::move(OW), + std::move(Emitter), RelaxAll); } static MCStreamer *createMachOStreamer(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> &&OW, std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll, bool DWARFMustBeAtTheEnd) { - return createMachOStreamer(Ctx, std::move(TAB), OS, std::move(Emitter), - RelaxAll, DWARFMustBeAtTheEnd, + return createMachOStreamer(Ctx, std::move(TAB), std::move(OW), + std::move(Emitter), RelaxAll, DWARFMustBeAtTheEnd, /*LabelSections*/ true); } static MCStreamer * createWinCOFFStreamer(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> &&OW, std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll, bool IncrementalLinkerCompatible) { - return createAArch64WinCOFFStreamer(Ctx, std::move(TAB), OS, + return createAArch64WinCOFFStreamer(Ctx, std::move(TAB), std::move(OW), std::move(Emitter), RelaxAll, IncrementalLinkerCompatible); } +namespace { + +class AArch64MCInstrAnalysis : public MCInstrAnalysis { +public: + AArch64MCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} + + bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + uint64_t &Target) const override { + // Search for a PC-relative argument. + // This will handle instructions like bcc (where the first argument is the + // condition code) and cbz (where it is a register). + const auto &Desc = Info->get(Inst.getOpcode()); + for (unsigned i = 0, e = Inst.getNumOperands(); i != e; i++) { + if (Desc.OpInfo[i].OperandType == MCOI::OPERAND_PCREL) { + int64_t Imm = Inst.getOperand(i).getImm() * 4; + Target = Addr + Imm; + return true; + } + } + return false; + } +}; + +} // end anonymous namespace + static MCInstrAnalysis *createAArch64InstrAnalysis(const MCInstrInfo *Info) { - return new MCInstrAnalysis(Info); + return new AArch64MCInstrAnalysis(Info); } // Force static initialization. diff --git a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h index a5720e0e8b87..63f50778ccdb 100644 --- a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h +++ b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h @@ -26,7 +26,7 @@ class MCContext; class MCInstrInfo; class MCInstPrinter; class MCRegisterInfo; -class MCObjectWriter; +class MCObjectTargetWriter; class MCStreamer; class MCSubtargetInfo; class MCTargetOptions; @@ -53,16 +53,13 @@ MCAsmBackend *createAArch64beAsmBackend(const Target &T, const MCRegisterInfo &MRI, const MCTargetOptions &Options); -std::unique_ptr<MCObjectWriter> -createAArch64ELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI, - bool IsLittleEndian, bool IsILP32); +std::unique_ptr<MCObjectTargetWriter> +createAArch64ELFObjectWriter(uint8_t OSABI, bool IsILP32); -std::unique_ptr<MCObjectWriter> -createAArch64MachObjectWriter(raw_pwrite_stream &OS, uint32_t CPUType, - uint32_t CPUSubtype); +std::unique_ptr<MCObjectTargetWriter> +createAArch64MachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype); -std::unique_ptr<MCObjectWriter> -createAArch64WinCOFFObjectWriter(raw_pwrite_stream &OS); +std::unique_ptr<MCObjectTargetWriter> createAArch64WinCOFFObjectWriter(); MCTargetStreamer *createAArch64AsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS, diff --git a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MachObjectWriter.cpp b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MachObjectWriter.cpp index 55151c2b8d21..1021cdeeb3be 100644 --- a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MachObjectWriter.cpp +++ b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MachObjectWriter.cpp @@ -306,39 +306,24 @@ void AArch64MachObjectWriter::recordRelocation( bool CanUseLocalRelocation = canUseLocalRelocation(Section, *Symbol, Log2Size); if (Symbol->isTemporary() && (Value || !CanUseLocalRelocation)) { + // Make sure that the symbol is actually in a section here. If it isn't, + // emit an error and exit. + if (!Symbol->isInSection()) { + Asm.getContext().reportError( + Fixup.getLoc(), + "unsupported relocation of local symbol '" + Symbol->getName() + + "'. Must have non-local symbol earlier in section."); + return; + } const MCSection &Sec = Symbol->getSection(); if (!Asm.getContext().getAsmInfo()->isSectionAtomizableBySymbols(Sec)) Symbol->setUsedInReloc(); } const MCSymbol *Base = Asm.getAtom(*Symbol); - - // If the symbol is a variable and we weren't able to get a Base for it - // (i.e., it's not in the symbol table associated with a section) resolve - // the relocation based its expansion instead. - if (Symbol->isVariable() && !Base) { - // If the evaluation is an absolute value, just use that directly - // to keep things easy. - int64_t Res; - if (Symbol->getVariableValue()->evaluateAsAbsolute( - Res, Layout, Writer->getSectionAddressMap())) { - FixedValue = Res; - return; - } - - // FIXME: Will the Target we already have ever have any data in it - // we need to preserve and merge with the new Target? How about - // the FixedValue? - if (!Symbol->getVariableValue()->evaluateAsRelocatable(Target, &Layout, - &Fixup)) { - Asm.getContext().reportError(Fixup.getLoc(), - "unable to resolve variable '" + - Symbol->getName() + "'"); - return; - } - return recordRelocation(Writer, Asm, Layout, Fragment, Fixup, Target, - FixedValue); - } + // If the symbol is a variable it can either be in a section and + // we have a base or it is absolute and should have been expanded. + assert(!Symbol->isVariable() || Base); // Relocations inside debug sections always use local relocations when // possible. This seems to be done because the debugger doesn't fully @@ -377,19 +362,8 @@ void AArch64MachObjectWriter::recordRelocation( Value -= Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset() + (1ULL << Log2Size); } else { - // Resolve constant variables. - if (Symbol->isVariable()) { - int64_t Res; - if (Symbol->getVariableValue()->evaluateAsAbsolute( - Res, Layout, Writer->getSectionAddressMap())) { - FixedValue = Res; - return; - } - } - Asm.getContext().reportError(Fixup.getLoc(), - "unsupported relocation of variable '" + - Symbol->getName() + "'"); - return; + llvm_unreachable( + "This constant variable should have been expanded during evaluation"); } } @@ -430,10 +404,7 @@ void AArch64MachObjectWriter::recordRelocation( Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE); } -std::unique_ptr<MCObjectWriter> -llvm::createAArch64MachObjectWriter(raw_pwrite_stream &OS, uint32_t CPUType, - uint32_t CPUSubtype) { - return createMachObjectWriter( - llvm::make_unique<AArch64MachObjectWriter>(CPUType, CPUSubtype), OS, - /*IsLittleEndian=*/true); +std::unique_ptr<MCObjectTargetWriter> +llvm::createAArch64MachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype) { + return llvm::make_unique<AArch64MachObjectWriter>(CPUType, CPUSubtype); } diff --git a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFObjectWriter.cpp b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFObjectWriter.cpp index d06c5e8862ae..7ea7d5f2a20e 100644 --- a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFObjectWriter.cpp +++ b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFObjectWriter.cpp @@ -8,6 +8,7 @@ //===---------------------------------------------------------------------===// #include "MCTargetDesc/AArch64FixupKinds.h" +#include "MCTargetDesc/AArch64MCExpr.h" #include "llvm/ADT/Twine.h" #include "llvm/BinaryFormat/COFF.h" #include "llvm/MC/MCAsmBackend.h" @@ -46,6 +47,7 @@ unsigned AArch64WinCOFFObjectWriter::getRelocType( bool IsCrossSection, const MCAsmBackend &MAB) const { auto Modifier = Target.isAbsolute() ? MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); + const MCExpr *Expr = Fixup.getValue(); switch (static_cast<unsigned>(Fixup.getKind())) { default: { @@ -73,6 +75,13 @@ unsigned AArch64WinCOFFObjectWriter::getRelocType( return COFF::IMAGE_REL_ARM64_SECREL; case AArch64::fixup_aarch64_add_imm12: + if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) { + AArch64MCExpr::VariantKind RefKind = A64E->getKind(); + if (RefKind == AArch64MCExpr::VK_SECREL_LO12) + return COFF::IMAGE_REL_ARM64_SECREL_LOW12A; + if (RefKind == AArch64MCExpr::VK_SECREL_HI12) + return COFF::IMAGE_REL_ARM64_SECREL_HIGH12A; + } return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12A; case AArch64::fixup_aarch64_ldst_imm12_scale1: @@ -80,11 +89,25 @@ unsigned AArch64WinCOFFObjectWriter::getRelocType( case AArch64::fixup_aarch64_ldst_imm12_scale4: case AArch64::fixup_aarch64_ldst_imm12_scale8: case AArch64::fixup_aarch64_ldst_imm12_scale16: + if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) { + AArch64MCExpr::VariantKind RefKind = A64E->getKind(); + if (RefKind == AArch64MCExpr::VK_SECREL_LO12) + return COFF::IMAGE_REL_ARM64_SECREL_LOW12L; + } return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12L; + case AArch64::fixup_aarch64_pcrel_adr_imm21: + return COFF::IMAGE_REL_ARM64_REL21; + case AArch64::fixup_aarch64_pcrel_adrp_imm21: return COFF::IMAGE_REL_ARM64_PAGEBASE_REL21; + case AArch64::fixup_aarch64_pcrel_branch14: + return COFF::IMAGE_REL_ARM64_BRANCH14; + + case AArch64::fixup_aarch64_pcrel_branch19: + return COFF::IMAGE_REL_ARM64_BRANCH19; + case AArch64::fixup_aarch64_pcrel_branch26: case AArch64::fixup_aarch64_pcrel_call26: return COFF::IMAGE_REL_ARM64_BRANCH26; @@ -97,10 +120,8 @@ bool AArch64WinCOFFObjectWriter::recordRelocation(const MCFixup &Fixup) const { namespace llvm { -std::unique_ptr<MCObjectWriter> -createAArch64WinCOFFObjectWriter(raw_pwrite_stream &OS) { - auto MOTW = llvm::make_unique<AArch64WinCOFFObjectWriter>(); - return createWinCOFFObjectWriter(std::move(MOTW), OS); +std::unique_ptr<MCObjectTargetWriter> createAArch64WinCOFFObjectWriter() { + return llvm::make_unique<AArch64WinCOFFObjectWriter>(); } } // end namespace llvm diff --git a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp index c88363d2c250..9871dc553bed 100644 --- a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp +++ b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp @@ -10,6 +10,7 @@ #include "AArch64WinCOFFStreamer.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCObjectWriter.h" using namespace llvm; @@ -21,8 +22,8 @@ public: AArch64WinCOFFStreamer(MCContext &C, std::unique_ptr<MCAsmBackend> AB, std::unique_ptr<MCCodeEmitter> CE, - raw_pwrite_stream &OS) - : MCWinCOFFStreamer(C, std::move(AB), std::move(CE), OS) {} + std::unique_ptr<MCObjectWriter> OW) + : MCWinCOFFStreamer(C, std::move(AB), std::move(CE), std::move(OW)) {} void FinishImpl() override; }; @@ -37,10 +38,10 @@ void AArch64WinCOFFStreamer::FinishImpl() { namespace llvm { MCWinCOFFStreamer *createAArch64WinCOFFStreamer( MCContext &Context, std::unique_ptr<MCAsmBackend> MAB, - raw_pwrite_stream &OS, std::unique_ptr<MCCodeEmitter> Emitter, + std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter, bool RelaxAll, bool IncrementalLinkerCompatible) { auto *S = new AArch64WinCOFFStreamer(Context, std::move(MAB), - std::move(Emitter), OS); + std::move(Emitter), std::move(OW)); S->getAssembler().setIncrementalLinkerCompatible(IncrementalLinkerCompatible); return S; } diff --git a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.h b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.h index b67a19e883e9..c05422163584 100644 --- a/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.h +++ b/contrib/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.h @@ -35,7 +35,7 @@ namespace llvm { MCWinCOFFStreamer *createAArch64WinCOFFStreamer( MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, - raw_pwrite_stream &OS, std::unique_ptr<MCCodeEmitter> Emitter, + std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter, bool RelaxAll, bool IncrementalLinkerCompatible); } // end llvm namespace |