diff options
Diffstat (limited to 'llvm/lib/Target/PowerPC/PPCMCInstLower.cpp')
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCMCInstLower.cpp | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp b/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp new file mode 100644 index 000000000000..b6496f189a3a --- /dev/null +++ b/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp @@ -0,0 +1,202 @@ +//===-- 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 Module *M = MF->getFunction().getParent(); + const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>()); + const TargetMachine &TM = Printer.TM; + const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, RefKind, Ctx); + // If -msecure-plt -fPIC, add 32768 to symbol. + if (Subtarget->isSecurePlt() && TM.isPositionIndependent() && + M->getPICLevel() == PICLevel::BigPIC && + 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_MCSymbol: + OutMO = GetSymbolRef(MO, MO.getMCSymbol(), AP, IsDarwin); + return true; + case MachineOperand::MO_RegisterMask: + return false; + } +} |