chigraph  master
Systems programming language written for beginners in LLVM
DefaultModuleCache.cpp
Go to the documentation of this file.
1 
3 #include "chi/DefaultModuleCache.hpp"
4 #include "chi/BitcodeParser.hpp"
5 #include "chi/Context.hpp"
6 #include "chi/LLVMVersion.hpp"
7 #include "chi/ModuleCache.hpp"
8 #include "chi/Support/Result.hpp"
9 
10 #include <cassert>
11 
12 #include <boost/filesystem/operations.hpp>
13 
14 #if LLVM_VERSION_LESS_EQUAL(3, 9)
15 #include <llvm/Bitcode/ReaderWriter.h>
16 #else
17 #include <llvm/Bitcode/BitcodeWriter.h>
18 #endif
19 
20 #include <llvm/IR/Module.h>
21 #include <llvm/Support/FileSystem.h>
22 #include <llvm/Support/raw_ostream.h>
23 
24 namespace chi {
25 
27 
28 Result DefaultModuleCache::cacheModule(const boost::filesystem::path& moduleName,
29  llvm::Module& compiledModule, std::time_t timeAtFileRead) {
30  assert(!moduleName.empty() &&
31  "Cannot pass a empty module name to DefaultModuleCache::cacheModule");
32 
33  Result res;
34 
35  auto cachePath = cachePathForModule(moduleName);
36 
37  // make the directories
38  boost::filesystem::create_directories(cachePath.parent_path());
39 
40  // open & write
41  {
42  // open the file
43  std::error_code errCode;
44  std::string errString;
45  llvm::raw_fd_ostream fileStream {
46  cachePath.string().c_str(),
47 #if LLVM_VERSION_LESS_EQUAL(3, 5)
48  errString,
49 #else
50  errCode,
51 #endif
52  llvm::sys::fs::F_RW
53  };
54 
55  if (errCode || !errString.empty()) {
56  res.addEntry("EUKN", "Failed to open file", {{"Path", cachePath.string()}});
57  return res;
58  }
59 
60  // write it
61  llvm::WriteBitcodeToFile(&compiledModule, fileStream);
62  }
63 
64  // set age to be correct
65  boost::filesystem::last_write_time(cachePath, timeAtFileRead);
66 
67  return res;
68 }
69 
71  const boost::filesystem::path& moduleName) const {
72  return context().workspacePath() / "lib" / (moduleName.string() + ".bc");
73 }
74 
75 void DefaultModuleCache::invalidateCache(const boost::filesystem::path& moduleName) {
76  assert(!moduleName.empty() && "Cannot pass empty path to DefaultModuleCache::invalidateCache");
77 
78  auto cachePath = cachePathForModule(moduleName);
79 
80  boost::filesystem::remove(cachePath);
81 }
82 
83 std::time_t DefaultModuleCache::cacheUpdateTime(const boost::filesystem::path& moduleName) const {
84  return boost::filesystem::last_write_time(cachePathForModule(moduleName));
85 }
86 
87 std::unique_ptr<llvm::Module> DefaultModuleCache::retrieveFromCache(
88  const boost::filesystem::path& moduleName, std::time_t atLeastThisNew) {
89  assert(!moduleName.empty() &&
90  "Cannot pass empty path to DefaultModuleCache::retrieveFromCache");
91 
92  auto cachePath = cachePathForModule(moduleName);
93 
94  // if there is no cache, then there is nothing to retrieve
95  if (!boost::filesystem::is_regular_file(cachePath)) { return nullptr; }
96 
97  // see if the cache is new enough
98  auto cacheEditTime = cacheUpdateTime(moduleName);
99  if (cacheEditTime < atLeastThisNew) { return nullptr; }
100 
101  // read the cache
102  std::unique_ptr<llvm::Module> fetchedMod;
103  auto res = parseBitcodeFile(cachePath, context().llvmContext(), &fetchedMod);
104 
105  if (!res) { return nullptr; }
106 
107  return fetchedMod;
108 }
109 
110 } // namespace chi
Result parseBitcodeFile(const boost::filesystem::path &file, llvm::LLVMContext &ctx, std::unique_ptr< llvm::Module > *toFill)
Parse a bitcode file.
void invalidateCache(const boost::filesystem::path &moduleName) override
Defines the Result class and related functions.
boost::filesystem::path workspacePath() const
Get the workspace path of the Context.
Definition: Context.hpp:138
std::unique_ptr< llvm::Module > retrieveFromCache(const boost::filesystem::path &moduleName, std::time_t atLeastThisNew) override
Retrieve a module from the cache.
The class that handles the loading, creation, storing, and compilation of modules It also stores a LL...
Definition: Context.hpp:55
boost::filesystem::path cachePathForModule(const boost::filesystem::path &moduleName) const
Get the cache name for a module.
std::time_t cacheUpdateTime(const boost::filesystem::path &moduleName) const override
Get the time that a cache was updated.
This class provides an interface for creating module caches.
Definition: ModuleCache.hpp:16
Result cacheModule(const boost::filesystem::path &moduleName, llvm::Module &compiledModule, std::time_t timeAtFileRead) override
Cache a module.
Context & context() const
Get the context this cache is bound to.
Definition: ModuleCache.hpp:59
The namespace where chigraph lives.
Defines the Context class and related functions.
The result object, used for identifiying errors with good diagnostics.
Definition: Result.hpp:72
DefaultModuleCache(Context &ctx)
Default constrcutor.