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 MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, 330b57cec5SDimitry Andric AsmPrinter &AP) { 34*5f757f3fSDimitry Andric if (MO.isGlobal()) { 35*5f757f3fSDimitry Andric // Get the symbol from the global, accounting for XCOFF-specific 36*5f757f3fSDimitry Andric // intricacies (see TargetLoweringObjectFileXCOFF::getTargetSymbol). 370b57cec5SDimitry Andric const GlobalValue *GV = MO.getGlobal(); 38*5f757f3fSDimitry Andric return AP.getSymbol(GV); 390b57cec5SDimitry Andric } 400b57cec5SDimitry Andric 41*5f757f3fSDimitry Andric assert(MO.isSymbol() && "Isn't a symbol reference"); 420b57cec5SDimitry Andric 43*5f757f3fSDimitry Andric SmallString<128> Name; 44*5f757f3fSDimitry Andric const DataLayout &DL = AP.getDataLayout(); 45*5f757f3fSDimitry Andric Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL); 46*5f757f3fSDimitry Andric 47*5f757f3fSDimitry Andric MCContext &Ctx = AP.OutContext; 48*5f757f3fSDimitry Andric MCSymbol *Sym = Ctx.getOrCreateSymbol(Name); 490b57cec5SDimitry Andric return Sym; 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, 535ffd83dbSDimitry Andric AsmPrinter &Printer) { 540b57cec5SDimitry Andric MCContext &Ctx = Printer.OutContext; 550b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; 560b57cec5SDimitry Andric 57*5f757f3fSDimitry Andric unsigned access = MO.getTargetFlags(); 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric switch (access) { 600b57cec5SDimitry Andric case PPCII::MO_TPREL_LO: 610b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TPREL_LO; 620b57cec5SDimitry Andric break; 630b57cec5SDimitry Andric case PPCII::MO_TPREL_HA: 640b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TPREL_HA; 650b57cec5SDimitry Andric break; 660b57cec5SDimitry Andric case PPCII::MO_DTPREL_LO: 670b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_DTPREL_LO; 680b57cec5SDimitry Andric break; 690b57cec5SDimitry Andric case PPCII::MO_TLSLD_LO: 700b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO; 710b57cec5SDimitry Andric break; 720b57cec5SDimitry Andric case PPCII::MO_TOC_LO: 730b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO; 740b57cec5SDimitry Andric break; 750b57cec5SDimitry Andric case PPCII::MO_TLS: 76*5f757f3fSDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TLS; 77*5f757f3fSDimitry Andric break; 78*5f757f3fSDimitry Andric case PPCII::MO_TLS_PCREL_FLAG: 79*5f757f3fSDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TLS_PCREL; 800b57cec5SDimitry Andric break; 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric 83*5f757f3fSDimitry Andric const TargetMachine &TM = Printer.TM; 84*5f757f3fSDimitry Andric 850b57cec5SDimitry Andric if (MO.getTargetFlags() == PPCII::MO_PLT) 860b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PLT; 875ffd83dbSDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_PCREL_FLAG) 885ffd83dbSDimitry Andric RefKind = MCSymbolRefExpr::VK_PCREL; 89*5f757f3fSDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_GOT_PCREL_FLAG) 905ffd83dbSDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_GOT_PCREL; 91*5f757f3fSDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_TPREL_PCREL_FLAG) 92e8d8bef9SDimitry Andric RefKind = MCSymbolRefExpr::VK_TPREL; 93e8d8bef9SDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG) 94e8d8bef9SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL; 95e8d8bef9SDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSLD_PCREL_FLAG) 96e8d8bef9SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL; 97e8d8bef9SDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_GOT_TPREL_PCREL_FLAG) 98e8d8bef9SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL; 99*5f757f3fSDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_TPREL_FLAG) { 100*5f757f3fSDimitry Andric assert(MO.isGlobal() && "Only expecting a global MachineOperand here!"); 101*5f757f3fSDimitry Andric TLSModel::Model Model = TM.getTLSModel(MO.getGlobal()); 102*5f757f3fSDimitry Andric // For the local-exec TLS model, we may generate the offset from the TLS 103*5f757f3fSDimitry Andric // base as an immediate operand (instead of using a TOC entry). 104*5f757f3fSDimitry Andric // Set the relocation type in case the result is used for purposes other 105*5f757f3fSDimitry Andric // than a TOC reference. In TOC reference cases, this result is discarded. 106*5f757f3fSDimitry Andric if (Model == TLSModel::LocalExec) 107*5f757f3fSDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_AIX_TLSLE; 108*5f757f3fSDimitry Andric } 1090b57cec5SDimitry Andric 1105ffd83dbSDimitry Andric const MachineInstr *MI = MO.getParent(); 1115ffd83dbSDimitry Andric const MachineFunction *MF = MI->getMF(); 1120b57cec5SDimitry Andric const Module *M = MF->getFunction().getParent(); 1130b57cec5SDimitry Andric const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>()); 1145ffd83dbSDimitry Andric 1155ffd83dbSDimitry Andric unsigned MIOpcode = MI->getOpcode(); 1165ffd83dbSDimitry Andric assert((Subtarget->isUsingPCRelativeCalls() || MIOpcode != PPC::BL8_NOTOC) && 1175ffd83dbSDimitry Andric "BL8_NOTOC is only valid when using PC Relative Calls."); 1185ffd83dbSDimitry Andric if (Subtarget->isUsingPCRelativeCalls()) { 1195ffd83dbSDimitry Andric if (MIOpcode == PPC::TAILB || MIOpcode == PPC::TAILB8 || 1205ffd83dbSDimitry Andric MIOpcode == PPC::TCRETURNdi || MIOpcode == PPC::TCRETURNdi8 || 12181ad6265SDimitry Andric MIOpcode == PPC::BL8_NOTOC || MIOpcode == PPC::BL8_NOTOC_RM) { 1225ffd83dbSDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_NOTOC; 1235ffd83dbSDimitry Andric } 124e8d8bef9SDimitry Andric if (MO.getTargetFlags() == PPCII::MO_PCREL_OPT_FLAG) 125e8d8bef9SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_PCREL_OPT; 1265ffd83dbSDimitry Andric } 1275ffd83dbSDimitry Andric 1280b57cec5SDimitry Andric const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, RefKind, Ctx); 1290b57cec5SDimitry Andric // If -msecure-plt -fPIC, add 32768 to symbol. 1300b57cec5SDimitry Andric if (Subtarget->isSecurePlt() && TM.isPositionIndependent() && 1310b57cec5SDimitry Andric M->getPICLevel() == PICLevel::BigPIC && 1320b57cec5SDimitry Andric MO.getTargetFlags() == PPCII::MO_PLT) 1330b57cec5SDimitry Andric Expr = 1340b57cec5SDimitry Andric MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(32768, Ctx), Ctx); 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric if (!MO.isJTI() && MO.getOffset()) 1370b57cec5SDimitry Andric Expr = MCBinaryExpr::createAdd(Expr, 1380b57cec5SDimitry Andric MCConstantExpr::create(MO.getOffset(), Ctx), 1390b57cec5SDimitry Andric Ctx); 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric // Subtract off the PIC base if required. 142*5f757f3fSDimitry Andric if (MO.getTargetFlags() == PPCII::MO_PIC_FLAG || 143*5f757f3fSDimitry Andric MO.getTargetFlags() == PPCII::MO_PIC_HA_FLAG || 144*5f757f3fSDimitry Andric MO.getTargetFlags() == PPCII::MO_PIC_LO_FLAG) { 1450b57cec5SDimitry Andric const MachineFunction *MF = MO.getParent()->getParent()->getParent(); 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric const MCExpr *PB = MCSymbolRefExpr::create(MF->getPICBaseSymbol(), Ctx); 1480b57cec5SDimitry Andric Expr = MCBinaryExpr::createSub(Expr, PB, Ctx); 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric // Add ha16() / lo16() markers if required. 1520b57cec5SDimitry Andric switch (access) { 1530b57cec5SDimitry Andric case PPCII::MO_LO: 154*5f757f3fSDimitry Andric case PPCII::MO_PIC_LO_FLAG: 1555ffd83dbSDimitry Andric Expr = PPCMCExpr::createLo(Expr, Ctx); 1560b57cec5SDimitry Andric break; 1570b57cec5SDimitry Andric case PPCII::MO_HA: 158*5f757f3fSDimitry Andric case PPCII::MO_PIC_HA_FLAG: 1595ffd83dbSDimitry Andric Expr = PPCMCExpr::createHa(Expr, Ctx); 1600b57cec5SDimitry Andric break; 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric return MCOperand::createExpr(Expr); 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, 1675ffd83dbSDimitry Andric AsmPrinter &AP) { 1680b57cec5SDimitry Andric OutMI.setOpcode(MI->getOpcode()); 1690b57cec5SDimitry Andric 1704824e7fdSDimitry Andric for (const MachineOperand &MO : MI->operands()) { 1710b57cec5SDimitry Andric MCOperand MCOp; 1724824e7fdSDimitry Andric if (LowerPPCMachineOperandToMCOperand(MO, MCOp, AP)) 1730b57cec5SDimitry Andric OutMI.addOperand(MCOp); 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric bool llvm::LowerPPCMachineOperandToMCOperand(const MachineOperand &MO, 1785ffd83dbSDimitry Andric MCOperand &OutMO, AsmPrinter &AP) { 1790b57cec5SDimitry Andric switch (MO.getType()) { 1800b57cec5SDimitry Andric default: 1810b57cec5SDimitry Andric llvm_unreachable("unknown operand type"); 1820b57cec5SDimitry Andric case MachineOperand::MO_Register: 1830b57cec5SDimitry Andric assert(!MO.getSubReg() && "Subregs should be eliminated!"); 1840b57cec5SDimitry Andric assert(MO.getReg() > PPC::NoRegister && 1850b57cec5SDimitry Andric MO.getReg() < PPC::NUM_TARGET_REGS && 1860b57cec5SDimitry Andric "Invalid register for this target!"); 1875ffd83dbSDimitry Andric // Ignore all implicit register operands. 1885ffd83dbSDimitry Andric if (MO.isImplicit()) 1895ffd83dbSDimitry Andric return false; 1900b57cec5SDimitry Andric OutMO = MCOperand::createReg(MO.getReg()); 1910b57cec5SDimitry Andric return true; 1920b57cec5SDimitry Andric case MachineOperand::MO_Immediate: 1930b57cec5SDimitry Andric OutMO = MCOperand::createImm(MO.getImm()); 1940b57cec5SDimitry Andric return true; 1950b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 1960b57cec5SDimitry Andric OutMO = MCOperand::createExpr( 1970b57cec5SDimitry Andric MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), AP.OutContext)); 1980b57cec5SDimitry Andric return true; 1990b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress: 2000b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol: 2015ffd83dbSDimitry Andric OutMO = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP); 2020b57cec5SDimitry Andric return true; 2030b57cec5SDimitry Andric case MachineOperand::MO_JumpTableIndex: 2045ffd83dbSDimitry Andric OutMO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP); 2050b57cec5SDimitry Andric return true; 2060b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 2075ffd83dbSDimitry Andric OutMO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP); 2080b57cec5SDimitry Andric return true; 2090b57cec5SDimitry Andric case MachineOperand::MO_BlockAddress: 2105ffd83dbSDimitry Andric OutMO = 2115ffd83dbSDimitry Andric GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP); 2128bcb0991SDimitry Andric return true; 2138bcb0991SDimitry Andric case MachineOperand::MO_MCSymbol: 2145ffd83dbSDimitry Andric OutMO = GetSymbolRef(MO, MO.getMCSymbol(), AP); 2150b57cec5SDimitry Andric return true; 2160b57cec5SDimitry Andric case MachineOperand::MO_RegisterMask: 2170b57cec5SDimitry Andric return false; 2180b57cec5SDimitry Andric } 2190b57cec5SDimitry Andric } 220