chigraph  master
Systems programming language written for beginners in LLVM
Context.cpp
Go to the documentation of this file.
1 
3 #include "chi/Context.hpp"
4 #include "chi/BitcodeParser.hpp"
5 #include "chi/DefaultModuleCache.hpp"
6 #include "chi/GraphFunction.hpp"
7 #include "chi/NodeType.hpp"
8 #include "chi/GraphModule.hpp"
9 #include "chi/GraphStruct.hpp"
10 #include "chi/JsonDeserializer.hpp"
11 #include "chi/LLVMVersion.hpp"
12 #include "chi/LangModule.hpp"
13 #include "chi/NodeInstance.hpp"
15 #include "chi/Support/Result.hpp"
16 
17 #include <llvm/ExecutionEngine/ExecutionEngine.h>
18 #include <llvm/ExecutionEngine/GenericValue.h>
19 #include <llvm/ExecutionEngine/SectionMemoryManager.h>
20 #include <llvm/IR/Module.h>
21 #include <llvm/IR/Type.h>
22 #include <llvm/IR/Verifier.h>
23 #include <llvm/Linker/Linker.h>
24 #include <llvm/Support/TargetRegistry.h>
25 #include <llvm/Support/TargetSelect.h>
26 #include <llvm/Support/raw_ostream.h>
27 #include <llvm/Target/TargetMachine.h>
28 #include <llvm/Target/TargetOptions.h>
29 
30 #include <boost/algorithm/string/replace.hpp>
31 #include <boost/filesystem.hpp>
32 #include <boost/range.hpp>
33 
34 #include <deque>
35 #include <unordered_set>
36 
37 namespace fs = boost::filesystem;
38 
39 namespace chi {
40 Context::Context(const boost::filesystem::path& workPath) {
41  mWorkspacePath = workspaceFromChildPath(workPath);
42 
43  mModuleCache = std::make_unique<DefaultModuleCache>(*this);
44 }
45 
46 Context::~Context() = default;
47 
48 ChiModule* Context::moduleByFullName(const boost::filesystem::path& fullModuleName) const noexcept {
49  for (auto& module : mModules) {
50  if (module->fullName() == fullModuleName) { return module.get(); }
51  }
52  return nullptr;
53 }
54 
55 GraphModule* Context::newGraphModule(const boost::filesystem::path& fullName) {
56  // create the module
57  GraphModule* mod = nullptr;
58  {
59  auto uMod = std::make_unique<GraphModule>(*this, fullName);
60 
61  mod = uMod.get();
62  addModule(std::move(uMod));
63  }
64 
65  return mod;
66 }
67 
68 std::vector<std::string> Context::listModulesInWorkspace() const noexcept {
69  std::vector<std::string> moduleList;
70 
71  fs::path srcDir = workspacePath() / "src";
72 
73  if (!fs::is_directory(srcDir)) { return {}; }
74 
75  for (const auto& dirEntry : boost::make_iterator_range(
76  fs::recursive_directory_iterator{srcDir, fs::symlink_option::recurse}, {})) {
77  const fs::path& p = dirEntry;
78 
79  // see if it's a chigraph module
80  if (fs::is_regular_file(p) && p.extension() == ".chimod") {
81  fs::path relPath = fs::relative(p, srcDir);
82 
83  relPath.replace_extension(""); // remove .chimod
84  moduleList.emplace_back(relPath.string());
85  }
86  }
87 
88  return moduleList;
89 }
90 
91 Result Context::loadModule(const fs::path& name, ChiModule** toFill) {
92  assert(!name.empty() && "Name should not be empty when calling chi::Context::loadModule");
93 
94  Result res;
95 
96  auto requestedModCtx = res.addScopedContext({{"Requested Module Name", name.generic_string()}});
97 
98  // check for built-in modules
99  if (name == "lang") {
100  if (langModule() != nullptr) {
101  if (toFill != nullptr) { *toFill = langModule(); }
102  return {};
103  }
104  auto mod = std::make_unique<LangModule>(*this);
105  if (toFill != nullptr) { *toFill = mod.get(); }
106  addModule(std::move(mod));
107  return {};
108  }
109 
110  // see if it's already loaded
111  {
112  auto mod = moduleByFullName(name);
113  if (mod != nullptr) {
114  if (toFill != nullptr) { *toFill = mod; }
115  return {};
116  }
117  }
118 
119  if (workspacePath().empty()) {
120  res.addEntry("E52", "Cannot load module without a workspace path", {});
121  return res;
122  }
123 
124  // find it in the workspace
125  fs::path fullPath = workspacePath() / "src" / name;
126  fullPath.replace_extension(".chimod");
127 
128  if (!fs::is_regular_file(fullPath)) {
129  res.addEntry("EUKN", "Failed to find module",
130  {{"Workspace Path", workspacePath().string()},
131  {"Expected Path", fullPath.generic_string()}});
132  return res;
133  }
134 
135  // load the JSON
136  nlohmann::json readJson = {};
137  try {
138  fs::ifstream inFile{fullPath};
139 
140  inFile >> readJson;
141  } catch (std::exception& e) {
142  res.addEntry("EUKN", "Failed to parse json", {{"Error", e.what()}});
143  return res;
144  }
145 
146  GraphModule* toFillJson = nullptr;
147  res += addModuleFromJson(name.generic_string(), readJson, &toFillJson);
148  if (toFill != nullptr) { *toFill = toFillJson; }
149 
150  // set this to the last time the file was edited
151  toFillJson->updateLastEditTime(boost::filesystem::last_write_time(fullPath));
152 
153  return res;
154 }
155 
156 Result Context::addModuleFromJson(const fs::path& fullName, const nlohmann::json& json,
157  GraphModule** toFill) {
158  Result res;
159 
160  auto scopedCtx = res.addScopedContext({{"Requested Module Name", fullName.string()}});
161 
162  // make sure it's not already added
163  {
164  auto mod = moduleByFullName(fullName);
165  if (mod != nullptr) {
166  if (toFill != nullptr) {
167  auto casted = dynamic_cast<GraphModule*>(mod);
168  if (casted != nullptr) { *toFill = casted; }
169  }
170  return {};
171  }
172  }
173 
174  // Create the module
175  GraphModule* jMod = nullptr;
176  res += jsonToGraphModule(*this, json, fullName, &jMod);
177  if (toFill != nullptr) { *toFill = jMod; }
178 
179  // if we failed, remove the module
180  if (!res) { unloadModule(jMod->fullName()); }
181 
182  return res;
183 }
184 
185 bool Context::addModule(std::unique_ptr<ChiModule> modToAdd) noexcept {
186  assert(modToAdd != nullptr);
187 
188  // make sure it's unique
189  auto ptr = moduleByFullName(modToAdd->fullName());
190  if (ptr != nullptr) { return false; }
191 
192  if (modToAdd->fullName() == "lang") { mLangModule = dynamic_cast<LangModule*>(modToAdd.get()); }
193 
194  // add the converter nodes
195  for (const auto& tyName : modToAdd->nodeTypeNames()) {
196  // create it
197  std::unique_ptr<NodeType> ty;
198  auto res = modToAdd->nodeTypeFromName(tyName, {}, &ty);
199 
200  if (!res) {
201  // converter nodes must be stateless
202  continue;
203  }
204 
205  if (!ty->converter()) {
206  continue;
207  }
208 
209  // add it!
210  mTypeConverters[ty->dataInputs()[0].type.qualifiedName()][ty->dataOutputs()[0].type.qualifiedName()] = std::move(ty);
211  }
212 
213  mModules.push_back(std::move(modToAdd));
214 
215 
216  return true;
217 }
218 
219 bool Context::unloadModule(const fs::path& fullName) {
220  // find the module, and if we see it then delete it
221  for (auto idx = 0ull; idx < mModules.size(); ++idx) {
222  if (mModules[idx]->fullName() == fullName) {
223  mModules.erase(mModules.begin() + idx);
224  return true;
225  }
226  }
227 
228  // if we get here it wasn't removed
229  return false;
230 }
231 
232 Result Context::typeFromModule(const fs::path& module, boost::string_view name,
233  DataType* toFill) noexcept {
234  assert(toFill != nullptr);
235 
236  Result res;
237 
238  ChiModule* mod = moduleByFullName(module);
239  if (mod == nullptr) {
240  res.addEntry("E36", "Could not find module", {{"module", module.generic_string()}});
241  return res;
242  }
243 
244  *toFill = mod->typeFromName(name);
245  if (!toFill->valid()) {
246  res.addEntry("E37", "Could not find type in module",
247  {{"type", name.to_string()}, {"module", module.generic_string()}});
248  }
249 
250  return res;
251 }
252 
253 Result Context::nodeTypeFromModule(const fs::path& moduleName, boost::string_view typeName,
254  const nlohmann::json& data,
255  std::unique_ptr<NodeType>* toFill) noexcept {
256  Result res;
257 
258  auto module = moduleByFullName(moduleName);
259  if (module == nullptr) {
260  res.addEntry("E36", "Could not find module", {{"module", moduleName.generic_string()}});
261  return res;
262  }
263 
264  res += module->nodeTypeFromName(typeName, data, toFill);
265 
266  return res;
267 }
268 
269 std::unique_ptr<NodeType> Context::createConverterNodeType(const DataType& fromType, const DataType& toType) {
270  auto fromIter = mTypeConverters.find(fromType.qualifiedName());
271  if (fromIter == mTypeConverters.end()) {
272  return nullptr;
273  }
274 
275  auto toIter = fromIter->second.find(toType.qualifiedName());
276  if (toIter == fromIter->second.end()) {
277  return nullptr;
278  }
279 
280  return toIter->second->clone();
281 }
282 
283 
284 Result Context::compileModule(const boost::filesystem::path& fullName,
285  Flags<CompileSettings> settings,
286  std::unique_ptr<llvm::Module>* toFill) {
287  Result res;
288 
289  auto mod = moduleByFullName(fullName);
290  if (mod == nullptr) {
291  res.addEntry("E36", "Could not find module", {{"module", fullName.generic_string()}});
292  return res;
293  }
294 
295  return compileModule(*mod, settings, toFill);
296 }
297 
299  std::unique_ptr<llvm::Module>* toFill) {
300  assert(toFill != nullptr);
301 
302  Result res;
303 
304  auto modNameCtx = res.addScopedContext({{"Module Name", mod.fullName()}});
305 
306  // generate module or load it from the cache
307  std::unique_ptr<llvm::Module> llmod;
308  {
309  // try to get it from the cache
310  if (settings & CompileSettings::UseCache) {
311  llmod = moduleCache().retrieveFromCache(mod.fullNamePath(), mod.lastEditTime());
312  }
313 
314  // compile it if the cache failed or if
315  if (!llmod) {
316  llmod = std::make_unique<llvm::Module>(mod.fullName(), llvmContext());
317 
318  // add forward declartions for all dependencies
319  {
320  std::unordered_set<fs::path> added(mod.dependencies().begin(),
321  mod.dependencies().end());
322  std::deque<fs::path> depsToAdd(mod.dependencies().begin(),
323  mod.dependencies().end());
324  while (!depsToAdd.empty()) {
325  auto& depName = depsToAdd[0];
326 
327  auto depMod = moduleByFullName(depName);
328  if (depMod == nullptr) {
329  res.addEntry("E36", "Could not find module",
330  {{"module", depName.generic_string()}});
331  return res;
332  }
333 
334  res += depMod->addForwardDeclarations(*llmod);
335  if (!res) { return res; }
336 
337  for (const auto& depOfDep : depMod->dependencies()) {
338  if (added.find(depOfDep) == added.end()) {
339  depsToAdd.push_back(depOfDep);
340  added.insert(depOfDep);
341  }
342  }
343  depsToAdd.pop_front();
344  }
345  }
346 
347  res += mod.generateModule(*llmod);
348 
349  // set debug info version if it doesn't already have it
350  if (llmod->getModuleFlag("Debug Info Version") == nullptr) {
351  llmod->addModuleFlag(llvm::Module::Warning, "Debug Info Version",
352  llvm::DEBUG_METADATA_VERSION);
353  }
354  }
355  }
356 
357  // exit if there's already an error to avoid caching it
358  if (!res) { return res; }
359 
360 #ifndef NDEBUG
361 
362  // verify the created module
363  bool errored;
364  std::string err;
365  {
366  llvm::raw_string_ostream os(err);
367  errored = llvm::verifyModule(*llmod, &os);
368  }
369 
370  if (errored) {
371  // print out the module for the good errors
372  std::string moduleStr;
373  {
374  llvm::raw_string_ostream printerStr{moduleStr};
375  llmod->print(printerStr, nullptr);
376  }
377 
378  res.addEntry("EINT", "Internal compiler error: Invalid module created",
379  {{"Error", err}, {"Full Name", mod.fullName()}, {"Module", moduleStr}});
380  }
381 #endif
382 
383  // cache the module
384  res += moduleCache().cacheModule(mod.fullNamePath(), *llmod, mod.lastEditTime());
385 
386  // generate dependencies
387  if (settings & CompileSettings::LinkDependencies) {
388  for (const auto& depName : mod.dependencies()) {
389  std::unique_ptr<llvm::Module> compiledDep;
390  res += compileModule(depName, settings,
391  &compiledDep); // TODO(#62): detect circular dependencies
392 
393  if (!res) { return res; }
394 
395 // link it in
396 #if LLVM_VERSION_LESS_EQUAL(3, 7)
397  llvm::Linker::LinkModules(llmod.get(), compiledDep.get()
398 #if LLVM_VERSION_LESS_EQUAL(3, 5)
399  ,
400  llvm::Linker::DestroySource, nullptr
401 #endif
402  );
403 #else
404  llvm::Linker::linkModules(*llmod, std::move(compiledDep));
405 #endif
406  }
407 
408  // link in runtime if this is a main module
409  if (mod.shortName() == "main") {
410  // find the runtime
411  auto runtimebc =
412  executablePath().parent_path().parent_path() / "lib" / "chigraph" / "runtime.bc";
413 
414  if (!fs::is_regular_file(runtimebc)) {
415  res.addEntry(
416  "EUKN", "Failed to find runtime.bc in lib/chigraph/runtime.bc",
417  {{"Install prefix", executablePath().parent_path().parent_path().string()}});
418  }
419 
420  // load the BC file
421  std::unique_ptr<llvm::Module> runtimeMod;
422  res += parseBitcodeFile(runtimebc, llvmContext(), &runtimeMod);
423  if (!res) { return res; }
424 
425 // link it in
426 #if LLVM_VERSION_LESS_EQUAL(3, 7)
427  llvm::Linker::LinkModules(llmod.get(), runtimeMod.get()
428 #if LLVM_VERSION_LESS_EQUAL(3, 5)
429  ,
430  llvm::Linker::DestroySource, nullptr
431 #endif
432  );
433 #else
434  llvm::Linker::linkModules(*llmod, std::move(runtimeMod));
435 #endif
436  }
437  }
438 
439  *toFill = std::move(llmod);
440 
441  return res;
442 }
443 
444 std::vector<NodeInstance*> Context::findInstancesOfType(const fs::path& moduleName,
445  boost::string_view typeName) const {
446  std::vector<NodeInstance*> ret;
447 
448  for (const auto& module : mModules) {
449  // see if it's a GraphModule
450  auto castedMod = dynamic_cast<GraphModule*>(module.get());
451  if (castedMod == nullptr) { continue; }
452 
453  for (const auto& func : castedMod->functions()) {
454  auto vec = func->nodesWithType(moduleName, typeName);
455  std::copy(vec.begin(), vec.end(), std::back_inserter(ret));
456  }
457  }
458 
459  return ret;
460 }
461 
462 fs::path workspaceFromChildPath(const boost::filesystem::path& path) {
463  fs::path ret = path;
464 
465  // initialize workspace directory
466  // go up until it is a workspace
467  while (!ret.empty() && !fs::is_regular_file(ret / ".chigraphworkspace")) {
468  ret = ret.parent_path();
469  }
470 
471  return ret; // it's ok if it's empty
472 }
473 
474 std::string stringifyLLVMType(llvm::Type* ty) {
475  assert(ty != nullptr);
476 
477  std::string data;
478  {
479  llvm::raw_string_ostream stream{data};
480  ty->print(stream);
481  }
482  return data;
483 }
484 
485 namespace {
486 
487 std::unique_ptr<llvm::ExecutionEngine> createEE(std::unique_ptr<llvm::Module> mod,
488  llvm::CodeGenOpt::Level optLevel,
489  std::string& errMsg) {
490  llvm::InitializeNativeTarget();
491  llvm::InitializeNativeTargetAsmPrinter();
492  llvm::InitializeNativeTargetAsmParser();
493 
494  llvm::EngineBuilder EEBuilder(
495 #if LLVM_VERSION_LESS_EQUAL(3, 5)
496  mod.get()
497 #else
498  std::move(mod)
499 #endif
500 
501  );
502 
503  EEBuilder.setEngineKind(llvm::EngineKind::JIT);
504 
505 #ifndef _NDEBUG
506  EEBuilder.setVerifyModules(true);
507 #endif
508 
509  EEBuilder.setOptLevel(optLevel);
510 
511  EEBuilder.setErrorStr(&errMsg);
512 
513 #if LLVM_VERSION_LESS_EQUAL(3, 5)
514  EEBuilder.setUseMCJIT(true);
515 #endif
516 
517  EEBuilder.setMCJITMemoryManager(
518 #if LLVM_VERSION_AT_LEAST(3, 6)
519  std::unique_ptr<llvm::SectionMemoryManager>
520 #endif
521  (new llvm::SectionMemoryManager()));
522 
523  return std::unique_ptr<llvm::ExecutionEngine>(EEBuilder.create());
524 }
525 
526 } // anonymous namespace
527 
528 Result interpretLLVMIR(std::unique_ptr<llvm::Module> mod, llvm::CodeGenOpt::Level optLevel,
529  const std::vector<llvm::GenericValue>& args, llvm::Function* funcToRun,
530  llvm::GenericValue* ret) {
531  assert(mod);
532 
533  Result res;
534 
535  if (funcToRun == nullptr) {
536  funcToRun = mod->getFunction("main");
537 
538  if (funcToRun == nullptr) {
539  res.addEntry("EUKN", "Failed to find main function in module",
540  {{"Module Name", mod->getModuleIdentifier()}});
541  return res;
542  }
543  }
544 
545  std::string errMsg;
546  auto EE = createEE(std::move(mod), optLevel, errMsg);
547  EE->finalizeObject();
548  EE->runStaticConstructorsDestructors(false);
549 
550  if (!EE) {
551  res.addEntry("EINT", "Failed to create an LLVM ExecutionEngine", {{"Error", errMsg}});
552  return res;
553  }
554 
555  auto returnValue = EE->runFunction(funcToRun, args);
556 
557  EE->runStaticConstructorsDestructors(true);
558 
559  if (ret != nullptr) { *ret = returnValue; }
560 
561  return res;
562 }
563 
564 Result interpretLLVMIRAsMain(std::unique_ptr<llvm::Module> mod, llvm::CodeGenOpt::Level optLevel,
565  const std::vector<std::string>& args, llvm::Function* funcToRun,
566  int* ret) {
567  assert(mod);
568 
569  Result res;
570 
571  if (funcToRun == nullptr) {
572  funcToRun = mod->getFunction("main");
573 
574  if (funcToRun == nullptr) {
575  res.addEntry("EUKN", "Failed to find main function in module",
576  {{"Module Name", mod->getModuleIdentifier()}});
577  return res;
578  }
579  }
580 
581  std::string errMsg;
582  auto EE = createEE(std::move(mod), optLevel, errMsg);
583  EE->finalizeObject();
584  EE->runStaticConstructorsDestructors(false);
585 
586  if (!EE) {
587  res.addEntry("EINT", "Failed to create an LLVM ExecutionEngine", {{"Error", errMsg}});
588  return res;
589  }
590 
591  auto returnValue = EE->runFunctionAsMain(funcToRun, args, nullptr);
592 
593  EE->runStaticConstructorsDestructors(true);
594 
595  if (ret != nullptr) { *ret = returnValue; }
596 
597  return res;
598 }
599 void Context::setModuleCache(std::unique_ptr<ModuleCache> newCache) {
600  assert(newCache != nullptr && "Cannot set the modulecache to be nullptr");
601 
602  mModuleCache = std::move(newCache);
603 }
604 
605 } // namespace chi
Result parseBitcodeFile(const boost::filesystem::path &file, llvm::LLVMContext &ctx, std::unique_ptr< llvm::Module > *toFill)
Parse a bitcode file.
Result nodeTypeFromName(boost::string_view name, const nlohmann::json &jsonData, std::unique_ptr< NodeType > *toFill) override
Create a node type that is in the module from the name and json.
Definition: LangModule.cpp:847
LangModule * langModule() const
Get the LangModule, if it has been loaded.
Definition: Context.hpp:177
ChiModule * moduleByFullName(const boost::filesystem::path &fullModuleName) const noexcept
Gets the module by the full name.
Definition: Context.cpp:48
boost::filesystem::path executablePath()
Get the path of the executable.
virtual Result generateModule(llvm::Module &module)=0
Generate a llvm::Module from the module.
void addEntry(const char *ec, const char *overview, nlohmann::json data)
Add a entry to the result, either a warning or an error.
Definition: Result.cpp:52
Result nodeTypeFromModule(const boost::filesystem::path &moduleName, boost::string_view typeName, const nlohmann::json &data, std::unique_ptr< NodeType > *toFill) noexcept
Gets a NodeType from the JSON and name.
Definition: Context.cpp:253
bool unloadModule(const boost::filesystem::path &fullName)
Unloads a module.
Definition: Context.cpp:219
The module that provides built-in operations like literals, math operations, etc. ...
Definition: LangModule.hpp:16
Defines the Result class and related functions.
bool addModule(std::unique_ptr< ChiModule > modToAdd) noexcept
Adds a custom module to the Context.
Definition: Context.cpp:185
std::vector< std::string > listModulesInWorkspace() const noexcept
Get the list of modules in the workspace.
Definition: Context.cpp:68
Result loadModule(const boost::filesystem::path &name, ChiModule **toFill=nullptr)
Load a module from disk, also loads dependencies.
Definition: Context.cpp:91
std::vector< NodeInstance * > findInstancesOfType(const boost::filesystem::path &moduleName, boost::string_view typeName) const
Find all uses of a node type in all the loaded modules.
Definition: Context.cpp:444
boost::filesystem::path workspacePath() const
Get the workspace path of the Context.
Definition: Context.hpp:138
Define GraphStruct.
Context(const boost::filesystem::path &workPath={})
Creates a context with just the lang module.
Definition: Context.cpp:40
Result jsonToGraphModule(Context &createInside, const nlohmann::json &input, const boost::filesystem::path &fullName, GraphModule **toFill=nullptr)
Load a GraphModule from json.
boost::filesystem::path workspaceFromChildPath(const boost::filesystem::path &path)
Get the workspace directory from a child of the workspace directory Example: say you have a workspace...
Definition: Context.cpp:462
virtual Result cacheModule(const boost::filesystem::path &moduleName, llvm::Module &compiledModule, std::time_t timeAtFileRead)=0
Cache a module.
std::string fullName() const
Get the full name of the module.
Definition: ChiModule.hpp:61
ScopedContext addScopedContext(const nlohmann::json &data)
Add a context with a scope Example usage: chi::Result res; res.contextJson(); // returns {} { aut...
Definition: Result.hpp:123
virtual std::unique_ptr< llvm::Module > retrieveFromCache(const boost::filesystem::path &moduleName, std::time_t atLeastThisNew)=0
Retrieve a module from the cache.
An abstract class that represents a module of code in Chigraph Can be compiled to a llvm::Module...
Definition: ChiModule.hpp:24
Result interpretLLVMIRAsMain(std::unique_ptr< llvm::Module > mod, llvm::CodeGenOpt::Level optLevel=llvm::CodeGenOpt::Default, const std::vector< std::string > &args={}, llvm::Function *funcToRun=nullptr, int *ret=nullptr)
Interpret LLVM IR as if it were the main function.
Definition: Context.cpp:564
std::unique_ptr< NodeType > createConverterNodeType(const DataType &fromType, const DataType &toType)
Create a converter node.
Definition: Context.cpp:269
Result interpretLLVMIR(std::unique_ptr< llvm::Module > mod, llvm::CodeGenOpt::Level optLevel=llvm::CodeGenOpt::Default, const std::vector< llvm::GenericValue > &args={}, llvm::Function *funcToRun=nullptr, llvm::GenericValue *ret=nullptr)
Interpret LLVM IR, just a convenience function.
Definition: Context.cpp:528
A template class for type-safe flags.
Definition: Flags.hpp:26
Defines the NodeType class.
llvm::LLVMContext & llvmContext()
Get the LLVMContext
Definition: Context.hpp:173
std::string qualifiedName() const
Get the qualified name of the type (module().fullName() + ":" name())
Definition: DataType.cpp:8
const ModuleCache & moduleCache() const
Get the module cache.
Definition: Context.hpp:191
const std::set< boost::filesystem::path > & dependencies() const
Get the dependencies.
Definition: ChiModule.hpp:83
Defines the LangModule class.
void updateLastEditTime(std::time_t newLastEditTime=std::time(nullptr))
Update the last edit time, signifying that it&#39;s been edited.
Definition: ChiModule.hpp:105
Result typeFromModule(const boost::filesystem::path &module, boost::string_view name, DataType *toFill) noexcept
Gets a DataType from a module.
Definition: Context.cpp:232
Result compileModule(const boost::filesystem::path &fullName, Flags< CompileSettings > settings, std::unique_ptr< llvm::Module > *toFill)
Compile a module to a llvm::Module.
Definition: Context.cpp:284
void setModuleCache(std::unique_ptr< ModuleCache > newCache)
Set the module cache.
Definition: Context.cpp:599
Module that holds graph functions.
Definition: GraphModule.hpp:16
boost::filesystem::path fullNamePath() const
Get the full name of the module in a path.
Definition: ChiModule.hpp:64
Defines the GraphModule class.
virtual DataType typeFromName(boost::string_view name)=0
Get a DataType from the name.
The namespace where chigraph lives.
Use the cache in lib.
~Context()
Destructor.
std::string stringifyLLVMType(llvm::Type *ty)
Turns a type into a string.
Definition: Context.cpp:474
Defines the Context class and related functions.
A type of data Loose wrapper around llvm::Type*, except it knows which ChiModule it&#39;s in and it embed...
Definition: DataType.hpp:17
GraphModule * newGraphModule(const boost::filesystem::path &fullName)
Create a new GraphModule with the given full name.
Definition: Context.cpp:55
std::time_t lastEditTime() const
Get the time that this module was last edited.
Definition: ChiModule.hpp:101
Link in dependencies If this is set, it will be a ready to run module If not, it&#39;ll contain forward d...
std::string shortName() const
Get the short name of the module (the last bit)
Definition: ChiModule.hpp:58
The result object, used for identifiying errors with good diagnostics.
Definition: Result.hpp:72
Declares the GraphFunction class.
Defines the NodeInstance class and related functions.
Define deserialization functions.
Result addModuleFromJson(const boost::filesystem::path &fullName, const nlohmann::json &json, GraphModule **toFill=nullptr)
Load a module from JSON – avoid this use the string overload.
Definition: Context.cpp:156