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" 16*0fca6ea1SDimitry Andric #include "PPCMachineFunctionInfo.h" 170b57cec5SDimitry Andric #include "PPCSubtarget.h" 180b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 190b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h" 240b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 250b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h" 260b57cec5SDimitry Andric #include "llvm/IR/Mangler.h" 27*0fca6ea1SDimitry Andric #include "llvm/IR/Module.h" 280b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 290b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 300b57cec5SDimitry Andric #include "llvm/MC/MCInst.h" 310b57cec5SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h" 320b57cec5SDimitry Andric using namespace llvm; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, 350b57cec5SDimitry Andric AsmPrinter &AP) { 365f757f3fSDimitry Andric if (MO.isGlobal()) { 375f757f3fSDimitry Andric // Get the symbol from the global, accounting for XCOFF-specific 385f757f3fSDimitry Andric // intricacies (see TargetLoweringObjectFileXCOFF::getTargetSymbol). 390b57cec5SDimitry Andric const GlobalValue *GV = MO.getGlobal(); 405f757f3fSDimitry Andric return AP.getSymbol(GV); 410b57cec5SDimitry Andric } 420b57cec5SDimitry Andric 435f757f3fSDimitry Andric assert(MO.isSymbol() && "Isn't a symbol reference"); 440b57cec5SDimitry Andric 455f757f3fSDimitry Andric SmallString<128> Name; 465f757f3fSDimitry Andric const DataLayout &DL = AP.getDataLayout(); 475f757f3fSDimitry Andric Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL); 485f757f3fSDimitry Andric 495f757f3fSDimitry Andric MCContext &Ctx = AP.OutContext; 505f757f3fSDimitry Andric MCSymbol *Sym = Ctx.getOrCreateSymbol(Name); 510b57cec5SDimitry Andric return Sym; 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, 555ffd83dbSDimitry Andric AsmPrinter &Printer) { 560b57cec5SDimitry Andric MCContext &Ctx = Printer.OutContext; 570b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; 580b57cec5SDimitry Andric 595f757f3fSDimitry Andric unsigned access = MO.getTargetFlags(); 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric switch (access) { 620b57cec5SDimitry Andric case PPCII::MO_TPREL_LO: 630b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TPREL_LO; 640b57cec5SDimitry Andric break; 650b57cec5SDimitry Andric case PPCII::MO_TPREL_HA: 660b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TPREL_HA; 670b57cec5SDimitry Andric break; 680b57cec5SDimitry Andric case PPCII::MO_DTPREL_LO: 690b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_DTPREL_LO; 700b57cec5SDimitry Andric break; 710b57cec5SDimitry Andric case PPCII::MO_TLSLD_LO: 720b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO; 730b57cec5SDimitry Andric break; 740b57cec5SDimitry Andric case PPCII::MO_TOC_LO: 750b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO; 760b57cec5SDimitry Andric break; 770b57cec5SDimitry Andric case PPCII::MO_TLS: 785f757f3fSDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TLS; 795f757f3fSDimitry Andric break; 805f757f3fSDimitry Andric case PPCII::MO_TLS_PCREL_FLAG: 815f757f3fSDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TLS_PCREL; 820b57cec5SDimitry Andric break; 830b57cec5SDimitry Andric } 840b57cec5SDimitry Andric 855f757f3fSDimitry Andric const TargetMachine &TM = Printer.TM; 86*0fca6ea1SDimitry Andric const MachineInstr *MI = MO.getParent(); 87*0fca6ea1SDimitry Andric const MachineFunction *MF = MI->getMF(); 885f757f3fSDimitry Andric 890b57cec5SDimitry Andric if (MO.getTargetFlags() == PPCII::MO_PLT) 900b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PLT; 915ffd83dbSDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_PCREL_FLAG) 925ffd83dbSDimitry Andric RefKind = MCSymbolRefExpr::VK_PCREL; 935f757f3fSDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_GOT_PCREL_FLAG) 945ffd83dbSDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_GOT_PCREL; 955f757f3fSDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_TPREL_PCREL_FLAG) 96e8d8bef9SDimitry Andric RefKind = MCSymbolRefExpr::VK_TPREL; 97e8d8bef9SDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG) 98e8d8bef9SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL; 99e8d8bef9SDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSLD_PCREL_FLAG) 100e8d8bef9SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL; 101e8d8bef9SDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_GOT_TPREL_PCREL_FLAG) 102e8d8bef9SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL; 103*0fca6ea1SDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_TPREL_FLAG || 104*0fca6ea1SDimitry Andric MO.getTargetFlags() == PPCII::MO_TLSLD_FLAG) { 1055f757f3fSDimitry Andric assert(MO.isGlobal() && "Only expecting a global MachineOperand here!"); 1065f757f3fSDimitry Andric TLSModel::Model Model = TM.getTLSModel(MO.getGlobal()); 107*0fca6ea1SDimitry Andric const PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>(); 108*0fca6ea1SDimitry Andric // For the local-[exec|dynamic] TLS model, we may generate the offset from 109*0fca6ea1SDimitry Andric // the TLS base as an immediate operand (instead of using a TOC entry). Set 110*0fca6ea1SDimitry Andric // the relocation type in case the result is used for purposes other than a 111*0fca6ea1SDimitry Andric // TOC reference. In TOC reference cases, this result is discarded. 1125f757f3fSDimitry Andric if (Model == TLSModel::LocalExec) 1135f757f3fSDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_AIX_TLSLE; 114*0fca6ea1SDimitry Andric else if (Model == TLSModel::LocalDynamic && 115*0fca6ea1SDimitry Andric FuncInfo->isAIXFuncUseTLSIEForLD()) 116*0fca6ea1SDimitry Andric // On AIX, TLS model opt may have turned local-dynamic accesses into 117*0fca6ea1SDimitry Andric // initial-exec accesses. 118*0fca6ea1SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_AIX_TLSIE; 119*0fca6ea1SDimitry Andric else if (Model == TLSModel::LocalDynamic) 120*0fca6ea1SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_AIX_TLSLD; 1215f757f3fSDimitry Andric } 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric const Module *M = MF->getFunction().getParent(); 1240b57cec5SDimitry Andric const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>()); 1255ffd83dbSDimitry Andric 1265ffd83dbSDimitry Andric unsigned MIOpcode = MI->getOpcode(); 1275ffd83dbSDimitry Andric assert((Subtarget->isUsingPCRelativeCalls() || MIOpcode != PPC::BL8_NOTOC) && 1285ffd83dbSDimitry Andric "BL8_NOTOC is only valid when using PC Relative Calls."); 1295ffd83dbSDimitry Andric if (Subtarget->isUsingPCRelativeCalls()) { 1305ffd83dbSDimitry Andric if (MIOpcode == PPC::TAILB || MIOpcode == PPC::TAILB8 || 1315ffd83dbSDimitry Andric MIOpcode == PPC::TCRETURNdi || MIOpcode == PPC::TCRETURNdi8 || 13281ad6265SDimitry Andric MIOpcode == PPC::BL8_NOTOC || MIOpcode == PPC::BL8_NOTOC_RM) { 1335ffd83dbSDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_NOTOC; 1345ffd83dbSDimitry Andric } 135e8d8bef9SDimitry Andric if (MO.getTargetFlags() == PPCII::MO_PCREL_OPT_FLAG) 136e8d8bef9SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_PCREL_OPT; 1375ffd83dbSDimitry Andric } 1385ffd83dbSDimitry Andric 1390b57cec5SDimitry Andric const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, RefKind, Ctx); 1400b57cec5SDimitry Andric // If -msecure-plt -fPIC, add 32768 to symbol. 1410b57cec5SDimitry Andric if (Subtarget->isSecurePlt() && TM.isPositionIndependent() && 1420b57cec5SDimitry Andric M->getPICLevel() == PICLevel::BigPIC && 1430b57cec5SDimitry Andric MO.getTargetFlags() == PPCII::MO_PLT) 1440b57cec5SDimitry Andric Expr = 1450b57cec5SDimitry Andric MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(32768, Ctx), Ctx); 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric if (!MO.isJTI() && MO.getOffset()) 1480b57cec5SDimitry Andric Expr = MCBinaryExpr::createAdd(Expr, 1490b57cec5SDimitry Andric MCConstantExpr::create(MO.getOffset(), Ctx), 1500b57cec5SDimitry Andric Ctx); 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric // Subtract off the PIC base if required. 1535f757f3fSDimitry Andric if (MO.getTargetFlags() == PPCII::MO_PIC_FLAG || 1545f757f3fSDimitry Andric MO.getTargetFlags() == PPCII::MO_PIC_HA_FLAG || 1555f757f3fSDimitry Andric MO.getTargetFlags() == PPCII::MO_PIC_LO_FLAG) { 1560b57cec5SDimitry Andric const MachineFunction *MF = MO.getParent()->getParent()->getParent(); 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric const MCExpr *PB = MCSymbolRefExpr::create(MF->getPICBaseSymbol(), Ctx); 1590b57cec5SDimitry Andric Expr = MCBinaryExpr::createSub(Expr, PB, Ctx); 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric // Add ha16() / lo16() markers if required. 1630b57cec5SDimitry Andric switch (access) { 1640b57cec5SDimitry Andric case PPCII::MO_LO: 1655f757f3fSDimitry Andric case PPCII::MO_PIC_LO_FLAG: 1665ffd83dbSDimitry Andric Expr = PPCMCExpr::createLo(Expr, Ctx); 1670b57cec5SDimitry Andric break; 1680b57cec5SDimitry Andric case PPCII::MO_HA: 1695f757f3fSDimitry Andric case PPCII::MO_PIC_HA_FLAG: 1705ffd83dbSDimitry Andric Expr = PPCMCExpr::createHa(Expr, Ctx); 1710b57cec5SDimitry Andric break; 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric return MCOperand::createExpr(Expr); 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, 1785ffd83dbSDimitry Andric AsmPrinter &AP) { 1790b57cec5SDimitry Andric OutMI.setOpcode(MI->getOpcode()); 1800b57cec5SDimitry Andric 1814824e7fdSDimitry Andric for (const MachineOperand &MO : MI->operands()) { 1820b57cec5SDimitry Andric MCOperand MCOp; 1834824e7fdSDimitry Andric if (LowerPPCMachineOperandToMCOperand(MO, MCOp, AP)) 1840b57cec5SDimitry Andric OutMI.addOperand(MCOp); 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric bool llvm::LowerPPCMachineOperandToMCOperand(const MachineOperand &MO, 1895ffd83dbSDimitry Andric MCOperand &OutMO, AsmPrinter &AP) { 1900b57cec5SDimitry Andric switch (MO.getType()) { 1910b57cec5SDimitry Andric default: 1920b57cec5SDimitry Andric llvm_unreachable("unknown operand type"); 1930b57cec5SDimitry Andric case MachineOperand::MO_Register: 1940b57cec5SDimitry Andric assert(!MO.getSubReg() && "Subregs should be eliminated!"); 1950b57cec5SDimitry Andric assert(MO.getReg() > PPC::NoRegister && 1960b57cec5SDimitry Andric MO.getReg() < PPC::NUM_TARGET_REGS && 1970b57cec5SDimitry Andric "Invalid register for this target!"); 1985ffd83dbSDimitry Andric // Ignore all implicit register operands. 1995ffd83dbSDimitry Andric if (MO.isImplicit()) 2005ffd83dbSDimitry Andric return false; 2010b57cec5SDimitry Andric OutMO = MCOperand::createReg(MO.getReg()); 2020b57cec5SDimitry Andric return true; 2030b57cec5SDimitry Andric case MachineOperand::MO_Immediate: 2040b57cec5SDimitry Andric OutMO = MCOperand::createImm(MO.getImm()); 2050b57cec5SDimitry Andric return true; 2060b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 2070b57cec5SDimitry Andric OutMO = MCOperand::createExpr( 2080b57cec5SDimitry Andric MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), AP.OutContext)); 2090b57cec5SDimitry Andric return true; 2100b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress: 2110b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol: 2125ffd83dbSDimitry Andric OutMO = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP); 2130b57cec5SDimitry Andric return true; 2140b57cec5SDimitry Andric case MachineOperand::MO_JumpTableIndex: 2155ffd83dbSDimitry Andric OutMO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP); 2160b57cec5SDimitry Andric return true; 2170b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 2185ffd83dbSDimitry Andric OutMO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP); 2190b57cec5SDimitry Andric return true; 2200b57cec5SDimitry Andric case MachineOperand::MO_BlockAddress: 2215ffd83dbSDimitry Andric OutMO = 2225ffd83dbSDimitry Andric GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP); 2238bcb0991SDimitry Andric return true; 2248bcb0991SDimitry Andric case MachineOperand::MO_MCSymbol: 2255ffd83dbSDimitry Andric OutMO = GetSymbolRef(MO, MO.getMCSymbol(), AP); 2260b57cec5SDimitry Andric return true; 2270b57cec5SDimitry Andric case MachineOperand::MO_RegisterMask: 2280b57cec5SDimitry Andric return false; 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric } 231