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" 30using namespace llvm; 31 32ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI) 33 : ARMBaseInstrInfo(STI), RI() {} 34 35/// getNoopForMachoTarget - Return the noop instruction to use for a noop. 36void 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 52unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const { 53 switch (Opc) { 54 default: break; 55 case ARM::LDR_PRE_IMM: 56 case ARM::LDR_PRE_REG: 57 case ARM::LDR_POST_IMM: 58 case ARM::LDR_POST_REG: 59 return ARM::LDRi12; 60 case ARM::LDRH_PRE: 61 case ARM::LDRH_POST: 62 return ARM::LDRH; 63 case ARM::LDRB_PRE_IMM: 64 case ARM::LDRB_PRE_REG: 65 case ARM::LDRB_POST_IMM: 66 case ARM::LDRB_POST_REG: 67 return ARM::LDRBi12; 68 case ARM::LDRSH_PRE: 69 case ARM::LDRSH_POST: 70 return ARM::LDRSH; 71 case ARM::LDRSB_PRE: 72 case ARM::LDRSB_POST: 73 return ARM::LDRSB; 74 case ARM::STR_PRE_IMM: 75 case ARM::STR_PRE_REG: 76 case ARM::STR_POST_IMM: 77 case ARM::STR_POST_REG: 78 return ARM::STRi12; 79 case ARM::STRH_PRE: 80 case ARM::STRH_POST: 81 return ARM::STRH; 82 case ARM::STRB_PRE_IMM: 83 case ARM::STRB_PRE_REG: 84 case ARM::STRB_POST_IMM: 85 case ARM::STRB_POST_REG: 86 return ARM::STRBi12; 87 } 88 89 return 0; 90} 91 92void ARMInstrInfo::expandLoadStackGuard(MachineBasicBlock::iterator MI, 93 Reloc::Model RM) const { 94 MachineFunction &MF = *MI->getParent()->getParent(); 95 const ARMSubtarget &Subtarget = MF.getSubtarget<ARMSubtarget>(); 96 97 if (!Subtarget.useMovt(MF)) { 98 if (RM == Reloc::PIC_) 99 expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_pcrel, ARM::LDRi12, RM); 100 else 101 expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_abs, ARM::LDRi12, RM); 102 return; 103 } 104 105 if (RM != Reloc::PIC_) { 106 expandLoadStackGuardBase(MI, ARM::MOVi32imm, ARM::LDRi12, RM); 107 return; 108 } 109 110 const GlobalValue *GV = 111 cast<GlobalValue>((*MI->memoperands_begin())->getValue()); 112 113 if (!Subtarget.GVIsIndirectSymbol(GV, RM)) { 114 expandLoadStackGuardBase(MI, ARM::MOV_ga_pcrel, ARM::LDRi12, RM); 115 return; 116 } 117 118 MachineBasicBlock &MBB = *MI->getParent(); 119 DebugLoc DL = MI->getDebugLoc(); 120 unsigned Reg = MI->getOperand(0).getReg(); 121 MachineInstrBuilder MIB; 122 123 MIB = BuildMI(MBB, MI, DL, get(ARM::MOV_ga_pcrel_ldr), Reg) 124 .addGlobalAddress(GV, 0, ARMII::MO_NONLAZY); 125 unsigned Flag = MachineMemOperand::MOLoad | MachineMemOperand::MOInvariant; 126 MachineMemOperand *MMO = MBB.getParent()->getMachineMemOperand( 127 MachinePointerInfo::getGOT(), Flag, 4, 4); 128 MIB.addMemOperand(MMO); 129 MIB = BuildMI(MBB, MI, DL, get(ARM::LDRi12), Reg); 130 MIB.addReg(Reg, RegState::Kill).addImm(0); 131 MIB.setMemRefs(MI->memoperands_begin(), MI->memoperands_end()); 132 AddDefaultPred(MIB); 133} 134 135namespace { 136 /// ARMCGBR - Create Global Base Reg pass. This initializes the PIC 137 /// global base register for ARM ELF. 138 struct ARMCGBR : public MachineFunctionPass { 139 static char ID; 140 ARMCGBR() : MachineFunctionPass(ID) {} 141 142 bool runOnMachineFunction(MachineFunction &MF) override { 143 ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 144 if (AFI->getGlobalBaseReg() == 0) 145 return false; 146 const ARMSubtarget &STI = 147 static_cast<const ARMSubtarget &>(MF.getSubtarget()); 148 // Don't do this for Thumb1. 149 if (STI.isThumb1Only()) 150 return false; 151 152 const TargetMachine &TM = MF.getTarget(); 153 if (TM.getRelocationModel() != Reloc::PIC_) 154 return false; 155 156 LLVMContext *Context = &MF.getFunction()->getContext(); 157 unsigned ARMPCLabelIndex = AFI->createPICLabelUId(); 158 unsigned PCAdj = STI.isThumb() ? 4 : 8; 159 ARMConstantPoolValue *CPV = ARMConstantPoolSymbol::Create( 160 *Context, "_GLOBAL_OFFSET_TABLE_", ARMPCLabelIndex, PCAdj); 161 162 unsigned Align = TM.getDataLayout()->getPrefTypeAlignment( 163 Type::getInt32PtrTy(*Context)); 164 unsigned Idx = MF.getConstantPool()->getConstantPoolIndex(CPV, Align); 165 166 MachineBasicBlock &FirstMBB = MF.front(); 167 MachineBasicBlock::iterator MBBI = FirstMBB.begin(); 168 DebugLoc DL = FirstMBB.findDebugLoc(MBBI); 169 unsigned TempReg = 170 MF.getRegInfo().createVirtualRegister(&ARM::rGPRRegClass); 171 unsigned Opc = STI.isThumb2() ? ARM::t2LDRpci : ARM::LDRcp; 172 const TargetInstrInfo &TII = *STI.getInstrInfo(); 173 MachineInstrBuilder MIB = BuildMI(FirstMBB, MBBI, DL, 174 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 203char ARMCGBR::ID = 0; 204FunctionPass* 205llvm::createARMGlobalBaseRegPass() { return new ARMCGBR(); } 206