| chigraph master Systems programming language written for beginners in LLVM

GraphStruct.cpp
Go to the documentation of this file.
1
3 #include "chi/GraphStruct.hpp"
4 #include "chi/Context.hpp"
5 #include "chi/GraphModule.hpp"
6 #include "chi/LLVMVersion.hpp"
7 #include "chi/NodeInstance.hpp"
8 #include "chi/NodeType.hpp"
9 #include "chi/Support/Result.hpp"
10
11 #include <llvm/IR/DIBuilder.h>
12 #include <llvm/IR/DebugInfo.h>
13 #include <llvm/IR/DerivedTypes.h>
14
15 #if LLVM_VERSION_LESS_EQUAL(3, 6)
16 #include <llvm/IR/Module.h>
17 #endif
18
19 namespace chi {
20
21 GraphStruct::GraphStruct(GraphModule& mod, std::string name)
22 : mModule{&mod}, mContext{&mod.context()}, mName{std::move(name)} {}
23
24 std::vector<NodeInstance*> GraphStruct::setName(std::string newName, bool updateReferences) {
25 assert(!newName.empty() && "Cannot pass an empty name to GraphStruct::setName");
26
27 module().updateLastEditTime();
28
29 auto oldName = name();
30 mName = std::move(newName);
31
32 // find references to update
33 if (updateReferences) {
34 auto makeInstances =
35 context().findInstancesOfType(module().fullNamePath(), "_make_" + oldName);
36
37 for (auto makeInst : makeInstances) {
38 std::unique_ptr<NodeType> type;
39 auto res = module().nodeTypeFromName("_make_" + name(), {}, &type);
40
41 if (!res) { return {}; }
42
43 makeInst->setType(std::move(type));
44 }
45
46 auto breakInstances =
47 context().findInstancesOfType(module().fullNamePath(), "_break_" + oldName);
48
49 for (auto breakInst : breakInstances) {
50 std::unique_ptr<NodeType> type;
51 auto res = module().nodeTypeFromName("_break_" + name(), {}, &type);
52
53 if (!res) { return {}; }
54
55 breakInst->setType(std::move(type));
56 }
57
58 // append breakInstances to makeInstances so wer can return the updated nodes
59 makeInstances.reserve(breakInstances.size() + makeInstances.size());
60 std::copy(breakInstances.begin(), breakInstances.end(), std::back_inserter(makeInstances));
61
62 return makeInstances;
63 }
64
65 return {};
66 }
67
68 void GraphStruct::addType(DataType ty, std::string name, size_t addBefore, bool updateReferences) {
69 assert(addBefore <= types().size() && ty.valid());
70
71 // invalidate the cache
72 module().updateLastEditTime();
73
74 mTypes.emplace_back(name, ty);
75
76 // invalidate the current DataType
77 mDataType = {};
78
79 if (updateReferences) { updateNodeReferences(); }
80 }
81
82 void GraphStruct::modifyType(size_t id, DataType newTy, std::string newName,
83 bool updateReferences) {
84 assert(id < types().size() && newTy.valid() && !newName.empty());
85
86 // invalidate the cache
87 module().updateLastEditTime();
88
89 mTypes[id] = {std::move(newName), std::move(newTy)};
90
91 // invalidate the current DataType
92 mDataType = {};
93
94 if (updateReferences) { updateNodeReferences(); }
95 }
96
97 void GraphStruct::removeType(size_t id, bool updateReferences) {
98 assert(id < types().size());
99
100 // invalidate the cache
101 module().updateLastEditTime();
102
103 mTypes.erase(mTypes.begin() + id);
104
105 // invalidate the current DataType
106 mDataType = {};
107
108 if (updateReferences) { updateNodeReferences(); }
109 }
110
111 DataType GraphStruct::dataType() {
112 // if we have already calculated this, use that
113 if (mDataType.valid()) { return mDataType; }
114
115 if (types().empty()) { return {}; }
116
117 // create llvm::Type
118 std::vector<llvm::Type*> llTypes;
119 llTypes.reserve(types().size());
120
121 std::vector<
122 #if LLVM_VERSION_LESS_EQUAL(3, 5)
123 llvm::Value*
124 #else
125 llvm::Metadata*
126 #endif
127 >
128 diTypes;
129 diTypes.reserve(types().size());
130
131 size_t currentOffset = 0;
132
133 #if LLVM_VERSION_LESS_EQUAL(3, 6)
134 // make a temp module so we can make a DIBuilder
135 auto tmpMod = std::make_unique<llvm::Module>("tmp", context().llvmContext());
136 auto diBuilder = std::make_unique<llvm::DIBuilder>(*tmpMod);
137 #endif
138
139 for (const auto& type : types()) {
140 auto debugType = type.type.debugType();
141
142 llTypes.push_back(type.type.llvmType());
143
144 auto member =
145 #if LLVM_VERSION_LESS_EQUAL(3, 6)
146 diBuilder->createMemberType(llvm::DIDescriptor(), type.name, llvm::DIFile(), 0,
147 debugType->getSizeInBits(), 8, currentOffset, 0, *debugType)
148 #else
149 llvm::DIDerivedType::get(context().llvmContext(), llvm::dwarf::DW_TAG_member,
150 #if LLVM_VERSION_LESS_EQUAL(3, 8)
151 llvm::MDString::get(context().llvmContext(), type.name),
152 #else
153 type.name,
154 #endif
155 nullptr, 0, nullptr, debugType, debugType->getSizeInBits(), 8,
156 currentOffset,
157 #if LLVM_VERSION_AT_LEAST(5, 0)
158 llvm::None,
159 #endif
160 llvm::DINode::DIFlags{}, nullptr)
161 #endif
162 ;
163
164 diTypes.push_back(member);
165
166 currentOffset += debugType->getSizeInBits();
167 }
168 auto llType = llvm::StructType::create(llTypes, name());
169
170 auto diStructType =
171 #if LLVM_VERSION_LESS_EQUAL(3, 6)
172 new llvm::DICompositeType(diBuilder->createStructType(
173 llvm::DIDescriptor(), name(), llvm::DIFile(), 0, currentOffset, 8, 0, llvm::DIType(),
174 diBuilder->getOrCreateArray(
175 diTypes))); // TODO (#77): yeah this is a memory leak. Fix it.
176 #else
177 llvm::DICompositeType::get(
178 context().llvmContext(), llvm::dwarf::DW_TAG_structure_type, name(), nullptr, 0,
179 nullptr, nullptr, currentOffset, 8, 0, llvm::DINode::DIFlags{},
180 llvm::MDTuple::get(context().llvmContext(), diTypes), 0, nullptr, {}, "")
181 #endif
182 ;
183
184 mDataType = DataType(&module(), name(), llType, diStructType);
185
186 return mDataType;
187 }
188
189 void GraphStruct::updateNodeReferences() {
190 auto makeInstances = context().findInstancesOfType(module().fullNamePath(), "_make_" + name());
191
192 for (auto inst : makeInstances) {
193 // make a make type
194 std::unique_ptr<NodeType> ty;
195 auto res = module().nodeTypeFromName("_make_" + name(), {}, &ty);
196 if (!res) { return; }
197
198 inst->setType(std::move(ty));
199 }
200
201 auto breakInstances =
202 context().findInstancesOfType(module().fullNamePath(), "_break_" + name());
203 for (auto inst : breakInstances) {
204 // make a break type
205 std::unique_ptr<NodeType> ty;
206 auto res = module().nodeTypeFromName("_break_" + name(), {}, &ty);
207 if (!res) { return; }
208
209 inst->setType(std::move(ty));
210 }
211 }
212
213 } // namespace chi
LLVMVersion.hpp
chi::GraphStruct::setName
std::vector< NodeInstance * > setName(std::string newName, bool updateReferences=true)
Set the name of the struct, and optionally update all references in the context.
Definition: GraphStruct.cpp:24
chi::GraphStruct::name
const std::string & name() const
Get the name of the type.
Definition: GraphStruct.hpp:43
chi::GraphStruct::modifyType
void modifyType(size_t id, DataType newTy, std::string newName, bool updateReferences=true)
Change the type and name of a type.
Definition: GraphStruct.cpp:82
Result.hpp
Defines the Result class and related functions.
chi::GraphStruct::module
GraphModule & module() const
Get the module.
Definition: GraphStruct.hpp:30
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::GraphStruct::GraphStruct
GraphStruct(GraphModule &mod, std::string name)
GraphType constructor; don&#39;t use this use GraphModule::newStruct.
Definition: GraphStruct.cpp:21
GraphStruct.hpp
Define GraphStruct.
chi::GraphStruct::context
Context & context() const
Get the context.
Definition: GraphStruct.hpp:26
chi::GraphStruct::dataType
DataType dataType()
Get the DataType of the struct.
Definition: GraphStruct.cpp:111
NodeType.hpp
Defines the NodeType class.
chi::Context::llvmContext
llvm::LLVMContext & llvmContext()
Get the LLVMContext
Definition: Context.hpp:173
chi::GraphStruct::removeType
void removeType(size_t id, bool updateReferences=true)
Remove a type from a struct.
Definition: GraphStruct.cpp:97
chi::GraphStruct::types
const std::vector< NamedDataType > & types() const
Get the types the struct contains.
Definition: GraphStruct.hpp:47
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::GraphModule::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: GraphModule.cpp:606
chi::DataType::valid
bool valid() const
Check if the DataType is valid (if it&#39;s actually bound to a type and module)
Definition: DataType.hpp:44
chi::GraphStruct::addType
void addType(DataType ty, std::string name, size_t addBefore, bool updateReferences=true)
Add a new type to the struct.
Definition: GraphStruct.cpp:68
chi::GraphModule
Module that holds graph functions.
Definition: GraphModule.hpp:16
GraphModule.hpp
Defines the GraphModule class.
chi
The namespace where chigraph lives.
Definition: BitcodeParser.hpp:12
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
NodeInstance.hpp
Defines the NodeInstance class and related functions.