20 #include "TClingUtils.h"
22 #include "clang/Frontend/FrontendDiagnostic.h"
23 #include "clang/Lex/HeaderSearchOptions.h"
24 #include "clang/Lex/Preprocessor.h"
25 #include "clang/Sema/Sema.h"
26 #include "clang/Serialization/ASTReader.h"
27 #include "clang/Serialization/Module.h"
29 #include "llvm/ADT/Hashing.h"
30 #include "llvm/Bitcode/BitstreamWriter.h"
31 #include "llvm/Support/FileSystem.h"
32 #include "llvm/Support/MemoryBuffer.h"
33 #include "llvm/Support/Path.h"
34 #include "llvm/Support/raw_ostream.h"
37 const std::string ROOT_CLING_RDICT_BLOCK_NAME =
"root.cling.rdict";
40 constexpr uint16_t ROOT_CLING_RDICT_VERSION_MAJOR = 1;
45 constexpr uint16_t ROOT_CLING_RDICT_VERSION_MINOR = 1;
48 TClingRdictModuleFileExtension::Writer::~Writer() {}
50 void TClingRdictModuleFileExtension::Writer::writeExtensionContents(clang::Sema &SemaRef, llvm::BitstreamWriter &Stream)
53 const clang::LangOptions &Opts = SemaRef.getLangOpts();
54 const clang::Preprocessor &PP = SemaRef.getPreprocessor();
56 llvm::StringRef CachePath = PP.getHeaderSearchInfo().getHeaderSearchOpts().ModuleCachePath;
57 std::string RdictsStart =
"lib" + Opts.CurrentModule +
"_";
58 const std::string RdictsEnd =
"_rdict.pcm";
61 using namespace clang;
62 using namespace clang::serialization;
64 auto Abv = std::make_shared<BitCodeAbbrev>();
65 Abv->Add(BitCodeAbbrevOp(FIRST_EXTENSION_RECORD_ID));
66 Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
67 auto Abbrev = Stream.EmitAbbrev(std::move(Abv));
68 auto Abv1 = std::make_shared<BitCodeAbbrev>();
69 Abv1->Add(BitCodeAbbrevOp(FIRST_EXTENSION_RECORD_ID + 1));
70 Abv1->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
71 auto Abbrev1 = Stream.EmitAbbrev(std::move(Abv1));
75 for (llvm::sys::fs::directory_iterator DirIt(CachePath, EC), DirEnd; DirIt != DirEnd && !EC; DirIt.increment(EC)) {
76 StringRef FilePath(DirIt->path());
77 if (llvm::sys::fs::is_directory(FilePath))
79 StringRef FileName = llvm::sys::path::filename(FilePath);
80 if (FileName.startswith(RdictsStart) && FileName.endswith(RdictsEnd)) {
82 uint64_t Record[] = {FIRST_EXTENSION_RECORD_ID};
83 Stream.EmitRecordWithBlob(Abbrev, Record, FileName);
85 uint64_t Record1[] = {FIRST_EXTENSION_RECORD_ID + 1};
86 auto MBOrErr = MemoryBuffer::getFile(FilePath);
87 MemoryBuffer &MB = *MBOrErr.get();
88 Stream.EmitRecordWithBlob(Abbrev1, Record1, MB.getBuffer());
90 llvm::sys::fs::remove(FilePath);
95 extern "C" void TCling__RegisterRdictForLoadPCM(
const std::string &pcmFileNameFullPath, llvm::StringRef *pcmContent);
97 TClingRdictModuleFileExtension::Reader::Reader(clang::ModuleFileExtension *Ext, clang::ASTReader &Reader,
98 clang::serialization::ModuleFile &Mod,
99 const llvm::BitstreamCursor &InStream)
100 : ModuleFileExtensionReader(Ext), Stream(InStream)
103 llvm::SmallVector<uint64_t, 4> Record;
104 llvm::StringRef CurrentRdictName;
106 llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
107 switch (Entry.Kind) {
108 case llvm::BitstreamEntry::SubBlock:
109 case llvm::BitstreamEntry::EndBlock:
110 case llvm::BitstreamEntry::Error:
return;
112 case llvm::BitstreamEntry::Record:
break;
116 llvm::StringRef Blob;
117 unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob);
118 using namespace clang::serialization;
120 case FIRST_EXTENSION_RECORD_ID: {
121 CurrentRdictName = Blob;
124 case FIRST_EXTENSION_RECORD_ID + 1: {
126 std::string ResolvedFileName
127 = ROOT::TMetaUtils::GetRealPath(Mod.FileName);
128 llvm::StringRef ModDir = llvm::sys::path::parent_path(ResolvedFileName);
129 llvm::SmallString<255> FullRdictName = ModDir;
130 llvm::sys::path::append(FullRdictName, CurrentRdictName);
131 TCling__RegisterRdictForLoadPCM(FullRdictName.str(), &Blob);
138 TClingRdictModuleFileExtension::Reader::~Reader() {}
140 TClingRdictModuleFileExtension::~TClingRdictModuleFileExtension() {}
142 clang::ModuleFileExtensionMetadata TClingRdictModuleFileExtension::getExtensionMetadata()
const
144 const std::string UserInfo =
"";
145 return {ROOT_CLING_RDICT_BLOCK_NAME, ROOT_CLING_RDICT_VERSION_MAJOR, ROOT_CLING_RDICT_VERSION_MINOR, UserInfo};
148 llvm::hash_code TClingRdictModuleFileExtension::hashExtension(llvm::hash_code Code)
const
150 Code = llvm::hash_combine(Code, ROOT_CLING_RDICT_BLOCK_NAME);
151 Code = llvm::hash_combine(Code, ROOT_CLING_RDICT_VERSION_MAJOR);
152 Code = llvm::hash_combine(Code, ROOT_CLING_RDICT_VERSION_MINOR);
157 std::unique_ptr<clang::ModuleFileExtensionWriter>
158 TClingRdictModuleFileExtension::createExtensionWriter(clang::ASTWriter &)
160 return std::unique_ptr<clang::ModuleFileExtensionWriter>(
new Writer(
this));
163 std::unique_ptr<clang::ModuleFileExtensionReader>
164 TClingRdictModuleFileExtension::createExtensionReader(
const clang::ModuleFileExtensionMetadata &Metadata,
165 clang::ASTReader &Reader, clang::serialization::ModuleFile &Mod,
166 const llvm::BitstreamCursor &Stream)
168 return std::unique_ptr<clang::ModuleFileExtensionReader>(
169 new TClingRdictModuleFileExtension::Reader(
this, Reader, Mod, Stream));