diff options
Diffstat (limited to 'lib/Target/ARM/MCTargetDesc')
23 files changed, 1926 insertions, 982 deletions
diff --git a/lib/Target/ARM/MCTargetDesc/ARMArchName.def b/lib/Target/ARM/MCTargetDesc/ARMArchName.def new file mode 100644 index 000000000000..9f007a035a88 --- /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 000000000000..34b9fc126ff1 --- /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 5615b808fc11..7acd9cc4d302 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); @@ -251,8 +306,36 @@ bool ARMAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { return true; } +static uint32_t swapHalfWords(uint32_t Value, bool IsLittleEndian) { + if (IsLittleEndian) { + // Note that the halfwords are stored high first and low second in thumb; + // so we need to swap the fixup value here to map properly. + uint32_t Swapped = (Value & 0xFFFF0000) >> 16; + Swapped |= (Value & 0x0000FFFF) << 16; + return Swapped; + } + else + return Value; +} + +static uint32_t joinHalfWords(uint32_t FirstHalf, uint32_t SecondHalf, + bool IsLittleEndian) { + uint32_t Value; + + if (IsLittleEndian) { + Value = (SecondHalf & 0xFFFF) << 16; + Value |= (FirstHalf & 0xFFFF); + } else { + Value = (SecondHalf & 0xFFFF); + Value |= (FirstHalf & 0xFFFF) << 16; + } + + return Value; +} + static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, - MCContext *Ctx = NULL) { + bool IsPCRel, MCContext *Ctx, + bool IsLittleEndian) { unsigned Kind = Fixup.getKind(); switch (Kind) { default: @@ -261,12 +344,15 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, case FK_Data_2: case FK_Data_4: return Value; + case FK_SecRel_2: + return Value; + case FK_SecRel_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 +361,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; @@ -290,9 +374,7 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, // inst{14-12} = Mid3; // inst{7-0} = Lo8; Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8); - uint64_t swapped = (Value & 0xFFFF0000) >> 16; - swapped |= (Value & 0x0000FFFF) << 16; - return swapped; + return swapHalfWords(Value, IsLittleEndian); } case ARM::fixup_arm_ldst_pcrel_12: // ARM PC-relative values are offset by 8. @@ -312,11 +394,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, // Same addressing mode as fixup_arm_pcrel_10, // but with 16-bit halfwords swapped. - if (Kind == ARM::fixup_t2_ldst_pcrel_12) { - uint64_t swapped = (Value & 0xFFFF0000) >> 16; - swapped |= (Value & 0x0000FFFF) << 16; - return swapped; - } + if (Kind == ARM::fixup_t2_ldst_pcrel_12) + return swapHalfWords(Value, IsLittleEndian); return Value; } @@ -349,9 +428,7 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, out |= (Value & 0x700) << 4; out |= (Value & 0x0FF); - uint64_t swapped = (out & 0xFFFF0000) >> 16; - swapped |= (out & 0x0000FFFF) << 16; - return swapped; + return swapHalfWords(out, IsLittleEndian); } case ARM::fixup_arm_condbranch: @@ -361,6 +438,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; @@ -379,9 +459,7 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, out |= (Value & 0x1FF800) << 5; // imm6 field out |= (Value & 0x0007FF); // imm11 field - uint64_t swapped = (out & 0xFFFF0000) >> 16; - swapped |= (out & 0x0000FFFF) << 16; - return swapped; + return swapHalfWords(out, IsLittleEndian); } case ARM::fixup_t2_condbranch: { Value = Value - 4; @@ -394,70 +472,64 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, out |= (Value & 0x1F800) << 5; // imm6 field out |= (Value & 0x007FF); // imm11 field - uint32_t swapped = (out & 0xFFFF0000) >> 16; - swapped |= (out & 0x0000FFFF) << 16; - return swapped; + return swapHalfWords(out, IsLittleEndian); } 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 FirstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10Bits); + uint32_t SecondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) | + (uint16_t)imm11Bits); + return joinHalfWords(FirstHalf, SecondHalf, IsLittleEndian); } 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 FirstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10HBits); + uint32_t SecondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) | + ((uint16_t)imm10LBits) << 1); + return joinHalfWords(FirstHalf, SecondHalf, IsLittleEndian); } case ARM::fixup_arm_thumb_cp: // Offset by 4, and don't encode the low two bits. Two bytes of that @@ -509,11 +581,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, // Same addressing mode as fixup_arm_pcrel_10, but with 16-bit halfwords // swapped. - if (Kind == ARM::fixup_t2_pcrel_10) { - uint32_t swapped = (Value & 0xFFFF0000) >> 16; - swapped |= (Value & 0x0000FFFF) << 16; - return swapped; - } + if (Kind == ARM::fixup_t2_pcrel_10) + return swapHalfWords(Value, IsLittleEndian); return Value; } @@ -524,7 +593,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 +610,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(); + const 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 +630,8 @@ 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(), + IsLittleEndian); } /// getFixupKindNumBytes - The number of bytes the fixup may change. @@ -595,33 +672,101 @@ 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; + + case FK_SecRel_2: + return 2; + case FK_SecRel_4: + 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, IsLittleEndian); 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()); + assert((Offset + FullSizeBytes) <= DataSize && "Invalid fixup size!"); + assert(NumBytes <= FullSizeBytes && "Invalid fixup size!"); + } + // 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 { +// FIXME: This should be in a separate file. +class ARMWinCOFFAsmBackend : public ARMAsmBackend { +public: + ARMWinCOFFAsmBackend(const Target &T, const StringRef &Triple) + : ARMAsmBackend(T, Triple, true) { } + MCObjectWriter *createObjectWriter(raw_ostream &OS) const override { + return createARMWinCOFFObjectWriter(OS, /*Is64Bit=*/false); + } +}; // FIXME: This should be in a separate file. // ELF is an ELF of course... @@ -629,11 +774,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 +788,28 @@ 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()) { + switch (TheTriple.getObjectFormat()) { + default: llvm_unreachable("unsupported object format"); + case Triple::MachO: { MachO::CPUSubTypeARM CS = StringSwitch<MachO::CPUSubTypeARM>(TheTriple.getArchName()) .Cases("armv4t", "thumbv4t", MachO::CPU_SUBTYPE_ARM_V4T) @@ -673,7 +817,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) @@ -681,13 +824,37 @@ MCAsmBackend *llvm::createARMAsmBackend(const Target &T, return new DarwinARMAsmBackend(T, TT, CS); } + case Triple::COFF: + assert(TheTriple.isOSWindows() && "non-Windows ARM COFF is not supported"); + return new ARMWinCOFFAsmBackend(T, TT); + case Triple::ELF: + assert(TheTriple.isOSBinFormatELF() && "using ELF for non-ELF target"); + uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS()); + return new ELFARMAsmBackend(T, TT, OSABI, isLittle); + } +} -#if 0 - // FIXME: Introduce yet another checker but assert(0). - if (TheTriple.isOSBinFormatCOFF()) - assert(0 && "Windows not supported on ARM"); -#endif +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); +} - uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS()); - return new ELFARMAsmBackend(T, TT, OSABI); +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 af939fc19129..1686d76b8e1b 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,41 @@ 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 = 0x3f, + + /// MO_DLLIMPORT - On a symbol operand, this represents that the reference + /// to the symbol is for an import stub. This is used for DLL import + /// storage class indication on Windows. + MO_DLLIMPORT = 0x40, + + /// 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 f98bbd204c7a..a86601b6bb5b 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp @@ -34,14 +34,11 @@ 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(const MCSymbolData &SD, + unsigned Type) const override; }; } @@ -52,91 +49,19 @@ 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(const MCSymbolData &SD, + 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 +69,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 = Target.getAccessVariant(); unsigned Type = 0; if (IsPCRel) { @@ -166,19 +88,25 @@ 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; + case MCSymbolRefExpr::VK_GOTPCREL: + Type = ELF::R_ARM_GOT_PREL; + break; } break; 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 +122,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,24 +154,27 @@ 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_GOTPCREL: + Type = ELF::R_ARM_GOT_PREL; + break; case MCSymbolRefExpr::VK_ARM_TARGET1: Type = ELF::R_ARM_TARGET1; break; @@ -250,6 +184,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 +229,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 471897de5c1c..7b5d8b01dfe6 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" @@ -30,6 +30,7 @@ #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSection.h" @@ -37,16 +38,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(); } @@ -58,7 +63,46 @@ static const char *GetFPUName(unsigned ID) { #define ARM_FPU_NAME(NAME, ID) case ARM::ID: return NAME; #include "ARMFPUName.def" } - return NULL; + return nullptr; +} + +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 nullptr; +} + +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 nullptr; +} + +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 { @@ -68,36 +112,56 @@ 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; + void emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) 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 +173,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 +206,82 @@ 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::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) { + OS << "\t.thumb_set\t" << *Symbol << ", " << *Value << '\n'; +} + +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 +292,8 @@ private: enum { HiddenAttribute = 0, NumericAttribute, - TextAttribute + TextAttribute, + NumericAndTextAttributes } Type; unsigned Tag; unsigned IntValue; @@ -171,26 +306,17 @@ 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) return &Contents[i]; - return 0; + return nullptr; } void setAttributeItem(unsigned Attribute, unsigned Value, @@ -199,6 +325,7 @@ private: if (AttributeItem *Item = getAttributeItem(Attribute)) { if (!OverwriteExisting) return; + Item->Type = AttributeItem::NumericAttribute; Item->IntValue = Value; return; } @@ -219,6 +346,7 @@ private: if (AttributeItem *Item = getAttributeItem(Attribute)) { if (!OverwriteExisting) return; + Item->Type = AttributeItem::TextAttribute; Item->StringValue = Value; return; } @@ -233,33 +361,69 @@ 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 emitLabel(MCSymbol *Symbol) override; + + void AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) override; + void emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) 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(nullptr) {} }; /// Extend the generic ELFStreamer class so that it can emit mapping symbols at @@ -278,30 +442,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 +480,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 +539,13 @@ 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, + const SMLoc &Loc) override { EmitDataMappingSymbol(); MCELFStreamer::EmitValueImpl(Value, Size); } - virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) { + void EmitAssemblerFlag(MCAssemblerFlag Flag) override { MCELFStreamer::EmitAssemblerFlag(Flag); switch (Flag) { @@ -402,13 +608,9 @@ private: Symbol->setVariableValue(Value); } - void EmitThumbFunc(MCSymbol *Func) { - // FIXME: Anything needed here to flag the function as thumb? - + void EmitThumbFunc(MCSymbol *Func) override { getAssembler().setIsThumbFunc(Func); - - MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Func); - SD.setFlags(SD.getFlags() | ELF_Other_ThumbFunc); + EmitSymbolAttribute(Func, MCSA_ELF_TypeFunction); } // Helper functions for ARM exception handling directives @@ -423,6 +625,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 +650,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 +659,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 +669,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 +679,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 +704,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 +813,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 +858,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 +868,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 +876,9 @@ void ARMTargetELFStreamer::emitFPUDefaultAttributes() { /* OverwriteExisting= */ false); break; + case ARM::SOFTVFP: + break; + default: report_fatal_error("Unknown FPU: " + Twine(FPU)); break; @@ -574,13 +892,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 +920,9 @@ void ARMTargetELFStreamer::finishAttributeSection() { if (FPU != ARM::INVALID_FPU) emitFPUDefaultAttributes(); + if (Arch != ARM::INVALID_ARCH) + emitArchDefaultAttributes(); + if (Contents.empty()) return; @@ -648,6 +974,11 @@ 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; } } @@ -655,8 +986,41 @@ void ARMTargetELFStreamer::finishAttributeSection() { FPU = ARM::INVALID_FPU; } +void ARMTargetELFStreamer::emitLabel(MCSymbol *Symbol) { + ARMELFStreamer &Streamer = getStreamer(); + if (!Streamer.IsThumb) + return; + + const MCSymbolData &SD = Streamer.getOrCreateSymbolData(Symbol); + unsigned Type = MCELF::GetType(SD); + if (Type == ELF_STT_Func || Type == ELF_STT_GnuIFunc) + Streamer.EmitThumbFunc(Symbol); +} + +void +ARMTargetELFStreamer::AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *S) { + getStreamer().EmitFixup(S, FK_Data_4); +} + +void ARMTargetELFStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) { + if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Value)) { + const MCSymbol &Sym = SRE->getSymbol(); + if (!Sym.isDefined()) { + getStreamer().EmitAssignment(Symbol, Value); + return; + } + } + + getStreamer().EmitThumbFunc(Symbol); + getStreamer().EmitAssignment(Symbol, Value); +} + +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(); @@ -679,7 +1043,7 @@ inline void ARMELFStreamer::SwitchToEHSection(const char *Prefix, } // Get .ARM.extab or .ARM.exidx section - const MCSectionELF *EHSection = NULL; + const MCSectionELF *EHSection = nullptr; if (const MCSymbol *Group = FnSection.getGroup()) { EHSection = getContext().getELFSection( EHSecName, Type, Flags | ELF::SHF_GROUP, Kind, @@ -691,7 +1055,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 +1073,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; + ExTab = nullptr; + FnStart = nullptr; + Personality = nullptr; + PersonalityIndex = ARM::EHABI::NUM_PERSONALITY_INDEX; FPReg = ARM::SP; FPOffset = 0; SPOffset = 0; @@ -727,13 +1096,13 @@ void ARMELFStreamer::Reset() { } void ARMELFStreamer::emitFnStart() { - assert(FnStart == 0); + assert(FnStart == nullptr); FnStart = getContext().CreateTempSymbol(); EmitLabel(FnStart); } 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 +1111,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 +1122,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,12 +1134,15 @@ 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 && - "Compact model must use __aeabi_cpp_unwind_pr0 as personality"); + assert(PersonalityIndex == ARM::EHABI::AEABI_UNWIND_CPP_PR0 && + "Compact model must use __aeabi_unwind_cpp_pr0 as personality"); assert(Opcodes.size() == 4u && - "Unwind opcode size for __aeabi_cpp_unwind_pr0 must be equal to 4"); - EmitBytes(StringRef(reinterpret_cast<const char*>(Opcodes.data()), - Opcodes.size())); + "Unwind opcode size for __aeabi_unwind_cpp_pr0 must be equal to 4"); + uint64_t Intval = Opcodes[0] | + Opcodes[1] << 8 | + Opcodes[2] << 16 | + Opcodes[3] << 24; + EmitIntValue(Intval, Opcodes.size()); } // Switch to the section containing FnStart @@ -789,7 +1161,7 @@ void ARMELFStreamer::EmitPersonalityFixup(StringRef Name) { const MCSymbolRefExpr *PersonalityRef = MCSymbolRefExpr::Create( PersonalitySym, MCSymbolRefExpr::VK_ARM_NONE, getContext()); - AddValueSymbols(PersonalityRef); + visitUsedExpr(*PersonalityRef); MCDataFragment *DF = getOrCreateDataFragment(); DF->getFixups().push_back(MCFixup::Create(DF->getContents().size(), PersonalityRef, @@ -820,7 +1192,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. @@ -842,8 +1214,15 @@ void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) { } // Emit unwind opcodes - EmitBytes(StringRef(reinterpret_cast<const char *>(Opcodes.data()), - Opcodes.size())); + assert((Opcodes.size() % 4) == 0 && + "Unwind opcode size for __aeabi_cpp_unwind_pr0 must be multiple of 4"); + for (unsigned I = 0; I != Opcodes.size(); I += 4) { + uint64_t Intval = Opcodes[I] | + Opcodes[I + 1] << 8 | + Opcodes[I + 2] << 16 | + Opcodes[I + 3] << 24; + EmitIntValue(Intval, 4); + } // According to ARM EHABI section 9.2, if the __aeabi_unwind_cpp_pr1() or // __aeabi_unwind_cpp_pr2() is used, then the handler data must be emitted @@ -863,6 +1242,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 +1261,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 +1314,37 @@ 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 useDwarfDirectory, + bool isVerboseAsm, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst) { - ARMTargetAsmStreamer *S = new ARMTargetAsmStreamer(OS, *InstPrint); + MCStreamer *S = llvm::createAsmStreamer( + Ctx, OS, isVerboseAsm, useDwarfDirectory, InstPrint, CE, TAB, ShowInst); + new ARMTargetAsmStreamer(*S, OS, *InstPrint, isVerboseAsm); + return S; +} - return llvm::createAsmStreamer(Ctx, S, OS, isVerboseAsm, useLoc, useCFI, - useDwarfDirectory, InstPrint, CE, TAB, - ShowInst); +MCStreamer *createARMNullStreamer(MCContext &Ctx) { + MCStreamer *S = llvm::createNullStreamer(Ctx); + new ARMTargetStreamer(*S); + 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 0085feb82069..bfd9e3364825 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 ad796e660e96..7a19208cffc7 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp @@ -13,19 +13,19 @@ #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() { - Data64bitsDirective = 0; +ARMMCAsmInfoDarwin::ARMMCAsmInfoDarwin(StringRef TT) { + Triple TheTriple(TT); + if ((TheTriple.getArch() == Triple::armeb) || + (TheTriple.getArch() == Triple::thumbeb)) + IsLittleEndian = false; + + Data64bitsDirective = nullptr; CommentString = "@"; Code16Directive = ".code\t16"; Code32Directive = ".code\t32"; @@ -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; + Data64bitsDirective = nullptr; CommentString = "@"; - PrivateGlobalPrefix = ".L"; Code16Directive = ".code\t16"; Code32Directive = ".code\t32"; @@ -53,6 +59,56 @@ ARMELFMCAsmInfo::ARMELFMCAsmInfo() { SupportsDebugInformation = true; // Exceptions handling - if (EnableARMEHABI) + switch (TheTriple.getOS()) { + case Triple::NetBSD: + ExceptionsType = ExceptionHandling::DwarfCFI; + break; + default: ExceptionsType = ExceptionHandling::ARM; + break; + } + + // 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; + HasSingleParameterDotFile = true; + + 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 e1f716d936ad..51cfa0adc1a9 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() override; + public: + explicit ARMCOFFMCAsmInfoMicrosoft(); + }; + + class ARMCOFFMCAsmInfoGNU : public MCAsmInfoGNUCOFF { + void anchor() override; + public: + explicit ARMCOFFMCAsmInfoGNU(); }; } // namespace llvm diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp index 4382d0d97144..b8ee55574972 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "mccodeemitter" #include "MCTargetDesc/ARMMCTargetDesc.h" #include "MCTargetDesc/ARMAddressingModes.h" #include "MCTargetDesc/ARMBaseInfo.h" @@ -26,10 +25,13 @@ #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; +#define DEBUG_TYPE "mccodeemitter" + STATISTIC(MCNumEmitted, "Number of MC instructions emitted."); STATISTIC(MCNumCPRelocations, "Number of constant pool relocations created."); @@ -38,27 +40,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 +66,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 +216,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 +271,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 +306,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 +315,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 +405,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 +455,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 +469,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 +482,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 +494,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 +507,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 +536,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 +566,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 +603,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 +616,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 +681,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 +711,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 +726,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 +739,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 +769,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 +810,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 +830,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 +843,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 +858,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 +876,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 +896,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 +910,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 +942,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 +963,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 +983,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 +994,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,51 +1012,48 @@ 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())); return 0; } // If the expression doesn't have :upper16: or :lower16: on it, - // it's just a plain immediate expression, and those evaluate to + // it's just a plain immediate expression, previously those evaluated 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); - Fixups.push_back(MCFixup::Create(0, E, Kind, MI.getLoc())); - return 0; + // we have a movt or a movw, but that led to misleadingly results. + // This is now disallowed in the the AsmParser in validateInstruction() + // so this should never happen. + llvm_unreachable("expression without :upper16: or :lower16:"); } 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 +1086,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 +1124,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 +1136,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 +1156,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 +1193,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 +1209,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 +1224,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 +1252,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 +1260,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 +1274,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 +1322,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 +1369,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 +1388,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 +1410,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 +1427,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 +1444,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 +1487,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 +1501,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 +1538,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 +1562,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 +1589,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 +1610,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 +1619,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 +1661,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.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCExpr.cpp index fc8505b052bd..e545e3c2f301 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCExpr.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCExpr.cpp @@ -7,12 +7,13 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "armmcexpr" #include "ARMMCExpr.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" using namespace llvm; +#define DEBUG_TYPE "armmcexpr" + const ARMMCExpr* ARMMCExpr::Create(VariantKind Kind, const MCExpr *Expr, MCContext &Ctx) { @@ -40,33 +41,6 @@ ARMMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, return false; } -// FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps -// that method should be made public? -static void AddValueSymbols_(const MCExpr *Value, MCAssembler *Asm) { - switch (Value->getKind()) { - case MCExpr::Target: - llvm_unreachable("Can't handle nested target expr!"); - - case MCExpr::Constant: - break; - - case MCExpr::Binary: { - const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value); - AddValueSymbols_(BE->getLHS(), Asm); - AddValueSymbols_(BE->getRHS(), Asm); - break; - } - - case MCExpr::SymbolRef: - Asm->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol()); - break; - - case MCExpr::Unary: - AddValueSymbols_(cast<MCUnaryExpr>(Value)->getSubExpr(), Asm); - break; - } -} - -void ARMMCExpr::AddValueSymbols(MCAssembler *Asm) const { - AddValueSymbols_(getSubExpr(), Asm); +void ARMMCExpr::visitUsedExpr(MCStreamer &Streamer) const { + Streamer.visitUsedExpr(*getSubExpr()); } diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCExpr.h b/lib/Target/ARM/MCTargetDesc/ARMMCExpr.h index cd4067a52955..c5c0b10f8ad9 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 visitUsedExpr(MCStreamer &Streamer) 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 a99de0e78230..6a3ec8fcc486 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp @@ -21,6 +21,7 @@ #include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" @@ -83,89 +84,87 @@ static bool getITDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI, std::string ARM_MC::ParseARMTriple(StringRef TT, StringRef CPU) { Triple triple(TT); - // Set the boolean corresponding to the current target triple, or the default - // if one cannot be determined, to true. - unsigned Len = TT.size(); - unsigned Idx = 0; - - // FIXME: Enhance Triple helper class to extract ARM version. - bool isThumb = false; - 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; - } + bool isThumb = triple.getArch() == Triple::thumb || + triple.getArch() == Triple::thumbeb; bool NoCPU = CPU == "generic" || CPU.empty(); std::string ARMArchFeature; - if (Idx) { - unsigned SubVer = TT[Idx]; - if (SubVer == '8') { - if (NoCPU) - // v8a: FeatureDB, FeatureFPARMv8, FeatureNEON, FeatureDSPThumb2, FeatureMP, - // FeatureHWDiv, FeatureHWDivARM, FeatureTrustZone, FeatureT2XtPk, FeatureCrypto, FeatureCRC - ARMArchFeature = "+v8,+db,+fp-armv8,+neon,+t2dsp,+mp,+hwdiv,+hwdiv-arm,+trustzone,+t2xtpk,+crypto,+crc"; - else - // Use CPU to figure out the exact features - ARMArchFeature = "+v8"; - } else if (SubVer == '7') { - if (Len >= Idx+2 && TT[Idx+1] == 'm') { - isThumb = true; - if (NoCPU) - // v7m: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureMClass - ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+mclass"; - else - // Use CPU to figure out the exact features. - ARMArchFeature = "+v7"; - } else if (Len >= Idx+3 && TT[Idx+1] == 'e'&& TT[Idx+2] == 'm') { - if (NoCPU) - // v7em: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureDSPThumb2, - // FeatureT2XtPk, FeatureMClass - ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+t2dsp,t2xtpk,+mclass"; - else - // Use CPU to figure out the exact features. - ARMArchFeature = "+v7"; - } else if (Len >= Idx+2 && TT[Idx+1] == 's') { - if (NoCPU) - // v7s: FeatureNEON, FeatureDB, FeatureDSPThumb2, FeatureT2XtPk - // Swift - ARMArchFeature = "+v7,+swift,+neon,+db,+t2dsp,+t2xtpk"; - else - // Use CPU to figure out the exact features. - ARMArchFeature = "+v7"; - } else { - // v7 CPUs have lots of different feature sets. If no CPU is specified, - // then assume v7a (e.g. cortex-a8) feature set. Otherwise, return - // the "minimum" feature set and use CPU string to figure out the exact - // features. - if (NoCPU) - // v7a: FeatureNEON, FeatureDB, FeatureDSPThumb2, FeatureT2XtPk - ARMArchFeature = "+v7,+neon,+db,+t2dsp,+t2xtpk"; - else - // Use CPU to figure out the exact features. - ARMArchFeature = "+v7"; - } - } else if (SubVer == '6') { - if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') - ARMArchFeature = "+v6t2"; - else if (Len >= Idx+2 && TT[Idx+1] == 'm') { - isThumb = true; - if (NoCPU) - // v6m: FeatureNoARM, FeatureMClass - ARMArchFeature = "+v6m,+noarm,+mclass"; - else - ARMArchFeature = "+v6"; - } else - ARMArchFeature = "+v6"; - } else if (SubVer == '5') { - if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e') - ARMArchFeature = "+v5te"; - else - ARMArchFeature = "+v5t"; - } else if (SubVer == '4' && Len >= Idx+2 && TT[Idx+1] == 't') - ARMArchFeature = "+v4t"; + switch (triple.getSubArch()) { + case Triple::ARMSubArch_v8: + if (NoCPU) + // v8a: FeatureDB, FeatureFPARMv8, FeatureNEON, FeatureDSPThumb2, + // FeatureMP, FeatureHWDiv, FeatureHWDivARM, FeatureTrustZone, + // FeatureT2XtPk, FeatureCrypto, FeatureCRC + ARMArchFeature = "+v8,+db,+fp-armv8,+neon,+t2dsp,+mp,+hwdiv,+hwdiv-arm," + "+trustzone,+t2xtpk,+crypto,+crc"; + else + // Use CPU to figure out the exact features + ARMArchFeature = "+v8"; + break; + case Triple::ARMSubArch_v7m: + isThumb = true; + if (NoCPU) + // v7m: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureMClass + ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+mclass"; + else + // Use CPU to figure out the exact features. + ARMArchFeature = "+v7"; + break; + case Triple::ARMSubArch_v7em: + if (NoCPU) + // v7em: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureDSPThumb2, + // FeatureT2XtPk, FeatureMClass + ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+t2dsp,t2xtpk,+mclass"; + else + // Use CPU to figure out the exact features. + ARMArchFeature = "+v7"; + break; + case Triple::ARMSubArch_v7s: + if (NoCPU) + // v7s: FeatureNEON, FeatureDB, FeatureDSPThumb2, FeatureHasRAS + // Swift + ARMArchFeature = "+v7,+swift,+neon,+db,+t2dsp,+ras"; + else + // Use CPU to figure out the exact features. + ARMArchFeature = "+v7"; + break; + case Triple::ARMSubArch_v7: + // v7 CPUs have lots of different feature sets. If no CPU is specified, + // then assume v7a (e.g. cortex-a8) feature set. Otherwise, return + // the "minimum" feature set and use CPU string to figure out the exact + // features. + if (NoCPU) + // v7a: FeatureNEON, FeatureDB, FeatureDSPThumb2, FeatureT2XtPk + ARMArchFeature = "+v7,+neon,+db,+t2dsp,+t2xtpk"; + else + // Use CPU to figure out the exact features. + ARMArchFeature = "+v7"; + break; + case Triple::ARMSubArch_v6t2: + ARMArchFeature = "+v6t2"; + break; + case Triple::ARMSubArch_v6m: + isThumb = true; + if (NoCPU) + // v6m: FeatureNoARM, FeatureMClass + ARMArchFeature = "+v6m,+noarm,+mclass"; + else + ARMArchFeature = "+v6"; + break; + case Triple::ARMSubArch_v6: + ARMArchFeature = "+v6"; + break; + case Triple::ARMSubArch_v5te: + ARMArchFeature = "+v5te"; + break; + case Triple::ARMSubArch_v5: + ARMArchFeature = "+v5t"; + break; + case Triple::ARMSubArch_v4t: + ARMArchFeature = "+v4t"; + break; + case Triple::NoSubArch: + break; } if (isThumb) { @@ -215,10 +214,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(nullptr, Reg, 0)); - return new ARMELFMCAsmInfo(); + return MAI; } static MCCodeGenInfo *createARMMCCodeGenInfo(StringRef TT, Reloc::Model RM, @@ -239,19 +265,25 @@ 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.isOSWindows()) { - llvm_unreachable("ARM does not support Windows COFF format"); + switch (TheTriple.getObjectFormat()) { + default: llvm_unreachable("unsupported object format"); + case Triple::MachO: { + MCStreamer *S = createMachOStreamer(Ctx, MAB, OS, Emitter, false); + new ARMTargetStreamer(*S); + return S; + } + case Triple::COFF: + assert(TheTriple.isOSWindows() && "non-Windows ARM COFF is not supported"); + return createARMWinCOFFStreamer(Ctx, MAB, *Emitter, OS); + case Triple::ELF: + return createARMELFStreamer(Ctx, MAB, OS, Emitter, false, NoExecStack, + TheTriple.getArch() == Triple::thumb); } - - return createARMELFStreamer(Ctx, MAB, OS, Emitter, false, NoExecStack, - TheTriple.getArch() == Triple::thumb); } static MCInstPrinter *createARMMCInstPrinter(const Target &T, @@ -262,13 +294,13 @@ static MCInstPrinter *createARMMCInstPrinter(const Target &T, const MCSubtargetInfo &STI) { if (SyntaxVariant == 0) return new ARMInstPrinter(MAI, MII, MRI, STI); - return 0; + return nullptr; } 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 +312,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 +327,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 +348,100 @@ 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(TheARMBETarget, ARM_MC::createARMMCSubtargetInfo); - TargetRegistry::RegisterMCSubtargetInfo(TheThumbTarget, + 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(TheThumbLETarget, createARMMCInstrAnalysis); - TargetRegistry::RegisterMCInstrAnalysis(TheThumbTarget, + 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 null streamer. + TargetRegistry::RegisterNullStreamer(TheARMLETarget, createARMNullStreamer); + TargetRegistry::RegisterNullStreamer(TheARMBETarget, createARMNullStreamer); + TargetRegistry::RegisterNullStreamer(TheThumbLETarget, createARMNullStreamer); + TargetRegistry::RegisterNullStreamer(TheThumbBETarget, createARMNullStreamer); // 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 959be8b55c3a..5326e564f363 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,47 @@ namespace ARM_MC { } MCStreamer *createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, - bool isVerboseAsm, bool useLoc, bool useCFI, - bool useDwarfDirectory, + bool isVerboseAsm, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst); -MCCodeEmitter *createARMMCCodeEmitter(const MCInstrInfo &MCII, - const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI, - MCContext &Ctx); +MCStreamer *createARMNullStreamer(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); + +/// createARMWinCOFFStreamer - Construct a PE/COFF machine code streamer which +/// will generate a PE/COFF object file. +MCStreamer *createARMWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, + MCCodeEmitter &Emitter, raw_ostream &OS); + /// 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, @@ -69,6 +95,8 @@ MCObjectWriter *createARMMachObjectWriter(raw_ostream &OS, uint32_t CPUType, uint32_t CPUSubtype); +/// createARMWinCOFFObjectWriter - Construct an ARM PE/COFF object writer. +MCObjectWriter *createARMWinCOFFObjectWriter(raw_ostream &OS, bool Is64Bit); /// createARMMachORelocationInfo - Construct ARM Mach-O relocation info. MCRelocationInfo *createARMMachORelocationInfo(MCContext &Ctx); diff --git a/lib/Target/ARM/MCTargetDesc/ARMMachORelocationInfo.cpp b/lib/Target/ARM/MCTargetDesc/ARMMachORelocationInfo.cpp index 807c9483bc38..d4b00e6e4fb5 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 1f681bac2242..186776a1944f 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp @@ -32,6 +32,7 @@ class ARMMachObjectWriter : public MCMachObjectTargetWriter { const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, + unsigned Type, unsigned Log2Size, uint64_t &FixedValue); void RecordARMScatteredHalfRelocation(MachObjectWriter *Writer, @@ -56,7 +57,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 +83,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 +124,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; @@ -156,7 +157,7 @@ RecordARMScatteredHalfRelocation(MachObjectWriter *Writer, // See <reloc.h>. const MCSymbol *A = &Target.getSymA()->getSymbol(); - MCSymbolData *A_SD = &Asm.getSymbolData(*A); + const MCSymbolData *A_SD = &Asm.getSymbolData(*A); if (!A_SD->getFragment()) Asm.getContext().FatalError(Fixup.getLoc(), @@ -170,7 +171,7 @@ RecordARMScatteredHalfRelocation(MachObjectWriter *Writer, FixedValue += SecAddr; if (const MCSymbolRefExpr *B = Target.getSymB()) { - MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); + const MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); if (!B_SD->getFragment()) Asm.getContext().FatalError(Fixup.getLoc(), @@ -202,22 +203,19 @@ 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 // is a thumb function. Clear it out here. - if (A_SD->getFlags() & SF_ThumbFunc) + if (Asm.isThumbFunc(A)) FixedValue &= 0xfffffffe; break; case ARM::fixup_t2_movt_hi16: - case ARM::fixup_t2_movt_hi16_pcrel: - if (A_SD->getFlags() & SF_ThumbFunc) + if (Asm.isThumbFunc(A)) FixedValue &= 0xfffffffe; MovtBit = 1; // Fallthrough case ARM::fixup_t2_movw_lo16: - case ARM::fixup_t2_movw_lo16_pcrel: ThumbBit = 1; break; } @@ -254,15 +252,15 @@ void ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, + unsigned Type, unsigned Log2Size, uint64_t &FixedValue) { uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); - unsigned Type = MachO::ARM_RELOC_VANILLA; // See <reloc.h>. const MCSymbol *A = &Target.getSymA()->getSymbol(); - MCSymbolData *A_SD = &Asm.getSymbolData(*A); + const MCSymbolData *A_SD = &Asm.getSymbolData(*A); if (!A_SD->getFragment()) Asm.getContext().FatalError(Fixup.getLoc(), @@ -275,7 +273,8 @@ void ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer, uint32_t Value2 = 0; if (const MCSymbolRefExpr *B = Target.getSymB()) { - MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); + assert(Type == MachO::ARM_RELOC_VANILLA && "invalid reloc for 2 symbols"); + const MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); if (!B_SD->getFragment()) Asm.getContext().FatalError(Fixup.getLoc(), @@ -377,11 +376,12 @@ void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer, return RecordARMScatteredHalfRelocation(Writer, Asm, Layout, Fragment, Fixup, Target, FixedValue); return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, - Target, Log2Size, FixedValue); + Target, RelocType, Log2Size, + FixedValue); } // Get the symbol data, if any. - MCSymbolData *SD = 0; + const MCSymbolData *SD = nullptr; if (Target.getSymA()) SD = &Asm.getSymbolData(Target.getSymA()->getSymbol()); @@ -395,7 +395,8 @@ void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer, Offset += 1 << Log2Size; if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD)) return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, - Target, Log2Size, FixedValue); + Target, RelocType, Log2Size, + FixedValue); // See <reloc.h>. uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); @@ -461,15 +462,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 000000000000..8acd7aff6bca --- /dev/null +++ b/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp @@ -0,0 +1,73 @@ +//===- 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/ConstantPools.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCStreamer.h" + +using namespace llvm; +// +// 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, 4); +} + +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() {} +void ARMTargetStreamer::emitFnEnd() {} +void ARMTargetStreamer::emitCantUnwind() {} +void ARMTargetStreamer::emitPersonality(const MCSymbol *Personality) {} +void ARMTargetStreamer::emitPersonalityIndex(unsigned Index) {} +void ARMTargetStreamer::emitHandlerData() {} +void ARMTargetStreamer::emitSetFP(unsigned FpReg, unsigned SpReg, + int64_t Offset) {} +void ARMTargetStreamer::emitMovSP(unsigned Reg, int64_t Offset) {} +void ARMTargetStreamer::emitPad(int64_t Offset) {} +void ARMTargetStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, + bool isVector) {} +void ARMTargetStreamer::emitUnwindRaw(int64_t StackOffset, + const SmallVectorImpl<uint8_t> &Opcodes) { +} +void ARMTargetStreamer::switchVendor(StringRef Vendor) {} +void ARMTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) {} +void ARMTargetStreamer::emitTextAttribute(unsigned Attribute, + StringRef String) {} +void ARMTargetStreamer::emitIntTextAttribute(unsigned Attribute, + unsigned IntValue, + StringRef StringValue) {} +void ARMTargetStreamer::emitArch(unsigned Arch) {} +void ARMTargetStreamer::emitObjectArch(unsigned Arch) {} +void ARMTargetStreamer::emitFPU(unsigned FPU) {} +void ARMTargetStreamer::finishAttributeSection() {} +void ARMTargetStreamer::emitInst(uint32_t Inst, char Suffix) {} +void +ARMTargetStreamer::AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) {} + +void ARMTargetStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) {} diff --git a/lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h b/lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h deleted file mode 100644 index fa4add65a8df..000000000000 --- 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 c94337081884..593fe349b1d4 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 ac67c6efabb7..cd5875924300 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/ARMWinCOFFObjectWriter.cpp b/lib/Target/ARM/MCTargetDesc/ARMWinCOFFObjectWriter.cpp new file mode 100644 index 000000000000..d31f1f41c697 --- /dev/null +++ b/lib/Target/ARM/MCTargetDesc/ARMWinCOFFObjectWriter.cpp @@ -0,0 +1,82 @@ +//===-- ARMWinCOFFObjectWriter.cpp - ARM Windows COFF Object Writer -- C++ -==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/ARMFixupKinds.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCValue.h" +#include "llvm/MC/MCWinCOFFObjectWriter.h" +#include "llvm/Support/COFF.h" +#include "llvm/Support/Debug.h" + +using namespace llvm; + +namespace { +class ARMWinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter { +public: + ARMWinCOFFObjectWriter(bool Is64Bit) + : MCWinCOFFObjectTargetWriter(COFF::IMAGE_FILE_MACHINE_ARMNT) { + assert(!Is64Bit && "AArch64 support not yet implemented"); + } + virtual ~ARMWinCOFFObjectWriter() { } + + unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsCrossSection) const override; + + bool recordRelocation(const MCFixup &) const override; +}; + +unsigned ARMWinCOFFObjectWriter::getRelocType(const MCValue &Target, + const MCFixup &Fixup, + bool IsCrossSection) const { + assert(getMachine() == COFF::IMAGE_FILE_MACHINE_ARMNT && + "AArch64 support not yet implemented"); + + MCSymbolRefExpr::VariantKind Modifier = + Target.isAbsolute() ? MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); + + switch (static_cast<unsigned>(Fixup.getKind())) { + default: llvm_unreachable("unsupported relocation type"); + case FK_Data_4: + switch (Modifier) { + case MCSymbolRefExpr::VK_COFF_IMGREL32: + return COFF::IMAGE_REL_ARM_ADDR32NB; + case MCSymbolRefExpr::VK_SECREL: + return COFF::IMAGE_REL_ARM_SECREL; + default: + return COFF::IMAGE_REL_ARM_ADDR32; + } + case FK_SecRel_2: + return COFF::IMAGE_REL_ARM_SECTION; + case FK_SecRel_4: + return COFF::IMAGE_REL_ARM_SECREL; + case ARM::fixup_t2_condbranch: + return COFF::IMAGE_REL_ARM_BRANCH20T; + case ARM::fixup_t2_uncondbranch: + return COFF::IMAGE_REL_ARM_BRANCH24T; + case ARM::fixup_arm_thumb_bl: + case ARM::fixup_arm_thumb_blx: + return COFF::IMAGE_REL_ARM_BLX23T; + case ARM::fixup_t2_movw_lo16: + case ARM::fixup_t2_movt_hi16: + return COFF::IMAGE_REL_ARM_MOV32T; + } +} + +bool ARMWinCOFFObjectWriter::recordRelocation(const MCFixup &Fixup) const { + return static_cast<unsigned>(Fixup.getKind()) != ARM::fixup_t2_movt_hi16; +} +} + +namespace llvm { +MCObjectWriter *createARMWinCOFFObjectWriter(raw_ostream &OS, bool Is64Bit) { + MCWinCOFFObjectTargetWriter *MOTW = new ARMWinCOFFObjectWriter(Is64Bit); + return createWinCOFFObjectWriter(MOTW, OS); +} +} + diff --git a/lib/Target/ARM/MCTargetDesc/ARMWinCOFFStreamer.cpp b/lib/Target/ARM/MCTargetDesc/ARMWinCOFFStreamer.cpp new file mode 100644 index 000000000000..b344ced2f67a --- /dev/null +++ b/lib/Target/ARM/MCTargetDesc/ARMWinCOFFStreamer.cpp @@ -0,0 +1,46 @@ +//===-- ARMWinCOFFStreamer.cpp - ARM Target WinCOFF Streamer ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ARMMCTargetDesc.h" +#include "llvm/MC/MCWinCOFFStreamer.h" + +using namespace llvm; + +namespace { +class ARMWinCOFFStreamer : public MCWinCOFFStreamer { +public: + ARMWinCOFFStreamer(MCContext &C, MCAsmBackend &AB, MCCodeEmitter &CE, + raw_ostream &OS) + : MCWinCOFFStreamer(C, AB, CE, OS) { } + + void EmitAssemblerFlag(MCAssemblerFlag Flag) override; + void EmitThumbFunc(MCSymbol *Symbol) override; +}; + +void ARMWinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { + switch (Flag) { + default: llvm_unreachable("not implemented"); + case MCAF_SyntaxUnified: + case MCAF_Code16: + break; + } +} + +void ARMWinCOFFStreamer::EmitThumbFunc(MCSymbol *Symbol) { + getAssembler().setIsThumbFunc(Symbol); +} +} + +namespace llvm { +MCStreamer *createARMWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, + MCCodeEmitter &Emitter, raw_ostream &OS) { + return new ARMWinCOFFStreamer(Context, MAB, Emitter, OS); +} +} + diff --git a/lib/Target/ARM/MCTargetDesc/CMakeLists.txt b/lib/Target/ARM/MCTargetDesc/CMakeLists.txt index bab59f41c989..9582e8cbef47 100644 --- a/lib/Target/ARM/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/ARM/MCTargetDesc/CMakeLists.txt @@ -1,17 +1,16 @@ add_llvm_library(LLVMARMDesc ARMAsmBackend.cpp ARMELFObjectWriter.cpp + ARMELFObjectWriter.cpp ARMELFStreamer.cpp + ARMMachObjectWriter.cpp + ARMMachORelocationInfo.cpp ARMMCAsmInfo.cpp ARMMCCodeEmitter.cpp ARMMCExpr.cpp ARMMCTargetDesc.cpp - ARMMachObjectWriter.cpp - ARMELFObjectWriter.cpp + ARMTargetStreamer.cpp ARMUnwindOpAsm.cpp - ARMMachORelocationInfo.cpp + ARMWinCOFFObjectWriter.cpp + ARMWinCOFFStreamer.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}/..) |