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, 54*5ffd83dbSDimitry 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: 770b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_TLS; 780b57cec5SDimitry Andric break; 790b57cec5SDimitry Andric } 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric if (MO.getTargetFlags() == PPCII::MO_PLT) 820b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PLT; 83*5ffd83dbSDimitry Andric else if (MO.getTargetFlags() == PPCII::MO_PCREL_FLAG) 84*5ffd83dbSDimitry Andric RefKind = MCSymbolRefExpr::VK_PCREL; 85*5ffd83dbSDimitry Andric else if (MO.getTargetFlags() == (PPCII::MO_PCREL_FLAG | PPCII::MO_GOT_FLAG)) 86*5ffd83dbSDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_GOT_PCREL; 870b57cec5SDimitry Andric 88*5ffd83dbSDimitry Andric const MachineInstr *MI = MO.getParent(); 89*5ffd83dbSDimitry Andric const MachineFunction *MF = MI->getMF(); 900b57cec5SDimitry Andric const Module *M = MF->getFunction().getParent(); 910b57cec5SDimitry Andric const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>()); 920b57cec5SDimitry Andric const TargetMachine &TM = Printer.TM; 93*5ffd83dbSDimitry Andric 94*5ffd83dbSDimitry Andric unsigned MIOpcode = MI->getOpcode(); 95*5ffd83dbSDimitry Andric assert((Subtarget->isUsingPCRelativeCalls() || MIOpcode != PPC::BL8_NOTOC) && 96*5ffd83dbSDimitry Andric "BL8_NOTOC is only valid when using PC Relative Calls."); 97*5ffd83dbSDimitry Andric if (Subtarget->isUsingPCRelativeCalls()) { 98*5ffd83dbSDimitry Andric if (MIOpcode == PPC::TAILB || MIOpcode == PPC::TAILB8 || 99*5ffd83dbSDimitry Andric MIOpcode == PPC::TCRETURNdi || MIOpcode == PPC::TCRETURNdi8 || 100*5ffd83dbSDimitry Andric MIOpcode == PPC::BL8_NOTOC) { 101*5ffd83dbSDimitry Andric RefKind = MCSymbolRefExpr::VK_PPC_NOTOC; 102*5ffd83dbSDimitry Andric } 103*5ffd83dbSDimitry Andric } 104*5ffd83dbSDimitry Andric 1050b57cec5SDimitry Andric const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, RefKind, Ctx); 1060b57cec5SDimitry Andric // If -msecure-plt -fPIC, add 32768 to symbol. 1070b57cec5SDimitry Andric if (Subtarget->isSecurePlt() && TM.isPositionIndependent() && 1080b57cec5SDimitry Andric M->getPICLevel() == PICLevel::BigPIC && 1090b57cec5SDimitry Andric MO.getTargetFlags() == PPCII::MO_PLT) 1100b57cec5SDimitry Andric Expr = 1110b57cec5SDimitry Andric MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(32768, Ctx), Ctx); 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric if (!MO.isJTI() && MO.getOffset()) 1140b57cec5SDimitry Andric Expr = MCBinaryExpr::createAdd(Expr, 1150b57cec5SDimitry Andric MCConstantExpr::create(MO.getOffset(), Ctx), 1160b57cec5SDimitry Andric Ctx); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric // Subtract off the PIC base if required. 1190b57cec5SDimitry Andric if (MO.getTargetFlags() & PPCII::MO_PIC_FLAG) { 1200b57cec5SDimitry Andric const MachineFunction *MF = MO.getParent()->getParent()->getParent(); 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric const MCExpr *PB = MCSymbolRefExpr::create(MF->getPICBaseSymbol(), Ctx); 1230b57cec5SDimitry Andric Expr = MCBinaryExpr::createSub(Expr, PB, Ctx); 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric // Add ha16() / lo16() markers if required. 1270b57cec5SDimitry Andric switch (access) { 1280b57cec5SDimitry Andric case PPCII::MO_LO: 129*5ffd83dbSDimitry Andric Expr = PPCMCExpr::createLo(Expr, Ctx); 1300b57cec5SDimitry Andric break; 1310b57cec5SDimitry Andric case PPCII::MO_HA: 132*5ffd83dbSDimitry Andric Expr = PPCMCExpr::createHa(Expr, Ctx); 1330b57cec5SDimitry Andric break; 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric return MCOperand::createExpr(Expr); 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, 140*5ffd83dbSDimitry Andric AsmPrinter &AP) { 1410b57cec5SDimitry Andric OutMI.setOpcode(MI->getOpcode()); 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 1440b57cec5SDimitry Andric MCOperand MCOp; 145*5ffd83dbSDimitry Andric if (LowerPPCMachineOperandToMCOperand(MI->getOperand(i), MCOp, AP)) 1460b57cec5SDimitry Andric OutMI.addOperand(MCOp); 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric bool llvm::LowerPPCMachineOperandToMCOperand(const MachineOperand &MO, 151*5ffd83dbSDimitry Andric MCOperand &OutMO, AsmPrinter &AP) { 1520b57cec5SDimitry Andric switch (MO.getType()) { 1530b57cec5SDimitry Andric default: 1540b57cec5SDimitry Andric llvm_unreachable("unknown operand type"); 1550b57cec5SDimitry Andric case MachineOperand::MO_Register: 1560b57cec5SDimitry Andric assert(!MO.getSubReg() && "Subregs should be eliminated!"); 1570b57cec5SDimitry Andric assert(MO.getReg() > PPC::NoRegister && 1580b57cec5SDimitry Andric MO.getReg() < PPC::NUM_TARGET_REGS && 1590b57cec5SDimitry Andric "Invalid register for this target!"); 160*5ffd83dbSDimitry Andric // Ignore all implicit register operands. 161*5ffd83dbSDimitry Andric if (MO.isImplicit()) 162*5ffd83dbSDimitry Andric return false; 1630b57cec5SDimitry Andric OutMO = MCOperand::createReg(MO.getReg()); 1640b57cec5SDimitry Andric return true; 1650b57cec5SDimitry Andric case MachineOperand::MO_Immediate: 1660b57cec5SDimitry Andric OutMO = MCOperand::createImm(MO.getImm()); 1670b57cec5SDimitry Andric return true; 1680b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 1690b57cec5SDimitry Andric OutMO = MCOperand::createExpr( 1700b57cec5SDimitry Andric MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), AP.OutContext)); 1710b57cec5SDimitry Andric return true; 1720b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress: 1730b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol: 174*5ffd83dbSDimitry Andric OutMO = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP); 1750b57cec5SDimitry Andric return true; 1760b57cec5SDimitry Andric case MachineOperand::MO_JumpTableIndex: 177*5ffd83dbSDimitry Andric OutMO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP); 1780b57cec5SDimitry Andric return true; 1790b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 180*5ffd83dbSDimitry Andric OutMO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP); 1810b57cec5SDimitry Andric return true; 1820b57cec5SDimitry Andric case MachineOperand::MO_BlockAddress: 183*5ffd83dbSDimitry Andric OutMO = 184*5ffd83dbSDimitry Andric GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP); 1858bcb0991SDimitry Andric return true; 1868bcb0991SDimitry Andric case MachineOperand::MO_MCSymbol: 187*5ffd83dbSDimitry Andric OutMO = GetSymbolRef(MO, MO.getMCSymbol(), AP); 1880b57cec5SDimitry Andric return true; 1890b57cec5SDimitry Andric case MachineOperand::MO_RegisterMask: 1900b57cec5SDimitry Andric return false; 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric } 193