diff options
Diffstat (limited to 'lib/Target/ARM/MCTargetDesc')
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h | 11 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 122 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h | 20 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp | 281 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h | 11 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp | 6 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h | 10 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp | 70 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMMCExpr.cpp | 5 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMMCExpr.h | 2 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp | 6 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h | 4 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp | 26 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/CMakeLists.txt | 2 |
14 files changed, 493 insertions, 83 deletions
diff --git a/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h b/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h index 9982fa6..62473b2 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h +++ b/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h @@ -1,4 +1,4 @@ -//===- ARMAddressingModes.h - ARM Addressing Modes --------------*- C++ -*-===// +//===-- ARMAddressingModes.h - ARM Addressing Modes -------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,6 +16,7 @@ #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include <cassert> @@ -43,7 +44,7 @@ namespace ARM_AM { static inline const char *getShiftOpcStr(ShiftOpc Op) { switch (Op) { - default: assert(0 && "Unknown shift opc!"); + default: llvm_unreachable("Unknown shift opc!"); case ARM_AM::asr: return "asr"; case ARM_AM::lsl: return "lsl"; case ARM_AM::lsr: return "lsr"; @@ -54,7 +55,7 @@ namespace ARM_AM { static inline unsigned getShiftOpcEncoding(ShiftOpc Op) { switch (Op) { - default: assert(0 && "Unknown shift opc!"); + default: llvm_unreachable("Unknown shift opc!"); case ARM_AM::asr: return 2; case ARM_AM::lsl: return 0; case ARM_AM::lsr: return 1; @@ -72,7 +73,7 @@ namespace ARM_AM { static inline const char *getAMSubModeStr(AMSubMode Mode) { switch (Mode) { - default: assert(0 && "Unknown addressing sub-mode!"); + default: llvm_unreachable("Unknown addressing sub-mode!"); case ARM_AM::ia: return "ia"; case ARM_AM::ib: return "ib"; case ARM_AM::da: return "da"; @@ -569,7 +570,7 @@ namespace ARM_AM { } EltBits = 64; } else { - assert(false && "Unsupported NEON immediate"); + llvm_unreachable("Unsupported NEON immediate"); } return Val; } diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index bf1f0e8..d3a3d3a 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -22,6 +22,7 @@ #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCValue.h" #include "llvm/Object/MachOFormat.h" #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" @@ -31,8 +32,8 @@ using namespace llvm; namespace { class ARMELFObjectWriter : public MCELFObjectTargetWriter { public: - ARMELFObjectWriter(Triple::OSType OSType) - : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSType, ELF::EM_ARM, + ARMELFObjectWriter(uint8_t OSABI) + : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI, ELF::EM_ARM, /*HasRelocationAddend*/ false) {} }; @@ -63,6 +64,7 @@ public: { "fixup_arm_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_t2_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, +{ "fixup_arm_pcrel_10_unscaled", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, @@ -76,6 +78,8 @@ public: { "fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_arm_bl", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_arm_blx", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_thumb_blx", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, @@ -100,18 +104,46 @@ public: return Infos[Kind - FirstTargetFixupKind]; } - bool MayNeedRelaxation(const MCInst &Inst) const; + /// processFixupValue - Target hook to process the literal value of a fixup + /// if necessary. + void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFixup &Fixup, const MCFragment *DF, + MCValue &Target, uint64_t &Value, + bool &IsResolved) { + const MCSymbolRefExpr *A = Target.getSymA(); + // Some fixups to thumb function symbols need the low bit (thumb bit) + // twiddled. + if ((unsigned)Fixup.getKind() != ARM::fixup_arm_ldst_pcrel_12 && + (unsigned)Fixup.getKind() != ARM::fixup_t2_ldst_pcrel_12 && + (unsigned)Fixup.getKind() != ARM::fixup_arm_thumb_cp) { + if (A) { + const MCSymbol &Sym = A->getSymbol().AliasedSymbol(); + if (Asm.isThumbFunc(&Sym)) + Value |= 1; + } + } + // We must always generate a relocation for BL/BLX instructions if we have + // a symbol to reference, as the linker relies on knowing the destination + // symbol's thumb-ness to get interworking right. + if (A && ((unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_blx || + (unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_bl || + (unsigned)Fixup.getKind() == ARM::fixup_arm_blx || + (unsigned)Fixup.getKind() == ARM::fixup_arm_bl)) + IsResolved = false; + } + + bool mayNeedRelaxation(const MCInst &Inst) const; bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCInstFragment *DF, const MCAsmLayout &Layout) const; - void RelaxInstruction(const MCInst &Inst, MCInst &Res) const; + void relaxInstruction(const MCInst &Inst, MCInst &Res) const; - bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const; + bool writeNopData(uint64_t Count, MCObjectWriter *OW) const; - void HandleAssemblerFlag(MCAssemblerFlag Flag) { + void handleAssemblerFlag(MCAssemblerFlag Flag) { switch (Flag) { default: break; case MCAF_Code16: @@ -132,11 +164,13 @@ public: static unsigned getRelaxedOpcode(unsigned Op) { switch (Op) { default: return Op; - case ARM::tBcc: return ARM::t2Bcc; + case ARM::tBcc: return ARM::t2Bcc; + case ARM::tLDRpciASM: return ARM::t2LDRpci; + case ARM::tADR: return ARM::t2ADR; } } -bool ARMAsmBackend::MayNeedRelaxation(const MCInst &Inst) const { +bool ARMAsmBackend::mayNeedRelaxation(const MCInst &Inst) const { if (getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode()) return true; return false; @@ -146,17 +180,29 @@ bool ARMAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCInstFragment *DF, const MCAsmLayout &Layout) const { - // Relaxing tBcc to t2Bcc. tBcc has a signed 9-bit displacement with the - // low bit being an implied zero. There's an implied +4 offset for the - // branch, so we adjust the other way here to determine what's - // encodable. - // - // Relax if the value is too big for a (signed) i8. - int64_t Offset = int64_t(Value) - 4; - return Offset > 254 || Offset < -256; + switch ((unsigned)Fixup.getKind()) { + case ARM::fixup_arm_thumb_bcc: { + // Relaxing tBcc to t2Bcc. tBcc has a signed 9-bit displacement with the + // low bit being an implied zero. There's an implied +4 offset for the + // branch, so we adjust the other way here to determine what's + // encodable. + // + // Relax if the value is too big for a (signed) i8. + int64_t Offset = int64_t(Value) - 4; + return Offset > 254 || Offset < -256; + } + case ARM::fixup_thumb_adr_pcrel_10: + case ARM::fixup_arm_thumb_cp: { + // If the immediate is negative, greater than 1020, or not a multiple + // of four, the wide version of the instruction must be used. + int64_t Offset = int64_t(Value) - 4; + return Offset > 1020 || Offset < 0 || Offset & 3; + } + } + llvm_unreachable("Unexpected fixup kind in fixupNeedsRelaxation()!"); } -void ARMAsmBackend::RelaxInstruction(const MCInst &Inst, MCInst &Res) const { +void ARMAsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const { unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode()); // Sanity check w/ diagnostic if we get here w/ a bogus instruction. @@ -174,7 +220,7 @@ void ARMAsmBackend::RelaxInstruction(const MCInst &Inst, MCInst &Res) const { Res.setOpcode(RelaxedOp); } -bool ARMAsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const { +bool ARMAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { const uint16_t Thumb1_16bitNopEncoding = 0x46c0; // using MOV r8,r8 const uint16_t Thumb2_16bitNopEncoding = 0xbf00; // NOP const uint32_t ARMv4_NopEncoding = 0xe1a0000; // using MOV r0,r0 @@ -309,6 +355,8 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { case ARM::fixup_arm_condbranch: case ARM::fixup_arm_uncondbranch: + case ARM::fixup_arm_bl: + case ARM::fixup_arm_blx: // These values don't encode the low two bits since they're always zero. // Offset by 8 just as above. return 0xffffff & ((Value - 8) >> 2); @@ -399,6 +447,17 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { case ARM::fixup_arm_thumb_bcc: // Offset by 4 and don't encode the lower bit, which is always 0. return ((Value - 4) >> 1) & 0xff; + case ARM::fixup_arm_pcrel_10_unscaled: { + Value = Value - 8; // ARM fixups offset by an additional word and don't + // need to adjust for the half-word ordering. + bool isAdd = true; + if ((int64_t)Value < 0) { + Value = -Value; + isAdd = false; + } + assert ((Value < 256) && "Out of range pc-relative fixup value!"); + return Value | (isAdd << 23); + } case ARM::fixup_arm_pcrel_10: Value = Value - 4; // ARM fixups offset by an additional word and don't // need to adjust for the half-word ordering. @@ -416,8 +475,8 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { assert ((Value < 256) && "Out of range pc-relative fixup value!"); Value |= isAdd << 23; - // Same addressing mode as fixup_arm_pcrel_10, - // but with 16-bit halfwords swapped. + // Same addressing mode as fixup_arm_pcrel_10, but with 16-bit halfwords + // swapped. if (Kind == ARM::fixup_t2_pcrel_10) { uint32_t swapped = (Value & 0xFFFF0000) >> 16; swapped |= (Value & 0x0000FFFF) << 16; @@ -435,22 +494,21 @@ namespace { // ELF is an ELF of course... class ELFARMAsmBackend : public ARMAsmBackend { public: - Triple::OSType OSType; + uint8_t OSABI; ELFARMAsmBackend(const Target &T, const StringRef TT, - Triple::OSType _OSType) - : ARMAsmBackend(T, TT), OSType(_OSType) { } + uint8_t _OSABI) + : ARMAsmBackend(T, TT), OSABI(_OSABI) { } - void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, + void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const; MCObjectWriter *createObjectWriter(raw_ostream &OS) const { - return createELFObjectWriter(new ARMELFObjectWriter(OSType), OS, - /*IsLittleEndian*/ true); + return createARMELFObjectWriter(OS, OSABI); } }; // FIXME: Raise this to share code between Darwin and ELF. -void ELFARMAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data, +void ELFARMAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const { unsigned NumBytes = 4; // FIXME: 2 for Thumb Value = adjustFixupValue(Fixup.getKind(), Value); @@ -479,7 +537,7 @@ public: Subtype); } - void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, + void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const; virtual bool doesSectionRequireSymbols(const MCSection &Section) const { @@ -504,9 +562,12 @@ static unsigned getFixupKindNumBytes(unsigned Kind) { case ARM::fixup_arm_thumb_cb: return 2; + case ARM::fixup_arm_pcrel_10_unscaled: case ARM::fixup_arm_ldst_pcrel_12: case ARM::fixup_arm_pcrel_10: case ARM::fixup_arm_adr_pcrel_12: + case ARM::fixup_arm_bl: + case ARM::fixup_arm_blx: case ARM::fixup_arm_condbranch: case ARM::fixup_arm_uncondbranch: return 3; @@ -531,7 +592,7 @@ static unsigned getFixupKindNumBytes(unsigned Kind) { } } -void DarwinARMAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data, +void DarwinARMAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const { unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); Value = adjustFixupValue(Fixup.getKind(), Value); @@ -567,5 +628,6 @@ MCAsmBackend *llvm::createARMAsmBackend(const Target &T, StringRef TT) { if (TheTriple.isOSWindows()) assert(0 && "Windows not supported on ARM"); - return new ELFARMAsmBackend(T, TT, Triple(TT).getOS()); + uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS()); + return new ELFARMAsmBackend(T, TT, OSABI); } diff --git a/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h b/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h index ec4b6ff..06eb4e5 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h +++ b/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h @@ -67,7 +67,6 @@ namespace ARMCC { inline static const char *ARMCondCodeToString(ARMCC::CondCodes CC) { switch (CC) { - default: llvm_unreachable("Unknown condition code"); case ARMCC::EQ: return "eq"; case ARMCC::NE: return "ne"; case ARMCC::HS: return "hs"; @@ -84,6 +83,7 @@ inline static const char *ARMCondCodeToString(ARMCC::CondCodes CC) { case ARMCC::LE: return "le"; case ARMCC::AL: return "al"; } + llvm_unreachable("Unknown condition code"); } namespace ARM_PROC { @@ -185,6 +185,23 @@ inline static unsigned getARMRegisterNumbering(unsigned Reg) { case S29: case D29: return 29; case S30: case D30: return 30; case S31: case D31: return 31; + + // Composite registers use the regnum of the first register in the list. + case D1_D2: return 1; + case D3_D5: return 3; + case D5_D7: return 5; + case D7_D9: return 7; + case D9_D10: return 9; + case D11_D12: return 11; + case D13_D14: return 13; + case D15_D16: return 15; + case D17_D18: return 17; + case D19_D20: return 19; + case D21_D22: return 21; + case D23_D24: return 23; + case D25_D26: return 25; + case D27_D28: return 27; + case D29_D30: return 29; } } @@ -237,7 +254,6 @@ namespace ARMII { inline static const char *AddrModeToString(AddrMode addrmode) { switch (addrmode) { - default: llvm_unreachable("Unknown memory operation"); case AddrModeNone: return "AddrModeNone"; case AddrMode1: return "AddrMode1"; case AddrMode2: return "AddrMode2"; diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp new file mode 100644 index 0000000..5476a46 --- /dev/null +++ b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp @@ -0,0 +1,281 @@ +//===-- ARMELFObjectWriter.cpp - ARM ELF Writer ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/ARMFixupKinds.h" +#include "MCTargetDesc/ARMMCTargetDesc.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCValue.h" + +using namespace llvm; + +namespace { + class ARMELFObjectWriter : public MCELFObjectTargetWriter { + enum { DefaultEABIVersion = 0x05000000U }; + unsigned GetRelocTypeInner(const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel) const; + + + public: + ARMELFObjectWriter(uint8_t OSABI); + + virtual ~ARMELFObjectWriter(); + + virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsPCRel, bool IsRelocWithSymbol, + int64_t Addend) const; + virtual unsigned getEFlags() const; + virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F, + const MCFixup &Fixup, + bool IsPCRel) const; + }; +} + +ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI) + : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI, + ELF::EM_ARM, + /*HasRelocationAddend*/ false) {} + +ARMELFObjectWriter::~ARMELFObjectWriter() {} + +// FIXME: get the real EABI Version from the Triple. +unsigned ARMELFObjectWriter::getEFlags() const { + return ELF::EF_ARM_EABIMASK & DefaultEABIVersion; +} + +// In ARM, _MergedGlobals and other most symbols get emitted directly. +// I.e. not as an offset to a section symbol. +// This code is an approximation of what ARM/gcc does. + +STATISTIC(PCRelCount, "Total number of PIC Relocations"); +STATISTIC(NonPCRelCount, "Total number of non-PIC relocations"); + +const MCSymbol *ARMELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F, + const MCFixup &Fixup, + bool IsPCRel) const { + const MCSymbol &Symbol = Target.getSymA()->getSymbol().AliasedSymbol(); + bool EmitThisSym = false; + + const MCSectionELF &Section = + static_cast<const MCSectionELF&>(Symbol.getSection()); + bool InNormalSection = true; + unsigned RelocType = 0; + RelocType = GetRelocTypeInner(Target, Fixup, IsPCRel); + + DEBUG( + const MCSymbolRefExpr::VariantKind Kind = Target.getSymA()->getKind(); + MCSymbolRefExpr::VariantKind Kind2; + Kind2 = Target.getSymB() ? Target.getSymB()->getKind() : + MCSymbolRefExpr::VK_None; + dbgs() << "considering symbol " + << Section.getSectionName() << "/" + << Symbol.getName() << "/" + << " Rel:" << (unsigned)RelocType + << " Kind: " << (int)Kind << "/" << (int)Kind2 + << " Tmp:" + << Symbol.isAbsolute() << "/" << Symbol.isDefined() << "/" + << Symbol.isVariable() << "/" << Symbol.isTemporary() + << " Counts:" << PCRelCount << "/" << NonPCRelCount << "\n"); + + if (IsPCRel) { ++PCRelCount; + switch (RelocType) { + default: + // Most relocation types are emitted as explicit symbols + InNormalSection = + StringSwitch<bool>(Section.getSectionName()) + .Case(".data.rel.ro.local", false) + .Case(".data.rel", false) + .Case(".bss", false) + .Default(true); + EmitThisSym = true; + break; + case ELF::R_ARM_ABS32: + // But things get strange with R_ARM_ABS32 + // In this case, most things that go in .rodata show up + // as section relative relocations + InNormalSection = + StringSwitch<bool>(Section.getSectionName()) + .Case(".data.rel.ro.local", false) + .Case(".data.rel", false) + .Case(".rodata", false) + .Case(".bss", false) + .Default(true); + EmitThisSym = false; + break; + } + } else { + NonPCRelCount++; + InNormalSection = + StringSwitch<bool>(Section.getSectionName()) + .Case(".data.rel.ro.local", false) + .Case(".rodata", false) + .Case(".data.rel", false) + .Case(".bss", false) + .Default(true); + + switch (RelocType) { + default: EmitThisSym = true; break; + case ELF::R_ARM_ABS32: EmitThisSym = false; break; + } + } + + if (EmitThisSym) + return &Symbol; + if (! Symbol.isTemporary() && InNormalSection) { + return &Symbol; + } + return NULL; +} + +// Need to examine the Fixup when determining whether to +// emit the relocation as an explicit symbol or as a section relative +// offset +unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel, + bool IsRelocWithSymbol, + int64_t Addend) const { + return GetRelocTypeInner(Target, Fixup, IsPCRel); +} + +unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel) const { + MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ? + MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); + + unsigned Type = 0; + if (IsPCRel) { + switch ((unsigned)Fixup.getKind()) { + default: llvm_unreachable("Unimplemented"); + case FK_Data_4: + switch (Modifier) { + default: llvm_unreachable("Unsupported Modifier"); + case MCSymbolRefExpr::VK_None: + Type = ELF::R_ARM_REL32; + break; + case MCSymbolRefExpr::VK_ARM_TLSGD: + llvm_unreachable("unimplemented"); + case MCSymbolRefExpr::VK_ARM_GOTTPOFF: + Type = ELF::R_ARM_TLS_IE32; + break; + } + break; + case ARM::fixup_arm_bl: + case ARM::fixup_arm_blx: + case ARM::fixup_arm_uncondbranch: + switch (Modifier) { + case MCSymbolRefExpr::VK_ARM_PLT: + Type = ELF::R_ARM_PLT32; + break; + default: + Type = ELF::R_ARM_CALL; + break; + } + break; + case ARM::fixup_arm_condbranch: + Type = ELF::R_ARM_JUMP24; + break; + case ARM::fixup_arm_movt_hi16: + case ARM::fixup_arm_movt_hi16_pcrel: + Type = ELF::R_ARM_MOVT_PREL; + break; + case ARM::fixup_arm_movw_lo16: + case ARM::fixup_arm_movw_lo16_pcrel: + Type = ELF::R_ARM_MOVW_PREL_NC; + break; + case ARM::fixup_t2_movt_hi16: + case ARM::fixup_t2_movt_hi16_pcrel: + Type = ELF::R_ARM_THM_MOVT_PREL; + break; + case ARM::fixup_t2_movw_lo16: + case ARM::fixup_t2_movw_lo16_pcrel: + Type = ELF::R_ARM_THM_MOVW_PREL_NC; + break; + case ARM::fixup_arm_thumb_bl: + case ARM::fixup_arm_thumb_blx: + Type = ELF::R_ARM_THM_CALL; + break; + } + } else { + switch ((unsigned)Fixup.getKind()) { + default: llvm_unreachable("invalid fixup kind!"); + case FK_Data_4: + switch (Modifier) { + default: llvm_unreachable("Unsupported Modifier"); + case MCSymbolRefExpr::VK_ARM_GOT: + Type = ELF::R_ARM_GOT_BREL; + break; + case MCSymbolRefExpr::VK_ARM_TLSGD: + Type = ELF::R_ARM_TLS_GD32; + break; + case MCSymbolRefExpr::VK_ARM_TPOFF: + Type = ELF::R_ARM_TLS_LE32; + break; + case MCSymbolRefExpr::VK_ARM_GOTTPOFF: + Type = ELF::R_ARM_TLS_IE32; + break; + case MCSymbolRefExpr::VK_None: + Type = ELF::R_ARM_ABS32; + break; + case MCSymbolRefExpr::VK_ARM_GOTOFF: + Type = ELF::R_ARM_GOTOFF32; + break; + case MCSymbolRefExpr::VK_ARM_TARGET1: + Type = ELF::R_ARM_TARGET1; + break; + } + break; + case ARM::fixup_arm_ldst_pcrel_12: + case ARM::fixup_arm_pcrel_10: + case ARM::fixup_arm_adr_pcrel_12: + case ARM::fixup_arm_thumb_bl: + case ARM::fixup_arm_thumb_cb: + case ARM::fixup_arm_thumb_cp: + case ARM::fixup_arm_thumb_br: + llvm_unreachable("Unimplemented"); + case ARM::fixup_arm_uncondbranch: + Type = ELF::R_ARM_CALL; + break; + case ARM::fixup_arm_condbranch: + Type = ELF::R_ARM_JUMP24; + break; + case ARM::fixup_arm_movt_hi16: + Type = ELF::R_ARM_MOVT_ABS; + break; + case ARM::fixup_arm_movw_lo16: + Type = ELF::R_ARM_MOVW_ABS_NC; + break; + case ARM::fixup_t2_movt_hi16: + Type = ELF::R_ARM_THM_MOVT_ABS; + break; + case ARM::fixup_t2_movw_lo16: + Type = ELF::R_ARM_THM_MOVW_ABS_NC; + break; + } + } + + return Type; +} + +MCObjectWriter *llvm::createARMELFObjectWriter(raw_ostream &OS, + uint8_t OSABI) { + MCELFObjectTargetWriter *MOTW = new ARMELFObjectWriter(OSABI); + return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/true); +} diff --git a/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h b/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h index 350c92d..1827986 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h +++ b/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h @@ -1,4 +1,4 @@ -//===-- ARM/ARMFixupKinds.h - ARM Specific Fixup Entries --------*- C++ -*-===// +//===-- ARMFixupKinds.h - ARM Specific Fixup Entries ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -23,6 +23,9 @@ enum Fixups { // the 16-bit halfwords reordered. fixup_t2_ldst_pcrel_12, + // fixup_arm_pcrel_10_unscaled - 10-bit PC relative relocation for symbol + // addresses used in LDRD/LDRH/LDRB/etc. instructions. All bits are encoded. + fixup_arm_pcrel_10_unscaled, // fixup_arm_pcrel_10 - 10-bit PC relative relocation for symbol addresses // used in VFP instructions where the lower 2 bits are not encoded // (so it's encoded as an 8-bit immediate). @@ -56,6 +59,12 @@ enum Fixups { // fixup_arm_thumb_br - 12-bit fixup for Thumb B instructions. fixup_arm_thumb_br, + // fixup_arm_bl - Fixup for ARM BL instructions. + fixup_arm_bl, + + // fixup_arm_blx - Fixup for ARM BLX instructions. + fixup_arm_blx, + // fixup_arm_thumb_bl - Fixup for Thumb BL instructions. fixup_arm_thumb_bl, diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp index 1c109e0..03e8d5f 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp @@ -1,4 +1,4 @@ -//===-- ARMMCAsmInfo.cpp - ARM asm properties -------------------*- C++ -*-===// +//===-- ARMMCAsmInfo.cpp - ARM asm properties -----------------------------===// // // The LLVM Compiler Infrastructure // @@ -48,6 +48,8 @@ static const char *const arm_asm_table[] = { 0,0 }; +void ARMMCAsmInfoDarwin::anchor() { } + ARMMCAsmInfoDarwin::ARMMCAsmInfoDarwin() { AsmTransCBE = arm_asm_table; Data64bitsDirective = 0; @@ -61,6 +63,8 @@ ARMMCAsmInfoDarwin::ARMMCAsmInfoDarwin() { ExceptionsType = ExceptionHandling::SjLj; } +void ARMELFMCAsmInfo::anchor() { } + ARMELFMCAsmInfo::ARMELFMCAsmInfo() { // ".comm align is in bytes but .align is pow-2." AlignmentIsInBytes = false; diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h index 90f7822..f0b289c 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h +++ b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h @@ -1,4 +1,4 @@ -//=====-- ARMMCAsmInfo.h - ARM asm properties -------------*- C++ -*--====// +//===-- ARMMCAsmInfo.h - ARM asm properties --------------------*- C++ -*--===// // // The LLVM Compiler Infrastructure // @@ -18,11 +18,15 @@ namespace llvm { - struct ARMMCAsmInfoDarwin : public MCAsmInfoDarwin { + class ARMMCAsmInfoDarwin : public MCAsmInfoDarwin { + virtual void anchor(); + public: explicit ARMMCAsmInfoDarwin(); }; - struct ARMELFMCAsmInfo : public MCAsmInfo { + class ARMELFMCAsmInfo : public MCAsmInfo { + virtual void anchor(); + public: explicit ARMELFMCAsmInfo(); }; diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp index c38a882..4445dcd 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp @@ -64,7 +64,7 @@ public: // getBinaryCodeForInstr - TableGen'erated function for getting the // binary encoding for an instruction. - unsigned getBinaryCodeForInstr(const MCInst &MI, + uint64_t getBinaryCodeForInstr(const MCInst &MI, SmallVectorImpl<MCFixup> &Fixups) const; /// getMachineOpValue - Return binary encoding of operand. If the machine @@ -118,8 +118,10 @@ public: /// branch target. uint32_t getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups) const; + uint32_t getARMBLTargetOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl<MCFixup> &Fixups) const; uint32_t getARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups) const; /// getAdrLabelOpValue - Return encoding info for 12-bit immediate /// ADR label target. @@ -166,7 +168,7 @@ public: SmallVectorImpl<MCFixup> &Fixups) const { ARM_AM::AMSubMode Mode = (ARM_AM::AMSubMode)MI.getOperand(OpIdx).getImm(); switch (Mode) { - default: assert(0 && "Unknown addressing sub-mode!"); + default: llvm_unreachable("Unknown addressing sub-mode!"); case ARM_AM::da: return 0; case ARM_AM::ia: return 1; case ARM_AM::db: return 2; @@ -177,7 +179,6 @@ public: /// unsigned getShiftOp(ARM_AM::ShiftOpc ShOpc) const { switch (ShOpc) { - default: llvm_unreachable("Unknown shift opc!"); case ARM_AM::no_shift: case ARM_AM::lsl: return 0; case ARM_AM::lsr: return 1; @@ -185,7 +186,7 @@ public: case ARM_AM::ror: case ARM_AM::rrx: return 3; } - return 0; + llvm_unreachable("Invalid ShiftOpc!"); } /// getAddrMode2OpValue - Return encoding for addrmode2 operands. @@ -423,7 +424,6 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, } llvm_unreachable("Unable to encode MCOperand!"); - return 0; } /// getAddrModeImmOpValue - Return encoding info for 'reg +/- imm' operand. @@ -466,7 +466,7 @@ static uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, assert(MO.isExpr() && "Unexpected branch target type!"); const MCExpr *Expr = MO.getExpr(); MCFixupKind Kind = MCFixupKind(FixupKind); - Fixups.push_back(MCFixup::Create(0, Expr, Kind)); + Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); // All of the information is in the fixup. return 0; @@ -594,16 +594,21 @@ getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, } uint32_t ARMMCCodeEmitter:: +getARMBLTargetOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl<MCFixup> &Fixups) const { + const MCOperand MO = MI.getOperand(OpIdx); + if (MO.isExpr()) + return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_bl, Fixups); + + return MO.getImm() >> 2; +} + +uint32_t ARMMCCodeEmitter:: getARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups) const { const MCOperand MO = MI.getOperand(OpIdx); - if (MO.isExpr()) { - if (HasConditionalBranch(MI)) - return ::getBranchTargetOpValue(MI, OpIdx, - ARM::fixup_arm_condbranch, Fixups); - return ::getBranchTargetOpValue(MI, OpIdx, - ARM::fixup_arm_uncondbranch, Fixups); - } + if (MO.isExpr()) + return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_blx, Fixups); return MO.getImm() >> 1; } @@ -718,12 +723,13 @@ getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, Kind = MCFixupKind(ARM::fixup_t2_ldst_pcrel_12); else Kind = MCFixupKind(ARM::fixup_arm_ldst_pcrel_12); - Fixups.push_back(MCFixup::Create(0, Expr, Kind)); + Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); ++MCNumCPRelocations; } else { Reg = ARM::PC; int32_t Offset = MO.getImm(); + // FIXME: Handle #-0. if (Offset < 0) { Offset *= -1; isAdd = false; @@ -791,8 +797,8 @@ getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx, assert(MO.isExpr() && "Unexpected machine operand type!"); const MCExpr *Expr = MO.getExpr(); - MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_10); - Fixups.push_back(MCFixup::Create(0, Expr, Kind)); + MCFixupKind Kind = MCFixupKind(ARM::fixup_t2_pcrel_10); + Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); ++MCNumCPRelocations; } else @@ -833,7 +839,7 @@ getT2AddrModeImm0_1020s4OpValue(const MCInst &MI, unsigned OpIdx, // but this is good enough for now. static bool EvaluateAsPCRel(const MCExpr *Expr) { switch (Expr->getKind()) { - default: assert(0 && "Unexpected expression type"); + default: llvm_unreachable("Unexpected expression type"); case MCExpr::SymbolRef: return false; case MCExpr::Binary: return true; } @@ -857,7 +863,7 @@ ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx, MCFixupKind Kind; switch (ARM16Expr->getKind()) { - default: assert(0 && "Unsupported ARMFixup"); + default: llvm_unreachable("Unsupported ARMFixup"); case ARMMCExpr::VK_ARM_HI16: if (!isTargetDarwin() && EvaluateAsPCRel(E)) Kind = MCFixupKind(isThumb2() @@ -879,12 +885,11 @@ ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx, : ARM::fixup_arm_movw_lo16); break; } - Fixups.push_back(MCFixup::Create(0, E, Kind)); + Fixups.push_back(MCFixup::Create(0, E, Kind, MI.getLoc())); return 0; }; llvm_unreachable("Unsupported MCExpr type in MCOperand!"); - return 0; } uint32_t ARMMCCodeEmitter:: @@ -993,6 +998,19 @@ getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx, const MCOperand &MO = MI.getOperand(OpIdx); const MCOperand &MO1 = MI.getOperand(OpIdx+1); const MCOperand &MO2 = MI.getOperand(OpIdx+2); + + // If The first operand isn't a register, we have a label reference. + if (!MO.isReg()) { + unsigned Rn = getARMRegisterNumbering(ARM::PC); // Rn is PC. + + assert(MO.isExpr() && "Unexpected machine operand type!"); + const MCExpr *Expr = MO.getExpr(); + MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_10_unscaled); + Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); + + ++MCNumCPRelocations; + return (Rn << 9) | (1 << 13); + } unsigned Rn = getARMRegisterNumbering(MO.getReg()); unsigned Imm = MO2.getImm(); bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add; @@ -1066,7 +1084,7 @@ getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, Kind = MCFixupKind(ARM::fixup_t2_pcrel_10); else Kind = MCFixupKind(ARM::fixup_arm_pcrel_10); - Fixups.push_back(MCFixup::Create(0, Expr, Kind)); + Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); ++MCNumCPRelocations; } else { @@ -1372,11 +1390,11 @@ getAddrMode6OneLane32AddressOpValue(const MCInst &MI, unsigned Op, switch (Imm.getImm()) { default: break; - case 2: - case 4: case 8: - case 16: Align = 0x00; break; - case 32: Align = 0x03; break; + case 16: + case 32: // Default '0' value for invalid alignments of 8, 16, 32 bytes. + case 2: Align = 0x00; break; + case 4: Align = 0x03; break; } return RegNo | (Align << 4); diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCExpr.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCExpr.cpp index 2727ba8..22e14a2 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCExpr.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCExpr.cpp @@ -21,7 +21,7 @@ ARMMCExpr::Create(VariantKind Kind, const MCExpr *Expr, void ARMMCExpr::PrintImpl(raw_ostream &OS) const { switch (Kind) { - default: assert(0 && "Invalid kind!"); + default: llvm_unreachable("Invalid kind!"); case VK_ARM_HI16: OS << ":upper16:"; break; case VK_ARM_LO16: OS << ":lower16:"; break; } @@ -45,8 +45,7 @@ ARMMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, static void AddValueSymbols_(const MCExpr *Value, MCAssembler *Asm) { switch (Value->getKind()) { case MCExpr::Target: - assert(0 && "Can't handle nested target expr!"); - break; + llvm_unreachable("Can't handle nested target expr!"); case MCExpr::Constant: break; diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCExpr.h b/lib/Target/ARM/MCTargetDesc/ARMMCExpr.h index 0a2e883..a727e08 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCExpr.h +++ b/lib/Target/ARM/MCTargetDesc/ARMMCExpr.h @@ -1,4 +1,4 @@ -//===-- ARMMCExpr.h - ARM specific MC expression classes ------------------===// +//===-- ARMMCExpr.h - ARM specific MC expression classes --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp index e86f48e..1606b92 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp @@ -1,4 +1,4 @@ -//===-- ARMMCTargetDesc.cpp - ARM Target Descriptions -----------*- C++ -*-===// +//===-- ARMMCTargetDesc.cpp - ARM Target Descriptions ---------------------===// // // The LLVM Compiler Infrastructure // @@ -155,7 +155,6 @@ static MCStreamer *createMCStreamer(const Target &T, StringRef TT, if (TheTriple.isOSWindows()) { llvm_unreachable("ARM does not support Windows COFF format"); - return NULL; } return createELFStreamer(Ctx, MAB, OS, Emitter, RelaxAll, NoExecStack); @@ -164,9 +163,10 @@ static MCStreamer *createMCStreamer(const Target &T, StringRef TT, static MCInstPrinter *createARMMCInstPrinter(const Target &T, unsigned SyntaxVariant, const MCAsmInfo &MAI, + const MCRegisterInfo &MRI, const MCSubtargetInfo &STI) { if (SyntaxVariant == 0) - return new ARMInstPrinter(MAI, STI); + return new ARMInstPrinter(MAI, MRI, STI); return 0; } diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h index 9b3d3bd..88472d7 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h +++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h @@ -46,6 +46,10 @@ MCCodeEmitter *createARMMCCodeEmitter(const MCInstrInfo &MCII, MCAsmBackend *createARMAsmBackend(const Target &T, StringRef TT); +/// createARMELFObjectWriter - Construct an ELF Mach-O object writer. +MCObjectWriter *createARMELFObjectWriter(raw_ostream &OS, + uint8_t OSABI); + /// createARMMachObjectWriter - Construct an ARM Mach-O object writer. MCObjectWriter *createARMMachObjectWriter(raw_ostream &OS, bool Is64Bit, diff --git a/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp b/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp index f394b4f..faf73ac 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp @@ -13,6 +13,7 @@ #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCMachObjectWriter.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCFixup.h" #include "llvm/MC/MCFixupKindInfo.h" @@ -81,6 +82,8 @@ static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType, case ARM::fixup_arm_adr_pcrel_12: case ARM::fixup_arm_condbranch: case ARM::fixup_arm_uncondbranch: + case ARM::fixup_arm_bl: + case ARM::fixup_arm_blx: RelocType = unsigned(macho::RIT_ARM_Branch24Bit); // Report as 'long', even though that is not quite accurate. Log2Size = llvm::Log2_32(4); @@ -136,7 +139,8 @@ RecordARMMovwMovtRelocation(MachObjectWriter *Writer, MCSymbolData *A_SD = &Asm.getSymbolData(*A); if (!A_SD->getFragment()) - report_fatal_error("symbol '" + A->getName() + + Asm.getContext().FatalError(Fixup.getLoc(), + "symbol '" + A->getName() + "' can not be undefined in a subtraction expression"); uint32_t Value = Writer->getSymbolAddress(A_SD, Layout); @@ -149,7 +153,8 @@ RecordARMMovwMovtRelocation(MachObjectWriter *Writer, MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); if (!B_SD->getFragment()) - report_fatal_error("symbol '" + B->getSymbol().getName() + + Asm.getContext().FatalError(Fixup.getLoc(), + "symbol '" + B->getSymbol().getName() + "' can not be undefined in a subtraction expression"); // Select the appropriate difference relocation type. @@ -240,7 +245,8 @@ void ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer, MCSymbolData *A_SD = &Asm.getSymbolData(*A); if (!A_SD->getFragment()) - report_fatal_error("symbol '" + A->getName() + + Asm.getContext().FatalError(Fixup.getLoc(), + "symbol '" + A->getName() + "' can not be undefined in a subtraction expression"); uint32_t Value = Writer->getSymbolAddress(A_SD, Layout); @@ -252,7 +258,8 @@ void ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer, MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); if (!B_SD->getFragment()) - report_fatal_error("symbol '" + B->getSymbol().getName() + + Asm.getContext().FatalError(Fixup.getLoc(), + "symbol '" + B->getSymbol().getName() + "' can not be undefined in a subtraction expression"); // Select the appropriate difference relocation type. @@ -294,10 +301,13 @@ void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer, unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); unsigned Log2Size; unsigned RelocType = macho::RIT_Vanilla; - if (!getARMFixupKindMachOInfo(Fixup.getKind(), RelocType, Log2Size)) { - report_fatal_error("unknown ARM fixup kind!"); - return; - } + if (!getARMFixupKindMachOInfo(Fixup.getKind(), RelocType, Log2Size)) + // If we failed to get fixup kind info, it's because there's no legal + // relocation type for the fixup kind. This happens when it's a fixup that's + // expected to always be resolvable at assembly time and not have any + // relocations needed. + Asm.getContext().FatalError(Fixup.getLoc(), + "unsupported relocation on symbol"); // If this is a difference or a defined symbol plus an offset, then we need a // scattered relocation entry. Differences always require scattered diff --git a/lib/Target/ARM/MCTargetDesc/CMakeLists.txt b/lib/Target/ARM/MCTargetDesc/CMakeLists.txt index f2cf78a..2565994 100644 --- a/lib/Target/ARM/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/ARM/MCTargetDesc/CMakeLists.txt @@ -1,10 +1,12 @@ add_llvm_library(LLVMARMDesc ARMAsmBackend.cpp + ARMELFObjectWriter.cpp ARMMCAsmInfo.cpp ARMMCCodeEmitter.cpp ARMMCExpr.cpp ARMMCTargetDesc.cpp ARMMachObjectWriter.cpp + ARMELFObjectWriter.cpp ) add_dependencies(LLVMARMDesc ARMCommonTableGen) |