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 const TargetMachine &TM = AP.TM; 35 Mangler &Mang = TM.getObjFileLowering()->getMangler(); 36 const DataLayout &DL = AP.getDataLayout(); 37 MCContext &Ctx = AP.OutContext; 38 39 SmallString<128> Name; 40 if (!MO.isGlobal()) { 41 assert(MO.isSymbol() && "Isn't a symbol reference"); 42 Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL); 43 } else { 44 const GlobalValue *GV = MO.getGlobal(); 45 if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) 46 if (GVar->hasAttribute("toc-data")) 47 return TM.getSymbol(GV); 48 49 TM.getNameWithPrefix(Name, GV, Mang); 50 } 51 52 MCSymbol *Sym = Ctx.getOrCreateSymbol(Name); 53 54 return Sym; 55 } 56 57 static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, 58 AsmPrinter &Printer) { 59 MCContext &Ctx = Printer.OutContext; 60 MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; 61 62 unsigned access = MO.getTargetFlags() & PPCII::MO_ACCESS_MASK; 63 64 switch (access) { 65 case PPCII::MO_TPREL_LO: 66 RefKind = MCSymbolRefExpr::VK_PPC_TPREL_LO; 67 break; 68 case PPCII::MO_TPREL_HA: 69 RefKind = MCSymbolRefExpr::VK_PPC_TPREL_HA; 70 break; 71 case PPCII::MO_DTPREL_LO: 72 RefKind = MCSymbolRefExpr::VK_PPC_DTPREL_LO; 73 break; 74 case PPCII::MO_TLSLD_LO: 75 RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO; 76 break; 77 case PPCII::MO_TOC_LO: 78 RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO; 79 break; 80 case PPCII::MO_TLS: 81 bool IsPCRel = (MO.getTargetFlags() & ~access) == PPCII::MO_PCREL_FLAG; 82 RefKind = IsPCRel ? MCSymbolRefExpr::VK_PPC_TLS_PCREL 83 : MCSymbolRefExpr::VK_PPC_TLS; 84 break; 85 } 86 87 if (MO.getTargetFlags() == PPCII::MO_PLT) 88 RefKind = MCSymbolRefExpr::VK_PLT; 89 else if (MO.getTargetFlags() == PPCII::MO_PCREL_FLAG) 90 RefKind = MCSymbolRefExpr::VK_PCREL; 91 else if (MO.getTargetFlags() == (PPCII::MO_PCREL_FLAG | PPCII::MO_GOT_FLAG)) 92 RefKind = MCSymbolRefExpr::VK_PPC_GOT_PCREL; 93 else if (MO.getTargetFlags() == (PPCII::MO_PCREL_FLAG | PPCII::MO_TPREL_FLAG)) 94 RefKind = MCSymbolRefExpr::VK_TPREL; 95 else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG) 96 RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL; 97 else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSLD_PCREL_FLAG) 98 RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL; 99 else if (MO.getTargetFlags() == PPCII::MO_GOT_TPREL_PCREL_FLAG) 100 RefKind = MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL; 101 102 const MachineInstr *MI = MO.getParent(); 103 const MachineFunction *MF = MI->getMF(); 104 const Module *M = MF->getFunction().getParent(); 105 const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>()); 106 const TargetMachine &TM = Printer.TM; 107 108 unsigned MIOpcode = MI->getOpcode(); 109 assert((Subtarget->isUsingPCRelativeCalls() || MIOpcode != PPC::BL8_NOTOC) && 110 "BL8_NOTOC is only valid when using PC Relative Calls."); 111 if (Subtarget->isUsingPCRelativeCalls()) { 112 if (MIOpcode == PPC::TAILB || MIOpcode == PPC::TAILB8 || 113 MIOpcode == PPC::TCRETURNdi || MIOpcode == PPC::TCRETURNdi8 || 114 MIOpcode == PPC::BL8_NOTOC || MIOpcode == PPC::BL8_NOTOC_RM) { 115 RefKind = MCSymbolRefExpr::VK_PPC_NOTOC; 116 } 117 if (MO.getTargetFlags() == PPCII::MO_PCREL_OPT_FLAG) 118 RefKind = MCSymbolRefExpr::VK_PPC_PCREL_OPT; 119 } 120 121 const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, RefKind, Ctx); 122 // If -msecure-plt -fPIC, add 32768 to symbol. 123 if (Subtarget->isSecurePlt() && TM.isPositionIndependent() && 124 M->getPICLevel() == PICLevel::BigPIC && 125 MO.getTargetFlags() == PPCII::MO_PLT) 126 Expr = 127 MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(32768, Ctx), Ctx); 128 129 if (!MO.isJTI() && MO.getOffset()) 130 Expr = MCBinaryExpr::createAdd(Expr, 131 MCConstantExpr::create(MO.getOffset(), Ctx), 132 Ctx); 133 134 // Subtract off the PIC base if required. 135 if (MO.getTargetFlags() & PPCII::MO_PIC_FLAG) { 136 const MachineFunction *MF = MO.getParent()->getParent()->getParent(); 137 138 const MCExpr *PB = MCSymbolRefExpr::create(MF->getPICBaseSymbol(), Ctx); 139 Expr = MCBinaryExpr::createSub(Expr, PB, Ctx); 140 } 141 142 // Add ha16() / lo16() markers if required. 143 switch (access) { 144 case PPCII::MO_LO: 145 Expr = PPCMCExpr::createLo(Expr, Ctx); 146 break; 147 case PPCII::MO_HA: 148 Expr = PPCMCExpr::createHa(Expr, Ctx); 149 break; 150 } 151 152 return MCOperand::createExpr(Expr); 153 } 154 155 void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, 156 AsmPrinter &AP) { 157 OutMI.setOpcode(MI->getOpcode()); 158 159 for (const MachineOperand &MO : MI->operands()) { 160 MCOperand MCOp; 161 if (LowerPPCMachineOperandToMCOperand(MO, MCOp, AP)) 162 OutMI.addOperand(MCOp); 163 } 164 } 165 166 bool llvm::LowerPPCMachineOperandToMCOperand(const MachineOperand &MO, 167 MCOperand &OutMO, AsmPrinter &AP) { 168 switch (MO.getType()) { 169 default: 170 llvm_unreachable("unknown operand type"); 171 case MachineOperand::MO_Register: 172 assert(!MO.getSubReg() && "Subregs should be eliminated!"); 173 assert(MO.getReg() > PPC::NoRegister && 174 MO.getReg() < PPC::NUM_TARGET_REGS && 175 "Invalid register for this target!"); 176 // Ignore all implicit register operands. 177 if (MO.isImplicit()) 178 return false; 179 OutMO = MCOperand::createReg(MO.getReg()); 180 return true; 181 case MachineOperand::MO_Immediate: 182 OutMO = MCOperand::createImm(MO.getImm()); 183 return true; 184 case MachineOperand::MO_MachineBasicBlock: 185 OutMO = MCOperand::createExpr( 186 MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), AP.OutContext)); 187 return true; 188 case MachineOperand::MO_GlobalAddress: 189 case MachineOperand::MO_ExternalSymbol: 190 OutMO = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP); 191 return true; 192 case MachineOperand::MO_JumpTableIndex: 193 OutMO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP); 194 return true; 195 case MachineOperand::MO_ConstantPoolIndex: 196 OutMO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP); 197 return true; 198 case MachineOperand::MO_BlockAddress: 199 OutMO = 200 GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP); 201 return true; 202 case MachineOperand::MO_MCSymbol: 203 OutMO = GetSymbolRef(MO, MO.getMCSymbol(), AP); 204 return true; 205 case MachineOperand::MO_RegisterMask: 206 return false; 207 } 208 } 209