Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright Contributors to the OpenVDB Project | ||
2 | // SPDX-License-Identifier: MPL-2.0 | ||
3 | |||
4 | /// @file codegen/Utils.h | ||
5 | /// | ||
6 | /// @authors Nick Avramoussis | ||
7 | /// | ||
8 | /// @brief Utility code generation methods for performing various llvm | ||
9 | /// operations | ||
10 | /// | ||
11 | |||
12 | #ifndef OPENVDB_AX_CODEGEN_UTILS_HAS_BEEN_INCLUDED | ||
13 | #define OPENVDB_AX_CODEGEN_UTILS_HAS_BEEN_INCLUDED | ||
14 | |||
15 | #include "Types.h" | ||
16 | |||
17 | #include "../ast/Tokens.h" | ||
18 | #include "../Exceptions.h" | ||
19 | |||
20 | #include <openvdb/version.h> | ||
21 | |||
22 | #include <llvm/IR/IRBuilder.h> | ||
23 | #include <llvm/IR/LLVMContext.h> | ||
24 | |||
25 | // Note: As of LLVM 5.0, the llvm::Type::dump() method isn't being | ||
26 | // picked up correctly by the linker. dump() is internally implemented | ||
27 | // using Type::print(llvm::errs()) which is being used in place. See: | ||
28 | // | ||
29 | // https://stackoverflow.com/questions/43723127/llvm-5-0-makefile-undefined-reference-fail | ||
30 | // | ||
31 | #include <llvm/Support/raw_ostream.h> // llvm::errs() | ||
32 | |||
33 | namespace openvdb { | ||
34 | OPENVDB_USE_VERSION_NAMESPACE | ||
35 | namespace OPENVDB_VERSION_NAME { | ||
36 | |||
37 | namespace ax { | ||
38 | namespace codegen { | ||
39 | |||
40 | /// @note Function definitions for some types returned from automatic token to | ||
41 | /// llvm IR operations. See llvmArithmeticConversion and llvmBianryConversion | ||
42 | |||
43 | using CastFunction = std::function<llvm::Value* | ||
44 | (llvm::IRBuilder<>&, llvm::Value*, llvm::Type*)>; | ||
45 | |||
46 | using BinaryFunction = std::function<llvm::Value* | ||
47 | (llvm::IRBuilder<>&, llvm::Value*, llvm::Value*)>; | ||
48 | |||
49 | /// @brief Populate a vector of llvm Types from a vector of llvm values | ||
50 | /// | ||
51 | /// @param values A vector of llvm values to retrieve types from | ||
52 | /// @param types A vector of llvm types to populate | ||
53 | /// | ||
54 | inline void | ||
55 | 43751 | valuesToTypes(const std::vector<llvm::Value*>& values, | |
56 | std::vector<llvm::Type*>& types) | ||
57 | { | ||
58 | 43751 | types.reserve(values.size()); | |
59 |
2/2✓ Branch 0 taken 136905 times.
✓ Branch 1 taken 43751 times.
|
180656 | for (const auto& v : values) { |
60 | 136905 | types.emplace_back(v->getType()); | |
61 | } | ||
62 | 43751 | } | |
63 | |||
64 | /// @brief Prints an llvm type to a std string | ||
65 | /// | ||
66 | /// @param type The llvm type to convert | ||
67 | /// @param str The string to store the type info to | ||
68 | /// | ||
69 | inline void | ||
70 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | llvmTypeToString(const llvm::Type* const type, std::string& str) |
71 | { | ||
72 | 2 | llvm::raw_string_ostream os(str); | |
73 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | type->print(os); |
74 | os.flush(); | ||
75 | 2 | } | |
76 | |||
77 | /// @brief Return the base llvm value which is being pointed to through | ||
78 | /// any number of layered pointers. | ||
79 | /// @note This function does not check for cyclical pointer dependencies | ||
80 | /// | ||
81 | /// @param type A llvm pointer type to traverse | ||
82 | /// | ||
83 | inline llvm::Type* | ||
84 | 7571 | getBaseContainedType(llvm::Type* const type) | |
85 | { | ||
86 | llvm::Type* elementType = type; | ||
87 |
2/2✓ Branch 0 taken 7571 times.
✓ Branch 1 taken 7571 times.
|
15142 | while (elementType->isPointerTy()) { |
88 | elementType = elementType->getContainedType(0); | ||
89 | } | ||
90 | 7571 | return elementType; | |
91 | } | ||
92 | |||
93 | /// @brief Return an llvm value representing a pointer to the provided ptr builtin | ||
94 | /// ValueT. | ||
95 | /// @note This is probably not a suitable solution for anything other than POD | ||
96 | /// types and should be used with caution. | ||
97 | /// | ||
98 | /// @param ptr A pointer to a type of ValueT whose address will be computed and | ||
99 | /// returned | ||
100 | /// @param builder The current llvm IRBuilder | ||
101 | /// | ||
102 | template <typename ValueT> | ||
103 | inline llvm::Value* | ||
104 | llvmPointerFromAddress(const ValueT* const& ptr, | ||
105 | llvm::IRBuilder<>& builder) | ||
106 | { | ||
107 | llvm::Value* address = | ||
108 | llvm::ConstantInt::get(llvm::Type::getIntNTy(builder.getContext(), sizeof(uintptr_t)*8), | ||
109 | reinterpret_cast<uintptr_t>(ptr)); | ||
110 | return builder.CreateIntToPtr(address, LLVMType<ValueT*>::get(builder.getContext())); | ||
111 | } | ||
112 | |||
113 | /// @brief Insert a stack allocation at the beginning of the current function | ||
114 | /// of the provided type and size. The IRBuilder's insertion point must | ||
115 | /// be set to a BasicBlock with a valid Function parent. | ||
116 | /// @note If a size is provided, the size must not depend on any other | ||
117 | /// instructions. If it does, invalid LLVM IR will bb generated. | ||
118 | /// | ||
119 | /// @param B The IRBuilder | ||
120 | /// @param type The type to allocate | ||
121 | /// @param size Optional count of allocations. If nullptr, runs a single allocation | ||
122 | inline llvm::Value* | ||
123 | 35450 | insertStaticAlloca(llvm::IRBuilder<>& B, | |
124 | llvm::Type* type, | ||
125 | llvm::Value* size = nullptr) | ||
126 | { | ||
127 | 35450 | llvm::Type* strtype = LLVMType<codegen::String>::get(B.getContext()); | |
128 | // Create the allocation at the start of the function block | ||
129 | llvm::Function* parent = B.GetInsertBlock()->getParent(); | ||
130 |
2/4✓ Branch 0 taken 35450 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 35450 times.
|
35450 | assert(parent && !parent->empty()); |
131 |
1/2✓ Branch 0 taken 35450 times.
✗ Branch 1 not taken.
|
35450 | auto IP = B.saveIP(); |
132 | llvm::BasicBlock& block = parent->front(); | ||
133 |
2/2✓ Branch 0 taken 3570 times.
✓ Branch 1 taken 31880 times.
|
35450 | if (block.empty()) B.SetInsertPoint(&block); |
134 |
1/2✓ Branch 0 taken 31880 times.
✗ Branch 1 not taken.
|
63760 | else B.SetInsertPoint(&(block.front())); |
135 | 35450 | llvm::Value* result = B.CreateAlloca(type, size); | |
136 | |||
137 | /// @note Strings need to be initialised correctly when they are | ||
138 | /// created. We alloc them at the start of the function but | ||
139 | /// strings in branches may not ever be set to anything. If | ||
140 | /// we don't init these correctly, the clearup frees will | ||
141 | /// try and free uninitialised memory | ||
142 |
2/2✓ Branch 0 taken 1114 times.
✓ Branch 1 taken 34336 times.
|
35450 | if (type == strtype) { |
143 | 1114 | llvm::Value* cptr = B.CreateStructGEP(strtype, result, 0); // char** | |
144 | 1114 | llvm::Value* sso = B.CreateStructGEP(strtype, result, 1); // char[]* | |
145 | 1114 | llvm::Value* sso_load = B.CreateConstGEP2_64(sso, 0 ,0); // char* | |
146 | 1114 | llvm::Value* len = B.CreateStructGEP(strtype, result, 2); | |
147 | 1114 | B.CreateStore(sso_load, cptr); // this->ptr = this->SSO; | |
148 | 1114 | B.CreateStore(B.getInt64(0), len); | |
149 | } | ||
150 | 35450 | B.restoreIP(IP); | |
151 | 35450 | return result; | |
152 | } | ||
153 | |||
154 | inline llvm::Argument* | ||
155 | 28 | extractArgument(llvm::Function* F, const size_t idx) | |
156 | { | ||
157 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | if (!F) return nullptr; |
158 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | if (idx >= F->arg_size()) return nullptr; |
159 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
|
28 | return llvm::cast<llvm::Argument>(F->arg_begin() + idx); |
160 | } | ||
161 | |||
162 | inline llvm::Argument* | ||
163 | 54919 | extractArgument(llvm::Function* F, const std::string& name) | |
164 | { | ||
165 |
1/2✓ Branch 0 taken 54919 times.
✗ Branch 1 not taken.
|
54919 | if (!F) return nullptr; |
166 |
1/2✓ Branch 0 taken 317218 times.
✗ Branch 1 not taken.
|
579517 | for (auto iter = F->arg_begin(); iter != F->arg_end(); ++iter) { |
167 | llvm::Argument* arg = llvm::cast<llvm::Argument>(iter); | ||
168 |
2/2✓ Branch 1 taken 262299 times.
✓ Branch 2 taken 54919 times.
|
317218 | if (arg->getName() == name) return arg; |
169 | } | ||
170 | return nullptr; | ||
171 | } | ||
172 | |||
173 | /// @brief Returns the highest order type from two LLVM Scalar types | ||
174 | /// | ||
175 | /// @param typeA The first scalar llvm type | ||
176 | /// @param typeB The second scalar llvm type | ||
177 | /// | ||
178 | inline llvm::Type* | ||
179 | 28037 | typePrecedence(llvm::Type* const typeA, | |
180 | llvm::Type* const typeB) | ||
181 | { | ||
182 |
3/4✓ Branch 0 taken 28037 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18361 times.
✓ Branch 3 taken 9676 times.
|
28037 | assert(typeA && (typeA->isIntegerTy() || typeA->isFloatingPointTy()) && |
183 | "First Type in typePrecedence is not a scalar type"); | ||
184 |
3/4✓ Branch 0 taken 28037 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21134 times.
✓ Branch 3 taken 6903 times.
|
28037 | assert(typeB && (typeB->isIntegerTy() || typeB->isFloatingPointTy()) && |
185 | "Second Type in typePrecedence is not a scalar type"); | ||
186 | |||
187 | // handle implicit arithmetic conversion | ||
188 | // (http://osr507doc.sco.com/en/tools/clang_conv_implicit.html) | ||
189 | |||
190 |
2/2✓ Branch 0 taken 19089 times.
✓ Branch 1 taken 8948 times.
|
28037 | if (typeA->isDoubleTy()) return typeA; |
191 |
2/2✓ Branch 0 taken 17236 times.
✓ Branch 1 taken 1853 times.
|
19089 | if (typeB->isDoubleTy()) return typeB; |
192 | |||
193 |
2/2✓ Branch 0 taken 8020 times.
✓ Branch 1 taken 9216 times.
|
17236 | if (typeA->isFloatTy()) return typeA; |
194 |
2/2✓ Branch 0 taken 6462 times.
✓ Branch 1 taken 1558 times.
|
8020 | if (typeB->isFloatTy()) return typeB; |
195 | |||
196 |
2/2✓ Branch 1 taken 6230 times.
✓ Branch 2 taken 232 times.
|
6462 | if (typeA->isIntegerTy(64)) return typeA; |
197 |
2/2✓ Branch 1 taken 6206 times.
✓ Branch 2 taken 24 times.
|
6230 | if (typeB->isIntegerTy(64)) return typeB; |
198 | |||
199 |
2/2✓ Branch 1 taken 1355 times.
✓ Branch 2 taken 4851 times.
|
6206 | if (typeA->isIntegerTy(32)) return typeA; |
200 |
2/2✓ Branch 1 taken 224 times.
✓ Branch 2 taken 1131 times.
|
1355 | if (typeB->isIntegerTy(32)) return typeB; |
201 | |||
202 |
2/2✓ Branch 1 taken 216 times.
✓ Branch 2 taken 8 times.
|
224 | if (typeA->isIntegerTy(16)) return typeA; |
203 |
1/2✓ Branch 1 taken 216 times.
✗ Branch 2 not taken.
|
216 | if (typeB->isIntegerTy(16)) return typeB; |
204 | |||
205 |
1/2✓ Branch 1 taken 216 times.
✗ Branch 2 not taken.
|
216 | if (typeA->isIntegerTy(8)) return typeA; |
206 |
1/2✓ Branch 1 taken 216 times.
✗ Branch 2 not taken.
|
216 | if (typeB->isIntegerTy(8)) return typeB; |
207 | |||
208 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 216 times.
|
216 | if (typeA->isIntegerTy(1)) return typeA; |
209 | ✗ | if (typeB->isIntegerTy(1)) return typeB; | |
210 | |||
211 | ✗ | assert(false && "invalid LLVM type precedence"); | |
212 | return nullptr; | ||
213 | } | ||
214 | |||
215 | /// @brief Returns a CastFunction which represents the corresponding instruction | ||
216 | /// to convert a source llvm Type to a target llvm Type. If the conversion | ||
217 | /// is unsupported, throws an error. | ||
218 | /// @warning This assumes any integer types are signed. | ||
219 | /// @param sourceType The source type to cast | ||
220 | /// @param targetType The target type to cast to | ||
221 | /// @param twine An optional string description of the cast function. This can | ||
222 | /// be used for for more verbose llvm information on IR compilation | ||
223 | /// failure | ||
224 | inline CastFunction | ||
225 |
2/2✓ Branch 0 taken 3413 times.
✓ Branch 1 taken 10673 times.
|
14086 | llvmArithmeticConversion(const llvm::Type* const sourceType, |
226 | const llvm::Type* const targetType, | ||
227 | const std::string& twine = "") | ||
228 | { | ||
229 | |||
230 | #define BIND_ARITHMETIC_CAST_OP(Function, Twine) \ | ||
231 | std::bind(&Function, \ | ||
232 | std::placeholders::_1, \ | ||
233 | std::placeholders::_2, \ | ||
234 | std::placeholders::_3, \ | ||
235 | Twine) | ||
236 | |||
237 |
2/2✓ Branch 0 taken 3413 times.
✓ Branch 1 taken 10673 times.
|
14086 | if (targetType->isDoubleTy()) { |
238 |
3/4✓ Branch 0 taken 2592 times.
✓ Branch 1 taken 821 times.
✓ Branch 4 taken 2592 times.
✗ Branch 5 not taken.
|
6005 | if (sourceType->isFloatTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPExt, twine); |
239 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 821 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
821 | else if (sourceType->isHalfTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPExt, twine); |
240 |
3/4✓ Branch 1 taken 52 times.
✓ Branch 2 taken 769 times.
✓ Branch 5 taken 52 times.
✗ Branch 6 not taken.
|
873 | else if (sourceType->isIntegerTy(64)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateSIToFP, twine); |
241 |
3/4✓ Branch 1 taken 709 times.
✓ Branch 2 taken 60 times.
✓ Branch 5 taken 709 times.
✗ Branch 6 not taken.
|
1478 | else if (sourceType->isIntegerTy(32)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateSIToFP, twine); |
242 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
60 | else if (sourceType->isIntegerTy(16)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateSIToFP, twine); |
243 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
60 | else if (sourceType->isIntegerTy(8)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateSIToFP, twine); |
244 |
2/4✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 60 times.
✗ Branch 6 not taken.
|
120 | else if (sourceType->isIntegerTy(1)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateUIToFP, twine); |
245 | } | ||
246 |
2/2✓ Branch 0 taken 1699 times.
✓ Branch 1 taken 8974 times.
|
10673 | else if (targetType->isFloatTy()) { |
247 |
3/4✓ Branch 0 taken 609 times.
✓ Branch 1 taken 1090 times.
✓ Branch 4 taken 609 times.
✗ Branch 5 not taken.
|
2308 | if (sourceType->isDoubleTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPTrunc, twine); |
248 |
3/4✓ Branch 0 taken 349 times.
✓ Branch 1 taken 741 times.
✓ Branch 4 taken 349 times.
✗ Branch 5 not taken.
|
1439 | else if (sourceType->isHalfTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPExt, twine); |
249 |
3/4✓ Branch 1 taken 53 times.
✓ Branch 2 taken 688 times.
✓ Branch 5 taken 53 times.
✗ Branch 6 not taken.
|
794 | else if (sourceType->isIntegerTy(64)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateSIToFP, twine); |
250 |
3/4✓ Branch 1 taken 627 times.
✓ Branch 2 taken 61 times.
✓ Branch 5 taken 627 times.
✗ Branch 6 not taken.
|
1315 | else if (sourceType->isIntegerTy(32)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateSIToFP, twine); |
251 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
61 | else if (sourceType->isIntegerTy(16)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateSIToFP, twine); |
252 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
61 | else if (sourceType->isIntegerTy(8)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateSIToFP, twine); |
253 |
2/4✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 61 times.
✗ Branch 6 not taken.
|
122 | else if (sourceType->isIntegerTy(1)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateUIToFP, twine); |
254 | } | ||
255 |
2/2✓ Branch 0 taken 340 times.
✓ Branch 1 taken 8634 times.
|
8974 | else if (targetType->isHalfTy()) { |
256 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 340 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
340 | if (sourceType->isDoubleTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPTrunc, twine); |
257 |
2/4✓ Branch 0 taken 340 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 340 times.
✗ Branch 5 not taken.
|
680 | else if (sourceType->isFloatTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPTrunc, twine); |
258 | ✗ | else if (sourceType->isIntegerTy(64)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateSIToFP, twine); | |
259 | ✗ | else if (sourceType->isIntegerTy(32)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateSIToFP, twine); | |
260 | ✗ | else if (sourceType->isIntegerTy(16)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateSIToFP, twine); | |
261 | ✗ | else if (sourceType->isIntegerTy(8)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateSIToFP, twine); | |
262 | ✗ | else if (sourceType->isIntegerTy(1)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateUIToFP, twine); | |
263 | } | ||
264 |
2/2✓ Branch 1 taken 886 times.
✓ Branch 2 taken 7748 times.
|
8634 | else if (targetType->isIntegerTy(64)) { |
265 |
3/4✓ Branch 0 taken 20 times.
✓ Branch 1 taken 866 times.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
906 | if (sourceType->isDoubleTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPToSI, twine); |
266 |
3/4✓ Branch 0 taken 9 times.
✓ Branch 1 taken 857 times.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
|
875 | else if (sourceType->isFloatTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPToSI, twine); |
267 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 857 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
857 | else if (sourceType->isHalfTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPToSI, twine); |
268 |
3/4✓ Branch 1 taken 840 times.
✓ Branch 2 taken 17 times.
✓ Branch 5 taken 840 times.
✗ Branch 6 not taken.
|
1697 | else if (sourceType->isIntegerTy(32)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateSExt, twine); |
269 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
17 | else if (sourceType->isIntegerTy(16)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateSExt, twine); |
270 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
17 | else if (sourceType->isIntegerTy(8)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateSExt, twine); |
271 |
2/4✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
|
34 | else if (sourceType->isIntegerTy(1)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateZExt, twine); |
272 | } | ||
273 |
2/2✓ Branch 1 taken 7608 times.
✓ Branch 2 taken 140 times.
|
7748 | else if (targetType->isIntegerTy(32)) { |
274 |
3/4✓ Branch 0 taken 97 times.
✓ Branch 1 taken 7511 times.
✓ Branch 4 taken 97 times.
✗ Branch 5 not taken.
|
7705 | if (sourceType->isDoubleTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPToSI, twine); |
275 |
3/4✓ Branch 0 taken 139 times.
✓ Branch 1 taken 7372 times.
✓ Branch 4 taken 139 times.
✗ Branch 5 not taken.
|
7650 | else if (sourceType->isFloatTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPToSI, twine); |
276 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 7372 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
7372 | else if (sourceType->isHalfTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPToSI, twine); |
277 |
3/4✓ Branch 1 taken 5121 times.
✓ Branch 2 taken 2251 times.
✓ Branch 5 taken 5121 times.
✗ Branch 6 not taken.
|
12493 | else if (sourceType->isIntegerTy(64)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateTrunc, twine); |
278 |
3/4✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2247 times.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
|
2255 | else if (sourceType->isIntegerTy(16)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateSExt, twine); |
279 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 2247 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
2247 | else if (sourceType->isIntegerTy(8)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateSExt, twine); |
280 |
2/4✓ Branch 1 taken 2247 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2247 times.
✗ Branch 6 not taken.
|
4494 | else if (sourceType->isIntegerTy(1)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateZExt, twine); |
281 | } | ||
282 |
1/2✓ Branch 1 taken 140 times.
✗ Branch 2 not taken.
|
140 | else if (targetType->isIntegerTy(16)) { |
283 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
140 | if (sourceType->isDoubleTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPToSI, twine); |
284 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
140 | else if (sourceType->isFloatTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPToSI, twine); |
285 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
140 | else if (sourceType->isHalfTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPToSI, twine); |
286 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 140 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
140 | else if (sourceType->isIntegerTy(64)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateTrunc, twine); |
287 |
3/4✓ Branch 1 taken 132 times.
✓ Branch 2 taken 8 times.
✓ Branch 5 taken 132 times.
✗ Branch 6 not taken.
|
272 | else if (sourceType->isIntegerTy(32)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateTrunc, twine); |
288 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
8 | else if (sourceType->isIntegerTy(8)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateSExt, twine); |
289 |
2/4✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
|
16 | else if (sourceType->isIntegerTy(1)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateZExt, twine); |
290 | } | ||
291 | ✗ | else if (targetType->isIntegerTy(8)) { | |
292 | ✗ | if (sourceType->isDoubleTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPToSI, twine); | |
293 | ✗ | else if (sourceType->isFloatTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPToSI, twine); | |
294 | ✗ | else if (sourceType->isHalfTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPToSI, twine); | |
295 | ✗ | else if (sourceType->isIntegerTy(64)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateTrunc, twine); | |
296 | ✗ | else if (sourceType->isIntegerTy(32)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateTrunc, twine); | |
297 | ✗ | else if (sourceType->isIntegerTy(16)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateTrunc, twine); | |
298 | ✗ | else if (sourceType->isIntegerTy(1)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateZExt, twine); | |
299 | } | ||
300 | ✗ | else if (targetType->isIntegerTy(1)) { | |
301 | ✗ | if (sourceType->isDoubleTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPToUI, twine); | |
302 | ✗ | else if (sourceType->isFloatTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPToUI, twine); | |
303 | ✗ | else if (sourceType->isHalfTy()) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateFPToUI, twine); | |
304 | ✗ | else if (sourceType->isIntegerTy(64)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateTrunc, twine); | |
305 | ✗ | else if (sourceType->isIntegerTy(32)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateTrunc, twine); | |
306 | ✗ | else if (sourceType->isIntegerTy(16)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateTrunc, twine); | |
307 | ✗ | else if (sourceType->isIntegerTy(8)) return BIND_ARITHMETIC_CAST_OP(llvm::IRBuilder<>::CreateTrunc, twine); | |
308 | } | ||
309 | |||
310 | #undef BIND_ARITHMETIC_CAST_OP | ||
311 | ✗ | assert(false && "invalid LLVM type conversion"); | |
312 | return CastFunction(); | ||
313 | } | ||
314 | |||
315 | /// @brief Returns a BinaryFunction representing the corresponding instruction to | ||
316 | /// perform on two scalar values, relative to a provided operator token. Note that | ||
317 | /// not all operations are supported on floating point types! If the token is not | ||
318 | /// supported, or the llvm type is not a scalar type, throws an error. | ||
319 | /// @note Various default arguments are bound to provide a simple function call | ||
320 | /// signature. For floating point operations, this includes a null pointer to | ||
321 | /// the optional metadata node. For integer operations, this includes disabling | ||
322 | /// all overflow/rounding optimisations | ||
323 | /// | ||
324 | /// @param type The type defining the precision of the binary operation | ||
325 | /// @param token The token used to create the relative binary operation | ||
326 | /// @param twine An optional string description of the binary function. This can | ||
327 | /// be used for for more verbose llvm information on IR compilation | ||
328 | /// failure | ||
329 | inline BinaryFunction | ||
330 |
1/2✓ Branch 0 taken 32850 times.
✗ Branch 1 not taken.
|
32850 | llvmBinaryConversion(const llvm::Type* const type, |
331 | const ast::tokens::OperatorToken& token, | ||
332 | const std::string& twine = "") | ||
333 | { | ||
334 | |||
335 | #define BIND_BINARY_OP(Function) \ | ||
336 | [twine](llvm::IRBuilder<>& B, llvm::Value* L, llvm::Value* R) \ | ||
337 | -> llvm::Value* { return B.Function(L, R, twine); } | ||
338 | |||
339 | // NOTE: Binary % and / ops always take sign into account (CreateSDiv vs CreateUDiv, CreateSRem vs CreateURem). | ||
340 | // See http://stackoverflow.com/questions/5346160/llvm-irbuildercreateudiv-createsdiv-createexactudiv | ||
341 | // a%b in AX is implemented as a floored modulo op and is handled explicitly in binaryExpression | ||
342 | |||
343 | if (type->isFloatingPointTy()) { | ||
344 |
2/2✓ Branch 0 taken 4158 times.
✓ Branch 1 taken 11953 times.
|
16111 | assert(!(ast::tokens::operatorType(token) == ast::tokens::LOGICAL || |
345 | ast::tokens::operatorType(token) == ast::tokens::BITWISE) | ||
346 | && "unable to perform logical or bitwise operation on floating point values"); | ||
347 | |||
348 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 4786 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 4786 times.
✓ Branch 10 taken 11325 times.
✓ Branch 13 taken 4786 times.
✗ Branch 14 not taken.
|
35255 | if (token == ast::tokens::PLUS) return BIND_BINARY_OP(CreateFAdd); |
349 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 1349 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 1349 times.
✓ Branch 10 taken 9976 times.
✓ Branch 13 taken 1349 times.
✗ Branch 14 not taken.
|
16721 | else if (token == ast::tokens::MINUS) return BIND_BINARY_OP(CreateFSub); |
350 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 5114 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 5114 times.
✓ Branch 10 taken 4862 times.
✓ Branch 13 taken 5114 times.
✗ Branch 14 not taken.
|
30432 | else if (token == ast::tokens::MULTIPLY) return BIND_BINARY_OP(CreateFMul); |
351 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 588 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 588 times.
✓ Branch 10 taken 4274 times.
✓ Branch 13 taken 588 times.
✗ Branch 14 not taken.
|
7214 | else if (token == ast::tokens::DIVIDE) return BIND_BINARY_OP(CreateFDiv); |
352 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 116 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 116 times.
✓ Branch 10 taken 4158 times.
✓ Branch 13 taken 116 times.
✗ Branch 14 not taken.
|
4738 | else if (token == ast::tokens::MODULO) return BIND_BINARY_OP(CreateFRem); // Note this is NOT a%b in AX. |
353 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 884 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 884 times.
✓ Branch 8 taken 3274 times.
✓ Branch 11 taken 884 times.
✗ Branch 12 not taken.
|
7694 | else if (token == ast::tokens::EQUALSEQUALS) return BIND_BINARY_OP(CreateFCmpOEQ); |
354 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 904 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 904 times.
✓ Branch 8 taken 2370 times.
✓ Branch 11 taken 904 times.
✗ Branch 12 not taken.
|
6890 | else if (token == ast::tokens::NOTEQUALS) return BIND_BINARY_OP(CreateFCmpONE); |
355 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 1136 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1136 times.
✓ Branch 8 taken 1234 times.
✓ Branch 11 taken 1136 times.
✗ Branch 12 not taken.
|
6914 | else if (token == ast::tokens::MORETHAN) return BIND_BINARY_OP(CreateFCmpOGT); |
356 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 300 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 300 times.
✓ Branch 8 taken 934 times.
✓ Branch 11 taken 300 times.
✗ Branch 12 not taken.
|
2434 | else if (token == ast::tokens::LESSTHAN) return BIND_BINARY_OP(CreateFCmpOLT); |
357 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 40 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 40 times.
✓ Branch 8 taken 894 times.
✓ Branch 11 taken 40 times.
✗ Branch 12 not taken.
|
1094 | else if (token == ast::tokens::MORETHANOREQUAL) return BIND_BINARY_OP(CreateFCmpOGE); |
358 |
3/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 894 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 894 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 894 times.
✗ Branch 12 not taken.
|
4470 | else if (token == ast::tokens::LESSTHANOREQUAL) return BIND_BINARY_OP(CreateFCmpOLE); |
359 | ✗ | assert(false && "unrecognised binary operator"); | |
360 | } | ||
361 |
1/2✓ Branch 0 taken 16739 times.
✗ Branch 1 not taken.
|
16739 | else if (type->isIntegerTy()) { |
362 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 1158 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1158 times.
✓ Branch 8 taken 15581 times.
✓ Branch 11 taken 1158 times.
✗ Branch 12 not taken.
|
21371 | if (token == ast::tokens::PLUS) return BIND_BINARY_OP(CreateAdd); // No Unsigned/Signed Wrap |
363 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 960 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 960 times.
✓ Branch 8 taken 14621 times.
✓ Branch 11 taken 960 times.
✗ Branch 12 not taken.
|
19421 | else if (token == ast::tokens::MINUS) return BIND_BINARY_OP(CreateSub); // No Unsigned/Signed Wrap |
364 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 684 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 684 times.
✓ Branch 8 taken 13937 times.
✓ Branch 11 taken 684 times.
✗ Branch 12 not taken.
|
17357 | else if (token == ast::tokens::MULTIPLY) return BIND_BINARY_OP(CreateMul); // No Unsigned/Signed Wrap |
365 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 148 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 148 times.
✓ Branch 10 taken 13789 times.
✓ Branch 13 taken 148 times.
✗ Branch 14 not taken.
|
14529 | else if (token == ast::tokens::DIVIDE) return BIND_BINARY_OP(CreateSDiv); // IsExact = false - when true, poison value if the reuslt is rounded |
366 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 76 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 76 times.
✓ Branch 10 taken 13713 times.
✓ Branch 13 taken 76 times.
✗ Branch 14 not taken.
|
14093 | else if (token == ast::tokens::MODULO) return BIND_BINARY_OP(CreateSRem); // Note this is NOT a%b in AX. |
367 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 1023 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1023 times.
✓ Branch 9 taken 12690 times.
✓ Branch 12 taken 1023 times.
✗ Branch 13 not taken.
|
17805 | else if (token == ast::tokens::EQUALSEQUALS) return BIND_BINARY_OP(CreateICmpEQ); |
368 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 1959 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1959 times.
✓ Branch 9 taken 10731 times.
✓ Branch 12 taken 1959 times.
✗ Branch 13 not taken.
|
20526 | else if (token == ast::tokens::NOTEQUALS) return BIND_BINARY_OP(CreateICmpNE); |
369 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 192 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 192 times.
✓ Branch 9 taken 10539 times.
✓ Branch 12 taken 192 times.
✗ Branch 13 not taken.
|
11499 | else if (token == ast::tokens::MORETHAN) return BIND_BINARY_OP(CreateICmpSGT); |
370 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 324 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 324 times.
✓ Branch 9 taken 10215 times.
✓ Branch 12 taken 324 times.
✗ Branch 13 not taken.
|
11835 | else if (token == ast::tokens::LESSTHAN) return BIND_BINARY_OP(CreateICmpSLT); |
371 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 48 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 48 times.
✓ Branch 9 taken 10167 times.
✓ Branch 12 taken 48 times.
✗ Branch 13 not taken.
|
10407 | else if (token == ast::tokens::MORETHANOREQUAL) return BIND_BINARY_OP(CreateICmpSGE); |
372 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 48 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 48 times.
✓ Branch 9 taken 10119 times.
✓ Branch 12 taken 48 times.
✗ Branch 13 not taken.
|
10359 | else if (token == ast::tokens::LESSTHANOREQUAL) return BIND_BINARY_OP(CreateICmpSLE); |
373 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 1088 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 1088 times.
✓ Branch 10 taken 9031 times.
✓ Branch 13 taken 1088 times.
✗ Branch 14 not taken.
|
14471 | else if (token == ast::tokens::AND) return BIND_BINARY_OP(CreateAnd); |
374 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 2715 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 2715 times.
✓ Branch 10 taken 6316 times.
✓ Branch 13 taken 2715 times.
✗ Branch 14 not taken.
|
19891 | else if (token == ast::tokens::OR) return BIND_BINARY_OP(CreateOr); |
375 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 1563 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1563 times.
✓ Branch 8 taken 4753 times.
✓ Branch 11 taken 1563 times.
✗ Branch 12 not taken.
|
12568 | else if (token == ast::tokens::SHIFTLEFT) return BIND_BINARY_OP(CreateShl); // No Unsigned/Signed Wrap |
376 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 1587 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 1587 times.
✓ Branch 10 taken 3166 times.
✓ Branch 13 taken 1587 times.
✗ Branch 14 not taken.
|
11101 | else if (token == ast::tokens::SHIFTRIGHT) return BIND_BINARY_OP(CreateAShr); // IsExact = false - poison value if any of the bits shifted out are non-zero. |
377 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 3078 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 3078 times.
✓ Branch 10 taken 88 times.
✓ Branch 13 taken 3078 times.
✗ Branch 14 not taken.
|
15478 | else if (token == ast::tokens::BITAND) return BIND_BINARY_OP(CreateAnd); |
378 |
4/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 40 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 40 times.
✓ Branch 10 taken 48 times.
✓ Branch 13 taken 40 times.
✗ Branch 14 not taken.
|
248 | else if (token == ast::tokens::BITOR) return BIND_BINARY_OP(CreateOr); |
379 |
3/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 48 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 48 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 48 times.
✗ Branch 14 not taken.
|
240 | else if (token == ast::tokens::BITXOR) return BIND_BINARY_OP(CreateXor); |
380 | ✗ | assert(false && "unrecognised binary operator"); | |
381 | } | ||
382 | |||
383 | #undef BIND_BINARY_OP | ||
384 | ✗ | assert(false && "invalid LLVM type for binary operation"); | |
385 | return BinaryFunction(); | ||
386 | } | ||
387 | |||
388 | /// @brief Returns true if the llvm Type 'from' can be safely cast to the llvm | ||
389 | /// Type 'to'. | ||
390 | 179852 | inline bool isValidCast(llvm::Type* from, llvm::Type* to) | |
391 | { | ||
392 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 179852 times.
|
179852 | assert(from && "llvm Type 'from' is null in isValidCast"); |
393 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 179852 times.
|
179852 | assert(to && "llvm Type 'to' is null in isValidCast"); |
394 | |||
395 |
4/4✓ Branch 0 taken 59708 times.
✓ Branch 1 taken 120144 times.
✓ Branch 2 taken 18072 times.
✓ Branch 3 taken 109525 times.
|
187305 | if ((from->isIntegerTy() || from->isFloatingPointTy()) && |
396 | (to->isIntegerTy() || to->isFloatingPointTy())) { | ||
397 | return true; | ||
398 | } | ||
399 |
4/4✓ Branch 0 taken 28871 times.
✓ Branch 1 taken 24828 times.
✓ Branch 2 taken 28864 times.
✓ Branch 3 taken 7 times.
|
53699 | if (from->isArrayTy() && to->isArrayTy()) { |
400 | 28864 | llvm::ArrayType* af = llvm::cast<llvm::ArrayType>(from); | |
401 | 28864 | llvm::ArrayType* at = llvm::cast<llvm::ArrayType>(to); | |
402 |
2/2✓ Branch 2 taken 4684 times.
✓ Branch 3 taken 24180 times.
|
28864 | if (af->getArrayNumElements() == at->getArrayNumElements()) { |
403 | 4684 | return isValidCast(af->getArrayElementType(), | |
404 | 4684 | at->getArrayElementType()); | |
405 | } | ||
406 | } | ||
407 | return false; | ||
408 | } | ||
409 | |||
410 | /// @brief Casts a scalar llvm Value to a target scalar llvm Type. Returns | ||
411 | /// the cast scalar value of type targetType. | ||
412 | /// @warning This assumes any integer types are signed. | ||
413 | /// @param value A llvm scalar value to convert | ||
414 | /// @param targetType The target llvm scalar type to convert to | ||
415 | /// @param builder The current llvm IRBuilder | ||
416 | inline llvm::Value* | ||
417 | 92306 | arithmeticConversion(llvm::Value* value, | |
418 | llvm::Type* targetType, | ||
419 | llvm::IRBuilder<>& builder) | ||
420 | { | ||
421 |
3/4✓ Branch 0 taken 92306 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66848 times.
✓ Branch 3 taken 25458 times.
|
92306 | assert(value && (value->getType()->isIntegerTy() || value->getType()->isFloatingPointTy()) && |
422 | "First Value in arithmeticConversion is not a scalar type"); | ||
423 |
3/4✓ Branch 0 taken 92306 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 67951 times.
✓ Branch 3 taken 24355 times.
|
92306 | assert(targetType && (targetType->isIntegerTy() || targetType->isFloatingPointTy()) && |
424 | "Target Type in arithmeticConversion is not a scalar type"); | ||
425 | |||
426 | const llvm::Type* const valueType = value->getType(); | ||
427 |
2/2✓ Branch 0 taken 13551 times.
✓ Branch 1 taken 78755 times.
|
92306 | if (valueType == targetType) return value; |
428 | |||
429 |
2/4✓ Branch 1 taken 13551 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13551 times.
✗ Branch 5 not taken.
|
13551 | CastFunction llvmCastFunction = llvmArithmeticConversion(valueType, targetType); |
430 |
1/2✓ Branch 1 taken 13551 times.
✗ Branch 2 not taken.
|
13551 | return llvmCastFunction(builder, value, targetType); |
431 | } | ||
432 | |||
433 | /// @brief Casts an array to another array of equal size but of a different element | ||
434 | /// type. Both source and target array element types must be scalar types. | ||
435 | /// The source array llvm Value should be a pointer to the array to cast. | ||
436 | /// | ||
437 | /// @param ptrToArray A llvm value which is a pointer to a llvm array | ||
438 | /// @param targetElementType The target llvm scalar type to convert each element | ||
439 | /// of the input array | ||
440 | /// @param builder The current llvm IRBuilder | ||
441 | /// | ||
442 | inline llvm::Value* | ||
443 | 7615 | arrayCast(llvm::Value* ptrToArray, | |
444 | llvm::Type* targetElementType, | ||
445 | llvm::IRBuilder<>& builder) | ||
446 | { | ||
447 |
3/4✓ Branch 0 taken 7615 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2142 times.
✓ Branch 3 taken 5473 times.
|
7615 | assert(targetElementType && (targetElementType->isIntegerTy() || |
448 | targetElementType->isFloatingPointTy()) && | ||
449 | "Target element type is not a scalar type"); | ||
450 |
2/4✓ Branch 0 taken 7615 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7615 times.
|
7615 | assert(ptrToArray && ptrToArray->getType()->isPointerTy() && |
451 | "Input to arrayCast is not a pointer type."); | ||
452 | |||
453 | llvm::Type* arrayType = ptrToArray->getType()->getContainedType(0); | ||
454 |
2/4✓ Branch 0 taken 7615 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7615 times.
|
7615 | assert(arrayType && llvm::isa<llvm::ArrayType>(arrayType)); |
455 | |||
456 | // getArrayElementType() calls getContainedType(0) | ||
457 | llvm::Type* sourceElementType = arrayType->getArrayElementType(); | ||
458 |
3/4✓ Branch 0 taken 7615 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1956 times.
✓ Branch 3 taken 5659 times.
|
7615 | assert(sourceElementType && (sourceElementType->isIntegerTy() || |
459 | sourceElementType->isFloatingPointTy()) && | ||
460 | "Source element type is not a scalar type"); | ||
461 | |||
462 |
2/2✓ Branch 0 taken 290 times.
✓ Branch 1 taken 7325 times.
|
7615 | if (sourceElementType == targetElementType) return ptrToArray; |
463 | |||
464 |
2/4✓ Branch 1 taken 290 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 290 times.
✗ Branch 5 not taken.
|
580 | CastFunction llvmCastFunction = llvmArithmeticConversion(sourceElementType, targetElementType); |
465 | |||
466 | const size_t elementSize = arrayType->getArrayNumElements(); | ||
467 | llvm::Value* targetArray = | ||
468 |
1/2✓ Branch 1 taken 290 times.
✗ Branch 2 not taken.
|
290 | insertStaticAlloca(builder, |
469 |
1/2✓ Branch 1 taken 290 times.
✗ Branch 2 not taken.
|
290 | llvm::ArrayType::get(targetElementType, elementSize)); |
470 | |||
471 |
2/2✓ Branch 0 taken 1050 times.
✓ Branch 1 taken 290 times.
|
1340 | for (size_t i = 0; i < elementSize; ++i) { |
472 | 1050 | llvm::Value* target = builder.CreateConstGEP2_64(targetArray, 0, i); | |
473 | 1050 | llvm::Value* source = builder.CreateConstGEP2_64(ptrToArray, 0, i); | |
474 |
1/4✓ Branch 2 taken 1050 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
1050 | source = builder.CreateLoad(source); |
475 |
1/2✓ Branch 1 taken 1050 times.
✗ Branch 2 not taken.
|
1050 | source = llvmCastFunction(builder, source, targetElementType); |
476 |
1/2✓ Branch 1 taken 1050 times.
✗ Branch 2 not taken.
|
1050 | builder.CreateStore(source, target); |
477 | } | ||
478 | |||
479 | return targetArray; | ||
480 | } | ||
481 | |||
482 | /// @brief Converts a vector of loaded llvm scalar values of the same type to a | ||
483 | /// target scalar type. Each value is converted individually and the loaded | ||
484 | /// result stored in the same location within values. | ||
485 | /// @warning This assumes any integer types are signed. | ||
486 | /// @param values A vector of llvm scalar values to convert | ||
487 | /// @param targetElementType The target llvm scalar type to convert each value | ||
488 | /// of the input vector | ||
489 | /// @param builder The current llvm IRBuilder | ||
490 | inline void | ||
491 | 245 | arithmeticConversion(std::vector<llvm::Value*>& values, | |
492 | llvm::Type* targetElementType, | ||
493 | llvm::IRBuilder<>& builder) | ||
494 | { | ||
495 |
3/4✓ Branch 0 taken 245 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 239 times.
✓ Branch 3 taken 6 times.
|
245 | assert(targetElementType && (targetElementType->isIntegerTy() || |
496 | targetElementType->isFloatingPointTy()) && | ||
497 | "Target element type is not a scalar type"); | ||
498 | |||
499 |
1/2✓ Branch 0 taken 245 times.
✗ Branch 1 not taken.
|
245 | llvm::Type* sourceElementType = values.front()->getType(); |
500 |
3/4✓ Branch 0 taken 245 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 231 times.
✓ Branch 3 taken 14 times.
|
245 | assert(sourceElementType && (sourceElementType->isIntegerTy() || |
501 | sourceElementType->isFloatingPointTy()) && | ||
502 | "Source element type is not a scalar type"); | ||
503 | |||
504 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
|
245 | if (sourceElementType == targetElementType) return; |
505 | |||
506 |
2/4✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 245 times.
✗ Branch 5 not taken.
|
490 | CastFunction llvmCastFunction = llvmArithmeticConversion(sourceElementType, targetElementType); |
507 | |||
508 |
2/2✓ Branch 0 taken 739 times.
✓ Branch 1 taken 245 times.
|
984 | for (llvm::Value*& value : values) { |
509 |
1/2✓ Branch 1 taken 739 times.
✗ Branch 2 not taken.
|
739 | value = llvmCastFunction(builder, value, targetElementType); |
510 | } | ||
511 | } | ||
512 | |||
513 | /// @brief Converts a vector of loaded llvm scalar values to the highest precision | ||
514 | /// type stored amongst them. Any values which are not scalar types are ignored | ||
515 | /// @warning This assumes any integer types are signed. | ||
516 | /// @param values A vector of llvm scalar values to convert | ||
517 | /// @param builder The current llvm IRBuilder | ||
518 | inline void | ||
519 | arithmeticConversion(std::vector<llvm::Value*>& values, | ||
520 | llvm::IRBuilder<>& builder) | ||
521 | { | ||
522 | llvm::Type* typeCast = LLVMType<bool>::get(builder.getContext()); | ||
523 | for (llvm::Value*& value : values) { | ||
524 | llvm::Type* type = value->getType(); | ||
525 | if (type->isIntegerTy() || type->isFloatingPointTy()) { | ||
526 | typeCast = typePrecedence(typeCast, type); | ||
527 | } | ||
528 | } | ||
529 | |||
530 | arithmeticConversion(values, typeCast, builder); | ||
531 | } | ||
532 | |||
533 | /// @brief Chooses the highest order llvm Type as defined by typePrecedence | ||
534 | /// from either of the two incoming values and casts the other value to | ||
535 | /// the choosen type if it is not already. The types of valueA and valueB | ||
536 | /// are guaranteed to match. Both values must be scalar LLVM types | ||
537 | /// @warning This assumes any integer types are signed. | ||
538 | /// @param valueA The first llvm value | ||
539 | /// @param valueB The second llvm value | ||
540 | /// @param builder The current llvm IRBuilder | ||
541 | inline void | ||
542 | arithmeticConversion(llvm::Value*& valueA, | ||
543 | llvm::Value*& valueB, | ||
544 | llvm::IRBuilder<>& builder) | ||
545 | { | ||
546 | llvm::Type* type = typePrecedence(valueA->getType(), valueB->getType()); | ||
547 | valueA = arithmeticConversion(valueA, type, builder); | ||
548 | valueB = arithmeticConversion(valueB, type, builder); | ||
549 | } | ||
550 | |||
551 | /// @brief Performs a C style boolean comparison from a given scalar LLVM value | ||
552 | /// | ||
553 | /// @param value The scalar llvm value to convert to a boolean | ||
554 | /// @param builder The current llvm IRBuilder | ||
555 | /// | ||
556 | inline llvm::Value* | ||
557 |
1/2✓ Branch 0 taken 27164 times.
✗ Branch 1 not taken.
|
27164 | boolComparison(llvm::Value* value, |
558 | llvm::IRBuilder<>& builder) | ||
559 | { | ||
560 | llvm::Type* type = value->getType(); | ||
561 | |||
562 | 80 | if (type->isFloatingPointTy()) return builder.CreateFCmpONE(value, llvm::ConstantFP::get(type, 0.0)); | |
563 |
2/2✓ Branch 1 taken 13128 times.
✓ Branch 2 taken 13996 times.
|
40252 | else if (type->isIntegerTy(1)) return builder.CreateICmpNE(value, llvm::ConstantInt::get(type, 0)); |
564 |
1/2✓ Branch 0 taken 13996 times.
✗ Branch 1 not taken.
|
27992 | else if (type->isIntegerTy()) return builder.CreateICmpNE(value, llvm::ConstantInt::getSigned(type, 0)); |
565 | ✗ | assert(false && "Invalid type for bool conversion"); | |
566 | return nullptr; | ||
567 | } | ||
568 | |||
569 | /// @ brief Performs a binary operation on two loaded llvm scalar values of the same type. | ||
570 | /// The type of operation performed is defined by the token (see the list of supported | ||
571 | /// tokens in ast/Tokens.h. Returns a loaded llvm scalar result | ||
572 | /// | ||
573 | /// @param lhs The left hand side value of the binary operation | ||
574 | /// @param rhs The right hand side value of the binary operation | ||
575 | /// @param token The token representing the binary operation to perform | ||
576 | /// @param builder The current llvm IRBuilder | ||
577 | inline llvm::Value* | ||
578 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32850 times.
|
32850 | binaryOperator(llvm::Value* lhs, llvm::Value* rhs, |
579 | const ast::tokens::OperatorToken& token, | ||
580 | llvm::IRBuilder<>& builder) | ||
581 | { | ||
582 | llvm::Type* lhsType = lhs->getType(); | ||
583 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 32850 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
32850 | assert(lhsType == rhs->getType() || |
584 | (token == ast::tokens::SHIFTLEFT || | ||
585 | token == ast::tokens::SHIFTRIGHT)); | ||
586 | |||
587 |
2/2✓ Branch 0 taken 17871 times.
✓ Branch 1 taken 14979 times.
|
32850 | const ast::tokens::OperatorType opType = ast::tokens::operatorType(token); |
588 | |||
589 | if (opType == ast::tokens::LOGICAL) { | ||
590 | 3803 | lhs = boolComparison(lhs, builder); | |
591 | 3803 | rhs = boolComparison(rhs, builder); | |
592 | lhsType = lhs->getType(); // now bool type | ||
593 | } | ||
594 | |||
595 |
2/4✓ Branch 1 taken 32850 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 32850 times.
✗ Branch 5 not taken.
|
32850 | const BinaryFunction llvmBinaryFunction = llvmBinaryConversion(lhsType, token); |
596 |
1/2✓ Branch 1 taken 32850 times.
✗ Branch 2 not taken.
|
65700 | return llvmBinaryFunction(builder, lhs, rhs); |
597 | } | ||
598 | |||
599 | /// @brief Unpack a particular element of an array and return a pointer to that element | ||
600 | /// The provided llvm Value is expected to be a pointer to an array | ||
601 | /// | ||
602 | /// @param ptrToArray A llvm value which is a pointer to a llvm array | ||
603 | /// @param index The index at which to access the array | ||
604 | /// @param builder The current llvm IRBuilder | ||
605 | /// | ||
606 | inline llvm::Value* | ||
607 | arrayIndexUnpack(llvm::Value* ptrToArray, | ||
608 | const int16_t index, | ||
609 | llvm::IRBuilder<>& builder) | ||
610 | { | ||
611 | return builder.CreateConstGEP2_64(ptrToArray, 0, index); | ||
612 | } | ||
613 | |||
614 | /// @brief Unpack an array type into llvm Values which represent all its elements | ||
615 | /// The provided llvm Value is expected to be a pointer to an array | ||
616 | /// If loadElements is true, values will store loaded llvm values instead | ||
617 | /// of pointers to the array elements | ||
618 | /// | ||
619 | /// @param ptrToArray A llvm value which is a pointer to a llvm array | ||
620 | /// @param values A vector of llvm values where to store the array elements | ||
621 | /// @param builder The current llvm IRBuilder | ||
622 | /// @param loadElements Whether or not to load each array element into a register | ||
623 | /// | ||
624 | inline void | ||
625 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3344 times.
|
3344 | arrayUnpack(llvm::Value* ptrToArray, |
626 | std::vector<llvm::Value*>& values, | ||
627 | llvm::IRBuilder<>& builder, | ||
628 | const bool loadElements = false) | ||
629 | { | ||
630 | const size_t elements = | ||
631 | ptrToArray->getType()->getContainedType(0)->getArrayNumElements(); | ||
632 | |||
633 | 3344 | values.reserve(elements); | |
634 |
2/2✓ Branch 0 taken 15324 times.
✓ Branch 1 taken 3344 times.
|
18668 | for (size_t i = 0; i < elements; ++i) { |
635 | 15324 | llvm::Value* value = builder.CreateConstGEP2_64(ptrToArray, 0, i); | |
636 |
2/2✓ Branch 0 taken 7380 times.
✓ Branch 1 taken 7944 times.
|
15324 | if (loadElements) value = builder.CreateLoad(value); |
637 | 15324 | values.push_back(value); | |
638 | } | ||
639 | 3344 | } | |
640 | |||
641 | /// @brief Unpack the first three elements of an array. | ||
642 | /// The provided llvm Value is expected to be a pointer to an array | ||
643 | /// @note The elements are note loaded | ||
644 | /// | ||
645 | /// @param ptrToArray A llvm value which is a pointer to a llvm array | ||
646 | /// @param value1 The first array value | ||
647 | /// @param value2 The second array value | ||
648 | /// @param value3 The third array value | ||
649 | /// @param builder The current llvm IRBuilder | ||
650 | /// | ||
651 | inline void | ||
652 | array3Unpack(llvm::Value* ptrToArray, | ||
653 | llvm::Value*& value1, | ||
654 | llvm::Value*& value2, | ||
655 | llvm::Value*& value3, | ||
656 | llvm::IRBuilder<>& builder) | ||
657 | { | ||
658 | assert(ptrToArray && ptrToArray->getType()->isPointerTy() && | ||
659 | "Input to array3Unpack is not a pointer type."); | ||
660 | |||
661 | value1 = builder.CreateConstGEP2_64(ptrToArray, 0, 0); | ||
662 | value2 = builder.CreateConstGEP2_64(ptrToArray, 0, 1); | ||
663 | value3 = builder.CreateConstGEP2_64(ptrToArray, 0, 2); | ||
664 | } | ||
665 | |||
666 | /// @brief Pack three values into a new array and return a pointer to the | ||
667 | /// newly allocated array. If the values are of a mismatching type, | ||
668 | /// the highets order type is uses, as defined by typePrecedence. All | ||
669 | /// llvm values are expected to a be a loaded scalar type | ||
670 | /// | ||
671 | /// @param value1 The first array value | ||
672 | /// @param value2 The second array value | ||
673 | /// @param value3 The third array value | ||
674 | /// @param builder The current llvm IRBuilder | ||
675 | /// | ||
676 | inline llvm::Value* | ||
677 | array3Pack(llvm::Value* value1, | ||
678 | llvm::Value* value2, | ||
679 | llvm::Value* value3, | ||
680 | llvm::IRBuilder<>& builder) | ||
681 | { | ||
682 | llvm::Type* type = typePrecedence(value1->getType(), value2->getType()); | ||
683 | type = typePrecedence(type, value3->getType()); | ||
684 | |||
685 | value1 = arithmeticConversion(value1, type, builder); | ||
686 | value2 = arithmeticConversion(value2, type, builder); | ||
687 | value3 = arithmeticConversion(value3, type, builder); | ||
688 | |||
689 | llvm::Type* vectorType = llvm::ArrayType::get(type, 3); | ||
690 | llvm::Value* vector = insertStaticAlloca(builder, vectorType); | ||
691 | |||
692 | llvm::Value* e1 = builder.CreateConstGEP2_64(vector, 0, 0); | ||
693 | llvm::Value* e2 = builder.CreateConstGEP2_64(vector, 0, 1); | ||
694 | llvm::Value* e3 = builder.CreateConstGEP2_64(vector, 0, 2); | ||
695 | |||
696 | builder.CreateStore(value1, e1); | ||
697 | builder.CreateStore(value2, e2); | ||
698 | builder.CreateStore(value3, e3); | ||
699 | |||
700 | return vector; | ||
701 | } | ||
702 | |||
703 | /// @brief Pack a loaded llvm scalar value into a new array of a specified | ||
704 | /// size and return a pointer to the newly allocated array. Each element | ||
705 | /// of the new array will have the value of the given scalar | ||
706 | /// | ||
707 | /// @param value The uniform scalar llvm value to pack into the array | ||
708 | /// @param builder The current llvm IRBuilder | ||
709 | /// @param size The size of the newly allocated array | ||
710 | /// | ||
711 | inline llvm::Value* | ||
712 | 32 | arrayPack(llvm::Value* value, | |
713 | llvm::IRBuilder<>& builder, | ||
714 | const size_t size = 3) | ||
715 | { | ||
716 |
2/4✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
|
32 | assert(value && (value->getType()->isIntegerTy() || |
717 | value->getType()->isFloatingPointTy()) && | ||
718 | "value type is not a scalar type"); | ||
719 | |||
720 | llvm::Type* type = value->getType(); | ||
721 | llvm::Value* array = | ||
722 | 32 | insertStaticAlloca(builder, | |
723 | 32 | llvm::ArrayType::get(type, size)); | |
724 | |||
725 |
2/2✓ Branch 0 taken 96 times.
✓ Branch 1 taken 32 times.
|
128 | for (size_t i = 0; i < size; ++i) { |
726 | 96 | llvm::Value* element = builder.CreateConstGEP2_64(array, 0, i); | |
727 | 96 | builder.CreateStore(value, element); | |
728 | } | ||
729 | |||
730 | 32 | return array; | |
731 | } | ||
732 | |||
733 | /// @brief Pack a vector of loaded llvm scalar values into a new array of | ||
734 | /// equal size and return a pointer to the newly allocated array. | ||
735 | /// | ||
736 | /// @param values A vector of loaded llvm scalar values to pack | ||
737 | /// @param builder The current llvm IRBuilder | ||
738 | /// | ||
739 | inline llvm::Value* | ||
740 | 4028 | arrayPack(const std::vector<llvm::Value*>& values, | |
741 | llvm::IRBuilder<>& builder) | ||
742 | { | ||
743 | 4028 | llvm::Type* type = values.front()->getType(); | |
744 | 4028 | llvm::Value* array = insertStaticAlloca(builder, | |
745 | 4028 | llvm::ArrayType::get(type, values.size())); | |
746 | |||
747 | size_t idx = 0; | ||
748 |
2/2✓ Branch 0 taken 22719 times.
✓ Branch 1 taken 4028 times.
|
26747 | for (llvm::Value* const& value : values) { |
749 | 22719 | llvm::Value* element = builder.CreateConstGEP2_64(array, 0, idx++); | |
750 | 22719 | builder.CreateStore(value, element); | |
751 | } | ||
752 | |||
753 | 4028 | return array; | |
754 | } | ||
755 | |||
756 | /// @brief Pack a vector of loaded llvm scalar values into a new array of | ||
757 | /// equal size and return a pointer to the newly allocated array. | ||
758 | /// arrayPackCast first checks all the contained types in values | ||
759 | /// and casts all types to the highest order type present. All llvm | ||
760 | /// values in values are expected to be loaded scalar types | ||
761 | /// | ||
762 | /// @param values A vector of loaded llvm scalar values to pack | ||
763 | /// @param builder The current llvm IRBuilder | ||
764 | /// | ||
765 | inline llvm::Value* | ||
766 | 3931 | arrayPackCast(std::vector<llvm::Value*>& values, | |
767 | llvm::IRBuilder<>& builder) | ||
768 | { | ||
769 | // get the highest order type present | ||
770 | |||
771 | llvm::Type* type = LLVMType<bool>::get(builder.getContext()); | ||
772 |
2/2✓ Branch 0 taken 21943 times.
✓ Branch 1 taken 3931 times.
|
25874 | for (llvm::Value* const& value : values) { |
773 | 21943 | type = typePrecedence(type, value->getType()); | |
774 | } | ||
775 | |||
776 | // convert all to this type | ||
777 | |||
778 |
2/2✓ Branch 0 taken 21943 times.
✓ Branch 1 taken 3931 times.
|
25874 | for (llvm::Value*& value : values) { |
779 | 21943 | value = arithmeticConversion(value, type, builder); | |
780 | } | ||
781 | |||
782 | 3931 | return arrayPack(values, builder); | |
783 | } | ||
784 | |||
785 | inline llvm::Value* | ||
786 | 118 | scalarToMatrix(llvm::Value* scalar, | |
787 | llvm::IRBuilder<>& builder, | ||
788 | const size_t dim = 3) | ||
789 | { | ||
790 |
3/4✓ Branch 0 taken 118 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 116 times.
✓ Branch 3 taken 2 times.
|
118 | assert(scalar && (scalar->getType()->isIntegerTy() || |
791 | scalar->getType()->isFloatingPointTy()) && | ||
792 | "value type is not a scalar type"); | ||
793 | |||
794 | llvm::Type* type = scalar->getType(); | ||
795 | llvm::Value* array = | ||
796 | 118 | insertStaticAlloca(builder, | |
797 | 118 | llvm::ArrayType::get(type, dim*dim)); | |
798 | |||
799 | 118 | llvm::Value* zero = llvmConstant(0, type); | |
800 |
2/2✓ Branch 0 taken 1426 times.
✓ Branch 1 taken 118 times.
|
1544 | for (size_t i = 0; i < dim*dim; ++i) { |
801 |
2/2✓ Branch 0 taken 1020 times.
✓ Branch 1 taken 406 times.
|
1426 | llvm::Value* m = ((i % (dim+1) == 0) ? scalar : zero); |
802 | 1426 | llvm::Value* element = builder.CreateConstGEP2_64(array, 0, i); | |
803 | 1426 | builder.CreateStore(m, element); | |
804 | } | ||
805 | |||
806 | 118 | return array; | |
807 | } | ||
808 | |||
809 | } // namespace codegen | ||
810 | } // namespace ax | ||
811 | } // namespace OPENVDB_VERSION_NAME | ||
812 | } // namespace openvdb | ||
813 | |||
814 | #endif // OPENVDB_AX_CODEGEN_UTILS_HAS_BEEN_INCLUDED | ||
815 | |||
816 |