Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TClingRdictModuleFileExtension.cxx
Go to the documentation of this file.
1/// \file TClingRdictModuleFileExtension.cxx
2///
3/// \brief The file contains facilities to work with C++ module files extensions
4/// used to store rdict files.
5///
6/// \author Vassil Vassilev <vvasilev@cern.ch>
7///
8/// \date May, 2019
9///
10/*************************************************************************
11 * Copyright (C) 1995-2018, Rene Brun and Fons Rademakers. *
12 * All rights reserved. *
13 * *
14 * For the licensing terms see $ROOTSYS/LICENSE. *
15 * For the list of contributors see $ROOTSYS/README/CREDITS. *
16 *************************************************************************/
17
19
20#include "TClingUtils.h"
21
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"
28
29#include "llvm/ADT/Hashing.h"
30#include "llvm/Bitstream/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"
35
36#include <fstream>
37#include <sstream>
38
39/// Rdict module extension block name.
40const std::string ROOT_CLING_RDICT_BLOCK_NAME = "root.cling.rdict";
41
42/// Rdict module extension major version number.
43constexpr uint16_t ROOT_CLING_RDICT_VERSION_MAJOR = 1;
44
45/// Rdict module extension minor version number.
46///
47/// When the format changes IN ANY WAY, this number should be incremented.
48constexpr uint16_t ROOT_CLING_RDICT_VERSION_MINOR = 1;
49
50
52
53void TClingRdictModuleFileExtension::Writer::writeExtensionContents(clang::Sema &SemaRef, llvm::BitstreamWriter &Stream)
54{
55
56 const clang::LangOptions &Opts = SemaRef.getLangOpts();
57 const clang::Preprocessor &PP = SemaRef.getPreprocessor();
58
59 llvm::StringRef CachePath = PP.getHeaderSearchInfo().getHeaderSearchOpts().ModuleCachePath;
60 std::string RdictsStart = "lib" + Opts.CurrentModule + "_";
61 const std::string RdictsEnd = "_rdict.pcm";
62
63 using namespace llvm;
64 using namespace clang;
65 using namespace clang::serialization;
66 // Write an abbreviation for this record.
67 auto Abv = std::make_shared<BitCodeAbbrev>();
68 Abv->Add(BitCodeAbbrevOp(FIRST_EXTENSION_RECORD_ID));
69 Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
70 auto Abbrev = Stream.EmitAbbrev(std::move(Abv));
71 auto Abv1 = std::make_shared<BitCodeAbbrev>();
72 Abv1->Add(BitCodeAbbrevOp(FIRST_EXTENSION_RECORD_ID + 1));
73 Abv1->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
74 auto Abbrev1 = Stream.EmitAbbrev(std::move(Abv1));
75
76 // Write a dict files into the extension block.
77 std::error_code EC;
78 for (llvm::sys::fs::directory_iterator DirIt(CachePath, EC), DirEnd; DirIt != DirEnd && !EC; DirIt.increment(EC)) {
79 StringRef FilePath(DirIt->path());
80 if (llvm::sys::fs::is_directory(FilePath))
81 continue;
82 StringRef FileName = llvm::sys::path::filename(FilePath);
83 if (FileName.startswith(RdictsStart) && FileName.endswith(RdictsEnd)) {
84
85 uint64_t Record[] = {FIRST_EXTENSION_RECORD_ID};
86 Stream.EmitRecordWithBlob(Abbrev, Record, FileName);
87
88 uint64_t Record1[] = {FIRST_EXTENSION_RECORD_ID + 1};
89 std::ifstream fp(FilePath, std::ios::binary);
90 std::ostringstream os;
91 os << fp.rdbuf();
92 Stream.EmitRecordWithBlob(Abbrev1, Record1, StringRef(os.str()));
93 fp.close();
94
95 EC = llvm::sys::fs::remove(FilePath);
96 assert(!EC && "Unable to close _rdict file");
97 }
98 }
99}
100
101extern "C" void TCling__RegisterRdictForLoadPCM(const std::string &pcmFileNameFullPath, llvm::StringRef *pcmContent);
102
103TClingRdictModuleFileExtension::Reader::Reader(clang::ModuleFileExtension *Ext, clang::ASTReader &Reader,
104 clang::serialization::ModuleFile &Mod,
105 const llvm::BitstreamCursor &InStream)
106 : ModuleFileExtensionReader(Ext), Stream(InStream)
107{
108 // Read the extension block.
109 llvm::SmallVector<uint64_t, 4> Record;
110 llvm::StringRef CurrentRdictName;
111 while (true) {
112 llvm::BitstreamEntry Entry = llvm::cantFail(Stream.advanceSkippingSubblocks());
113 switch (Entry.Kind) {
114 case llvm::BitstreamEntry::SubBlock:
115 case llvm::BitstreamEntry::EndBlock:
116 case llvm::BitstreamEntry::Error: return;
117
118 case llvm::BitstreamEntry::Record: break;
119 }
120
121 Record.clear();
122 llvm::StringRef Blob;
123 unsigned RecCode = llvm::cantFail(Stream.readRecord(Entry.ID, Record, &Blob));
124 using namespace clang::serialization;
125 switch (RecCode) {
126 case FIRST_EXTENSION_RECORD_ID: {
127 CurrentRdictName = Blob;
128 break;
129 }
130 case FIRST_EXTENSION_RECORD_ID + 1: {
131 // FIXME: Remove the string copy in fPendingRdicts.
132 std::string ResolvedFileName
133 = ROOT::TMetaUtils::GetRealPath(Mod.FileName);
134 llvm::StringRef ModDir = llvm::sys::path::parent_path(ResolvedFileName);
135 llvm::SmallString<255> FullRdictName = ModDir;
136 llvm::sys::path::append(FullRdictName, CurrentRdictName);
137 TCling__RegisterRdictForLoadPCM(FullRdictName.str(), &Blob);
138 break;
139 }
140 }
141 }
142}
143
145
147
148clang::ModuleFileExtensionMetadata TClingRdictModuleFileExtension::getExtensionMetadata() const
149{
150 const std::string UserInfo = "";
152}
153
154llvm::hash_code TClingRdictModuleFileExtension::hashExtension(llvm::hash_code Code) const
155{
156 Code = llvm::hash_combine(Code, ROOT_CLING_RDICT_BLOCK_NAME);
157 Code = llvm::hash_combine(Code, ROOT_CLING_RDICT_VERSION_MAJOR);
158 Code = llvm::hash_combine(Code, ROOT_CLING_RDICT_VERSION_MINOR);
159
160 return Code;
161}
162
163std::unique_ptr<clang::ModuleFileExtensionWriter>
165{
166 return std::unique_ptr<clang::ModuleFileExtensionWriter>(new Writer(this));
167}
168
169std::unique_ptr<clang::ModuleFileExtensionReader>
170TClingRdictModuleFileExtension::createExtensionReader(const clang::ModuleFileExtensionMetadata &Metadata,
171 clang::ASTReader &Reader, clang::serialization::ModuleFile &Mod,
172 const llvm::BitstreamCursor &Stream)
173{
174 return std::unique_ptr<clang::ModuleFileExtensionReader>(
175 new TClingRdictModuleFileExtension::Reader(this, Reader, Mod, Stream));
176}
constexpr uint16_t ROOT_CLING_RDICT_VERSION_MINOR
Rdict module extension minor version number.
const std::string ROOT_CLING_RDICT_BLOCK_NAME
Rdict module extension block name.
constexpr uint16_t ROOT_CLING_RDICT_VERSION_MAJOR
Rdict module extension major version number.
The file contains facilities to work with C++ module files extensions used to store rdict files.
void TCling__RegisterRdictForLoadPCM(const std::string &pcmFileNameFullPath, llvm::StringRef *pcmContent)
Definition TCling.cxx:578
Reader(clang::ModuleFileExtension *Ext, clang::ASTReader &Reader, clang::serialization::ModuleFile &Mod, const llvm::BitstreamCursor &InStream)
void writeExtensionContents(clang::Sema &SemaRef, llvm::BitstreamWriter &Stream) override
std::unique_ptr< clang::ModuleFileExtensionReader > createExtensionReader(const clang::ModuleFileExtensionMetadata &Metadata, clang::ASTReader &Reader, clang::serialization::ModuleFile &Mod, const llvm::BitstreamCursor &Stream) override
clang::ModuleFileExtensionMetadata getExtensionMetadata() const override
std::unique_ptr< clang::ModuleFileExtensionWriter > createExtensionWriter(clang::ASTWriter &Writer) override
llvm::hash_code hashExtension(llvm::hash_code Code) const override
std::string GetRealPath(const std::string &path)