OpenVDB 12.1.0

Loading...
Searching...
No Matches
Value.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/Value.h
5///
6/// @authors Nick Avramoussis
7///
8/// @brief Intermediate representation of supported AX values
9///
10
11#ifndef OPENVDB_AX_CODEGEN_VALUE_HAS_BEEN_INCLUDED
12#define OPENVDB_AX_CODEGEN_VALUE_HAS_BEEN_INCLUDED
13
14#include "Types.h"
15#include "Utils.h"
16
17#include "../ast/AST.h"
18#include "../ast/Tokens.h"
19#include "../compiler/Logger.h"
20
21#include <openvdb/version.h>
22#include <openvdb/util/Assert.h>
23
24#include <llvm/IR/IRBuilder.h>
25#include <llvm/IR/LLVMContext.h>
26
27 namespace openvdb {
28 OPENVDB_USE_VERSION_NAMESPACE
29 namespace OPENVDB_VERSION_NAME {
30
31 namespace ax {
32 namespace codegen {
33
34/// @brief Intermediate representation wrapper for supported value types in AX
35/// as immutable instances.
36///@details This class allows you to generate LLVM IR for common operations
37/// supported by the AX grammar whilst abstracting away a lot of the
38/// complexity of the underlying LLVM state. This class is not meant as a
39/// definitive representation of all possible LLVM IR instructions that can
40/// be emitted, more as a strict helper translation layer for some supported
41/// AX instructions to LLVM IR. More generally, this is intended to be used
42/// for all arithmetic operations and less so for program control flow
43/// (branches, loops, etc). Importantly, this class abstracts away the
44/// concept of ptr/loaded instructions. That is, users of this API usually do
45/// not need to worry about explicitly loading or querying the state of LLVM
46/// IR allocations when calling methods. Instances of Value types also ensure
47/// that the required underlying type information is retained, necessary from
48/// LLVM 15 onwards (due to the introduction of LLVM's opaque ptr changes).
49///
50/// The subset of possible types this class supports are
51/// - void types (for function returns)
52/// - AX scalar values (bool, ints, floats)
53/// - AX array values (element types of ints or floats)
54/// - AX string values
55///
56/// Note that a Value can have a variety of arithmetic type/precision states.
57/// The API of this class does not guaranteed compatibility between all
58/// states. Some failure cases may report a log message and return
59/// Value::Invalid() or generate invalid IR/result in undefined behaviour if
60/// the inputs are not correct. Refer to individual API methods for more
61/// details.
62 class OPENVDB_AX_API Value
63{
64 public:
65 /// @brief Create a Value with a provided underlying type
66 /// @warning This constructor assumes that the underlying type is correct.
67 /// This cannot be asserted from LLVM 15 onwards. This should be used
68 /// sparingly and currently only exists to support some holes in the
69 /// compute generator. This constructor should eventually be removed as
70 /// these get closed, in favour of the static create/alloc methods.
71 Value(llvm::Value* val, llvm::Type* utype)
72 : mVal(val)
73 , mUType(utype) {
74 OPENVDB_ASSERT((!mVal && !mUType) || bool(*this));
75 }
76 /// @brief Initialize from a constant value
77 explicit Value(llvm::Constant* costant)
78 : Value(static_cast<llvm::Value*>(costant), costant->getType()) {}
79
80 Value(const Value&) = default;
81 Value(Value&&) = default;
82 Value& operator=(const Value&) = default;
83 Value& operator=(Value&&) = default;
84
85 /// @brief Return an invalid Value. This is used to represent various fail
86 /// cases. Note that the operator bool(Value) will return false in for
87 /// Value::Invalid
88 static Value Invalid() { return Value(nullptr, nullptr); }
89
90 /// @brief Create an arithmetic literal
91 template <typename ValueType>
92 static Value Create(llvm::LLVMContext& C, const ValueType& value)
93 {
94 return Value(LLVMType<ValueType>::get(C, value),
95 LLVMType<ValueType>::get(C));
96 }
97
98 /// @brief Create a value that represents a return value from a function.
99 /// Really only intended to be used by the function framework. If ret is
100 /// not provided, a void return is created.
101 static Value Return(llvm::IRBuilder<>& B, Value* ret = nullptr)
102 {
103 return ret ? Value(B.CreateRet(ret->GetValue()), B.getVoidTy()) :
104 Value(B.CreateRetVoid(), B.getVoidTy());
105 }
106
107 /// @brief Return true if the underlying type held by utype is supported
108 /// via the interface of this Value class
109 static bool Supports(llvm::Type* utype)
110 {
111 llvm::Type* strtype = LLVMType<codegen::String>::get(utype->getContext());
112 return utype->isVoidTy() ||
113 utype->isIntegerTy() ||
114 utype->isFloatingPointTy() ||
115 utype == strtype ||
116 (utype->isArrayTy() &&
117 (utype->getArrayElementType()->isIntegerTy() ||
118 utype->getArrayElementType()->isFloatingPointTy()));
119 }
120
121 /// @brief Emit IR inserting an allocation at the front of the BasicBlock
122 /// pointed to by the provided IRBuilder. The type is expected to be a
123 /// supported utype.
124 static Value Alloc(llvm::IRBuilder<>& B, llvm::Type* type, llvm::Value* size = nullptr)
125 {
126 OPENVDB_ASSERT(Value::Supports(type));
127 // Create the allocation at the start of the function block
128 llvm::Function* parent = B.GetInsertBlock()->getParent();
129 OPENVDB_ASSERT(parent && !parent->empty());
130 auto IP = B.saveIP();
131 llvm::BasicBlock& block = parent->front();
132 if (block.empty()) B.SetInsertPoint(&block);
133 else B.SetInsertPoint(&(block.front()));
134 llvm::Value* result = B.CreateAlloca(type, size);
135
136 /// @note Strings need to be initialised correctly when they are
137 /// created. We alloc them at the start of the function but
138 /// strings in branches may not ever be set to anything. If
139 /// we don't init these correctly, the clearup frees will
140 /// try and free uninitialised memory
141 llvm::StructType* strtype = LLVMType<codegen::String>::get(B.getContext());
142 if (type == strtype) {
143 llvm::Value* cptr = B.CreateStructGEP(strtype, result, 0); // char**
144 llvm::Value* sso = B.CreateStructGEP(strtype, result, 1); // char[]*
145 OPENVDB_ASSERT(AssertOpaquePtrs(sso, strtype->getTypeAtIndex(1)));
146 llvm::Value* sso_load = B.CreateConstInBoundsGEP2_64(strtype->getTypeAtIndex(1), sso, 0, 0); // char[]
147 llvm::Value* len = B.CreateStructGEP(strtype, result, 2);
148 B.CreateStore(sso_load, cptr); // this->ptr = this->SSO;
149 B.CreateStore(B.getInt64(0), len);
150 }
151 B.restoreIP(IP);
152 return Value(result, type);
153 }
154
155 /// @brief Emit IR to create an array from a set of scalar values. Will
156 /// generate invalid IR if the values are not all scalar or are of
157 /// different precision. values cannot be empty.
158 static Value ScalarsToArray(llvm::IRBuilder<>& B, const std::vector<Value>& values)
159 {
160 OPENVDB_ASSERT(!values.empty());
161
162 llvm::Type* type = values.front().GetUnderlyingType();
163 llvm::Type* arrayType = llvm::ArrayType::get(type, values.size());
164 Value array = Value::Alloc(B, arrayType);
165
166 size_t idx = 0;
167 for (const Value& value : values)
168 {
169 OPENVDB_ASSERT(value);
170 OPENVDB_ASSERT(value.IsScalar());
171 OPENVDB_ASSERT(value.GetUnderlyingType() == type);
172 Value element = array.GetArrayElement(B, idx++);
173 B.CreateStore(value.GetValue(), element.GetValue());
174 }
175
176 return array;
177 }
178
179 /// @brief Create a new zero scalar Value using the underlying scalar
180 /// precision of this Value. Does not generate IR, however will return
181 /// an invalid constant if this Value is a string
182 Value Zero() const
183 {
184 return Value(llvmConstant<uint64_t>(0, this->GetUnderlyingScalarType()));
185 }
186
187 /// @brief Create a new one scalar Value using the underlying scalar
188 /// precision of this Value. Does not generate IR, however will return
189 /// an invalid constant if this Value is a string
190 Value One() const
191 {
192 return Value(llvmConstant<uint64_t>(1, this->GetUnderlyingScalarType()));
193 }
194
195 ///////////////////////////////////////////////////////////////////////////
196 ///////////////////////////////////////////////////////////////////////////
197
198 /// @brief Check if this Value contains an active underlying llvm
199 /// Value/Type. When asserts are enabled. This method strictly checks all
200 /// possible valid combination types of a Value.
201 operator bool() const;
202
203 /// @brief See bool operator
204 bool operator!() const { return !bool(*this); }
205
206 /// @brief Return true if this value represents a void type. This is
207 /// typically only possible for void function returns
208 /// @note Void types are only ever explicitly void, never pointers to void
209 bool IsVoid() const
210 {
211 OPENVDB_ASSERT(*this);
212 return mUType->isVoidTy();
213 }
214
215 /// @brief Return true if the underlying type is a bool type
216 /// @note A bool's underlying state can be either as a pointer or
217 /// loaded. This method returns true in both instances if the underlying
218 /// type is a bool.
219 bool IsBool() const
220 {
221 OPENVDB_ASSERT(*this);
222 return mUType->isIntegerTy(1);
223 }
224
225 /// @brief Return true if the underlying type is a scalar type (bool, int
226 /// or float).
227 /// @note A scalar's underlying state can be either as a pointer or
228 /// loaded. This method returns true in both instances if the underlying
229 /// type is a scalar.
230 bool IsScalar() const
231 {
232 OPENVDB_ASSERT(*this);
233 return (mUType->isIntegerTy() || mUType->isFloatingPointTy());
234 }
235
236 /// @brief Return true if the underlying type is an integer type
237 /// @note A integer's underlying state can be either as a pointer or
238 /// loaded. This method returns true in both instances if the underlying
239 /// type is a integer.
240 bool IsInteger() const
241 {
242 OPENVDB_ASSERT(*this);
243 return mUType->isIntegerTy();
244 }
245
246 /// @brief Return true if the underlying type is an floating point type
247 /// (float or double).
248 /// @note A float's underlying state can be either as a pointer or
249 /// loaded. This method returns true in both instances if the underlying
250 /// type is a float/double.
251 bool IsFloat() const
252 {
253 OPENVDB_ASSERT(*this);
254 return mUType->isFloatingPointTy();
255 }
256
257 /// @brief Return true if the underlying type is an array type
258 /// @note An array type's state is only ever a pointer to an array
259 /// allocation
260 bool IsArray() const
261 {
262 OPENVDB_ASSERT(*this);
263 return mUType->isArrayTy();
264 }
265
266 /// @brief Return true if the underlying type is an vector 2/3/4 type
267 /// @note An vector type's state is only ever a pointer to a vector
268 /// allocation
269 bool IsVector() const
270 {
271 OPENVDB_ASSERT(*this);
272 return mUType->isArrayTy() && !this->IsMatrix();
273 }
274
275 /// @brief Return true if the underlying type is an matrix 3/4 type
276 /// @note An matrix type's state is only ever a pointer to a matrix
277 /// allocation
278 bool IsMatrix() const
279 {
280 OPENVDB_ASSERT(*this);
281 return mUType->isArrayTy() &&
282 // @todo This is dumb, add type-metadata for this
283 (this->GetArrayNumElements() == 9 || this->GetArrayNumElements() == 16);
284 }
285
286 /// @brief Return true if the underlying type is a string type
287 /// @note An string type's state is only ever a pointer to a string
288 /// allocation
289 bool IsString() const
290 {
291 OPENVDB_ASSERT(*this);
292 return mUType == LLVMType<codegen::String>::get(mUType->getContext());
293 }
294
295 /// @brief Return true if this Value is a pointer type
296 bool IsPtr() const
297 {
298 OPENVDB_ASSERT(*this);
299 return mVal->getType()->isPointerTy();
300 }
301
302 /// @brief Return true if this Value is a constant
303 bool IsConstant() const
304 {
305 return bool(llvm::dyn_cast<llvm::Constant>(this->GetValue()));
306 }
307
308 /// @brief Return the number of elements in this array type
309 size_t GetArrayNumElements() const
310 {
311 OPENVDB_ASSERT(this->IsArray());
312 return mUType->getArrayNumElements();
313 }
314
315 ///////////////////////////////////////////////////////////////////////////
316 ///////////////////////////////////////////////////////////////////////////
317
318 // The following method generate IR and return new Value instances
319
320 /// @brief Emit IR to check whether this value is NaN. Only works on Float
321 /// types and will generate invalid IR if this Value is not a Float
322 /// instance.
323 Value IsNan(llvm::IRBuilder<>& B) const
324 {
325 OPENVDB_ASSERT(*this);
326 OPENVDB_ASSERT(this->IsFloat());
327 Value self = this->LoadIfPtr(B);
328 llvm::Value* result = B.CreateFCmpUNO(self.GetValue(), self.GetValue());
329 return Value(result, result->getType());
330 }
331
332 /// @brief Emit IR to load the current value. Not typically required to
333 /// call directly. Will generate invalid IR if this Value is not a Ptr.
334 /// @warning Should only ever be called for ptrs to scalar types
335 Value Load(llvm::IRBuilder<>& B) const
336 {
337 OPENVDB_ASSERT(*this);
338 OPENVDB_ASSERT(this->IsPtr());
339 OPENVDB_ASSERT(this->IsScalar()); // Should only be loading scalars
340 return Value(B.CreateLoad(mUType, mVal), mUType);
341 }
342
343 /// @brief Emit IR to load the current value if it is a ptr. Not typically
344 /// required to call directly.
345 /// @warning Should only ever be called for ptrs to scalar types
346 Value LoadIfPtr(llvm::IRBuilder<>& B) const
347 {
348 OPENVDB_ASSERT(*this);
349 OPENVDB_ASSERT(this->IsScalar()); // Should only be loading scalars
350 return this->IsPtr() ? this->Load(B) : *this;
351 }
352
353 /// @brief Emit IR to return a scalar at the provided index from this
354 /// array value. Will generate invalid IR if this Value is not an array
355 /// or if idx is not an integer.
356 Value GetArrayElement(llvm::IRBuilder<>& B, Value idx) const
357 {
358 OPENVDB_ASSERT(*this);
359 OPENVDB_ASSERT(this->IsArray());
360 OPENVDB_ASSERT(idx.IsInteger());
361 idx = idx.LoadIfPtr(B);
362 if (this->IsPtr()) {
363 Value zero = idx.Zero(); // same int precision as idx
364 return Value(B.CreateInBoundsGEP(mUType, mVal, {zero.GetValue(), idx.GetValue()}), mUType->getArrayElementType());
365 }
366 else {
367 OPENVDB_ASSERT(this->IsConstant());
368 return Value(B.CreateInBoundsGEP(mUType, mVal, {idx.GetValue()}), mUType->getArrayElementType());
369 }
370 }
371
372 /// @brief Emit IR to return a scalar at the provided index from this
373 /// array value. Will generate invalid IR if this Value is not an array.
374 Value GetArrayElement(llvm::IRBuilder<>& B, uint64_t idx) const
375 {
376 OPENVDB_ASSERT(*this);
377 OPENVDB_ASSERT(this->IsArray());
378 OPENVDB_ASSERT(idx < this->GetArrayNumElements());
379 if (this->IsPtr()) {
380 return Value(B.CreateConstInBoundsGEP2_64(mUType, mVal, uint64_t(0), idx), mUType->getArrayElementType());
381 }
382 else {
383 OPENVDB_ASSERT(this->IsConstant());
384 return Value(B.CreateConstInBoundsGEP1_64(mUType, mVal, idx), mUType->getArrayElementType());
385 }
386 }
387
388 /// @brief Emit IR to extract scalar values from the elements in this
389 /// array and populate the provided vector with them. The scalars are
390 /// additionally loaded if load is true. Will generate invalid IR if this
391 /// is not an array
392 void ArrayToScalars(llvm::IRBuilder<>& B,
393 std::vector<Value>& elements,
394 const bool load = false) const
395 {
396 OPENVDB_ASSERT(*this);
397 OPENVDB_ASSERT(this->IsArray());
398
399 const size_t size = this->GetArrayNumElements();
400 elements.reserve(size);
401
402 for (size_t i = 0; i < size; ++i)
403 {
404 Value elem = this->GetArrayElement(B, i);
405 if (load) elem = elem.Load(B);
406 OPENVDB_ASSERT(elem);
407 elements.emplace_back(elem);
408 }
409
410 OPENVDB_ASSERT(!elements.empty());
411 }
412
413 /// @brief Emit IR to broadcast this scalar to a new array. Will generated
414 /// invalid IR if this is not a scalar or if size is zero.
415 /// @warning This fills the array with the current scalar value. It does
416 /// NOT do scalar->matrix promotion.
417 Value ScalarToArray(llvm::IRBuilder<>& B, size_t size) const
418 {
419 OPENVDB_ASSERT(*this);
420 OPENVDB_ASSERT_MESSAGE(this->IsScalar(), "value type is not a scalar type");
421 Value scalar = this->LoadIfPtr(B);
422
423 llvm::Type* type = llvm::ArrayType::get(scalar.GetUnderlyingType(), size);
424 Value array = Value::Alloc(B, type);
425 for (size_t i = 0; i < size; ++i) {
426 Value element = array.GetArrayElement(B, i);
427 B.CreateStore(scalar.GetValue(), element.GetValue());
428 }
429 return array;
430 }
431
432 /// @brief Emit IR to create a new 3x3 matrix from this scalar value,
433 /// adhering to scalar->matrix promotion rules. Will generate invalid IR
434 /// if this is not a scalar value.
435 Value ScalarToIdentMatrix3(llvm::IRBuilder<>& B) const
436 {
437 return this->ScalarToIdentMatrixN<3>(B);
438 }
439
440 /// @brief Emit IR to create a new 4x4 matrix from this scalar value,
441 /// adhering to scalar->matrix promotion rules. Will generate invalid IR
442 /// if this is not a scalar value.
443 Value ScalarToIdentMatrix4(llvm::IRBuilder<>& B) const
444 {
445 return this->ScalarToIdentMatrixN<4>(B);
446 }
447
448 /// @brief Emit IR to perform standard boolean comparison on this scalar
449 /// i.e. bool(scalar) or bool(scalar == 0). Returns a Value of type bool.
450 /// Will return Value::Invalid() if this is not a bool/int/float.
451 Value ScalarBoolComparison(llvm::IRBuilder<>& B) const;
452
453 /// @brief Emit IR to select a value based on this boolean scalar value.
454 /// Will generate invalid IR if this is not a boolean value, or if
455 /// trueval and falseval have different types.
456 Value Select(llvm::IRBuilder<>& B, const Value& trueval, const Value& falseval) const;
457
458 /// @brief Emit IR to cast this scalar or array to a new value of the
459 /// provided scalar precision. Returns a new value of the same class type
460 /// (scalar or array) but with a new precision. Will generate invalid IR
461 /// if the precision is not an integer or floating point precision type.
462 /// If this is not an array or scalar, no IR is emitted and
463 /// Value::Invalid() is returned. Additionally, if the provided precision
464 /// is the same as this scalar/array's underlying precision, no IR is
465 /// emitted and no new value is created.
466 Value CastToPrecision(llvm::IRBuilder<>& B, llvm::Type* precision) const;
467
468 ///////////////////////////////////////////////////////////////////////////
469 ///////////////////////////////////////////////////////////////////////////
470
471 // Unary IR emission
472
473 /// @brief Emit IR to create a unary not instruction on this scalar or
474 /// integer array (i.e. !value). If the value is not a int/float/integer
475 /// array, no IR is emitted, a warning is logged (if a logger is provided)
476 /// and Value::Invalid is returned.
477 Value Not(llvm::IRBuilder<>& B, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const;
478
479 /// @brief Emit IR to create a unary not instruction on this integer or
480 /// integer array (i.e. ~value). If the value is not a int/integer array,
481 /// no IR is emitted, a warning is logged (if a logger is provided) and
482 /// Value::Invalid is returned.
483 Value BitNot(llvm::IRBuilder<>& B, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const;
484
485 /// @brief Emit IR to create a unary not instruction on this scalar or
486 /// array (i.e. -value). If the value is not a int/float/array, no IR is
487 /// is emitted, a warning is logged (if a logger is provided) and
488 /// Value::Invalid is returned.
489 Value Negate(llvm::IRBuilder<>& B, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const;
490
491 /// @brief Emit IR to increment this scalar (i.e. value + 1). Will
492 /// return Value::Invalid() and report a message to a logger (if provided)
493 /// if this is not an integer (non-bool) or float scalar.
494 Value Increment(llvm::IRBuilder<>& B, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const;
495
496 /// @brief Emit IR to increment this scalar (i.e. value - 1). Will
497 /// return Value::Invalid() and report a message to a logger (if provided)
498 /// if this is not an integer (non-bool) or float scalar.
499 Value Decrement(llvm::IRBuilder<>& B, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const;
500
501 ///////////////////////////////////////////////////////////////////////////
502 ///////////////////////////////////////////////////////////////////////////
503
504 /// @brief Emit IR to perform a binary operation on this LHS value and a
505 /// provided RHS value. If the operation is not a valid binary operation,
506 /// Value::Invalid() is returned. Defer to the explicit binary methods on
507 /// this class for more details.
508 /// @note For all methods, performing type promotion/casting where necessary
509 /// or return Value::Invalid() on incompatible inputs and report a
510 /// message to the log, if provided.
511 Value Binary(llvm::IRBuilder<>& B,
512 Value rhs,
513 const ast::tokens::OperatorToken& op,
514 Logger* log = nullptr,
515 const ax::ast::Node* node = nullptr) const
516 {
517 OPENVDB_ASSERT(*this);
518 OPENVDB_ASSERT(rhs);
519 switch (op)
520 {
521 case ast::tokens::OperatorToken::PLUS : return this->Add(B, rhs, log, node);
522 case ast::tokens::OperatorToken::MINUS : return this->Subtract(B, rhs, log, node);
523 case ast::tokens::OperatorToken::MULTIPLY : return this->Multiply(B, rhs, log, node);
524 case ast::tokens::OperatorToken::DIVIDE : return this->Divide(B, rhs, log, node);
525 case ast::tokens::OperatorToken::MODULO : return this->Modulo(B, rhs, log, node);
526 case ast::tokens::OperatorToken::EQUALSEQUALS : return this->Equals(B, rhs, log, node);
527 case ast::tokens::OperatorToken::NOTEQUALS : return this->NotEquals(B, rhs, log, node);
528 case ast::tokens::OperatorToken::MORETHAN : return this->GreaterThan(B, rhs, log, node);
529 case ast::tokens::OperatorToken::MORETHANOREQUAL : return this->GreaterThanEquals(B, rhs, log, node);
530 case ast::tokens::OperatorToken::LESSTHAN : return this->LessThan(B, rhs, log, node);
531 case ast::tokens::OperatorToken::LESSTHANOREQUAL : return this->LessThanEquals(B, rhs, log, node);
532 case ast::tokens::OperatorToken::SHIFTLEFT : return this->ShiftLeft(B, rhs, log, node);
533 case ast::tokens::OperatorToken::SHIFTRIGHT : return this->ShiftRight(B, rhs, log, node);
534 case ast::tokens::OperatorToken::BITAND : return this->BitAnd(B, rhs, log, node);
535 case ast::tokens::OperatorToken::BITOR : return this->BitOr(B, rhs, log, node);
536 case ast::tokens::OperatorToken::BITXOR : return this->BitXor(B, rhs, log, node);
537 default: return Value::Invalid();
538 }
539 }
540
541 // Binary arithmetic IR emission.
542
543 /// @brief Emit IR to perform a && operation on two scalars. Assumes both
544 /// inputs are scalars (this checking is currently done in the
545 /// ComputeGenerator) and will cause undefined behaviour if they are not.
546 /// @warning This does not perform short circuiting. See:
547 /// ComputeGenerator::visit(const ast::BinaryOperator*)
548 Value And(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const
549 {
550 OPENVDB_ASSERT(*this);
551 OPENVDB_ASSERT(rhs);
552 OPENVDB_ASSERT(this->IsScalar());
553 OPENVDB_ASSERT(rhs.IsScalar());
554 Value lhs = *this;
555 lhs = lhs.ScalarBoolComparison(B);
556 rhs = rhs.ScalarBoolComparison(B);
557 return this->TrivialBinary(B, rhs, ast::tokens::AND, log, node);
558 }
559
560 /// @brief Emit IR to perform a || operation on two scalars. Assumes both
561 /// inputs are scalars (this checking is currently done in the
562 /// ComputeGenerator) and will cause undefined behaviour if they are not.
563 /// @warning This does not perform short circuiting. See:
564 /// ComputeGenerator::visit(const ast::BinaryOperator*)
565 Value Or(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const
566 {
567 OPENVDB_ASSERT(*this);
568 OPENVDB_ASSERT(rhs);
569 OPENVDB_ASSERT(this->IsScalar());
570 OPENVDB_ASSERT(rhs.IsScalar());
571 Value lhs = *this;
572 lhs = lhs.ScalarBoolComparison(B);
573 rhs = rhs.ScalarBoolComparison(B);
574 return this->TrivialBinary(B, rhs, ast::tokens::OR, log, node);
575 }
576
577 /// @brief Emit IR to perform a + operation on two values
578 Value Add(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const;
579
580 /// @brief Emit IR to perform a - operation on two values
581 Value Subtract(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const;
582
583 /// @brief Emit IR to perform a * operation on two values
584 Value Multiply(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const;
585
586 /// @brief Emit IR to perform a / operation on two values If the denominator is constant and
587 /// zero, returns Value::Invalid()
588 Value Divide(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const;
589
590 /// @brief Emit IR to perform a FLOORED % operation on two values
591 Value Modulo(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const;
592
593 /// @brief Emit IR to perform a TRUNCATED % operation on two values
594 Value TruncatedModulo(llvm::IRBuilder<>& B, Value rhs) const;
595
596 // Binary Relational IR emission
597
598 /// @brief Emit IR to perform a == operation on two values
599 Value Equals(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const;
600
601 /// @brief Emit IR to perform a != operation on two values
602 Value NotEquals(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const;
603
604 /// @brief Emit IR to perform a > operation on two values
605 Value GreaterThan(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const
606 {
607 return this->Relational(B, rhs, ast::tokens::MORETHAN, log, node);
608 }
609
610 /// @brief Emit IR to perform a >= operation on two values
611 Value GreaterThanEquals(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const
612 {
613 return this->Relational(B, rhs, ast::tokens::MORETHANOREQUAL, log, node);
614 }
615
616 /// @brief Emit IR to perform a < operation on two values
617 Value LessThan(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const
618 {
619 return this->Relational(B, rhs, ast::tokens::LESSTHAN, log, node);
620 }
621
622 /// @brief Emit IR to perform a <= operation on two values
623 Value LessThanEquals(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const
624 {
625 return this->Relational(B, rhs, ast::tokens::LESSTHANOREQUAL, log, node);
626 }
627
628 // Binary Bitwise IR emission
629
630 /// @brief Emit IR to perform a << operation. Both values must be integers
631 Value ShiftLeft(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const
632 {
633 return this->Bitwise(B, rhs, ast::tokens::SHIFTLEFT, log, node);
634 }
635
636 /// @brief Emit IR to perform a >> operation. Both values must be integers
637 Value ShiftRight(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const
638 {
639 return this->Bitwise(B, rhs, ast::tokens::SHIFTRIGHT, log, node);
640 }
641
642 /// @brief Emit IR to perform a & operation. Both values must be integers
643 Value BitAnd(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const
644 {
645 return this->Bitwise(B, rhs, ast::tokens::BITAND, log, node);
646 }
647
648 /// @brief Emit IR to perform a | operation. Both values must be integers
649 Value BitOr(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const
650 {
651 return this->Bitwise(B, rhs, ast::tokens::BITOR, log, node);
652 }
653
654 /// @brief Emit IR to perform a ^ operation. Both values must be integers
655 Value BitXor(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const
656 {
657 return this->Bitwise(B, rhs, ast::tokens::BITXOR, log, node);
658 }
659
660 ///////////////////////////////////////////////////////////////////////////
661 ///////////////////////////////////////////////////////////////////////////
662
663 /// @brief Emit IR to assign the provided rhs to this value.
664 Value Assign(llvm::IRBuilder<>& B, Value rhs, Logger* log = nullptr, const ax::ast::Node* node = nullptr) const;
665
666 ///////////////////////////////////////////////////////////////////////////
667 ///////////////////////////////////////////////////////////////////////////
668
669 /// @brief Dump this value/type to llvm::errs
670 void Print() const;
671
672 /// @brief Access the underlying llvm Value
673 llvm::Value* GetValue() const { return mVal; }
674
675 /// @brief Access the underlying llvm Type
676 llvm::Type* GetUnderlyingType() const { return mUType; }
677
678 /// @brief Access the underlying scalar type. This method assumes the
679 /// current value is a scalar or array
680 llvm::Type* GetUnderlyingScalarType() const
681 {
682 OPENVDB_ASSERT(*this);
683 OPENVDB_ASSERT(this->IsScalar() || this->IsArray());
684 return mUType->isArrayTy() ? mUType->getArrayElementType() : mUType;
685 }
686
687 private:
688 template <size_t Dim>
689 Value ScalarToIdentMatrixN(llvm::IRBuilder<>& B) const
690 {
691 static_assert(Dim == 3 || Dim == 4);
692 OPENVDB_ASSERT(*this);
693 OPENVDB_ASSERT_MESSAGE(this->IsScalar(), "value type is not a scalar type");
694
695 Value scalar = this->LoadIfPtr(B);
696 llvm::Type* type = llvm::ArrayType::get(scalar.GetUnderlyingType(), Dim*Dim);
697 Value array = Value::Alloc(B, type);
698 Value zero = scalar.Zero();
699
700 for (size_t i = 0; i < Dim*Dim; ++i) {
701 const Value& m = ((i % (Dim+1) == 0) ? scalar : zero);
702 llvm::Value* element = array.GetArrayElement(B, i).GetValue();
703 B.CreateStore(m.GetValue(), element);
704 }
705
706 return array;
707 }
708
709 Value TrivialBinary(llvm::IRBuilder<>& B,
710 Value rhs,
711 const ast::tokens::OperatorToken& op,
712 Logger* log,
713 const ax::ast::Node* node) const;
714
715 Value Bitwise(llvm::IRBuilder<>& B,
716 Value rhs,
717 const ast::tokens::OperatorToken& op,
718 Logger* log,
719 const ax::ast::Node* node) const;
720
721 Value Relational(llvm::IRBuilder<>& B,
722 Value rhs,
723 const ast::tokens::OperatorToken& op,
724 Logger* log,
725 const ax::ast::Node* node) const;
726
727
728 static Value Reduce(llvm::IRBuilder<>& B,
729 const std::vector<Value>& bools,
730 const ast::tokens::OperatorToken& op)
731 {
732 OPENVDB_ASSERT(!bools.empty());
733 OPENVDB_ASSERT(op == ast::tokens::AND || op == ast::tokens::OR);
734 Value result = bools.front();
735 OPENVDB_ASSERT(result.IsBool());
736 for (size_t i = 1; i < bools.size(); ++i) {
737 result = result.TrivialBinary(B, bools[i], op, nullptr, nullptr);
738 }
739 return result;
740 }
741
742 Value ReduceBoolArray(llvm::IRBuilder<>& B, const ast::tokens::OperatorToken& op) const
743 {
744 OPENVDB_ASSERT(this->IsArray());
745 OPENVDB_ASSERT(this->GetUnderlyingScalarType() == LLVMType<bool>::get(B.getContext()));
746 std::vector<Value> elements;
747 this->ArrayToScalars(B, elements);
748 return Value::Reduce(B, elements, op);
749 }
750
751 static bool WImplicitScalarToMatrix(Logger* log, const ax::ast::Node* node)
752 {
753 if (!node) return true;
754 if (auto* child = node->child(0)) {
755 if (child->isType<ast::ArrayPack>()) {
756 if (log) log->error("unable to deduce implicit {...} type for binary op as value "
757 "may be a matrix or array. assign to a local mat variable", child);
758 return false;
759 }
760 }
761 if (log && !log->warning("implicit cast to matrix from scalar. resulting "
762 "cast will be equal to scalar <op> identity.", node->child(1))) return false;
763 return true;
764 }
765
766 static Value WUnsupportedOp(const ast::tokens::CoreType& type,
767 const ast::tokens::OperatorToken& op,
768 Logger* log,
769 const ax::ast::Node* node)
770 {
771 const std::string typestr = ast::tokens::typeStringFromToken(type);
772 return Value::WUnsupportedOp(typestr, op, log, node);
773 }
774
775 static Value WUnsupportedOp(const std::string& typestr,
776 const ast::tokens::OperatorToken& op,
777 Logger* log,
778 const ax::ast::Node* node)
779 {
780 if (log) {
781 const std::string opstr = ast::tokens::operatorNameFromToken(op);
782 log->error("unsupported " + typestr + " operation \"" + opstr + "\"", node);
783 }
784 return Value::Invalid();
785 }
786
787 private:
788 llvm::Value* mVal {nullptr};
789 llvm::Type* mUType {nullptr};
790};
791
792} // namespace codegen
793} // namespace ax
794} // namespace OPENVDB_VERSION_NAME
795} // namespace openvdb
796
797#endif // OPENVDB_AX_CODEGEN_VALUE_HAS_BEEN_INCLUDED
798
AST.h
Provides the definition for every abstract and concrete derived class which represent a particular ab...
Assert.h
OPENVDB_ASSERT_MESSAGE
#define OPENVDB_ASSERT_MESSAGE(X, MSG)
Definition Assert.h:42
OPENVDB_ASSERT
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
Logger.h
Logging system to collect errors and warnings throughout the different stages of parsing and compilat...
OPENVDB_AX_API
#define OPENVDB_AX_API
Definition Platform.h:312
Tokens.h
Various function and operator tokens used throughout the AST and code generation.
Types.h
Consolidated llvm types for most supported types.
openvdb::v12_1::ax::Logger
Logger for collecting errors and warnings that occur during AX compilation.
Definition Logger.h:58
openvdb::v12_1::ax::codegen::Value
Intermediate representation wrapper for supported value types in AX as immutable instances.
Definition Value.h:63
openvdb::v12_1::ax::codegen::Value::GetArrayElement
Value GetArrayElement(llvm::IRBuilder<> &B, Value idx) const
Emit IR to return a scalar at the provided index from this array value. Will generate invalid IR if t...
Definition Value.h:356
openvdb::v12_1::ax::codegen::Value::BitNot
Value BitNot(llvm::IRBuilder<> &B, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to create a unary not instruction on this integer or integer array (i.e. ~value)....
openvdb::v12_1::ax::codegen::Value::IsPtr
bool IsPtr() const
Return true if this Value is a pointer type.
Definition Value.h:296
openvdb::v12_1::ax::codegen::Value::Or
Value Or(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a || operation on two scalars. Assumes both inputs are scalars (this checking is c...
Definition Value.h:565
openvdb::v12_1::ax::codegen::Value::GetArrayNumElements
size_t GetArrayNumElements() const
Return the number of elements in this array type.
Definition Value.h:309
openvdb::v12_1::ax::codegen::Value::BitAnd
Value BitAnd(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a & operation. Both values must be integers.
Definition Value.h:643
openvdb::v12_1::ax::codegen::Value::LessThanEquals
Value LessThanEquals(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a <= operation on two values.
Definition Value.h:623
openvdb::v12_1::ax::codegen::Value::Alloc
static Value Alloc(llvm::IRBuilder<> &B, llvm::Type *type, llvm::Value *size=nullptr)
Emit IR inserting an allocation at the front of the BasicBlock pointed to by the provided IRBuilder....
Definition Value.h:124
openvdb::v12_1::ax::codegen::Value::ScalarToArray
Value ScalarToArray(llvm::IRBuilder<> &B, size_t size) const
Emit IR to broadcast this scalar to a new array. Will generated invalid IR if this is not a scalar or...
Definition Value.h:417
openvdb::v12_1::ax::codegen::Value::Create
static Value Create(llvm::LLVMContext &C, const ValueType &value)
Create an arithmetic literal.
Definition Value.h:92
openvdb::v12_1::ax::codegen::Value::GetUnderlyingScalarType
llvm::Type * GetUnderlyingScalarType() const
Access the underlying scalar type. This method assumes the current value is a scalar or array.
Definition Value.h:680
openvdb::v12_1::ax::codegen::Value::Assign
Value Assign(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to assign the provided rhs to this value.
openvdb::v12_1::ax::codegen::Value::ScalarToIdentMatrix4
Value ScalarToIdentMatrix4(llvm::IRBuilder<> &B) const
Emit IR to create a new 4x4 matrix from this scalar value, adhering to scalar->matrix promotion rules...
Definition Value.h:443
openvdb::v12_1::ax::codegen::Value::BitOr
Value BitOr(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a | operation. Both values must be integers.
Definition Value.h:649
openvdb::v12_1::ax::codegen::Value::ShiftLeft
Value ShiftLeft(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a << operation. Both values must be integers.
Definition Value.h:631
openvdb::v12_1::ax::codegen::Value::ArrayToScalars
void ArrayToScalars(llvm::IRBuilder<> &B, std::vector< Value > &elements, const bool load=false) const
Emit IR to extract scalar values from the elements in this array and populate the provided vector wit...
Definition Value.h:392
openvdb::v12_1::ax::codegen::Value::ScalarsToArray
static Value ScalarsToArray(llvm::IRBuilder<> &B, const std::vector< Value > &values)
Emit IR to create an array from a set of scalar values. Will generate invalid IR if the values are no...
Definition Value.h:158
openvdb::v12_1::ax::codegen::Value::Load
Value Load(llvm::IRBuilder<> &B) const
Emit IR to load the current value. Not typically required to call directly. Will generate invalid IR ...
Definition Value.h:335
openvdb::v12_1::ax::codegen::Value::IsNan
Value IsNan(llvm::IRBuilder<> &B) const
Emit IR to check whether this value is NaN. Only works on Float types and will generate invalid IR if...
Definition Value.h:323
openvdb::v12_1::ax::codegen::Value::IsVoid
bool IsVoid() const
Return true if this value represents a void type. This is typically only possible for void function r...
Definition Value.h:209
openvdb::v12_1::ax::codegen::Value::Value
Value(Value &&)=default
openvdb::v12_1::ax::codegen::Value::ScalarBoolComparison
Value ScalarBoolComparison(llvm::IRBuilder<> &B) const
Emit IR to perform standard boolean comparison on this scalar i.e. bool(scalar) or bool(scalar == 0)....
openvdb::v12_1::ax::codegen::Value::Modulo
Value Modulo(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a FLOORED % operation on two values.
openvdb::v12_1::ax::codegen::Value::operator!
bool operator!() const
See bool operator.
Definition Value.h:204
openvdb::v12_1::ax::codegen::Value::Increment
Value Increment(llvm::IRBuilder<> &B, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to increment this scalar (i.e. value + 1). Will return Value::Invalid() and report a message ...
openvdb::v12_1::ax::codegen::Value::BitXor
Value BitXor(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a ^ operation. Both values must be integers.
Definition Value.h:655
openvdb::v12_1::ax::codegen::Value::GetValue
llvm::Value * GetValue() const
Access the underlying llvm Value.
Definition Value.h:673
openvdb::v12_1::ax::codegen::Value::IsMatrix
bool IsMatrix() const
Return true if the underlying type is an matrix 3/4 type.
Definition Value.h:278
openvdb::v12_1::ax::codegen::Value::Value
Value(const Value &)=default
openvdb::v12_1::ax::codegen::Value::Value
Value(llvm::Constant *costant)
Initialize from a constant value.
Definition Value.h:77
openvdb::v12_1::ax::codegen::Value::operator=
Value & operator=(const Value &)=default
openvdb::v12_1::ax::codegen::Value::NotEquals
Value NotEquals(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a != operation on two values.
openvdb::v12_1::ax::codegen::Value::LessThan
Value LessThan(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a < operation on two values.
Definition Value.h:617
openvdb::v12_1::ax::codegen::Value::IsVector
bool IsVector() const
Return true if the underlying type is an vector 2/3/4 type.
Definition Value.h:269
openvdb::v12_1::ax::codegen::Value::IsString
bool IsString() const
Return true if the underlying type is a string type.
Definition Value.h:289
openvdb::v12_1::ax::codegen::Value::IsInteger
bool IsInteger() const
Return true if the underlying type is an integer type.
Definition Value.h:240
openvdb::v12_1::ax::codegen::Value::Divide
Value Divide(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a / operation on two values If the denominator is constant and zero,...
openvdb::v12_1::ax::codegen::Value::ScalarToIdentMatrix3
Value ScalarToIdentMatrix3(llvm::IRBuilder<> &B) const
Emit IR to create a new 3x3 matrix from this scalar value, adhering to scalar->matrix promotion rules...
Definition Value.h:435
openvdb::v12_1::ax::codegen::Value::IsConstant
bool IsConstant() const
Return true if this Value is a constant.
Definition Value.h:303
openvdb::v12_1::ax::codegen::Value::ShiftRight
Value ShiftRight(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a >> operation. Both values must be integers.
Definition Value.h:637
openvdb::v12_1::ax::codegen::Value::Return
static Value Return(llvm::IRBuilder<> &B, Value *ret=nullptr)
Create a value that represents a return value from a function. Really only intended to be used by the...
Definition Value.h:101
openvdb::v12_1::ax::codegen::Value::Not
Value Not(llvm::IRBuilder<> &B, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to create a unary not instruction on this scalar or integer array (i.e. !value)....
openvdb::v12_1::ax::codegen::Value::Negate
Value Negate(llvm::IRBuilder<> &B, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to create a unary not instruction on this scalar or array (i.e. -value). If the value is not ...
openvdb::v12_1::ax::codegen::Value::One
Value One() const
Create a new one scalar Value using the underlying scalar precision of this Value....
Definition Value.h:190
openvdb::v12_1::ax::codegen::Value::operator=
Value & operator=(Value &&)=default
openvdb::v12_1::ax::codegen::Value::Multiply
Value Multiply(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a * operation on two values.
openvdb::v12_1::ax::codegen::Value::Binary
Value Binary(llvm::IRBuilder<> &B, Value rhs, const ast::tokens::OperatorToken &op, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a binary operation on this LHS value and a provided RHS value. If the operation is...
Definition Value.h:511
openvdb::v12_1::ax::codegen::Value::LoadIfPtr
Value LoadIfPtr(llvm::IRBuilder<> &B) const
Emit IR to load the current value if it is a ptr. Not typically required to call directly.
Definition Value.h:346
openvdb::v12_1::ax::codegen::Value::And
Value And(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a && operation on two scalars. Assumes both inputs are scalars (this checking is c...
Definition Value.h:548
openvdb::v12_1::ax::codegen::Value::Select
Value Select(llvm::IRBuilder<> &B, const Value &trueval, const Value &falseval) const
Emit IR to select a value based on this boolean scalar value. Will generate invalid IR if this is not...
openvdb::v12_1::ax::codegen::Value::Equals
Value Equals(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a == operation on two values.
openvdb::v12_1::ax::codegen::Value::GreaterThanEquals
Value GreaterThanEquals(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a >= operation on two values.
Definition Value.h:611
openvdb::v12_1::ax::codegen::Value::Print
void Print() const
Dump this value/type to llvm::errs.
openvdb::v12_1::ax::codegen::Value::GetUnderlyingType
llvm::Type * GetUnderlyingType() const
Access the underlying llvm Type.
Definition Value.h:676
openvdb::v12_1::ax::codegen::Value::Subtract
Value Subtract(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a - operation on two values.
openvdb::v12_1::ax::codegen::Value::TruncatedModulo
Value TruncatedModulo(llvm::IRBuilder<> &B, Value rhs) const
Emit IR to perform a TRUNCATED % operation on two values.
openvdb::v12_1::ax::codegen::Value::Decrement
Value Decrement(llvm::IRBuilder<> &B, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to increment this scalar (i.e. value - 1). Will return Value::Invalid() and report a message ...
openvdb::v12_1::ax::codegen::Value::Zero
Value Zero() const
Create a new zero scalar Value using the underlying scalar precision of this Value....
Definition Value.h:182
openvdb::v12_1::ax::codegen::Value::Invalid
static Value Invalid()
Return an invalid Value. This is used to represent various fail cases. Note that the operator bool(Va...
Definition Value.h:88
openvdb::v12_1::ax::codegen::Value::Add
Value Add(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a + operation on two values.
openvdb::v12_1::ax::codegen::Value::IsArray
bool IsArray() const
Return true if the underlying type is an array type.
Definition Value.h:260
openvdb::v12_1::ax::codegen::Value::IsFloat
bool IsFloat() const
Return true if the underlying type is an floating point type (float or double).
Definition Value.h:251
openvdb::v12_1::ax::codegen::Value::IsBool
bool IsBool() const
Return true if the underlying type is a bool type.
Definition Value.h:219
openvdb::v12_1::ax::codegen::Value::CastToPrecision
Value CastToPrecision(llvm::IRBuilder<> &B, llvm::Type *precision) const
Emit IR to cast this scalar or array to a new value of the provided scalar precision....
openvdb::v12_1::ax::codegen::Value::Value
Value(llvm::Value *val, llvm::Type *utype)
Create a Value with a provided underlying type.
Definition Value.h:71
openvdb::v12_1::ax::codegen::Value::GreaterThan
Value GreaterThan(llvm::IRBuilder<> &B, Value rhs, Logger *log=nullptr, const ax::ast::Node *node=nullptr) const
Emit IR to perform a > operation on two values.
Definition Value.h:605
openvdb::v12_1::ax::codegen::Value::GetArrayElement
Value GetArrayElement(llvm::IRBuilder<> &B, uint64_t idx) const
Emit IR to return a scalar at the provided index from this array value. Will generate invalid IR if t...
Definition Value.h:374
openvdb::v12_1::ax::codegen::Value::IsScalar
bool IsScalar() const
Return true if the underlying type is a scalar type (bool, int or float).
Definition Value.h:230
openvdb::v12_1::ax::codegen::Value::Supports
static bool Supports(llvm::Type *utype)
Return true if the underlying type held by utype is supported via the interface of this Value class.
Definition Value.h:109
llvm
Definition FunctionRegistry.h:23
openvdb::v12_1::ax::ast::tokens::OperatorToken
OperatorToken
Definition Tokens.h:151
openvdb::v12_1::ax::ast::tokens::BITOR
@ BITOR
Definition Tokens.h:181
openvdb::v12_1::ax::ast::tokens::DIVIDE
@ DIVIDE
Definition Tokens.h:158
openvdb::v12_1::ax::ast::tokens::LESSTHANOREQUAL
@ LESSTHANOREQUAL
Definition Tokens.h:174
openvdb::v12_1::ax::ast::tokens::SHIFTRIGHT
@ SHIFTRIGHT
Definition Tokens.h:179
openvdb::v12_1::ax::ast::tokens::MORETHANOREQUAL
@ MORETHANOREQUAL
Definition Tokens.h:173
openvdb::v12_1::ax::ast::tokens::EQUALSEQUALS
@ EQUALSEQUALS
RELATIONAL.
Definition Tokens.h:169
openvdb::v12_1::ax::ast::tokens::BITXOR
@ BITXOR
Definition Tokens.h:182
openvdb::v12_1::ax::ast::tokens::BITAND
@ BITAND
Definition Tokens.h:180
openvdb::v12_1::ax::ast::tokens::AND
@ AND
LOGICAL.
Definition Tokens.h:163
openvdb::v12_1::ax::ast::tokens::PLUS
@ PLUS
ARITHMETIC.
Definition Tokens.h:155
openvdb::v12_1::ax::ast::tokens::LESSTHAN
@ LESSTHAN
Definition Tokens.h:172
openvdb::v12_1::ax::ast::tokens::OR
@ OR
Definition Tokens.h:164
openvdb::v12_1::ax::ast::tokens::MODULO
@ MODULO
Definition Tokens.h:159
openvdb::v12_1::ax::ast::tokens::MORETHAN
@ MORETHAN
Definition Tokens.h:171
openvdb::v12_1::ax::ast::tokens::NOTEQUALS
@ NOTEQUALS
Definition Tokens.h:170
openvdb::v12_1::ax::ast::tokens::MULTIPLY
@ MULTIPLY
Definition Tokens.h:157
openvdb::v12_1::ax::ast::tokens::SHIFTLEFT
@ SHIFTLEFT
BITWISE.
Definition Tokens.h:178
openvdb::v12_1::ax::ast::tokens::MINUS
@ MINUS
Definition Tokens.h:156
openvdb::v12_1::ax::codegen::AssertOpaquePtrs
bool AssertOpaquePtrs(llvm::Value *opaque, llvm::Type *type)
Definition Utils.h:43
openvdb::v12_1::ax::codegen::llvmConstant
llvm::Constant * llvmConstant(const T t, llvm::Type *type)
Returns an llvm Constant holding a scalar value.
Definition Types.h:360
openvdb
Definition Exceptions.h:13
Utils.h
Utility code generation methods for performing various llvm operations.
openvdb::v12_1::ax::ast::Node
The base abstract node which determines the interface and required methods for all derived concrete n...
Definition AST.h:103
openvdb::v12_1::ax::codegen::LLVMType::get
static llvm::Type * get(llvm::LLVMContext &C)
Return an LLVM type which represents T.
Definition Types.h:81
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