1234353Sdim//===-- PPCAsmPrinter.cpp - Print machine instrs to PowerPC assembly ------===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This file contains a printer that converts from our internal representation 11218885Sdim// of machine-dependent LLVM code to PowerPC assembly language. This printer is 12218885Sdim// the output mechanism used by `llc'. 13218885Sdim// 14218885Sdim// Documentation at http://developer.apple.com/documentation/DeveloperTools/ 15218885Sdim// Reference/Assembler/ASMIntroduction/chapter_1_section_1.html 16218885Sdim// 17218885Sdim//===----------------------------------------------------------------------===// 18218885Sdim 19218885Sdim#define DEBUG_TYPE "asmprinter" 20218885Sdim#include "PPC.h" 21234353Sdim#include "InstPrinter/PPCInstPrinter.h" 22226633Sdim#include "MCTargetDesc/PPCPredicates.h" 23263508Sdim#include "MCTargetDesc/PPCMCExpr.h" 24249423Sdim#include "PPCSubtarget.h" 25249423Sdim#include "PPCTargetMachine.h" 26263508Sdim#include "PPCTargetStreamer.h" 27249423Sdim#include "llvm/ADT/MapVector.h" 28249423Sdim#include "llvm/ADT/SmallString.h" 29249423Sdim#include "llvm/ADT/StringExtras.h" 30218885Sdim#include "llvm/Assembly/Writer.h" 31218885Sdim#include "llvm/CodeGen/AsmPrinter.h" 32218885Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 33218885Sdim#include "llvm/CodeGen/MachineInstr.h" 34218885Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 35218885Sdim#include "llvm/CodeGen/MachineModuleInfoImpls.h" 36218885Sdim#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 37249423Sdim#include "llvm/DebugInfo.h" 38249423Sdim#include "llvm/IR/Constants.h" 39249423Sdim#include "llvm/IR/DerivedTypes.h" 40249423Sdim#include "llvm/IR/Module.h" 41218885Sdim#include "llvm/MC/MCAsmInfo.h" 42218885Sdim#include "llvm/MC/MCContext.h" 43218885Sdim#include "llvm/MC/MCExpr.h" 44218885Sdim#include "llvm/MC/MCInst.h" 45249423Sdim#include "llvm/MC/MCInstBuilder.h" 46249423Sdim#include "llvm/MC/MCSectionELF.h" 47218885Sdim#include "llvm/MC/MCSectionMachO.h" 48218885Sdim#include "llvm/MC/MCStreamer.h" 49218885Sdim#include "llvm/MC/MCSymbol.h" 50218885Sdim#include "llvm/Support/CommandLine.h" 51218885Sdim#include "llvm/Support/Debug.h" 52249423Sdim#include "llvm/Support/ELF.h" 53249423Sdim#include "llvm/Support/ErrorHandling.h" 54218885Sdim#include "llvm/Support/MathExtras.h" 55226633Sdim#include "llvm/Support/TargetRegistry.h" 56218885Sdim#include "llvm/Support/raw_ostream.h" 57249423Sdim#include "llvm/Target/Mangler.h" 58249423Sdim#include "llvm/Target/TargetInstrInfo.h" 59249423Sdim#include "llvm/Target/TargetOptions.h" 60249423Sdim#include "llvm/Target/TargetRegisterInfo.h" 61218885Sdimusing namespace llvm; 62218885Sdim 63218885Sdimnamespace { 64218885Sdim class PPCAsmPrinter : public AsmPrinter { 65218885Sdim protected: 66243830Sdim MapVector<MCSymbol*, MCSymbol*> TOC; 67218885Sdim const PPCSubtarget &Subtarget; 68218885Sdim uint64_t TOCLabelID; 69218885Sdim public: 70218885Sdim explicit PPCAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 71218885Sdim : AsmPrinter(TM, Streamer), 72218885Sdim Subtarget(TM.getSubtarget<PPCSubtarget>()), TOCLabelID(0) {} 73218885Sdim 74218885Sdim virtual const char *getPassName() const { 75218885Sdim return "PowerPC Assembly Printer"; 76218885Sdim } 77218885Sdim 78249423Sdim MCSymbol *lookUpOrCreateTOCEntry(MCSymbol *Sym); 79218885Sdim 80218885Sdim virtual void EmitInstruction(const MachineInstr *MI); 81218885Sdim 82218885Sdim void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O); 83218885Sdim 84218885Sdim bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 85218885Sdim unsigned AsmVariant, const char *ExtraCode, 86218885Sdim raw_ostream &O); 87218885Sdim bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, 88218885Sdim unsigned AsmVariant, const char *ExtraCode, 89218885Sdim raw_ostream &O); 90218885Sdim }; 91218885Sdim 92218885Sdim /// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux 93218885Sdim class PPCLinuxAsmPrinter : public PPCAsmPrinter { 94218885Sdim public: 95218885Sdim explicit PPCLinuxAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 96218885Sdim : PPCAsmPrinter(TM, Streamer) {} 97218885Sdim 98218885Sdim virtual const char *getPassName() const { 99218885Sdim return "Linux PPC Assembly Printer"; 100218885Sdim } 101218885Sdim 102218885Sdim bool doFinalization(Module &M); 103218885Sdim 104218885Sdim virtual void EmitFunctionEntryLabel(); 105243830Sdim 106243830Sdim void EmitFunctionBodyEnd(); 107218885Sdim }; 108218885Sdim 109218885Sdim /// PPCDarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac 110218885Sdim /// OS X 111218885Sdim class PPCDarwinAsmPrinter : public PPCAsmPrinter { 112218885Sdim public: 113218885Sdim explicit PPCDarwinAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 114218885Sdim : PPCAsmPrinter(TM, Streamer) {} 115218885Sdim 116218885Sdim virtual const char *getPassName() const { 117218885Sdim return "Darwin PPC Assembly Printer"; 118218885Sdim } 119218885Sdim 120218885Sdim bool doFinalization(Module &M); 121218885Sdim void EmitStartOfAsmFile(Module &M); 122218885Sdim 123218885Sdim void EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs); 124218885Sdim }; 125218885Sdim} // end of anonymous namespace 126218885Sdim 127218885Sdim/// stripRegisterPrefix - This method strips the character prefix from a 128218885Sdim/// register name so that only the number is left. Used by for linux asm. 129218885Sdimstatic const char *stripRegisterPrefix(const char *RegName) { 130218885Sdim switch (RegName[0]) { 131218885Sdim case 'r': 132218885Sdim case 'f': 133218885Sdim case 'v': return RegName + 1; 134218885Sdim case 'c': if (RegName[1] == 'r') return RegName + 2; 135218885Sdim } 136218885Sdim 137218885Sdim return RegName; 138218885Sdim} 139218885Sdim 140218885Sdimvoid PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, 141218885Sdim raw_ostream &O) { 142218885Sdim const MachineOperand &MO = MI->getOperand(OpNo); 143218885Sdim 144218885Sdim switch (MO.getType()) { 145218885Sdim case MachineOperand::MO_Register: { 146218885Sdim const char *RegName = PPCInstPrinter::getRegisterName(MO.getReg()); 147218885Sdim // Linux assembler (Others?) does not take register mnemonics. 148218885Sdim // FIXME - What about special registers used in mfspr/mtspr? 149218885Sdim if (!Subtarget.isDarwin()) RegName = stripRegisterPrefix(RegName); 150218885Sdim O << RegName; 151218885Sdim return; 152218885Sdim } 153218885Sdim case MachineOperand::MO_Immediate: 154218885Sdim O << MO.getImm(); 155218885Sdim return; 156218885Sdim 157218885Sdim case MachineOperand::MO_MachineBasicBlock: 158218885Sdim O << *MO.getMBB()->getSymbol(); 159218885Sdim return; 160218885Sdim case MachineOperand::MO_JumpTableIndex: 161218885Sdim O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() 162218885Sdim << '_' << MO.getIndex(); 163218885Sdim // FIXME: PIC relocation model 164218885Sdim return; 165218885Sdim case MachineOperand::MO_ConstantPoolIndex: 166218885Sdim O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() 167218885Sdim << '_' << MO.getIndex(); 168218885Sdim return; 169218885Sdim case MachineOperand::MO_BlockAddress: 170218885Sdim O << *GetBlockAddressSymbol(MO.getBlockAddress()); 171218885Sdim return; 172218885Sdim case MachineOperand::MO_ExternalSymbol: { 173218885Sdim // Computing the address of an external symbol, not calling it. 174218885Sdim if (TM.getRelocationModel() == Reloc::Static) { 175218885Sdim O << *GetExternalSymbolSymbol(MO.getSymbolName()); 176218885Sdim return; 177218885Sdim } 178218885Sdim 179218885Sdim MCSymbol *NLPSym = 180218885Sdim OutContext.GetOrCreateSymbol(StringRef(MAI->getGlobalPrefix())+ 181218885Sdim MO.getSymbolName()+"$non_lazy_ptr"); 182218885Sdim MachineModuleInfoImpl::StubValueTy &StubSym = 183218885Sdim MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(NLPSym); 184218885Sdim if (StubSym.getPointer() == 0) 185218885Sdim StubSym = MachineModuleInfoImpl:: 186218885Sdim StubValueTy(GetExternalSymbolSymbol(MO.getSymbolName()), true); 187218885Sdim 188218885Sdim O << *NLPSym; 189218885Sdim return; 190218885Sdim } 191218885Sdim case MachineOperand::MO_GlobalAddress: { 192218885Sdim // Computing the address of a global symbol, not calling it. 193218885Sdim const GlobalValue *GV = MO.getGlobal(); 194218885Sdim MCSymbol *SymToPrint; 195218885Sdim 196218885Sdim // External or weakly linked global variables need non-lazily-resolved stubs 197218885Sdim if (TM.getRelocationModel() != Reloc::Static && 198218885Sdim (GV->isDeclaration() || GV->isWeakForLinker())) { 199218885Sdim if (!GV->hasHiddenVisibility()) { 200218885Sdim SymToPrint = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); 201218885Sdim MachineModuleInfoImpl::StubValueTy &StubSym = 202218885Sdim MMI->getObjFileInfo<MachineModuleInfoMachO>() 203218885Sdim .getGVStubEntry(SymToPrint); 204218885Sdim if (StubSym.getPointer() == 0) 205218885Sdim StubSym = MachineModuleInfoImpl:: 206263508Sdim StubValueTy(getSymbol(GV), !GV->hasInternalLinkage()); 207218885Sdim } else if (GV->isDeclaration() || GV->hasCommonLinkage() || 208218885Sdim GV->hasAvailableExternallyLinkage()) { 209218885Sdim SymToPrint = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); 210218885Sdim 211218885Sdim MachineModuleInfoImpl::StubValueTy &StubSym = 212218885Sdim MMI->getObjFileInfo<MachineModuleInfoMachO>(). 213218885Sdim getHiddenGVStubEntry(SymToPrint); 214218885Sdim if (StubSym.getPointer() == 0) 215218885Sdim StubSym = MachineModuleInfoImpl:: 216263508Sdim StubValueTy(getSymbol(GV), !GV->hasInternalLinkage()); 217218885Sdim } else { 218263508Sdim SymToPrint = getSymbol(GV); 219218885Sdim } 220218885Sdim } else { 221263508Sdim SymToPrint = getSymbol(GV); 222218885Sdim } 223218885Sdim 224218885Sdim O << *SymToPrint; 225218885Sdim 226218885Sdim printOffset(MO.getOffset(), O); 227218885Sdim return; 228218885Sdim } 229218885Sdim 230218885Sdim default: 231218885Sdim O << "<unknown operand type: " << MO.getType() << ">"; 232218885Sdim return; 233218885Sdim } 234218885Sdim} 235218885Sdim 236218885Sdim/// PrintAsmOperand - Print out an operand for an inline asm expression. 237218885Sdim/// 238218885Sdimbool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 239218885Sdim unsigned AsmVariant, 240218885Sdim const char *ExtraCode, raw_ostream &O) { 241218885Sdim // Does this asm operand have a single letter operand modifier? 242218885Sdim if (ExtraCode && ExtraCode[0]) { 243218885Sdim if (ExtraCode[1] != 0) return true; // Unknown modifier. 244218885Sdim 245218885Sdim switch (ExtraCode[0]) { 246239462Sdim default: 247239462Sdim // See if this is a generic print operand 248239462Sdim return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O); 249218885Sdim case 'c': // Don't print "$" before a global var name or constant. 250218885Sdim break; // PPC never has a prefix. 251218885Sdim case 'L': // Write second word of DImode reference. 252218885Sdim // Verify that this operand has two consecutive registers. 253218885Sdim if (!MI->getOperand(OpNo).isReg() || 254218885Sdim OpNo+1 == MI->getNumOperands() || 255218885Sdim !MI->getOperand(OpNo+1).isReg()) 256218885Sdim return true; 257218885Sdim ++OpNo; // Return the high-part. 258218885Sdim break; 259218885Sdim case 'I': 260218885Sdim // Write 'i' if an integer constant, otherwise nothing. Used to print 261218885Sdim // addi vs add, etc. 262218885Sdim if (MI->getOperand(OpNo).isImm()) 263218885Sdim O << "i"; 264218885Sdim return false; 265218885Sdim } 266218885Sdim } 267218885Sdim 268218885Sdim printOperand(MI, OpNo, O); 269218885Sdim return false; 270218885Sdim} 271218885Sdim 272218885Sdim// At the moment, all inline asm memory operands are a single register. 273218885Sdim// In any case, the output of this routine should always be just one 274218885Sdim// assembler operand. 275218885Sdim 276218885Sdimbool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, 277218885Sdim unsigned AsmVariant, 278218885Sdim const char *ExtraCode, 279218885Sdim raw_ostream &O) { 280243830Sdim if (ExtraCode && ExtraCode[0]) { 281243830Sdim if (ExtraCode[1] != 0) return true; // Unknown modifier. 282243830Sdim 283243830Sdim switch (ExtraCode[0]) { 284243830Sdim default: return true; // Unknown modifier. 285243830Sdim case 'y': // A memory reference for an X-form instruction 286243830Sdim { 287243830Sdim const char *RegName = "r0"; 288243830Sdim if (!Subtarget.isDarwin()) RegName = stripRegisterPrefix(RegName); 289243830Sdim O << RegName << ", "; 290243830Sdim printOperand(MI, OpNo, O); 291243830Sdim return false; 292243830Sdim } 293243830Sdim } 294243830Sdim } 295243830Sdim 296218885Sdim assert(MI->getOperand(OpNo).isReg()); 297218885Sdim O << "0("; 298218885Sdim printOperand(MI, OpNo, O); 299218885Sdim O << ")"; 300218885Sdim return false; 301218885Sdim} 302218885Sdim 303218885Sdim 304249423Sdim/// lookUpOrCreateTOCEntry -- Given a symbol, look up whether a TOC entry 305249423Sdim/// exists for it. If not, create one. Then return a symbol that references 306249423Sdim/// the TOC entry. 307249423SdimMCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(MCSymbol *Sym) { 308249423Sdim 309249423Sdim MCSymbol *&TOCEntry = TOC[Sym]; 310249423Sdim 311249423Sdim // To avoid name clash check if the name already exists. 312249423Sdim while (TOCEntry == 0) { 313249423Sdim if (OutContext.LookupSymbol(Twine(MAI->getPrivateGlobalPrefix()) + 314249423Sdim "C" + Twine(TOCLabelID++)) == 0) { 315249423Sdim TOCEntry = GetTempSymbol("C", TOCLabelID); 316249423Sdim } 317249423Sdim } 318249423Sdim 319249423Sdim return TOCEntry; 320249423Sdim} 321249423Sdim 322249423Sdim 323218885Sdim/// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to 324218885Sdim/// the current output stream. 325218885Sdim/// 326218885Sdimvoid PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { 327218885Sdim MCInst TmpInst; 328218885Sdim 329218885Sdim // Lower multi-instruction pseudo operations. 330218885Sdim switch (MI->getOpcode()) { 331218885Sdim default: break; 332263508Sdim case TargetOpcode::DBG_VALUE: 333263508Sdim llvm_unreachable("Should be handled target independently"); 334218885Sdim case PPC::MovePCtoLR: 335218885Sdim case PPC::MovePCtoLR8: { 336218885Sdim // Transform %LR = MovePCtoLR 337218885Sdim // Into this, where the label is the PIC base: 338218885Sdim // bl L1$pb 339218885Sdim // L1$pb: 340218885Sdim MCSymbol *PICBase = MF->getPICBaseSymbol(); 341218885Sdim 342218885Sdim // Emit the 'bl'. 343249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::BL) 344249423Sdim // FIXME: We would like an efficient form for this, so we don't have to do 345249423Sdim // a lot of extra uniquing. 346249423Sdim .addExpr(MCSymbolRefExpr::Create(PICBase, OutContext))); 347218885Sdim 348218885Sdim // Emit the label. 349218885Sdim OutStreamer.EmitLabel(PICBase); 350218885Sdim return; 351218885Sdim } 352243830Sdim case PPC::LDtocJTI: 353243830Sdim case PPC::LDtocCPT: 354218885Sdim case PPC::LDtoc: { 355218885Sdim // Transform %X3 = LDtoc <ga:@min1>, %X2 356223017Sdim LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); 357243830Sdim 358218885Sdim // Change the opcode to LD, and the global address operand to be a 359218885Sdim // reference to the TOC entry we will synthesize later. 360218885Sdim TmpInst.setOpcode(PPC::LD); 361218885Sdim const MachineOperand &MO = MI->getOperand(1); 362243830Sdim 363243830Sdim // Map symbol -> label of TOC entry 364243830Sdim assert(MO.isGlobal() || MO.isCPI() || MO.isJTI()); 365243830Sdim MCSymbol *MOSymbol = 0; 366243830Sdim if (MO.isGlobal()) 367263508Sdim MOSymbol = getSymbol(MO.getGlobal()); 368243830Sdim else if (MO.isCPI()) 369243830Sdim MOSymbol = GetCPISymbol(MO.getIndex()); 370243830Sdim else if (MO.isJTI()) 371243830Sdim MOSymbol = GetJTISymbol(MO.getIndex()); 372243830Sdim 373249423Sdim MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol); 374249423Sdim 375218885Sdim const MCExpr *Exp = 376263508Sdim MCSymbolRefExpr::Create(TOCEntry, MCSymbolRefExpr::VK_PPC_TOC, 377218885Sdim OutContext); 378218885Sdim TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp); 379218885Sdim OutStreamer.EmitInstruction(TmpInst); 380218885Sdim return; 381218885Sdim } 382218885Sdim 383249423Sdim case PPC::ADDIStocHA: { 384249423Sdim // Transform %Xd = ADDIStocHA %X2, <ga:@sym> 385249423Sdim LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); 386249423Sdim 387249423Sdim // Change the opcode to ADDIS8. If the global address is external, 388249423Sdim // has common linkage, is a function address, or is a jump table 389249423Sdim // address, then generate a TOC entry and reference that. Otherwise 390249423Sdim // reference the symbol directly. 391249423Sdim TmpInst.setOpcode(PPC::ADDIS8); 392249423Sdim const MachineOperand &MO = MI->getOperand(2); 393249423Sdim assert((MO.isGlobal() || MO.isCPI() || MO.isJTI()) && 394249423Sdim "Invalid operand for ADDIStocHA!"); 395249423Sdim MCSymbol *MOSymbol = 0; 396249423Sdim bool IsExternal = false; 397249423Sdim bool IsFunction = false; 398249423Sdim bool IsCommon = false; 399249423Sdim bool IsAvailExt = false; 400249423Sdim 401249423Sdim if (MO.isGlobal()) { 402249423Sdim const GlobalValue *GValue = MO.getGlobal(); 403249423Sdim const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue); 404249423Sdim const GlobalValue *RealGValue = GAlias ? 405249423Sdim GAlias->resolveAliasedGlobal(false) : GValue; 406263508Sdim MOSymbol = getSymbol(RealGValue); 407249423Sdim const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue); 408249423Sdim IsExternal = GVar && !GVar->hasInitializer(); 409249423Sdim IsCommon = GVar && RealGValue->hasCommonLinkage(); 410249423Sdim IsFunction = !GVar; 411249423Sdim IsAvailExt = GVar && RealGValue->hasAvailableExternallyLinkage(); 412249423Sdim } else if (MO.isCPI()) 413249423Sdim MOSymbol = GetCPISymbol(MO.getIndex()); 414249423Sdim else if (MO.isJTI()) 415249423Sdim MOSymbol = GetJTISymbol(MO.getIndex()); 416249423Sdim 417263508Sdim if (IsExternal || IsFunction || IsCommon || IsAvailExt || MO.isJTI() || 418263508Sdim TM.getCodeModel() == CodeModel::Large) 419249423Sdim MOSymbol = lookUpOrCreateTOCEntry(MOSymbol); 420249423Sdim 421249423Sdim const MCExpr *Exp = 422263508Sdim MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC_HA, 423249423Sdim OutContext); 424249423Sdim TmpInst.getOperand(2) = MCOperand::CreateExpr(Exp); 425249423Sdim OutStreamer.EmitInstruction(TmpInst); 426249423Sdim return; 427249423Sdim } 428249423Sdim case PPC::LDtocL: { 429249423Sdim // Transform %Xd = LDtocL <ga:@sym>, %Xs 430249423Sdim LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); 431249423Sdim 432249423Sdim // Change the opcode to LD. If the global address is external, has 433249423Sdim // common linkage, or is a jump table address, then reference the 434249423Sdim // associated TOC entry. Otherwise reference the symbol directly. 435249423Sdim TmpInst.setOpcode(PPC::LD); 436249423Sdim const MachineOperand &MO = MI->getOperand(1); 437249423Sdim assert((MO.isGlobal() || MO.isJTI() || MO.isCPI()) && 438249423Sdim "Invalid operand for LDtocL!"); 439249423Sdim MCSymbol *MOSymbol = 0; 440249423Sdim 441249423Sdim if (MO.isJTI()) 442249423Sdim MOSymbol = lookUpOrCreateTOCEntry(GetJTISymbol(MO.getIndex())); 443263508Sdim else if (MO.isCPI()) { 444249423Sdim MOSymbol = GetCPISymbol(MO.getIndex()); 445263508Sdim if (TM.getCodeModel() == CodeModel::Large) 446263508Sdim MOSymbol = lookUpOrCreateTOCEntry(MOSymbol); 447263508Sdim } 448249423Sdim else if (MO.isGlobal()) { 449249423Sdim const GlobalValue *GValue = MO.getGlobal(); 450249423Sdim const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue); 451249423Sdim const GlobalValue *RealGValue = GAlias ? 452249423Sdim GAlias->resolveAliasedGlobal(false) : GValue; 453263508Sdim MOSymbol = getSymbol(RealGValue); 454249423Sdim const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue); 455249423Sdim 456249423Sdim if (!GVar || !GVar->hasInitializer() || RealGValue->hasCommonLinkage() || 457263508Sdim RealGValue->hasAvailableExternallyLinkage() || 458263508Sdim TM.getCodeModel() == CodeModel::Large) 459249423Sdim MOSymbol = lookUpOrCreateTOCEntry(MOSymbol); 460249423Sdim } 461249423Sdim 462249423Sdim const MCExpr *Exp = 463263508Sdim MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC_LO, 464249423Sdim OutContext); 465249423Sdim TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp); 466249423Sdim OutStreamer.EmitInstruction(TmpInst); 467249423Sdim return; 468249423Sdim } 469249423Sdim case PPC::ADDItocL: { 470249423Sdim // Transform %Xd = ADDItocL %Xs, <ga:@sym> 471249423Sdim LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); 472249423Sdim 473249423Sdim // Change the opcode to ADDI8. If the global address is external, then 474249423Sdim // generate a TOC entry and reference that. Otherwise reference the 475249423Sdim // symbol directly. 476249423Sdim TmpInst.setOpcode(PPC::ADDI8); 477249423Sdim const MachineOperand &MO = MI->getOperand(2); 478249423Sdim assert((MO.isGlobal() || MO.isCPI()) && "Invalid operand for ADDItocL"); 479249423Sdim MCSymbol *MOSymbol = 0; 480249423Sdim bool IsExternal = false; 481249423Sdim bool IsFunction = false; 482249423Sdim 483249423Sdim if (MO.isGlobal()) { 484249423Sdim const GlobalValue *GValue = MO.getGlobal(); 485249423Sdim const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue); 486249423Sdim const GlobalValue *RealGValue = GAlias ? 487249423Sdim GAlias->resolveAliasedGlobal(false) : GValue; 488263508Sdim MOSymbol = getSymbol(RealGValue); 489249423Sdim const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue); 490249423Sdim IsExternal = GVar && !GVar->hasInitializer(); 491249423Sdim IsFunction = !GVar; 492249423Sdim } else if (MO.isCPI()) 493249423Sdim MOSymbol = GetCPISymbol(MO.getIndex()); 494249423Sdim 495263508Sdim if (IsFunction || IsExternal || TM.getCodeModel() == CodeModel::Large) 496249423Sdim MOSymbol = lookUpOrCreateTOCEntry(MOSymbol); 497249423Sdim 498249423Sdim const MCExpr *Exp = 499263508Sdim MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC_LO, 500249423Sdim OutContext); 501249423Sdim TmpInst.getOperand(2) = MCOperand::CreateExpr(Exp); 502249423Sdim OutStreamer.EmitInstruction(TmpInst); 503249423Sdim return; 504249423Sdim } 505249423Sdim case PPC::ADDISgotTprelHA: { 506249423Sdim // Transform: %Xd = ADDISgotTprelHA %X2, <ga:@sym> 507249423Sdim // Into: %Xd = ADDIS8 %X2, sym@got@tlsgd@ha 508249423Sdim assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC"); 509249423Sdim const MachineOperand &MO = MI->getOperand(2); 510249423Sdim const GlobalValue *GValue = MO.getGlobal(); 511263508Sdim MCSymbol *MOSymbol = getSymbol(GValue); 512249423Sdim const MCExpr *SymGotTprel = 513263508Sdim MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA, 514249423Sdim OutContext); 515249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS8) 516249423Sdim .addReg(MI->getOperand(0).getReg()) 517249423Sdim .addReg(PPC::X2) 518249423Sdim .addExpr(SymGotTprel)); 519249423Sdim return; 520249423Sdim } 521249423Sdim case PPC::LDgotTprelL: { 522249423Sdim // Transform %Xd = LDgotTprelL <ga:@sym>, %Xs 523249423Sdim LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); 524249423Sdim 525249423Sdim // Change the opcode to LD. 526249423Sdim TmpInst.setOpcode(PPC::LD); 527249423Sdim const MachineOperand &MO = MI->getOperand(1); 528249423Sdim const GlobalValue *GValue = MO.getGlobal(); 529263508Sdim MCSymbol *MOSymbol = getSymbol(GValue); 530249423Sdim const MCExpr *Exp = 531263508Sdim MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO, 532249423Sdim OutContext); 533249423Sdim TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp); 534249423Sdim OutStreamer.EmitInstruction(TmpInst); 535249423Sdim return; 536249423Sdim } 537249423Sdim case PPC::ADDIStlsgdHA: { 538249423Sdim // Transform: %Xd = ADDIStlsgdHA %X2, <ga:@sym> 539249423Sdim // Into: %Xd = ADDIS8 %X2, sym@got@tlsgd@ha 540249423Sdim assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC"); 541249423Sdim const MachineOperand &MO = MI->getOperand(2); 542249423Sdim const GlobalValue *GValue = MO.getGlobal(); 543263508Sdim MCSymbol *MOSymbol = getSymbol(GValue); 544249423Sdim const MCExpr *SymGotTlsGD = 545263508Sdim MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA, 546249423Sdim OutContext); 547249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS8) 548249423Sdim .addReg(MI->getOperand(0).getReg()) 549249423Sdim .addReg(PPC::X2) 550249423Sdim .addExpr(SymGotTlsGD)); 551249423Sdim return; 552249423Sdim } 553249423Sdim case PPC::ADDItlsgdL: { 554249423Sdim // Transform: %Xd = ADDItlsgdL %Xs, <ga:@sym> 555249423Sdim // Into: %Xd = ADDI8 %Xs, sym@got@tlsgd@l 556249423Sdim assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC"); 557249423Sdim const MachineOperand &MO = MI->getOperand(2); 558249423Sdim const GlobalValue *GValue = MO.getGlobal(); 559263508Sdim MCSymbol *MOSymbol = getSymbol(GValue); 560249423Sdim const MCExpr *SymGotTlsGD = 561263508Sdim MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO, 562249423Sdim OutContext); 563249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDI8) 564249423Sdim .addReg(MI->getOperand(0).getReg()) 565249423Sdim .addReg(MI->getOperand(1).getReg()) 566249423Sdim .addExpr(SymGotTlsGD)); 567249423Sdim return; 568249423Sdim } 569249423Sdim case PPC::GETtlsADDR: { 570249423Sdim // Transform: %X3 = GETtlsADDR %X3, <ga:@sym> 571263508Sdim // Into: BL8_NOP_TLS __tls_get_addr(sym@tlsgd) 572249423Sdim assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC"); 573249423Sdim 574249423Sdim StringRef Name = "__tls_get_addr"; 575249423Sdim MCSymbol *TlsGetAddr = OutContext.GetOrCreateSymbol(Name); 576249423Sdim const MCSymbolRefExpr *TlsRef = 577249423Sdim MCSymbolRefExpr::Create(TlsGetAddr, MCSymbolRefExpr::VK_None, OutContext); 578249423Sdim const MachineOperand &MO = MI->getOperand(2); 579249423Sdim const GlobalValue *GValue = MO.getGlobal(); 580263508Sdim MCSymbol *MOSymbol = getSymbol(GValue); 581249423Sdim const MCExpr *SymVar = 582249423Sdim MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TLSGD, 583249423Sdim OutContext); 584263508Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::BL8_NOP_TLS) 585249423Sdim .addExpr(TlsRef) 586249423Sdim .addExpr(SymVar)); 587249423Sdim return; 588249423Sdim } 589249423Sdim case PPC::ADDIStlsldHA: { 590249423Sdim // Transform: %Xd = ADDIStlsldHA %X2, <ga:@sym> 591249423Sdim // Into: %Xd = ADDIS8 %X2, sym@got@tlsld@ha 592249423Sdim assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC"); 593249423Sdim const MachineOperand &MO = MI->getOperand(2); 594249423Sdim const GlobalValue *GValue = MO.getGlobal(); 595263508Sdim MCSymbol *MOSymbol = getSymbol(GValue); 596249423Sdim const MCExpr *SymGotTlsLD = 597263508Sdim MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA, 598249423Sdim OutContext); 599249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS8) 600249423Sdim .addReg(MI->getOperand(0).getReg()) 601249423Sdim .addReg(PPC::X2) 602249423Sdim .addExpr(SymGotTlsLD)); 603249423Sdim return; 604249423Sdim } 605249423Sdim case PPC::ADDItlsldL: { 606249423Sdim // Transform: %Xd = ADDItlsldL %Xs, <ga:@sym> 607249423Sdim // Into: %Xd = ADDI8 %Xs, sym@got@tlsld@l 608249423Sdim assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC"); 609249423Sdim const MachineOperand &MO = MI->getOperand(2); 610249423Sdim const GlobalValue *GValue = MO.getGlobal(); 611263508Sdim MCSymbol *MOSymbol = getSymbol(GValue); 612249423Sdim const MCExpr *SymGotTlsLD = 613263508Sdim MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO, 614249423Sdim OutContext); 615249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDI8) 616249423Sdim .addReg(MI->getOperand(0).getReg()) 617249423Sdim .addReg(MI->getOperand(1).getReg()) 618249423Sdim .addExpr(SymGotTlsLD)); 619249423Sdim return; 620249423Sdim } 621249423Sdim case PPC::GETtlsldADDR: { 622249423Sdim // Transform: %X3 = GETtlsldADDR %X3, <ga:@sym> 623263508Sdim // Into: BL8_NOP_TLS __tls_get_addr(sym@tlsld) 624249423Sdim assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC"); 625249423Sdim 626249423Sdim StringRef Name = "__tls_get_addr"; 627249423Sdim MCSymbol *TlsGetAddr = OutContext.GetOrCreateSymbol(Name); 628249423Sdim const MCSymbolRefExpr *TlsRef = 629249423Sdim MCSymbolRefExpr::Create(TlsGetAddr, MCSymbolRefExpr::VK_None, OutContext); 630249423Sdim const MachineOperand &MO = MI->getOperand(2); 631249423Sdim const GlobalValue *GValue = MO.getGlobal(); 632263508Sdim MCSymbol *MOSymbol = getSymbol(GValue); 633249423Sdim const MCExpr *SymVar = 634249423Sdim MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TLSLD, 635249423Sdim OutContext); 636263508Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::BL8_NOP_TLS) 637249423Sdim .addExpr(TlsRef) 638249423Sdim .addExpr(SymVar)); 639249423Sdim return; 640249423Sdim } 641249423Sdim case PPC::ADDISdtprelHA: { 642249423Sdim // Transform: %Xd = ADDISdtprelHA %X3, <ga:@sym> 643249423Sdim // Into: %Xd = ADDIS8 %X3, sym@dtprel@ha 644249423Sdim assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC"); 645249423Sdim const MachineOperand &MO = MI->getOperand(2); 646249423Sdim const GlobalValue *GValue = MO.getGlobal(); 647263508Sdim MCSymbol *MOSymbol = getSymbol(GValue); 648249423Sdim const MCExpr *SymDtprel = 649263508Sdim MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_DTPREL_HA, 650249423Sdim OutContext); 651249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS8) 652249423Sdim .addReg(MI->getOperand(0).getReg()) 653249423Sdim .addReg(PPC::X3) 654249423Sdim .addExpr(SymDtprel)); 655249423Sdim return; 656249423Sdim } 657249423Sdim case PPC::ADDIdtprelL: { 658249423Sdim // Transform: %Xd = ADDIdtprelL %Xs, <ga:@sym> 659249423Sdim // Into: %Xd = ADDI8 %Xs, sym@dtprel@l 660249423Sdim assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC"); 661249423Sdim const MachineOperand &MO = MI->getOperand(2); 662249423Sdim const GlobalValue *GValue = MO.getGlobal(); 663263508Sdim MCSymbol *MOSymbol = getSymbol(GValue); 664249423Sdim const MCExpr *SymDtprel = 665263508Sdim MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_DTPREL_LO, 666249423Sdim OutContext); 667249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDI8) 668249423Sdim .addReg(MI->getOperand(0).getReg()) 669249423Sdim .addReg(MI->getOperand(1).getReg()) 670249423Sdim .addExpr(SymDtprel)); 671249423Sdim return; 672249423Sdim } 673263508Sdim case PPC::MFOCRF: 674263508Sdim case PPC::MFOCRF8: 675263508Sdim if (!Subtarget.hasMFOCRF()) { 676263508Sdim // Transform: %R3 = MFOCRF %CR7 677263508Sdim // Into: %R3 = MFCR ;; cr7 678263508Sdim unsigned NewOpcode = 679263508Sdim MI->getOpcode() == PPC::MFOCRF ? PPC::MFCR : PPC::MFCR8; 680263508Sdim OutStreamer.AddComment(PPCInstPrinter:: 681263508Sdim getRegisterName(MI->getOperand(1).getReg())); 682263508Sdim OutStreamer.EmitInstruction(MCInstBuilder(NewOpcode) 683263508Sdim .addReg(MI->getOperand(0).getReg())); 684263508Sdim return; 685263508Sdim } 686263508Sdim break; 687263508Sdim case PPC::MTOCRF: 688263508Sdim case PPC::MTOCRF8: 689263508Sdim if (!Subtarget.hasMFOCRF()) { 690263508Sdim // Transform: %CR7 = MTOCRF %R3 691263508Sdim // Into: MTCRF mask, %R3 ;; cr7 692263508Sdim unsigned NewOpcode = 693263508Sdim MI->getOpcode() == PPC::MTOCRF ? PPC::MTCRF : PPC::MTCRF8; 694263508Sdim unsigned Mask = 0x80 >> OutContext.getRegisterInfo() 695263508Sdim ->getEncodingValue(MI->getOperand(0).getReg()); 696263508Sdim OutStreamer.AddComment(PPCInstPrinter:: 697263508Sdim getRegisterName(MI->getOperand(0).getReg())); 698263508Sdim OutStreamer.EmitInstruction(MCInstBuilder(NewOpcode) 699263508Sdim .addImm(Mask) 700263508Sdim .addReg(MI->getOperand(1).getReg())); 701263508Sdim return; 702263508Sdim } 703263508Sdim break; 704263508Sdim case PPC::LD: 705263508Sdim case PPC::STD: 706263508Sdim case PPC::LWA_32: 707263508Sdim case PPC::LWA: { 708263508Sdim // Verify alignment is legal, so we don't create relocations 709263508Sdim // that can't be supported. 710263508Sdim // FIXME: This test is currently disabled for Darwin. The test 711263508Sdim // suite shows a handful of test cases that fail this check for 712263508Sdim // Darwin. Those need to be investigated before this sanity test 713263508Sdim // can be enabled for those subtargets. 714263508Sdim if (!Subtarget.isDarwin()) { 715263508Sdim unsigned OpNum = (MI->getOpcode() == PPC::STD) ? 2 : 1; 716263508Sdim const MachineOperand &MO = MI->getOperand(OpNum); 717263508Sdim if (MO.isGlobal() && MO.getGlobal()->getAlignment() < 4) 718263508Sdim llvm_unreachable("Global must be word-aligned for LD, STD, LWA!"); 719263508Sdim } 720263508Sdim // Now process the instruction normally. 721263508Sdim break; 722218885Sdim } 723263508Sdim } 724218885Sdim 725223017Sdim LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); 726218885Sdim OutStreamer.EmitInstruction(TmpInst); 727218885Sdim} 728218885Sdim 729218885Sdimvoid PPCLinuxAsmPrinter::EmitFunctionEntryLabel() { 730218885Sdim if (!Subtarget.isPPC64()) // linux/ppc32 - Normal entry label. 731218885Sdim return AsmPrinter::EmitFunctionEntryLabel(); 732218885Sdim 733218885Sdim // Emit an official procedure descriptor. 734251662Sdim MCSectionSubPair Current = OutStreamer.getCurrentSection(); 735234353Sdim const MCSectionELF *Section = OutStreamer.getContext().getELFSection(".opd", 736234353Sdim ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC, 737234353Sdim SectionKind::getReadOnly()); 738234353Sdim OutStreamer.SwitchSection(Section); 739218885Sdim OutStreamer.EmitLabel(CurrentFnSym); 740234353Sdim OutStreamer.EmitValueToAlignment(8); 741234353Sdim MCSymbol *Symbol1 = 742234353Sdim OutContext.GetOrCreateSymbol(".L." + Twine(CurrentFnSym->getName())); 743243830Sdim // Generates a R_PPC64_ADDR64 (from FK_DATA_8) relocation for the function 744243830Sdim // entry point. 745234353Sdim OutStreamer.EmitValue(MCSymbolRefExpr::Create(Symbol1, OutContext), 746249423Sdim 8 /*size*/); 747243830Sdim MCSymbol *Symbol2 = OutContext.GetOrCreateSymbol(StringRef(".TOC.")); 748243830Sdim // Generates a R_PPC64_TOC relocation for TOC base insertion. 749243830Sdim OutStreamer.EmitValue(MCSymbolRefExpr::Create(Symbol2, 750263508Sdim MCSymbolRefExpr::VK_PPC_TOCBASE, OutContext), 751249423Sdim 8/*size*/); 752243830Sdim // Emit a null environment pointer. 753249423Sdim OutStreamer.EmitIntValue(0, 8 /* size */); 754251662Sdim OutStreamer.SwitchSection(Current.first, Current.second); 755234353Sdim 756234353Sdim MCSymbol *RealFnSym = OutContext.GetOrCreateSymbol( 757234353Sdim ".L." + Twine(CurrentFnSym->getName())); 758234353Sdim OutStreamer.EmitLabel(RealFnSym); 759234353Sdim CurrentFnSymForSize = RealFnSym; 760218885Sdim} 761218885Sdim 762218885Sdim 763218885Sdimbool PPCLinuxAsmPrinter::doFinalization(Module &M) { 764243830Sdim const DataLayout *TD = TM.getDataLayout(); 765218885Sdim 766218885Sdim bool isPPC64 = TD->getPointerSizeInBits() == 64; 767218885Sdim 768263508Sdim PPCTargetStreamer &TS = 769263508Sdim static_cast<PPCTargetStreamer &>(OutStreamer.getTargetStreamer()); 770263508Sdim 771218885Sdim if (isPPC64 && !TOC.empty()) { 772234353Sdim const MCSectionELF *Section = OutStreamer.getContext().getELFSection(".toc", 773234353Sdim ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC, 774234353Sdim SectionKind::getReadOnly()); 775234353Sdim OutStreamer.SwitchSection(Section); 776218885Sdim 777243830Sdim for (MapVector<MCSymbol*, MCSymbol*>::iterator I = TOC.begin(), 778218885Sdim E = TOC.end(); I != E; ++I) { 779218885Sdim OutStreamer.EmitLabel(I->second); 780243830Sdim MCSymbol *S = OutContext.GetOrCreateSymbol(I->first->getName()); 781263508Sdim TS.emitTCEntry(*S); 782218885Sdim } 783218885Sdim } 784218885Sdim 785249423Sdim MachineModuleInfoELF &MMIELF = 786249423Sdim MMI->getObjFileInfo<MachineModuleInfoELF>(); 787249423Sdim 788249423Sdim MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList(); 789249423Sdim if (!Stubs.empty()) { 790249423Sdim OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); 791249423Sdim for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 792249423Sdim // L_foo$stub: 793249423Sdim OutStreamer.EmitLabel(Stubs[i].first); 794249423Sdim // .long _foo 795249423Sdim OutStreamer.EmitValue(MCSymbolRefExpr::Create(Stubs[i].second.getPointer(), 796249423Sdim OutContext), 797263508Sdim isPPC64 ? 8 : 4/*size*/); 798249423Sdim } 799249423Sdim 800249423Sdim Stubs.clear(); 801249423Sdim OutStreamer.AddBlankLine(); 802249423Sdim } 803249423Sdim 804218885Sdim return AsmPrinter::doFinalization(M); 805218885Sdim} 806218885Sdim 807243830Sdim/// EmitFunctionBodyEnd - Print the traceback table before the .size 808243830Sdim/// directive. 809243830Sdim/// 810243830Sdimvoid PPCLinuxAsmPrinter::EmitFunctionBodyEnd() { 811243830Sdim // Only the 64-bit target requires a traceback table. For now, 812243830Sdim // we only emit the word of zeroes that GDB requires to find 813243830Sdim // the end of the function, and zeroes for the eight-byte 814243830Sdim // mandatory fields. 815243830Sdim // FIXME: We should fill in the eight-byte mandatory fields as described in 816243830Sdim // the PPC64 ELF ABI (this is a low-priority item because GDB does not 817243830Sdim // currently make use of these fields). 818243830Sdim if (Subtarget.isPPC64()) { 819243830Sdim OutStreamer.EmitIntValue(0, 4/*size*/); 820243830Sdim OutStreamer.EmitIntValue(0, 8/*size*/); 821243830Sdim } 822243830Sdim} 823243830Sdim 824218885Sdimvoid PPCDarwinAsmPrinter::EmitStartOfAsmFile(Module &M) { 825218885Sdim static const char *const CPUDirectives[] = { 826218885Sdim "", 827218885Sdim "ppc", 828234353Sdim "ppc440", 829218885Sdim "ppc601", 830218885Sdim "ppc602", 831218885Sdim "ppc603", 832218885Sdim "ppc7400", 833218885Sdim "ppc750", 834218885Sdim "ppc970", 835234353Sdim "ppcA2", 836243830Sdim "ppce500mc", 837243830Sdim "ppce5500", 838249423Sdim "power3", 839249423Sdim "power4", 840249423Sdim "power5", 841249423Sdim "power5x", 842239462Sdim "power6", 843249423Sdim "power6x", 844239462Sdim "power7", 845263508Sdim "ppc64", 846263508Sdim "ppc64le" 847218885Sdim }; 848218885Sdim 849218885Sdim unsigned Directive = Subtarget.getDarwinDirective(); 850239462Sdim if (Subtarget.hasMFOCRF() && Directive < PPC::DIR_970) 851218885Sdim Directive = PPC::DIR_970; 852218885Sdim if (Subtarget.hasAltivec() && Directive < PPC::DIR_7400) 853218885Sdim Directive = PPC::DIR_7400; 854234353Sdim if (Subtarget.isPPC64() && Directive < PPC::DIR_64) 855218885Sdim Directive = PPC::DIR_64; 856218885Sdim assert(Directive <= PPC::DIR_64 && "Directive out of range."); 857218885Sdim 858218885Sdim // FIXME: This is a total hack, finish mc'izing the PPC backend. 859249423Sdim if (OutStreamer.hasRawTextSupport()) { 860263508Sdim assert(Directive < array_lengthof(CPUDirectives) && 861249423Sdim "CPUDirectives[] might not be up-to-date!"); 862218885Sdim OutStreamer.EmitRawText("\t.machine " + Twine(CPUDirectives[Directive])); 863249423Sdim } 864218885Sdim 865218885Sdim // Prime text sections so they are adjacent. This reduces the likelihood a 866218885Sdim // large data or debug section causes a branch to exceed 16M limit. 867218885Sdim const TargetLoweringObjectFileMachO &TLOFMacho = 868218885Sdim static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); 869218885Sdim OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection()); 870218885Sdim if (TM.getRelocationModel() == Reloc::PIC_) { 871218885Sdim OutStreamer.SwitchSection( 872218885Sdim OutContext.getMachOSection("__TEXT", "__picsymbolstub1", 873218885Sdim MCSectionMachO::S_SYMBOL_STUBS | 874218885Sdim MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 875218885Sdim 32, SectionKind::getText())); 876218885Sdim } else if (TM.getRelocationModel() == Reloc::DynamicNoPIC) { 877218885Sdim OutStreamer.SwitchSection( 878218885Sdim OutContext.getMachOSection("__TEXT","__symbol_stub1", 879218885Sdim MCSectionMachO::S_SYMBOL_STUBS | 880218885Sdim MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 881218885Sdim 16, SectionKind::getText())); 882218885Sdim } 883218885Sdim OutStreamer.SwitchSection(getObjFileLowering().getTextSection()); 884218885Sdim} 885218885Sdim 886218885Sdimstatic MCSymbol *GetLazyPtr(MCSymbol *Sym, MCContext &Ctx) { 887218885Sdim // Remove $stub suffix, add $lazy_ptr. 888249423Sdim StringRef NoStub = Sym->getName().substr(0, Sym->getName().size()-5); 889249423Sdim return Ctx.GetOrCreateSymbol(NoStub + "$lazy_ptr"); 890218885Sdim} 891218885Sdim 892218885Sdimstatic MCSymbol *GetAnonSym(MCSymbol *Sym, MCContext &Ctx) { 893218885Sdim // Add $tmp suffix to $stub, yielding $stub$tmp. 894249423Sdim return Ctx.GetOrCreateSymbol(Sym->getName() + "$tmp"); 895218885Sdim} 896218885Sdim 897218885Sdimvoid PPCDarwinAsmPrinter:: 898218885SdimEmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) { 899243830Sdim bool isPPC64 = TM.getDataLayout()->getPointerSizeInBits() == 64; 900263508Sdim bool isDarwin = Subtarget.isDarwin(); 901218885Sdim 902218885Sdim const TargetLoweringObjectFileMachO &TLOFMacho = 903218885Sdim static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); 904218885Sdim 905218885Sdim // .lazy_symbol_pointer 906218885Sdim const MCSection *LSPSection = TLOFMacho.getLazySymbolPointerSection(); 907218885Sdim 908218885Sdim // Output stubs for dynamically-linked functions 909218885Sdim if (TM.getRelocationModel() == Reloc::PIC_) { 910218885Sdim const MCSection *StubSection = 911218885Sdim OutContext.getMachOSection("__TEXT", "__picsymbolstub1", 912218885Sdim MCSectionMachO::S_SYMBOL_STUBS | 913218885Sdim MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 914218885Sdim 32, SectionKind::getText()); 915218885Sdim for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 916218885Sdim OutStreamer.SwitchSection(StubSection); 917218885Sdim EmitAlignment(4); 918218885Sdim 919218885Sdim MCSymbol *Stub = Stubs[i].first; 920218885Sdim MCSymbol *RawSym = Stubs[i].second.getPointer(); 921218885Sdim MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); 922218885Sdim MCSymbol *AnonSymbol = GetAnonSym(Stub, OutContext); 923218885Sdim 924218885Sdim OutStreamer.EmitLabel(Stub); 925218885Sdim OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); 926249423Sdim 927249423Sdim const MCExpr *Anon = MCSymbolRefExpr::Create(AnonSymbol, OutContext); 928263508Sdim const MCExpr *LazyPtrExpr = MCSymbolRefExpr::Create(LazyPtr, OutContext); 929263508Sdim const MCExpr *Sub = 930263508Sdim MCBinaryExpr::CreateSub(LazyPtrExpr, Anon, OutContext); 931249423Sdim 932249423Sdim // mflr r0 933249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::MFLR).addReg(PPC::R0)); 934249423Sdim // bcl 20, 31, AnonSymbol 935249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::BCLalways).addExpr(Anon)); 936218885Sdim OutStreamer.EmitLabel(AnonSymbol); 937249423Sdim // mflr r11 938249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::MFLR).addReg(PPC::R11)); 939249423Sdim // addis r11, r11, ha16(LazyPtr - AnonSymbol) 940263508Sdim const MCExpr *SubHa16 = PPCMCExpr::CreateHa(Sub, isDarwin, OutContext); 941249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS) 942249423Sdim .addReg(PPC::R11) 943249423Sdim .addReg(PPC::R11) 944263508Sdim .addExpr(SubHa16)); 945249423Sdim // mtlr r0 946249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::MTLR).addReg(PPC::R0)); 947249423Sdim 948249423Sdim // ldu r12, lo16(LazyPtr - AnonSymbol)(r11) 949249423Sdim // lwzu r12, lo16(LazyPtr - AnonSymbol)(r11) 950263508Sdim const MCExpr *SubLo16 = PPCMCExpr::CreateLo(Sub, isDarwin, OutContext); 951249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(isPPC64 ? PPC::LDU : PPC::LWZU) 952249423Sdim .addReg(PPC::R12) 953263508Sdim .addExpr(SubLo16).addExpr(SubLo16) 954249423Sdim .addReg(PPC::R11)); 955249423Sdim // mtctr r12 956249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::MTCTR).addReg(PPC::R12)); 957249423Sdim // bctr 958249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::BCTR)); 959249423Sdim 960218885Sdim OutStreamer.SwitchSection(LSPSection); 961218885Sdim OutStreamer.EmitLabel(LazyPtr); 962218885Sdim OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); 963249423Sdim 964249423Sdim MCSymbol *DyldStubBindingHelper = 965249423Sdim OutContext.GetOrCreateSymbol(StringRef("dyld_stub_binding_helper")); 966249423Sdim if (isPPC64) { 967249423Sdim // .quad dyld_stub_binding_helper 968249423Sdim OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 8); 969249423Sdim } else { 970249423Sdim // .long dyld_stub_binding_helper 971249423Sdim OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 4); 972249423Sdim } 973218885Sdim } 974218885Sdim OutStreamer.AddBlankLine(); 975218885Sdim return; 976218885Sdim } 977218885Sdim 978218885Sdim const MCSection *StubSection = 979218885Sdim OutContext.getMachOSection("__TEXT","__symbol_stub1", 980218885Sdim MCSectionMachO::S_SYMBOL_STUBS | 981218885Sdim MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 982218885Sdim 16, SectionKind::getText()); 983218885Sdim for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 984218885Sdim MCSymbol *Stub = Stubs[i].first; 985218885Sdim MCSymbol *RawSym = Stubs[i].second.getPointer(); 986218885Sdim MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); 987263508Sdim const MCExpr *LazyPtrExpr = MCSymbolRefExpr::Create(LazyPtr, OutContext); 988218885Sdim 989218885Sdim OutStreamer.SwitchSection(StubSection); 990218885Sdim EmitAlignment(4); 991218885Sdim OutStreamer.EmitLabel(Stub); 992218885Sdim OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); 993263508Sdim 994249423Sdim // lis r11, ha16(LazyPtr) 995249423Sdim const MCExpr *LazyPtrHa16 = 996263508Sdim PPCMCExpr::CreateHa(LazyPtrExpr, isDarwin, OutContext); 997249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::LIS) 998249423Sdim .addReg(PPC::R11) 999249423Sdim .addExpr(LazyPtrHa16)); 1000249423Sdim 1001249423Sdim // ldu r12, lo16(LazyPtr)(r11) 1002249423Sdim // lwzu r12, lo16(LazyPtr)(r11) 1003263508Sdim const MCExpr *LazyPtrLo16 = 1004263508Sdim PPCMCExpr::CreateLo(LazyPtrExpr, isDarwin, OutContext); 1005249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(isPPC64 ? PPC::LDU : PPC::LWZU) 1006249423Sdim .addReg(PPC::R12) 1007249423Sdim .addExpr(LazyPtrLo16).addExpr(LazyPtrLo16) 1008249423Sdim .addReg(PPC::R11)); 1009249423Sdim 1010249423Sdim // mtctr r12 1011249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::MTCTR).addReg(PPC::R12)); 1012249423Sdim // bctr 1013249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(PPC::BCTR)); 1014249423Sdim 1015218885Sdim OutStreamer.SwitchSection(LSPSection); 1016218885Sdim OutStreamer.EmitLabel(LazyPtr); 1017218885Sdim OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); 1018249423Sdim 1019249423Sdim MCSymbol *DyldStubBindingHelper = 1020249423Sdim OutContext.GetOrCreateSymbol(StringRef("dyld_stub_binding_helper")); 1021249423Sdim if (isPPC64) { 1022249423Sdim // .quad dyld_stub_binding_helper 1023249423Sdim OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 8); 1024249423Sdim } else { 1025249423Sdim // .long dyld_stub_binding_helper 1026249423Sdim OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 4); 1027249423Sdim } 1028218885Sdim } 1029218885Sdim 1030218885Sdim OutStreamer.AddBlankLine(); 1031218885Sdim} 1032218885Sdim 1033218885Sdim 1034218885Sdimbool PPCDarwinAsmPrinter::doFinalization(Module &M) { 1035243830Sdim bool isPPC64 = TM.getDataLayout()->getPointerSizeInBits() == 64; 1036218885Sdim 1037218885Sdim // Darwin/PPC always uses mach-o. 1038218885Sdim const TargetLoweringObjectFileMachO &TLOFMacho = 1039218885Sdim static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); 1040218885Sdim MachineModuleInfoMachO &MMIMacho = 1041218885Sdim MMI->getObjFileInfo<MachineModuleInfoMachO>(); 1042218885Sdim 1043218885Sdim MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetFnStubList(); 1044218885Sdim if (!Stubs.empty()) 1045218885Sdim EmitFunctionStubs(Stubs); 1046218885Sdim 1047218885Sdim if (MAI->doesSupportExceptionHandling() && MMI) { 1048218885Sdim // Add the (possibly multiple) personalities to the set of global values. 1049218885Sdim // Only referenced functions get into the Personalities list. 1050218885Sdim const std::vector<const Function*> &Personalities = MMI->getPersonalities(); 1051218885Sdim for (std::vector<const Function*>::const_iterator I = Personalities.begin(), 1052218885Sdim E = Personalities.end(); I != E; ++I) { 1053218885Sdim if (*I) { 1054218885Sdim MCSymbol *NLPSym = GetSymbolWithGlobalValueBase(*I, "$non_lazy_ptr"); 1055218885Sdim MachineModuleInfoImpl::StubValueTy &StubSym = 1056218885Sdim MMIMacho.getGVStubEntry(NLPSym); 1057263508Sdim StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(*I), true); 1058218885Sdim } 1059218885Sdim } 1060218885Sdim } 1061218885Sdim 1062218885Sdim // Output stubs for dynamically-linked functions. 1063218885Sdim Stubs = MMIMacho.GetGVStubList(); 1064218885Sdim 1065218885Sdim // Output macho stubs for external and common global variables. 1066218885Sdim if (!Stubs.empty()) { 1067218885Sdim // Switch with ".non_lazy_symbol_pointer" directive. 1068218885Sdim OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); 1069218885Sdim EmitAlignment(isPPC64 ? 3 : 2); 1070218885Sdim 1071218885Sdim for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 1072218885Sdim // L_foo$stub: 1073218885Sdim OutStreamer.EmitLabel(Stubs[i].first); 1074218885Sdim // .indirect_symbol _foo 1075218885Sdim MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second; 1076218885Sdim OutStreamer.EmitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol); 1077218885Sdim 1078218885Sdim if (MCSym.getInt()) 1079218885Sdim // External to current translation unit. 1080249423Sdim OutStreamer.EmitIntValue(0, isPPC64 ? 8 : 4/*size*/); 1081218885Sdim else 1082218885Sdim // Internal to current translation unit. 1083218885Sdim // 1084218885Sdim // When we place the LSDA into the TEXT section, the type info pointers 1085218885Sdim // need to be indirect and pc-rel. We accomplish this by using NLPs. 1086218885Sdim // However, sometimes the types are local to the file. So we need to 1087218885Sdim // fill in the value for the NLP in those cases. 1088218885Sdim OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(), 1089218885Sdim OutContext), 1090249423Sdim isPPC64 ? 8 : 4/*size*/); 1091218885Sdim } 1092218885Sdim 1093218885Sdim Stubs.clear(); 1094218885Sdim OutStreamer.AddBlankLine(); 1095218885Sdim } 1096218885Sdim 1097218885Sdim Stubs = MMIMacho.GetHiddenGVStubList(); 1098218885Sdim if (!Stubs.empty()) { 1099218885Sdim OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); 1100218885Sdim EmitAlignment(isPPC64 ? 3 : 2); 1101218885Sdim 1102218885Sdim for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 1103218885Sdim // L_foo$stub: 1104218885Sdim OutStreamer.EmitLabel(Stubs[i].first); 1105218885Sdim // .long _foo 1106218885Sdim OutStreamer.EmitValue(MCSymbolRefExpr:: 1107218885Sdim Create(Stubs[i].second.getPointer(), 1108218885Sdim OutContext), 1109249423Sdim isPPC64 ? 8 : 4/*size*/); 1110218885Sdim } 1111218885Sdim 1112218885Sdim Stubs.clear(); 1113218885Sdim OutStreamer.AddBlankLine(); 1114218885Sdim } 1115218885Sdim 1116218885Sdim // Funny Darwin hack: This flag tells the linker that no global symbols 1117218885Sdim // contain code that falls through to other global symbols (e.g. the obvious 1118218885Sdim // implementation of multiple entry points). If this doesn't occur, the 1119218885Sdim // linker can safely perform dead code stripping. Since LLVM never generates 1120218885Sdim // code that does this, it is always safe to set. 1121218885Sdim OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); 1122218885Sdim 1123218885Sdim return AsmPrinter::doFinalization(M); 1124218885Sdim} 1125218885Sdim 1126218885Sdim/// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code 1127218885Sdim/// for a MachineFunction to the given output stream, in a format that the 1128218885Sdim/// Darwin assembler can deal with. 1129218885Sdim/// 1130218885Sdimstatic AsmPrinter *createPPCAsmPrinterPass(TargetMachine &tm, 1131218885Sdim MCStreamer &Streamer) { 1132218885Sdim const PPCSubtarget *Subtarget = &tm.getSubtarget<PPCSubtarget>(); 1133218885Sdim 1134218885Sdim if (Subtarget->isDarwin()) 1135218885Sdim return new PPCDarwinAsmPrinter(tm, Streamer); 1136218885Sdim return new PPCLinuxAsmPrinter(tm, Streamer); 1137218885Sdim} 1138218885Sdim 1139218885Sdim// Force static initialization. 1140218885Sdimextern "C" void LLVMInitializePowerPCAsmPrinter() { 1141218885Sdim TargetRegistry::RegisterAsmPrinter(ThePPC32Target, createPPCAsmPrinterPass); 1142218885Sdim TargetRegistry::RegisterAsmPrinter(ThePPC64Target, createPPCAsmPrinterPass); 1143218885Sdim} 1144