X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FTarget%2FARM%2FMCTargetDesc%2FARMMCCodeEmitter.cpp;h=6b650f09f7e1ba8393643dc500188ec7398562a5;hp=6fc909a6962cafa877f245388433b93c4ed4ce92;hb=c16fc548515f2fd01bc2cbe4befd822a636cc154;hpb=4faa861f19b73cfd8e537e2af5379d6ba53c82d0 diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp index 6fc909a6962..6b650f09f7e 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" @@ -31,33 +30,33 @@ using namespace llvm; +#define DEBUG_TYPE "mccodeemitter" + STATISTIC(MCNumEmitted, "Number of MC instructions emitted."); STATISTIC(MCNumCPRelocations, "Number of constant pool relocations created."); namespace { class ARMMCCodeEmitter : public MCCodeEmitter { - ARMMCCodeEmitter(const ARMMCCodeEmitter &) LLVM_DELETED_FUNCTION; - void operator=(const ARMMCCodeEmitter &) LLVM_DELETED_FUNCTION; + ARMMCCodeEmitter(const ARMMCCodeEmitter &) = delete; + void operator=(const ARMMCCodeEmitter &) = delete; 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() {} + ~ARMMCCodeEmitter() override {} - 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 isTargetMachO() const { + bool isTargetMachO(const MCSubtargetInfo &STI) const { Triple TT(STI.getTargetTriple()); return TT.isOSBinFormatMachO(); } @@ -274,7 +273,25 @@ public: unsigned getSOImmOpValue(const MCInst &MI, unsigned Op, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { - unsigned SoImm = MI.getOperand(Op).getImm(); + + 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!"); @@ -287,6 +304,28 @@ public: return Binary; } + unsigned getModImmOpValue(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &ST) const { + const MCOperand &MO = MI.getOperand(Op); + + // Support for fixups (MCFixup) + 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; + } + + // Immediate is already in its encoded format + return MO.getImm(); + } + /// getT2SOImmOpValue - Return an encoded 12-bit shifted-immediate value. unsigned getT2SOImmOpValue(const MCInst &MI, unsigned Op, SmallVectorImpl &Fixups, @@ -388,23 +427,28 @@ 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 &Fixups, - const MCSubtargetInfo &STI) const; + 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, + MCContext &Ctx) { + return new ARMMCCodeEmitter(MCII, Ctx, true); +} + +MCCodeEmitter *llvm::createARMBEMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + MCContext &Ctx) { + return new ARMMCCodeEmitter(MCII, Ctx, false); } /// NEONThumb2DataIPostEncoder - Post-process encoded NEON data-processing @@ -413,7 +457,7 @@ MCCodeEmitter *llvm::createARMMCCodeEmitter(const MCInstrInfo &MCII, unsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const { - if (isThumb2()) { + 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. @@ -433,7 +477,7 @@ unsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI, unsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const { - if (isThumb2()) { + if (isThumb2(STI)) { EncodedValue &= 0xF0FFFFFF; EncodedValue |= 0x09000000; } @@ -447,7 +491,7 @@ unsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI, unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const { - if (isThumb2()) { + if (isThumb2(STI)) { EncodedValue &= 0x00FFFFFF; EncodedValue |= 0xEE000000; } @@ -460,7 +504,7 @@ unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI, unsigned ARMMCCodeEmitter::NEONThumb2V8PostEncoder(const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const { - if (isThumb2()) { + if (isThumb2(STI)) { EncodedValue |= 0xC000000; // Set bits 27-26 } @@ -472,7 +516,7 @@ unsigned ARMMCCodeEmitter::NEONThumb2V8PostEncoder(const MCInst &MI, unsigned ARMMCCodeEmitter:: VFPThumb2PostEncoder(const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const { - if (isThumb2()) { + if (isThumb2(STI)) { EncodedValue &= 0x0FFFFFFF; EncodedValue |= 0xE0000000; } @@ -661,7 +705,7 @@ getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 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, STI); return getARMBranchTargetOpValue(MI, OpIdx, Fixups, STI); @@ -852,7 +896,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); @@ -970,19 +1014,6 @@ 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 &Fixups, @@ -1018,43 +1049,25 @@ ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx, switch (ARM16Expr->getKind()) { default: llvm_unreachable("Unsupported ARMFixup"); case ARMMCExpr::VK_ARM_HI16: - if (!isTargetMachO() && 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 (!isTargetMachO() && 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 (!isTargetMachO() && 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:: @@ -1259,7 +1272,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); @@ -1671,7 +1684,7 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, 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