OpenVDB: openvdb_ax/codegen/Utils.h Source File

OpenVDB 12.0.0 |

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