| 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"
14 #include "chi/Support/ExecutablePath.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
298 Result Context::compileModule(ChiModule& mod, Flags<CompileSettings> settings,
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
BitcodeParser.hpp
LLVMVersion.hpp
chi::parseBitcodeFile
Result parseBitcodeFile(const boost::filesystem::path &file, llvm::LLVMContext &ctx, std::unique_ptr< llvm::Module > *toFill)
Parse a bitcode file.
Definition: BitcodeParser.cpp:56
chi::LangModule::nodeTypeFromName
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
chi::Context::langModule
LangModule * langModule() const
Get the LangModule, if it has been loaded.
Definition: Context.hpp:177
chi::Context::moduleByFullName
ChiModule * moduleByFullName(const boost::filesystem::path &fullModuleName) const noexcept
Gets the module by the full name.
Definition: Context.cpp:48
chi::executablePath
boost::filesystem::path executablePath()
Get the path of the executable.
chi::ChiModule::generateModule
virtual Result generateModule(llvm::Module &module)=0
Generate a llvm::Module from the module.
chi::Result::addEntry
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
chi::Context::nodeTypeFromModule
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
chi::Context::unloadModule
bool unloadModule(const boost::filesystem::path &fullName)
Unloads a module.
Definition: Context.cpp:219
chi::LangModule
The module that provides built-in operations like literals, math operations, etc. ...
Definition: LangModule.hpp:16
Result.hpp
Defines the Result class and related functions.
chi::Context::addModule
bool addModule(std::unique_ptr< ChiModule > modToAdd) noexcept
Adds a custom module to the Context.
Definition: Context.cpp:185
chi::Context::listModulesInWorkspace
std::vector< std::string > listModulesInWorkspace() const noexcept
Get the list of modules in the workspace.
Definition: Context.cpp:68
chi::Context::loadModule
Result loadModule(const boost::filesystem::path &name, ChiModule **toFill=nullptr)
Load a module from disk, also loads dependencies.
Definition: Context.cpp:91
chi::Context::findInstancesOfType
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
chi::Context::workspacePath
boost::filesystem::path workspacePath() const
Get the workspace path of the Context.
Definition: Context.hpp:138
GraphStruct.hpp
Define GraphStruct.
chi::Context::Context
Context(const boost::filesystem::path &workPath={})
Creates a context with just the lang module.
Definition: Context.cpp:40
chi::jsonToGraphModule
Result jsonToGraphModule(Context &createInside, const nlohmann::json &input, const boost::filesystem::path &fullName, GraphModule **toFill=nullptr)
Load a GraphModule from json.
Definition: JsonDeserializer.cpp:14
chi::workspaceFromChildPath
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
chi::ModuleCache::cacheModule
virtual Result cacheModule(const boost::filesystem::path &moduleName, llvm::Module &compiledModule, std::time_t timeAtFileRead)=0
Cache a module.
chi::ChiModule::fullName
std::string fullName() const
Get the full name of the module.
Definition: ChiModule.hpp:61
chi::Result::addScopedContext
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
chi::ModuleCache::retrieveFromCache
virtual std::unique_ptr< llvm::Module > retrieveFromCache(const boost::filesystem::path &moduleName, std::time_t atLeastThisNew)=0
Retrieve a module from the cache.
chi::ChiModule
An abstract class that represents a module of code in Chigraph Can be compiled to a llvm::Module...
Definition: ChiModule.hpp:24
chi::interpretLLVMIRAsMain
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
chi::Context::createConverterNodeType
std::unique_ptr< NodeType > createConverterNodeType(const DataType &fromType, const DataType &toType)
Create a converter node.
Definition: Context.cpp:269
chi::interpretLLVMIR
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
chi::Flags
A template class for type-safe flags.
Definition: Flags.hpp:26
NodeType.hpp
Defines the NodeType class.
chi::Context::llvmContext
llvm::LLVMContext & llvmContext()
Get the LLVMContext
Definition: Context.hpp:173
chi::DataType::qualifiedName
std::string qualifiedName() const
Get the qualified name of the type (module().fullName() + ":" name())
Definition: DataType.cpp:8
chi::Context::moduleCache
const ModuleCache & moduleCache() const
Get the module cache.
Definition: Context.hpp:191
chi::ChiModule::dependencies
const std::set< boost::filesystem::path > & dependencies() const
Get the dependencies.
Definition: ChiModule.hpp:83
LangModule.hpp
Defines the LangModule class.
chi::ChiModule::updateLastEditTime
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
chi::Context::typeFromModule
Result typeFromModule(const boost::filesystem::path &module, boost::string_view name, DataType *toFill) noexcept
Gets a DataType from a module.
Definition: Context.cpp:232
chi::Context::compileModule
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
chi::Context::setModuleCache
void setModuleCache(std::unique_ptr< ModuleCache > newCache)
Set the module cache.
Definition: Context.cpp:599
chi::GraphModule
Module that holds graph functions.
Definition: GraphModule.hpp:16
chi::ChiModule::fullNamePath
boost::filesystem::path fullNamePath() const
Get the full name of the module in a path.
Definition: ChiModule.hpp:64
GraphModule.hpp
Defines the GraphModule class.
chi::ChiModule::typeFromName
virtual DataType typeFromName(boost::string_view name)=0
Get a DataType from the name.
chi
The namespace where chigraph lives.
Definition: BitcodeParser.hpp:12
chi::CompileSettings::UseCache
Use the cache in lib.
chi::Context::~Context
~Context()
Destructor.
chi::stringifyLLVMType
std::string stringifyLLVMType(llvm::Type *ty)
Turns a type into a string.
Definition: Context.cpp:474
Context.hpp
Defines the Context class and related functions.
chi::DataType
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
chi::Context::newGraphModule
GraphModule * newGraphModule(const boost::filesystem::path &fullName)
Create a new GraphModule with the given full name.
Definition: Context.cpp:55
chi::ChiModule::lastEditTime
std::time_t lastEditTime() const
Get the time that this module was last edited.
Definition: ChiModule.hpp:101
chi::CompileSettings::LinkDependencies
Link in dependencies If this is set, it will be a ready to run module If not, it&#39;ll contain forward d...
chi::ChiModule::shortName
std::string shortName() const
Get the short name of the module (the last bit)
Definition: ChiModule.hpp:58
chi::Result
The result object, used for identifiying errors with good diagnostics.
Definition: Result.hpp:72
ExecutablePath.hpp
GraphFunction.hpp
Declares the GraphFunction class.
NodeInstance.hpp
Defines the NodeInstance class and related functions.
JsonDeserializer.hpp
Define deserialization functions.
chi::Context::addModuleFromJson
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