/// EmitStringTable - If the current symbol table is non-empty, emit the string /// table for it void ELFWriter::EmitStringTable(const std::string &ModuleName) { if (!SymbolList.size()) return; // Empty symbol table. ELFSection &StrTab = getStringTableSection(); // Set the zero'th symbol to a null byte, as required. StrTab.emitByte(0); // Walk on the symbol list and write symbol names into the string table. unsigned Index = 1; for (ELFSymIter I=SymbolList.begin(), E=SymbolList.end(); I != E; ++I) { ELFSym &Sym = *(*I); std::string Name; if (Sym.isGlobalValue()) { SmallString<40> NameStr; Mang->getNameWithPrefix(NameStr, Sym.getGlobalValue(), false); Name.append(NameStr.begin(), NameStr.end()); } else if (Sym.isExternalSym()) Name.append(Sym.getExternalSymbol()); else if (Sym.isFileType()) Name.append(ModuleName); if (Name.empty()) { Sym.NameIdx = 0; } else { Sym.NameIdx = Index; StrTab.emitString(Name); // Keep track of the number of bytes emitted to this section. Index += Name.size()+1; } } assert(Index == StrTab.size()); StrTab.Size = Index; }
// Compute the relative path from From to To. static std::string computeRelativePath(StringRef From, StringRef To) { if (sys::path::is_absolute(From) || sys::path::is_absolute(To)) return To; StringRef DirFrom = sys::path::parent_path(From); auto FromI = sys::path::begin(DirFrom); auto ToI = sys::path::begin(To); while (*FromI == *ToI) { ++FromI; ++ToI; } SmallString<128> Relative; for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI) sys::path::append(Relative, ".."); for (auto ToE = sys::path::end(To); ToI != ToE; ++ToI) sys::path::append(Relative, *ToI); #ifdef LLVM_ON_WIN32 // Replace backslashes with slashes so that the path is portable between *nix // and Windows. std::replace(Relative.begin(), Relative.end(), '\\', '/'); #endif return Relative.str(); }
void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst) { MCInstFragment *IF = new MCInstFragment(Inst, getCurrentSectionData()); SmallString<128> Code; raw_svector_ostream VecOS(Code); getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, IF->getFixups()); VecOS.flush(); IF->getCode().append(Code.begin(), Code.end()); }
void MCELFStreamer::EmitInstToData(const MCInst &Inst) { MCAssembler &Assembler = getAssembler(); SmallVector<MCFixup, 4> Fixups; SmallString<256> Code; raw_svector_ostream VecOS(Code); Assembler.getEmitter().EncodeInstruction(Inst, VecOS, Fixups); VecOS.flush(); for (unsigned i = 0, e = Fixups.size(); i != e; ++i) fixSymbolsInTLSFixups(Fixups[i].getValue()); // There are several possibilities here: // // If bundling is disabled, append the encoded instruction to the current data // fragment (or create a new such fragment if the current fragment is not a // data fragment). // // If bundling is enabled: // - If we're not in a bundle-locked group, emit the instruction into a data // fragment of its own. // - If we're in a bundle-locked group, append the instruction to the current // data fragment because we want all the instructions in a group to get into // the same fragment. Be careful not to do that for the first instruction in // the group, though. MCDataFragment *DF; if (Assembler.isBundlingEnabled()) { MCSectionData *SD = getCurrentSectionData(); if (SD->isBundleLocked() && !SD->isBundleGroupBeforeFirstInst()) DF = getOrCreateDataFragment(); else { DF = new MCDataFragment(SD); if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) { // If this is a new fragment created for a bundle-locked group, and the // group was marked as "align_to_end", set a flag in the fragment. DF->setAlignToBundleEnd(true); } } // We're now emitting an instruction in a bundle group, so this flag has // to be turned off. SD->setBundleGroupBeforeFirstInst(false); } else { DF = getOrCreateDataFragment(); } // Add the fixups and data. for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); DF->getFixups().push_back(Fixups[i]); } DF->setHasInstructions(true); DF->getContents().append(Code.begin(), Code.end()); }
void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst) { // Always create a new, separate fragment here, because its size can change // during relaxation. MCRelaxableFragment *IF = new MCRelaxableFragment(Inst); insert(IF); SmallString<128> Code; raw_svector_ostream VecOS(Code); getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, IF->getFixups()); VecOS.flush(); IF->getContents().append(Code.begin(), Code.end()); }
StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info) : ID(Info.getID()), Level(Level) { assert((Info.getLocation().isInvalid() || Info.hasSourceManager()) && "Valid source location without setting a source manager for diagnostic"); if (Info.getLocation().isValid()) Loc = FullSourceLoc(Info.getLocation(), Info.getSourceManager()); SmallString<64> Message; Info.FormatDiagnostic(Message); this->Message.assign(Message.begin(), Message.end()); this->Ranges.assign(Info.getRanges().begin(), Info.getRanges().end()); this->FixIts.assign(Info.getFixItHints().begin(), Info.getFixItHints().end()); }
void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &STI) { if (getAssembler().getRelaxAll() && getAssembler().isBundlingEnabled()) llvm_unreachable("All instructions should have already been relaxed"); // Always create a new, separate fragment here, because its size can change // during relaxation. MCRelaxableFragment *IF = new MCRelaxableFragment(Inst, STI); insert(IF); SmallString<128> Code; raw_svector_ostream VecOS(Code); getAssembler().getEmitter().encodeInstruction(Inst, VecOS, IF->getFixups(), STI); IF->getContents().append(Code.begin(), Code.end()); }
void MCMachOStreamer::EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) { MCDataFragment *DF = getOrCreateDataFragment(); SmallVector<MCFixup, 4> Fixups; SmallString<256> Code; raw_svector_ostream VecOS(Code); getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); // Add the fixups and data. for (MCFixup &Fixup : Fixups) { Fixup.setOffset(Fixup.getOffset() + DF->getContents().size()); DF->getFixups().push_back(Fixup); } DF->getContents().append(Code.begin(), Code.end()); }
void MCMachOStreamer::EmitInstToData(const MCInst &Inst) { MCDataFragment *DF = getOrCreateDataFragment(); SmallVector<MCFixup, 4> Fixups; SmallString<256> Code; raw_svector_ostream VecOS(Code); getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups); VecOS.flush(); // Add the fixups and data. for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); DF->addFixup(Fixups[i]); } DF->getContents().append(Code.begin(), Code.end()); }
static ErrorOr<std::unique_ptr<MemoryBuffer>> getMemoryBufferForStream(int FD, const Twine &BufferName) { const ssize_t ChunkSize = 4096*4; SmallString<ChunkSize> Buffer; ssize_t ReadBytes; // Read into Buffer until we hit EOF. do { Buffer.reserve(Buffer.size() + ChunkSize); ReadBytes = read(FD, Buffer.end(), ChunkSize); if (ReadBytes == -1) { if (errno == EINTR) continue; return std::error_code(errno, std::generic_category()); } Buffer.set_size(Buffer.size() + ReadBytes); } while (ReadBytes != 0); return MemoryBuffer::getMemBufferCopy(Buffer, BufferName); }
HeaderSearch::LoadModuleMapResult HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir) { llvm::DenseMap<const DirectoryEntry *, bool>::iterator KnownDir = DirectoryHasModuleMap.find(Dir); if (KnownDir != DirectoryHasModuleMap.end()) return KnownDir->second? LMM_AlreadyLoaded : LMM_InvalidModuleMap; SmallString<128> ModuleMapFileName; ModuleMapFileName += Dir->getName(); unsigned ModuleMapDirNameLen = ModuleMapFileName.size(); llvm::sys::path::append(ModuleMapFileName, "module.map"); if (const FileEntry *ModuleMapFile = FileMgr.getFile(ModuleMapFileName)) { // We have found a module map file. Try to parse it. if (ModMap.parseModuleMapFile(ModuleMapFile)) { // No suitable module map. DirectoryHasModuleMap[Dir] = false; return LMM_InvalidModuleMap; } // This directory has a module map. DirectoryHasModuleMap[Dir] = true; // Check whether there is a private module map that we need to load as well. ModuleMapFileName.erase(ModuleMapFileName.begin() + ModuleMapDirNameLen, ModuleMapFileName.end()); llvm::sys::path::append(ModuleMapFileName, "module_private.map"); if (const FileEntry *PrivateModuleMapFile = FileMgr.getFile(ModuleMapFileName)) { if (ModMap.parseModuleMapFile(PrivateModuleMapFile)) { // No suitable module map. DirectoryHasModuleMap[Dir] = false; return LMM_InvalidModuleMap; } } return LMM_NewlyLoaded; } // No suitable module map. DirectoryHasModuleMap[Dir] = false; return LMM_InvalidModuleMap; }
static error_code getMemoryBufferForStream(int FD, StringRef BufferName, std::unique_ptr<MemoryBuffer> &Result) { const ssize_t ChunkSize = 4096*4; SmallString<ChunkSize> Buffer; ssize_t ReadBytes; // Read into Buffer until we hit EOF. do { Buffer.reserve(Buffer.size() + ChunkSize); ReadBytes = read(FD, Buffer.end(), ChunkSize); if (ReadBytes == -1) { if (errno == EINTR) continue; return error_code(errno, posix_category()); } Buffer.set_size(Buffer.size() + ReadBytes); } while (ReadBytes != 0); Result.reset(MemoryBuffer::getMemBufferCopy(Buffer, BufferName)); return error_code::success(); }
StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info) : ID(Info.getID()), Level(Level) { assert((Info.getLocation().isInvalid() || Info.hasSourceManager()) && "Valid source location without setting a source manager for diagnostic"); if (Info.getLocation().isValid()) Loc = FullSourceLoc(Info.getLocation(), Info.getSourceManager()); SmallString<64> Message; Info.FormatDiagnostic(Message); this->Message.assign(Message.begin(), Message.end()); Ranges.reserve(Info.getNumRanges()); for (unsigned I = 0, N = Info.getNumRanges(); I != N; ++I) Ranges.push_back(Info.getRange(I)); FixIts.reserve(Info.getNumFixItHints()); for (unsigned I = 0, N = Info.getNumFixItHints(); I != N; ++I) FixIts.push_back(Info.getFixItHint(I)); }
void MCELFStreamer::mergeFragment(MCDataFragment *DF, MCEncodedFragmentWithFixups *EF) { MCAssembler &Assembler = getAssembler(); if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) { uint64_t FSize = EF->getContents().size(); if (FSize > Assembler.getBundleAlignSize()) report_fatal_error("Fragment can't be larger than a bundle size"); uint64_t RequiredBundlePadding = computeBundlePadding( Assembler, EF, DF->getContents().size(), FSize); if (RequiredBundlePadding > UINT8_MAX) report_fatal_error("Padding cannot exceed 255 bytes"); if (RequiredBundlePadding > 0) { SmallString<256> Code; raw_svector_ostream VecOS(Code); MCObjectWriter *OW = Assembler.getBackend().createObjectWriter(VecOS); EF->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding)); Assembler.writeFragmentPadding(*EF, FSize, OW); VecOS.flush(); delete OW; DF->getContents().append(Code.begin(), Code.end()); } } flushPendingLabels(DF, DF->getContents().size()); for (unsigned i = 0, e = EF->getFixups().size(); i != e; ++i) { EF->getFixups()[i].setOffset(EF->getFixups()[i].getOffset() + DF->getContents().size()); DF->getFixups().push_back(EF->getFixups()[i]); } DF->setHasInstructions(true); DF->getContents().append(EF->getContents().begin(), EF->getContents().end()); }
/// linkDefinedTypeBodies - Produce a body for an opaque type in the dest /// module from a type definition in the source module. void TypeMapTy::linkDefinedTypeBodies() { SmallVector<Type*, 16> Elements; SmallString<16> TmpName; // Note that processing entries in this loop (calling 'get') can add new // entries to the SrcDefinitionsToResolve vector. while (!SrcDefinitionsToResolve.empty()) { StructType *SrcSTy = SrcDefinitionsToResolve.pop_back_val(); StructType *DstSTy = cast<StructType>(MappedTypes[SrcSTy]); // TypeMap is a many-to-one mapping, if there were multiple types that // provide a body for DstSTy then previous iterations of this loop may have // already handled it. Just ignore this case. if (!DstSTy->isOpaque()) continue; assert(!SrcSTy->isOpaque() && "Not resolving a definition?"); // Map the body of the source type over to a new body for the dest type. Elements.resize(SrcSTy->getNumElements()); for (unsigned i = 0, e = Elements.size(); i != e; ++i) Elements[i] = getImpl(SrcSTy->getElementType(i)); DstSTy->setBody(Elements, SrcSTy->isPacked()); // If DstSTy has no name or has a longer name than STy, then viciously steal // STy's name. if (!SrcSTy->hasName()) continue; StringRef SrcName = SrcSTy->getName(); if (!DstSTy->hasName() || DstSTy->getName().size() > SrcName.size()) { TmpName.insert(TmpName.end(), SrcName.begin(), SrcName.end()); SrcSTy->setName(""); DstSTy->setName(TmpName.str()); TmpName.clear(); } } DstResolvedOpaqueTypes.clear(); }
error_code MemoryBuffer::getSTDIN(OwningPtr<MemoryBuffer> &result) { // Read in all of the data from stdin, we cannot mmap stdin. // // FIXME: That isn't necessarily true, we should try to mmap stdin and // fallback if it fails. sys::Program::ChangeStdinToBinary(); const ssize_t ChunkSize = 4096*4; SmallString<ChunkSize> Buffer; ssize_t ReadBytes; // Read into Buffer until we hit EOF. do { Buffer.reserve(Buffer.size() + ChunkSize); ReadBytes = read(0, Buffer.end(), ChunkSize); if (ReadBytes == -1) { if (errno == EINTR) continue; return error_code(errno, posix_category()); } Buffer.set_size(Buffer.size() + ReadBytes); } while (ReadBytes != 0); result.reset(getMemBufferCopy(Buffer, "<stdin>")); return error_code::success(); }
/// ComputeSymbolTable - Compute the symbol table data /// /// \param StringTable [out] - The string table data. /// \param StringIndexMap [out] - Map from symbol names to offsets in the /// string table. void MachObjectWriter:: ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, std::vector<MachSymbolData> &LocalSymbolData, std::vector<MachSymbolData> &ExternalSymbolData, std::vector<MachSymbolData> &UndefinedSymbolData) { // Build section lookup table. DenseMap<const MCSection*, uint8_t> SectionIndexMap; unsigned Index = 1; for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it, ++Index) SectionIndexMap[&it->getSection()] = Index; assert(Index <= 256 && "Too many sections!"); // Index 0 is always the empty string. StringMap<uint64_t> StringIndexMap; StringTable += '\x00'; // Build the symbol arrays and the string table, but only for non-local // symbols. // // The particular order that we collect the symbols and create the string // table, then sort the symbols is chosen to match 'as'. Even though it // doesn't matter for correctness, this is important for letting us diff .o // files. for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), ie = Asm.symbol_end(); it != ie; ++it) { const MCSymbol &Symbol = it->getSymbol(); // Ignore non-linker visible symbols. if (!Asm.isSymbolLinkerVisible(it->getSymbol())) continue; if (!it->isExternal() && !Symbol.isUndefined()) continue; uint64_t &Entry = StringIndexMap[Symbol.getName()]; if (!Entry) { Entry = StringTable.size(); StringTable += Symbol.getName(); StringTable += '\x00'; } MachSymbolData MSD; MSD.SymbolData = it; MSD.StringIndex = Entry; if (Symbol.isUndefined()) { MSD.SectionIndex = 0; UndefinedSymbolData.push_back(MSD); } else if (Symbol.isAbsolute()) { MSD.SectionIndex = 0; ExternalSymbolData.push_back(MSD); } else { MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection()); assert(MSD.SectionIndex && "Invalid section index!"); ExternalSymbolData.push_back(MSD); } } // Now add the data for local symbols. for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), ie = Asm.symbol_end(); it != ie; ++it) { const MCSymbol &Symbol = it->getSymbol(); // Ignore non-linker visible symbols. if (!Asm.isSymbolLinkerVisible(it->getSymbol())) continue; if (it->isExternal() || Symbol.isUndefined()) continue; uint64_t &Entry = StringIndexMap[Symbol.getName()]; if (!Entry) { Entry = StringTable.size(); StringTable += Symbol.getName(); StringTable += '\x00'; } MachSymbolData MSD; MSD.SymbolData = it; MSD.StringIndex = Entry; if (Symbol.isAbsolute()) { MSD.SectionIndex = 0; LocalSymbolData.push_back(MSD); } else { MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection()); assert(MSD.SectionIndex && "Invalid section index!"); LocalSymbolData.push_back(MSD); } } // External and undefined symbols are required to be in lexicographic order. std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end()); std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end()); // Set the symbol indices. Index = 0; for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) LocalSymbolData[i].SymbolData->setIndex(Index++); for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) ExternalSymbolData[i].SymbolData->setIndex(Index++); for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) UndefinedSymbolData[i].SymbolData->setIndex(Index++); // The string table is padded to a multiple of 4. while (StringTable.size() % 4) StringTable += '\x00'; }
void MCELFStreamer::EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) { MCAssembler &Assembler = getAssembler(); SmallVector<MCFixup, 4> Fixups; SmallString<256> Code; raw_svector_ostream VecOS(Code); Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); VecOS.flush(); for (unsigned i = 0, e = Fixups.size(); i != e; ++i) fixSymbolsInTLSFixups(Fixups[i].getValue()); // There are several possibilities here: // // If bundling is disabled, append the encoded instruction to the current data // fragment (or create a new such fragment if the current fragment is not a // data fragment). // // If bundling is enabled: // - If we're not in a bundle-locked group, emit the instruction into a // fragment of its own. If there are no fixups registered for the // instruction, emit a MCCompactEncodedInstFragment. Otherwise, emit a // MCDataFragment. // - If we're in a bundle-locked group, append the instruction to the current // data fragment because we want all the instructions in a group to get into // the same fragment. Be careful not to do that for the first instruction in // the group, though. MCDataFragment *DF; if (Assembler.isBundlingEnabled()) { MCSection &Sec = *getCurrentSectionOnly(); if (Assembler.getRelaxAll() && isBundleLocked()) // If the -mc-relax-all flag is used and we are bundle-locked, we re-use // the current bundle group. DF = BundleGroups.back(); else if (Assembler.getRelaxAll() && !isBundleLocked()) // When not in a bundle-locked group and the -mc-relax-all flag is used, // we create a new temporary fragment which will be later merged into // the current fragment. DF = new MCDataFragment(); else if (isBundleLocked() && !Sec.isBundleGroupBeforeFirstInst()) // If we are bundle-locked, we re-use the current fragment. // The bundle-locking directive ensures this is a new data fragment. DF = cast<MCDataFragment>(getCurrentFragment()); else if (!isBundleLocked() && Fixups.size() == 0) { // Optimize memory usage by emitting the instruction to a // MCCompactEncodedInstFragment when not in a bundle-locked group and // there are no fixups registered. MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment(); insert(CEIF); CEIF->getContents().append(Code.begin(), Code.end()); return; } else { DF = new MCDataFragment(); insert(DF); } if (Sec.getBundleLockState() == MCSection::BundleLockedAlignToEnd) { // If this fragment is for a group marked "align_to_end", set a flag // in the fragment. This can happen after the fragment has already been // created if there are nested bundle_align groups and an inner one // is the one marked align_to_end. DF->setAlignToBundleEnd(true); } // We're now emitting an instruction in a bundle group, so this flag has // to be turned off. Sec.setBundleGroupBeforeFirstInst(false); } else { DF = getOrCreateDataFragment(); } // Add the fixups and data. for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); DF->getFixups().push_back(Fixups[i]); } DF->setHasInstructions(true); DF->getContents().append(Code.begin(), Code.end()); if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) { if (!isBundleLocked()) { mergeFragment(getOrCreateDataFragment(), DF); delete DF; } } }
/// DoFrameworkLookup - Do a lookup of the specified file in the current /// DirectoryLookup, which is a framework directory. const FileEntry *DirectoryLookup::DoFrameworkLookup( StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, ModuleMap::KnownHeader *SuggestedModule, bool &InUserSpecifiedSystemFramework) const { FileManager &FileMgr = HS.getFileMgr(); // Framework names must have a '/' in the filename. size_t SlashPos = Filename.find('/'); if (SlashPos == StringRef::npos) return nullptr; // Find out if this is the home for the specified framework, by checking // HeaderSearch. Possible answers are yes/no and unknown. HeaderSearch::FrameworkCacheEntry &CacheEntry = HS.LookupFrameworkCache(Filename.substr(0, SlashPos)); // If it is known and in some other directory, fail. if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDir()) return nullptr; // Otherwise, construct the path to this framework dir. // FrameworkName = "/System/Library/Frameworks/" SmallString<1024> FrameworkName; FrameworkName += getFrameworkDir()->getName(); if (FrameworkName.empty() || FrameworkName.back() != '/') FrameworkName.push_back('/'); // FrameworkName = "/System/Library/Frameworks/Cocoa" StringRef ModuleName(Filename.begin(), SlashPos); FrameworkName += ModuleName; // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/" FrameworkName += ".framework/"; // If the cache entry was unresolved, populate it now. if (!CacheEntry.Directory) { HS.IncrementFrameworkLookupCount(); // If the framework dir doesn't exist, we fail. const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str()); if (!Dir) return nullptr; // Otherwise, if it does, remember that this is the right direntry for this // framework. CacheEntry.Directory = getFrameworkDir(); // If this is a user search directory, check if the framework has been // user-specified as a system framework. if (getDirCharacteristic() == SrcMgr::C_User) { SmallString<1024> SystemFrameworkMarker(FrameworkName); SystemFrameworkMarker += ".system_framework"; if (llvm::sys::fs::exists(SystemFrameworkMarker.str())) { CacheEntry.IsUserSpecifiedSystemFramework = true; } } } // Set the 'user-specified system framework' flag. InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework; if (RelativePath) { RelativePath->clear(); RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); } // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h" unsigned OrigSize = FrameworkName.size(); FrameworkName += "Headers/"; if (SearchPath) { SearchPath->clear(); // Without trailing '/'. SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1); } FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); const FileEntry *FE = FileMgr.getFile(FrameworkName.str(), /*openFile=*/!SuggestedModule); if (!FE) { // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h" const char *Private = "Private"; FrameworkName.insert(FrameworkName.begin()+OrigSize, Private, Private+strlen(Private)); if (SearchPath) SearchPath->insert(SearchPath->begin()+OrigSize, Private, Private+strlen(Private)); FE = FileMgr.getFile(FrameworkName.str(), /*openFile=*/!SuggestedModule); } // If we found the header and are allowed to suggest a module, do so now. if (FE && SuggestedModule) { // Find the framework in which this header occurs. StringRef FrameworkPath = FE->getDir()->getName(); bool FoundFramework = false; do { // Determine whether this directory exists. const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkPath); if (!Dir) break; // If this is a framework directory, then we're a subframework of this // framework. if (llvm::sys::path::extension(FrameworkPath) == ".framework") { FoundFramework = true; break; } // Get the parent directory name. FrameworkPath = llvm::sys::path::parent_path(FrameworkPath); if (FrameworkPath.empty()) break; } while (true); if (FoundFramework) { // Find the top-level framework based on this framework. SmallVector<std::string, 4> SubmodulePath; const DirectoryEntry *TopFrameworkDir = ::getTopFrameworkDir(FileMgr, FrameworkPath, SubmodulePath); // Determine the name of the top-level framework. StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName()); // Load this framework module. If that succeeds, find the suggested module // for this header, if any. bool IsSystem = getDirCharacteristic() != SrcMgr::C_User; if (HS.loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystem)) { *SuggestedModule = HS.findModuleForHeader(FE); } } else { *SuggestedModule = HS.findModuleForHeader(FE); } } return FE; }
/// DoFrameworkLookup - Do a lookup of the specified file in the current /// DirectoryLookup, which is a framework directory. const FileEntry *DirectoryLookup::DoFrameworkLookup( StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, Module **SuggestedModule, bool &InUserSpecifiedSystemFramework) const { FileManager &FileMgr = HS.getFileMgr(); // Framework names must have a '/' in the filename. size_t SlashPos = Filename.find('/'); if (SlashPos == StringRef::npos) return 0; // Find out if this is the home for the specified framework, by checking // HeaderSearch. Possible answers are yes/no and unknown. HeaderSearch::FrameworkCacheEntry &CacheEntry = HS.LookupFrameworkCache(Filename.substr(0, SlashPos)); // If it is known and in some other directory, fail. if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDir()) return 0; // Otherwise, construct the path to this framework dir. // FrameworkName = "/System/Library/Frameworks/" SmallString<1024> FrameworkName; FrameworkName += getFrameworkDir()->getName(); if (FrameworkName.empty() || FrameworkName.back() != '/') FrameworkName.push_back('/'); // FrameworkName = "/System/Library/Frameworks/Cocoa" StringRef ModuleName(Filename.begin(), SlashPos); FrameworkName += ModuleName; // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/" FrameworkName += ".framework/"; // If the cache entry was unresolved, populate it now. if (CacheEntry.Directory == 0) { HS.IncrementFrameworkLookupCount(); // If the framework dir doesn't exist, we fail. const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str()); if (Dir == 0) return 0; // Otherwise, if it does, remember that this is the right direntry for this // framework. CacheEntry.Directory = getFrameworkDir(); // If this is a user search directory, check if the framework has been // user-specified as a system framework. if (getDirCharacteristic() == SrcMgr::C_User) { SmallString<1024> SystemFrameworkMarker(FrameworkName); SystemFrameworkMarker += ".system_framework"; if (llvm::sys::fs::exists(SystemFrameworkMarker.str())) { CacheEntry.IsUserSpecifiedSystemFramework = true; } } } // Set the 'user-specified system framework' flag. InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework; if (RelativePath != NULL) { RelativePath->clear(); RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); } // If we're allowed to look for modules, try to load or create the module // corresponding to this framework. Module *Module = 0; if (SuggestedModule) { if (const DirectoryEntry *FrameworkDir = FileMgr.getDirectory(FrameworkName)) { bool IsSystem = getDirCharacteristic() != SrcMgr::C_User; Module = HS.loadFrameworkModule(ModuleName, FrameworkDir, IsSystem); } } // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h" unsigned OrigSize = FrameworkName.size(); FrameworkName += "Headers/"; if (SearchPath != NULL) { SearchPath->clear(); // Without trailing '/'. SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1); } // Determine whether this is the module we're building or not. bool AutomaticImport = Module; FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str(), /*openFile=*/!AutomaticImport)) { if (AutomaticImport) *SuggestedModule = HS.findModuleForHeader(FE); return FE; } // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h" const char *Private = "Private"; FrameworkName.insert(FrameworkName.begin()+OrigSize, Private, Private+strlen(Private)); if (SearchPath != NULL) SearchPath->insert(SearchPath->begin()+OrigSize, Private, Private+strlen(Private)); const FileEntry *FE = FileMgr.getFile(FrameworkName.str(), /*openFile=*/!AutomaticImport); if (FE && AutomaticImport) *SuggestedModule = HS.findModuleForHeader(FE); return FE; }
std::string Twine::str() const { SmallString<256> Vec; toVector(Vec); return std::string(Vec.begin(), Vec.end()); }
/// printSymbolOperand - Print a raw symbol reference operand. This handles /// jump tables, constant pools, global address and external symbols, all of /// which print to a label with various suffixes for relocation types etc. void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO, raw_ostream &O) { switch (MO.getType()) { default: llvm_unreachable("unknown symbol type!"); case MachineOperand::MO_JumpTableIndex: O << *GetJTISymbol(MO.getIndex()); break; case MachineOperand::MO_ConstantPoolIndex: O << *GetCPISymbol(MO.getIndex()); printOffset(MO.getOffset(), O); break; case MachineOperand::MO_GlobalAddress: { const GlobalValue *GV = MO.getGlobal(); MCSymbol *GVSym; if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) GVSym = GetSymbolWithGlobalValueBase(GV, "$stub"); else if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE || MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE) GVSym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); else GVSym = Mang->getSymbol(GV); // Handle dllimport linkage. if (MO.getTargetFlags() == X86II::MO_DLLIMPORT) GVSym = OutContext.GetOrCreateSymbol(Twine("__imp_") + GVSym->getName()); if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE) { MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); MachineModuleInfoImpl::StubValueTy &StubSym = MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(Sym); if (StubSym.getPointer() == 0) StubSym = MachineModuleInfoImpl:: StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); } else if (MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE){ MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); MachineModuleInfoImpl::StubValueTy &StubSym = MMI->getObjFileInfo<MachineModuleInfoMachO>().getHiddenGVStubEntry(Sym); if (StubSym.getPointer() == 0) StubSym = MachineModuleInfoImpl:: StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); } else if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) { MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$stub"); MachineModuleInfoImpl::StubValueTy &StubSym = MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym); if (StubSym.getPointer() == 0) StubSym = MachineModuleInfoImpl:: StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); } // If the name begins with a dollar-sign, enclose it in parens. We do this // to avoid having it look like an integer immediate to the assembler. if (GVSym->getName()[0] != '$') O << *GVSym; else O << '(' << *GVSym << ')'; printOffset(MO.getOffset(), O); break; } case MachineOperand::MO_ExternalSymbol: { const MCSymbol *SymToPrint; if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) { SmallString<128> TempNameStr; TempNameStr += StringRef(MO.getSymbolName()); TempNameStr += StringRef("$stub"); MCSymbol *Sym = GetExternalSymbolSymbol(TempNameStr.str()); MachineModuleInfoImpl::StubValueTy &StubSym = MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym); if (StubSym.getPointer() == 0) { TempNameStr.erase(TempNameStr.end()-5, TempNameStr.end()); StubSym = MachineModuleInfoImpl:: StubValueTy(OutContext.GetOrCreateSymbol(TempNameStr.str()), true); } SymToPrint = StubSym.getPointer(); } else { SymToPrint = GetExternalSymbolSymbol(MO.getSymbolName()); } // If the name begins with a dollar-sign, enclose it in parens. We do this // to avoid having it look like an integer immediate to the assembler. if (SymToPrint->getName()[0] != '$') O << *SymToPrint; else O << '(' << *SymToPrint << '('; break; } } switch (MO.getTargetFlags()) { default: llvm_unreachable("Unknown target flag on GV operand"); case X86II::MO_NO_FLAG: // No flag. break; case X86II::MO_DARWIN_NONLAZY: case X86II::MO_DLLIMPORT: case X86II::MO_DARWIN_STUB: // These affect the name of the symbol, not any suffix. break; case X86II::MO_GOT_ABSOLUTE_ADDRESS: O << " + [.-" << *MF->getPICBaseSymbol() << ']'; break; case X86II::MO_PIC_BASE_OFFSET: case X86II::MO_DARWIN_NONLAZY_PIC_BASE: case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: O << '-' << *MF->getPICBaseSymbol(); break; case X86II::MO_TLSGD: O << "@TLSGD"; break; case X86II::MO_TLSLD: O << "@TLSLD"; break; case X86II::MO_TLSLDM: O << "@TLSLDM"; break; case X86II::MO_GOTTPOFF: O << "@GOTTPOFF"; break; case X86II::MO_INDNTPOFF: O << "@INDNTPOFF"; break; case X86II::MO_TPOFF: O << "@TPOFF"; break; case X86II::MO_DTPOFF: O << "@DTPOFF"; break; case X86II::MO_NTPOFF: O << "@NTPOFF"; break; case X86II::MO_GOTNTPOFF: O << "@GOTNTPOFF"; break; case X86II::MO_GOTPCREL: O << "@GOTPCREL"; break; case X86II::MO_GOT: O << "@GOT"; break; case X86II::MO_GOTOFF: O << "@GOTOFF"; break; case X86II::MO_PLT: O << "@PLT"; break; case X86II::MO_TLVP: O << "@TLVP"; break; case X86II::MO_TLVP_PIC_BASE: O << "@TLVP" << '-' << *MF->getPICBaseSymbol(); break; case X86II::MO_SECREL: O << "@SECREL"; break; } }
/// GetSymbolFromOperand - Lower an MO_GlobalAddress or MO_ExternalSymbol /// operand to an MCSymbol. MCSymbol *X86MCInstLower:: GetSymbolFromOperand(const MachineOperand &MO) const { assert((MO.isGlobal() || MO.isSymbol()) && "Isn't a symbol reference"); SmallString<128> Name; if (!MO.isGlobal()) { assert(MO.isSymbol()); Name += MAI.getGlobalPrefix(); Name += MO.getSymbolName(); } else { const GlobalValue *GV = MO.getGlobal(); bool isImplicitlyPrivate = false; if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB || MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE || MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE) isImplicitlyPrivate = true; Mang->getNameWithPrefix(Name, GV, isImplicitlyPrivate); } // If the target flags on the operand changes the name of the symbol, do that // before we return the symbol. switch (MO.getTargetFlags()) { default: break; case X86II::MO_DLLIMPORT: { // Handle dllimport linkage. const char *Prefix = "__imp_"; Name.insert(Name.begin(), Prefix, Prefix+strlen(Prefix)); break; } case X86II::MO_DARWIN_NONLAZY: case X86II::MO_DARWIN_NONLAZY_PIC_BASE: { Name += "$non_lazy_ptr"; MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); MachineModuleInfoImpl::StubValueTy &StubSym = getMachOMMI().getGVStubEntry(Sym); if (StubSym.getPointer() == 0) { assert(MO.isGlobal() && "Extern symbol not handled yet"); StubSym = MachineModuleInfoImpl:: StubValueTy(Mang->getSymbol(MO.getGlobal()), !MO.getGlobal()->hasInternalLinkage()); } return Sym; } case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: { Name += "$non_lazy_ptr"; MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); MachineModuleInfoImpl::StubValueTy &StubSym = getMachOMMI().getHiddenGVStubEntry(Sym); if (StubSym.getPointer() == 0) { assert(MO.isGlobal() && "Extern symbol not handled yet"); StubSym = MachineModuleInfoImpl:: StubValueTy(Mang->getSymbol(MO.getGlobal()), !MO.getGlobal()->hasInternalLinkage()); } return Sym; } case X86II::MO_DARWIN_STUB: { Name += "$stub"; MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); MachineModuleInfoImpl::StubValueTy &StubSym = getMachOMMI().getFnStubEntry(Sym); if (StubSym.getPointer()) return Sym; if (MO.isGlobal()) { StubSym = MachineModuleInfoImpl:: StubValueTy(Mang->getSymbol(MO.getGlobal()), !MO.getGlobal()->hasInternalLinkage()); } else { Name.erase(Name.end()-5, Name.end()); StubSym = MachineModuleInfoImpl:: StubValueTy(Ctx.GetOrCreateSymbol(Name.str()), false); } return Sym; } } return Ctx.GetOrCreateSymbol(Name.str()); }
static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, AsmPrinter &AP){ MCContext &Ctx = AP.OutContext; SmallString<128> Name; if (!MO.isGlobal()) { assert(MO.isSymbol() && "Isn't a symbol reference"); Name += AP.MAI->getGlobalPrefix(); Name += MO.getSymbolName(); } else { const GlobalValue *GV = MO.getGlobal(); bool isImplicitlyPrivate = false; if (MO.getTargetFlags() == PPCII::MO_DARWIN_STUB || (MO.getTargetFlags() & PPCII::MO_NLP_FLAG)) isImplicitlyPrivate = true; AP.Mang->getNameWithPrefix(Name, GV, isImplicitlyPrivate); } // If the target flags on the operand changes the name of the symbol, do that // before we return the symbol. if (MO.getTargetFlags() == PPCII::MO_DARWIN_STUB) { Name += "$stub"; const char *PGP = AP.MAI->getPrivateGlobalPrefix(); const char *Prefix = ""; if (!Name.startswith(PGP)) { // http://llvm.org/bugs/show_bug.cgi?id=15763 // all stubs and lazy_ptrs should be local symbols, which need leading 'L' Prefix = PGP; } MCSymbol *Sym = Ctx.GetOrCreateSymbol(Twine(Prefix) + Twine(Name)); MachineModuleInfoImpl::StubValueTy &StubSym = getMachOMMI(AP).getFnStubEntry(Sym); if (StubSym.getPointer()) return Sym; if (MO.isGlobal()) { StubSym = MachineModuleInfoImpl:: StubValueTy(AP.Mang->getSymbol(MO.getGlobal()), !MO.getGlobal()->hasInternalLinkage()); } else { Name.erase(Name.end()-5, Name.end()); StubSym = MachineModuleInfoImpl:: StubValueTy(Ctx.GetOrCreateSymbol(Name.str()), false); } return Sym; } // If the symbol reference is actually to a non_lazy_ptr, not to the symbol, // then add the suffix. if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG) { Name += "$non_lazy_ptr"; MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); MachineModuleInfoMachO &MachO = getMachOMMI(AP); MachineModuleInfoImpl::StubValueTy &StubSym = (MO.getTargetFlags() & PPCII::MO_NLP_HIDDEN_FLAG) ? MachO.getHiddenGVStubEntry(Sym) : MachO.getGVStubEntry(Sym); if (StubSym.getPointer() == 0) { assert(MO.isGlobal() && "Extern symbol not handled yet"); StubSym = MachineModuleInfoImpl:: StubValueTy(AP.Mang->getSymbol(MO.getGlobal()), !MO.getGlobal()->hasInternalLinkage()); } return Sym; } return Ctx.GetOrCreateSymbol(Name.str()); }