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