19 #include <llvm/IR/DIBuilder.h> 20 #include <llvm/IR/IRBuilder.h> 21 #include <llvm/IR/Module.h> 22 #include <llvm/Linker/Linker.h> 23 #include <llvm/Support/Compiler.h> 24 #include <llvm/Support/FileSystem.h> 25 #include <llvm/Support/MemoryBuffer.h> 26 #include <llvm/Transforms/Utils/Cloning.h> 28 #include <boost/filesystem.hpp> 29 #include <boost/range.hpp> 31 #include <boost/uuid/uuid_io.hpp> 33 namespace fs = boost::filesystem;
39 struct CFuncNode : NodeType {
40 CFuncNode(GraphModule& mod, std::string cCode, std::string functionName,
41 std::vector<std::string> extraArgs, std::vector<NamedDataType> inputs,
43 : NodeType{mod,
"c-call",
"call C code"},
44 mFunctionName{std::move(functionName)},
45 mCCode(std::move(cCode)),
46 mExtraArguments{std::move(extraArgs)},
47 mInputs{std::move(inputs)},
48 mOutput{std::move(output)},
53 setDataInputs(mInputs);
54 if (mOutput.valid()) { setDataOutputs({{
"", mOutput}}); }
57 Result codegen(NodeCompiler& compiler, llvm::BasicBlock& codegenInto,
size_t ,
58 const llvm::DebugLoc& nodeLocation,
const std::vector<llvm::Value*>& io,
59 const std::vector<llvm::BasicBlock*>& outputBlocks)
override {
60 assert(io.size() == dataInputs().size() + dataOutputs().size() && outputBlocks.size() == 1);
65 if (llcompiledmod ==
nullptr) {
66 auto args = mExtraArguments;
70 args.push_back(mGraphModule->pathToCSources().string());
73 fs::path(llvm::sys::fs::getMainExecutable(
nullptr,
nullptr)).parent_path() /
79 context().llvmContext(), args, mCCode, &llcompiledmod);
81 if (!res) {
return res; }
85 auto copymod = llvm::CloneModule(llcompiledmod.get());
89 auto parentModule = &compiler.llvmModule();
91 #if LLVM_VERSION_LESS_EQUAL(3, 7) 92 llvm::Linker::LinkModules(parentModule, copymod
93 #
if LLVM_VERSION_LESS_EQUAL(3, 5)
95 llvm::Linker::DestroySource,
nullptr 99 llvm::Linker::linkModules(*parentModule, std::move(copymod));
102 parentModule->setDataLayout(
"");
104 auto llfunc = parentModule->getFunction(mFunctionName);
105 assert(llfunc !=
nullptr);
107 llvm::IRBuilder<> builder(&codegenInto);
109 size_t ioSize = io.size();
111 std::string outputName;
114 if (!dataOutputs().empty()) {
116 outputName = dataOutputs()[0].name;
119 auto callinst = builder.CreateCall(llfunc, {io.data(), ioSize}, outputName);
120 callinst->setDebugLoc(nodeLocation);
123 if (!dataOutputs().empty()) {
124 auto stoInst = builder.CreateStore(callinst, io[dataInputs().size()]);
125 stoInst->setDebugLoc(nodeLocation);
128 auto brInst = builder.CreateBr(outputBlocks[0]);
129 brInst->setDebugLoc(nodeLocation);
134 nlohmann::json toJSON()
const override {
135 auto j = nlohmann::json{};
137 j = nlohmann::json::object();
139 j[
"function"] = mFunctionName;
141 auto& jsonExtraFlags = j[
"extraflags"];
142 jsonExtraFlags = nlohmann::json::array();
143 for (
const auto& flag : mExtraArguments) { jsonExtraFlags.push_back(flag); }
145 auto& jsonInputs = j[
"inputs"];
146 jsonInputs = nlohmann::json::array();
147 for (
const auto& in : mInputs) {
148 jsonInputs.push_back({{in.name, in.type.qualifiedName()}});
151 if (mOutput.valid()) {
152 j[
"output"] = mOutput.qualifiedName();
154 j[
"output"] = nlohmann::json();
160 std::unique_ptr<NodeType> clone()
const override {
163 return std::make_unique<CFuncNode>(*mGraphModule, mCCode, mFunctionName, mExtraArguments,
167 std::string mFunctionName;
169 std::vector<std::string> mExtraArguments;
170 std::vector<NamedDataType> mInputs;
172 GraphModule* mGraphModule;
174 std::unique_ptr<llvm::Module> llcompiledmod;
177 struct GraphFuncCallType :
public NodeType {
178 GraphFuncCallType(GraphModule& json_module, std::string funcname, Result* resPtr)
179 : NodeType(json_module,
std::move(funcname),
""), JModule(&json_module) {
180 Result& res = *resPtr;
182 auto* mygraph = JModule->functionFromName(name());
183 setDescription(mygraph->description());
185 if (mygraph ==
nullptr) {
186 res.addEntry(
"EINT",
"Graph doesn't exist in module",
187 {{
"Module Name", JModule->fullName()}, {
"Requested Name", name()}});
191 setDataOutputs(mygraph->dataOutputs());
193 setDataInputs(mygraph->dataInputs());
195 setExecInputs(mygraph->execInputs());
196 setExecOutputs(mygraph->execOutputs());
199 Result codegen(NodeCompiler& compiler, llvm::BasicBlock& codegenInto,
size_t execInputID,
200 const llvm::DebugLoc& nodeLocation,
const std::vector<llvm::Value*>& io,
201 const std::vector<llvm::BasicBlock*>& outputBlocks)
override {
204 llvm::IRBuilder<> builder(&codegenInto);
205 builder.SetCurrentDebugLocation(nodeLocation);
207 auto func = compiler.funcCompiler().llvmModule().getFunction(
210 if (func ==
nullptr) {
211 res.addEntry(
"EINT",
"Could not find function in llvm module",
212 {{
"Requested Function", name()}});
217 std::vector<llvm::Value*> passingIO;
218 passingIO.push_back(builder.getInt32(execInputID));
220 std::copy(io.begin(), io.end(), std::back_inserter(passingIO));
222 auto ret = builder.CreateCall(func, passingIO,
"call_function");
225 auto switchInst = builder.CreateSwitch(ret, outputBlocks[0]);
228 for (
auto out : outputBlocks) {
229 switchInst->addCase(builder.getInt32(
id), out);
236 nlohmann::json toJSON()
const override {
return {}; }
237 std::unique_ptr<NodeType> clone()
const override {
239 return std::make_unique<GraphFuncCallType>(*JModule, name(), &res);
242 GraphModule* JModule;
245 struct MakeStructNodeType :
public NodeType {
246 MakeStructNodeType(GraphStruct& ty) : NodeType(ty.module()), mStruct{&ty} {
247 setName(
"_make_" + ty.name());
248 setDescription(
"Make a " + ty.name() +
" structure");
252 setDataInputs(ty.types());
255 setDataOutputs({{
"", ty.dataType()}});
258 Result codegen(NodeCompiler& , llvm::BasicBlock& codegenInto,
259 size_t ,
const llvm::DebugLoc& nodeLocation,
260 const std::vector<llvm::Value*>& io,
261 const std::vector<llvm::BasicBlock*>& outputBlocks)
override {
262 llvm::IRBuilder<> builder{&codegenInto};
263 builder.SetCurrentDebugLocation(nodeLocation);
265 llvm::Value* out = io[io.size() - 1];
266 for (
auto id = 0ull;
id < io.size() - 1; ++id) {
267 auto ptr = builder.CreateStructGEP(
268 #
if LLVM_VERSION_AT_LEAST(3, 7)
269 mStruct->dataType().llvmType(),
272 builder.CreateStore(io[
id], ptr);
275 builder.CreateBr(outputBlocks[0]);
280 nlohmann::json toJSON()
const override {
return {}; }
281 std::unique_ptr<NodeType> clone()
const override {
282 return std::make_unique<MakeStructNodeType>(*mStruct);
285 GraphStruct* mStruct;
288 struct BreakStructNodeType :
public NodeType {
289 BreakStructNodeType(GraphStruct& ty) : NodeType(ty.module()), mStruct{&ty} {
290 setName(
"_break_" + ty.name());
291 setDescription(
"Break a " + ty.name() +
" structure");
295 setDataInputs({{
"", ty.dataType()}});
298 setDataOutputs(ty.types());
301 Result codegen(NodeCompiler& , llvm::BasicBlock& codegenInto,
302 size_t ,
const llvm::DebugLoc& nodeLocation,
303 const std::vector<llvm::Value*>& io,
304 const std::vector<llvm::BasicBlock*>& outputBlocks)
override {
305 llvm::IRBuilder<> builder{&codegenInto};
306 builder.SetCurrentDebugLocation(nodeLocation);
309 auto tempStruct = builder.CreateAlloca(mStruct->dataType().llvmType());
310 builder.CreateStore(io[0], tempStruct);
312 for (
auto id = 1ull;
id < io.size(); ++id) {
313 auto ptr = builder.CreateStructGEP(
314 #
if LLVM_VERSION_AT_LEAST(3, 7)
320 auto val = builder.CreateLoad(ptr);
321 builder.CreateStore(val, io[
id]);
324 builder.CreateBr(outputBlocks[0]);
329 nlohmann::json toJSON()
const override {
return {}; }
330 std::unique_ptr<NodeType> clone()
const override {
331 return std::make_unique<BreakStructNodeType>(*mStruct);
334 GraphStruct* mStruct;
337 struct SetLocalNodeType :
public NodeType {
338 SetLocalNodeType(ChiModule& mod, NamedDataType ty) : NodeType(mod), mDataType{std::move(ty)} {
339 setName(
"_set_" + mDataType.name);
340 setDescription(
"Set " + mDataType.name);
342 setDataInputs({{
"", mDataType.type}});
345 setExecOutputs({
""});
348 Result codegen(NodeCompiler& compiler, llvm::BasicBlock& codegenInto,
size_t ,
349 const llvm::DebugLoc& nodeLocation,
const std::vector<llvm::Value*>& io,
350 const std::vector<llvm::BasicBlock*>& outputBlocks)
override {
351 llvm::IRBuilder<> builder{&codegenInto};
352 builder.SetCurrentDebugLocation(nodeLocation);
354 auto value = compiler.funcCompiler().localVariable(mDataType.name);
355 assert(value !=
nullptr);
358 builder.CreateStore(io[0], value);
360 builder.CreateBr(outputBlocks[0]);
365 nlohmann::json toJSON()
const override {
return mDataType.type.qualifiedName(); }
366 std::unique_ptr<NodeType> clone()
const override {
367 return std::make_unique<SetLocalNodeType>(module(), mDataType);
370 NamedDataType mDataType;
373 struct GetLocalNodeType :
public NodeType {
374 GetLocalNodeType(ChiModule& mod, NamedDataType ty) : NodeType(mod), mDataType{std::move(ty)} {
375 setName(
"_get_" + mDataType.name);
376 setDescription(
"Get " + mDataType.name);
378 setDataOutputs({{
"", mDataType.type}});
383 Result codegen(NodeCompiler& compiler, llvm::BasicBlock& codegenInto,
size_t execInputID,
384 const llvm::DebugLoc& nodeLocation,
const std::vector<llvm::Value*>& io,
385 const std::vector<llvm::BasicBlock*>& outputBlocks)
override {
386 llvm::IRBuilder<> builder{&codegenInto};
387 builder.SetCurrentDebugLocation(nodeLocation);
389 auto value = compiler.funcCompiler().localVariable(mDataType.name);
390 assert(value !=
nullptr);
392 builder.CreateStore(builder.CreateLoad(value), io[0]);
394 builder.CreateBr(outputBlocks[0]);
399 nlohmann::json toJSON()
const override {
return mDataType.type.qualifiedName(); }
400 std::unique_ptr<NodeType> clone()
const override {
401 return std::make_unique<GetLocalNodeType>(module(), mDataType);
404 NamedDataType mDataType;
410 const std::vector<boost::filesystem::path>& dependencies)
417 std::vector<std::string> ret;
418 ret.reserve(structs().size());
420 for (
const auto& ty : structs()) { ret.push_back(ty->name()); }
427 for (
auto& graph : mFunctions) {
429 graph->functionType());
441 if (fs::is_directory(cPath)) {
443 for (
auto direntry : boost::make_iterator_range(
444 fs::recursive_directory_iterator{cPath, fs::symlink_option::recurse}, {})) {
445 const fs::path& CFile = direntry;
447 if (!fs::is_regular_file(CFile) ||
448 !(CFile.extension() ==
".c" || CFile.extension() ==
".C" ||
449 CFile.extension() ==
".cpp" || CFile.extension() ==
".cxx" ||
450 CFile.extension() ==
".c++" || CFile.extension() ==
".cc")) {
455 std::unique_ptr<llvm::Module> generatedModule;
457 fs::path(llvm::sys::fs::getMainExecutable(
nullptr,
nullptr)).parent_path() /
463 context().llvmContext(), {CFile.string()},
"", &generatedModule);
465 if (!res) {
return res; }
469 #if LLVM_VERSION_LESS_EQUAL(3, 7) 470 llvm::Linker::LinkModules(&module, generatedModule.get()
471 #if LLVM_VERSION_LESS_EQUAL(3, 5) 473 llvm::Linker::DestroySource,
nullptr 477 llvm::Linker::linkModules(module, std::move(generatedModule));
484 llvm::DIBuilder debugBuilder(module);
486 auto compileUnit = debugBuilder.createCompileUnit(llvm::dwarf::DW_LANG_C,
487 #
if LLVM_VERSION_LESS_EQUAL(3, 9)
491 debugBuilder.createFile(
495 "Chigraph Compiler",
false,
"", 0);
500 for (
auto& graph : mFunctions) {
502 #
if LLVM_VERSION_LESS_EQUAL(3, 6)
509 debugBuilder.finalize();
518 if (!
context().hasWorkspace()) {
519 res.
addEntry(
"EUKN",
"Cannot serialize without a worksapce", {});
527 fs::create_directories(modulePath.parent_path());
529 }
catch (std::exception& e) {
530 res.
addEntry(
"EUKN",
"Failed to create directoires in workspace",
531 {{
"Module File", modulePath.string()}});
539 fs::ofstream ostr(modulePath);
540 ostr << toFill.dump(2);
546 std::vector<NamedDataType> dataIns,
547 std::vector<NamedDataType> dataOuts,
548 std::vector<std::string> execIns,
549 std::vector<std::string> execOuts,
bool* inserted) {
552 if (foundFunc !=
nullptr) {
553 if (inserted !=
nullptr) { *inserted =
false; }
560 mFunctions.push_back(std::make_unique<GraphFunction>(*
this, std::move(name), std::move(dataIns),
561 std::move(dataOuts), std::move(execIns),
562 std::move(execOuts)));
564 if (inserted !=
nullptr) { *inserted =
true; }
565 return mFunctions[mFunctions.size() - 1].get();
574 if (funcPtr ==
nullptr) {
return false; }
585 if (deleteReferences) {
588 for (
auto node : references) { node->function().removeNode(*node); }
591 auto iter = std::find_if(mFunctions.begin(), mFunctions.end(),
592 [&func](
auto& uPtr) {
return uPtr.get() == &func; });
593 if (iter == mFunctions.end()) {
return; }
595 mFunctions.erase(iter);
599 auto iter = std::find_if(mFunctions.begin(), mFunctions.end(),
600 [&](
auto& ptr) {
return ptr->name() == name; });
602 if (iter != mFunctions.end()) {
return iter->get(); }
607 std::unique_ptr<NodeType>* toFill) {
611 if (
cEnabled() && name ==
"c-call") {
612 if (!jsonData.is_object()) {
613 res.
addEntry(
"WUKN",
"Data for c-call must be an object", {{
"Given Data", jsonData}});
617 if (jsonData.is_object() && jsonData.find(
"code") != jsonData.end() &&
618 jsonData[
"code"].is_string()) {
619 code = jsonData[
"code"];
623 "Data for c-call must have a pair with the key of code and that the data is a " 625 {{
"Given Data", jsonData}});
628 std::string
function;
629 if (jsonData.is_object() && jsonData.find(
"function") != jsonData.end() &&
630 jsonData[
"function"].is_string()) {
631 function = jsonData[
"function"];
635 "Data for c-call must have a pair with the key of function and that the data is a " 637 {{
"Given Data", jsonData}});
640 std::vector<std::string> extraFlags;
641 if (jsonData.is_object() && jsonData.find(
"extraflags") != jsonData.end() &&
642 jsonData[
"extraflags"].is_array()) {
643 for (
const auto& flag : jsonData[
"extraflags"]) {
644 std::string str = flag;
645 extraFlags.emplace_back(std::move(str));
648 res.
addEntry(
"WUKN",
"Data for c-call must have an extraflags array",
649 {{
"Given Data", jsonData}});
652 std::vector<NamedDataType> inputs;
653 if (jsonData.is_object() && jsonData.find(
"inputs") != jsonData.end() &&
654 jsonData[
"inputs"].is_array()) {
655 inputs.reserve(jsonData[
"inputs"].size());
656 for (
const auto& jsonArg : jsonData[
"inputs"]) {
657 std::string docstring, qualifiedName;
660 std::string moduleName, typeName;
666 inputs.emplace_back(docstring, ty);
670 res.
addEntry(
"WUKN",
"Data for c-call must have an inputs array",
671 {{
"Given Data", jsonData}});
675 if (jsonData.is_object() && jsonData.find(
"output") != jsonData.end()) {
676 auto& outputJson = jsonData[
"output"];
679 if (outputJson.is_string()) {
680 std::string moduleName, typeName;
686 else if (!outputJson.is_null()) {
688 R
"("output" element in c-call must be either null or a string)", 689 {{"Given Data", jsonData}});
694 "Data for c-call must have an output element that is either null or a string",
695 {{
"Given Data", jsonData}});
698 *toFill = std::make_unique<CFuncNode>(*
this, code,
function, extraFlags, inputs, output);
701 }
else if (name ==
"c-call") {
702 res.
addEntry(
"EUKN",
"Tried to use a c-call node without c support enabled in the module",
709 if (graph ==
nullptr) {
711 std::string nameStr{name.to_string()};
712 if (nameStr.substr(0, 6) ==
"_make_") {
714 if (str !=
nullptr) {
715 *toFill = std::make_unique<MakeStructNodeType>(*str);
719 if (nameStr.substr(0, 7) ==
"_break_") {
721 if (str !=
nullptr) {
722 *toFill = std::make_unique<BreakStructNodeType>(*str);
726 if (nameStr.substr(0, 5) ==
"_get_") {
727 if (jsonData.is_string()) {
728 std::string module, typeName;
736 std::make_unique<GetLocalNodeType>(*
this,
NamedDataType{nameStr.substr(5), ty});
738 res.
addEntry(
"EUKN",
"Json data for _get_ node type isn't a string",
739 {{
"Given Data", jsonData}});
743 if (nameStr.substr(0, 5) ==
"_set_") {
744 if (jsonData.is_string()) {
745 std::string module, typeName;
752 *toFill = std::make_unique<SetLocalNodeType>(
755 res.
addEntry(
"EUKN",
"Json data for _set_ node type isn't a string",
756 {{
"Given Data", jsonData}});
762 res.
addEntry(
"EUKN",
"Graph not found in module",
763 {{
"Module Name",
fullName()}, {
"Requested Graph", name.to_string()}});
767 *toFill = std::make_unique<GraphFuncCallType>(*
this, name.to_string(), &res);
774 if (func ==
nullptr) {
return {}; }
776 return func->dataType();
780 std::vector<std::string> ret;
781 std::transform(mFunctions.begin(), mFunctions.end(), std::back_inserter(ret),
782 [](
auto& gPtr) {
return gPtr->name(); });
784 for (
const auto& str : structs()) {
785 ret.push_back(
"_make_" + str->name());
786 ret.push_back(
"_break_" + str->name());
789 if (
cEnabled()) { ret.push_back(
"c-call"); }
796 std::vector<NodeInstance*> nodes;
798 for (
const auto& node : f->nodes()) {
799 assert(node.second !=
nullptr);
800 nodes.push_back(node.second.get());
804 std::sort(nodes.begin(), nodes.end(), [](
const auto& lhs,
const auto& rhs) {
805 return (lhs->function().name() +
":" + boost::uuids::to_string(lhs->id())) <
806 (rhs->function().name() +
":" + boost::uuids::to_string(rhs->id()));
809 boost::bimap<unsigned, NodeInstance*> ret;
810 for (
unsigned i = 0; i < nodes.size(); ++i) {
811 ret.left.insert({i + 1, nodes[i]});
818 for (
const auto& str : structs()) {
819 if (str->name() == name) {
return str.get(); }
827 if (str !=
nullptr) {
828 if (inserted !=
nullptr) { *inserted =
false; }
834 mStructs.push_back(std::make_unique<GraphStruct>(*
this, std::move(name)));
836 if (inserted !=
nullptr) { *inserted =
true; }
837 return mStructs[mStructs.size() - 1].get();
844 for (
auto iter = structs().begin(); iter != structs().end(); ++iter) {
845 if ((*iter)->name() == name) {
846 mStructs.erase(iter);
856 assert(&tyToDel.
module() ==
this);
867 boost::string_view functionName,
868 std::vector<std::string> clangArgs,
869 std::unique_ptr<NodeType>* toFill) {
870 assert(toFill !=
nullptr);
875 clangArgs.push_back(
"-I");
878 std::unique_ptr<llvm::Module> mod;
880 compileCToLLVM(fs::path(llvm::sys::fs::getMainExecutable(
nullptr,
nullptr)).parent_path() /
886 context().llvmContext(), clangArgs, code, &mod);
888 if (!res) {
return res; }
890 auto llFunc = mod->getFunction(functionName.to_string());
892 if (llFunc ==
nullptr) {
893 res.
addEntry(
"EUKN",
"Failed to find function in C code",
894 {{
"Function Name", functionName.to_string()}, {
"C Code", code.to_string()}});
898 std::vector<NamedDataType> dInputs;
899 for (
const auto& argument : llFunc->args()) {
902 dInputs.emplace_back(argument.getName(), ty);
906 auto ret = llFunc->getReturnType();
910 *toFill = std::make_unique<CFuncNode>(*
this, code.to_string(), functionName.to_string(),
911 clangArgs, dInputs, output);
Result saveToDisk() const
Serialize to disk in the context.
std::string mangleFunctionName(std::string fullModuleName, const std::string &name)
Mangle a function name.
Define json serialization functions.
this is an AST-like representation of a function in a graph It is used for IDE-like behavior...
Result generateModule(llvm::Module &module) override
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.
const std::string & name() const
Get the name of the type.
boost::filesystem::path pathToCSources() const
Get the path to the .c directory. It is not garunteed to exist, even if cEnabled() is true...
A class holding a compound type defined in a GraphModule.
std::pair< std::string, std::string > parseColonPair(const std::string &in)
Parse a colonated pair Example: lang:i32 would turn into {lang, i32}.
boost::bimap< unsigned, NodeInstance * > createLineNumberAssoc() const
Create the associations from line number and function in debug info.
Defines the Result class and related functions.
const std::vector< std::unique_ptr< GraphFunction > > & functions() const
Get functions.
GraphFunction * functionFromName(boost::string_view name) const
Get a function from the name.
GraphModule & module() const
Get the module.
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.
Defines functions for compiling GraphFunction objects.
boost::filesystem::path workspacePath() const
Get the workspace path of the Context.
Result addDependency(boost::filesystem::path newDepFullPath)
Add a dependency to the module Loads the module from context() if it isn't already loaded...
Definitions for mangling functions.
GraphStruct * structFromName(boost::string_view name) const
Get a struct by name.
std::string name() const
Get the name of the function.
bool removeStruct(boost::string_view name)
Remove a struct from the module by name.
Basicaly a std::pair<std::string, DataType>, except it has nicer names.
GraphFunction * getOrCreateFunction(std::string name, std::vector< NamedDataType > dataIns, std::vector< NamedDataType > dataOuts, std::vector< std::string > execIns, std::vector< std::string > execOuts, bool *inserted=nullptr)
Create a new function if it does't already exist.
std::string fullName() const
Get the full name of the module.
The class that handles the loading, creation, storing, and compilation of modules It also stores a LL...
An abstract class that represents a module of code in Chigraph Can be compiled to a llvm::Module...
boost::filesystem::path sourceFilePath() const
Get the path to the source file It's not garunteed to exist, because it could have not been saved...
bool cEnabled() const
Gets if C support is enabled.
std::vector< std::string > nodeTypeNames() const override
Get the possible node type names.
GraphStruct * getOrCreateStruct(std::string name, bool *inserted=nullptr)
Create a new struct in the module.
Defines the NodeType class.
nlohmann::json graphModuleToJson(const GraphModule &mod)
Serialize a JsonModule to json.
Result compileCToLLVM(const boost::filesystem::path &ctollvmPath, llvm::LLVMContext &llvmContext, std::vector< std::string > arguments, boost::string_view inputCCode, std::unique_ptr< llvm::Module > *toFill)
Use chi-ctollvm to compile C source code to a llvm module It also uses stdCIncludePaths to find basic...
Result compileFunction(const GraphFunction &func, llvm::Module *mod, llvm::DICompileUnit *debugCU, llvm::DIBuilder &debugBuilder)
Compile the graph to an llvm::Function (usually called from JsonModule::generateModule) ...
Result addForwardDeclarations(llvm::Module &module) const override
Adds forward declartions for the functions in this module.
void updateLastEditTime(std::time_t newLastEditTime=std::time(nullptr))
Update the last edit time, signifying that it's been edited.
std::vector< std::string > typeNames() const override
Get the possible DataType names.
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.
GraphModule(Context &cont, boost::filesystem::path fullName, const std::vector< boost::filesystem::path > &dependencies={})
Construct a GraphModule.
DataType typeFromName(boost::string_view name) override
Get a DataType from the name.
Result typeFromModule(const boost::filesystem::path &module, boost::string_view name, DataType *toFill) noexcept
Gets a DataType from a module.
Defines the GraphModule class.
The namespace where chigraph lives.
Context & context() const
Get the Context that this module belongs to.
std::string stringifyLLVMType(llvm::Type *ty)
Turns a type into a string.
Defines the Context class and related functions.
A type of data Loose wrapper around llvm::Type*, except it knows which ChiModule it's in and it embed...
The result object, used for identifiying errors with good diagnostics.
std::pair< std::string, std::string > parseObjectPair(const nlohmann::json &object)
Parse something that looks like: {"hello": "there"} into {"hello", "there"}.
Declares the GraphFunction class.
Defines the NodeInstance class and related functions.
Result createNodeTypeFromCCode(boost::string_view code, boost::string_view functionName, std::vector< std::string > clangArgs, std::unique_ptr< NodeType > *toFill)
From C code, create a NodeType.
bool removeFunction(boost::string_view name, bool deleteReferences=true)
Remove a function from the module.
Define deserialization functions.