1 //===-- ARMInstrInfo.cpp - ARM Instruction Information --------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains the ARM implementation of the TargetInstrInfo class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "ARMInstrInfo.h" 15 #include "ARM.h" 16 #include "ARMConstantPoolValue.h" 17 #include "ARMMachineFunctionInfo.h" 18 #include "ARMTargetMachine.h" 19 #include "MCTargetDesc/ARMAddressingModes.h" 20 #include "llvm/ADT/STLExtras.h" 21 #include "llvm/CodeGen/LiveVariables.h" 22 #include "llvm/CodeGen/MachineFrameInfo.h" 23 #include "llvm/CodeGen/MachineInstrBuilder.h" 24 #include "llvm/CodeGen/MachineJumpTableInfo.h" 25 #include "llvm/CodeGen/MachineRegisterInfo.h" 26 #include "llvm/IR/Function.h" 27 #include "llvm/IR/GlobalVariable.h" 28 #include "llvm/MC/MCAsmInfo.h" 29 #include "llvm/MC/MCInst.h" 30 using namespace llvm; 31 32 ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI) 33 : ARMBaseInstrInfo(STI), RI() {} 34 35 /// getNoopForMachoTarget - Return the noop instruction to use for a noop. 36 void ARMInstrInfo::getNoopForMachoTarget(MCInst &NopInst) const { 37 if (hasNOP()) { 38 NopInst.setOpcode(ARM::HINT); 39 NopInst.addOperand(MCOperand::createImm(0)); 40 NopInst.addOperand(MCOperand::createImm(ARMCC::AL)); 41 NopInst.addOperand(MCOperand::createReg(0)); 42 } else { 43 NopInst.setOpcode(ARM::MOVr); 44 NopInst.addOperand(MCOperand::createReg(ARM::R0)); 45 NopInst.addOperand(MCOperand::createReg(ARM::R0)); 46 NopInst.addOperand(MCOperand::createImm(ARMCC::AL)); 47 NopInst.addOperand(MCOperand::createReg(0)); 48 NopInst.addOperand(MCOperand::createReg(0)); 49 } 50 } 51 52 unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const { 53 switch (Opc) { 54 default: 55 break; 56 case ARM::LDR_PRE_IMM: 57 case ARM::LDR_PRE_REG: 58 case ARM::LDR_POST_IMM: 59 case ARM::LDR_POST_REG: 60 return ARM::LDRi12; 61 case ARM::LDRH_PRE: 62 case ARM::LDRH_POST: 63 return ARM::LDRH; 64 case ARM::LDRB_PRE_IMM: 65 case ARM::LDRB_PRE_REG: 66 case ARM::LDRB_POST_IMM: 67 case ARM::LDRB_POST_REG: 68 return ARM::LDRBi12; 69 case ARM::LDRSH_PRE: 70 case ARM::LDRSH_POST: 71 return ARM::LDRSH; 72 case ARM::LDRSB_PRE: 73 case ARM::LDRSB_POST: 74 return ARM::LDRSB; 75 case ARM::STR_PRE_IMM: 76 case ARM::STR_PRE_REG: 77 case ARM::STR_POST_IMM: 78 case ARM::STR_POST_REG: 79 return ARM::STRi12; 80 case ARM::STRH_PRE: 81 case ARM::STRH_POST: 82 return ARM::STRH; 83 case ARM::STRB_PRE_IMM: 84 case ARM::STRB_PRE_REG: 85 case ARM::STRB_POST_IMM: 86 case ARM::STRB_POST_REG: 87 return ARM::STRBi12; 88 } 89 90 return 0; 91 } 92 93 void ARMInstrInfo::expandLoadStackGuard(MachineBasicBlock::iterator MI, 94 Reloc::Model RM) const { 95 MachineFunction &MF = *MI->getParent()->getParent(); 96 const ARMSubtarget &Subtarget = MF.getSubtarget<ARMSubtarget>(); 97 98 if (!Subtarget.useMovt(MF)) { 99 if (RM == Reloc::PIC_) 100 expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_pcrel, ARM::LDRi12, RM); 101 else 102 expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_abs, ARM::LDRi12, RM); 103 return; 104 } 105 106 if (RM != Reloc::PIC_) { 107 expandLoadStackGuardBase(MI, ARM::MOVi32imm, ARM::LDRi12, RM); 108 return; 109 } 110 111 const GlobalValue *GV = 112 cast<GlobalValue>((*MI->memoperands_begin())->getValue()); 113 114 if (!Subtarget.GVIsIndirectSymbol(GV, RM)) { 115 expandLoadStackGuardBase(MI, ARM::MOV_ga_pcrel, ARM::LDRi12, RM); 116 return; 117 } 118 119 MachineBasicBlock &MBB = *MI->getParent(); 120 DebugLoc DL = MI->getDebugLoc(); 121 unsigned Reg = MI->getOperand(0).getReg(); 122 MachineInstrBuilder MIB; 123 124 MIB = BuildMI(MBB, MI, DL, get(ARM::MOV_ga_pcrel_ldr), Reg) 125 .addGlobalAddress(GV, 0, ARMII::MO_NONLAZY); 126 unsigned Flag = MachineMemOperand::MOLoad | MachineMemOperand::MOInvariant; 127 MachineMemOperand *MMO = MBB.getParent()->getMachineMemOperand( 128 MachinePointerInfo::getGOT(*MBB.getParent()), Flag, 4, 4); 129 MIB.addMemOperand(MMO); 130 MIB = BuildMI(MBB, MI, DL, get(ARM::LDRi12), Reg); 131 MIB.addReg(Reg, RegState::Kill).addImm(0); 132 MIB.setMemRefs(MI->memoperands_begin(), MI->memoperands_end()); 133 AddDefaultPred(MIB); 134 } 135 136 namespace { 137 /// ARMCGBR - Create Global Base Reg pass. This initializes the PIC 138 /// global base register for ARM ELF. 139 struct ARMCGBR : public MachineFunctionPass { 140 static char ID; 141 ARMCGBR() : MachineFunctionPass(ID) {} 142 143 bool runOnMachineFunction(MachineFunction &MF) override { 144 ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 145 if (AFI->getGlobalBaseReg() == 0) 146 return false; 147 const ARMSubtarget &STI = 148 static_cast<const ARMSubtarget &>(MF.getSubtarget()); 149 // Don't do this for Thumb1. 150 if (STI.isThumb1Only()) 151 return false; 152 153 const TargetMachine &TM = MF.getTarget(); 154 if (TM.getRelocationModel() != Reloc::PIC_) 155 return false; 156 157 LLVMContext *Context = &MF.getFunction()->getContext(); 158 unsigned ARMPCLabelIndex = AFI->createPICLabelUId(); 159 unsigned PCAdj = STI.isThumb() ? 4 : 8; 160 ARMConstantPoolValue *CPV = ARMConstantPoolSymbol::Create( 161 *Context, "_GLOBAL_OFFSET_TABLE_", ARMPCLabelIndex, PCAdj); 162 163 unsigned Align = 164 MF.getDataLayout().getPrefTypeAlignment(Type::getInt32PtrTy(*Context)); 165 unsigned Idx = MF.getConstantPool()->getConstantPoolIndex(CPV, Align); 166 167 MachineBasicBlock &FirstMBB = MF.front(); 168 MachineBasicBlock::iterator MBBI = FirstMBB.begin(); 169 DebugLoc DL = FirstMBB.findDebugLoc(MBBI); 170 unsigned TempReg = 171 MF.getRegInfo().createVirtualRegister(&ARM::rGPRRegClass); 172 unsigned Opc = STI.isThumb2() ? ARM::t2LDRpci : ARM::LDRcp; 173 const TargetInstrInfo &TII = *STI.getInstrInfo(); 174 MachineInstrBuilder MIB = BuildMI(FirstMBB, MBBI, DL, TII.get(Opc), TempReg) 175 .addConstantPoolIndex(Idx); 176 if (Opc == ARM::LDRcp) 177 MIB.addImm(0); 178 AddDefaultPred(MIB); 179 180 // Fix the GOT address by adding pc. 181 unsigned GlobalBaseReg = AFI->getGlobalBaseReg(); 182 Opc = STI.isThumb2() ? ARM::tPICADD : ARM::PICADD; 183 MIB = BuildMI(FirstMBB, MBBI, DL, TII.get(Opc), GlobalBaseReg) 184 .addReg(TempReg) 185 .addImm(ARMPCLabelIndex); 186 if (Opc == ARM::PICADD) 187 AddDefaultPred(MIB); 188 189 return true; 190 } 191 192 const char *getPassName() const override { 193 return "ARM PIC Global Base Reg Initialization"; 194 } 195 196 void getAnalysisUsage(AnalysisUsage &AU) const override { 197 AU.setPreservesCFG(); 198 MachineFunctionPass::getAnalysisUsage(AU); 199 } 200 }; 201 } 202 203 char ARMCGBR::ID = 0; 204 FunctionPass *llvm::createARMGlobalBaseRegPass() { return new ARMCGBR(); } 205