bool PPCDarwinAsmPrinter::doFinalization(Module &M) { bool isPPC64 = TM.getTargetData()->getPointerSizeInBits() == 64; // Darwin/PPC always uses mach-o. const TargetLoweringObjectFileMachO &TLOFMacho = static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); MachineModuleInfoMachO &MMIMacho = MMI->getObjFileInfo<MachineModuleInfoMachO>(); MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetFnStubList(); if (!Stubs.empty()) EmitFunctionStubs(Stubs); if (MAI->doesSupportExceptionHandling() && MMI) { // Add the (possibly multiple) personalities to the set of global values. // Only referenced functions get into the Personalities list. const std::vector<const Function*> &Personalities = MMI->getPersonalities(); for (std::vector<const Function*>::const_iterator I = Personalities.begin(), E = Personalities.end(); I != E; ++I) { if (*I) { MCSymbol *NLPSym = GetSymbolWithGlobalValueBase(*I, "$non_lazy_ptr"); MachineModuleInfoImpl::StubValueTy &StubSym = MMIMacho.getGVStubEntry(NLPSym); StubSym = MachineModuleInfoImpl::StubValueTy(Mang->getSymbol(*I), true); } } } // Output stubs for dynamically-linked functions. Stubs = MMIMacho.GetGVStubList(); // Output macho stubs for external and common global variables. if (!Stubs.empty()) { // Switch with ".non_lazy_symbol_pointer" directive. OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); EmitAlignment(isPPC64 ? 3 : 2); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { // L_foo$stub: OutStreamer.EmitLabel(Stubs[i].first); // .indirect_symbol _foo MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second; OutStreamer.EmitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol); if (MCSym.getInt()) // External to current translation unit. OutStreamer.EmitIntValue(0, isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/); else // Internal to current translation unit. // // When we place the LSDA into the TEXT section, the type info pointers // need to be indirect and pc-rel. We accomplish this by using NLPs. // However, sometimes the types are local to the file. So we need to // fill in the value for the NLP in those cases. OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(), OutContext), isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/); } Stubs.clear(); OutStreamer.AddBlankLine(); } Stubs = MMIMacho.GetHiddenGVStubList(); if (!Stubs.empty()) { OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); EmitAlignment(isPPC64 ? 3 : 2); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { // L_foo$stub: OutStreamer.EmitLabel(Stubs[i].first); // .long _foo OutStreamer.EmitValue(MCSymbolRefExpr:: Create(Stubs[i].second.getPointer(), OutContext), isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/); } Stubs.clear(); OutStreamer.AddBlankLine(); } // Funny Darwin hack: This flag tells the linker that no global symbols // contain code that falls through to other global symbols (e.g. the obvious // implementation of multiple entry points). If this doesn't occur, the // linker can safely perform dead code stripping. Since LLVM never generates // code that does this, it is always safe to set. OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); return AsmPrinter::doFinalization(M); }
void Cse523AsmPrinter::EmitEndOfAsmFile(Module &M) { if (Subtarget->isTargetMacho()) { // All darwin targets use mach-o. MachineModuleInfoMachO &MMIMacho = MMI->getObjFileInfo<MachineModuleInfoMachO>(); // Output stubs for dynamically-linked functions. MachineModuleInfoMachO::SymbolListTy Stubs; Stubs = MMIMacho.GetFnStubList(); if (!Stubs.empty()) { const MCSection *TheSection = OutContext.getMachOSection("__IMPORT", "__jump_table", MCSectionMachO::S_SYMBOL_STUBS | MCSectionMachO::S_ATTR_SELF_MODIFYING_CODE | MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 5, SectionKind::getMetadata()); OutStreamer.SwitchSection(TheSection); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { // L_foo$stub: OutStreamer.EmitLabel(Stubs[i].first); // .indirect_symbol _foo OutStreamer.EmitSymbolAttribute(Stubs[i].second.getPointer(), MCSA_IndirectSymbol); // hlt; hlt; hlt; hlt; hlt hlt = 0xf4. const char HltInsts[] = "\xf4\xf4\xf4\xf4\xf4"; OutStreamer.EmitBytes(StringRef(HltInsts, 5)); } Stubs.clear(); OutStreamer.AddBlankLine(); } // Output stubs for external and common global variables. Stubs = MMIMacho.GetGVStubList(); if (!Stubs.empty()) { const MCSection *TheSection = OutContext.getMachOSection("__IMPORT", "__pointers", MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, SectionKind::getMetadata()); OutStreamer.SwitchSection(TheSection); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { // L_foo$non_lazy_ptr: OutStreamer.EmitLabel(Stubs[i].first); // .indirect_symbol _foo MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second; OutStreamer.EmitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol); // .long 0 if (MCSym.getInt()) // External to current translation unit. OutStreamer.EmitIntValue(0, 4/*size*/); else // Internal to current translation unit. // // When we place the LSDA into the TEXT section, the type info // pointers need to be indirect and pc-rel. We accomplish this by // using NLPs. However, sometimes the types are local to the file. So // we need to fill in the value for the NLP in those cases. OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(), OutContext), 4/*size*/); } Stubs.clear(); OutStreamer.AddBlankLine(); } Stubs = MMIMacho.GetHiddenGVStubList(); if (!Stubs.empty()) { OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); EmitAlignment(2); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { // L_foo$non_lazy_ptr: OutStreamer.EmitLabel(Stubs[i].first); // .long _foo OutStreamer.EmitValue(MCSymbolRefExpr:: Create(Stubs[i].second.getPointer(), OutContext), 4/*size*/); } Stubs.clear(); OutStreamer.AddBlankLine(); } SM.serializeToStackMapSection(); // Funny Darwin hack: This flag tells the linker that no global symbols // contain code that falls through to other global symbols (e.g. the obvious // implementation of multiple entry points). If this doesn't occur, the // linker can safely perform dead code stripping. Since LLVM never // generates code that does this, it is always safe to set. OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); } if (Subtarget->isTargetWindows() && !Subtarget->isTargetCygMing() && MMI->usesVAFloatArgument()) { StringRef SymbolName = Subtarget->is64Bit() ? "_fltused" : "__fltused"; MCSymbol *S = MMI->getContext().GetOrCreateSymbol(SymbolName); OutStreamer.EmitSymbolAttribute(S, MCSA_Global); } if (Subtarget->isTargetCOFF()) { Cse523COFFMachineModuleInfo &COFFMMI = MMI->getObjFileInfo<Cse523COFFMachineModuleInfo>(); // Emit type information for external functions typedef Cse523COFFMachineModuleInfo::externals_iterator externals_iterator; for (externals_iterator I = COFFMMI.externals_begin(), E = COFFMMI.externals_end(); I != E; ++I) { OutStreamer.BeginCOFFSymbolDef(CurrentFnSym); OutStreamer.EmitCOFFSymbolStorageClass(COFF::IMAGE_SYM_CLASS_EXTERNAL); OutStreamer.EmitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT); OutStreamer.EndCOFFSymbolDef(); } // Necessary for dllexport support std::vector<const MCSymbol*> DLLExportedFns, DLLExportedGlobals; for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) if (I->hasDLLExportStorageClass()) DLLExportedFns.push_back(getSymbol(I)); for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) if (I->hasDLLExportStorageClass()) DLLExportedGlobals.push_back(getSymbol(I)); for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) { const GlobalValue *GV = I; if (!GV->hasDLLExportStorageClass()) continue; while (const GlobalAlias *A = dyn_cast<GlobalAlias>(GV)) GV = A->getAliasedGlobal(); if (isa<Function>(GV)) DLLExportedFns.push_back(getSymbol(I)); else if (isa<GlobalVariable>(GV)) DLLExportedGlobals.push_back(getSymbol(I)); } // Output linker support code for dllexported globals on windows. if (!DLLExportedGlobals.empty() || !DLLExportedFns.empty()) { const TargetLoweringObjectFileCOFF &TLOFCOFF = static_cast<const TargetLoweringObjectFileCOFF&>(getObjFileLowering()); OutStreamer.SwitchSection(TLOFCOFF.getDrectveSection()); SmallString<128> name; for (unsigned i = 0, e = DLLExportedGlobals.size(); i != e; ++i) { if (Subtarget->isTargetWindows()) name = " /EXPORT:"; else name = " -export:"; name += DLLExportedGlobals[i]->getName(); if (Subtarget->isTargetWindows()) name += ",DATA"; else name += ",data"; OutStreamer.EmitBytes(name); } for (unsigned i = 0, e = DLLExportedFns.size(); i != e; ++i) { if (Subtarget->isTargetWindows()) name = " /EXPORT:"; else name = " -export:"; name += DLLExportedFns[i]->getName(); OutStreamer.EmitBytes(name); } } } if (Subtarget->isTargetELF()) { const TargetLoweringObjectFileELF &TLOFELF = static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering()); MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>(); // Output stubs for external and common global variables. MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList(); if (!Stubs.empty()) { OutStreamer.SwitchSection(TLOFELF.getDataRelSection()); const DataLayout *TD = TM.getDataLayout(); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { OutStreamer.EmitLabel(Stubs[i].first); OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(), TD->getPointerSize()); } Stubs.clear(); } } }
void PPCDarwinAsmPrinter:: EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) { bool isPPC64 = TM.getTargetData()->getPointerSizeInBits() == 64; const TargetLoweringObjectFileMachO &TLOFMacho = static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); // .lazy_symbol_pointer const MCSection *LSPSection = TLOFMacho.getLazySymbolPointerSection(); // Output stubs for dynamically-linked functions if (TM.getRelocationModel() == Reloc::PIC_) { const MCSection *StubSection = OutContext.getMachOSection("__TEXT", "__picsymbolstub1", MCSectionMachO::S_SYMBOL_STUBS | MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 32, SectionKind::getText()); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { OutStreamer.SwitchSection(StubSection); EmitAlignment(4); MCSymbol *Stub = Stubs[i].first; MCSymbol *RawSym = Stubs[i].second.getPointer(); MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); MCSymbol *AnonSymbol = GetAnonSym(Stub, OutContext); OutStreamer.EmitLabel(Stub); OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); // FIXME: MCize this. OutStreamer.EmitRawText(StringRef("\tmflr r0")); OutStreamer.EmitRawText("\tbcl 20,31," + Twine(AnonSymbol->getName())); OutStreamer.EmitLabel(AnonSymbol); OutStreamer.EmitRawText(StringRef("\tmflr r11")); OutStreamer.EmitRawText("\taddis r11,r11,ha16("+Twine(LazyPtr->getName())+ "-" + AnonSymbol->getName() + ")"); OutStreamer.EmitRawText(StringRef("\tmtlr r0")); if (isPPC64) OutStreamer.EmitRawText("\tldu r12,lo16(" + Twine(LazyPtr->getName()) + "-" + AnonSymbol->getName() + ")(r11)"); else OutStreamer.EmitRawText("\tlwzu r12,lo16(" + Twine(LazyPtr->getName()) + "-" + AnonSymbol->getName() + ")(r11)"); OutStreamer.EmitRawText(StringRef("\tmtctr r12")); OutStreamer.EmitRawText(StringRef("\tbctr")); OutStreamer.SwitchSection(LSPSection); OutStreamer.EmitLabel(LazyPtr); OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); if (isPPC64) OutStreamer.EmitRawText(StringRef("\t.quad dyld_stub_binding_helper")); else OutStreamer.EmitRawText(StringRef("\t.long dyld_stub_binding_helper")); } OutStreamer.AddBlankLine(); return; } const MCSection *StubSection = OutContext.getMachOSection("__TEXT","__symbol_stub1", MCSectionMachO::S_SYMBOL_STUBS | MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 16, SectionKind::getText()); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { MCSymbol *Stub = Stubs[i].first; MCSymbol *RawSym = Stubs[i].second.getPointer(); MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); OutStreamer.SwitchSection(StubSection); EmitAlignment(4); OutStreamer.EmitLabel(Stub); OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); OutStreamer.EmitRawText("\tlis r11,ha16(" + Twine(LazyPtr->getName()) +")"); if (isPPC64) OutStreamer.EmitRawText("\tldu r12,lo16(" + Twine(LazyPtr->getName()) + ")(r11)"); else OutStreamer.EmitRawText("\tlwzu r12,lo16(" + Twine(LazyPtr->getName()) + ")(r11)"); OutStreamer.EmitRawText(StringRef("\tmtctr r12")); OutStreamer.EmitRawText(StringRef("\tbctr")); OutStreamer.SwitchSection(LSPSection); OutStreamer.EmitLabel(LazyPtr); OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); if (isPPC64) OutStreamer.EmitRawText(StringRef("\t.quad dyld_stub_binding_helper")); else OutStreamer.EmitRawText(StringRef("\t.long dyld_stub_binding_helper")); } OutStreamer.AddBlankLine(); }
void PPCDarwinAsmPrinter:: EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) { bool isPPC64 = TM.getDataLayout()->getPointerSizeInBits() == 64; const TargetLoweringObjectFileMachO &TLOFMacho = static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); // .lazy_symbol_pointer const MCSection *LSPSection = TLOFMacho.getLazySymbolPointerSection(); // Output stubs for dynamically-linked functions if (TM.getRelocationModel() == Reloc::PIC_) { const MCSection *StubSection = OutContext.getMachOSection("__TEXT", "__picsymbolstub1", MCSectionMachO::S_SYMBOL_STUBS | MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 32, SectionKind::getText()); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { OutStreamer.SwitchSection(StubSection); EmitAlignment(4); MCSymbol *Stub = Stubs[i].first; MCSymbol *RawSym = Stubs[i].second.getPointer(); MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); MCSymbol *AnonSymbol = GetAnonSym(Stub, OutContext); OutStreamer.EmitLabel(Stub); OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); // mflr r0 OutStreamer.EmitInstruction(MCInstBuilder(PPC::MFLR).addReg(PPC::R0)); // FIXME: MCize this. OutStreamer.EmitRawText("\tbcl 20, 31, " + Twine(AnonSymbol->getName())); OutStreamer.EmitLabel(AnonSymbol); // mflr r11 OutStreamer.EmitInstruction(MCInstBuilder(PPC::MFLR).addReg(PPC::R11)); // addis r11, r11, ha16(LazyPtr - AnonSymbol) const MCExpr *Sub = MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(LazyPtr, OutContext), MCSymbolRefExpr::Create(AnonSymbol, OutContext), OutContext); OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS) .addReg(PPC::R11) .addReg(PPC::R11) .addExpr(Sub)); // mtlr r0 OutStreamer.EmitInstruction(MCInstBuilder(PPC::MTLR).addReg(PPC::R0)); // ldu r12, lo16(LazyPtr - AnonSymbol)(r11) // lwzu r12, lo16(LazyPtr - AnonSymbol)(r11) OutStreamer.EmitInstruction(MCInstBuilder(isPPC64 ? PPC::LDU : PPC::LWZU) .addReg(PPC::R12) .addExpr(Sub).addExpr(Sub) .addReg(PPC::R11)); // mtctr r12 OutStreamer.EmitInstruction(MCInstBuilder(PPC::MTCTR).addReg(PPC::R12)); // bctr OutStreamer.EmitInstruction(MCInstBuilder(PPC::BCTR)); OutStreamer.SwitchSection(LSPSection); OutStreamer.EmitLabel(LazyPtr); OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); MCSymbol *DyldStubBindingHelper = OutContext.GetOrCreateSymbol(StringRef("dyld_stub_binding_helper")); if (isPPC64) { // .quad dyld_stub_binding_helper OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 8); } else { // .long dyld_stub_binding_helper OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 4); } } OutStreamer.AddBlankLine(); return; } const MCSection *StubSection = OutContext.getMachOSection("__TEXT","__symbol_stub1", MCSectionMachO::S_SYMBOL_STUBS | MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 16, SectionKind::getText()); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { MCSymbol *Stub = Stubs[i].first; MCSymbol *RawSym = Stubs[i].second.getPointer(); MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); OutStreamer.SwitchSection(StubSection); EmitAlignment(4); OutStreamer.EmitLabel(Stub); OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); // lis r11, ha16(LazyPtr) const MCExpr *LazyPtrHa16 = MCSymbolRefExpr::Create(LazyPtr, MCSymbolRefExpr::VK_PPC_DARWIN_HA16, OutContext); OutStreamer.EmitInstruction(MCInstBuilder(PPC::LIS) .addReg(PPC::R11) .addExpr(LazyPtrHa16)); const MCExpr *LazyPtrLo16 = MCSymbolRefExpr::Create(LazyPtr, MCSymbolRefExpr::VK_PPC_DARWIN_LO16, OutContext); // ldu r12, lo16(LazyPtr)(r11) // lwzu r12, lo16(LazyPtr)(r11) OutStreamer.EmitInstruction(MCInstBuilder(isPPC64 ? PPC::LDU : PPC::LWZU) .addReg(PPC::R12) .addExpr(LazyPtrLo16).addExpr(LazyPtrLo16) .addReg(PPC::R11)); // mtctr r12 OutStreamer.EmitInstruction(MCInstBuilder(PPC::MTCTR).addReg(PPC::R12)); // bctr OutStreamer.EmitInstruction(MCInstBuilder(PPC::BCTR)); OutStreamer.SwitchSection(LSPSection); OutStreamer.EmitLabel(LazyPtr); OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); MCSymbol *DyldStubBindingHelper = OutContext.GetOrCreateSymbol(StringRef("dyld_stub_binding_helper")); if (isPPC64) { // .quad dyld_stub_binding_helper OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 8); } else { // .long dyld_stub_binding_helper OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 4); } } OutStreamer.AddBlankLine(); }