1 //===-- PPCMCInstLower.cpp - Convert PPC MachineInstr to an MCInst --------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains code to lower PPC MachineInstrs to their corresponding 10 // MCInst records. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "MCTargetDesc/PPCMCExpr.h" 15 #include "PPC.h" 16 #include "PPCSubtarget.h" 17 #include "llvm/ADT/SmallString.h" 18 #include "llvm/ADT/Twine.h" 19 #include "llvm/CodeGen/AsmPrinter.h" 20 #include "llvm/CodeGen/MachineFunction.h" 21 #include "llvm/CodeGen/MachineModuleInfoImpls.h" 22 #include "llvm/CodeGen/TargetLowering.h" 23 #include "llvm/IR/DataLayout.h" 24 #include "llvm/IR/GlobalValue.h" 25 #include "llvm/IR/Mangler.h" 26 #include "llvm/MC/MCAsmInfo.h" 27 #include "llvm/MC/MCExpr.h" 28 #include "llvm/MC/MCInst.h" 29 #include "llvm/Target/TargetLoweringObjectFile.h" 30 using namespace llvm; 31 32 static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, 33 AsmPrinter &AP) { 34 if (MO.isGlobal()) { 35 // Get the symbol from the global, accounting for XCOFF-specific 36 // intricacies (see TargetLoweringObjectFileXCOFF::getTargetSymbol). 37 const GlobalValue *GV = MO.getGlobal(); 38 return AP.getSymbol(GV); 39 } 40 41 assert(MO.isSymbol() && "Isn't a symbol reference"); 42 43 SmallString<128> Name; 44 const DataLayout &DL = AP.getDataLayout(); 45 Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL); 46 47 MCContext &Ctx = AP.OutContext; 48 MCSymbol *Sym = Ctx.getOrCreateSymbol(Name); 49 return Sym; 50 } 51 52 static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, 53 AsmPrinter &Printer) { 54 MCContext &Ctx = Printer.OutContext; 55 MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; 56 57 unsigned access = MO.getTargetFlags() & PPCII::MO_ACCESS_MASK; 58 59 switch (access) { 60 case PPCII::MO_TPREL_LO: 61 RefKind = MCSymbolRefExpr::VK_PPC_TPREL_LO; 62 break; 63 case PPCII::MO_TPREL_HA: 64 RefKind = MCSymbolRefExpr::VK_PPC_TPREL_HA; 65 break; 66 case PPCII::MO_DTPREL_LO: 67 RefKind = MCSymbolRefExpr::VK_PPC_DTPREL_LO; 68 break; 69 case PPCII::MO_TLSLD_LO: 70 RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO; 71 break; 72 case PPCII::MO_TOC_LO: 73 RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO; 74 break; 75 case PPCII::MO_TLS: 76 bool IsPCRel = (MO.getTargetFlags() & ~access) == PPCII::MO_PCREL_FLAG; 77 RefKind = IsPCRel ? MCSymbolRefExpr::VK_PPC_TLS_PCREL 78 : MCSymbolRefExpr::VK_PPC_TLS; 79 break; 80 } 81 82 const TargetMachine &TM = Printer.TM; 83 84 if (MO.getTargetFlags() == PPCII::MO_PLT) 85 RefKind = MCSymbolRefExpr::VK_PLT; 86 else if (MO.getTargetFlags() == PPCII::MO_PCREL_FLAG) 87 RefKind = MCSymbolRefExpr::VK_PCREL; 88 else if (MO.getTargetFlags() == (PPCII::MO_PCREL_FLAG | PPCII::MO_GOT_FLAG)) 89 RefKind = MCSymbolRefExpr::VK_PPC_GOT_PCREL; 90 else if (MO.getTargetFlags() == (PPCII::MO_PCREL_FLAG | PPCII::MO_TPREL_FLAG)) 91 RefKind = MCSymbolRefExpr::VK_TPREL; 92 else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG) 93 RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL; 94 else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSLD_PCREL_FLAG) 95 RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL; 96 else if (MO.getTargetFlags() == PPCII::MO_GOT_TPREL_PCREL_FLAG) 97 RefKind = MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL; 98 else if (MO.getTargetFlags() == PPCII::MO_TPREL_FLAG) { 99 assert(MO.isGlobal() && "Only expecting a global MachineOperand here!"); 100 TLSModel::Model Model = TM.getTLSModel(MO.getGlobal()); 101 // For the local-exec TLS model, we may generate the offset from the TLS 102 // base as an immediate operand (instead of using a TOC entry). 103 // Set the relocation type in case the result is used for purposes other 104 // than a TOC reference. In TOC reference cases, this result is discarded. 105 if (Model == TLSModel::LocalExec) 106 RefKind = MCSymbolRefExpr::VK_PPC_AIX_TLSLE; 107 } 108 109 const MachineInstr *MI = MO.getParent(); 110 const MachineFunction *MF = MI->getMF(); 111 const Module *M = MF->getFunction().getParent(); 112 const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>()); 113 114 unsigned MIOpcode = MI->getOpcode(); 115 assert((Subtarget->isUsingPCRelativeCalls() || MIOpcode != PPC::BL8_NOTOC) && 116 "BL8_NOTOC is only valid when using PC Relative Calls."); 117 if (Subtarget->isUsingPCRelativeCalls()) { 118 if (MIOpcode == PPC::TAILB || MIOpcode == PPC::TAILB8 || 119 MIOpcode == PPC::TCRETURNdi || MIOpcode == PPC::TCRETURNdi8 || 120 MIOpcode == PPC::BL8_NOTOC || MIOpcode == PPC::BL8_NOTOC_RM) { 121 RefKind = MCSymbolRefExpr::VK_PPC_NOTOC; 122 } 123 if (MO.getTargetFlags() == PPCII::MO_PCREL_OPT_FLAG) 124 RefKind = MCSymbolRefExpr::VK_PPC_PCREL_OPT; 125 } 126 127 const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, RefKind, Ctx); 128 // If -msecure-plt -fPIC, add 32768 to symbol. 129 if (Subtarget->isSecurePlt() && TM.isPositionIndependent() && 130 M->getPICLevel() == PICLevel::BigPIC && 131 MO.getTargetFlags() == PPCII::MO_PLT) 132 Expr = 133 MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(32768, Ctx), Ctx); 134 135 if (!MO.isJTI() && MO.getOffset()) 136 Expr = MCBinaryExpr::createAdd(Expr, 137 MCConstantExpr::create(MO.getOffset(), Ctx), 138 Ctx); 139 140 // Subtract off the PIC base if required. 141 if (MO.getTargetFlags() & PPCII::MO_PIC_FLAG) { 142 const MachineFunction *MF = MO.getParent()->getParent()->getParent(); 143 144 const MCExpr *PB = MCSymbolRefExpr::create(MF->getPICBaseSymbol(), Ctx); 145 Expr = MCBinaryExpr::createSub(Expr, PB, Ctx); 146 } 147 148 // Add ha16() / lo16() markers if required. 149 switch (access) { 150 case PPCII::MO_LO: 151 Expr = PPCMCExpr::createLo(Expr, Ctx); 152 break; 153 case PPCII::MO_HA: 154 Expr = PPCMCExpr::createHa(Expr, Ctx); 155 break; 156 } 157 158 return MCOperand::createExpr(Expr); 159 } 160 161 void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, 162 AsmPrinter &AP) { 163 OutMI.setOpcode(MI->getOpcode()); 164 165 for (const MachineOperand &MO : MI->operands()) { 166 MCOperand MCOp; 167 if (LowerPPCMachineOperandToMCOperand(MO, MCOp, AP)) 168 OutMI.addOperand(MCOp); 169 } 170 } 171 172 bool llvm::LowerPPCMachineOperandToMCOperand(const MachineOperand &MO, 173 MCOperand &OutMO, AsmPrinter &AP) { 174 switch (MO.getType()) { 175 default: 176 llvm_unreachable("unknown operand type"); 177 case MachineOperand::MO_Register: 178 assert(!MO.getSubReg() && "Subregs should be eliminated!"); 179 assert(MO.getReg() > PPC::NoRegister && 180 MO.getReg() < PPC::NUM_TARGET_REGS && 181 "Invalid register for this target!"); 182 // Ignore all implicit register operands. 183 if (MO.isImplicit()) 184 return false; 185 OutMO = MCOperand::createReg(MO.getReg()); 186 return true; 187 case MachineOperand::MO_Immediate: 188 OutMO = MCOperand::createImm(MO.getImm()); 189 return true; 190 case MachineOperand::MO_MachineBasicBlock: 191 OutMO = MCOperand::createExpr( 192 MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), AP.OutContext)); 193 return true; 194 case MachineOperand::MO_GlobalAddress: 195 case MachineOperand::MO_ExternalSymbol: 196 OutMO = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP); 197 return true; 198 case MachineOperand::MO_JumpTableIndex: 199 OutMO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP); 200 return true; 201 case MachineOperand::MO_ConstantPoolIndex: 202 OutMO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP); 203 return true; 204 case MachineOperand::MO_BlockAddress: 205 OutMO = 206 GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP); 207 return true; 208 case MachineOperand::MO_MCSymbol: 209 OutMO = GetSymbolRef(MO, MO.getMCSymbol(), AP); 210 return true; 211 case MachineOperand::MO_RegisterMask: 212 return false; 213 } 214 } 215