void ARM64AsmPrinter::EmitEndOfAsmFile(Module &M) { if (Subtarget->isTargetMachO()) { // 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); SM.serializeToStackMapSection(); } // Emit a .data.rel section containing any stubs that were created. 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(0)); } Stubs.clear(); } } }
void SparcAsmPrinter::EmitEndOfAsmFile(Module &M) { const TargetLoweringObjectFileELF &TLOFELF = static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering()); MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>(); // Generate stubs for global variables. MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList(); if (!Stubs.empty()) { OutStreamer.SwitchSection(TLOFELF.getDataSection()); unsigned PtrSize = TM.getDataLayout()->getPointerSize(0); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { OutStreamer.EmitLabel(Stubs[i].first); OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(), PtrSize); } } }
bool PPCLinuxAsmPrinter::doFinalization(Module &M) { const DataLayout *TD = TM.getDataLayout(); bool isPPC64 = TD->getPointerSizeInBits() == 64; if (isPPC64 && !TOC.empty()) { const MCSectionELF *Section = OutStreamer.getContext().getELFSection(".toc", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC, SectionKind::getReadOnly()); OutStreamer.SwitchSection(Section); for (MapVector<MCSymbol*, MCSymbol*>::iterator I = TOC.begin(), E = TOC.end(); I != E; ++I) { OutStreamer.EmitLabel(I->second); MCSymbol *S = OutContext.GetOrCreateSymbol(I->first->getName()); OutStreamer.EmitTCEntry(*S); } } MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>(); MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList(); if (!Stubs.empty()) { OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); 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(); } return AsmPrinter::doFinalization(M); }
void SystemZAsmPrinter::EmitEndOfAsmFile(Module &M) { if (Subtarget->isTargetELF()) { auto &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.getSubtargetImpl()->getDataLayout(); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { OutStreamer.EmitLabel(Stubs[i].first); OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(), TD->getPointerSize(0)); } Stubs.clear(); } } }
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(); } } }