//===-- ARMInstrInfo.cpp - ARM Instruction Information --------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file contains the ARM implementation of the TargetInstrInfo class. // //===----------------------------------------------------------------------===// #include "ARMInstrInfo.h" #include "ARM.h" #include "ARMConstantPoolValue.h" #include "ARMMachineFunctionInfo.h" #include "ARMTargetMachine.h" #include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/LiveVariables.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCInst.h" using namespace llvm; ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI) : ARMBaseInstrInfo(STI) {} /// Return the noop instruction to use for a noop. MCInst ARMInstrInfo::getNop() const { MCInst NopInst; if (hasNOP()) { NopInst.setOpcode(ARM::HINT); NopInst.addOperand(MCOperand::createImm(0)); NopInst.addOperand(MCOperand::createImm(ARMCC::AL)); NopInst.addOperand(MCOperand::createReg(0)); } else { NopInst.setOpcode(ARM::MOVr); NopInst.addOperand(MCOperand::createReg(ARM::R0)); NopInst.addOperand(MCOperand::createReg(ARM::R0)); NopInst.addOperand(MCOperand::createImm(ARMCC::AL)); NopInst.addOperand(MCOperand::createReg(0)); NopInst.addOperand(MCOperand::createReg(0)); } return NopInst; } unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const { switch (Opc) { default: break; case ARM::LDR_PRE_IMM: case ARM::LDR_PRE_REG: case ARM::LDR_POST_IMM: case ARM::LDR_POST_REG: return ARM::LDRi12; case ARM::LDRH_PRE: case ARM::LDRH_POST: return ARM::LDRH; case ARM::LDRB_PRE_IMM: case ARM::LDRB_PRE_REG: case ARM::LDRB_POST_IMM: case ARM::LDRB_POST_REG: return ARM::LDRBi12; case ARM::LDRSH_PRE: case ARM::LDRSH_POST: return ARM::LDRSH; case ARM::LDRSB_PRE: case ARM::LDRSB_POST: return ARM::LDRSB; case ARM::STR_PRE_IMM: case ARM::STR_PRE_REG: case ARM::STR_POST_IMM: case ARM::STR_POST_REG: return ARM::STRi12; case ARM::STRH_PRE: case ARM::STRH_POST: return ARM::STRH; case ARM::STRB_PRE_IMM: case ARM::STRB_PRE_REG: case ARM::STRB_POST_IMM: case ARM::STRB_POST_REG: return ARM::STRBi12; } return 0; } void ARMInstrInfo::expandLoadStackGuard(MachineBasicBlock::iterator MI) const { MachineFunction &MF = *MI->getParent()->getParent(); const ARMSubtarget &Subtarget = MF.getSubtarget(); const TargetMachine &TM = MF.getTarget(); Module &M = *MF.getFunction().getParent(); if (M.getStackProtectorGuard() == "tls") { expandLoadStackGuardBase(MI, ARM::MRC, ARM::LDRi12); return; } const GlobalValue *GV = cast((*MI->memoperands_begin())->getValue()); bool ForceELFGOTPIC = Subtarget.isTargetELF() && !GV->isDSOLocal(); if (!Subtarget.useMovt() || ForceELFGOTPIC) { // For ELF non-PIC, use GOT PIC code sequence as well because R_ARM_GOT_ABS // does not have assembler support. if (TM.isPositionIndependent() || ForceELFGOTPIC) expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_pcrel, ARM::LDRi12); else expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_abs, ARM::LDRi12); return; } if (!TM.isPositionIndependent()) { expandLoadStackGuardBase(MI, ARM::MOVi32imm, ARM::LDRi12); return; } if (!Subtarget.isGVIndirectSymbol(GV)) { expandLoadStackGuardBase(MI, ARM::MOV_ga_pcrel, ARM::LDRi12); return; } MachineBasicBlock &MBB = *MI->getParent(); DebugLoc DL = MI->getDebugLoc(); Register Reg = MI->getOperand(0).getReg(); MachineInstrBuilder MIB; MIB = BuildMI(MBB, MI, DL, get(ARM::MOV_ga_pcrel_ldr), Reg) .addGlobalAddress(GV, 0, ARMII::MO_NONLAZY); auto Flags = MachineMemOperand::MOLoad | MachineMemOperand::MODereferenceable | MachineMemOperand::MOInvariant; MachineMemOperand *MMO = MBB.getParent()->getMachineMemOperand( MachinePointerInfo::getGOT(*MBB.getParent()), Flags, 4, Align(4)); MIB.addMemOperand(MMO); BuildMI(MBB, MI, DL, get(ARM::LDRi12), Reg) .addReg(Reg, RegState::Kill) .addImm(0) .cloneMemRefs(*MI) .add(predOps(ARMCC::AL)); }