diff options
Diffstat (limited to 'lib/Target/ARM/MCTargetDesc')
21 files changed, 1709 insertions, 806 deletions
diff --git a/lib/Target/ARM/MCTargetDesc/ARMArchName.def b/lib/Target/ARM/MCTargetDesc/ARMArchName.def new file mode 100644 index 0000000..9f007a0 --- /dev/null +++ b/lib/Target/ARM/MCTargetDesc/ARMArchName.def @@ -0,0 +1,50 @@ +//===-- ARMArchName.def - List of the ARM arch names ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the list of the supported ARM architecture names, +// i.e. the supported value for -march= option. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +#ifndef ARM_ARCH_NAME +#error "You must define ARM_ARCH_NAME before including ARMArchName.def" +#endif + +// ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) +ARM_ARCH_NAME("armv2", ARMV2, "2", v4) +ARM_ARCH_NAME("armv2a", ARMV2A, "2A", v4) +ARM_ARCH_NAME("armv3", ARMV3, "3", v4) +ARM_ARCH_NAME("armv3m", ARMV3M, "3M", v4) +ARM_ARCH_NAME("armv4", ARMV4, "4", v4) +ARM_ARCH_NAME("armv4t", ARMV4T, "4T", v4T) +ARM_ARCH_NAME("armv5", ARMV5, "5", v5T) +ARM_ARCH_NAME("armv5t", ARMV5T, "5T", v5T) +ARM_ARCH_NAME("armv5te", ARMV5TE, "5TE", v5TE) +ARM_ARCH_NAME("armv6", ARMV6, "6", v6) +ARM_ARCH_NAME("armv6j", ARMV6J, "6J", v6) +ARM_ARCH_NAME("armv6t2", ARMV6T2, "6T2", v6T2) +ARM_ARCH_NAME("armv6z", ARMV6Z, "6Z", v6KZ) +ARM_ARCH_NAME("armv6zk", ARMV6ZK, "6ZK", v6KZ) +ARM_ARCH_NAME("armv6-m", ARMV6M, "6-M", v6_M) +ARM_ARCH_NAME("armv7", ARMV7, "7", v7) +ARM_ARCH_NAME("armv7-a", ARMV7A, "7-A", v7) +ARM_ARCH_ALIAS("armv7a", ARMV7A) +ARM_ARCH_NAME("armv7-r", ARMV7R, "7-R", v7) +ARM_ARCH_ALIAS("armv7r", ARMV7R) +ARM_ARCH_NAME("armv7-m", ARMV7M, "7-M", v7) +ARM_ARCH_ALIAS("armv7m", ARMV7M) +ARM_ARCH_NAME("armv8-a", ARMV8A, "8-A", v8) +ARM_ARCH_ALIAS("armv8a", ARMV8A) +ARM_ARCH_NAME("iwmmxt", IWMMXT, "iwmmxt", v5TE) +ARM_ARCH_NAME("iwmmxt2", IWMMXT2, "iwmmxt2", v5TE) + +#undef ARM_ARCH_NAME +#undef ARM_ARCH_ALIAS diff --git a/lib/Target/ARM/MCTargetDesc/ARMArchName.h b/lib/Target/ARM/MCTargetDesc/ARMArchName.h new file mode 100644 index 0000000..34b9fc1 --- /dev/null +++ b/lib/Target/ARM/MCTargetDesc/ARMArchName.h @@ -0,0 +1,27 @@ +//===-- ARMArchName.h - List of the ARM arch names --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMARCHNAME_H +#define ARMARCHNAME_H + +namespace llvm { +namespace ARM { + +enum ArchKind { + INVALID_ARCH = 0 + +#define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) , ID +#define ARM_ARCH_ALIAS(NAME, ID) /* empty */ +#include "ARMArchName.def" +}; + +} // namespace ARM +} // namespace llvm + +#endif // ARMARCHNAME_H diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 5615b80..1db517f 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -41,24 +41,27 @@ public: class ARMAsmBackend : public MCAsmBackend { const MCSubtargetInfo* STI; - bool isThumbMode; // Currently emitting Thumb code. + bool isThumbMode; // Currently emitting Thumb code. + bool IsLittleEndian; // Big or little endian. public: - ARMAsmBackend(const Target &T, const StringRef TT) + ARMAsmBackend(const Target &T, const StringRef TT, bool IsLittle) : MCAsmBackend(), STI(ARM_MC::createARMMCSubtargetInfo(TT, "", "")), - isThumbMode(TT.startswith("thumb")) {} + isThumbMode(TT.startswith("thumb")), IsLittleEndian(IsLittle) {} ~ARMAsmBackend() { delete STI; } - unsigned getNumFixupKinds() const { return ARM::NumTargetFixupKinds; } + unsigned getNumFixupKinds() const override { + return ARM::NumTargetFixupKinds; + } bool hasNOP() const { return (STI->getFeatureBits() & ARM::HasV6T2Ops) != 0; } - const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { - const static MCFixupKindInfo Infos[ARM::NumTargetFixupKinds] = { + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { + const static MCFixupKindInfo InfosLE[ARM::NumTargetFixupKinds] = { // This table *must* be in the order that the fixup_* kinds are defined in // ARMFixupKinds.h. // @@ -94,10 +97,43 @@ public: { "fixup_arm_movw_lo16", 0, 20, 0 }, { "fixup_t2_movt_hi16", 0, 20, 0 }, { "fixup_t2_movw_lo16", 0, 20, 0 }, -{ "fixup_arm_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, -{ "fixup_arm_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, -{ "fixup_t2_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, -{ "fixup_t2_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, + }; + const static MCFixupKindInfo InfosBE[ARM::NumTargetFixupKinds] = { +// This table *must* be in the order that the fixup_* kinds are defined in +// ARMFixupKinds.h. +// +// Name Offset (bits) Size (bits) Flags +{ "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}, +{ "fixup_thumb_adr_pcrel_10",8, 8, MCFixupKindInfo::FKF_IsPCRel | + MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, +{ "fixup_arm_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_t2_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | + MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, +{ "fixup_arm_condbranch", 8, 24, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_arm_uncondbranch", 8, 24, MCFixupKindInfo::FKF_IsPCRel }, +{ "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_uncondbl", 8, 24, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_arm_condbl", 8, 24, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_arm_blx", 8, 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 }, +{ "fixup_arm_thumb_cp", 8, 8, MCFixupKindInfo::FKF_IsPCRel | + MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, +{ "fixup_arm_thumb_bcc", 8, 8, MCFixupKindInfo::FKF_IsPCRel }, +// movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 16 - 19. +{ "fixup_arm_movt_hi16", 12, 20, 0 }, +{ "fixup_arm_movw_lo16", 12, 20, 0 }, +{ "fixup_t2_movt_hi16", 12, 20, 0 }, +{ "fixup_t2_movw_lo16", 12, 20, 0 }, }; if (Kind < FirstTargetFixupKind) @@ -105,32 +141,31 @@ public: assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && "Invalid kind!"); - return Infos[Kind - FirstTargetFixupKind]; + return (IsLittleEndian ? InfosLE : InfosBE)[Kind - FirstTargetFixupKind]; } /// 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 MCValue &Target, uint64_t &Value, + bool &IsResolved) override; void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, - uint64_t Value) const; + uint64_t Value, bool IsPCRel) const override; - bool mayNeedRelaxation(const MCInst &Inst) const; + bool mayNeedRelaxation(const MCInst &Inst) const override; - bool fixupNeedsRelaxation(const MCFixup &Fixup, - uint64_t Value, + bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, - const MCAsmLayout &Layout) const; + const MCAsmLayout &Layout) const override; - void relaxInstruction(const MCInst &Inst, MCInst &Res) const; + void relaxInstruction(const MCInst &Inst, MCInst &Res) const override; - bool writeNopData(uint64_t Count, MCObjectWriter *OW) const; + bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; - void handleAssemblerFlag(MCAssemblerFlag Flag) { + void handleAssemblerFlag(MCAssemblerFlag Flag) override { switch (Flag) { default: break; case MCAF_Code16: @@ -145,6 +180,7 @@ public: unsigned getPointerSize() const { return 4; } bool isThumb() const { return isThumbMode; } void setIsThumb(bool it) { isThumbMode = it; } + bool isLittle() const { return IsLittleEndian; } }; } // end anonymous namespace @@ -155,6 +191,8 @@ static unsigned getRelaxedOpcode(unsigned Op) { case ARM::tLDRpci: return ARM::t2LDRpci; case ARM::tADR: return ARM::t2ADR; case ARM::tB: return ARM::t2B; + case ARM::tCBZ: return ARM::tHINT; + case ARM::tCBNZ: return ARM::tHINT; } } @@ -196,6 +234,12 @@ bool ARMAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, int64_t Offset = int64_t(Value) - 4; return Offset > 1020 || Offset < 0 || Offset & 3; } + case ARM::fixup_arm_thumb_cb: + // If we have a Thumb CBZ or CBNZ instruction and its target is the next + // instruction it is is actually out of range for the instruction. + // It will be changed to a NOP. + int64_t Offset = (Value & ~1); + return Offset == 2; } llvm_unreachable("Unexpected fixup kind in fixupNeedsRelaxation()!"); } @@ -212,7 +256,18 @@ void ARMAsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const { report_fatal_error("unexpected instruction to relax: " + OS.str()); } - // The instructions we're relaxing have (so far) the same operands. + // If we are changing Thumb CBZ or CBNZ instruction to a NOP, aka tHINT, we + // have to change the operands too. + if ((Inst.getOpcode() == ARM::tCBZ || Inst.getOpcode() == ARM::tCBNZ) && + RelaxedOp == ARM::tHINT) { + Res.setOpcode(RelaxedOp); + Res.addOperand(MCOperand::CreateImm(0)); + Res.addOperand(MCOperand::CreateImm(14)); + Res.addOperand(MCOperand::CreateReg(0)); + return; + } + + // The rest of instructions we're relaxing have the same operands. // We just need to update to the proper opcode. Res = Inst; Res.setOpcode(RelaxedOp); @@ -252,7 +307,7 @@ bool ARMAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { } static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, - MCContext *Ctx = NULL) { + bool IsPCRel, MCContext *Ctx) { unsigned Kind = Fixup.getKind(); switch (Kind) { default: @@ -262,11 +317,10 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, case FK_Data_4: return Value; case ARM::fixup_arm_movt_hi16: - Value >>= 16; + if (!IsPCRel) + Value >>= 16; // Fallthrough - case ARM::fixup_arm_movw_lo16: - case ARM::fixup_arm_movt_hi16_pcrel: - case ARM::fixup_arm_movw_lo16_pcrel: { + case ARM::fixup_arm_movw_lo16: { unsigned Hi4 = (Value & 0xF000) >> 12; unsigned Lo12 = Value & 0x0FFF; // inst{19-16} = Hi4; @@ -275,12 +329,10 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, return Value; } case ARM::fixup_t2_movt_hi16: - Value >>= 16; + if (!IsPCRel) + Value >>= 16; // Fallthrough - case ARM::fixup_t2_movw_lo16: - case ARM::fixup_t2_movt_hi16_pcrel: //FIXME: Shouldn't this be shifted like - // the other hi16 fixup? - case ARM::fixup_t2_movw_lo16_pcrel: { + case ARM::fixup_t2_movw_lo16: { unsigned Hi4 = (Value & 0xF000) >> 12; unsigned i = (Value & 0x800) >> 11; unsigned Mid3 = (Value & 0x700) >> 8; @@ -361,6 +413,9 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, 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. + if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Fixup.getValue())) + if (SRE->getKind() == MCSymbolRefExpr::VK_ARM_TLSCALL) + return 0; return 0xffffff & ((Value - 8) >> 2); case ARM::fixup_t2_uncondbranch: { Value = Value - 4; @@ -399,65 +454,67 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, return swapped; } case ARM::fixup_arm_thumb_bl: { - // The value doesn't encode the low bit (always zero) and is offset by - // four. The 32-bit immediate value is encoded as - // imm32 = SignExtend(S:I1:I2:imm10:imm11:0) - // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S). - // The value is encoded into disjoint bit positions in the destination - // opcode. x = unchanged, I = immediate value bit, S = sign extension bit, - // J = either J1 or J2 bit - // - // BL: xxxxxSIIIIIIIIII xxJxJIIIIIIIIIII - // - // Note that the halfwords are stored high first, low second; so we need - // to transpose the fixup value here to map properly. - uint32_t offset = (Value - 4) >> 1; - uint32_t signBit = (offset & 0x800000) >> 23; - uint32_t I1Bit = (offset & 0x400000) >> 22; - uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit; - uint32_t I2Bit = (offset & 0x200000) >> 21; - uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit; - uint32_t imm10Bits = (offset & 0x1FF800) >> 11; - uint32_t imm11Bits = (offset & 0x000007FF); - - uint32_t Binary = 0; - uint32_t firstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10Bits); - uint32_t secondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) | - (uint16_t)imm11Bits); - Binary |= secondHalf << 16; - Binary |= firstHalf; - return Binary; - + // The value doesn't encode the low bit (always zero) and is offset by + // four. The 32-bit immediate value is encoded as + // imm32 = SignExtend(S:I1:I2:imm10:imm11:0) + // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S). + // The value is encoded into disjoint bit positions in the destination + // opcode. x = unchanged, I = immediate value bit, S = sign extension bit, + // J = either J1 or J2 bit + // + // BL: xxxxxSIIIIIIIIII xxJxJIIIIIIIIIII + // + // Note that the halfwords are stored high first, low second; so we need + // to transpose the fixup value here to map properly. + uint32_t offset = (Value - 4) >> 1; + uint32_t signBit = (offset & 0x800000) >> 23; + uint32_t I1Bit = (offset & 0x400000) >> 22; + uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit; + uint32_t I2Bit = (offset & 0x200000) >> 21; + uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit; + uint32_t imm10Bits = (offset & 0x1FF800) >> 11; + uint32_t imm11Bits = (offset & 0x000007FF); + + uint32_t Binary = 0; + uint32_t firstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10Bits); + uint32_t secondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) | + (uint16_t)imm11Bits); + Binary |= secondHalf << 16; + Binary |= firstHalf; + return Binary; } case ARM::fixup_arm_thumb_blx: { - // The value doesn't encode the low two bits (always zero) and is offset by - // four (see fixup_arm_thumb_cp). The 32-bit immediate value is encoded as - // imm32 = SignExtend(S:I1:I2:imm10H:imm10L:00) - // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S). - // The value is encoded into disjoint bit positions in the destination - // opcode. x = unchanged, I = immediate value bit, S = sign extension bit, - // J = either J1 or J2 bit, 0 = zero. - // - // BLX: xxxxxSIIIIIIIIII xxJxJIIIIIIIIII0 - // - // Note that the halfwords are stored high first, low second; so we need - // to transpose the fixup value here to map properly. - uint32_t offset = (Value - 2) >> 2; - uint32_t signBit = (offset & 0x400000) >> 22; - uint32_t I1Bit = (offset & 0x200000) >> 21; - uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit; - uint32_t I2Bit = (offset & 0x100000) >> 20; - uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit; - uint32_t imm10HBits = (offset & 0xFFC00) >> 10; - uint32_t imm10LBits = (offset & 0x3FF); - - uint32_t Binary = 0; - uint32_t firstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10HBits); - uint32_t secondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) | - ((uint16_t)imm10LBits) << 1); - Binary |= secondHalf << 16; - Binary |= firstHalf; - return Binary; + // The value doesn't encode the low two bits (always zero) and is offset by + // four (see fixup_arm_thumb_cp). The 32-bit immediate value is encoded as + // imm32 = SignExtend(S:I1:I2:imm10H:imm10L:00) + // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S). + // The value is encoded into disjoint bit positions in the destination + // opcode. x = unchanged, I = immediate value bit, S = sign extension bit, + // J = either J1 or J2 bit, 0 = zero. + // + // BLX: xxxxxSIIIIIIIIII xxJxJIIIIIIIIII0 + // + // Note that the halfwords are stored high first, low second; so we need + // to transpose the fixup value here to map properly. + uint32_t offset = (Value - 2) >> 2; + if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Fixup.getValue())) + if (SRE->getKind() == MCSymbolRefExpr::VK_ARM_TLSCALL) + offset = 0; + uint32_t signBit = (offset & 0x400000) >> 22; + uint32_t I1Bit = (offset & 0x200000) >> 21; + uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit; + uint32_t I2Bit = (offset & 0x100000) >> 20; + uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit; + uint32_t imm10HBits = (offset & 0xFFC00) >> 10; + uint32_t imm10LBits = (offset & 0x3FF); + + uint32_t Binary = 0; + uint32_t firstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10HBits); + uint32_t secondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) | + ((uint16_t)imm10LBits) << 1); + Binary |= secondHalf << 16; + Binary |= firstHalf; + return Binary; } case ARM::fixup_arm_thumb_cp: // Offset by 4, and don't encode the low two bits. Two bytes of that @@ -524,7 +581,7 @@ void ARMAsmBackend::processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, - MCValue &Target, uint64_t &Value, + const MCValue &Target, uint64_t &Value, bool &IsResolved) { const MCSymbolRefExpr *A = Target.getSymA(); // Some fixups to thumb function symbols need the low bit (thumb bit) @@ -541,11 +598,18 @@ void ARMAsmBackend::processFixupValue(const MCAssembler &Asm, Value |= 1; } } + // For Thumb1 BL instruction, it is possible to be a long jump between + // the basic blocks of the same function. Thus, we would like to resolve + // the offset when the destination has the same MCFragment. + if (A && (unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_bl) { + const MCSymbol &Sym = A->getSymbol().AliasedSymbol(); + MCSymbolData &SymData = Asm.getSymbolData(Sym); + IsResolved = (SymData.getFragment() == DF); + } // 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_uncondbl || (unsigned)Fixup.getKind() == ARM::fixup_arm_condbl)) @@ -554,7 +618,7 @@ void ARMAsmBackend::processFixupValue(const MCAssembler &Asm, // Try to get the encoded value for the fixup as-if we're mapping it into // the instruction. This allows adjustFixupValue() to issue a diagnostic // if the value aren't invalid. - (void)adjustFixupValue(Fixup, Value, &Asm.getContext()); + (void)adjustFixupValue(Fixup, Value, false, &Asm.getContext()); } /// getFixupKindNumBytes - The number of bytes the fixup may change. @@ -595,30 +659,81 @@ static unsigned getFixupKindNumBytes(unsigned Kind) { case ARM::fixup_arm_thumb_blx: case ARM::fixup_arm_movt_hi16: case ARM::fixup_arm_movw_lo16: - case ARM::fixup_arm_movt_hi16_pcrel: - case ARM::fixup_arm_movw_lo16_pcrel: case ARM::fixup_t2_movt_hi16: case ARM::fixup_t2_movw_lo16: - case ARM::fixup_t2_movt_hi16_pcrel: - case ARM::fixup_t2_movw_lo16_pcrel: + return 4; + } +} + +/// getFixupKindContainerSizeBytes - The number of bytes of the +/// container involved in big endian. +static unsigned getFixupKindContainerSizeBytes(unsigned Kind) { + switch (Kind) { + default: + llvm_unreachable("Unknown fixup kind!"); + + case FK_Data_1: + return 1; + case FK_Data_2: + return 2; + case FK_Data_4: + return 4; + + case ARM::fixup_arm_thumb_bcc: + case ARM::fixup_arm_thumb_cp: + case ARM::fixup_thumb_adr_pcrel_10: + case ARM::fixup_arm_thumb_br: + case ARM::fixup_arm_thumb_cb: + // Instruction size is 2 bytes. + 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_uncondbl: + case ARM::fixup_arm_condbl: + case ARM::fixup_arm_blx: + case ARM::fixup_arm_condbranch: + case ARM::fixup_arm_uncondbranch: + case ARM::fixup_t2_ldst_pcrel_12: + case ARM::fixup_t2_condbranch: + case ARM::fixup_t2_uncondbranch: + case ARM::fixup_t2_pcrel_10: + case ARM::fixup_t2_adr_pcrel_12: + case ARM::fixup_arm_thumb_bl: + case ARM::fixup_arm_thumb_blx: + case ARM::fixup_arm_movt_hi16: + case ARM::fixup_arm_movw_lo16: + case ARM::fixup_t2_movt_hi16: + case ARM::fixup_t2_movw_lo16: + // Instruction size is 4 bytes. return 4; } } void ARMAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, - unsigned DataSize, uint64_t Value) const { + unsigned DataSize, uint64_t Value, + bool IsPCRel) const { unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); - Value = adjustFixupValue(Fixup, Value); + Value = adjustFixupValue(Fixup, Value, IsPCRel, nullptr); if (!Value) return; // Doesn't change encoding. unsigned Offset = Fixup.getOffset(); assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!"); + // Used to point to big endian bytes. + unsigned FullSizeBytes; + if (!IsLittleEndian) + FullSizeBytes = getFixupKindContainerSizeBytes(Fixup.getKind()); + // For each byte of the fragment that the fixup touches, mask in the bits from // the fixup value. The Value has been "split up" into the appropriate // bitfields above. - for (unsigned i = 0; i != NumBytes; ++i) - Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); + for (unsigned i = 0; i != NumBytes; ++i) { + unsigned Idx = IsLittleEndian ? i : (FullSizeBytes - 1 - i); + Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff); + } } namespace { @@ -629,11 +744,11 @@ class ELFARMAsmBackend : public ARMAsmBackend { public: uint8_t OSABI; ELFARMAsmBackend(const Target &T, const StringRef TT, - uint8_t _OSABI) - : ARMAsmBackend(T, TT), OSABI(_OSABI) { } + uint8_t OSABI, bool IsLittle) + : ARMAsmBackend(T, TT, IsLittle), OSABI(OSABI) { } - MCObjectWriter *createObjectWriter(raw_ostream &OS) const { - return createARMELFObjectWriter(OS, OSABI); + MCObjectWriter *createObjectWriter(raw_ostream &OS) const override { + return createARMELFObjectWriter(OS, OSABI, isLittle()); } }; @@ -643,29 +758,26 @@ public: const MachO::CPUSubTypeARM Subtype; DarwinARMAsmBackend(const Target &T, const StringRef TT, MachO::CPUSubTypeARM st) - : ARMAsmBackend(T, TT), Subtype(st) { + : ARMAsmBackend(T, TT, /* IsLittleEndian */ true), Subtype(st) { HasDataInCodeSupport = true; } - MCObjectWriter *createObjectWriter(raw_ostream &OS) const { + MCObjectWriter *createObjectWriter(raw_ostream &OS) const override { return createARMMachObjectWriter(OS, /*Is64Bit=*/false, MachO::CPU_TYPE_ARM, Subtype); } - - virtual bool doesSectionRequireSymbols(const MCSection &Section) const { - return false; - } }; } // end anonymous namespace MCAsmBackend *llvm::createARMAsmBackend(const Target &T, const MCRegisterInfo &MRI, - StringRef TT, StringRef CPU) { + StringRef TT, StringRef CPU, + bool isLittle) { Triple TheTriple(TT); - if (TheTriple.isOSDarwin()) { + if (TheTriple.isOSBinFormatMachO()) { MachO::CPUSubTypeARM CS = StringSwitch<MachO::CPUSubTypeARM>(TheTriple.getArchName()) .Cases("armv4t", "thumbv4t", MachO::CPU_SUBTYPE_ARM_V4T) @@ -673,7 +785,6 @@ MCAsmBackend *llvm::createARMAsmBackend(const Target &T, .Cases("armv6", "thumbv6", MachO::CPU_SUBTYPE_ARM_V6) .Cases("armv6m", "thumbv6m", MachO::CPU_SUBTYPE_ARM_V6M) .Cases("armv7em", "thumbv7em", MachO::CPU_SUBTYPE_ARM_V7EM) - .Cases("armv7f", "thumbv7f", MachO::CPU_SUBTYPE_ARM_V7F) .Cases("armv7k", "thumbv7k", MachO::CPU_SUBTYPE_ARM_V7K) .Cases("armv7m", "thumbv7m", MachO::CPU_SUBTYPE_ARM_V7M) .Cases("armv7s", "thumbv7s", MachO::CPU_SUBTYPE_ARM_V7S) @@ -689,5 +800,30 @@ MCAsmBackend *llvm::createARMAsmBackend(const Target &T, #endif uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS()); - return new ELFARMAsmBackend(T, TT, OSABI); + return new ELFARMAsmBackend(T, TT, OSABI, isLittle); +} + +MCAsmBackend *llvm::createARMLEAsmBackend(const Target &T, + const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU) { + return createARMAsmBackend(T, MRI, TT, CPU, true); +} + +MCAsmBackend *llvm::createARMBEAsmBackend(const Target &T, + const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU) { + return createARMAsmBackend(T, MRI, TT, CPU, false); } + +MCAsmBackend *llvm::createThumbLEAsmBackend(const Target &T, + const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU) { + return createARMAsmBackend(T, MRI, TT, CPU, true); +} + +MCAsmBackend *llvm::createThumbBEAsmBackend(const Target &T, + const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU) { + return createARMAsmBackend(T, MRI, TT, CPU, false); +} + diff --git a/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h b/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h index af939fc..42a1cbb 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h +++ b/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h @@ -183,7 +183,8 @@ namespace ARM_ISB { inline static const char *InstSyncBOptToString(unsigned val) { switch (val) { - default: llvm_unreachable("Unkown memory operation"); + default: + llvm_unreachable("Unknown memory operation"); case RESERVED_0: return "#0x0"; case RESERVED_1: return "#0x1"; case RESERVED_2: return "#0x2"; @@ -278,42 +279,36 @@ namespace ARMII { //===------------------------------------------------------------------===// // ARM Specific MachineOperand flags. - MO_NO_FLAG, + MO_NO_FLAG = 0, /// MO_LO16 - On a symbol operand, this represents a relocation containing /// lower 16 bit of the address. Used only via movw instruction. - MO_LO16, + MO_LO16 = 0x1, /// MO_HI16 - On a symbol operand, this represents a relocation containing /// higher 16 bit of the address. Used only via movt instruction. - MO_HI16, - - /// MO_LO16_NONLAZY - On a symbol operand "FOO", this represents a - /// relocation containing lower 16 bit of the non-lazy-ptr indirect symbol, - /// i.e. "FOO$non_lazy_ptr". - /// Used only via movw instruction. - MO_LO16_NONLAZY, - - /// MO_HI16_NONLAZY - On a symbol operand "FOO", this represents a - /// relocation containing lower 16 bit of the non-lazy-ptr indirect symbol, - /// i.e. "FOO$non_lazy_ptr". Used only via movt instruction. - MO_HI16_NONLAZY, - - /// MO_LO16_NONLAZY_PIC - On a symbol operand "FOO", this represents a - /// relocation containing lower 16 bit of the PC relative address of the - /// non-lazy-ptr indirect symbol, i.e. "FOO$non_lazy_ptr - LABEL". - /// Used only via movw instruction. - MO_LO16_NONLAZY_PIC, - - /// MO_HI16_NONLAZY_PIC - On a symbol operand "FOO", this represents a - /// relocation containing lower 16 bit of the PC relative address of the - /// non-lazy-ptr indirect symbol, i.e. "FOO$non_lazy_ptr - LABEL". - /// Used only via movt instruction. - MO_HI16_NONLAZY_PIC, + MO_HI16 = 0x2, /// MO_PLT - On a symbol operand, this represents an ELF PLT reference on a /// call operand. - MO_PLT + MO_PLT = 0x3, + + /// MO_OPTION_MASK - Most flags are mutually exclusive; this mask selects + /// just that part of the flag set. + MO_OPTION_MASK = 0x7f, + + /// MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it + /// represents a symbol which, if indirect, will get special Darwin mangling + /// as a non-lazy-ptr indirect symbol (i.e. "L_FOO$non_lazy_ptr"). Can be + /// combined with MO_LO16, MO_HI16 or MO_NO_FLAG (in a constant-pool, for + /// example). + MO_NONLAZY = 0x80, + + // It's undefined behaviour if an enum overflows the range between its + // smallest and largest values, but since these are |ed together, it can + // happen. Put a sentinel in (values of this enum are stored as "unsigned + // char"). + MO_UNUSED_MAXIMUM = 0xff }; enum { diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp index f98bbd2..a4661b1 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp @@ -34,14 +34,10 @@ namespace { virtual ~ARMELFObjectWriter(); - virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, - bool IsPCRel, bool IsRelocWithSymbol, - int64_t Addend) const; - virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const; + unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsPCRel) const override; + + bool needsRelocateWithSymbol(unsigned Type) const override; }; } @@ -52,91 +48,18 @@ ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI) ARMELFObjectWriter::~ARMELFObjectWriter() {} -// 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; - case ELF::R_ARM_PREL31: EmitThisSym = false; break; - } - } - - if (EmitThisSym) - return &Symbol; - if (! Symbol.isTemporary() && InNormalSection) { - return &Symbol; +bool ARMELFObjectWriter::needsRelocateWithSymbol(unsigned Type) const { + // FIXME: This is extremelly conservative. This really needs to use a + // whitelist with a clear explanation for why each realocation needs to + // point to the symbol, not to the section. + switch (Type) { + default: + return true; + + case ELF::R_ARM_PREL31: + case ELF::R_ARM_ABS32: + return false; } - return NULL; } // Need to examine the Fixup when determining whether to @@ -144,17 +67,14 @@ const MCSymbol *ARMELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm, // offset unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target, const MCFixup &Fixup, - bool IsPCRel, - bool IsRelocWithSymbol, - int64_t Addend) const { + bool IsPCRel) 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(); + MCSymbolRefExpr::VariantKind Modifier = Fixup.getAccessVariant(); unsigned Type = 0; if (IsPCRel) { @@ -166,9 +86,9 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, case MCSymbolRefExpr::VK_None: Type = ELF::R_ARM_REL32; break; - case MCSymbolRefExpr::VK_ARM_TLSGD: + case MCSymbolRefExpr::VK_TLSGD: llvm_unreachable("unimplemented"); - case MCSymbolRefExpr::VK_ARM_GOTTPOFF: + case MCSymbolRefExpr::VK_GOTTPOFF: Type = ELF::R_ARM_TLS_IE32; break; } @@ -176,9 +96,12 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, case ARM::fixup_arm_blx: case ARM::fixup_arm_uncondbl: switch (Modifier) { - case MCSymbolRefExpr::VK_ARM_PLT: + case MCSymbolRefExpr::VK_PLT: Type = ELF::R_ARM_PLT32; break; + case MCSymbolRefExpr::VK_ARM_TLSCALL: + Type = ELF::R_ARM_TLS_CALL; + break; default: Type = ELF::R_ARM_CALL; break; @@ -194,24 +117,27 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, Type = ELF::R_ARM_THM_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; + switch (Modifier) { + case MCSymbolRefExpr::VK_ARM_TLSCALL: + Type = ELF::R_ARM_THM_TLS_CALL; + break; + default: + Type = ELF::R_ARM_THM_CALL; + break; + } break; } } else { @@ -223,22 +149,22 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, case MCSymbolRefExpr::VK_ARM_NONE: Type = ELF::R_ARM_NONE; break; - case MCSymbolRefExpr::VK_ARM_GOT: + case MCSymbolRefExpr::VK_GOT: Type = ELF::R_ARM_GOT_BREL; break; - case MCSymbolRefExpr::VK_ARM_TLSGD: + case MCSymbolRefExpr::VK_TLSGD: Type = ELF::R_ARM_TLS_GD32; break; - case MCSymbolRefExpr::VK_ARM_TPOFF: + case MCSymbolRefExpr::VK_TPOFF: Type = ELF::R_ARM_TLS_LE32; break; - case MCSymbolRefExpr::VK_ARM_GOTTPOFF: + case MCSymbolRefExpr::VK_GOTTPOFF: Type = ELF::R_ARM_TLS_IE32; break; case MCSymbolRefExpr::VK_None: Type = ELF::R_ARM_ABS32; break; - case MCSymbolRefExpr::VK_ARM_GOTOFF: + case MCSymbolRefExpr::VK_GOTOFF: Type = ELF::R_ARM_GOTOFF32; break; case MCSymbolRefExpr::VK_ARM_TARGET1: @@ -250,6 +176,18 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, case MCSymbolRefExpr::VK_ARM_PREL31: Type = ELF::R_ARM_PREL31; break; + case MCSymbolRefExpr::VK_ARM_TLSLDO: + Type = ELF::R_ARM_TLS_LDO32; + break; + case MCSymbolRefExpr::VK_ARM_TLSCALL: + Type = ELF::R_ARM_TLS_CALL; + break; + case MCSymbolRefExpr::VK_ARM_TLSDESC: + Type = ELF::R_ARM_TLS_GOTDESC; + break; + case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ: + Type = ELF::R_ARM_TLS_DESCSEQ; + break; } break; case ARM::fixup_arm_ldst_pcrel_12: @@ -283,7 +221,8 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, } MCObjectWriter *llvm::createARMELFObjectWriter(raw_ostream &OS, - uint8_t OSABI) { + uint8_t OSABI, + bool IsLittleEndian) { MCELFObjectTargetWriter *MOTW = new ARMELFObjectWriter(OSABI); - return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/true); + return createELFObjectWriter(MOTW, OS, IsLittleEndian); } diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp index 471897d..5a01d26 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -13,14 +13,14 @@ // //===----------------------------------------------------------------------===// -#include "ARMBuildAttrs.h" +#include "ARMArchName.h" #include "ARMFPUName.h" #include "ARMRegisterInfo.h" -#include "ARMUnwindOp.h" #include "ARMUnwindOpAsm.h" -#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" @@ -37,16 +37,20 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" +#include "llvm/Support/ARMBuildAttributes.h" +#include "llvm/Support/ARMEHABI.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/LEB128.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> using namespace llvm; static std::string GetAEABIUnwindPersonalityName(unsigned Index) { - assert(Index < NUM_PERSONALITY_INDEX && "Invalid personality index"); + assert(Index < ARM::EHABI::NUM_PERSONALITY_INDEX && + "Invalid personality index"); return (Twine("__aeabi_unwind_cpp_pr") + Twine(Index)).str(); } @@ -61,6 +65,45 @@ static const char *GetFPUName(unsigned ID) { return NULL; } +static const char *GetArchName(unsigned ID) { + switch (ID) { + default: + llvm_unreachable("Unknown ARCH kind"); + break; +#define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) \ + case ARM::ID: return NAME; +#define ARM_ARCH_ALIAS(NAME, ID) /* empty */ +#include "ARMArchName.def" + } + return NULL; +} + +static const char *GetArchDefaultCPUName(unsigned ID) { + switch (ID) { + default: + llvm_unreachable("Unknown ARCH kind"); + break; +#define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) \ + case ARM::ID: return DEFAULT_CPU_NAME; +#define ARM_ARCH_ALIAS(NAME, ID) /* empty */ +#include "ARMArchName.def" + } + return NULL; +} + +static unsigned GetArchDefaultCPUArch(unsigned ID) { + switch (ID) { + default: + llvm_unreachable("Unknown ARCH kind"); + break; +#define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) \ + case ARM::ID: return ARMBuildAttrs::DEFAULT_CPU_ARCH; +#define ARM_ARCH_ALIAS(NAME, ID) /* empty */ +#include "ARMArchName.def" + } + return 0; +} + namespace { class ARMELFStreamer; @@ -68,36 +111,55 @@ class ARMELFStreamer; class ARMTargetAsmStreamer : public ARMTargetStreamer { formatted_raw_ostream &OS; MCInstPrinter &InstPrinter; - - virtual void emitFnStart(); - virtual void emitFnEnd(); - virtual void emitCantUnwind(); - virtual void emitPersonality(const MCSymbol *Personality); - virtual void emitHandlerData(); - virtual void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0); - virtual void emitPad(int64_t Offset); - virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList, - bool isVector); - - virtual void switchVendor(StringRef Vendor); - virtual void emitAttribute(unsigned Attribute, unsigned Value); - virtual void emitTextAttribute(unsigned Attribute, StringRef String); - virtual void emitFPU(unsigned FPU); - virtual void finishAttributeSection(); + bool IsVerboseAsm; + + void emitFnStart() override; + void emitFnEnd() override; + void emitCantUnwind() override; + void emitPersonality(const MCSymbol *Personality) override; + void emitPersonalityIndex(unsigned Index) override; + void emitHandlerData() override; + void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0) override; + void emitMovSP(unsigned Reg, int64_t Offset = 0) override; + void emitPad(int64_t Offset) override; + void emitRegSave(const SmallVectorImpl<unsigned> &RegList, + bool isVector) override; + void emitUnwindRaw(int64_t Offset, + const SmallVectorImpl<uint8_t> &Opcodes) override; + + void switchVendor(StringRef Vendor) override; + void emitAttribute(unsigned Attribute, unsigned Value) override; + void emitTextAttribute(unsigned Attribute, StringRef String) override; + void emitIntTextAttribute(unsigned Attribute, unsigned IntValue, + StringRef StrinValue) override; + void emitArch(unsigned Arch) override; + void emitObjectArch(unsigned Arch) override; + void emitFPU(unsigned FPU) override; + void emitInst(uint32_t Inst, char Suffix = '\0') override; + void finishAttributeSection() override; + + void AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) override; public: - ARMTargetAsmStreamer(formatted_raw_ostream &OS, MCInstPrinter &InstPrinter); + ARMTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS, + MCInstPrinter &InstPrinter, bool VerboseAsm); }; -ARMTargetAsmStreamer::ARMTargetAsmStreamer(formatted_raw_ostream &OS, - MCInstPrinter &InstPrinter) - : OS(OS), InstPrinter(InstPrinter) {} +ARMTargetAsmStreamer::ARMTargetAsmStreamer(MCStreamer &S, + formatted_raw_ostream &OS, + MCInstPrinter &InstPrinter, + bool VerboseAsm) + : ARMTargetStreamer(S), OS(OS), InstPrinter(InstPrinter), + IsVerboseAsm(VerboseAsm) {} void ARMTargetAsmStreamer::emitFnStart() { OS << "\t.fnstart\n"; } void ARMTargetAsmStreamer::emitFnEnd() { OS << "\t.fnend\n"; } void ARMTargetAsmStreamer::emitCantUnwind() { OS << "\t.cantunwind\n"; } void ARMTargetAsmStreamer::emitPersonality(const MCSymbol *Personality) { OS << "\t.personality " << Personality->getName() << '\n'; } +void ARMTargetAsmStreamer::emitPersonalityIndex(unsigned Index) { + OS << "\t.personalityindex " << Index << '\n'; +} void ARMTargetAsmStreamer::emitHandlerData() { OS << "\t.handlerdata\n"; } void ARMTargetAsmStreamer::emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset) { @@ -109,6 +171,16 @@ void ARMTargetAsmStreamer::emitSetFP(unsigned FpReg, unsigned SpReg, OS << ", #" << Offset; OS << '\n'; } +void ARMTargetAsmStreamer::emitMovSP(unsigned Reg, int64_t Offset) { + assert((Reg != ARM::SP && Reg != ARM::PC) && + "the operand of .movsp cannot be either sp or pc"); + + OS << "\t.movsp\t"; + InstPrinter.printRegName(OS, Reg); + if (Offset) + OS << ", #" << Offset; + OS << '\n'; +} void ARMTargetAsmStreamer::emitPad(int64_t Offset) { OS << "\t.pad\t#" << Offset << '\n'; } @@ -132,22 +204,78 @@ void ARMTargetAsmStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, void ARMTargetAsmStreamer::switchVendor(StringRef Vendor) { } void ARMTargetAsmStreamer::emitAttribute(unsigned Attribute, unsigned Value) { - OS << "\t.eabi_attribute\t" << Attribute << ", " << Twine(Value) << "\n"; + OS << "\t.eabi_attribute\t" << Attribute << ", " << Twine(Value); + if (IsVerboseAsm) { + StringRef Name = ARMBuildAttrs::AttrTypeAsString(Attribute); + if (!Name.empty()) + OS << "\t@ " << Name; + } + OS << "\n"; } void ARMTargetAsmStreamer::emitTextAttribute(unsigned Attribute, StringRef String) { switch (Attribute) { - default: llvm_unreachable("Unsupported Text attribute in ASM Mode"); case ARMBuildAttrs::CPU_name: - OS << "\t.cpu\t" << String.lower() << "\n"; + OS << "\t.cpu\t" << String.lower(); + break; + default: + OS << "\t.eabi_attribute\t" << Attribute << ", \"" << String << "\""; + if (IsVerboseAsm) { + StringRef Name = ARMBuildAttrs::AttrTypeAsString(Attribute); + if (!Name.empty()) + OS << "\t@ " << Name; + } break; } + OS << "\n"; +} +void ARMTargetAsmStreamer::emitIntTextAttribute(unsigned Attribute, + unsigned IntValue, + StringRef StringValue) { + switch (Attribute) { + default: llvm_unreachable("unsupported multi-value attribute in asm mode"); + case ARMBuildAttrs::compatibility: + OS << "\t.eabi_attribute\t" << Attribute << ", " << IntValue; + if (!StringValue.empty()) + OS << ", \"" << StringValue << "\""; + if (IsVerboseAsm) + OS << "\t@ " << ARMBuildAttrs::AttrTypeAsString(Attribute); + break; + } + OS << "\n"; +} +void ARMTargetAsmStreamer::emitArch(unsigned Arch) { + OS << "\t.arch\t" << GetArchName(Arch) << "\n"; +} +void ARMTargetAsmStreamer::emitObjectArch(unsigned Arch) { + OS << "\t.object_arch\t" << GetArchName(Arch) << '\n'; } void ARMTargetAsmStreamer::emitFPU(unsigned FPU) { OS << "\t.fpu\t" << GetFPUName(FPU) << "\n"; } void ARMTargetAsmStreamer::finishAttributeSection() { } +void +ARMTargetAsmStreamer::AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *S) { + OS << "\t.tlsdescseq\t" << S->getSymbol().getName(); +} + +void ARMTargetAsmStreamer::emitInst(uint32_t Inst, char Suffix) { + OS << "\t.inst"; + if (Suffix) + OS << "." << Suffix; + OS << "\t0x" << utohexstr(Inst) << "\n"; +} + +void ARMTargetAsmStreamer::emitUnwindRaw(int64_t Offset, + const SmallVectorImpl<uint8_t> &Opcodes) { + OS << "\t.unwind_raw " << Offset; + for (SmallVectorImpl<uint8_t>::const_iterator OCI = Opcodes.begin(), + OCE = Opcodes.end(); + OCI != OCE; ++OCI) + OS << ", 0x" << utohexstr(*OCI); + OS << '\n'; +} class ARMTargetELFStreamer : public ARMTargetStreamer { private: @@ -158,7 +286,8 @@ private: enum { HiddenAttribute = 0, NumericAttribute, - TextAttribute + TextAttribute, + NumericAndTextAttributes } Type; unsigned Tag; unsigned IntValue; @@ -171,21 +300,12 @@ private: StringRef CurrentVendor; unsigned FPU; + unsigned Arch; + unsigned EmittedArch; SmallVector<AttributeItem, 64> Contents; const MCSection *AttributeSection; - // FIXME: this should be in a more generic place, but - // getULEBSize() is in MCAsmInfo and will be moved to MCDwarf - static size_t getULEBSize(int Value) { - size_t Size = 0; - do { - Value >>= 7; - Size += sizeof(int8_t); // Is this really necessary? - } while (Value); - return Size; - } - AttributeItem *getAttributeItem(unsigned Attribute) { for (size_t i = 0; i < Contents.size(); ++i) if (Contents[i].Tag == Attribute) @@ -199,6 +319,7 @@ private: if (AttributeItem *Item = getAttributeItem(Attribute)) { if (!OverwriteExisting) return; + Item->Type = AttributeItem::NumericAttribute; Item->IntValue = Value; return; } @@ -219,6 +340,7 @@ private: if (AttributeItem *Item = getAttributeItem(Attribute)) { if (!OverwriteExisting) return; + Item->Type = AttributeItem::TextAttribute; Item->StringValue = Value; return; } @@ -233,33 +355,67 @@ private: Contents.push_back(Item); } + void setAttributeItems(unsigned Attribute, unsigned IntValue, + StringRef StringValue, bool OverwriteExisting) { + // Look for existing attribute item + if (AttributeItem *Item = getAttributeItem(Attribute)) { + if (!OverwriteExisting) + return; + Item->Type = AttributeItem::NumericAndTextAttributes; + Item->IntValue = IntValue; + Item->StringValue = StringValue; + return; + } + + // Create new attribute item + AttributeItem Item = { + AttributeItem::NumericAndTextAttributes, + Attribute, + IntValue, + StringValue + }; + Contents.push_back(Item); + } + + void emitArchDefaultAttributes(); void emitFPUDefaultAttributes(); ARMELFStreamer &getStreamer(); - virtual void emitFnStart(); - virtual void emitFnEnd(); - virtual void emitCantUnwind(); - virtual void emitPersonality(const MCSymbol *Personality); - virtual void emitHandlerData(); - virtual void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0); - virtual void emitPad(int64_t Offset); - virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList, - bool isVector); - - virtual void switchVendor(StringRef Vendor); - virtual void emitAttribute(unsigned Attribute, unsigned Value); - virtual void emitTextAttribute(unsigned Attribute, StringRef String); - virtual void emitFPU(unsigned FPU); - virtual void finishAttributeSection(); + void emitFnStart() override; + void emitFnEnd() override; + void emitCantUnwind() override; + void emitPersonality(const MCSymbol *Personality) override; + void emitPersonalityIndex(unsigned Index) override; + void emitHandlerData() override; + void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0) override; + void emitMovSP(unsigned Reg, int64_t Offset = 0) override; + void emitPad(int64_t Offset) override; + void emitRegSave(const SmallVectorImpl<unsigned> &RegList, + bool isVector) override; + void emitUnwindRaw(int64_t Offset, + const SmallVectorImpl<uint8_t> &Opcodes) override; + + void switchVendor(StringRef Vendor) override; + void emitAttribute(unsigned Attribute, unsigned Value) override; + void emitTextAttribute(unsigned Attribute, StringRef String) override; + void emitIntTextAttribute(unsigned Attribute, unsigned IntValue, + StringRef StringValue) override; + void emitArch(unsigned Arch) override; + void emitObjectArch(unsigned Arch) override; + void emitFPU(unsigned FPU) override; + void emitInst(uint32_t Inst, char Suffix = '\0') override; + void finishAttributeSection() override; + + void AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) override; size_t calculateContentSize() const; public: - ARMTargetELFStreamer() - : ARMTargetStreamer(), CurrentVendor("aeabi"), FPU(ARM::INVALID_FPU), - AttributeSection(0) { - } + ARMTargetELFStreamer(MCStreamer &S) + : ARMTargetStreamer(S), CurrentVendor("aeabi"), FPU(ARM::INVALID_FPU), + Arch(ARM::INVALID_ARCH), EmittedArch(ARM::INVALID_ARCH), + AttributeSection(0) {} }; /// Extend the generic ELFStreamer class so that it can emit mapping symbols at @@ -278,30 +434,32 @@ class ARMELFStreamer : public MCELFStreamer { public: friend class ARMTargetELFStreamer; - ARMELFStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, - MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, - bool IsThumb) - : MCELFStreamer(Context, TargetStreamer, TAB, OS, Emitter), - IsThumb(IsThumb), MappingSymbolCounter(0), LastEMS(EMS_None) { + ARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, + MCCodeEmitter *Emitter, bool IsThumb) + : MCELFStreamer(Context, TAB, OS, Emitter), IsThumb(IsThumb), + MappingSymbolCounter(0), LastEMS(EMS_None) { Reset(); } ~ARMELFStreamer() {} - virtual void FinishImpl(); + void FinishImpl() override; // ARM exception handling directives void emitFnStart(); void emitFnEnd(); void emitCantUnwind(); void emitPersonality(const MCSymbol *Per); + void emitPersonalityIndex(unsigned index); void emitHandlerData(); void emitSetFP(unsigned NewFpReg, unsigned NewSpReg, int64_t Offset = 0); + void emitMovSP(unsigned Reg, int64_t Offset = 0); void emitPad(int64_t Offset); void emitRegSave(const SmallVectorImpl<unsigned> &RegList, bool isVector); + void emitUnwindRaw(int64_t Offset, const SmallVectorImpl<uint8_t> &Opcodes); - virtual void ChangeSection(const MCSection *Section, - const MCExpr *Subsection) { + void ChangeSection(const MCSection *Section, + const MCExpr *Subsection) override { // We have to keep track of the mapping symbol state of any sections we // use. Each one should start off as EMS_None, which is provided as the // default constructor by DenseMap::lookup. @@ -314,19 +472,58 @@ public: /// This function is the one used to emit instruction data into the ELF /// streamer. We override it to add the appropriate mapping symbol if /// necessary. - virtual void EmitInstruction(const MCInst& Inst) { + void EmitInstruction(const MCInst& Inst, + const MCSubtargetInfo &STI) override { if (IsThumb) EmitThumbMappingSymbol(); else EmitARMMappingSymbol(); - MCELFStreamer::EmitInstruction(Inst); + MCELFStreamer::EmitInstruction(Inst, STI); + } + + void emitInst(uint32_t Inst, char Suffix) { + unsigned Size; + char Buffer[4]; + const bool LittleEndian = getContext().getAsmInfo()->isLittleEndian(); + + switch (Suffix) { + case '\0': + Size = 4; + + assert(!IsThumb); + EmitARMMappingSymbol(); + for (unsigned II = 0, IE = Size; II != IE; II++) { + const unsigned I = LittleEndian ? (Size - II - 1) : II; + Buffer[Size - II - 1] = uint8_t(Inst >> I * CHAR_BIT); + } + + break; + case 'n': + case 'w': + Size = (Suffix == 'n' ? 2 : 4); + + assert(IsThumb); + EmitThumbMappingSymbol(); + for (unsigned II = 0, IE = Size; II != IE; II = II + 2) { + const unsigned I0 = LittleEndian ? II + 0 : (Size - II - 1); + const unsigned I1 = LittleEndian ? II + 1 : (Size - II - 2); + Buffer[Size - II - 2] = uint8_t(Inst >> I0 * CHAR_BIT); + Buffer[Size - II - 1] = uint8_t(Inst >> I1 * CHAR_BIT); + } + + break; + default: + llvm_unreachable("Invalid Suffix"); + } + + MCELFStreamer::EmitBytes(StringRef(Buffer, Size)); } /// This is one of the functions used to emit data into an ELF section, so the /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if /// necessary. - virtual void EmitBytes(StringRef Data) { + void EmitBytes(StringRef Data) override { EmitDataMappingSymbol(); MCELFStreamer::EmitBytes(Data); } @@ -334,12 +531,12 @@ public: /// This is one of the functions used to emit data into an ELF section, so the /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if /// necessary. - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size) { + void EmitValueImpl(const MCExpr *Value, unsigned Size) override { EmitDataMappingSymbol(); MCELFStreamer::EmitValueImpl(Value, Size); } - virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) { + void EmitAssemblerFlag(MCAssemblerFlag Flag) override { MCELFStreamer::EmitAssemblerFlag(Flag); switch (Flag) { @@ -402,7 +599,7 @@ private: Symbol->setVariableValue(Value); } - void EmitThumbFunc(MCSymbol *Func) { + void EmitThumbFunc(MCSymbol *Func) override { // FIXME: Anything needed here to flag the function as thumb? getAssembler().setIsThumbFunc(Func); @@ -423,6 +620,8 @@ private: void SwitchToExTabSection(const MCSymbol &FnStart); void SwitchToExIdxSection(const MCSymbol &FnStart); + void EmitFixup(const MCExpr *Expr, MCFixupKind Kind); + bool IsThumb; int64_t MappingSymbolCounter; @@ -446,8 +645,7 @@ private: } // end anonymous namespace ARMELFStreamer &ARMTargetELFStreamer::getStreamer() { - ARMELFStreamer *S = static_cast<ARMELFStreamer *>(Streamer); - return *S; + return static_cast<ARMELFStreamer &>(Streamer); } void ARMTargetELFStreamer::emitFnStart() { getStreamer().emitFnStart(); } @@ -456,6 +654,9 @@ void ARMTargetELFStreamer::emitCantUnwind() { getStreamer().emitCantUnwind(); } void ARMTargetELFStreamer::emitPersonality(const MCSymbol *Personality) { getStreamer().emitPersonality(Personality); } +void ARMTargetELFStreamer::emitPersonalityIndex(unsigned Index) { + getStreamer().emitPersonalityIndex(Index); +} void ARMTargetELFStreamer::emitHandlerData() { getStreamer().emitHandlerData(); } @@ -463,6 +664,9 @@ void ARMTargetELFStreamer::emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset) { getStreamer().emitSetFP(FpReg, SpReg, Offset); } +void ARMTargetELFStreamer::emitMovSP(unsigned Reg, int64_t Offset) { + getStreamer().emitMovSP(Reg, Offset); +} void ARMTargetELFStreamer::emitPad(int64_t Offset) { getStreamer().emitPad(Offset); } @@ -470,6 +674,10 @@ void ARMTargetELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, bool isVector) { getStreamer().emitRegSave(RegList, isVector); } +void ARMTargetELFStreamer::emitUnwindRaw(int64_t Offset, + const SmallVectorImpl<uint8_t> &Opcodes) { + getStreamer().emitUnwindRaw(Offset, Opcodes); +} void ARMTargetELFStreamer::switchVendor(StringRef Vendor) { assert(!Vendor.empty() && "Vendor cannot be empty."); @@ -491,6 +699,108 @@ void ARMTargetELFStreamer::emitTextAttribute(unsigned Attribute, StringRef Value) { setAttributeItem(Attribute, Value, /* OverwriteExisting= */ true); } +void ARMTargetELFStreamer::emitIntTextAttribute(unsigned Attribute, + unsigned IntValue, + StringRef StringValue) { + setAttributeItems(Attribute, IntValue, StringValue, + /* OverwriteExisting= */ true); +} +void ARMTargetELFStreamer::emitArch(unsigned Value) { + Arch = Value; +} +void ARMTargetELFStreamer::emitObjectArch(unsigned Value) { + EmittedArch = Value; +} +void ARMTargetELFStreamer::emitArchDefaultAttributes() { + using namespace ARMBuildAttrs; + + setAttributeItem(CPU_name, GetArchDefaultCPUName(Arch), false); + if (EmittedArch == ARM::INVALID_ARCH) + setAttributeItem(CPU_arch, GetArchDefaultCPUArch(Arch), false); + else + setAttributeItem(CPU_arch, GetArchDefaultCPUArch(EmittedArch), false); + + switch (Arch) { + case ARM::ARMV2: + case ARM::ARMV2A: + case ARM::ARMV3: + case ARM::ARMV3M: + case ARM::ARMV4: + case ARM::ARMV5: + setAttributeItem(ARM_ISA_use, Allowed, false); + break; + + case ARM::ARMV4T: + case ARM::ARMV5T: + case ARM::ARMV5TE: + case ARM::ARMV6: + case ARM::ARMV6J: + setAttributeItem(ARM_ISA_use, Allowed, false); + setAttributeItem(THUMB_ISA_use, Allowed, false); + break; + + case ARM::ARMV6T2: + setAttributeItem(ARM_ISA_use, Allowed, false); + setAttributeItem(THUMB_ISA_use, AllowThumb32, false); + break; + + case ARM::ARMV6Z: + case ARM::ARMV6ZK: + setAttributeItem(ARM_ISA_use, Allowed, false); + setAttributeItem(THUMB_ISA_use, Allowed, false); + setAttributeItem(Virtualization_use, AllowTZ, false); + break; + + case ARM::ARMV6M: + setAttributeItem(THUMB_ISA_use, Allowed, false); + break; + + case ARM::ARMV7: + setAttributeItem(THUMB_ISA_use, AllowThumb32, false); + break; + + case ARM::ARMV7A: + setAttributeItem(CPU_arch_profile, ApplicationProfile, false); + setAttributeItem(ARM_ISA_use, Allowed, false); + setAttributeItem(THUMB_ISA_use, AllowThumb32, false); + break; + + case ARM::ARMV7R: + setAttributeItem(CPU_arch_profile, RealTimeProfile, false); + setAttributeItem(ARM_ISA_use, Allowed, false); + setAttributeItem(THUMB_ISA_use, AllowThumb32, false); + break; + + case ARM::ARMV7M: + setAttributeItem(CPU_arch_profile, MicroControllerProfile, false); + setAttributeItem(THUMB_ISA_use, AllowThumb32, false); + break; + + case ARM::ARMV8A: + setAttributeItem(CPU_arch_profile, ApplicationProfile, false); + setAttributeItem(ARM_ISA_use, Allowed, false); + setAttributeItem(THUMB_ISA_use, AllowThumb32, false); + setAttributeItem(MPextension_use, Allowed, false); + setAttributeItem(Virtualization_use, AllowTZVirtualization, false); + break; + + case ARM::IWMMXT: + setAttributeItem(ARM_ISA_use, Allowed, false); + setAttributeItem(THUMB_ISA_use, Allowed, false); + setAttributeItem(WMMX_arch, AllowWMMXv1, false); + break; + + case ARM::IWMMXT2: + setAttributeItem(ARM_ISA_use, Allowed, false); + setAttributeItem(THUMB_ISA_use, Allowed, false); + setAttributeItem(WMMX_arch, AllowWMMXv2, false); + break; + + default: + report_fatal_error("Unknown Arch: " + Twine(Arch)); + break; + } +} void ARMTargetELFStreamer::emitFPU(unsigned Value) { FPU = Value; } @@ -498,43 +808,43 @@ void ARMTargetELFStreamer::emitFPUDefaultAttributes() { switch (FPU) { case ARM::VFP: case ARM::VFPV2: - setAttributeItem(ARMBuildAttrs::VFP_arch, + setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv2, /* OverwriteExisting= */ false); break; case ARM::VFPV3: - setAttributeItem(ARMBuildAttrs::VFP_arch, + setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3A, /* OverwriteExisting= */ false); break; case ARM::VFPV3_D16: - setAttributeItem(ARMBuildAttrs::VFP_arch, + setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3B, /* OverwriteExisting= */ false); break; case ARM::VFPV4: - setAttributeItem(ARMBuildAttrs::VFP_arch, + setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv4A, /* OverwriteExisting= */ false); break; case ARM::VFPV4_D16: - setAttributeItem(ARMBuildAttrs::VFP_arch, + setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv4B, /* OverwriteExisting= */ false); break; case ARM::FP_ARMV8: - setAttributeItem(ARMBuildAttrs::VFP_arch, + setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPARMv8A, /* OverwriteExisting= */ false); break; case ARM::NEON: - setAttributeItem(ARMBuildAttrs::VFP_arch, + setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3A, /* OverwriteExisting= */ false); setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch, @@ -543,7 +853,7 @@ void ARMTargetELFStreamer::emitFPUDefaultAttributes() { break; case ARM::NEON_VFPV4: - setAttributeItem(ARMBuildAttrs::VFP_arch, + setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv4A, /* OverwriteExisting= */ false); setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch, @@ -553,7 +863,7 @@ void ARMTargetELFStreamer::emitFPUDefaultAttributes() { case ARM::NEON_FP_ARMV8: case ARM::CRYPTO_NEON_FP_ARMV8: - setAttributeItem(ARMBuildAttrs::VFP_arch, + setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPARMv8A, /* OverwriteExisting= */ false); setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch, @@ -561,6 +871,9 @@ void ARMTargetELFStreamer::emitFPUDefaultAttributes() { /* OverwriteExisting= */ false); break; + case ARM::SOFTVFP: + break; + default: report_fatal_error("Unknown FPU: " + Twine(FPU)); break; @@ -574,13 +887,18 @@ size_t ARMTargetELFStreamer::calculateContentSize() const { case AttributeItem::HiddenAttribute: break; case AttributeItem::NumericAttribute: - Result += getULEBSize(item.Tag); - Result += getULEBSize(item.IntValue); + Result += getULEB128Size(item.Tag); + Result += getULEB128Size(item.IntValue); break; case AttributeItem::TextAttribute: - Result += getULEBSize(item.Tag); + Result += getULEB128Size(item.Tag); Result += item.StringValue.size() + 1; // string + '\0' break; + case AttributeItem::NumericAndTextAttributes: + Result += getULEB128Size(item.Tag); + Result += getULEB128Size(item.IntValue); + Result += item.StringValue.size() + 1; // string + '\0'; + break; } } return Result; @@ -597,6 +915,9 @@ void ARMTargetELFStreamer::finishAttributeSection() { if (FPU != ARM::INVALID_FPU) emitFPUDefaultAttributes(); + if (Arch != ARM::INVALID_ARCH) + emitArchDefaultAttributes(); + if (Contents.empty()) return; @@ -648,15 +969,27 @@ void ARMTargetELFStreamer::finishAttributeSection() { Streamer.EmitBytes(item.StringValue.upper()); Streamer.EmitIntValue(0, 1); // '\0' break; + case AttributeItem::NumericAndTextAttributes: + Streamer.EmitULEB128IntValue(item.IntValue); + Streamer.EmitBytes(item.StringValue.upper()); + Streamer.EmitIntValue(0, 1); // '\0' + break; } } Contents.clear(); FPU = ARM::INVALID_FPU; } +void +ARMTargetELFStreamer::AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *S) { + getStreamer().EmitFixup(S, FK_Data_4); +} +void ARMTargetELFStreamer::emitInst(uint32_t Inst, char Suffix) { + getStreamer().emitInst(Inst, Suffix); +} void ARMELFStreamer::FinishImpl() { - MCTargetStreamer &TS = getTargetStreamer(); + MCTargetStreamer &TS = *getTargetStreamer(); ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS); ATS.finishAttributeSection(); @@ -691,7 +1024,7 @@ inline void ARMELFStreamer::SwitchToEHSection(const char *Prefix, // Switch to .ARM.extab or .ARM.exidx section SwitchSection(EHSection); - EmitCodeAlignment(4, 0); + EmitCodeAlignment(4); } inline void ARMELFStreamer::SwitchToExTabSection(const MCSymbol &FnStart) { @@ -709,12 +1042,17 @@ inline void ARMELFStreamer::SwitchToExIdxSection(const MCSymbol &FnStart) { SectionKind::getDataRel(), FnStart); } +void ARMELFStreamer::EmitFixup(const MCExpr *Expr, MCFixupKind Kind) { + MCDataFragment *Frag = getOrCreateDataFragment(); + Frag->getFixups().push_back(MCFixup::Create(Frag->getContents().size(), Expr, + Kind)); +} void ARMELFStreamer::Reset() { ExTab = NULL; FnStart = NULL; Personality = NULL; - PersonalityIndex = NUM_PERSONALITY_INDEX; + PersonalityIndex = ARM::EHABI::NUM_PERSONALITY_INDEX; FPReg = ARM::SP; FPOffset = 0; SPOffset = 0; @@ -733,7 +1071,7 @@ void ARMELFStreamer::emitFnStart() { } void ARMELFStreamer::emitFnEnd() { - assert(FnStart && ".fnstart must preceeds .fnend"); + assert(FnStart && ".fnstart must precedes .fnend"); // Emit unwind opcodes if there is no .handlerdata directive if (!ExTab && !CantUnwind) @@ -742,7 +1080,7 @@ void ARMELFStreamer::emitFnEnd() { // Emit the exception index table entry SwitchToExIdxSection(*FnStart); - if (PersonalityIndex < NUM_PERSONALITY_INDEX) + if (PersonalityIndex < ARM::EHABI::NUM_PERSONALITY_INDEX) EmitPersonalityFixup(GetAEABIUnwindPersonalityName(PersonalityIndex)); const MCSymbolRefExpr *FnStartRef = @@ -753,7 +1091,7 @@ void ARMELFStreamer::emitFnEnd() { EmitValue(FnStartRef, 4); if (CantUnwind) { - EmitIntValue(EXIDX_CANTUNWIND, 4); + EmitIntValue(ARM::EHABI::EXIDX_CANTUNWIND, 4); } else if (ExTab) { // Emit a reference to the unwind opcodes in the ".ARM.extab" section. const MCSymbolRefExpr *ExTabEntryRef = @@ -765,7 +1103,7 @@ void ARMELFStreamer::emitFnEnd() { // For the __aeabi_unwind_cpp_pr0, we have to emit the unwind opcodes in // the second word of exception index table entry. The size of the unwind // opcodes should always be 4 bytes. - assert(PersonalityIndex == AEABI_UNWIND_CPP_PR0 && + assert(PersonalityIndex == ARM::EHABI::AEABI_UNWIND_CPP_PR0 && "Compact model must use __aeabi_cpp_unwind_pr0 as personality"); assert(Opcodes.size() == 4u && "Unwind opcode size for __aeabi_cpp_unwind_pr0 must be equal to 4"); @@ -820,7 +1158,7 @@ void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) { // For compact model 0, we have to emit the unwind opcodes in the .ARM.exidx // section. Thus, we don't have to create an entry in the .ARM.extab // section. - if (NoHandlerData && PersonalityIndex == AEABI_UNWIND_CPP_PR0) + if (NoHandlerData && PersonalityIndex == ARM::EHABI::AEABI_UNWIND_CPP_PR0) return; // Switch to .ARM.extab section. @@ -863,6 +1201,11 @@ void ARMELFStreamer::emitPersonality(const MCSymbol *Per) { UnwindOpAsm.setPersonality(Per); } +void ARMELFStreamer::emitPersonalityIndex(unsigned Index) { + assert(Index < ARM::EHABI::NUM_PERSONALITY_INDEX && "invalid index"); + PersonalityIndex = Index; +} + void ARMELFStreamer::emitSetFP(unsigned NewFPReg, unsigned NewSPReg, int64_t Offset) { assert((NewSPReg == ARM::SP || NewSPReg == FPReg) && @@ -877,6 +1220,20 @@ void ARMELFStreamer::emitSetFP(unsigned NewFPReg, unsigned NewSPReg, FPOffset += Offset; } +void ARMELFStreamer::emitMovSP(unsigned Reg, int64_t Offset) { + assert((Reg != ARM::SP && Reg != ARM::PC) && + "the operand of .movsp cannot be either sp or pc"); + assert(FPReg == ARM::SP && "current FP must be SP"); + + FlushPendingOffset(); + + FPReg = Reg; + FPOffset = SPOffset + Offset; + + const MCRegisterInfo *MRI = getContext().getRegisterInfo(); + UnwindOpAsm.EmitSetSP(MRI->getEncodingValue(FPReg)); +} + void ARMELFStreamer::emitPad(int64_t Offset) { // Track the change of the $sp offset SPOffset -= Offset; @@ -916,27 +1273,33 @@ void ARMELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, UnwindOpAsm.EmitRegSave(Mask); } +void ARMELFStreamer::emitUnwindRaw(int64_t Offset, + const SmallVectorImpl<uint8_t> &Opcodes) { + FlushPendingOffset(); + SPOffset = SPOffset - Offset; + UnwindOpAsm.EmitRaw(Opcodes); +} + namespace llvm { MCStreamer *createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, - bool isVerboseAsm, bool useLoc, bool useCFI, + bool isVerboseAsm, bool useCFI, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst) { - ARMTargetAsmStreamer *S = new ARMTargetAsmStreamer(OS, *InstPrint); - - return llvm::createAsmStreamer(Ctx, S, OS, isVerboseAsm, useLoc, useCFI, - useDwarfDirectory, InstPrint, CE, TAB, - ShowInst); + MCStreamer *S = + llvm::createAsmStreamer(Ctx, OS, isVerboseAsm, useCFI, useDwarfDirectory, + InstPrint, CE, TAB, ShowInst); + new ARMTargetAsmStreamer(*S, OS, *InstPrint, isVerboseAsm); + return S; } MCELFStreamer* createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, bool RelaxAll, bool NoExecStack, bool IsThumb) { - ARMTargetELFStreamer *TS = new ARMTargetELFStreamer(); - ARMELFStreamer *S = - new ARMELFStreamer(Context, TS, TAB, OS, Emitter, IsThumb); + ARMELFStreamer *S = new ARMELFStreamer(Context, TAB, OS, Emitter, IsThumb); + new ARMTargetELFStreamer(*S); // FIXME: This should eventually end up somewhere else where more // intelligent flag decisions can be made. For now we are just maintaining // the status quo for ARM and setting EF_ARM_EABI_VER5 as the default. diff --git a/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h b/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h index 0085feb..bfd9e33 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h +++ b/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h @@ -100,15 +100,6 @@ enum Fixups { fixup_t2_movt_hi16, // :upper16: fixup_t2_movw_lo16, // :lower16: - // It is possible to create an "immediate" that happens to be pcrel. - // movw r0, :lower16:Foo-(Bar+8) and movt r0, :upper16:Foo-(Bar+8) - // result in different reloc tags than the above two. - // Needed to support ELF::R_ARM_MOVT_PREL and ELF::R_ARM_MOVW_PREL_NC - fixup_arm_movt_hi16_pcrel, // :upper16: - fixup_arm_movw_lo16_pcrel, // :lower16: - fixup_t2_movt_hi16_pcrel, // :upper16: - fixup_t2_movw_lo16_pcrel, // :lower16: - // Marker LastTargetFixupKind, NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp index ad796e6..b7f96e0 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp @@ -13,18 +13,18 @@ #include "ARMMCAsmInfo.h" #include "llvm/Support/CommandLine.h" +#include "llvm/ADT/Triple.h" using namespace llvm; -cl::opt<bool> -EnableARMEHABI("arm-enable-ehabi", cl::Hidden, - cl::desc("Generate ARM EHABI tables"), - cl::init(false)); - - void ARMMCAsmInfoDarwin::anchor() { } -ARMMCAsmInfoDarwin::ARMMCAsmInfoDarwin() { +ARMMCAsmInfoDarwin::ARMMCAsmInfoDarwin(StringRef TT) { + Triple TheTriple(TT); + if ((TheTriple.getArch() == Triple::armeb) || + (TheTriple.getArch() == Triple::thumbeb)) + IsLittleEndian = false; + Data64bitsDirective = 0; CommentString = "@"; Code16Directive = ".code\t16"; @@ -35,17 +35,23 @@ ARMMCAsmInfoDarwin::ARMMCAsmInfoDarwin() { // Exceptions handling ExceptionsType = ExceptionHandling::SjLj; + + UseIntegratedAssembler = true; } void ARMELFMCAsmInfo::anchor() { } -ARMELFMCAsmInfo::ARMELFMCAsmInfo() { +ARMELFMCAsmInfo::ARMELFMCAsmInfo(StringRef TT) { + Triple TheTriple(TT); + if ((TheTriple.getArch() == Triple::armeb) || + (TheTriple.getArch() == Triple::thumbeb)) + IsLittleEndian = false; + // ".comm align is in bytes but .align is pow-2." AlignmentIsInBytes = false; Data64bitsDirective = 0; CommentString = "@"; - PrivateGlobalPrefix = ".L"; Code16Directive = ".code\t16"; Code32Directive = ".code\t32"; @@ -53,6 +59,48 @@ ARMELFMCAsmInfo::ARMELFMCAsmInfo() { SupportsDebugInformation = true; // Exceptions handling - if (EnableARMEHABI) - ExceptionsType = ExceptionHandling::ARM; + ExceptionsType = ExceptionHandling::ARM; + + // foo(plt) instead of foo@plt + UseParensForSymbolVariant = true; + + UseIntegratedAssembler = true; +} + +void ARMELFMCAsmInfo::setUseIntegratedAssembler(bool Value) { + UseIntegratedAssembler = Value; + if (!UseIntegratedAssembler) { + // gas doesn't handle VFP register names in cfi directives, + // so don't use register names with external assembler. + // See https://sourceware.org/bugzilla/show_bug.cgi?id=16694 + DwarfRegNumForCFI = true; + } +} + +void ARMCOFFMCAsmInfoMicrosoft::anchor() { } + +ARMCOFFMCAsmInfoMicrosoft::ARMCOFFMCAsmInfoMicrosoft() { + AlignmentIsInBytes = false; + + PrivateGlobalPrefix = "$M"; } + +void ARMCOFFMCAsmInfoGNU::anchor() { } + +ARMCOFFMCAsmInfoGNU::ARMCOFFMCAsmInfoGNU() { + AlignmentIsInBytes = false; + + CommentString = "@"; + Code16Directive = ".code\t16"; + Code32Directive = ".code\t32"; + PrivateGlobalPrefix = ".L"; + + HasLEB128 = true; + SupportsDebugInformation = true; + ExceptionsType = ExceptionHandling::None; + UseParensForSymbolVariant = true; + + UseIntegratedAssembler = false; + DwarfRegNumForCFI = true; +} + diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h index e1f716d..beaf6a4 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h +++ b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h @@ -14,21 +14,36 @@ #ifndef LLVM_ARMTARGETASMINFO_H #define LLVM_ARMTARGETASMINFO_H +#include "llvm/MC/MCAsmInfoCOFF.h" #include "llvm/MC/MCAsmInfoDarwin.h" #include "llvm/MC/MCAsmInfoELF.h" namespace llvm { class ARMMCAsmInfoDarwin : public MCAsmInfoDarwin { - virtual void anchor(); + void anchor() override; public: - explicit ARMMCAsmInfoDarwin(); + explicit ARMMCAsmInfoDarwin(StringRef TT); }; class ARMELFMCAsmInfo : public MCAsmInfoELF { - virtual void anchor(); + void anchor() override; public: - explicit ARMELFMCAsmInfo(); + explicit ARMELFMCAsmInfo(StringRef TT); + + void setUseIntegratedAssembler(bool Value) override; + }; + + class ARMCOFFMCAsmInfoMicrosoft : public MCAsmInfoMicrosoft { + void anchor(); + public: + explicit ARMCOFFMCAsmInfoMicrosoft(); + }; + + class ARMCOFFMCAsmInfoGNU : public MCAsmInfoGNUCOFF { + void anchor(); + public: + explicit ARMCOFFMCAsmInfoGNU(); }; } // namespace llvm diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp index 4382d0d..5564e0a 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp @@ -26,6 +26,7 @@ #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -38,27 +39,25 @@ class ARMMCCodeEmitter : public MCCodeEmitter { ARMMCCodeEmitter(const ARMMCCodeEmitter &) LLVM_DELETED_FUNCTION; void operator=(const ARMMCCodeEmitter &) LLVM_DELETED_FUNCTION; const MCInstrInfo &MCII; - const MCSubtargetInfo &STI; const MCContext &CTX; + bool IsLittleEndian; public: - ARMMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti, - MCContext &ctx) - : MCII(mcii), STI(sti), CTX(ctx) { + ARMMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx, bool IsLittle) + : MCII(mcii), CTX(ctx), IsLittleEndian(IsLittle) { } ~ARMMCCodeEmitter() {} - bool isThumb() const { - // FIXME: Can tablegen auto-generate this? + bool isThumb(const MCSubtargetInfo &STI) const { return (STI.getFeatureBits() & ARM::ModeThumb) != 0; } - bool isThumb2() const { - return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) != 0; + bool isThumb2(const MCSubtargetInfo &STI) const { + return isThumb(STI) && (STI.getFeatureBits() & ARM::FeatureThumb2) != 0; } - bool isTargetDarwin() const { + bool isTargetMachO(const MCSubtargetInfo &STI) const { Triple TT(STI.getTargetTriple()); - return TT.isOSDarwin(); + return TT.isOSBinFormatMachO(); } unsigned getMachineSoImmOpValue(unsigned SoImm) const; @@ -66,107 +65,131 @@ public: // getBinaryCodeForInstr - TableGen'erated function for getting the // binary encoding for an instruction. uint64_t getBinaryCodeForInstr(const MCInst &MI, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getMachineOpValue - Return binary encoding of operand. If the machine /// operand requires relocation, record the relocation and return zero. unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getHiLo16ImmOpValue - Return the encoding for the hi / low 16-bit of /// the specified operand. This is used for operands with :lower16: and /// :upper16: prefixes. uint32_t getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; bool EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, unsigned &Reg, unsigned &Imm, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getThumbBLTargetOpValue - Return encoding info for Thumb immediate /// BL branch target. uint32_t getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate /// BLX branch target. uint32_t getThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getThumbBRTargetOpValue - Return encoding info for Thumb branch target. uint32_t getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getThumbBCCTargetOpValue - Return encoding info for Thumb branch target. uint32_t getThumbBCCTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getThumbCBTargetOpValue - Return encoding info for Thumb branch target. uint32_t getThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getBranchTargetOpValue - Return encoding info for 24-bit immediate /// branch target. uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit /// immediate Thumb2 direct branch target. uint32_t getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getARMBranchTargetOpValue - Return encoding info for 24-bit immediate /// branch target. uint32_t getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; uint32_t getARMBLTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; uint32_t getARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getAdrLabelOpValue - Return encoding info for 12-bit immediate /// ADR label target. uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; uint32_t getThumbAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; uint32_t getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' /// operand. uint32_t getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getThumbAddrModeRegRegOpValue - Return encoding for 'reg + reg' operand. uint32_t getThumbAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups)const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getT2AddrModeImm8s4OpValue - Return encoding info for 'reg +/- imm8<<2' /// operand. uint32_t getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getT2AddrModeImm0_1020s4OpValue - Return encoding info for 'reg + imm8<<2' /// operand. uint32_t getT2AddrModeImm0_1020s4OpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getT2Imm8s4OpValue - Return encoding info for '+/- imm8<<2' /// operand. uint32_t getT2Imm8s4OpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getLdStSORegOpValue - Return encoding info for 'reg +/- reg shop imm' /// operand as needed by load/store instructions. uint32_t getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getLdStmModeOpValue - Return encoding for load/store multiple mode. uint32_t getLdStmModeOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { ARM_AM::AMSubMode Mode = (ARM_AM::AMSubMode)MI.getOperand(OpIdx).getImm(); switch (Mode) { default: llvm_unreachable("Unknown addressing sub-mode!"); @@ -192,44 +215,54 @@ public: /// getAddrMode2OpValue - Return encoding for addrmode2 operands. uint32_t getAddrMode2OpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getAddrMode2OffsetOpValue - Return encoding for am2offset operands. uint32_t getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getPostIdxRegOpValue - Return encoding for postidx_reg operands. uint32_t getPostIdxRegOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getAddrMode3OffsetOpValue - Return encoding for am3offset operands. uint32_t getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getAddrMode3OpValue - Return encoding for addrmode3 operands. uint32_t getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getAddrModeThumbSPOpValue - Return encoding info for 'reg +/- imm12' /// operand. uint32_t getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getAddrModeISOpValue - Encode the t_addrmode_is# operands. uint32_t getAddrModeISOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands. uint32_t getAddrModePCOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getAddrMode5OpValue - Return encoding info for 'reg +/- imm8' operand. uint32_t getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getCCOutOpValue - Return encoding of the 's' bit. unsigned getCCOutOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // The operand is either reg0 or CPSR. The 's' bit is encoded as '0' or // '1' respectively. return MI.getOperand(Op).getReg() == ARM::CPSR; @@ -237,8 +270,27 @@ public: /// getSOImmOpValue - Return an encoded 12-bit shifted-immediate value. unsigned getSOImmOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const { - unsigned SoImm = MI.getOperand(Op).getImm(); + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + + const MCOperand &MO = MI.getOperand(Op); + + // We expect MO to be an immediate or an expression, + // if it is an immediate - that's fine, just encode the value. + // Otherwise - create a Fixup. + if (MO.isExpr()) { + const MCExpr *Expr = MO.getExpr(); + // In instruction code this value always encoded as lowest 12 bits, + // so we don't have to perform any specific adjustments. + // Due to requirements of relocatable records we have to use FK_Data_4. + // See ARMELFObjectWriter::ExplicitRelSym and + // ARMELFObjectWriter::GetRelocTypeInner for more details. + MCFixupKind Kind = MCFixupKind(FK_Data_4); + Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); + return 0; + } + + unsigned SoImm = MO.getImm(); int SoImmVal = ARM_AM::getSOImmVal(SoImm); assert(SoImmVal != -1 && "Not a valid so_imm value!"); @@ -253,7 +305,8 @@ public: /// getT2SOImmOpValue - Return an encoded 12-bit shifted-immediate value. unsigned getT2SOImmOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { unsigned SoImm = MI.getOperand(Op).getImm(); unsigned Encoded = ARM_AM::getT2SOImmVal(SoImm); assert(Encoded != ~0U && "Not a Thumb2 so_imm value?"); @@ -261,64 +314,88 @@ public: } unsigned getT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getT2AddrModeImm8OpValue(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getT2AddrModeImm12OffsetOpValue(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; /// getSORegOpValue - Return an encoded so_reg shifted register value. unsigned getSORegRegOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getSORegImmOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getT2SORegOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getNEONVcvtImm32OpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { return 64 - MI.getOperand(Op).getImm(); } unsigned getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getRegisterListOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getAddrMode6AddressOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getAddrMode6OneLane32AddressOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getAddrMode6DupAddressOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getShiftRight8Imm(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getShiftRight16Imm(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getShiftRight32Imm(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getShiftRight64Imm(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getThumbSRImmOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned NEONThumb2DataIPostEncoder(const MCInst &MI, - unsigned EncodedValue) const; + unsigned EncodedValue, + const MCSubtargetInfo &STI) const; unsigned NEONThumb2LoadStorePostEncoder(const MCInst &MI, - unsigned EncodedValue) const; + unsigned EncodedValue, + const MCSubtargetInfo &STI) const; unsigned NEONThumb2DupPostEncoder(const MCInst &MI, - unsigned EncodedValue) const; + unsigned EncodedValue, + const MCSubtargetInfo &STI) const; unsigned NEONThumb2V8PostEncoder(const MCInst &MI, - unsigned EncodedValue) const; + unsigned EncodedValue, + const MCSubtargetInfo &STI) const; unsigned VFPThumb2PostEncoder(const MCInst &MI, - unsigned EncodedValue) const; + unsigned EncodedValue, + const MCSubtargetInfo &STI) const; void EmitByte(unsigned char C, raw_ostream &OS) const { OS << (char)C; @@ -327,30 +404,39 @@ public: void EmitConstant(uint64_t Val, unsigned Size, raw_ostream &OS) const { // Output the constant in little endian byte order. for (unsigned i = 0; i != Size; ++i) { - EmitByte(Val & 255, OS); - Val >>= 8; + unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8; + EmitByte((Val >> Shift) & 0xff, OS); } } void EncodeInstruction(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const override; }; } // end anonymous namespace -MCCodeEmitter *llvm::createARMMCCodeEmitter(const MCInstrInfo &MCII, - const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI, - MCContext &Ctx) { - return new ARMMCCodeEmitter(MCII, STI, Ctx); +MCCodeEmitter *llvm::createARMLEMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + const MCSubtargetInfo &STI, + MCContext &Ctx) { + return new ARMMCCodeEmitter(MCII, Ctx, true); +} + +MCCodeEmitter *llvm::createARMBEMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + const MCSubtargetInfo &STI, + MCContext &Ctx) { + return new ARMMCCodeEmitter(MCII, Ctx, false); } /// NEONThumb2DataIPostEncoder - Post-process encoded NEON data-processing /// instructions, and rewrite them to their Thumb2 form if we are currently in /// Thumb2 mode. unsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI, - unsigned EncodedValue) const { - if (isThumb2()) { + unsigned EncodedValue, + const MCSubtargetInfo &STI) const { + if (isThumb2(STI)) { // NEON Thumb2 data-processsing encodings are very simple: bit 24 is moved // to bit 12 of the high half-word (i.e. bit 28), and bits 27-24 are // set to 1111. @@ -368,8 +454,9 @@ unsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI, /// instructions, and rewrite them to their Thumb2 form if we are currently in /// Thumb2 mode. unsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI, - unsigned EncodedValue) const { - if (isThumb2()) { + unsigned EncodedValue, + const MCSubtargetInfo &STI) const { + if (isThumb2(STI)) { EncodedValue &= 0xF0FFFFFF; EncodedValue |= 0x09000000; } @@ -381,8 +468,9 @@ unsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI, /// instructions, and rewrite them to their Thumb2 form if we are currently in /// Thumb2 mode. unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI, - unsigned EncodedValue) const { - if (isThumb2()) { + unsigned EncodedValue, + const MCSubtargetInfo &STI) const { + if (isThumb2(STI)) { EncodedValue &= 0x00FFFFFF; EncodedValue |= 0xEE000000; } @@ -393,8 +481,9 @@ unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI, /// Post-process encoded NEON v8 instructions, and rewrite them to Thumb2 form /// if we are in Thumb2. unsigned ARMMCCodeEmitter::NEONThumb2V8PostEncoder(const MCInst &MI, - unsigned EncodedValue) const { - if (isThumb2()) { + unsigned EncodedValue, + const MCSubtargetInfo &STI) const { + if (isThumb2(STI)) { EncodedValue |= 0xC000000; // Set bits 27-26 } @@ -404,8 +493,9 @@ unsigned ARMMCCodeEmitter::NEONThumb2V8PostEncoder(const MCInst &MI, /// VFPThumb2PostEncoder - Post-process encoded VFP instructions and rewrite /// them to their Thumb2 form if we are currently in Thumb2 mode. unsigned ARMMCCodeEmitter:: -VFPThumb2PostEncoder(const MCInst &MI, unsigned EncodedValue) const { - if (isThumb2()) { +VFPThumb2PostEncoder(const MCInst &MI, unsigned EncodedValue, + const MCSubtargetInfo &STI) const { + if (isThumb2(STI)) { EncodedValue &= 0x0FFFFFFF; EncodedValue |= 0xE0000000; } @@ -416,7 +506,8 @@ VFPThumb2PostEncoder(const MCInst &MI, unsigned EncodedValue) const { /// operand requires relocation, record the relocation and return zero. unsigned ARMMCCodeEmitter:: getMachineOpValue(const MCInst &MI, const MCOperand &MO, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { if (MO.isReg()) { unsigned Reg = MO.getReg(); unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(Reg); @@ -444,7 +535,8 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, /// getAddrModeImmOpValue - Return encoding info for 'reg +/- imm' operand. bool ARMMCCodeEmitter:: EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, unsigned &Reg, - unsigned &Imm, SmallVectorImpl<MCFixup> &Fixups) const { + unsigned &Imm, SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand &MO = MI.getOperand(OpIdx); const MCOperand &MO1 = MI.getOperand(OpIdx + 1); @@ -473,7 +565,8 @@ EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, unsigned &Reg, /// which is either an immediate or requires a fixup. static uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, unsigned FixupKind, - SmallVectorImpl<MCFixup> &Fixups) { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) { const MCOperand &MO = MI.getOperand(OpIdx); // If the destination is an immediate, we have nothing to do. @@ -509,11 +602,12 @@ static int32_t encodeThumbBLOffset(int32_t offset) { /// getThumbBLTargetOpValue - Return encoding info for immediate branch target. uint32_t ARMMCCodeEmitter:: getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand MO = MI.getOperand(OpIdx); if (MO.isExpr()) return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bl, - Fixups); + Fixups, STI); return encodeThumbBLOffset(MO.getImm()); } @@ -521,43 +615,47 @@ getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx, /// BLX branch target. uint32_t ARMMCCodeEmitter:: getThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand MO = MI.getOperand(OpIdx); if (MO.isExpr()) return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_blx, - Fixups); + Fixups, STI); return encodeThumbBLOffset(MO.getImm()); } /// getThumbBRTargetOpValue - Return encoding info for Thumb branch target. uint32_t ARMMCCodeEmitter:: getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand MO = MI.getOperand(OpIdx); if (MO.isExpr()) return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_br, - Fixups); + Fixups, STI); return (MO.getImm() >> 1); } /// getThumbBCCTargetOpValue - Return encoding info for Thumb branch target. uint32_t ARMMCCodeEmitter:: getThumbBCCTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand MO = MI.getOperand(OpIdx); if (MO.isExpr()) return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bcc, - Fixups); + Fixups, STI); return (MO.getImm() >> 1); } /// getThumbCBTargetOpValue - Return encoding info for Thumb branch target. uint32_t ARMMCCodeEmitter:: getThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand MO = MI.getOperand(OpIdx); if (MO.isExpr()) - return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cb, Fixups); + return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cb, Fixups, STI); return (MO.getImm() >> 1); } @@ -582,27 +680,29 @@ static bool HasConditionalBranch(const MCInst &MI) { /// target. uint32_t ARMMCCodeEmitter:: getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // FIXME: This really, really shouldn't use TargetMachine. We don't want // coupling between MC and TM anywhere we can help it. - if (isThumb2()) + if (isThumb2(STI)) return - ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_condbranch, Fixups); - return getARMBranchTargetOpValue(MI, OpIdx, Fixups); + ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_condbranch, Fixups, STI); + return getARMBranchTargetOpValue(MI, OpIdx, Fixups, STI); } /// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch /// target. uint32_t ARMMCCodeEmitter:: getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand MO = MI.getOperand(OpIdx); if (MO.isExpr()) { if (HasConditionalBranch(MI)) return ::getBranchTargetOpValue(MI, OpIdx, - ARM::fixup_arm_condbranch, Fixups); + ARM::fixup_arm_condbranch, Fixups, STI); return ::getBranchTargetOpValue(MI, OpIdx, - ARM::fixup_arm_uncondbranch, Fixups); + ARM::fixup_arm_uncondbranch, Fixups, STI); } return MO.getImm() >> 2; @@ -610,13 +710,14 @@ getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, uint32_t ARMMCCodeEmitter:: getARMBLTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand MO = MI.getOperand(OpIdx); if (MO.isExpr()) { if (HasConditionalBranch(MI)) return ::getBranchTargetOpValue(MI, OpIdx, - ARM::fixup_arm_condbl, Fixups); - return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_uncondbl, Fixups); + ARM::fixup_arm_condbl, Fixups, STI); + return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_uncondbl, Fixups, STI); } return MO.getImm() >> 2; @@ -624,10 +725,11 @@ getARMBLTargetOpValue(const MCInst &MI, unsigned OpIdx, uint32_t ARMMCCodeEmitter:: getARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand MO = MI.getOperand(OpIdx); if (MO.isExpr()) - return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_blx, Fixups); + return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_blx, Fixups, STI); return MO.getImm() >> 1; } @@ -636,12 +738,13 @@ getARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, /// immediate branch target. uint32_t ARMMCCodeEmitter:: getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { unsigned Val = 0; const MCOperand MO = MI.getOperand(OpIdx); if(MO.isExpr()) - return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_uncondbranch, Fixups); + return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_uncondbranch, Fixups, STI); else Val = MO.getImm() >> 1; @@ -665,11 +768,12 @@ getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, /// ADR label target. uint32_t ARMMCCodeEmitter:: getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand MO = MI.getOperand(OpIdx); if (MO.isExpr()) return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_adr_pcrel_12, - Fixups); + Fixups, STI); int64_t offset = MO.getImm(); uint32_t Val = 0x2000; @@ -705,11 +809,12 @@ getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, /// target. uint32_t ARMMCCodeEmitter:: getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand MO = MI.getOperand(OpIdx); if (MO.isExpr()) return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_adr_pcrel_12, - Fixups); + Fixups, STI); int32_t Val = MO.getImm(); if (Val == INT32_MIN) Val = 0x1000; @@ -724,11 +829,12 @@ getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx, /// target. uint32_t ARMMCCodeEmitter:: getThumbAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand MO = MI.getOperand(OpIdx); if (MO.isExpr()) return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_thumb_adr_pcrel_10, - Fixups); + Fixups, STI); return MO.getImm(); } @@ -736,7 +842,8 @@ getThumbAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, /// operand. uint32_t ARMMCCodeEmitter:: getThumbAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &) const { + SmallVectorImpl<MCFixup> &, + const MCSubtargetInfo &STI) const { // [Rn, Rm] // {5-3} = Rm // {2-0} = Rn @@ -750,7 +857,8 @@ getThumbAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx, /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' operand. uint32_t ARMMCCodeEmitter:: getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // {17-13} = reg // {12} = (U)nsigned (add == '1', sub == '0') // {11-0} = imm12 @@ -767,7 +875,7 @@ getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, isAdd = false ; // 'U' bit is set as part of the fixup. MCFixupKind Kind; - if (isThumb2()) + if (isThumb2(STI)) Kind = MCFixupKind(ARM::fixup_t2_ldst_pcrel_12); else Kind = MCFixupKind(ARM::fixup_arm_ldst_pcrel_12); @@ -787,7 +895,7 @@ getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, Imm12 = Offset; } } else - isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm12, Fixups); + isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm12, Fixups, STI); uint32_t Binary = Imm12 & 0xfff; // Immediate is always encoded as positive. The 'U' bit controls add vs sub. @@ -801,7 +909,8 @@ getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, /// '+/- imm8<<2' operand. uint32_t ARMMCCodeEmitter:: getT2Imm8s4OpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // FIXME: The immediate operand should have already been encoded like this // before ever getting here. The encoder method should just need to combine // the MI operands for the register and the offset into a single @@ -832,7 +941,8 @@ getT2Imm8s4OpValue(const MCInst &MI, unsigned OpIdx, /// 'reg +/- imm8<<2' operand. uint32_t ARMMCCodeEmitter:: getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // {12-9} = reg // {8} = (U)nsigned (add == '1', sub == '0') // {7-0} = imm8 @@ -852,7 +962,7 @@ getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx, ++MCNumCPRelocations; } else - isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups); + isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups, STI); // FIXME: The immediate operand should have already been encoded like this // before ever getting here. The encoder method should just need to combine @@ -872,7 +982,8 @@ getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx, /// 'reg + imm8<<2' operand. uint32_t ARMMCCodeEmitter:: getT2AddrModeImm0_1020s4OpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // {11-8} = reg // {7-0} = imm8 const MCOperand &MO = MI.getOperand(OpIdx); @@ -882,22 +993,10 @@ getT2AddrModeImm0_1020s4OpValue(const MCInst &MI, unsigned OpIdx, return (Reg << 8) | Imm8; } -// FIXME: This routine assumes that a binary -// expression will always result in a PCRel expression -// In reality, its only true if one or more subexpressions -// is itself a PCRel (i.e. "." in asm or some other pcrel construct) -// but this is good enough for now. -static bool EvaluateAsPCRel(const MCExpr *Expr) { - switch (Expr->getKind()) { - default: llvm_unreachable("Unexpected expression type"); - case MCExpr::SymbolRef: return false; - case MCExpr::Binary: return true; - } -} - uint32_t ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // {20-16} = imm{15-12} // {11-0} = imm{11-0} const MCOperand &MO = MI.getOperand(OpIdx); @@ -912,27 +1011,29 @@ ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx, const ARMMCExpr *ARM16Expr = cast<ARMMCExpr>(E); E = ARM16Expr->getSubExpr(); + if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(E)) { + const int64_t Value = MCE->getValue(); + if (Value > UINT32_MAX) + report_fatal_error("constant value truncated (limited to 32-bit)"); + + switch (ARM16Expr->getKind()) { + case ARMMCExpr::VK_ARM_HI16: + return (int32_t(Value) & 0xffff0000) >> 16; + case ARMMCExpr::VK_ARM_LO16: + return (int32_t(Value) & 0x0000ffff); + default: llvm_unreachable("Unsupported ARMFixup"); + } + } + switch (ARM16Expr->getKind()) { default: llvm_unreachable("Unsupported ARMFixup"); case ARMMCExpr::VK_ARM_HI16: - if (!isTargetDarwin() && EvaluateAsPCRel(E)) - Kind = MCFixupKind(isThumb2() - ? ARM::fixup_t2_movt_hi16_pcrel - : ARM::fixup_arm_movt_hi16_pcrel); - else - Kind = MCFixupKind(isThumb2() - ? ARM::fixup_t2_movt_hi16 - : ARM::fixup_arm_movt_hi16); + Kind = MCFixupKind(isThumb2(STI) ? ARM::fixup_t2_movt_hi16 + : ARM::fixup_arm_movt_hi16); break; case ARMMCExpr::VK_ARM_LO16: - if (!isTargetDarwin() && EvaluateAsPCRel(E)) - Kind = MCFixupKind(isThumb2() - ? ARM::fixup_t2_movw_lo16_pcrel - : ARM::fixup_arm_movw_lo16_pcrel); - else - Kind = MCFixupKind(isThumb2() - ? ARM::fixup_t2_movw_lo16 - : ARM::fixup_arm_movw_lo16); + Kind = MCFixupKind(isThumb2(STI) ? ARM::fixup_t2_movw_lo16 + : ARM::fixup_arm_movw_lo16); break; } Fixups.push_back(MCFixup::Create(0, E, Kind, MI.getLoc())); @@ -942,21 +1043,16 @@ ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx, // it's just a plain immediate expression, and those evaluate to // the lower 16 bits of the expression regardless of whether // we have a movt or a movw. - if (!isTargetDarwin() && EvaluateAsPCRel(E)) - Kind = MCFixupKind(isThumb2() - ? ARM::fixup_t2_movw_lo16_pcrel - : ARM::fixup_arm_movw_lo16_pcrel); - else - Kind = MCFixupKind(isThumb2() - ? ARM::fixup_t2_movw_lo16 - : ARM::fixup_arm_movw_lo16); + Kind = MCFixupKind(isThumb2(STI) ? ARM::fixup_t2_movw_lo16 + : ARM::fixup_arm_movw_lo16); Fixups.push_back(MCFixup::Create(0, E, Kind, MI.getLoc())); return 0; } uint32_t ARMMCCodeEmitter:: getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand &MO = MI.getOperand(OpIdx); const MCOperand &MO1 = MI.getOperand(OpIdx+1); const MCOperand &MO2 = MI.getOperand(OpIdx+2); @@ -989,21 +1085,23 @@ getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx, uint32_t ARMMCCodeEmitter:: getAddrMode2OpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // {17-14} Rn // {13} 1 == imm12, 0 == Rm // {12} isAdd // {11-0} imm12/Rm const MCOperand &MO = MI.getOperand(OpIdx); unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); - uint32_t Binary = getAddrMode2OffsetOpValue(MI, OpIdx + 1, Fixups); + uint32_t Binary = getAddrMode2OffsetOpValue(MI, OpIdx + 1, Fixups, STI); Binary |= Rn << 14; return Binary; } uint32_t ARMMCCodeEmitter:: getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // {13} 1 == imm12, 0 == Rm // {12} isAdd // {11-0} imm12/Rm @@ -1025,7 +1123,8 @@ getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx, uint32_t ARMMCCodeEmitter:: getPostIdxRegOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // {4} isAdd // {3-0} Rm const MCOperand &MO = MI.getOperand(OpIdx); @@ -1036,7 +1135,8 @@ getPostIdxRegOpValue(const MCInst &MI, unsigned OpIdx, uint32_t ARMMCCodeEmitter:: getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // {9} 1 == imm8, 0 == Rm // {8} isAdd // {7-4} imm7_4/zero @@ -1055,7 +1155,8 @@ getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx, uint32_t ARMMCCodeEmitter:: getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // {13} 1 == imm8, 0 == Rm // {12-9} Rn // {8} isAdd @@ -1091,7 +1192,8 @@ getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx, /// getAddrModeThumbSPOpValue - Encode the t_addrmode_sp operands. uint32_t ARMMCCodeEmitter:: getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // [SP, #imm] // {7-0} = imm8 const MCOperand &MO1 = MI.getOperand(OpIdx + 1); @@ -1106,7 +1208,8 @@ getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx, /// getAddrModeISOpValue - Encode the t_addrmode_is# operands. uint32_t ARMMCCodeEmitter:: getAddrModeISOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // [Rn, #imm] // {7-3} = imm5 // {2-0} = Rn @@ -1120,17 +1223,19 @@ getAddrModeISOpValue(const MCInst &MI, unsigned OpIdx, /// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands. uint32_t ARMMCCodeEmitter:: getAddrModePCOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand MO = MI.getOperand(OpIdx); if (MO.isExpr()) - return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cp, Fixups); + return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cp, Fixups, STI); return (MO.getImm() >> 2); } /// getAddrMode5OpValue - Return encoding info for 'reg +/- imm10' operand. uint32_t ARMMCCodeEmitter:: getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // {12-9} = reg // {8} = (U)nsigned (add == '1', sub == '0') // {7-0} = imm8 @@ -1146,7 +1251,7 @@ getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, assert(MO.isExpr() && "Unexpected machine operand type!"); const MCExpr *Expr = MO.getExpr(); MCFixupKind Kind; - if (isThumb2()) + if (isThumb2(STI)) Kind = MCFixupKind(ARM::fixup_t2_pcrel_10); else Kind = MCFixupKind(ARM::fixup_arm_pcrel_10); @@ -1154,7 +1259,7 @@ getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, ++MCNumCPRelocations; } else { - EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups); + EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups, STI); isAdd = ARM_AM::getAM5Op(Imm8) == ARM_AM::add; } @@ -1168,7 +1273,8 @@ getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, unsigned ARMMCCodeEmitter:: getSORegRegOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // Sub-operands are [reg, reg, imm]. The first register is Rm, the reg to be // shifted. The second is Rs, the amount to shift by, and the third specifies // the type of the shift. @@ -1215,7 +1321,8 @@ getSORegRegOpValue(const MCInst &MI, unsigned OpIdx, unsigned ARMMCCodeEmitter:: getSORegImmOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // Sub-operands are [reg, imm]. The first register is Rm, the reg to be // shifted. The second is the amount to shift by. // @@ -1261,7 +1368,8 @@ getSORegImmOpValue(const MCInst &MI, unsigned OpIdx, unsigned ARMMCCodeEmitter:: getT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand &MO1 = MI.getOperand(OpNum); const MCOperand &MO2 = MI.getOperand(OpNum+1); const MCOperand &MO3 = MI.getOperand(OpNum+2); @@ -1279,7 +1387,8 @@ getT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum, unsigned ARMMCCodeEmitter:: getT2AddrModeImm8OpValue(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand &MO1 = MI.getOperand(OpNum); const MCOperand &MO2 = MI.getOperand(OpNum+1); @@ -1300,7 +1409,8 @@ getT2AddrModeImm8OpValue(const MCInst &MI, unsigned OpNum, unsigned ARMMCCodeEmitter:: getT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand &MO1 = MI.getOperand(OpNum); // FIXME: Needs fixup support. @@ -1316,7 +1426,8 @@ getT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum, unsigned ARMMCCodeEmitter:: getT2AddrModeImm12OffsetOpValue(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand &MO1 = MI.getOperand(OpNum); // FIXME: Needs fixup support. @@ -1332,7 +1443,8 @@ getT2AddrModeImm12OffsetOpValue(const MCInst &MI, unsigned OpNum, unsigned ARMMCCodeEmitter:: getT2SORegOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // Sub-operands are [reg, imm]. The first register is Rm, the reg to be // shifted. The second is the amount to shift by. // @@ -1374,7 +1486,8 @@ getT2SORegOpValue(const MCInst &MI, unsigned OpIdx, unsigned ARMMCCodeEmitter:: getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // 10 bits. lower 5 bits are are the lsb of the mask, high five bits are the // msb of the mask. const MCOperand &MO = MI.getOperand(Op); @@ -1387,7 +1500,8 @@ getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op, unsigned ARMMCCodeEmitter:: getRegisterListOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // VLDM/VSTM: // {12-8} = Vd // {7-0} = Number of registers @@ -1423,7 +1537,8 @@ getRegisterListOpValue(const MCInst &MI, unsigned Op, /// with the alignment operand. unsigned ARMMCCodeEmitter:: getAddrMode6AddressOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand &Reg = MI.getOperand(Op); const MCOperand &Imm = MI.getOperand(Op + 1); @@ -1446,7 +1561,8 @@ getAddrMode6AddressOpValue(const MCInst &MI, unsigned Op, /// along with the alignment operand for use in VST1 and VLD1 with size 32. unsigned ARMMCCodeEmitter:: getAddrMode6OneLane32AddressOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand &Reg = MI.getOperand(Op); const MCOperand &Imm = MI.getOperand(Op + 1); @@ -1472,7 +1588,8 @@ getAddrMode6OneLane32AddressOpValue(const MCInst &MI, unsigned Op, /// different for VLD4-dup. unsigned ARMMCCodeEmitter:: getAddrMode6DupAddressOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand &Reg = MI.getOperand(Op); const MCOperand &Imm = MI.getOperand(Op + 1); @@ -1492,7 +1609,8 @@ getAddrMode6DupAddressOpValue(const MCInst &MI, unsigned Op, unsigned ARMMCCodeEmitter:: getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand &MO = MI.getOperand(Op); if (MO.getReg() == 0) return 0x0D; return CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); @@ -1500,31 +1618,36 @@ getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op, unsigned ARMMCCodeEmitter:: getShiftRight8Imm(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { return 8 - MI.getOperand(Op).getImm(); } unsigned ARMMCCodeEmitter:: getShiftRight16Imm(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { return 16 - MI.getOperand(Op).getImm(); } unsigned ARMMCCodeEmitter:: getShiftRight32Imm(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { return 32 - MI.getOperand(Op).getImm(); } unsigned ARMMCCodeEmitter:: getShiftRight64Imm(const MCInst &MI, unsigned Op, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { return 64 - MI.getOperand(Op).getImm(); } void ARMMCCodeEmitter:: EncodeInstruction(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // Pseudo instructions don't get encoded. const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); uint64_t TSFlags = Desc.TSFlags; @@ -1537,10 +1660,10 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, else llvm_unreachable("Unexpected instruction size!"); - uint32_t Binary = getBinaryCodeForInstr(MI, Fixups); + uint32_t Binary = getBinaryCodeForInstr(MI, Fixups, STI); // Thumb 32-bit wide instructions need to emit the high order halfword // first. - if (isThumb() && Size == 4) { + if (isThumb(STI) && Size == 4) { EmitConstant(Binary >> 16, 2, OS); EmitConstant(Binary & 0xffff, 2, OS); } else diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCExpr.h b/lib/Target/ARM/MCTargetDesc/ARMMCExpr.h index cd4067a..d819139 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCExpr.h +++ b/lib/Target/ARM/MCTargetDesc/ARMMCExpr.h @@ -56,16 +56,16 @@ public: /// @} - void PrintImpl(raw_ostream &OS) const; + void PrintImpl(raw_ostream &OS) const override; bool EvaluateAsRelocatableImpl(MCValue &Res, - const MCAsmLayout *Layout) const; - void AddValueSymbols(MCAssembler *) const; - const MCSection *FindAssociatedSection() const { + const MCAsmLayout *Layout) const override; + void AddValueSymbols(MCAssembler *) const override; + const MCSection *FindAssociatedSection() const override { return getSubExpr()->FindAssociatedSection(); } // There are no TLS ARMMCExprs at the moment. - void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {} + void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {} static bool classof(const MCExpr *E) { return E->getKind() == MCExpr::Target; diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp index a99de0e..949a3d5 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp @@ -89,14 +89,16 @@ std::string ARM_MC::ParseARMTriple(StringRef TT, StringRef CPU) { unsigned Idx = 0; // FIXME: Enhance Triple helper class to extract ARM version. - bool isThumb = false; + bool isThumb = triple.getArch() == Triple::thumb || + triple.getArch() == Triple::thumbeb; if (Len >= 5 && TT.substr(0, 4) == "armv") Idx = 4; - else if (Len >= 6 && TT.substr(0, 5) == "thumb") { - isThumb = true; - if (Len >= 7 && TT[5] == 'v') - Idx = 6; - } + else if (Len >= 7 && TT.substr(0, 6) == "armebv") + Idx = 6; + else if (Len >= 7 && TT.substr(0, 6) == "thumbv") + Idx = 6; + else if (Len >= 9 && TT.substr(0, 8) == "thumbebv") + Idx = 8; bool NoCPU = CPU == "generic" || CPU.empty(); std::string ARMArchFeature; @@ -129,9 +131,9 @@ std::string ARM_MC::ParseARMTriple(StringRef TT, StringRef CPU) { ARMArchFeature = "+v7"; } else if (Len >= Idx+2 && TT[Idx+1] == 's') { if (NoCPU) - // v7s: FeatureNEON, FeatureDB, FeatureDSPThumb2, FeatureT2XtPk + // v7s: FeatureNEON, FeatureDB, FeatureDSPThumb2, FeatureHasRAS // Swift - ARMArchFeature = "+v7,+swift,+neon,+db,+t2dsp,+t2xtpk"; + ARMArchFeature = "+v7,+swift,+neon,+db,+t2dsp,+ras"; else // Use CPU to figure out the exact features. ARMArchFeature = "+v7"; @@ -215,10 +217,37 @@ static MCRegisterInfo *createARMMCRegisterInfo(StringRef Triple) { static MCAsmInfo *createARMMCAsmInfo(const MCRegisterInfo &MRI, StringRef TT) { Triple TheTriple(TT); - if (TheTriple.isOSDarwin()) - return new ARMMCAsmInfoDarwin(); + MCAsmInfo *MAI; + switch (TheTriple.getOS()) { + case llvm::Triple::Darwin: + case llvm::Triple::IOS: + case llvm::Triple::MacOSX: + MAI = new ARMMCAsmInfoDarwin(TT); + break; + case llvm::Triple::Win32: + switch (TheTriple.getEnvironment()) { + case llvm::Triple::Itanium: + MAI = new ARMCOFFMCAsmInfoGNU(); + break; + case llvm::Triple::MSVC: + MAI = new ARMCOFFMCAsmInfoMicrosoft(); + break; + default: + llvm_unreachable("invalid environment"); + } + break; + default: + if (TheTriple.isOSBinFormatMachO()) + MAI = new ARMMCAsmInfoDarwin(TT); + else + MAI = new ARMELFMCAsmInfo(TT); + break; + } + + unsigned Reg = MRI.getDwarfRegNum(ARM::SP, true); + MAI->addInitialFrameState(MCCFIInstruction::createDefCfa(0, Reg, 0)); - return new ARMELFMCAsmInfo(); + return MAI; } static MCCodeGenInfo *createARMMCCodeGenInfo(StringRef TT, Reloc::Model RM, @@ -239,12 +268,16 @@ static MCStreamer *createMCStreamer(const Target &T, StringRef TT, MCContext &Ctx, MCAsmBackend &MAB, raw_ostream &OS, MCCodeEmitter *Emitter, + const MCSubtargetInfo &STI, bool RelaxAll, bool NoExecStack) { Triple TheTriple(TT); - if (TheTriple.isOSDarwin()) - return createMachOStreamer(Ctx, MAB, OS, Emitter, false); + if (TheTriple.isOSBinFormatMachO()) { + MCStreamer *S = createMachOStreamer(Ctx, MAB, OS, Emitter, false); + new ARMTargetStreamer(*S); + return S; + } if (TheTriple.isOSWindows()) { llvm_unreachable("ARM does not support Windows COFF format"); @@ -268,7 +301,7 @@ static MCInstPrinter *createARMMCInstPrinter(const Target &T, static MCRelocationInfo *createARMMCRelocationInfo(StringRef TT, MCContext &Ctx) { Triple TheTriple(TT); - if (TheTriple.isEnvironmentMachO()) + if (TheTriple.isOSBinFormatMachO()) return createARMMachORelocationInfo(Ctx); // Default to the stock relocation info. return llvm::createMCRelocationInfo(TT, Ctx); @@ -280,14 +313,14 @@ class ARMMCInstrAnalysis : public MCInstrAnalysis { public: ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} - virtual bool isUnconditionalBranch(const MCInst &Inst) const { + bool isUnconditionalBranch(const MCInst &Inst) const override { // BCCs with the "always" predicate are unconditional branches. if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL) return true; return MCInstrAnalysis::isUnconditionalBranch(Inst); } - virtual bool isConditionalBranch(const MCInst &Inst) const { + bool isConditionalBranch(const MCInst &Inst) const override { // BCCs with the "always" predicate are unconditional branches. if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL) return false; @@ -295,7 +328,7 @@ public: } bool evaluateBranch(const MCInst &Inst, uint64_t Addr, - uint64_t Size, uint64_t &Target) const { + uint64_t Size, uint64_t &Target) const override { // We only handle PCRel branches for now. if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType!=MCOI::OPERAND_PCREL) return false; @@ -316,56 +349,94 @@ static MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) { // Force static initialization. extern "C" void LLVMInitializeARMTargetMC() { // Register the MC asm info. - RegisterMCAsmInfoFn A(TheARMTarget, createARMMCAsmInfo); - RegisterMCAsmInfoFn B(TheThumbTarget, createARMMCAsmInfo); + RegisterMCAsmInfoFn X(TheARMLETarget, createARMMCAsmInfo); + RegisterMCAsmInfoFn Y(TheARMBETarget, createARMMCAsmInfo); + RegisterMCAsmInfoFn A(TheThumbLETarget, createARMMCAsmInfo); + RegisterMCAsmInfoFn B(TheThumbBETarget, createARMMCAsmInfo); // Register the MC codegen info. - TargetRegistry::RegisterMCCodeGenInfo(TheARMTarget, createARMMCCodeGenInfo); - TargetRegistry::RegisterMCCodeGenInfo(TheThumbTarget, createARMMCCodeGenInfo); + TargetRegistry::RegisterMCCodeGenInfo(TheARMLETarget, createARMMCCodeGenInfo); + TargetRegistry::RegisterMCCodeGenInfo(TheARMBETarget, createARMMCCodeGenInfo); + TargetRegistry::RegisterMCCodeGenInfo(TheThumbLETarget, createARMMCCodeGenInfo); + TargetRegistry::RegisterMCCodeGenInfo(TheThumbBETarget, createARMMCCodeGenInfo); // Register the MC instruction info. - TargetRegistry::RegisterMCInstrInfo(TheARMTarget, createARMMCInstrInfo); - TargetRegistry::RegisterMCInstrInfo(TheThumbTarget, createARMMCInstrInfo); + TargetRegistry::RegisterMCInstrInfo(TheARMLETarget, createARMMCInstrInfo); + TargetRegistry::RegisterMCInstrInfo(TheARMBETarget, createARMMCInstrInfo); + TargetRegistry::RegisterMCInstrInfo(TheThumbLETarget, createARMMCInstrInfo); + TargetRegistry::RegisterMCInstrInfo(TheThumbBETarget, createARMMCInstrInfo); // Register the MC register info. - TargetRegistry::RegisterMCRegInfo(TheARMTarget, createARMMCRegisterInfo); - TargetRegistry::RegisterMCRegInfo(TheThumbTarget, createARMMCRegisterInfo); + TargetRegistry::RegisterMCRegInfo(TheARMLETarget, createARMMCRegisterInfo); + TargetRegistry::RegisterMCRegInfo(TheARMBETarget, createARMMCRegisterInfo); + TargetRegistry::RegisterMCRegInfo(TheThumbLETarget, createARMMCRegisterInfo); + TargetRegistry::RegisterMCRegInfo(TheThumbBETarget, createARMMCRegisterInfo); // Register the MC subtarget info. - TargetRegistry::RegisterMCSubtargetInfo(TheARMTarget, + TargetRegistry::RegisterMCSubtargetInfo(TheARMLETarget, ARM_MC::createARMMCSubtargetInfo); - TargetRegistry::RegisterMCSubtargetInfo(TheThumbTarget, + TargetRegistry::RegisterMCSubtargetInfo(TheARMBETarget, + ARM_MC::createARMMCSubtargetInfo); + TargetRegistry::RegisterMCSubtargetInfo(TheThumbLETarget, + ARM_MC::createARMMCSubtargetInfo); + TargetRegistry::RegisterMCSubtargetInfo(TheThumbBETarget, ARM_MC::createARMMCSubtargetInfo); // Register the MC instruction analyzer. - TargetRegistry::RegisterMCInstrAnalysis(TheARMTarget, + TargetRegistry::RegisterMCInstrAnalysis(TheARMLETarget, + createARMMCInstrAnalysis); + TargetRegistry::RegisterMCInstrAnalysis(TheARMBETarget, createARMMCInstrAnalysis); - TargetRegistry::RegisterMCInstrAnalysis(TheThumbTarget, + TargetRegistry::RegisterMCInstrAnalysis(TheThumbLETarget, + createARMMCInstrAnalysis); + TargetRegistry::RegisterMCInstrAnalysis(TheThumbBETarget, createARMMCInstrAnalysis); // Register the MC Code Emitter - TargetRegistry::RegisterMCCodeEmitter(TheARMTarget, createARMMCCodeEmitter); - TargetRegistry::RegisterMCCodeEmitter(TheThumbTarget, createARMMCCodeEmitter); + TargetRegistry::RegisterMCCodeEmitter(TheARMLETarget, + createARMLEMCCodeEmitter); + TargetRegistry::RegisterMCCodeEmitter(TheARMBETarget, + createARMBEMCCodeEmitter); + TargetRegistry::RegisterMCCodeEmitter(TheThumbLETarget, + createARMLEMCCodeEmitter); + TargetRegistry::RegisterMCCodeEmitter(TheThumbBETarget, + createARMBEMCCodeEmitter); // Register the asm backend. - TargetRegistry::RegisterMCAsmBackend(TheARMTarget, createARMAsmBackend); - TargetRegistry::RegisterMCAsmBackend(TheThumbTarget, createARMAsmBackend); + TargetRegistry::RegisterMCAsmBackend(TheARMLETarget, createARMLEAsmBackend); + TargetRegistry::RegisterMCAsmBackend(TheARMBETarget, createARMBEAsmBackend); + TargetRegistry::RegisterMCAsmBackend(TheThumbLETarget, + createThumbLEAsmBackend); + TargetRegistry::RegisterMCAsmBackend(TheThumbBETarget, + createThumbBEAsmBackend); // Register the object streamer. - TargetRegistry::RegisterMCObjectStreamer(TheARMTarget, createMCStreamer); - TargetRegistry::RegisterMCObjectStreamer(TheThumbTarget, createMCStreamer); + TargetRegistry::RegisterMCObjectStreamer(TheARMLETarget, createMCStreamer); + TargetRegistry::RegisterMCObjectStreamer(TheARMBETarget, createMCStreamer); + TargetRegistry::RegisterMCObjectStreamer(TheThumbLETarget, createMCStreamer); + TargetRegistry::RegisterMCObjectStreamer(TheThumbBETarget, createMCStreamer); // Register the asm streamer. - TargetRegistry::RegisterAsmStreamer(TheARMTarget, createMCAsmStreamer); - TargetRegistry::RegisterAsmStreamer(TheThumbTarget, createMCAsmStreamer); + TargetRegistry::RegisterAsmStreamer(TheARMLETarget, createMCAsmStreamer); + TargetRegistry::RegisterAsmStreamer(TheARMBETarget, createMCAsmStreamer); + TargetRegistry::RegisterAsmStreamer(TheThumbLETarget, createMCAsmStreamer); + TargetRegistry::RegisterAsmStreamer(TheThumbBETarget, createMCAsmStreamer); // Register the MCInstPrinter. - TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter); - TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(TheARMLETarget, createARMMCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(TheARMBETarget, createARMMCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(TheThumbLETarget, + createARMMCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(TheThumbBETarget, + createARMMCInstPrinter); // Register the MC relocation info. - TargetRegistry::RegisterMCRelocationInfo(TheARMTarget, + TargetRegistry::RegisterMCRelocationInfo(TheARMLETarget, + createARMMCRelocationInfo); + TargetRegistry::RegisterMCRelocationInfo(TheARMBETarget, + createARMMCRelocationInfo); + TargetRegistry::RegisterMCRelocationInfo(TheThumbLETarget, createARMMCRelocationInfo); - TargetRegistry::RegisterMCRelocationInfo(TheThumbTarget, + TargetRegistry::RegisterMCRelocationInfo(TheThumbBETarget, createARMMCRelocationInfo); } diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h index 959be8b..e81876f 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h +++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h @@ -33,7 +33,8 @@ class StringRef; class Target; class raw_ostream; -extern Target TheARMTarget, TheThumbTarget; +extern Target TheARMLETarget, TheThumbLETarget; +extern Target TheARMBETarget, TheThumbBETarget; namespace ARM_MC { std::string ParseARMTriple(StringRef TT, StringRef CPU); @@ -46,22 +47,41 @@ namespace ARM_MC { } MCStreamer *createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, - bool isVerboseAsm, bool useLoc, bool useCFI, + bool isVerboseAsm, bool useCFI, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst); -MCCodeEmitter *createARMMCCodeEmitter(const MCInstrInfo &MCII, - const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI, - MCContext &Ctx); +MCCodeEmitter *createARMLEMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + const MCSubtargetInfo &STI, + MCContext &Ctx); + +MCCodeEmitter *createARMBEMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + const MCSubtargetInfo &STI, + MCContext &Ctx); MCAsmBackend *createARMAsmBackend(const Target &T, const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU, + bool IsLittleEndian); + +MCAsmBackend *createARMLEAsmBackend(const Target &T, const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU); + +MCAsmBackend *createARMBEAsmBackend(const Target &T, const MCRegisterInfo &MRI, StringRef TT, StringRef CPU); +MCAsmBackend *createThumbLEAsmBackend(const Target &T, const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU); + +MCAsmBackend *createThumbBEAsmBackend(const Target &T, const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU); + /// createARMELFObjectWriter - Construct an ELF Mach-O object writer. MCObjectWriter *createARMELFObjectWriter(raw_ostream &OS, - uint8_t OSABI); + uint8_t OSABI, + bool IsLittleEndian); /// createARMMachObjectWriter - Construct an ARM Mach-O object writer. MCObjectWriter *createARMMachObjectWriter(raw_ostream &OS, diff --git a/lib/Target/ARM/MCTargetDesc/ARMMachORelocationInfo.cpp b/lib/Target/ARM/MCTargetDesc/ARMMachORelocationInfo.cpp index 807c948..d4b00e6 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMachORelocationInfo.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMachORelocationInfo.cpp @@ -9,10 +9,10 @@ #include "MCTargetDesc/ARMMCTargetDesc.h" #include "ARMMCExpr.h" +#include "llvm-c/Disassembler.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCRelocationInfo.h" -#include "llvm-c/Disassembler.h" using namespace llvm; using namespace object; @@ -23,7 +23,7 @@ public: ARMMachORelocationInfo(MCContext &Ctx) : MCRelocationInfo(Ctx) {} const MCExpr *createExprForCAPIVariantKind(const MCExpr *SubExpr, - unsigned VariantKind) { + unsigned VariantKind) override { switch(VariantKind) { case LLVMDisassembler_VariantKind_ARM_HI16: return ARMMCExpr::CreateUpper16(SubExpr, Ctx); diff --git a/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp b/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp index 1f681ba..3bf5cf1 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp @@ -56,7 +56,7 @@ public: void RecordRelocation(MachObjectWriter *Writer, const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, - MCValue Target, uint64_t &FixedValue); + MCValue Target, uint64_t &FixedValue) override; }; } @@ -82,10 +82,14 @@ static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType, Log2Size = llvm::Log2_32(8); return true; - // Handle 24-bit branch kinds. + // These fixups are expected to always be resolvable at assembly time and + // have no relocations supported. case ARM::fixup_arm_ldst_pcrel_12: case ARM::fixup_arm_pcrel_10: case ARM::fixup_arm_adr_pcrel_12: + return false; + + // Handle 24-bit branch kinds. case ARM::fixup_arm_condbranch: case ARM::fixup_arm_uncondbranch: case ARM::fixup_arm_uncondbl: @@ -119,23 +123,19 @@ static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType, // 0 - arm instructions // 1 - thumb instructions case ARM::fixup_arm_movt_hi16: - case ARM::fixup_arm_movt_hi16_pcrel: RelocType = unsigned(MachO::ARM_RELOC_HALF); Log2Size = 1; return true; case ARM::fixup_t2_movt_hi16: - case ARM::fixup_t2_movt_hi16_pcrel: RelocType = unsigned(MachO::ARM_RELOC_HALF); Log2Size = 3; return true; case ARM::fixup_arm_movw_lo16: - case ARM::fixup_arm_movw_lo16_pcrel: RelocType = unsigned(MachO::ARM_RELOC_HALF); Log2Size = 0; return true; case ARM::fixup_t2_movw_lo16: - case ARM::fixup_t2_movw_lo16_pcrel: RelocType = unsigned(MachO::ARM_RELOC_HALF); Log2Size = 2; return true; @@ -202,7 +202,6 @@ RecordARMScatteredHalfRelocation(MachObjectWriter *Writer, switch ((unsigned)Fixup.getKind()) { default: break; case ARM::fixup_arm_movt_hi16: - case ARM::fixup_arm_movt_hi16_pcrel: MovtBit = 1; // The thumb bit shouldn't be set in the 'other-half' bit of the // relocation, but it will be set in FixedValue if the base symbol @@ -211,13 +210,11 @@ RecordARMScatteredHalfRelocation(MachObjectWriter *Writer, FixedValue &= 0xfffffffe; break; case ARM::fixup_t2_movt_hi16: - case ARM::fixup_t2_movt_hi16_pcrel: if (A_SD->getFlags() & SF_ThumbFunc) FixedValue &= 0xfffffffe; MovtBit = 1; // Fallthrough case ARM::fixup_t2_movw_lo16: - case ARM::fixup_t2_movw_lo16_pcrel: ThumbBit = 1; break; } @@ -461,15 +458,11 @@ void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer, switch ((unsigned)Fixup.getKind()) { default: break; case ARM::fixup_arm_movw_lo16: - case ARM::fixup_arm_movw_lo16_pcrel: case ARM::fixup_t2_movw_lo16: - case ARM::fixup_t2_movw_lo16_pcrel: Value = (FixedValue >> 16) & 0xffff; break; case ARM::fixup_arm_movt_hi16: - case ARM::fixup_arm_movt_hi16_pcrel: case ARM::fixup_t2_movt_hi16: - case ARM::fixup_t2_movt_hi16_pcrel: Value = FixedValue & 0xffff; break; } diff --git a/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp b/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp new file mode 100644 index 0000000..fdc0ed7 --- /dev/null +++ b/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp @@ -0,0 +1,248 @@ +//===- ARMTargetStreamer.cpp - ARMTargetStreamer class --*- C++ -*---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the ARMTargetStreamer class. +// +//===----------------------------------------------------------------------===// +#include "llvm/ADT/MapVector.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCStreamer.h" + +using namespace llvm; + +namespace { +// A class to keep track of assembler-generated constant pools that are use to +// implement the ldr-pseudo. +class ConstantPool { + typedef SmallVector<std::pair<MCSymbol *, const MCExpr *>, 4> EntryVecTy; + EntryVecTy Entries; + +public: + // Initialize a new empty constant pool + ConstantPool() {} + + // Add a new entry to the constant pool in the next slot. + // \param Value is the new entry to put in the constant pool. + // + // \returns a MCExpr that references the newly inserted value + const MCExpr *addEntry(const MCExpr *Value, MCContext &Context); + + // Emit the contents of the constant pool using the provided streamer. + void emitEntries(MCStreamer &Streamer); + + // Return true if the constant pool is empty + bool empty(); +}; +} + +namespace llvm { +class AssemblerConstantPools { + // Map type used to keep track of per-Section constant pools used by the + // ldr-pseudo opcode. The map associates a section to its constant pool. The + // constant pool is a vector of (label, value) pairs. When the ldr + // pseudo is parsed we insert a new (label, value) pair into the constant pool + // for the current section and add MCSymbolRefExpr to the new label as + // an opcode to the ldr. After we have parsed all the user input we + // output the (label, value) pairs in each constant pool at the end of the + // section. + // + // We use the MapVector for the map type to ensure stable iteration of + // the sections at the end of the parse. We need to iterate over the + // sections in a stable order to ensure that we have print the + // constant pools in a deterministic order when printing an assembly + // file. + typedef MapVector<const MCSection *, ConstantPool> ConstantPoolMapTy; + ConstantPoolMapTy ConstantPools; + +public: + AssemblerConstantPools() {} + ~AssemblerConstantPools() {} + + void emitAll(MCStreamer &Streamer); + void emitForCurrentSection(MCStreamer &Streamer); + const MCExpr *addEntry(MCStreamer &Streamer, const MCExpr *Expr); + +private: + ConstantPool *getConstantPool(const MCSection *Section); + ConstantPool &getOrCreateConstantPool(const MCSection *Section); +}; +} + +// +// ConstantPool implementation +// +// Emit the contents of the constant pool using the provided streamer. +void ConstantPool::emitEntries(MCStreamer &Streamer) { + if (Entries.empty()) + return; + Streamer.EmitCodeAlignment(4); // align to 4-byte address + Streamer.EmitDataRegion(MCDR_DataRegion); + for (EntryVecTy::const_iterator I = Entries.begin(), E = Entries.end(); + I != E; ++I) { + Streamer.EmitLabel(I->first); + Streamer.EmitValue(I->second, 4); + } + Streamer.EmitDataRegion(MCDR_DataRegionEnd); + Entries.clear(); +} + +const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context) { + MCSymbol *CPEntryLabel = Context.CreateTempSymbol(); + + Entries.push_back(std::make_pair(CPEntryLabel, Value)); + return MCSymbolRefExpr::Create(CPEntryLabel, Context); +} + +bool ConstantPool::empty() { return Entries.empty(); } + +// +// AssemblerConstantPools implementation +// +ConstantPool * +AssemblerConstantPools::getConstantPool(const MCSection *Section) { + ConstantPoolMapTy::iterator CP = ConstantPools.find(Section); + if (CP == ConstantPools.end()) + return 0; + + return &CP->second; +} + +ConstantPool & +AssemblerConstantPools::getOrCreateConstantPool(const MCSection *Section) { + return ConstantPools[Section]; +} + +static void emitConstantPool(MCStreamer &Streamer, const MCSection *Section, + ConstantPool &CP) { + if (!CP.empty()) { + Streamer.SwitchSection(Section); + CP.emitEntries(Streamer); + } +} + +void AssemblerConstantPools::emitAll(MCStreamer &Streamer) { + // Dump contents of assembler constant pools. + for (ConstantPoolMapTy::iterator CPI = ConstantPools.begin(), + CPE = ConstantPools.end(); + CPI != CPE; ++CPI) { + const MCSection *Section = CPI->first; + ConstantPool &CP = CPI->second; + + emitConstantPool(Streamer, Section, CP); + } +} + +void AssemblerConstantPools::emitForCurrentSection(MCStreamer &Streamer) { + const MCSection *Section = Streamer.getCurrentSection().first; + if (ConstantPool *CP = getConstantPool(Section)) { + emitConstantPool(Streamer, Section, *CP); + } +} + +const MCExpr *AssemblerConstantPools::addEntry(MCStreamer &Streamer, + const MCExpr *Expr) { + const MCSection *Section = Streamer.getCurrentSection().first; + return getOrCreateConstantPool(Section).addEntry(Expr, Streamer.getContext()); +} + +// +// ARMTargetStreamer Implemenation +// +ARMTargetStreamer::ARMTargetStreamer(MCStreamer &S) + : MCTargetStreamer(S), ConstantPools(new AssemblerConstantPools()) {} + +ARMTargetStreamer::~ARMTargetStreamer() {} + +// The constant pool handling is shared by all ARMTargetStreamer +// implementations. +const MCExpr *ARMTargetStreamer::addConstantPoolEntry(const MCExpr *Expr) { + return ConstantPools->addEntry(Streamer, Expr); +} + +void ARMTargetStreamer::emitCurrentConstantPool() { + ConstantPools->emitForCurrentSection(Streamer); +} + +// finish() - write out any non-empty assembler constant pools. +void ARMTargetStreamer::finish() { ConstantPools->emitAll(Streamer); } + +// The remaining callbacks should be handled separately by each +// streamer. +void ARMTargetStreamer::emitFnStart() { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::emitFnEnd() { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::emitCantUnwind() { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::emitPersonality(const MCSymbol *Personality) { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::emitPersonalityIndex(unsigned Index) { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::emitHandlerData() { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::emitSetFP(unsigned FpReg, unsigned SpReg, + int64_t Offset) { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::emitMovSP(unsigned Reg, int64_t Offset) { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::emitPad(int64_t Offset) { + llvm_unreachable("unimplemented"); +} +void +ARMTargetStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, + bool isVector) { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::emitUnwindRaw( + int64_t StackOffset, const SmallVectorImpl<uint8_t> &Opcodes) { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::switchVendor(StringRef Vendor) { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::emitTextAttribute(unsigned Attribute, + StringRef String) { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::emitIntTextAttribute(unsigned Attribute, + unsigned IntValue, + StringRef StringValue) { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::emitArch(unsigned Arch) { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::emitObjectArch(unsigned Arch) { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::emitFPU(unsigned FPU) { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::finishAttributeSection() { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::emitInst(uint32_t Inst, char Suffix) { + llvm_unreachable("unimplemented"); +} +void ARMTargetStreamer::AnnotateTLSDescriptorSequence( + const MCSymbolRefExpr *SRE) { + llvm_unreachable("unimplemented"); +} diff --git a/lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h b/lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h deleted file mode 100644 index fa4add6..0000000 --- a/lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h +++ /dev/null @@ -1,125 +0,0 @@ -//===-- ARMUnwindOp.h - ARM Unwind Opcodes ----------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the constants for the ARM unwind opcodes and exception -// handling table entry kinds. -// -//===----------------------------------------------------------------------===// - -#ifndef ARM_UNWIND_OP_H -#define ARM_UNWIND_OP_H - -namespace llvm { - - /// ARM exception handling table entry kinds - enum ARMEHTEntryKind { - EHT_GENERIC = 0x00, - EHT_COMPACT = 0x80 - }; - - enum { - /// Special entry for the function never unwind - EXIDX_CANTUNWIND = 0x1 - }; - - /// ARM-defined frame unwinding opcodes - enum ARMUnwindOpcodes { - // Format: 00xxxxxx - // Purpose: vsp = vsp + ((x << 2) + 4) - UNWIND_OPCODE_INC_VSP = 0x00, - - // Format: 01xxxxxx - // Purpose: vsp = vsp - ((x << 2) + 4) - UNWIND_OPCODE_DEC_VSP = 0x40, - - // Format: 10000000 00000000 - // Purpose: refuse to unwind - UNWIND_OPCODE_REFUSE = 0x8000, - - // Format: 1000xxxx xxxxxxxx - // Purpose: pop r[15:12], r[11:4] - // Constraint: x != 0 - UNWIND_OPCODE_POP_REG_MASK_R4 = 0x8000, - - // Format: 1001xxxx - // Purpose: vsp = r[x] - // Constraint: x != 13 && x != 15 - UNWIND_OPCODE_SET_VSP = 0x90, - - // Format: 10100xxx - // Purpose: pop r[(4+x):4] - UNWIND_OPCODE_POP_REG_RANGE_R4 = 0xa0, - - // Format: 10101xxx - // Purpose: pop r14, r[(4+x):4] - UNWIND_OPCODE_POP_REG_RANGE_R4_R14 = 0xa8, - - // Format: 10110000 - // Purpose: finish - UNWIND_OPCODE_FINISH = 0xb0, - - // Format: 10110001 0000xxxx - // Purpose: pop r[3:0] - // Constraint: x != 0 - UNWIND_OPCODE_POP_REG_MASK = 0xb100, - - // Format: 10110010 x(uleb128) - // Purpose: vsp = vsp + ((x << 2) + 0x204) - UNWIND_OPCODE_INC_VSP_ULEB128 = 0xb2, - - // Format: 10110011 xxxxyyyy - // Purpose: pop d[(x+y):x] - UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDX = 0xb300, - - // Format: 10111xxx - // Purpose: pop d[(8+x):8] - UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDX_D8 = 0xb8, - - // Format: 11000xxx - // Purpose: pop wR[(10+x):10] - UNWIND_OPCODE_POP_WIRELESS_MMX_REG_RANGE_WR10 = 0xc0, - - // Format: 11000110 xxxxyyyy - // Purpose: pop wR[(x+y):x] - UNWIND_OPCODE_POP_WIRELESS_MMX_REG_RANGE = 0xc600, - - // Format: 11000111 0000xxxx - // Purpose: pop wCGR[3:0] - // Constraint: x != 0 - UNWIND_OPCODE_POP_WIRELESS_MMX_REG_MASK = 0xc700, - - // Format: 11001000 xxxxyyyy - // Purpose: pop d[(16+x+y):(16+x)] - UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD_D16 = 0xc800, - - // Format: 11001001 xxxxyyyy - // Purpose: pop d[(x+y):x] - UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD = 0xc900, - - // Format: 11010xxx - // Purpose: pop d[(8+x):8] - UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD_D8 = 0xd0 - }; - - /// ARM-defined Personality Routine Index - enum ARMPersonalityRoutineIndex { - // To make the exception handling table become more compact, ARM defined - // several personality routines in EHABI. There are 3 different - // personality routines in ARM EHABI currently. It is possible to have 16 - // pre-defined personality routines at most. - AEABI_UNWIND_CPP_PR0 = 0, - AEABI_UNWIND_CPP_PR1 = 1, - AEABI_UNWIND_CPP_PR2 = 2, - - NUM_PERSONALITY_INDEX - }; - -} - -#endif // ARM_UNWIND_OP_H diff --git a/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp b/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp index c943370..593fe34 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp @@ -13,8 +13,7 @@ //===----------------------------------------------------------------------===// #include "ARMUnwindOpAsm.h" - -#include "ARMUnwindOp.h" +#include "llvm/Support/ARMEHABI.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/LEB128.h" @@ -50,14 +49,15 @@ namespace { /// Emit the personality index prefix. inline void EmitPersonalityIndex(unsigned PI) { - assert(PI < NUM_PERSONALITY_INDEX && "Invalid personality prefix"); - EmitByte(EHT_COMPACT | PI); + assert(PI < ARM::EHABI::NUM_PERSONALITY_INDEX && + "Invalid personality prefix"); + EmitByte(ARM::EHABI::EHT_COMPACT | PI); } /// Fill the rest of bytes with FINISH opcode. inline void FillFinishOpcode() { while (Pos < Vec.size()) - EmitByte(UNWIND_OPCODE_FINISH); + EmitByte(ARM::EHABI::UNWIND_OPCODE_FINISH); } }; } @@ -85,22 +85,22 @@ void UnwindOpcodeAssembler::EmitRegSave(uint32_t RegSave) { uint32_t UnmaskedReg = RegSave & 0xfff0u & (~Mask); if (UnmaskedReg == 0u) { // Pop r[4 : (4 + n)] - EmitInt8(UNWIND_OPCODE_POP_REG_RANGE_R4 | Range); + EmitInt8(ARM::EHABI::UNWIND_OPCODE_POP_REG_RANGE_R4 | Range); RegSave &= 0x000fu; } else if (UnmaskedReg == (1u << 14)) { // Pop r[14] + r[4 : (4 + n)] - EmitInt8(UNWIND_OPCODE_POP_REG_RANGE_R4_R14 | Range); + EmitInt8(ARM::EHABI::UNWIND_OPCODE_POP_REG_RANGE_R4_R14 | Range); RegSave &= 0x000fu; } } // Two bytes opcode to save register r15-r4 if ((RegSave & 0xfff0u) != 0) - EmitInt16(UNWIND_OPCODE_POP_REG_MASK_R4 | (RegSave >> 4)); + EmitInt16(ARM::EHABI::UNWIND_OPCODE_POP_REG_MASK_R4 | (RegSave >> 4)); // Opcode to save register r3-r0 if ((RegSave & 0x000fu) != 0) - EmitInt16(UNWIND_OPCODE_POP_REG_MASK | (RegSave & 0x000fu)); + EmitInt16(ARM::EHABI::UNWIND_OPCODE_POP_REG_MASK | (RegSave & 0x000fu)); } /// Emit unwind opcodes for .vsave directives @@ -125,7 +125,7 @@ void UnwindOpcodeAssembler::EmitVFPRegSave(uint32_t VFPRegSave) { Bit >>= 1; } - EmitInt16(UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD_D16 | + EmitInt16(ARM::EHABI::UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD_D16 | ((i - 16) << 4) | Range); } @@ -147,34 +147,36 @@ void UnwindOpcodeAssembler::EmitVFPRegSave(uint32_t VFPRegSave) { Bit >>= 1; } - EmitInt16(UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD | (i << 4) | Range); + EmitInt16(ARM::EHABI::UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD | (i << 4) | + Range); } } /// Emit unwind opcodes to copy address from source register to $sp. void UnwindOpcodeAssembler::EmitSetSP(uint16_t Reg) { - EmitInt8(UNWIND_OPCODE_SET_VSP | Reg); + EmitInt8(ARM::EHABI::UNWIND_OPCODE_SET_VSP | Reg); } /// Emit unwind opcodes to add $sp with an offset. void UnwindOpcodeAssembler::EmitSPOffset(int64_t Offset) { if (Offset > 0x200) { uint8_t Buff[16]; - Buff[0] = UNWIND_OPCODE_INC_VSP_ULEB128; + Buff[0] = ARM::EHABI::UNWIND_OPCODE_INC_VSP_ULEB128; size_t ULEBSize = encodeULEB128((Offset - 0x204) >> 2, Buff + 1); EmitBytes(Buff, ULEBSize + 1); } else if (Offset > 0) { if (Offset > 0x100) { - EmitInt8(UNWIND_OPCODE_INC_VSP | 0x3fu); + EmitInt8(ARM::EHABI::UNWIND_OPCODE_INC_VSP | 0x3fu); Offset -= 0x100; } - EmitInt8(UNWIND_OPCODE_INC_VSP | static_cast<uint8_t>((Offset - 4) >> 2)); + EmitInt8(ARM::EHABI::UNWIND_OPCODE_INC_VSP | + static_cast<uint8_t>((Offset - 4) >> 2)); } else if (Offset < 0) { while (Offset < -0x100) { - EmitInt8(UNWIND_OPCODE_DEC_VSP | 0x3fu); + EmitInt8(ARM::EHABI::UNWIND_OPCODE_DEC_VSP | 0x3fu); Offset += 0x100; } - EmitInt8(UNWIND_OPCODE_DEC_VSP | + EmitInt8(ARM::EHABI::UNWIND_OPCODE_DEC_VSP | static_cast<uint8_t>(((-Offset) - 4) >> 2)); } } @@ -186,20 +188,23 @@ void UnwindOpcodeAssembler::Finalize(unsigned &PersonalityIndex, if (HasPersonality) { // User-specifed personality routine: [ SIZE , OP1 , OP2 , ... ] - PersonalityIndex = NUM_PERSONALITY_INDEX; + PersonalityIndex = ARM::EHABI::NUM_PERSONALITY_INDEX; size_t TotalSize = Ops.size() + 1; size_t RoundUpSize = (TotalSize + 3) / 4 * 4; Result.resize(RoundUpSize); OpStreamer.EmitSize(RoundUpSize); } else { - if (Ops.size() <= 3) { + // If no personalityindex is specified, select ane + if (PersonalityIndex == ARM::EHABI::NUM_PERSONALITY_INDEX) + PersonalityIndex = (Ops.size() <= 3) ? ARM::EHABI::AEABI_UNWIND_CPP_PR0 + : ARM::EHABI::AEABI_UNWIND_CPP_PR1; + if (PersonalityIndex == ARM::EHABI::AEABI_UNWIND_CPP_PR0) { // __aeabi_unwind_cpp_pr0: [ 0x80 , OP1 , OP2 , OP3 ] - PersonalityIndex = AEABI_UNWIND_CPP_PR0; + assert(Ops.size() <= 3 && "too many opcodes for __aeabi_unwind_cpp_pr0"); Result.resize(4); OpStreamer.EmitPersonalityIndex(PersonalityIndex); } else { - // __aeabi_unwind_cpp_pr1: [ 0x81 , SIZE , OP1 , OP2 , ... ] - PersonalityIndex = AEABI_UNWIND_CPP_PR1; + // __aeabi_unwind_cpp_pr{1,2}: [ {0x81,0x82} , SIZE , OP1 , OP2 , ... ] size_t TotalSize = Ops.size() + 2; size_t RoundUpSize = (TotalSize + 3) / 4 * 4; Result.resize(RoundUpSize); diff --git a/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h b/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h index ac67c6e..cd58759 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h +++ b/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h @@ -15,10 +15,8 @@ #ifndef ARM_UNWIND_OP_ASM_H #define ARM_UNWIND_OP_ASM_H -#include "ARMUnwindOp.h" - #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" +#include "llvm/Support/ARMEHABI.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -45,7 +43,7 @@ public: HasPersonality = 0; } - /// Set the personality index + /// Set the personality void setPersonality(const MCSymbol *Per) { HasPersonality = 1; } @@ -62,6 +60,12 @@ public: /// Emit unwind opcodes to add $sp with an offset. void EmitSPOffset(int64_t Offset); + /// Emit unwind raw opcodes + void EmitRaw(const SmallVectorImpl<uint8_t> &Opcodes) { + Ops.insert(Ops.end(), Opcodes.begin(), Opcodes.end()); + OpBegins.push_back(OpBegins.back() + Opcodes.size()); + } + /// Finalize the unwind opcode sequence for EmitBytes() void Finalize(unsigned &PersonalityIndex, SmallVectorImpl<uint8_t> &Result); diff --git a/lib/Target/ARM/MCTargetDesc/Android.mk b/lib/Target/ARM/MCTargetDesc/Android.mk index faa482c..074d29e 100644 --- a/lib/Target/ARM/MCTargetDesc/Android.mk +++ b/lib/Target/ARM/MCTargetDesc/Android.mk @@ -16,6 +16,7 @@ arm_mc_desc_SRC_FILES := \ ARMMCTargetDesc.cpp \ ARMMachObjectWriter.cpp \ ARMMachORelocationInfo.cpp \ + ARMTargetStreamer.cpp \ ARMUnwindOpAsm.cpp # For the host @@ -40,6 +41,7 @@ include $(BUILD_HOST_STATIC_LIBRARY) # For the device only # ===================================================== +ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS)) include $(CLEAR_VARS) include $(CLEAR_TBLGEN_VARS) @@ -56,3 +58,4 @@ include $(LLVM_DEVICE_BUILD_MK) include $(LLVM_TBLGEN_RULES_MK) include $(LLVM_GEN_INTRINSICS_MK) include $(BUILD_STATIC_LIBRARY) +endif diff --git a/lib/Target/ARM/MCTargetDesc/CMakeLists.txt b/lib/Target/ARM/MCTargetDesc/CMakeLists.txt index bab59f4..06812d4 100644 --- a/lib/Target/ARM/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/ARM/MCTargetDesc/CMakeLists.txt @@ -8,10 +8,7 @@ add_llvm_library(LLVMARMDesc ARMMCTargetDesc.cpp ARMMachObjectWriter.cpp ARMELFObjectWriter.cpp + ARMTargetStreamer.cpp ARMUnwindOpAsm.cpp ARMMachORelocationInfo.cpp ) -add_dependencies(LLVMARMDesc ARMCommonTableGen) - -# Hack: we need to include 'main' target directory to grab private headers -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/..) |