| //===-- 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 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; | |
| 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); | |
| } | |
| MCSymbol *Sym = Ctx.getOrCreateSymbol(Name); | |
| return Sym; | |
| } | |
| static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, | |
| AsmPrinter &Printer) { | |
| 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: | |
| bool IsPCRel = (MO.getTargetFlags() & ~access) == PPCII::MO_PCREL_FLAG; | |
| RefKind = IsPCRel ? MCSymbolRefExpr::VK_PPC_TLS_PCREL | |
| : MCSymbolRefExpr::VK_PPC_TLS; | |
| break; | |
| } | |
| if (MO.getTargetFlags() == PPCII::MO_PLT) | |
| RefKind = MCSymbolRefExpr::VK_PLT; | |
| else if (MO.getTargetFlags() == PPCII::MO_PCREL_FLAG) | |
| RefKind = MCSymbolRefExpr::VK_PCREL; | |
| else if (MO.getTargetFlags() == (PPCII::MO_PCREL_FLAG | PPCII::MO_GOT_FLAG)) | |
| RefKind = MCSymbolRefExpr::VK_PPC_GOT_PCREL; | |
| else if (MO.getTargetFlags() == (PPCII::MO_PCREL_FLAG | PPCII::MO_TPREL_FLAG)) | |
| RefKind = MCSymbolRefExpr::VK_TPREL; | |
| else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG) | |
| RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL; | |
| else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSLD_PCREL_FLAG) | |
| RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL; | |
| else if (MO.getTargetFlags() == PPCII::MO_GOT_TPREL_PCREL_FLAG) | |
| RefKind = MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL; | |
| const MachineInstr *MI = MO.getParent(); | |
| const MachineFunction *MF = MI->getMF(); | |
| const Module *M = MF->getFunction().getParent(); | |
| const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>()); | |
| const TargetMachine &TM = Printer.TM; | |
| unsigned MIOpcode = MI->getOpcode(); | |
| assert((Subtarget->isUsingPCRelativeCalls() || MIOpcode != PPC::BL8_NOTOC) && | |
| "BL8_NOTOC is only valid when using PC Relative Calls."); | |
| if (Subtarget->isUsingPCRelativeCalls()) { | |
| if (MIOpcode == PPC::TAILB || MIOpcode == PPC::TAILB8 || | |
| MIOpcode == PPC::TCRETURNdi || MIOpcode == PPC::TCRETURNdi8 || | |
| MIOpcode == PPC::BL8_NOTOC || MIOpcode == PPC::BL8_NOTOC_RM) { | |
| RefKind = MCSymbolRefExpr::VK_PPC_NOTOC; | |
| } | |
| if (MO.getTargetFlags() == PPCII::MO_PCREL_OPT_FLAG) | |
| RefKind = MCSymbolRefExpr::VK_PPC_PCREL_OPT; | |
| } | |
| 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, Ctx); | |
| break; | |
| case PPCII::MO_HA: | |
| Expr = PPCMCExpr::createHa(Expr, Ctx); | |
| break; | |
| } | |
| return MCOperand::createExpr(Expr); | |
| } | |
| void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, | |
| AsmPrinter &AP) { | |
| OutMI.setOpcode(MI->getOpcode()); | |
| for (const MachineOperand &MO : MI->operands()) { | |
| MCOperand MCOp; | |
| if (LowerPPCMachineOperandToMCOperand(MO, MCOp, AP)) | |
| OutMI.addOperand(MCOp); | |
| } | |
| } | |
| bool llvm::LowerPPCMachineOperandToMCOperand(const MachineOperand &MO, | |
| MCOperand &OutMO, AsmPrinter &AP) { | |
| 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!"); | |
| // Ignore all implicit register operands. | |
| if (MO.isImplicit()) | |
| return false; | |
| 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); | |
| return true; | |
| case MachineOperand::MO_JumpTableIndex: | |
| OutMO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP); | |
| return true; | |
| case MachineOperand::MO_ConstantPoolIndex: | |
| OutMO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP); | |
| return true; | |
| case MachineOperand::MO_BlockAddress: | |
| OutMO = | |
| GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP); | |
| return true; | |
| case MachineOperand::MO_MCSymbol: | |
| OutMO = GetSymbolRef(MO, MO.getMCSymbol(), AP); | |
| return true; | |
| case MachineOperand::MO_RegisterMask: | |
| return false; | |
| } | |
| } |