1 //===--- CrossTranslationUnit.h - -------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file provides an interface to load binary AST dumps on demand. This 11 // feature can be utilized for tools that require cross translation unit 12 // support. 13 // 14 //===----------------------------------------------------------------------===// 15 #ifndef LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H 16 #define LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H 17 18 #include "clang/AST/ASTImporterLookupTable.h" 19 #include "clang/Basic/LLVM.h" 20 #include "llvm/ADT/DenseMap.h" 21 #include "llvm/ADT/SmallPtrSet.h" 22 #include "llvm/ADT/StringMap.h" 23 #include "llvm/Support/Error.h" 24 25 namespace clang { 26 class CompilerInstance; 27 class ASTContext; 28 class ASTImporter; 29 class ASTUnit; 30 class DeclContext; 31 class FunctionDecl; 32 class NamedDecl; 33 class TranslationUnitDecl; 34 35 namespace cross_tu { 36 37 enum class index_error_code { 38 unspecified = 1, 39 missing_index_file, 40 invalid_index_format, 41 multiple_definitions, 42 missing_definition, 43 failed_import, 44 failed_to_get_external_ast, 45 failed_to_generate_usr, 46 triple_mismatch, 47 lang_mismatch 48 }; 49 50 class IndexError : public llvm::ErrorInfo<IndexError> { 51 public: 52 static char ID; IndexError(index_error_code C)53 IndexError(index_error_code C) : Code(C), LineNo(0) {} 54 IndexError(index_error_code C, std::string FileName, int LineNo = 0) Code(C)55 : Code(C), FileName(std::move(FileName)), LineNo(LineNo) {} IndexError(index_error_code C,std::string FileName,std::string TripleToName,std::string TripleFromName)56 IndexError(index_error_code C, std::string FileName, std::string TripleToName, 57 std::string TripleFromName) 58 : Code(C), FileName(std::move(FileName)), 59 TripleToName(std::move(TripleToName)), 60 TripleFromName(std::move(TripleFromName)) {} 61 void log(raw_ostream &OS) const override; 62 std::error_code convertToErrorCode() const override; getCode()63 index_error_code getCode() const { return Code; } getLineNum()64 int getLineNum() const { return LineNo; } getFileName()65 std::string getFileName() const { return FileName; } getTripleToName()66 std::string getTripleToName() const { return TripleToName; } getTripleFromName()67 std::string getTripleFromName() const { return TripleFromName; } 68 69 private: 70 index_error_code Code; 71 std::string FileName; 72 int LineNo; 73 std::string TripleToName; 74 std::string TripleFromName; 75 }; 76 77 /// This function parses an index file that determines which 78 /// translation unit contains which definition. 79 /// 80 /// The index file format is the following: 81 /// each line consists of an USR and a filepath separated by a space. 82 /// 83 /// \return Returns a map where the USR is the key and the filepath is the value 84 /// or an error. 85 llvm::Expected<llvm::StringMap<std::string>> 86 parseCrossTUIndex(StringRef IndexPath, StringRef CrossTUDir); 87 88 std::string createCrossTUIndexString(const llvm::StringMap<std::string> &Index); 89 90 /// This class is used for tools that requires cross translation 91 /// unit capability. 92 /// 93 /// This class can load definitions from external AST files. 94 /// The loaded definition will be merged back to the original AST using the 95 /// AST Importer. 96 /// In order to use this class, an index file is required that describes 97 /// the locations of the AST files for each definition. 98 /// 99 /// Note that this class also implements caching. 100 class CrossTranslationUnitContext { 101 public: 102 CrossTranslationUnitContext(CompilerInstance &CI); 103 ~CrossTranslationUnitContext(); 104 105 /// This function loads a function definition from an external AST 106 /// file and merge it into the original AST. 107 /// 108 /// This method should only be used on functions that have no definitions in 109 /// the current translation unit. A function definition with the same 110 /// declaration will be looked up in the index file which should be in the 111 /// \p CrossTUDir directory, called \p IndexName. In case the declaration is 112 /// found in the index the corresponding AST file will be loaded and the 113 /// definition of the function will be merged into the original AST using 114 /// the AST Importer. 115 /// 116 /// \return The declaration with the definition will be returned. 117 /// If no suitable definition is found in the index file or multiple 118 /// definitions found error will be returned. 119 /// 120 /// Note that the AST files should also be in the \p CrossTUDir. 121 llvm::Expected<const FunctionDecl *> 122 getCrossTUDefinition(const FunctionDecl *FD, StringRef CrossTUDir, 123 StringRef IndexName, bool DisplayCTUProgress = false); 124 125 /// This function loads a function definition from an external AST 126 /// file. 127 /// 128 /// A function definition with the same declaration will be looked up in the 129 /// index file which should be in the \p CrossTUDir directory, called 130 /// \p IndexName. In case the declaration is found in the index the 131 /// corresponding AST file will be loaded. 132 /// 133 /// \return Returns a pointer to the ASTUnit that contains the definition of 134 /// the looked up function or an Error. 135 /// The returned pointer is never a nullptr. 136 /// 137 /// Note that the AST files should also be in the \p CrossTUDir. 138 llvm::Expected<ASTUnit *> loadExternalAST(StringRef LookupName, 139 StringRef CrossTUDir, 140 StringRef IndexName, 141 bool DisplayCTUProgress = false); 142 143 /// This function merges a definition from a separate AST Unit into 144 /// the current one which was created by the compiler instance that 145 /// was passed to the constructor. 146 /// 147 /// \return Returns the resulting definition or an error. 148 llvm::Expected<const FunctionDecl *> importDefinition(const FunctionDecl *FD); 149 150 /// Get a name to identify a function. 151 static std::string getLookupName(const NamedDecl *ND); 152 153 /// Emit diagnostics for the user for potential configuration errors. 154 void emitCrossTUDiagnostics(const IndexError &IE); 155 156 private: 157 void lazyInitLookupTable(TranslationUnitDecl *ToTU); 158 ASTImporter &getOrCreateASTImporter(ASTContext &From); 159 const FunctionDecl *findFunctionInDeclContext(const DeclContext *DC, 160 StringRef LookupFnName); 161 162 llvm::StringMap<std::unique_ptr<clang::ASTUnit>> FileASTUnitMap; 163 llvm::StringMap<clang::ASTUnit *> FunctionASTUnitMap; 164 llvm::StringMap<std::string> FunctionFileMap; 165 llvm::DenseMap<TranslationUnitDecl *, std::unique_ptr<ASTImporter>> 166 ASTUnitImporterMap; 167 CompilerInstance &CI; 168 ASTContext &Context; 169 std::unique_ptr<ASTImporterLookupTable> LookupTable; 170 }; 171 172 } // namespace cross_tu 173 } // namespace clang 174 175 #endif // LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H 176