|  | //===-- PPCMCInstLower.cpp - Convert PPC MachineInstr to an MCInst --------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // This file contains code to lower PPC MachineInstrs to their corresponding | 
|  | // MCInst records. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "MCTargetDesc/PPCMCExpr.h" | 
|  | #include "PPC.h" | 
|  | #include "PPCSubtarget.h" | 
|  | #include "llvm/ADT/SmallString.h" | 
|  | #include "llvm/ADT/Twine.h" | 
|  | #include "llvm/CodeGen/AsmPrinter.h" | 
|  | #include "llvm/CodeGen/MachineFunction.h" | 
|  | #include "llvm/CodeGen/MachineModuleInfoImpls.h" | 
|  | #include "llvm/CodeGen/TargetLowering.h" | 
|  | #include "llvm/IR/DataLayout.h" | 
|  | #include "llvm/IR/GlobalValue.h" | 
|  | #include "llvm/IR/Mangler.h" | 
|  | #include "llvm/MC/MCAsmInfo.h" | 
|  | #include "llvm/MC/MCExpr.h" | 
|  | #include "llvm/MC/MCInst.h" | 
|  | #include "llvm/Target/TargetLoweringObjectFile.h" | 
|  | using namespace llvm; | 
|  |  | 
|  | static MachineModuleInfoMachO &getMachOMMI(AsmPrinter &AP) { | 
|  | return AP.MMI->getObjFileInfo<MachineModuleInfoMachO>(); | 
|  | } | 
|  |  | 
|  | static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, | 
|  | AsmPrinter &AP) { | 
|  | const TargetMachine &TM = AP.TM; | 
|  | Mangler &Mang = TM.getObjFileLowering()->getMangler(); | 
|  | const DataLayout &DL = AP.getDataLayout(); | 
|  | MCContext &Ctx = AP.OutContext; | 
|  |  | 
|  | SmallString<128> Name; | 
|  | StringRef Suffix; | 
|  | if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG) | 
|  | Suffix = "$non_lazy_ptr"; | 
|  |  | 
|  | if (!Suffix.empty()) | 
|  | Name += DL.getPrivateGlobalPrefix(); | 
|  |  | 
|  | if (!MO.isGlobal()) { | 
|  | assert(MO.isSymbol() && "Isn't a symbol reference"); | 
|  | Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL); | 
|  | } else { | 
|  | const GlobalValue *GV = MO.getGlobal(); | 
|  | TM.getNameWithPrefix(Name, GV, Mang); | 
|  | } | 
|  |  | 
|  | Name += Suffix; | 
|  | MCSymbol *Sym = Ctx.getOrCreateSymbol(Name); | 
|  |  | 
|  | // If the symbol reference is actually to a non_lazy_ptr, not to the symbol, | 
|  | // then add the suffix. | 
|  | if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG) { | 
|  | MachineModuleInfoMachO &MachO = getMachOMMI(AP); | 
|  |  | 
|  | MachineModuleInfoImpl::StubValueTy &StubSym = MachO.getGVStubEntry(Sym); | 
|  |  | 
|  | if (!StubSym.getPointer()) { | 
|  | assert(MO.isGlobal() && "Extern symbol not handled yet"); | 
|  | StubSym = MachineModuleInfoImpl:: | 
|  | StubValueTy(AP.getSymbol(MO.getGlobal()), | 
|  | !MO.getGlobal()->hasInternalLinkage()); | 
|  | } | 
|  | return Sym; | 
|  | } | 
|  |  | 
|  | return Sym; | 
|  | } | 
|  |  | 
|  | static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, | 
|  | AsmPrinter &Printer, bool isDarwin) { | 
|  | MCContext &Ctx = Printer.OutContext; | 
|  | MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; | 
|  |  | 
|  | unsigned access = MO.getTargetFlags() & PPCII::MO_ACCESS_MASK; | 
|  |  | 
|  | switch (access) { | 
|  | case PPCII::MO_TPREL_LO: | 
|  | RefKind = MCSymbolRefExpr::VK_PPC_TPREL_LO; | 
|  | break; | 
|  | case PPCII::MO_TPREL_HA: | 
|  | RefKind = MCSymbolRefExpr::VK_PPC_TPREL_HA; | 
|  | break; | 
|  | case PPCII::MO_DTPREL_LO: | 
|  | RefKind = MCSymbolRefExpr::VK_PPC_DTPREL_LO; | 
|  | break; | 
|  | case PPCII::MO_TLSLD_LO: | 
|  | RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO; | 
|  | break; | 
|  | case PPCII::MO_TOC_LO: | 
|  | RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO; | 
|  | break; | 
|  | case PPCII::MO_TLS: | 
|  | RefKind = MCSymbolRefExpr::VK_PPC_TLS; | 
|  | break; | 
|  | } | 
|  |  | 
|  | if (MO.getTargetFlags() == PPCII::MO_PLT) | 
|  | RefKind = MCSymbolRefExpr::VK_PLT; | 
|  |  | 
|  | const MachineFunction *MF = MO.getParent()->getParent()->getParent(); | 
|  | const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>()); | 
|  | const TargetMachine &TM = Printer.TM; | 
|  | const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, RefKind, Ctx); | 
|  | // -msecure-plt option works only in PIC mode. If secure plt mode | 
|  | // is on add 32768 to symbol. | 
|  | if (Subtarget->isSecurePlt() && TM.isPositionIndependent() && | 
|  | MO.getTargetFlags() == PPCII::MO_PLT) | 
|  | Expr = MCBinaryExpr::createAdd(Expr, | 
|  | MCConstantExpr::create(32768, Ctx), | 
|  | Ctx); | 
|  |  | 
|  | if (!MO.isJTI() && MO.getOffset()) | 
|  | Expr = MCBinaryExpr::createAdd(Expr, | 
|  | MCConstantExpr::create(MO.getOffset(), Ctx), | 
|  | Ctx); | 
|  |  | 
|  | // Subtract off the PIC base if required. | 
|  | if (MO.getTargetFlags() & PPCII::MO_PIC_FLAG) { | 
|  | const MachineFunction *MF = MO.getParent()->getParent()->getParent(); | 
|  |  | 
|  | const MCExpr *PB = MCSymbolRefExpr::create(MF->getPICBaseSymbol(), Ctx); | 
|  | Expr = MCBinaryExpr::createSub(Expr, PB, Ctx); | 
|  | } | 
|  |  | 
|  | // Add ha16() / lo16() markers if required. | 
|  | switch (access) { | 
|  | case PPCII::MO_LO: | 
|  | Expr = PPCMCExpr::createLo(Expr, isDarwin, Ctx); | 
|  | break; | 
|  | case PPCII::MO_HA: | 
|  | Expr = PPCMCExpr::createHa(Expr, isDarwin, Ctx); | 
|  | break; | 
|  | } | 
|  |  | 
|  | return MCOperand::createExpr(Expr); | 
|  | } | 
|  |  | 
|  | void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, | 
|  | AsmPrinter &AP, bool isDarwin) { | 
|  | OutMI.setOpcode(MI->getOpcode()); | 
|  |  | 
|  | for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { | 
|  | MCOperand MCOp; | 
|  | if (LowerPPCMachineOperandToMCOperand(MI->getOperand(i), MCOp, AP, | 
|  | isDarwin)) | 
|  | OutMI.addOperand(MCOp); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool llvm::LowerPPCMachineOperandToMCOperand(const MachineOperand &MO, | 
|  | MCOperand &OutMO, AsmPrinter &AP, | 
|  | bool isDarwin) { | 
|  | switch (MO.getType()) { | 
|  | default: | 
|  | llvm_unreachable("unknown operand type"); | 
|  | case MachineOperand::MO_Register: | 
|  | assert(!MO.getSubReg() && "Subregs should be eliminated!"); | 
|  | assert(MO.getReg() > PPC::NoRegister && | 
|  | MO.getReg() < PPC::NUM_TARGET_REGS && | 
|  | "Invalid register for this target!"); | 
|  | OutMO = MCOperand::createReg(MO.getReg()); | 
|  | return true; | 
|  | case MachineOperand::MO_Immediate: | 
|  | OutMO = MCOperand::createImm(MO.getImm()); | 
|  | return true; | 
|  | case MachineOperand::MO_MachineBasicBlock: | 
|  | OutMO = MCOperand::createExpr( | 
|  | MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), AP.OutContext)); | 
|  | return true; | 
|  | case MachineOperand::MO_GlobalAddress: | 
|  | case MachineOperand::MO_ExternalSymbol: | 
|  | OutMO = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP, isDarwin); | 
|  | return true; | 
|  | case MachineOperand::MO_JumpTableIndex: | 
|  | OutMO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP, isDarwin); | 
|  | return true; | 
|  | case MachineOperand::MO_ConstantPoolIndex: | 
|  | OutMO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP, isDarwin); | 
|  | return true; | 
|  | case MachineOperand::MO_BlockAddress: | 
|  | OutMO = GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP, | 
|  | isDarwin); | 
|  | return true; | 
|  | case MachineOperand::MO_RegisterMask: | 
|  | return false; | 
|  | } | 
|  | } |