bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const { if (TII.getSubtarget().isROPI() || TII.getSubtarget().isRWPI()) { DEBUG(dbgs() << "ROPI and RWPI not supported yet\n"); return false; } if (TM.isPositionIndependent()) { DEBUG(dbgs() << "PIC not supported yet\n"); return false; } auto GV = MIB->getOperand(1).getGlobal(); if (GV->isThreadLocal()) { DEBUG(dbgs() << "TLS variables not supported yet\n"); return false; } auto &MBB = *MIB->getParent(); auto &MF = *MBB.getParent(); auto ObjectFormat = TII.getSubtarget().getTargetTriple().getObjectFormat(); bool UseMovt = TII.getSubtarget().useMovt(MF); if (ObjectFormat == Triple::ELF) { if (UseMovt) { MIB->setDesc(TII.get(ARM::MOVi32imm)); } else { // Load the global's address from the constant pool. MIB->setDesc(TII.get(ARM::LDRi12)); MIB->RemoveOperand(1); unsigned Alignment = 4; MIB.addConstantPoolIndex( MF.getConstantPool()->getConstantPoolIndex(GV, Alignment), /* Offset */ 0, /* TargetFlags */ 0) .addMemOperand(MF.getMachineMemOperand( MachinePointerInfo::getConstantPool(MF), MachineMemOperand::MOLoad, TM.getPointerSize(), Alignment)) .addImm(0) .add(predOps(ARMCC::AL)); } } else if (ObjectFormat == Triple::MachO) { if (UseMovt) MIB->setDesc(TII.get(ARM::MOVi32imm)); else MIB->setDesc(TII.get(ARM::LDRLIT_ga_abs)); } else { DEBUG(dbgs() << "Object format not supported yet\n"); return false; } return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); }
bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const { if ((STI.isROPI() || STI.isRWPI()) && !STI.isTargetELF()) { LLVM_DEBUG(dbgs() << "ROPI and RWPI only supported for ELF\n"); return false; } auto GV = MIB->getOperand(1).getGlobal(); if (GV->isThreadLocal()) { LLVM_DEBUG(dbgs() << "TLS variables not supported yet\n"); return false; } auto &MBB = *MIB->getParent(); auto &MF = *MBB.getParent(); bool UseMovt = STI.useMovt(MF); unsigned Size = TM.getPointerSize(0); unsigned Alignment = 4; auto addOpsForConstantPoolLoad = [&MF, Alignment, Size](MachineInstrBuilder &MIB, const GlobalValue *GV, bool IsSBREL) { assert(MIB->getOpcode() == ARM::LDRi12 && "Unsupported instruction"); auto ConstPool = MF.getConstantPool(); auto CPIndex = // For SB relative entries we need a target-specific constant pool. // Otherwise, just use a regular constant pool entry. IsSBREL ? ConstPool->getConstantPoolIndex( ARMConstantPoolConstant::Create(GV, ARMCP::SBREL), Alignment) : ConstPool->getConstantPoolIndex(GV, Alignment); MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0) .addMemOperand( MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF), MachineMemOperand::MOLoad, Size, Alignment)) .addImm(0) .add(predOps(ARMCC::AL)); }; if (TM.isPositionIndependent()) { bool Indirect = STI.isGVIndirectSymbol(GV); // FIXME: Taking advantage of MOVT for ELF is pretty involved, so we don't // support it yet. See PR28229. unsigned Opc = UseMovt && !STI.isTargetELF() ? (Indirect ? ARM::MOV_ga_pcrel_ldr : ARM::MOV_ga_pcrel) : (Indirect ? ARM::LDRLIT_ga_pcrel_ldr : ARM::LDRLIT_ga_pcrel); MIB->setDesc(TII.get(Opc)); int TargetFlags = ARMII::MO_NO_FLAG; if (STI.isTargetDarwin()) TargetFlags |= ARMII::MO_NONLAZY; if (STI.isGVInGOT(GV)) TargetFlags |= ARMII::MO_GOT; MIB->getOperand(1).setTargetFlags(TargetFlags); if (Indirect) MIB.addMemOperand(MF.getMachineMemOperand( MachinePointerInfo::getGOT(MF), MachineMemOperand::MOLoad, TM.getProgramPointerSize(), Alignment)); return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); } bool isReadOnly = STI.getTargetLowering()->isReadOnly(GV); if (STI.isROPI() && isReadOnly) { unsigned Opc = UseMovt ? ARM::MOV_ga_pcrel : ARM::LDRLIT_ga_pcrel; MIB->setDesc(TII.get(Opc)); return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); } if (STI.isRWPI() && !isReadOnly) { auto Offset = MRI.createVirtualRegister(&ARM::GPRRegClass); MachineInstrBuilder OffsetMIB; if (UseMovt) { OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(), TII.get(ARM::MOVi32imm), Offset); OffsetMIB.addGlobalAddress(GV, /*Offset*/ 0, ARMII::MO_SBREL); } else { // Load the offset from the constant pool. OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(), TII.get(ARM::LDRi12), Offset); addOpsForConstantPoolLoad(OffsetMIB, GV, /*IsSBREL*/ true); } if (!constrainSelectedInstRegOperands(*OffsetMIB, TII, TRI, RBI)) return false; // Add the offset to the SB register. MIB->setDesc(TII.get(ARM::ADDrr)); MIB->RemoveOperand(1); MIB.addReg(ARM::R9) // FIXME: don't hardcode R9 .addReg(Offset) .add(predOps(ARMCC::AL)) .add(condCodeOp()); return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); } if (STI.isTargetELF()) { if (UseMovt) { MIB->setDesc(TII.get(ARM::MOVi32imm)); } else { // Load the global's address from the constant pool. MIB->setDesc(TII.get(ARM::LDRi12)); MIB->RemoveOperand(1); addOpsForConstantPoolLoad(MIB, GV, /*IsSBREL*/ false); } } else if (STI.isTargetMachO()) { if (UseMovt) MIB->setDesc(TII.get(ARM::MOVi32imm)); else MIB->setDesc(TII.get(ARM::LDRLIT_ga_abs)); } else { LLVM_DEBUG(dbgs() << "Object format not supported yet\n"); return false; } return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); }
/// AddOperand - Add the specified operand to the specified machine instr. II /// specifies the instruction information for the node, and IIOpNum is the /// operand number (in the II) that we are adding. void InstrEmitter::AddOperand(MachineInstrBuilder &MIB, SDValue Op, unsigned IIOpNum, const MCInstrDesc *II, DenseMap<SDValue, unsigned> &VRBaseMap, bool IsDebug, bool IsClone, bool IsCloned) { if (Op.isMachineOpcode()) { AddRegisterOperand(MIB, Op, IIOpNum, II, VRBaseMap, IsDebug, IsClone, IsCloned); } else if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { MIB.addImm(C->getSExtValue()); } else if (ConstantFPSDNode *F = dyn_cast<ConstantFPSDNode>(Op)) { MIB.addFPImm(F->getConstantFPValue()); } else if (RegisterSDNode *R = dyn_cast<RegisterSDNode>(Op)) { unsigned VReg = R->getReg(); MVT OpVT = Op.getSimpleValueType(); const TargetRegisterClass *OpRC = TLI->isTypeLegal(OpVT) ? TLI->getRegClassFor(OpVT) : nullptr; const TargetRegisterClass *IIRC = II ? TRI->getAllocatableClass(TII->getRegClass(*II, IIOpNum, TRI, *MF)) : nullptr; if (OpRC && IIRC && OpRC != IIRC && TargetRegisterInfo::isVirtualRegister(VReg)) { unsigned NewVReg = MRI->createVirtualRegister(IIRC); BuildMI(*MBB, InsertPos, Op.getNode()->getDebugLoc(), TII->get(TargetOpcode::COPY), NewVReg).addReg(VReg); VReg = NewVReg; } // Turn additional physreg operands into implicit uses on non-variadic // instructions. This is used by call and return instructions passing // arguments in registers. bool Imp = II && (IIOpNum >= II->getNumOperands() && !II->isVariadic()); MIB.addReg(VReg, getImplRegState(Imp)); } else if (RegisterMaskSDNode *RM = dyn_cast<RegisterMaskSDNode>(Op)) { MIB.addRegMask(RM->getRegMask()); } else if (GlobalAddressSDNode *TGA = dyn_cast<GlobalAddressSDNode>(Op)) { MIB.addGlobalAddress(TGA->getGlobal(), TGA->getOffset(), TGA->getTargetFlags()); } else if (BasicBlockSDNode *BBNode = dyn_cast<BasicBlockSDNode>(Op)) { MIB.addMBB(BBNode->getBasicBlock()); } else if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Op)) { MIB.addFrameIndex(FI->getIndex()); } else if (JumpTableSDNode *JT = dyn_cast<JumpTableSDNode>(Op)) { MIB.addJumpTableIndex(JT->getIndex(), JT->getTargetFlags()); } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op)) { int Offset = CP->getOffset(); unsigned Align = CP->getAlignment(); Type *Type = CP->getType(); // MachineConstantPool wants an explicit alignment. if (Align == 0) { Align = MF->getDataLayout().getPrefTypeAlignment(Type); if (Align == 0) { // Alignment of vector types. FIXME! Align = MF->getDataLayout().getTypeAllocSize(Type); } } unsigned Idx; MachineConstantPool *MCP = MF->getConstantPool(); if (CP->isMachineConstantPoolEntry()) Idx = MCP->getConstantPoolIndex(CP->getMachineCPVal(), Align); else Idx = MCP->getConstantPoolIndex(CP->getConstVal(), Align); MIB.addConstantPoolIndex(Idx, Offset, CP->getTargetFlags()); } else if (ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op)) { MIB.addExternalSymbol(ES->getSymbol(), ES->getTargetFlags()); } else if (auto *SymNode = dyn_cast<MCSymbolSDNode>(Op)) { MIB.addSym(SymNode->getMCSymbol()); } else if (BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op)) { MIB.addBlockAddress(BA->getBlockAddress(), BA->getOffset(), BA->getTargetFlags()); } else if (TargetIndexSDNode *TI = dyn_cast<TargetIndexSDNode>(Op)) { MIB.addTargetIndex(TI->getIndex(), TI->getOffset(), TI->getTargetFlags()); } else { assert(Op.getValueType() != MVT::Other && Op.getValueType() != MVT::Glue && "Chain and glue operands should occur at end of operand list!"); AddRegisterOperand(MIB, Op, IIOpNum, II, VRBaseMap, IsDebug, IsClone, IsCloned); } }