1 //===-- PPCMCInstLower.cpp - Convert PPC MachineInstr to an MCInst --------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains code to lower PPC MachineInstrs to their corresponding 11 // MCInst records. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "PPC.h" 16 #include "MCTargetDesc/PPCMCExpr.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/IR/GlobalValue.h" 23 #include "llvm/MC/MCAsmInfo.h" 24 #include "llvm/MC/MCExpr.h" 25 #include "llvm/MC/MCInst.h" 26 #include "llvm/Target/Mangler.h" 27 using namespace llvm; 28 29 static MachineModuleInfoMachO &getMachOMMI(AsmPrinter &AP) { 30 return AP.MMI->getObjFileInfo<MachineModuleInfoMachO>(); 31 } 32 33 34 static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, AsmPrinter &AP){ 35 MCContext &Ctx = AP.OutContext; 36 37 SmallString<128> Name; 38 StringRef Suffix; 39 if (MO.getTargetFlags() == PPCII::MO_DARWIN_STUB) 40 Suffix = "$stub"; 41 else if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG) 42 Suffix = "$non_lazy_ptr"; 43 44 if (!Suffix.empty()) 45 Name += AP.MAI->getPrivateGlobalPrefix(); 46 47 unsigned PrefixLen = Name.size(); 48 49 if (!MO.isGlobal()) { 50 assert(MO.isSymbol() && "Isn't a symbol reference"); 51 AP.Mang->getNameWithPrefix(Name, MO.getSymbolName()); 52 } else { 53 const GlobalValue *GV = MO.getGlobal(); 54 AP.Mang->getNameWithPrefix(Name, GV, false); 55 } 56 57 unsigned OrigLen = Name.size() - PrefixLen; 58 59 Name += Suffix; 60 MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); 61 StringRef OrigName = StringRef(Name).substr(PrefixLen, OrigLen); 62 63 // If the target flags on the operand changes the name of the symbol, do that 64 // before we return the symbol. 65 if (MO.getTargetFlags() == PPCII::MO_DARWIN_STUB) { 66 MachineModuleInfoImpl::StubValueTy &StubSym = 67 getMachOMMI(AP).getFnStubEntry(Sym); 68 if (StubSym.getPointer()) 69 return Sym; 70 71 if (MO.isGlobal()) { 72 StubSym = 73 MachineModuleInfoImpl:: 74 StubValueTy(AP.getSymbol(MO.getGlobal()), 75 !MO.getGlobal()->hasInternalLinkage()); 76 } else { 77 StubSym = 78 MachineModuleInfoImpl:: 79 StubValueTy(Ctx.GetOrCreateSymbol(OrigName), false); 80 } 81 return Sym; 82 } 83 84 // If the symbol reference is actually to a non_lazy_ptr, not to the symbol, 85 // then add the suffix. 86 if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG) { 87 MachineModuleInfoMachO &MachO = getMachOMMI(AP); 88 89 MachineModuleInfoImpl::StubValueTy &StubSym = 90 (MO.getTargetFlags() & PPCII::MO_NLP_HIDDEN_FLAG) ? 91 MachO.getHiddenGVStubEntry(Sym) : MachO.getGVStubEntry(Sym); 92 93 if (StubSym.getPointer() == 0) { 94 assert(MO.isGlobal() && "Extern symbol not handled yet"); 95 StubSym = MachineModuleInfoImpl:: 96 StubValueTy(AP.getSymbol(MO.getGlobal()), 97 !MO.getGlobal()->hasInternalLinkage()); 98 } 99 return Sym; 100 } 101 102 return Sym; 103 } 104 105 static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, 106 AsmPrinter &Printer, bool isDarwin) { 107 MCContext &Ctx = Printer.OutContext; 108 MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; 109 110 unsigned access = MO.getTargetFlags() & PPCII::MO_ACCESS_MASK; 111 112 switch (access) { 113 case PPCII::MO_TPREL_LO: 114 RefKind = MCSymbolRefExpr::VK_PPC_TPREL_LO; 115 break; 116 case PPCII::MO_TPREL_HA: 117 RefKind = MCSymbolRefExpr::VK_PPC_TPREL_HA; 118 break; 119 case PPCII::MO_DTPREL_LO: 120 RefKind = MCSymbolRefExpr::VK_PPC_DTPREL_LO; 121 break; 122 case PPCII::MO_TLSLD_LO: 123 RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO; 124 break; 125 case PPCII::MO_TOC_LO: 126 RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO; 127 break; 128 case PPCII::MO_TLS: 129 RefKind = MCSymbolRefExpr::VK_PPC_TLS; 130 break; 131 } 132 133 const MCExpr *Expr = MCSymbolRefExpr::Create(Symbol, RefKind, 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, isDarwin, Ctx); 152 break; 153 case PPCII::MO_HA: 154 Expr = PPCMCExpr::CreateHa(Expr, isDarwin, Ctx); 155 break; 156 } 157 158 return MCOperand::CreateExpr(Expr); 159 } 160 161 void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, 162 AsmPrinter &AP, bool isDarwin) { 163 OutMI.setOpcode(MI->getOpcode()); 164 165 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 166 const MachineOperand &MO = MI->getOperand(i); 167 168 MCOperand MCOp; 169 switch (MO.getType()) { 170 default: 171 MI->dump(); 172 llvm_unreachable("unknown operand type"); 173 case MachineOperand::MO_Register: 174 assert(!MO.getSubReg() && "Subregs should be eliminated!"); 175 MCOp = MCOperand::CreateReg(MO.getReg()); 176 break; 177 case MachineOperand::MO_Immediate: 178 MCOp = MCOperand::CreateImm(MO.getImm()); 179 break; 180 case MachineOperand::MO_MachineBasicBlock: 181 MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create( 182 MO.getMBB()->getSymbol(), AP.OutContext)); 183 break; 184 case MachineOperand::MO_GlobalAddress: 185 case MachineOperand::MO_ExternalSymbol: 186 MCOp = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP, isDarwin); 187 break; 188 case MachineOperand::MO_JumpTableIndex: 189 MCOp = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP, isDarwin); 190 break; 191 case MachineOperand::MO_ConstantPoolIndex: 192 MCOp = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP, isDarwin); 193 break; 194 case MachineOperand::MO_BlockAddress: 195 MCOp = GetSymbolRef(MO,AP.GetBlockAddressSymbol(MO.getBlockAddress()),AP, 196 isDarwin); 197 break; 198 case MachineOperand::MO_RegisterMask: 199 continue; 200 } 201 202 OutMI.addOperand(MCOp); 203 } 204 } 205