GCC Code Coverage Report


Directory: ./
File: openvdb_ax/openvdb_ax/codegen/FunctionTypes.cc
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 163 172 94.8%
Functions: 15 16 93.8%
Branches: 217 320 67.8%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 /// @file codegen/FunctionTypes.cc
5
6 #include "FunctionTypes.h"
7 #include "Types.h"
8 #include "Utils.h"
9
10 #include "../Exceptions.h"
11
12 #include <openvdb/util/Name.h>
13
14 #include <llvm/IR/Function.h>
15 #include <llvm/IR/LLVMContext.h>
16 #include <llvm/Support/raw_os_ostream.h>
17
18 namespace openvdb {
19 OPENVDB_USE_VERSION_NAMESPACE
20 namespace OPENVDB_VERSION_NAME {
21
22 namespace ax {
23 namespace codegen {
24
25 namespace {
26
27 inline void
28 58 printType(const llvm::Type* type, llvm::raw_os_ostream& stream, const bool axTypes)
29 {
30 const ast::tokens::CoreType token =
31
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 14 times.
58 axTypes ? tokenFromLLVMType(type) : ast::tokens::UNKNOWN;
32
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 37 times.
58 if (token == ast::tokens::UNKNOWN) type->print(stream);
33 74 else stream << ast::tokens::typeStringFromToken(token);
34 58 }
35
36 inline void
37
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 12 times.
17 printTypes(llvm::raw_os_ostream& stream,
38 const std::vector<llvm::Type*>& types,
39 const std::vector<const char*>& names = {},
40 const std::string sep = "; ",
41 const bool axTypes = false)
42 {
43
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 12 times.
17 if (types.empty()) return;
44 12 auto typeIter = types.cbegin();
45
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12 std::vector<const char*>::const_iterator nameIter;
46
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12 if (!names.empty()) nameIter = names.cbegin();
47
48
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 12 times.
41 for (; typeIter != types.cend() - 1; ++typeIter) {
49 29 printType(*typeIter, stream, axTypes);
50
4/4
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 1 times.
29 if (!names.empty() && nameIter != names.cend()) {
51
3/4
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 22 times.
26 if (*nameIter && (*nameIter)[0] != '\0') {
52
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
8 stream << ' ' << *nameIter;
53 }
54 ++nameIter;
55 }
56 29 stream << sep;
57 }
58
59 12 printType(*typeIter, stream, axTypes);
60
4/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
12 if (!names.empty() && nameIter != names.cend()) {
61
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
8 if (*nameIter && (*nameIter)[0] != '\0') {
62
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
8 stream << ' ' << *nameIter;
63 }
64 }
65 }
66
67 }
68
69 void
70
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 printSignature(std::ostream& os,
71 const std::vector<llvm::Type*>& signature,
72 const llvm::Type* returnType,
73 const char* name,
74 const std::vector<const char*>& names,
75 const bool axTypes)
76 {
77 17 llvm::raw_os_ostream stream(os);
78
79
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 printType(returnType, stream, axTypes);
80
4/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 2 times.
17 if (name && name[0] != '\0') {
81
2/4
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
13 stream << " " << name;
82 }
83 stream << '(';
84
3/6
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 17 times.
34 printTypes(stream, signature, names, "; ", axTypes);
85 stream << ')';
86 17 }
87
88
89 ///////////////////////////////////////////////////////////////////////////
90 ///////////////////////////////////////////////////////////////////////////
91
92 llvm::Function*
93 47616 Function::create(llvm::LLVMContext& C, llvm::Module* M) const
94 {
95
2/2
✓ Branch 0 taken 47606 times.
✓ Branch 1 taken 10 times.
47616 if (M) {
96
2/2
✓ Branch 1 taken 18732 times.
✓ Branch 2 taken 28874 times.
47606 if (llvm::Function* function = M->getFunction(this->symbol())) {
97 return function;
98 }
99 }
100
101 std::vector<llvm::Type*> parms;
102
1/2
✓ Branch 1 taken 18742 times.
✗ Branch 2 not taken.
18742 parms.reserve(this->size());
103
1/2
✓ Branch 1 taken 18742 times.
✗ Branch 2 not taken.
18742 llvm::Type* ret = this->types(parms, C);
104
105 llvm::FunctionType* type =
106
1/2
✓ Branch 1 taken 18742 times.
✗ Branch 2 not taken.
18742 llvm::FunctionType::get(ret, parms,
107 false); // varargs
108
109 llvm::Function* function =
110
3/4
✓ Branch 2 taken 18742 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4018 times.
✓ Branch 5 taken 14724 times.
18742 llvm::Function::Create(type,
111 llvm::Function::ExternalLinkage,
112 this->symbol(),
113 M);
114
115
2/2
✓ Branch 0 taken 4018 times.
✓ Branch 1 taken 14724 times.
18742 if (!mNames.empty()) {
116 // If some argument names have been specified, name the llvm values.
117 // This provides a more reliable way for function to index into values
118 // rather than relying on their position in the argument vector
119 // @note This does not guarantee that all arguments will have valid
120 // names
121
3/4
✓ Branch 1 taken 4018 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 20809 times.
✓ Branch 4 taken 4018 times.
28845 for (llvm::Argument& arg : function->args()) {
122
2/2
✓ Branch 0 taken 20123 times.
✓ Branch 1 taken 686 times.
20809 const char* name = this->argName(arg.getArgNo());
123
2/6
✓ Branch 0 taken 20809 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 20809 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
20809 if (name) arg.setName(name);
124 }
125 }
126
127
3/4
✓ Branch 1 taken 18742 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18714 times.
✓ Branch 4 taken 28 times.
18742 function->setAttributes(this->flattenAttrs(C));
128 return function;
129 }
130
131 llvm::Function* Function::get(const llvm::Module& M) const
132 {
133 return M.getFunction(this->symbol());
134 }
135
136 llvm::Value*
137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43757 times.
43757 Function::call(const std::vector<llvm::Value*>& args,
138 llvm::IRBuilder<>& B,
139 const bool cast) const
140 {
141 llvm::BasicBlock* block = B.GetInsertBlock();
142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43757 times.
43757 assert(block);
143 llvm::Function* currentFunction = block->getParent();
144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43757 times.
43757 assert(currentFunction);
145 llvm::Module* M = currentFunction->getParent();
146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43757 times.
43757 assert(M);
147 43757 llvm::Function* function = this->create(B.getContext(), M);
148 43757 std::vector<llvm::Value*> inputs(args);
149
2/2
✓ Branch 0 taken 5788 times.
✓ Branch 1 taken 37969 times.
43757 if (cast) {
150 std::vector<llvm::Type*> types;
151
1/2
✓ Branch 1 taken 5788 times.
✗ Branch 2 not taken.
5788 this->types(types, B.getContext());
152
1/2
✓ Branch 1 taken 5788 times.
✗ Branch 2 not taken.
5788 this->cast(inputs, types, B);
153 }
154
3/6
✓ Branch 2 taken 43757 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 43731 times.
✓ Branch 5 taken 26 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
87488 return B.CreateCall(function, inputs);
155 }
156
157 Function::SignatureMatch
158
2/2
✓ Branch 0 taken 293565 times.
✓ Branch 1 taken 105366 times.
398931 Function::match(const std::vector<llvm::Type*>& inputs, llvm::LLVMContext& C) const
159 {
160 // these checks mean we can design the match function signature to not
161 // require the llvm context and instead pull it out of the type vector
162 // which is guaranteed to not be empty
163
2/2
✓ Branch 0 taken 293565 times.
✓ Branch 1 taken 105366 times.
398931 if (inputs.size() != this->size()) return None;
164
3/4
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 293496 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 69 times.
293565 if (inputs.empty() && this->size() == 0) return Explicit;
165
166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 293496 times.
293496 assert(!inputs.empty());
167 //llvm::LLVMContext& C = inputs.front()->getContext();
168
169 std::vector<llvm::Type*> signature;
170
1/2
✓ Branch 1 taken 293496 times.
✗ Branch 2 not taken.
293496 this->types(signature, C);
171
2/2
✓ Branch 1 taken 246461 times.
✓ Branch 2 taken 47035 times.
293496 if (inputs == signature) return Explicit;
172
173
1/2
✓ Branch 1 taken 246461 times.
✗ Branch 2 not taken.
246461 llvm::Type* strType = LLVMType<codegen::String>::get(C);
174
175 // try implicit - signature should not be empty here
176
2/2
✓ Branch 0 taken 1089384 times.
✓ Branch 1 taken 27362 times.
1116746 for (size_t i = 0; i < signature.size(); ++i) {
177
2/2
✓ Branch 0 taken 743819 times.
✓ Branch 1 taken 345565 times.
1089384 llvm::Type* from = inputs[i];
178 1089384 llvm::Type* to = signature[i];
179 // if exactly matching, continue
180
2/2
✓ Branch 0 taken 743819 times.
✓ Branch 1 taken 345565 times.
1089384 if (from == to) continue;
181
182 // if arg is a ptr and is not marked as readonly, fail - memory will be modified
183
4/4
✓ Branch 0 taken 201812 times.
✓ Branch 1 taken 143753 times.
✓ Branch 2 taken 31728 times.
✓ Branch 3 taken 170084 times.
547377 if (to->isPointerTy() && !this->hasParamAttribute(i,
184
2/2
✓ Branch 1 taken 52566 times.
✓ Branch 2 taken 122915 times.
547377 llvm::Attribute::AttrKind::ReadOnly)) return Size;
185
186 // compare contained types if both are pointers
187
4/4
✓ Branch 0 taken 52566 times.
✓ Branch 1 taken 122915 times.
✓ Branch 2 taken 30288 times.
✓ Branch 3 taken 22278 times.
175481 if (from->isPointerTy() && to->isPointerTy()) {
188 from = from->getContainedType(0);
189 to = to->getContainedType(0);
190 }
191
192 // allow for string->char*. Note that this is only allowed from inputs->signature
193
4/4
✓ Branch 0 taken 1418 times.
✓ Branch 1 taken 174063 times.
✓ Branch 2 taken 1105 times.
✓ Branch 3 taken 313 times.
176899 if (from == strType && to == LLVMType<char>::get(C)) continue;
194
2/2
✓ Branch 1 taken 126153 times.
✓ Branch 2 taken 49015 times.
175168 if (!isValidCast(from, to)) return Size;
195 }
196
197 return Implicit;
198 }
199
200 void
201
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 Function::print(llvm::LLVMContext& C,
202 std::ostream& os,
203 const char* name,
204 const bool axTypes) const
205 {
206 std::vector<llvm::Type*> current;
207
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 llvm::Type* ret = this->types(current, C);
208
209 std::vector<const char*> names;
210
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 names.reserve(this->size());
211
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 4 times.
26 for (size_t i = 0; i < this->size(); ++i) {
212
1/4
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
22 names.emplace_back(this->argName(i));
213 }
214
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 printSignature(os, current, ret, name, names, axTypes);
215 4 }
216
217 void
218 5788 Function::cast(std::vector<llvm::Value*>& args,
219 const std::vector<llvm::Type*>& types,
220 llvm::IRBuilder<>& B)
221 {
222 llvm::LLVMContext& C = B.getContext();
223
2/2
✓ Branch 0 taken 31739 times.
✓ Branch 1 taken 5788 times.
37527 for (size_t i = 0; i < args.size(); ++i) {
224
1/2
✓ Branch 0 taken 31739 times.
✗ Branch 1 not taken.
31739 if (i >= types.size()) break;
225 llvm::Value*& value = args[i];
226
2/2
✓ Branch 0 taken 26527 times.
✓ Branch 1 taken 5212 times.
31739 llvm::Type* type = value->getType();
227
2/2
✓ Branch 0 taken 26527 times.
✓ Branch 1 taken 5212 times.
31739 if (type->isIntegerTy() || type->isFloatingPointTy()) {
228
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5464 times.
5464 if (types[i]->isIntegerTy(1)) {
229 // assume boolean target value
230 value = boolComparison(value, B);
231 }
232 else {
233 5464 value = arithmeticConversion(value, types[i], B);
234 }
235 }
236
2/2
✓ Branch 0 taken 7571 times.
✓ Branch 1 taken 18704 times.
26275 else if (type->getContainedType(0)->isArrayTy()) {
237 7571 llvm::Type* arrayType = getBaseContainedType(types[i]);
238 7571 value = arrayCast(value, arrayType->getArrayElementType(), B);
239 }
240 else {
241
2/2
✓ Branch 1 taken 15503 times.
✓ Branch 2 taken 3201 times.
18704 if (types[i] == LLVMType<char*>::get(C)) {
242 15503 llvm::Type* strType = LLVMType<codegen::String>::get(C);
243
2/2
✓ Branch 0 taken 313 times.
✓ Branch 1 taken 15190 times.
15503 if (type->getContainedType(0) == strType) {
244 313 value = B.CreateStructGEP(strType, value, 0); // char**
245 313 value = B.CreateLoad(value); // char*
246 }
247 }
248 }
249 }
250 5788 }
251
252 llvm::AttributeList
253
2/2
✓ Branch 0 taken 3675 times.
✓ Branch 1 taken 15067 times.
18742 Function::flattenAttrs(llvm::LLVMContext& C) const
254 {
255
2/2
✓ Branch 0 taken 3675 times.
✓ Branch 1 taken 15067 times.
18742 if (!mAttributes) return llvm::AttributeList();
256
257 78304 auto buildSetFromKinds = [&C](llvm::AttrBuilder& ab,
258 const std::vector<llvm::Attribute::AttrKind>& kinds)
259 78304 -> llvm::AttributeSet {
260
2/2
✓ Branch 0 taken 119888 times.
✓ Branch 1 taken 78304 times.
198192 for (auto& attr : kinds) {
261 119888 ab.addAttribute(attr);
262 }
263 78304 const llvm::AttributeSet set = llvm::AttributeSet::get(C, ab);
264 78304 ab.clear();
265 78304 return set;
266 15067 };
267
268 llvm::AttrBuilder ab;
269
1/2
✓ Branch 1 taken 15067 times.
✗ Branch 2 not taken.
15067 const llvm::AttributeSet fn = buildSetFromKinds(ab, mAttributes->mFnAttrs);
270
1/2
✓ Branch 1 taken 15067 times.
✗ Branch 2 not taken.
15067 const llvm::AttributeSet ret = buildSetFromKinds(ab, mAttributes->mRetAttrs);
271
272
1/2
✓ Branch 1 taken 15067 times.
✗ Branch 2 not taken.
15067 std::vector<llvm::AttributeSet> parms(this->size());
273
274
2/2
✓ Branch 0 taken 48171 times.
✓ Branch 1 taken 15067 times.
63238 for (auto& idxAttr : mAttributes->mParamAttrs) {
275
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 48170 times.
48171 const size_t idx = idxAttr.first;
276
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 48170 times.
48171 if (idx >= this->size()) continue;
277
1/2
✓ Branch 1 taken 48170 times.
✗ Branch 2 not taken.
48170 parms[idx] = buildSetFromKinds(ab, idxAttr.second);
278 }
279
280
2/6
✓ Branch 1 taken 15067 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15067 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
15067 return llvm::AttributeList::get(C, fn, ret, parms);
281 }
282
283
284 ///////////////////////////////////////////////////////////////////////////
285 ///////////////////////////////////////////////////////////////////////////
286
287
288 llvm::Function*
289
2/2
✓ Branch 0 taken 19182 times.
✓ Branch 1 taken 2 times.
19184 IRFunctionBase::create(llvm::LLVMContext& C, llvm::Module* M) const
290 {
291
2/2
✓ Branch 0 taken 19182 times.
✓ Branch 1 taken 2 times.
19184 if (this->hasEmbedIR()) return nullptr;
292
293 19182 llvm::Function* F = this->Function::create(C, M);
294
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19182 times.
19182 assert(F);
295 // return if the function has already been generated or if no
296 // module has been provided (just the function prototype requested)
297
4/4
✓ Branch 0 taken 8449 times.
✓ Branch 1 taken 10733 times.
✓ Branch 2 taken 8447 times.
✓ Branch 3 taken 2 times.
19182 if (!F->empty() || !M) return F;
298
299 // generate the body
300 llvm::BasicBlock* BB =
301
1/2
✓ Branch 2 taken 8447 times.
✗ Branch 3 not taken.
8447 llvm::BasicBlock::Create(C,
302
3/6
✓ Branch 1 taken 8447 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8447 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 8447 times.
✗ Branch 9 not taken.
16894 "entry_" + std::string(this->symbol()), F);
303
304 std::vector<llvm::Value*> fnargs;
305
1/2
✓ Branch 1 taken 8447 times.
✗ Branch 2 not taken.
8447 fnargs.reserve(this->size());
306 45712 for (auto arg = F->arg_begin(), arg_end = F->arg_end();
307
2/2
✓ Branch 0 taken 45712 times.
✓ Branch 1 taken 8447 times.
54159 arg != arg_end; ++arg) {
308
1/2
✓ Branch 1 taken 45712 times.
✗ Branch 2 not taken.
45712 fnargs.emplace_back(llvm::cast<llvm::Value>(arg));
309 }
310
311 // create a new builder per function (its lightweight)
312 // @todo could pass in the builder similar to Function::call
313
2/4
✓ Branch 1 taken 8447 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
8448 llvm::IRBuilder<> B(BB);
314
1/2
✓ Branch 1 taken 8447 times.
✗ Branch 2 not taken.
8447 llvm::Value* lastInstruction = mGen(fnargs, B);
315
316 // Allow the user to return a nullptr, an actual value or a return
317 // instruction from the generator callback. This facilitates the same
318 // generator being used for inline IR
319
320 // if nullptr, insert a ret void inst, otherwise if it's not a return
321 // instruction, either return the value if its supported or insert a
322 // ret void
323
2/2
✓ Branch 0 taken 2845 times.
✓ Branch 1 taken 5602 times.
8447 if (!lastInstruction) {
324 // @note if the ret type is not expected to be void, this will
325 // cause verifyResultType to throw
326
1/2
✓ Branch 1 taken 2845 times.
✗ Branch 2 not taken.
2845 lastInstruction = B.CreateRetVoid();
327 }
328
2/2
✓ Branch 0 taken 945 times.
✓ Branch 1 taken 4657 times.
5602 else if (!llvm::isa<llvm::ReturnInst>(lastInstruction)) {
329 assert(lastInstruction);
330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 945 times.
945 if (lastInstruction->getType()->isVoidTy()) {
331 lastInstruction = B.CreateRetVoid();
332 }
333 else {
334
1/2
✓ Branch 1 taken 945 times.
✗ Branch 2 not taken.
945 lastInstruction = B.CreateRet(lastInstruction);
335 }
336 }
337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8447 times.
8447 assert(lastInstruction);
338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8447 times.
8447 assert(llvm::isa<llvm::ReturnInst>(lastInstruction));
339
340 // pull out the ret type - is null if void
341 llvm::Value* rvalue =
342 llvm::cast<llvm::ReturnInst>
343 8447 (lastInstruction)->getReturnValue();
344
1/2
✓ Branch 0 taken 954 times.
✗ Branch 1 not taken.
954 llvm::Type* type = rvalue ? rvalue->getType() :
345
1/2
✓ Branch 1 taken 7493 times.
✗ Branch 2 not taken.
7493 llvm::Type::getVoidTy(C);
346
347
2/2
✓ Branch 1 taken 8446 times.
✓ Branch 2 taken 1 times.
8447 this->verifyResultType(type, F->getReturnType());
348 return F;
349 }
350
351
2/2
✓ Branch 0 taken 15363 times.
✓ Branch 1 taken 110 times.
15473 llvm::Value* IRFunctionBase::call(const std::vector<llvm::Value*>& args,
352 llvm::IRBuilder<>& B,
353 const bool cast) const
354 {
355
2/2
✓ Branch 0 taken 15363 times.
✓ Branch 1 taken 110 times.
15473 if (!this->hasEmbedIR()) {
356 15363 return this->Function::call(args, B, cast);
357 }
358
359 110 std::vector<llvm::Value*> inputs(args);
360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
110 if (cast) {
361 std::vector<llvm::Type*> types;
362 this->types(types, B.getContext());
363 this->cast(inputs, types, B);
364 }
365
366
2/2
✓ Branch 1 taken 97 times.
✓ Branch 2 taken 13 times.
110 llvm::Value* result = mGen(inputs, B);
367
1/2
✓ Branch 0 taken 97 times.
✗ Branch 1 not taken.
97 if (result) {
368 // only verify if result is not nullptr to
369 // allow for embedded instructions
370 std::vector<llvm::Type*> unused;
371
1/2
✓ Branch 1 taken 97 times.
✗ Branch 2 not taken.
97 this->verifyResultType(result->getType(),
372
1/2
✓ Branch 1 taken 97 times.
✗ Branch 2 not taken.
97 this->types(unused, B.getContext()));
373 }
374 return result;
375 }
376
377
378 ///////////////////////////////////////////////////////////////////////////
379 ///////////////////////////////////////////////////////////////////////////
380
381
382 const Function*
383 52850 FunctionGroup::match(const std::vector<llvm::Type*>& types,
384 llvm::LLVMContext& C,
385 Function::SignatureMatch* type) const
386 {
387 const Function* targetFunction = nullptr;
388
2/2
✓ Branch 0 taken 43775 times.
✓ Branch 1 taken 9075 times.
52850 if (type) *type = Function::SignatureMatch::None;
389
390
2/2
✓ Branch 0 taken 398422 times.
✓ Branch 1 taken 5792 times.
404214 for (const auto& function : mFunctionList) {
391
392 398422 const Function::SignatureMatch matchtype = function->match(types, C);
393
2/2
✓ Branch 0 taken 382294 times.
✓ Branch 1 taken 16128 times.
780716 if (type) *type = std::max(matchtype, *type);
394
395
2/2
✓ Branch 0 taken 105360 times.
✓ Branch 1 taken 293062 times.
617125 if (matchtype == Function::SignatureMatch::None) continue;
396
2/2
✓ Branch 0 taken 218703 times.
✓ Branch 1 taken 74359 times.
293062 else if (matchtype == Function::SignatureMatch::Size) continue;
397
2/2
✓ Branch 0 taken 47058 times.
✓ Branch 1 taken 27301 times.
74359 else if (matchtype == Function::SignatureMatch::Explicit) {
398 47058 return function.get();
399 }
400
1/2
✓ Branch 0 taken 27301 times.
✗ Branch 1 not taken.
27301 else if (matchtype == Function::SignatureMatch::Implicit) {
401
2/2
✓ Branch 0 taken 14990 times.
✓ Branch 1 taken 12311 times.
27301 if (!targetFunction) targetFunction = function.get();
402 }
403 }
404
405 5792 return targetFunction;
406 }
407
408 llvm::Value*
409
1/2
✓ Branch 1 taken 38806 times.
✗ Branch 2 not taken.
38806 FunctionGroup::execute(const std::vector<llvm::Value*>& args,
410 llvm::IRBuilder<>& B) const
411 {
412 std::vector<llvm::Type*> inputTypes;
413
1/2
✓ Branch 1 taken 38806 times.
✗ Branch 2 not taken.
38806 valuesToTypes(args, inputTypes);
414
415 Function::SignatureMatch match;
416
1/2
✓ Branch 1 taken 38806 times.
✗ Branch 2 not taken.
38806 const Function* target = this->match(inputTypes, B.getContext(), &match);
417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38806 times.
38806 assert(target);
418 llvm::Value* result =
419
2/2
✓ Branch 1 taken 38802 times.
✓ Branch 2 taken 4 times.
38806 target->call(args, B, /*cast=*/match == Function::SignatureMatch::Implicit);
420
421 #ifndef NDEBUG
422 std::vector<llvm::Type*> unused;
423
1/2
✓ Branch 1 taken 38802 times.
✗ Branch 2 not taken.
38802 llvm::Type* ret = target->types(unused, B.getContext());
424
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 38802 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
38802 assert(result || ret->isVoidTy());
425 #endif
426 38802 return result;
427 }
428
429 const Function*
430
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 FunctionGroup::execute(const std::vector<llvm::Value*>& args,
431 llvm::IRBuilder<>& B,
432 llvm::Value*& result) const
433 {
434 std::vector<llvm::Type*> inputTypes;
435
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 valuesToTypes(args, inputTypes);
436
437 Function::SignatureMatch match;
438
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 const Function* target = this->match(inputTypes, B.getContext(), &match);
439
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!target) return nullptr;
440
441 result = target->call(args, B, /*cast=*/match == Function::SignatureMatch::Implicit);
442
443 #ifndef NDEBUG
444 std::vector<llvm::Type*> unused;
445 llvm::Type* ret = target->types(unused, B.getContext());
446 assert(result || ret->isVoidTy());
447 #endif
448
449 return target;
450 }
451
452 } // namespace codegen
453 } // namespace ax
454 } // namespace OPENVDB_VERSION_NAME
455 } // namespace openvdb
456
457