Logo ROOT  
Reference Guide
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/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"
35 
36 /// Rdict module extension block name.
37 const std::string ROOT_CLING_RDICT_BLOCK_NAME = "root.cling.rdict";
38 
39 /// Rdict module extension major version number.
40 constexpr uint16_t ROOT_CLING_RDICT_VERSION_MAJOR = 1;
41 
42 /// Rdict module extension minor version number.
43 ///
44 /// When the format changes IN ANY WAY, this number should be incremented.
45 constexpr uint16_t ROOT_CLING_RDICT_VERSION_MINOR = 1;
46 
47 
49 
50 void TClingRdictModuleFileExtension::Writer::writeExtensionContents(clang::Sema &SemaRef, llvm::BitstreamWriter &Stream)
51 {
52 
53  const clang::LangOptions &Opts = SemaRef.getLangOpts();
54  const clang::Preprocessor &PP = SemaRef.getPreprocessor();
55 
56  llvm::StringRef CachePath = PP.getHeaderSearchInfo().getHeaderSearchOpts().ModuleCachePath;
57  std::string RdictsStart = "lib" + Opts.CurrentModule + "_";
58  const std::string RdictsEnd = "_rdict.pcm";
59 
60  using namespace llvm;
61  using namespace clang;
62  using namespace clang::serialization;
63  // Write an abbreviation for this record.
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));
72 
73  // Write a dict files into the extension block.
74  std::error_code EC;
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))
78  continue;
79  StringRef FileName = llvm::sys::path::filename(FilePath);
80  if (FileName.startswith(RdictsStart) && FileName.endswith(RdictsEnd)) {
81 
82  uint64_t Record[] = {FIRST_EXTENSION_RECORD_ID};
83  Stream.EmitRecordWithBlob(Abbrev, Record, FileName);
84 
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());
89 
90  llvm::sys::fs::remove(FilePath);
91  }
92  }
93 }
94 
95 extern "C" void TCling__RegisterRdictForLoadPCM(const std::string &pcmFileNameFullPath, llvm::StringRef *pcmContent);
96 
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)
101 {
102  // Read the extension block.
103  llvm::SmallVector<uint64_t, 4> Record;
104  llvm::StringRef CurrentRdictName;
105  while (true) {
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;
111 
112  case llvm::BitstreamEntry::Record: break;
113  }
114 
115  Record.clear();
116  llvm::StringRef Blob;
117  unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob);
118  using namespace clang::serialization;
119  switch (RecCode) {
120  case FIRST_EXTENSION_RECORD_ID: {
121  CurrentRdictName = Blob;
122  break;
123  }
124  case FIRST_EXTENSION_RECORD_ID + 1: {
125  // FIXME: Remove the string copy in fPendingRdicts.
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);
132  break;
133  }
134  }
135  }
136 }
137 
139 
141 
142 clang::ModuleFileExtensionMetadata TClingRdictModuleFileExtension::getExtensionMetadata() const
143 {
144  const std::string UserInfo = "";
146 }
147 
148 llvm::hash_code TClingRdictModuleFileExtension::hashExtension(llvm::hash_code Code) const
149 {
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);
153 
154  return Code;
155 }
156 
157 std::unique_ptr<clang::ModuleFileExtensionWriter>
159 {
160  return std::unique_ptr<clang::ModuleFileExtensionWriter>(new Writer(this));
161 }
162 
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)
167 {
168  return std::unique_ptr<clang::ModuleFileExtensionReader>(
170 }
TClingRdictModuleFileExtension::getExtensionMetadata
clang::ModuleFileExtensionMetadata getExtensionMetadata() const override
Definition: TClingRdictModuleFileExtension.cxx:142
llvm
Definition: TString.h:845
ROOT_CLING_RDICT_VERSION_MAJOR
constexpr uint16_t ROOT_CLING_RDICT_VERSION_MAJOR
Rdict module extension major version number.
Definition: TClingRdictModuleFileExtension.cxx:40
TClingRdictModuleFileExtension.h
The file contains facilities to work with C++ module files extensions used to store rdict files.
TClingRdictModuleFileExtension::~TClingRdictModuleFileExtension
~TClingRdictModuleFileExtension() override
Definition: TClingRdictModuleFileExtension.cxx:140
TClingRdictModuleFileExtension::Reader::~Reader
~Reader() override
Definition: TClingRdictModuleFileExtension.cxx:138
TCling__RegisterRdictForLoadPCM
void TCling__RegisterRdictForLoadPCM(const std::string &pcmFileNameFullPath, llvm::StringRef *pcmContent)
Definition: TCling.cxx:592
TClingRdictModuleFileExtension::Reader
Definition: TClingRdictModuleFileExtension.h:36
ROOT_CLING_RDICT_BLOCK_NAME
const std::string ROOT_CLING_RDICT_BLOCK_NAME
Rdict module extension block name.
Definition: TClingRdictModuleFileExtension.cxx:37
ROOT::TMetaUtils::GetRealPath
std::string GetRealPath(const std::string &path)
Definition: TClingUtils.cxx:73
TClingRdictModuleFileExtension::Writer
Definition: TClingRdictModuleFileExtension.h:28
TClingRdictModuleFileExtension::Writer::writeExtensionContents
void writeExtensionContents(clang::Sema &SemaRef, llvm::BitstreamWriter &Stream) override
Definition: TClingRdictModuleFileExtension.cxx:50
ROOT_CLING_RDICT_VERSION_MINOR
constexpr uint16_t ROOT_CLING_RDICT_VERSION_MINOR
Rdict module extension minor version number.
Definition: TClingRdictModuleFileExtension.cxx:45
TClingRdictModuleFileExtension::Writer::~Writer
~Writer() override
Definition: TClingRdictModuleFileExtension.cxx:48
TClingRdictModuleFileExtension::createExtensionWriter
std::unique_ptr< clang::ModuleFileExtensionWriter > createExtensionWriter(clang::ASTWriter &Writer) override
Definition: TClingRdictModuleFileExtension.cxx:158
TClingRdictModuleFileExtension::hashExtension
llvm::hash_code hashExtension(llvm::hash_code Code) const override
Definition: TClingRdictModuleFileExtension.cxx:148
TClingRdictModuleFileExtension::createExtensionReader
std::unique_ptr< clang::ModuleFileExtensionReader > createExtensionReader(const clang::ModuleFileExtensionMetadata &Metadata, clang::ASTReader &Reader, clang::serialization::ModuleFile &Mod, const llvm::BitstreamCursor &Stream) override
Definition: TClingRdictModuleFileExtension.cxx:164
clang
Definition: BaseSelectionRule.h:29
TClingUtils.h
TClingRdictModuleFileExtension::Reader::Stream
llvm::BitstreamCursor Stream
Definition: TClingRdictModuleFileExtension.h:37
TClingRdictModuleFileExtension::Reader::Reader
Reader(clang::ModuleFileExtension *Ext, clang::ASTReader &Reader, clang::serialization::ModuleFile &Mod, const llvm::BitstreamCursor &InStream)
Definition: TClingRdictModuleFileExtension.cxx:97
Error
void Error(const char *location, const char *msgfmt,...)