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) { 340b57cec5SDimitry Andric const TargetMachine &TM = AP.TM; 350b57cec5SDimitry Andric Mangler &Mang = TM.getObjFileLowering()->getMangler(); 360b57cec5SDimitry Andric const DataLayout &DL = AP.getDataLayout(); 370b57cec5SDimitry Andric MCContext &Ctx = AP.OutContext; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric SmallString<128> Name; 400b57cec5SDimitry Andric if (!MO.isGlobal()) { 410b57cec5SDimitry Andric assert(MO.isSymbol() && "Isn't a symbol reference"); 420b57cec5SDimitry Andric Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL); 430b57cec5SDimitry Andric } else { 440b57cec5SDimitry Andric const GlobalValue *GV = MO.getGlobal(); 450b57cec5SDimitry Andric TM.getNameWithPrefix(Name, GV, Mang); 460b57cec5SDimitry Andric } 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric MCSymbol *Sym = Ctx.getOrCreateSymbol(Name); 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric return Sym; 510b57cec5SDimitry Andric } 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, 545ffd83dbSDimitry Andric AsmPrinter &Printer) { 550b57cec5SDimitry Andric MCContext &Ctx = Printer.OutContext; 560b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric unsigned access = MO.getTargetFlags() & PPCII::MO_ACCESS_MASK; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric switch (access) { 610b57cec5SDimitry Andric case PPCII::MO_TPREL_LO: 620b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TPREL_LO; 630b57cec5SDimitry Andric break; 640b57cec5SDimitry Andric case PPCII::MO_TPREL_HA: 650b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TPREL_HA; 660b57cec5SDimitry Andric break; 670b57cec5SDimitry Andric case PPCII::MO_DTPREL_LO: 680b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_DTPREL_LO; 690b57cec5SDimitry Andric break; 700b57cec5SDimitry Andric case PPCII::MO_TLSLD_LO: 710b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO; 720b57cec5SDimitry Andric break; 730b57cec5SDimitry Andric case PPCII::MO_TOC_LO: 740b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO; 750b57cec5SDimitry Andric break; 760b57cec5SDimitry Andric case PPCII::MO_TLS: 77e8d8bef9SDimitry Andric bool IsPCRel = (MO.getTargetFlags() & ~access) == PPCII::MO_PCREL_FLAG; 78e8d8bef9SDimitry Andric RefKind = IsPCRel ? MCSymbolRefExpr::VK_PPC_TLS_PCREL 79e8d8bef9SDimitry Andric : MCSymbolRefExpr::VK_PPC_TLS; 800b57cec5SDimitry Andric break; 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric if (MO.getTargetFlags() == PPCII::MO_PLT) 840b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PLT; 855ffd83dbSDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_PCREL_FLAG) 865ffd83dbSDimitry Andric RefKind = MCSymbolRefExpr::VK_PCREL; 875ffd83dbSDimitry Andric else if (MO.getTargetFlags() == (PPCII::MO_PCREL_FLAG | PPCII::MO_GOT_FLAG)) 885ffd83dbSDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_GOT_PCREL; 89e8d8bef9SDimitry Andric else if (MO.getTargetFlags() == (PPCII::MO_PCREL_FLAG | PPCII::MO_TPREL_FLAG)) 90e8d8bef9SDimitry Andric RefKind = MCSymbolRefExpr::VK_TPREL; 91e8d8bef9SDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG) 92e8d8bef9SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL; 93e8d8bef9SDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSLD_PCREL_FLAG) 94e8d8bef9SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL; 95e8d8bef9SDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_GOT_TPREL_PCREL_FLAG) 96e8d8bef9SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL; 970b57cec5SDimitry Andric 985ffd83dbSDimitry Andric const MachineInstr *MI = MO.getParent(); 995ffd83dbSDimitry Andric const MachineFunction *MF = MI->getMF(); 1000b57cec5SDimitry Andric const Module *M = MF->getFunction().getParent(); 1010b57cec5SDimitry Andric const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>()); 1020b57cec5SDimitry Andric const TargetMachine &TM = Printer.TM; 1035ffd83dbSDimitry Andric 1045ffd83dbSDimitry Andric unsigned MIOpcode = MI->getOpcode(); 1055ffd83dbSDimitry Andric assert((Subtarget->isUsingPCRelativeCalls() || MIOpcode != PPC::BL8_NOTOC) && 1065ffd83dbSDimitry Andric "BL8_NOTOC is only valid when using PC Relative Calls."); 1075ffd83dbSDimitry Andric if (Subtarget->isUsingPCRelativeCalls()) { 1085ffd83dbSDimitry Andric if (MIOpcode == PPC::TAILB || MIOpcode == PPC::TAILB8 || 1095ffd83dbSDimitry Andric MIOpcode == PPC::TCRETURNdi || MIOpcode == PPC::TCRETURNdi8 || 1105ffd83dbSDimitry Andric MIOpcode == PPC::BL8_NOTOC) { 1115ffd83dbSDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_NOTOC; 1125ffd83dbSDimitry Andric } 113e8d8bef9SDimitry Andric if (MO.getTargetFlags() == PPCII::MO_PCREL_OPT_FLAG) 114e8d8bef9SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_PCREL_OPT; 1155ffd83dbSDimitry Andric } 1165ffd83dbSDimitry Andric 1170b57cec5SDimitry Andric const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, RefKind, Ctx); 1180b57cec5SDimitry Andric // If -msecure-plt -fPIC, add 32768 to symbol. 1190b57cec5SDimitry Andric if (Subtarget->isSecurePlt() && TM.isPositionIndependent() && 1200b57cec5SDimitry Andric M->getPICLevel() == PICLevel::BigPIC && 1210b57cec5SDimitry Andric MO.getTargetFlags() == PPCII::MO_PLT) 1220b57cec5SDimitry Andric Expr = 1230b57cec5SDimitry Andric MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(32768, Ctx), Ctx); 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric if (!MO.isJTI() && MO.getOffset()) 1260b57cec5SDimitry Andric Expr = MCBinaryExpr::createAdd(Expr, 1270b57cec5SDimitry Andric MCConstantExpr::create(MO.getOffset(), Ctx), 1280b57cec5SDimitry Andric Ctx); 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric // Subtract off the PIC base if required. 1310b57cec5SDimitry Andric if (MO.getTargetFlags() & PPCII::MO_PIC_FLAG) { 1320b57cec5SDimitry Andric const MachineFunction *MF = MO.getParent()->getParent()->getParent(); 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric const MCExpr *PB = MCSymbolRefExpr::create(MF->getPICBaseSymbol(), Ctx); 1350b57cec5SDimitry Andric Expr = MCBinaryExpr::createSub(Expr, PB, Ctx); 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric // Add ha16() / lo16() markers if required. 1390b57cec5SDimitry Andric switch (access) { 1400b57cec5SDimitry Andric case PPCII::MO_LO: 1415ffd83dbSDimitry Andric Expr = PPCMCExpr::createLo(Expr, Ctx); 1420b57cec5SDimitry Andric break; 1430b57cec5SDimitry Andric case PPCII::MO_HA: 1445ffd83dbSDimitry Andric Expr = PPCMCExpr::createHa(Expr, Ctx); 1450b57cec5SDimitry Andric break; 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric return MCOperand::createExpr(Expr); 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, 1525ffd83dbSDimitry Andric AsmPrinter &AP) { 1530b57cec5SDimitry Andric OutMI.setOpcode(MI->getOpcode()); 1540b57cec5SDimitry Andric 1554824e7fdSDimitry Andric for (const MachineOperand &MO : MI->operands()) { 1560b57cec5SDimitry Andric MCOperand MCOp; 1574824e7fdSDimitry Andric if (LowerPPCMachineOperandToMCOperand(MO, MCOp, AP)) 1580b57cec5SDimitry Andric OutMI.addOperand(MCOp); 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric bool llvm::LowerPPCMachineOperandToMCOperand(const MachineOperand &MO, 1635ffd83dbSDimitry Andric MCOperand &OutMO, AsmPrinter &AP) { 1640b57cec5SDimitry Andric switch (MO.getType()) { 1650b57cec5SDimitry Andric default: 1660b57cec5SDimitry Andric llvm_unreachable("unknown operand type"); 1670b57cec5SDimitry Andric case MachineOperand::MO_Register: 1680b57cec5SDimitry Andric assert(!MO.getSubReg() && "Subregs should be eliminated!"); 1690b57cec5SDimitry Andric assert(MO.getReg() > PPC::NoRegister && 1700b57cec5SDimitry Andric MO.getReg() < PPC::NUM_TARGET_REGS && 1710b57cec5SDimitry Andric "Invalid register for this target!"); 1725ffd83dbSDimitry Andric // Ignore all implicit register operands. 1735ffd83dbSDimitry Andric if (MO.isImplicit()) 1745ffd83dbSDimitry Andric return false; 1750b57cec5SDimitry Andric OutMO = MCOperand::createReg(MO.getReg()); 1760b57cec5SDimitry Andric return true; 1770b57cec5SDimitry Andric case MachineOperand::MO_Immediate: 1780b57cec5SDimitry Andric OutMO = MCOperand::createImm(MO.getImm()); 1790b57cec5SDimitry Andric return true; 1800b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 1810b57cec5SDimitry Andric OutMO = MCOperand::createExpr( 1820b57cec5SDimitry Andric MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), AP.OutContext)); 1830b57cec5SDimitry Andric return true; 1840b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress: 1850b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol: 1865ffd83dbSDimitry Andric OutMO = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP); 1870b57cec5SDimitry Andric return true; 1880b57cec5SDimitry Andric case MachineOperand::MO_JumpTableIndex: 1895ffd83dbSDimitry Andric OutMO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP); 1900b57cec5SDimitry Andric return true; 1910b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 1925ffd83dbSDimitry Andric OutMO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP); 1930b57cec5SDimitry Andric return true; 1940b57cec5SDimitry Andric case MachineOperand::MO_BlockAddress: 1955ffd83dbSDimitry Andric OutMO = 1965ffd83dbSDimitry Andric GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP); 1978bcb0991SDimitry Andric return true; 1988bcb0991SDimitry Andric case MachineOperand::MO_MCSymbol: 1995ffd83dbSDimitry Andric OutMO = GetSymbolRef(MO, MO.getMCSymbol(), AP); 2000b57cec5SDimitry Andric return true; 2010b57cec5SDimitry Andric case MachineOperand::MO_RegisterMask: 2020b57cec5SDimitry Andric return false; 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric } 205