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