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 "llvm/CodeGen/AsmPrinter.h" 17 #include "llvm/CodeGen/MachineFunction.h" 18 #include "llvm/CodeGen/MachineModuleInfoImpls.h" 19 #include "llvm/MC/MCAsmInfo.h" 20 #include "llvm/MC/MCExpr.h" 21 #include "llvm/MC/MCInst.h" 22 #include "llvm/Target/Mangler.h" 23 #include "llvm/ADT/SmallString.h" 24 using namespace llvm; 25 26 static MachineModuleInfoMachO &getMachOMMI(AsmPrinter &AP) { 27 return AP.MMI->getObjFileInfo<MachineModuleInfoMachO>(); 28 } 29 30 31 static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, AsmPrinter &AP){ 32 MCContext &Ctx = AP.OutContext; 33 34 SmallString<128> Name; 35 if (!MO.isGlobal()) { 36 assert(MO.isSymbol() && "Isn't a symbol reference"); 37 Name += AP.MAI->getGlobalPrefix(); 38 Name += MO.getSymbolName(); 39 } else { 40 const GlobalValue *GV = MO.getGlobal(); 41 bool isImplicitlyPrivate = false; 42 if (MO.getTargetFlags() == PPCII::MO_DARWIN_STUB || 43 //MO.getTargetFlags() == PPCII::MO_DARWIN_NONLAZY || 44 //MO.getTargetFlags() == PPCII::MO_DARWIN_NONLAZY_PIC_BASE || 45 //MO.getTargetFlags() == PPCII::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE 46 0) 47 isImplicitlyPrivate = true; 48 49 AP.Mang->getNameWithPrefix(Name, GV, isImplicitlyPrivate); 50 } 51 52 // If the target flags on the operand changes the name of the symbol, do that 53 // before we return the symbol. 54 switch (MO.getTargetFlags()) { 55 default: break; 56 #if 0 57 case X86II::MO_DARWIN_NONLAZY: 58 case X86II::MO_DARWIN_NONLAZY_PIC_BASE: { 59 Name += "$non_lazy_ptr"; 60 MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); 61 62 MachineModuleInfoImpl::StubValueTy &StubSym = 63 getMachOMMI(AP).getGVStubEntry(Sym); 64 if (StubSym.getPointer() == 0) { 65 assert(MO.isGlobal() && "Extern symbol not handled yet"); 66 StubSym = 67 MachineModuleInfoImpl:: 68 StubValueTy(Mang->getSymbol(MO.getGlobal()), 69 !MO.getGlobal()->hasInternalLinkage()); 70 } 71 return Sym; 72 } 73 case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: { 74 Name += "$non_lazy_ptr"; 75 MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); 76 MachineModuleInfoImpl::StubValueTy &StubSym = 77 getMachOMMI(AP).getHiddenGVStubEntry(Sym); 78 if (StubSym.getPointer() == 0) { 79 assert(MO.isGlobal() && "Extern symbol not handled yet"); 80 StubSym = 81 MachineModuleInfoImpl:: 82 StubValueTy(Mang->getSymbol(MO.getGlobal()), 83 !MO.getGlobal()->hasInternalLinkage()); 84 } 85 return Sym; 86 } 87 #endif 88 case PPCII::MO_DARWIN_STUB: { 89 Name += "$stub"; 90 MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); 91 MachineModuleInfoImpl::StubValueTy &StubSym = 92 getMachOMMI(AP).getFnStubEntry(Sym); 93 if (StubSym.getPointer()) 94 return Sym; 95 96 if (MO.isGlobal()) { 97 StubSym = 98 MachineModuleInfoImpl:: 99 StubValueTy(AP.Mang->getSymbol(MO.getGlobal()), 100 !MO.getGlobal()->hasInternalLinkage()); 101 } else { 102 Name.erase(Name.end()-5, Name.end()); 103 StubSym = 104 MachineModuleInfoImpl:: 105 StubValueTy(Ctx.GetOrCreateSymbol(Name.str()), false); 106 } 107 return Sym; 108 } 109 } 110 111 return Ctx.GetOrCreateSymbol(Name.str()); 112 } 113 114 static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, 115 AsmPrinter &Printer) { 116 MCContext &Ctx = Printer.OutContext; 117 MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; 118 119 const MCExpr *Expr = 0; 120 switch (MO.getTargetFlags()) { 121 default: assert(0 && "Unknown target flag on symbol operand"); 122 case PPCII::MO_NO_FLAG: 123 // These affect the name of the symbol, not any suffix. 124 case PPCII::MO_DARWIN_STUB: 125 break; 126 127 case PPCII::MO_LO16: RefKind = MCSymbolRefExpr::VK_PPC_LO16; break; 128 case PPCII::MO_HA16: RefKind = MCSymbolRefExpr::VK_PPC_HA16; break; 129 case PPCII::MO_LO16_PIC: break; 130 case PPCII::MO_HA16_PIC: break; 131 } 132 133 if (Expr == 0) 134 Expr = MCSymbolRefExpr::Create(Symbol, RefKind, Ctx); 135 136 if (!MO.isJTI() && MO.getOffset()) 137 Expr = MCBinaryExpr::CreateAdd(Expr, 138 MCConstantExpr::Create(MO.getOffset(), Ctx), 139 Ctx); 140 141 // Subtract off the PIC base. 142 if (MO.getTargetFlags() == PPCII::MO_LO16_PIC || 143 MO.getTargetFlags() == PPCII::MO_HA16_PIC) { 144 const MachineFunction *MF = MO.getParent()->getParent()->getParent(); 145 146 const MCExpr *PB = MCSymbolRefExpr::Create(MF->getPICBaseSymbol(), Ctx); 147 Expr = MCBinaryExpr::CreateSub(Expr, PB, Ctx); 148 // FIXME: We have no way to make the result be VK_PPC_LO16/VK_PPC_HA16, 149 // since it is not a symbol! 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 (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 160 const MachineOperand &MO = MI->getOperand(i); 161 162 MCOperand MCOp; 163 switch (MO.getType()) { 164 default: 165 MI->dump(); 166 assert(0 && "unknown operand type"); 167 case MachineOperand::MO_Register: 168 assert(!MO.getSubReg() && "Subregs should be eliminated!"); 169 MCOp = MCOperand::CreateReg(MO.getReg()); 170 break; 171 case MachineOperand::MO_Immediate: 172 MCOp = MCOperand::CreateImm(MO.getImm()); 173 break; 174 case MachineOperand::MO_MachineBasicBlock: 175 MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create( 176 MO.getMBB()->getSymbol(), AP.OutContext)); 177 break; 178 case MachineOperand::MO_GlobalAddress: 179 case MachineOperand::MO_ExternalSymbol: 180 MCOp = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP); 181 break; 182 case MachineOperand::MO_JumpTableIndex: 183 MCOp = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP); 184 break; 185 case MachineOperand::MO_ConstantPoolIndex: 186 MCOp = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP); 187 break; 188 case MachineOperand::MO_BlockAddress: 189 MCOp = GetSymbolRef(MO,AP.GetBlockAddressSymbol(MO.getBlockAddress()),AP); 190 break; 191 } 192 193 OutMI.addOperand(MCOp); 194 } 195 } 196