OpenVDB  12.0.0
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 
34 namespace openvdb {
36 namespace OPENVDB_VERSION_NAME {
37 
38 namespace ax {
39 namespace 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 ///
118 inline void
119 valuesToTypes(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 ///
133 inline void
134 llvmTypeToString(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 ///
147 inline llvm::Type*
148 getBaseContainedType(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 ///
166 template <typename ValueT>
167 inline llvm::Value*
168 llvmPointerFromAddress(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
186 inline llvm::Value*
187 insertStaticAlloca(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 
218 inline llvm::Argument*
219 extractArgument(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 
226 inline 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 ///
242 inline llvm::Type*
243 typePrecedence(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
288 inline CastFunction
289 llvmArithmeticConversion(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
393 inline BinaryFunction
394 llvmBinaryConversion(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()) {
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
480 inline llvm::Value*
481 arithmeticConversion(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 ///
506 inline llvm::Value*
507 arrayCast(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
554 inline 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
582 inline 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
605 inline 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 ///
620 inline llvm::Value*
621 boolComparison(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
641 inline llvm::Value*
642 binaryOperator(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 
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 ///
670 inline llvm::Value*
671 arrayIndexUnpack(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 ///
688 inline void
689 arrayUnpack(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 ///
715 inline void
716 array3Unpack(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 ///
740 inline llvm::Value*
741 array3Pack(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 ///
775 inline llvm::Value*
776 arrayPack(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 ///
803 inline 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 ///
829 inline llvm::Value*
830 arrayPackCast(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 
849 inline llvm::Value*
850 scalarToMatrix(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 
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
Definition: axparser.h:140
OperatorType
Definition: Tokens.h:200
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
#define BIND_ARITHMETIC_CAST_OP(Function, Twine)
LLVM type mapping from pod types.
Definition: Types.h:55
OperatorType operatorType(const OperatorToken token)
Definition: Tokens.h:210
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
#define BIND_BINARY_OP(Function)
bool isValidCast(llvm::Type *from, llvm::Type *to)
Returns true if the llvm Type &#39;from&#39; can be safely cast to the llvm Type &#39;to&#39;.
Definition: Utils.h:454
Definition: axparser.h:141
Definition: axparser.h:147
std::function< llvm::Value *(llvm::IRBuilder<> &, llvm::Value *, llvm::Type *)> CastFunction
Definition: Utils.h:45
Definition: axparser.h:144
std::function< llvm::Value *(llvm::IRBuilder<> &, llvm::Value *, llvm::Value *)> BinaryFunction
Definition: Utils.h:48
Definition: axparser.h:136
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
Definition: axparser.h:145
Consolidated llvm types for most supported types.
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
llvm::Argument * extractArgument(llvm::Function *F, const std::string &name)
Definition: Utils.h:227
Definition: axparser.h:143
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
llvm::Constant * llvmConstant(const T t, llvm::Type *type)
Returns an llvm Constant holding a scalar value.
Definition: Types.h:329
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
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
void arithmeticConversion(llvm::Value *&valueA, llvm::Value *&valueB, llvm::IRBuilder<> &builder)
Chooses the highest order llvm Type as defined by typePrecedence from either of the two incoming valu...
Definition: Utils.h:606
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
Definition: axparser.h:151
Definition: axparser.h:137
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
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
Definition: axparser.h:146
auto ir_load(llvm::IRBuilder<> &B, llvm::Value *ptr, const char *Name="")
Alias around IR load inst.
Definition: Utils.h:55
llvm::Value * arrayPack(const 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:804
Definition: Exceptions.h:13
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
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. If the values are of a mismatching type, the highets order type is uses, as defined by typePrecedence. All llvm values are expected to a be a loaded scalar type.
Definition: Utils.h:741
Definition: axparser.h:135
Definition: axparser.h:150
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
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
Definition: axparser.h:142
Definition: axparser.h:149
Definition: axparser.h:148
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
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
llvm::Value * scalarToMatrix(llvm::Value *scalar, llvm::IRBuilder<> &builder, const size_t dim=3)
Definition: Utils.h:850
Definition: axparser.h:139
Definition: axparser.h:152
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
Definition: axparser.h:138
llvm::Value * binaryOperator(llvm::Value *lhs, llvm::Value *rhs, const ast::tokens::OperatorToken &token, llvm::IRBuilder<> &builder)
Definition: Utils.h:642
std::string Name
Definition: Name.h:19
void llvmTypeToString(const llvm::Type *const type, std::string &str)
Prints an llvm type to a std string.
Definition: Utils.h:134
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
OperatorToken
Definition: Tokens.h:150
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218