10b57cec5SDimitry Andric //===-- PPCMCInstLower.cpp - Convert PPC MachineInstr to an MCInst --------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains code to lower PPC MachineInstrs to their corresponding 100b57cec5SDimitry Andric // MCInst records. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "MCTargetDesc/PPCMCExpr.h" 150b57cec5SDimitry Andric #include "PPC.h" 160b57cec5SDimitry Andric #include "PPCSubtarget.h" 170b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 180b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h" 230b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 240b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h" 250b57cec5SDimitry Andric #include "llvm/IR/Mangler.h" 260b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 270b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 280b57cec5SDimitry Andric #include "llvm/MC/MCInst.h" 290b57cec5SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h" 300b57cec5SDimitry Andric using namespace llvm; 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric static MachineModuleInfoMachO &getMachOMMI(AsmPrinter &AP) { 330b57cec5SDimitry Andric return AP.MMI->getObjFileInfo<MachineModuleInfoMachO>(); 340b57cec5SDimitry Andric } 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, 370b57cec5SDimitry Andric AsmPrinter &AP) { 380b57cec5SDimitry Andric const TargetMachine &TM = AP.TM; 390b57cec5SDimitry Andric Mangler &Mang = TM.getObjFileLowering()->getMangler(); 400b57cec5SDimitry Andric const DataLayout &DL = AP.getDataLayout(); 410b57cec5SDimitry Andric MCContext &Ctx = AP.OutContext; 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric SmallString<128> Name; 440b57cec5SDimitry Andric StringRef Suffix; 450b57cec5SDimitry Andric if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG) 460b57cec5SDimitry Andric Suffix = "$non_lazy_ptr"; 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric if (!Suffix.empty()) 490b57cec5SDimitry Andric Name += DL.getPrivateGlobalPrefix(); 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric if (!MO.isGlobal()) { 520b57cec5SDimitry Andric assert(MO.isSymbol() && "Isn't a symbol reference"); 530b57cec5SDimitry Andric Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL); 540b57cec5SDimitry Andric } else { 550b57cec5SDimitry Andric const GlobalValue *GV = MO.getGlobal(); 560b57cec5SDimitry Andric TM.getNameWithPrefix(Name, GV, Mang); 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric Name += Suffix; 600b57cec5SDimitry Andric MCSymbol *Sym = Ctx.getOrCreateSymbol(Name); 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric // If the symbol reference is actually to a non_lazy_ptr, not to the symbol, 630b57cec5SDimitry Andric // then add the suffix. 640b57cec5SDimitry Andric if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG) { 650b57cec5SDimitry Andric MachineModuleInfoMachO &MachO = getMachOMMI(AP); 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric MachineModuleInfoImpl::StubValueTy &StubSym = MachO.getGVStubEntry(Sym); 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric if (!StubSym.getPointer()) { 700b57cec5SDimitry Andric assert(MO.isGlobal() && "Extern symbol not handled yet"); 710b57cec5SDimitry Andric StubSym = MachineModuleInfoImpl:: 720b57cec5SDimitry Andric StubValueTy(AP.getSymbol(MO.getGlobal()), 730b57cec5SDimitry Andric !MO.getGlobal()->hasInternalLinkage()); 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric return Sym; 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric return Sym; 790b57cec5SDimitry Andric } 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, 82*8bcb0991SDimitry Andric AsmPrinter &Printer, bool IsDarwin) { 830b57cec5SDimitry Andric MCContext &Ctx = Printer.OutContext; 840b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric unsigned access = MO.getTargetFlags() & PPCII::MO_ACCESS_MASK; 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric switch (access) { 890b57cec5SDimitry Andric case PPCII::MO_TPREL_LO: 900b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TPREL_LO; 910b57cec5SDimitry Andric break; 920b57cec5SDimitry Andric case PPCII::MO_TPREL_HA: 930b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TPREL_HA; 940b57cec5SDimitry Andric break; 950b57cec5SDimitry Andric case PPCII::MO_DTPREL_LO: 960b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_DTPREL_LO; 970b57cec5SDimitry Andric break; 980b57cec5SDimitry Andric case PPCII::MO_TLSLD_LO: 990b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO; 1000b57cec5SDimitry Andric break; 1010b57cec5SDimitry Andric case PPCII::MO_TOC_LO: 1020b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO; 1030b57cec5SDimitry Andric break; 1040b57cec5SDimitry Andric case PPCII::MO_TLS: 1050b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TLS; 1060b57cec5SDimitry Andric break; 1070b57cec5SDimitry Andric } 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric if (MO.getTargetFlags() == PPCII::MO_PLT) 1100b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PLT; 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric const MachineFunction *MF = MO.getParent()->getParent()->getParent(); 1130b57cec5SDimitry Andric const Module *M = MF->getFunction().getParent(); 1140b57cec5SDimitry Andric const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>()); 1150b57cec5SDimitry Andric const TargetMachine &TM = Printer.TM; 1160b57cec5SDimitry Andric const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, RefKind, Ctx); 1170b57cec5SDimitry Andric // If -msecure-plt -fPIC, add 32768 to symbol. 1180b57cec5SDimitry Andric if (Subtarget->isSecurePlt() && TM.isPositionIndependent() && 1190b57cec5SDimitry Andric M->getPICLevel() == PICLevel::BigPIC && 1200b57cec5SDimitry Andric MO.getTargetFlags() == PPCII::MO_PLT) 1210b57cec5SDimitry Andric Expr = 1220b57cec5SDimitry Andric MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(32768, Ctx), Ctx); 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric if (!MO.isJTI() && MO.getOffset()) 1250b57cec5SDimitry Andric Expr = MCBinaryExpr::createAdd(Expr, 1260b57cec5SDimitry Andric MCConstantExpr::create(MO.getOffset(), Ctx), 1270b57cec5SDimitry Andric Ctx); 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric // Subtract off the PIC base if required. 1300b57cec5SDimitry Andric if (MO.getTargetFlags() & PPCII::MO_PIC_FLAG) { 1310b57cec5SDimitry Andric const MachineFunction *MF = MO.getParent()->getParent()->getParent(); 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric const MCExpr *PB = MCSymbolRefExpr::create(MF->getPICBaseSymbol(), Ctx); 1340b57cec5SDimitry Andric Expr = MCBinaryExpr::createSub(Expr, PB, Ctx); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric // Add ha16() / lo16() markers if required. 1380b57cec5SDimitry Andric switch (access) { 1390b57cec5SDimitry Andric case PPCII::MO_LO: 140*8bcb0991SDimitry Andric Expr = PPCMCExpr::createLo(Expr, IsDarwin, Ctx); 1410b57cec5SDimitry Andric break; 1420b57cec5SDimitry Andric case PPCII::MO_HA: 143*8bcb0991SDimitry Andric Expr = PPCMCExpr::createHa(Expr, IsDarwin, Ctx); 1440b57cec5SDimitry Andric break; 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric return MCOperand::createExpr(Expr); 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, 151*8bcb0991SDimitry Andric AsmPrinter &AP, bool IsDarwin) { 1520b57cec5SDimitry Andric OutMI.setOpcode(MI->getOpcode()); 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 1550b57cec5SDimitry Andric MCOperand MCOp; 1560b57cec5SDimitry Andric if (LowerPPCMachineOperandToMCOperand(MI->getOperand(i), MCOp, AP, 157*8bcb0991SDimitry Andric IsDarwin)) 1580b57cec5SDimitry Andric OutMI.addOperand(MCOp); 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric bool llvm::LowerPPCMachineOperandToMCOperand(const MachineOperand &MO, 1630b57cec5SDimitry Andric MCOperand &OutMO, AsmPrinter &AP, 164*8bcb0991SDimitry Andric bool IsDarwin) { 1650b57cec5SDimitry Andric switch (MO.getType()) { 1660b57cec5SDimitry Andric default: 1670b57cec5SDimitry Andric llvm_unreachable("unknown operand type"); 1680b57cec5SDimitry Andric case MachineOperand::MO_Register: 1690b57cec5SDimitry Andric assert(!MO.getSubReg() && "Subregs should be eliminated!"); 1700b57cec5SDimitry Andric assert(MO.getReg() > PPC::NoRegister && 1710b57cec5SDimitry Andric MO.getReg() < PPC::NUM_TARGET_REGS && 1720b57cec5SDimitry Andric "Invalid register for this target!"); 1730b57cec5SDimitry Andric OutMO = MCOperand::createReg(MO.getReg()); 1740b57cec5SDimitry Andric return true; 1750b57cec5SDimitry Andric case MachineOperand::MO_Immediate: 1760b57cec5SDimitry Andric OutMO = MCOperand::createImm(MO.getImm()); 1770b57cec5SDimitry Andric return true; 1780b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 1790b57cec5SDimitry Andric OutMO = MCOperand::createExpr( 1800b57cec5SDimitry Andric MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), AP.OutContext)); 1810b57cec5SDimitry Andric return true; 1820b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress: 1830b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol: 184*8bcb0991SDimitry Andric OutMO = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP, IsDarwin); 1850b57cec5SDimitry Andric return true; 1860b57cec5SDimitry Andric case MachineOperand::MO_JumpTableIndex: 187*8bcb0991SDimitry Andric OutMO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP, IsDarwin); 1880b57cec5SDimitry Andric return true; 1890b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 190*8bcb0991SDimitry Andric OutMO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP, IsDarwin); 1910b57cec5SDimitry Andric return true; 1920b57cec5SDimitry Andric case MachineOperand::MO_BlockAddress: 1930b57cec5SDimitry Andric OutMO = GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP, 194*8bcb0991SDimitry Andric IsDarwin); 195*8bcb0991SDimitry Andric return true; 196*8bcb0991SDimitry Andric case MachineOperand::MO_MCSymbol: 197*8bcb0991SDimitry Andric OutMO = GetSymbolRef(MO, MO.getMCSymbol(), AP, IsDarwin); 1980b57cec5SDimitry Andric return true; 1990b57cec5SDimitry Andric case MachineOperand::MO_RegisterMask: 2000b57cec5SDimitry Andric return false; 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric } 203