/// 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(); }
// Convert a path into the canonical form. // Canonical form is either "/", or "/segment" * N: // C:\foo\bar --> /c:/foo/bar // /foo/ --> /foo // a/b/c --> /a/b/c static SmallString<128> canonicalize(StringRef Path) { SmallString<128> Result = Path.rtrim('/'); native(Result, sys::path::Style::posix); if (Result.empty() || Result.front() != '/') Result.insert(Result.begin(), '/'); return Result; }
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()); }
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; }
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()); }
/// 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; } } }
std::string Twine::str() const { SmallString<256> Vec; toVector(Vec); return std::string(Vec.begin(), Vec.end()); }
void SwiftLangSupport::findInterfaceDocument(StringRef ModuleName, ArrayRef<const char *> Args, std::function<void(const InterfaceDocInfo &)> Receiver) { InterfaceDocInfo Info; CompilerInstance CI; // Display diagnostics to stderr. PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); CompilerInvocation Invocation; std::string Error; if (getASTManager().initCompilerInvocation(Invocation, Args, CI.getDiags(), StringRef(), Error)) { Info.Error = Error; return Receiver(Info); } if (auto IFaceGenRef = IFaceGenContexts.find(ModuleName, Invocation)) Info.ModuleInterfaceName = IFaceGenRef->getDocumentName(); SmallString<128> Buf; SmallVector<std::pair<unsigned, unsigned>, 16> ArgOffs; auto addArgPair = [&](StringRef Arg, StringRef Val) { assert(!Arg.empty()); if (Val.empty()) return; unsigned ArgBegin = Buf.size(); Buf += Arg; unsigned ArgEnd = Buf.size(); unsigned ValBegin = Buf.size(); Buf += Val; unsigned ValEnd = Buf.size(); ArgOffs.push_back(std::make_pair(ArgBegin, ArgEnd)); ArgOffs.push_back(std::make_pair(ValBegin, ValEnd)); }; auto addSingleArg = [&](StringRef Arg) { assert(!Arg.empty()); unsigned ArgBegin = Buf.size(); Buf += Arg; unsigned ArgEnd = Buf.size(); ArgOffs.push_back(std::make_pair(ArgBegin, ArgEnd)); }; addArgPair("-target", Invocation.getTargetTriple()); const auto &SPOpts = Invocation.getSearchPathOptions(); addArgPair("-sdk", SPOpts.SDKPath); for (auto &Path : SPOpts.FrameworkSearchPaths) addArgPair("-F", Path); for (auto &Path : SPOpts.ImportSearchPaths) addArgPair("-I", Path); const auto &ClangOpts = Invocation.getClangImporterOptions(); addArgPair("-module-cache-path", ClangOpts.ModuleCachePath); for (auto &ExtraArg : ClangOpts.ExtraArgs) addArgPair("-Xcc", ExtraArg); if (Invocation.getFrontendOptions().ImportUnderlyingModule) addSingleArg("-import-underlying-module"); addArgPair("-import-objc-header", Invocation.getFrontendOptions().ImplicitObjCHeaderPath); SmallVector<StringRef, 16> NewArgs; for (auto Pair : ArgOffs) { NewArgs.push_back(StringRef(Buf.begin()+Pair.first, Pair.second-Pair.first)); } Info.CompilerArgs = NewArgs; return Receiver(Info); }
/// Returns true for failure to resolve. static bool passCursorInfoForDecl(const ValueDecl *VD, const Module *MainModule, const Type Ty, bool IsRef, Optional<unsigned> OrigBufferID, SwiftLangSupport &Lang, const CompilerInvocation &Invok, ArrayRef<ImmutableTextSnapshotRef> PreviousASTSnaps, std::function<void(const CursorInfo &)> Receiver) { if (AvailableAttr::isUnavailable(VD)) return true; SmallString<64> SS; auto BaseType = findBaseTypeForReplacingArchetype(VD, Ty); unsigned NameBegin = SS.size(); { llvm::raw_svector_ostream OS(SS); SwiftLangSupport::printDisplayName(VD, OS); } unsigned NameEnd = SS.size(); unsigned USRBegin = SS.size(); { llvm::raw_svector_ostream OS(SS); SwiftLangSupport::printUSR(VD, OS); } unsigned USREnd = SS.size(); unsigned TypenameBegin = SS.size(); if (VD->hasType()) { llvm::raw_svector_ostream OS(SS); VD->getType().print(OS); } unsigned TypenameEnd = SS.size(); unsigned DocCommentBegin = SS.size(); { llvm::raw_svector_ostream OS(SS); ide::getDocumentationCommentAsXML(VD, OS); } unsigned DocCommentEnd = SS.size(); unsigned DeclBegin = SS.size(); { llvm::raw_svector_ostream OS(SS); printAnnotatedDeclaration(VD, Ty, BaseType, OS); } unsigned DeclEnd = SS.size(); SmallVector<std::pair<unsigned, unsigned>, 4> OverUSROffs; ide::walkOverriddenDecls(VD, [&](llvm::PointerUnion<const ValueDecl*, const clang::NamedDecl*> D) { unsigned OverUSRBegin = SS.size(); { llvm::raw_svector_ostream OS(SS); if (auto VD = D.dyn_cast<const ValueDecl*>()) { if (SwiftLangSupport::printUSR(VD, OS)) return; } else { llvm::SmallString<128> Buf; if (clang::index::generateUSRForDecl( D.get<const clang::NamedDecl*>(), Buf)) return; OS << Buf.str(); } } unsigned OverUSREnd = SS.size(); OverUSROffs.push_back(std::make_pair(OverUSRBegin, OverUSREnd)); }); SmallVector<std::pair<unsigned, unsigned>, 4> RelDeclOffs; walkRelatedDecls(VD, [&](const ValueDecl *RelatedDecl, bool DuplicateName) { unsigned RelatedDeclBegin = SS.size(); { llvm::raw_svector_ostream OS(SS); OS<<"<RelatedName usr=\""; SwiftLangSupport::printUSR(RelatedDecl, OS); OS<<"\">"; if (isa<AbstractFunctionDecl>(RelatedDecl) && DuplicateName) { // Related decls are generally overloads, so print parameter types to // differentiate them. PrintOptions PO; PO.SkipAttributes = true; PO.SkipIntroducerKeywords = true; PO.ArgAndParamPrinting = PrintOptions::ArgAndParamPrintingMode::ArgumentOnly; XMLEscapingPrinter Printer(OS); if (BaseType) PO.setArchetypeTransform(BaseType, VD->getDeclContext()); RelatedDecl->print(Printer, PO); } else { llvm::SmallString<128> Buf; { llvm::raw_svector_ostream OSBuf(Buf); SwiftLangSupport::printDisplayName(RelatedDecl, OSBuf); } llvm::markup::appendWithXMLEscaping(OS, Buf); } OS<<"</RelatedName>"; } unsigned RelatedDeclEnd = SS.size(); RelDeclOffs.push_back(std::make_pair(RelatedDeclBegin, RelatedDeclEnd)); }); ASTContext &Ctx = VD->getASTContext(); ClangImporter *Importer = static_cast<ClangImporter*>( Ctx.getClangModuleLoader()); std::string ModuleName; auto ClangNode = VD->getClangNode(); if (ClangNode) { auto ClangMod = Importer->getClangOwningModule(ClangNode); ModuleName = ClangMod->getFullModuleName(); } else if (VD->getLoc().isInvalid() && VD->getModuleContext() != MainModule) { ModuleName = VD->getModuleContext()->getName().str(); } StringRef ModuleInterfaceName; if (auto IFaceGenRef = Lang.getIFaceGenContexts().find(ModuleName, Invok)) ModuleInterfaceName = IFaceGenRef->getDocumentName(); UIdent Kind = SwiftLangSupport::getUIDForDecl(VD, IsRef); StringRef Name = StringRef(SS.begin()+NameBegin, NameEnd-NameBegin); StringRef USR = StringRef(SS.begin()+USRBegin, USREnd-USRBegin); StringRef TypeName = StringRef(SS.begin()+TypenameBegin, TypenameEnd-TypenameBegin); StringRef DocComment = StringRef(SS.begin()+DocCommentBegin, DocCommentEnd-DocCommentBegin); StringRef AnnotatedDecl = StringRef(SS.begin()+DeclBegin, DeclEnd-DeclBegin); llvm::Optional<std::pair<unsigned, unsigned>> DeclarationLoc; StringRef Filename; getLocationInfo(VD, DeclarationLoc, Filename); if (DeclarationLoc.hasValue()) { DeclarationLoc = tryRemappingLocToLatestSnapshot(Lang, *DeclarationLoc, Filename, PreviousASTSnaps); if (!DeclarationLoc.hasValue()) return true; // failed to remap. } SmallVector<StringRef, 4> OverUSRs; for (auto Offs : OverUSROffs) { OverUSRs.push_back(StringRef(SS.begin()+Offs.first, Offs.second-Offs.first)); } SmallVector<StringRef, 4> AnnotatedRelatedDecls; for (auto Offs : RelDeclOffs) { AnnotatedRelatedDecls.push_back(StringRef(SS.begin() + Offs.first, Offs.second - Offs.first)); } bool IsSystem = VD->getModuleContext()->isSystemModule(); std::string TypeInterface; CursorInfo Info; Info.Kind = Kind; Info.Name = Name; Info.USR = USR; Info.TypeName = TypeName; Info.DocComment = DocComment; Info.AnnotatedDeclaration = AnnotatedDecl; Info.ModuleName = ModuleName; Info.ModuleInterfaceName = ModuleInterfaceName; Info.DeclarationLoc = DeclarationLoc; Info.Filename = Filename; Info.OverrideUSRs = OverUSRs; Info.AnnotatedRelatedDeclarations = AnnotatedRelatedDecls; Info.IsSystem = IsSystem; Info.TypeInterface = ASTPrinter::printTypeInterface(Ty, VD->getDeclContext(), TypeInterface) ? StringRef(TypeInterface) : StringRef(); Receiver(Info); return false; }
/// 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; }
/// 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()); }
/// 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; }
/// parseTypeIdentifierOrTypeComposition /// - Identifiers and compositions both start with the same identifier /// token, parse it and continue constructing a composition if the /// next token is '&' /// /// type-composition: /// type-identifier ('&' type-identifier)* /// 'protocol' '<' type-composition-list-deprecated? '>' /// /// type-composition-list-deprecated: /// type-identifier (',' type-identifier)* ParserResult<TypeRepr> Parser::parseTypeIdentifierOrTypeComposition() { // Handle deprecated case if (Tok.getKind() == tok::kw_protocol && startsWithLess(peekToken())) { SourceLoc ProtocolLoc = consumeToken(tok::kw_protocol); SourceLoc LAngleLoc = consumeStartingLess(); // Parse the type-composition-list. ParserStatus Status; SmallVector<IdentTypeRepr *, 4> Protocols; bool IsEmpty = startsWithGreater(Tok); if (!IsEmpty) { do { // Parse the type-identifier. ParserResult<TypeRepr> Protocol = parseTypeIdentifier(); Status |= Protocol; if (auto *ident = dyn_cast_or_null<IdentTypeRepr>( Protocol.getPtrOrNull())) Protocols.push_back(ident); } while (consumeIf(tok::comma)); } // Check for the terminating '>'. SourceLoc RAngleLoc = PreviousLoc; if (startsWithGreater(Tok)) { RAngleLoc = consumeStartingGreater(); } else { if (Status.isSuccess()) { diagnose(Tok, diag::expected_rangle_protocol); diagnose(LAngleLoc, diag::opening_angle); Status.setIsParseError(); } // Skip until we hit the '>'. RAngleLoc = skipUntilGreaterInTypeList(/*protocolComposition=*/true); } auto composition = ProtocolCompositionTypeRepr::create( Context, Protocols, ProtocolLoc, {LAngleLoc, RAngleLoc}); if (Status.isSuccess()) { // Only if we have complete protocol<...> construct, diagnose deprecated. SmallString<32> replacement; if (Protocols.empty()) { replacement = "Any"; } else { auto extractText = [&](IdentTypeRepr *Ty) -> StringRef { auto SourceRange = Ty->getSourceRange(); return SourceMgr.extractText( Lexer::getCharSourceRangeFromSourceRange(SourceMgr, SourceRange)); }; auto Begin = Protocols.begin(); replacement += extractText(*Begin); while (++Begin != Protocols.end()) { replacement += " & "; replacement += extractText(*Begin); } } // Copy trailing content after '>' to the replacement string. // FIXME: lexer should smartly separate '>' and trailing contents like '?'. StringRef TrailingContent = L->getTokenAt(RAngleLoc).getRange().str(). substr(1); if (!TrailingContent.empty()) { if (Protocols.size() > 1) { replacement.insert(replacement.begin(), '('); replacement += ")"; } replacement += TrailingContent; } // Replace 'protocol<T1, T2>' with 'T1 & T2' diagnose(ProtocolLoc, IsEmpty ? diag::deprecated_any_composition : Protocols.size() > 1 ? diag::deprecated_protocol_composition : diag::deprecated_protocol_composition_single) .highlight(composition->getSourceRange()) .fixItReplace(composition->getSourceRange(), replacement); } return makeParserResult(Status, composition); } SourceLoc FirstTypeLoc = Tok.getLoc(); // Parse the first type ParserResult<TypeRepr> FirstType = parseTypeIdentifier(); if (!Tok.isContextualPunctuator("&")) return FirstType; SmallVector<IdentTypeRepr *, 4> Protocols; ParserStatus Status; // If it is not 'Any', add it to the protocol list if (auto *ident = dyn_cast_or_null<IdentTypeRepr>(FirstType.getPtrOrNull())) Protocols.push_back(ident); Status |= FirstType; auto FirstAmpersandLoc = Tok.getLoc(); while (Tok.isContextualPunctuator("&")) { consumeToken(); // consume '&' ParserResult<TypeRepr> Protocol = parseTypeIdentifier(); Status |= Protocol; if (auto *ident = dyn_cast_or_null<IdentTypeRepr>(Protocol.getPtrOrNull())) Protocols.push_back(ident); }; return makeParserResult(Status, ProtocolCompositionTypeRepr::create( Context, Protocols, FirstTypeLoc, {FirstAmpersandLoc, PreviousLoc})); }