1*0b57cec5SDimitry Andric //===-- PPCMCInstLower.cpp - Convert PPC MachineInstr to an MCInst --------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file contains code to lower PPC MachineInstrs to their corresponding 10*0b57cec5SDimitry Andric // MCInst records. 11*0b57cec5SDimitry Andric // 12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric #include "MCTargetDesc/PPCMCExpr.h" 15*0b57cec5SDimitry Andric #include "PPC.h" 16*0b57cec5SDimitry Andric #include "PPCSubtarget.h" 17*0b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 18*0b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 19*0b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h" 20*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 21*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h" 22*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h" 23*0b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 24*0b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h" 25*0b57cec5SDimitry Andric #include "llvm/IR/Mangler.h" 26*0b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 27*0b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 28*0b57cec5SDimitry Andric #include "llvm/MC/MCInst.h" 29*0b57cec5SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h" 30*0b57cec5SDimitry Andric using namespace llvm; 31*0b57cec5SDimitry Andric 32*0b57cec5SDimitry Andric static MachineModuleInfoMachO &getMachOMMI(AsmPrinter &AP) { 33*0b57cec5SDimitry Andric return AP.MMI->getObjFileInfo<MachineModuleInfoMachO>(); 34*0b57cec5SDimitry Andric } 35*0b57cec5SDimitry Andric 36*0b57cec5SDimitry Andric static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, 37*0b57cec5SDimitry Andric AsmPrinter &AP) { 38*0b57cec5SDimitry Andric const TargetMachine &TM = AP.TM; 39*0b57cec5SDimitry Andric Mangler &Mang = TM.getObjFileLowering()->getMangler(); 40*0b57cec5SDimitry Andric const DataLayout &DL = AP.getDataLayout(); 41*0b57cec5SDimitry Andric MCContext &Ctx = AP.OutContext; 42*0b57cec5SDimitry Andric 43*0b57cec5SDimitry Andric SmallString<128> Name; 44*0b57cec5SDimitry Andric StringRef Suffix; 45*0b57cec5SDimitry Andric if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG) 46*0b57cec5SDimitry Andric Suffix = "$non_lazy_ptr"; 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric if (!Suffix.empty()) 49*0b57cec5SDimitry Andric Name += DL.getPrivateGlobalPrefix(); 50*0b57cec5SDimitry Andric 51*0b57cec5SDimitry Andric if (!MO.isGlobal()) { 52*0b57cec5SDimitry Andric assert(MO.isSymbol() && "Isn't a symbol reference"); 53*0b57cec5SDimitry Andric Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL); 54*0b57cec5SDimitry Andric } else { 55*0b57cec5SDimitry Andric const GlobalValue *GV = MO.getGlobal(); 56*0b57cec5SDimitry Andric TM.getNameWithPrefix(Name, GV, Mang); 57*0b57cec5SDimitry Andric } 58*0b57cec5SDimitry Andric 59*0b57cec5SDimitry Andric Name += Suffix; 60*0b57cec5SDimitry Andric MCSymbol *Sym = Ctx.getOrCreateSymbol(Name); 61*0b57cec5SDimitry Andric 62*0b57cec5SDimitry Andric // If the symbol reference is actually to a non_lazy_ptr, not to the symbol, 63*0b57cec5SDimitry Andric // then add the suffix. 64*0b57cec5SDimitry Andric if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG) { 65*0b57cec5SDimitry Andric MachineModuleInfoMachO &MachO = getMachOMMI(AP); 66*0b57cec5SDimitry Andric 67*0b57cec5SDimitry Andric MachineModuleInfoImpl::StubValueTy &StubSym = MachO.getGVStubEntry(Sym); 68*0b57cec5SDimitry Andric 69*0b57cec5SDimitry Andric if (!StubSym.getPointer()) { 70*0b57cec5SDimitry Andric assert(MO.isGlobal() && "Extern symbol not handled yet"); 71*0b57cec5SDimitry Andric StubSym = MachineModuleInfoImpl:: 72*0b57cec5SDimitry Andric StubValueTy(AP.getSymbol(MO.getGlobal()), 73*0b57cec5SDimitry Andric !MO.getGlobal()->hasInternalLinkage()); 74*0b57cec5SDimitry Andric } 75*0b57cec5SDimitry Andric return Sym; 76*0b57cec5SDimitry Andric } 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric return Sym; 79*0b57cec5SDimitry Andric } 80*0b57cec5SDimitry Andric 81*0b57cec5SDimitry Andric static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, 82*0b57cec5SDimitry Andric AsmPrinter &Printer, bool isDarwin) { 83*0b57cec5SDimitry Andric MCContext &Ctx = Printer.OutContext; 84*0b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; 85*0b57cec5SDimitry Andric 86*0b57cec5SDimitry Andric unsigned access = MO.getTargetFlags() & PPCII::MO_ACCESS_MASK; 87*0b57cec5SDimitry Andric 88*0b57cec5SDimitry Andric switch (access) { 89*0b57cec5SDimitry Andric case PPCII::MO_TPREL_LO: 90*0b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TPREL_LO; 91*0b57cec5SDimitry Andric break; 92*0b57cec5SDimitry Andric case PPCII::MO_TPREL_HA: 93*0b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TPREL_HA; 94*0b57cec5SDimitry Andric break; 95*0b57cec5SDimitry Andric case PPCII::MO_DTPREL_LO: 96*0b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_DTPREL_LO; 97*0b57cec5SDimitry Andric break; 98*0b57cec5SDimitry Andric case PPCII::MO_TLSLD_LO: 99*0b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO; 100*0b57cec5SDimitry Andric break; 101*0b57cec5SDimitry Andric case PPCII::MO_TOC_LO: 102*0b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO; 103*0b57cec5SDimitry Andric break; 104*0b57cec5SDimitry Andric case PPCII::MO_TLS: 105*0b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TLS; 106*0b57cec5SDimitry Andric break; 107*0b57cec5SDimitry Andric } 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andric if (MO.getTargetFlags() == PPCII::MO_PLT) 110*0b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PLT; 111*0b57cec5SDimitry Andric 112*0b57cec5SDimitry Andric const MachineFunction *MF = MO.getParent()->getParent()->getParent(); 113*0b57cec5SDimitry Andric const Module *M = MF->getFunction().getParent(); 114*0b57cec5SDimitry Andric const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>()); 115*0b57cec5SDimitry Andric const TargetMachine &TM = Printer.TM; 116*0b57cec5SDimitry Andric const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, RefKind, Ctx); 117*0b57cec5SDimitry Andric // If -msecure-plt -fPIC, add 32768 to symbol. 118*0b57cec5SDimitry Andric if (Subtarget->isSecurePlt() && TM.isPositionIndependent() && 119*0b57cec5SDimitry Andric M->getPICLevel() == PICLevel::BigPIC && 120*0b57cec5SDimitry Andric MO.getTargetFlags() == PPCII::MO_PLT) 121*0b57cec5SDimitry Andric Expr = 122*0b57cec5SDimitry Andric MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(32768, Ctx), Ctx); 123*0b57cec5SDimitry Andric 124*0b57cec5SDimitry Andric if (!MO.isJTI() && MO.getOffset()) 125*0b57cec5SDimitry Andric Expr = MCBinaryExpr::createAdd(Expr, 126*0b57cec5SDimitry Andric MCConstantExpr::create(MO.getOffset(), Ctx), 127*0b57cec5SDimitry Andric Ctx); 128*0b57cec5SDimitry Andric 129*0b57cec5SDimitry Andric // Subtract off the PIC base if required. 130*0b57cec5SDimitry Andric if (MO.getTargetFlags() & PPCII::MO_PIC_FLAG) { 131*0b57cec5SDimitry Andric const MachineFunction *MF = MO.getParent()->getParent()->getParent(); 132*0b57cec5SDimitry Andric 133*0b57cec5SDimitry Andric const MCExpr *PB = MCSymbolRefExpr::create(MF->getPICBaseSymbol(), Ctx); 134*0b57cec5SDimitry Andric Expr = MCBinaryExpr::createSub(Expr, PB, Ctx); 135*0b57cec5SDimitry Andric } 136*0b57cec5SDimitry Andric 137*0b57cec5SDimitry Andric // Add ha16() / lo16() markers if required. 138*0b57cec5SDimitry Andric switch (access) { 139*0b57cec5SDimitry Andric case PPCII::MO_LO: 140*0b57cec5SDimitry Andric Expr = PPCMCExpr::createLo(Expr, isDarwin, Ctx); 141*0b57cec5SDimitry Andric break; 142*0b57cec5SDimitry Andric case PPCII::MO_HA: 143*0b57cec5SDimitry Andric Expr = PPCMCExpr::createHa(Expr, isDarwin, Ctx); 144*0b57cec5SDimitry Andric break; 145*0b57cec5SDimitry Andric } 146*0b57cec5SDimitry Andric 147*0b57cec5SDimitry Andric return MCOperand::createExpr(Expr); 148*0b57cec5SDimitry Andric } 149*0b57cec5SDimitry Andric 150*0b57cec5SDimitry Andric void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, 151*0b57cec5SDimitry Andric AsmPrinter &AP, bool isDarwin) { 152*0b57cec5SDimitry Andric OutMI.setOpcode(MI->getOpcode()); 153*0b57cec5SDimitry Andric 154*0b57cec5SDimitry Andric for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 155*0b57cec5SDimitry Andric MCOperand MCOp; 156*0b57cec5SDimitry Andric if (LowerPPCMachineOperandToMCOperand(MI->getOperand(i), MCOp, AP, 157*0b57cec5SDimitry Andric isDarwin)) 158*0b57cec5SDimitry Andric OutMI.addOperand(MCOp); 159*0b57cec5SDimitry Andric } 160*0b57cec5SDimitry Andric } 161*0b57cec5SDimitry Andric 162*0b57cec5SDimitry Andric bool llvm::LowerPPCMachineOperandToMCOperand(const MachineOperand &MO, 163*0b57cec5SDimitry Andric MCOperand &OutMO, AsmPrinter &AP, 164*0b57cec5SDimitry Andric bool isDarwin) { 165*0b57cec5SDimitry Andric switch (MO.getType()) { 166*0b57cec5SDimitry Andric default: 167*0b57cec5SDimitry Andric llvm_unreachable("unknown operand type"); 168*0b57cec5SDimitry Andric case MachineOperand::MO_Register: 169*0b57cec5SDimitry Andric assert(!MO.getSubReg() && "Subregs should be eliminated!"); 170*0b57cec5SDimitry Andric assert(MO.getReg() > PPC::NoRegister && 171*0b57cec5SDimitry Andric MO.getReg() < PPC::NUM_TARGET_REGS && 172*0b57cec5SDimitry Andric "Invalid register for this target!"); 173*0b57cec5SDimitry Andric OutMO = MCOperand::createReg(MO.getReg()); 174*0b57cec5SDimitry Andric return true; 175*0b57cec5SDimitry Andric case MachineOperand::MO_Immediate: 176*0b57cec5SDimitry Andric OutMO = MCOperand::createImm(MO.getImm()); 177*0b57cec5SDimitry Andric return true; 178*0b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 179*0b57cec5SDimitry Andric OutMO = MCOperand::createExpr( 180*0b57cec5SDimitry Andric MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), AP.OutContext)); 181*0b57cec5SDimitry Andric return true; 182*0b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress: 183*0b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol: 184*0b57cec5SDimitry Andric OutMO = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP, isDarwin); 185*0b57cec5SDimitry Andric return true; 186*0b57cec5SDimitry Andric case MachineOperand::MO_JumpTableIndex: 187*0b57cec5SDimitry Andric OutMO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP, isDarwin); 188*0b57cec5SDimitry Andric return true; 189*0b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 190*0b57cec5SDimitry Andric OutMO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP, isDarwin); 191*0b57cec5SDimitry Andric return true; 192*0b57cec5SDimitry Andric case MachineOperand::MO_BlockAddress: 193*0b57cec5SDimitry Andric OutMO = GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP, 194*0b57cec5SDimitry Andric isDarwin); 195*0b57cec5SDimitry Andric return true; 196*0b57cec5SDimitry Andric case MachineOperand::MO_RegisterMask: 197*0b57cec5SDimitry Andric return false; 198*0b57cec5SDimitry Andric } 199*0b57cec5SDimitry Andric } 200