11#ifndef OPENVDB_AX_CODEGEN_VALUE_HAS_BEEN_INCLUDED
12#define OPENVDB_AX_CODEGEN_VALUE_HAS_BEEN_INCLUDED
21#include <openvdb/version.h>
24#include <llvm/IR/IRBuilder.h>
25#include <llvm/IR/LLVMContext.h>
71 Value(llvm::Value* val, llvm::Type* utype)
77 explicit Value(llvm::Constant* costant)
91 template <
typename ValueType>
92 static Value Create(llvm::LLVMContext& C,
const ValueType& value)
103 return ret ?
Value(B.CreateRet(ret->GetValue()), B.getVoidTy()) :
104 Value(B.CreateRetVoid(), B.getVoidTy());
112 return utype->isVoidTy() ||
113 utype->isIntegerTy() ||
114 utype->isFloatingPointTy() ||
116 (utype->isArrayTy() &&
117 (utype->getArrayElementType()->isIntegerTy() ||
118 utype->getArrayElementType()->isFloatingPointTy()));
124 static Value Alloc(llvm::IRBuilder<>& B, llvm::Type* type, llvm::Value* size =
nullptr)
128 llvm::Function* parent = B.GetInsertBlock()->getParent();
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);
142 if (type == strtype) {
143 llvm::Value* cptr = B.CreateStructGEP(strtype, result, 0);
144 llvm::Value* sso = B.CreateStructGEP(strtype, result, 1);
146 llvm::Value* sso_load = B.CreateConstInBoundsGEP2_64(strtype->getTypeAtIndex(1), sso, 0, 0);
147 llvm::Value* len = B.CreateStructGEP(strtype, result, 2);
148 B.CreateStore(sso_load, cptr);
149 B.CreateStore(B.getInt64(0), len);
152 return Value(result, type);
162 llvm::Type* type = values.front().GetUnderlyingType();
163 llvm::Type* arrayType = llvm::ArrayType::get(type, values.size());
167 for (
const Value& value : values)
173 B.CreateStore(value.GetValue(), element.
GetValue());
201 operator bool()
const;
212 return mUType->isVoidTy();
222 return mUType->isIntegerTy(1);
233 return (mUType->isIntegerTy() || mUType->isFloatingPointTy());
243 return mUType->isIntegerTy();
254 return mUType->isFloatingPointTy();
263 return mUType->isArrayTy();
272 return mUType->isArrayTy() && !this->
IsMatrix();
281 return mUType->isArrayTy() &&
299 return mVal->getType()->isPointerTy();
305 return bool(llvm::dyn_cast<llvm::Constant>(this->
GetValue()));
312 return mUType->getArrayNumElements();
329 return Value(result, result->getType());
340 return Value(B.CreateLoad(mUType, mVal), mUType);
350 return this->
IsPtr() ? this->
Load(B) : *
this;
364 return Value(B.CreateInBoundsGEP(mUType, mVal, {zero.GetValue(), idx.GetValue()}), mUType->getArrayElementType());
368 return Value(B.CreateInBoundsGEP(mUType, mVal, {idx.GetValue()}), mUType->getArrayElementType());
380 return Value(B.CreateConstInBoundsGEP2_64(mUType, mVal, uint64_t(0), idx), mUType->getArrayElementType());
384 return Value(B.CreateConstInBoundsGEP1_64(mUType, mVal, idx), mUType->getArrayElementType());
393 std::vector<Value>& elements,
394 const bool load =
false)
const
400 elements.reserve(size);
402 for (
size_t i = 0; i < size; ++i)
405 if (load) elem = elem.
Load(B);
407 elements.emplace_back(elem);
425 for (
size_t i = 0; i < size; ++i) {
437 return this->ScalarToIdentMatrixN<3>(B);
445 return this->ScalarToIdentMatrixN<4>(B);
684 return mUType->isArrayTy() ? mUType->getArrayElementType() : mUType;
688 template <
size_t Dim>
689 Value ScalarToIdentMatrixN(llvm::IRBuilder<>& B)
const
691 static_assert(Dim == 3 || Dim == 4);
695 Value scalar = this->LoadIfPtr(B);
700 for (
size_t i = 0; i < Dim*Dim; ++i) {
701 const Value& m = ((i % (Dim+1) == 0) ? scalar : zero);
703 B.CreateStore(m.
GetValue(), element);
709 Value TrivialBinary(llvm::IRBuilder<>& B,
711 const ast::tokens::OperatorToken& op,
715 Value Bitwise(llvm::IRBuilder<>& B,
717 const ast::tokens::OperatorToken& op,
721 Value Relational(llvm::IRBuilder<>& B,
723 const ast::tokens::OperatorToken& op,
728 static Value Reduce(llvm::IRBuilder<>& B,
729 const std::vector<Value>& bools,
730 const ast::tokens::OperatorToken& op)
734 Value result = bools.front();
736 for (
size_t i = 1; i < bools.size(); ++i) {
737 result = result.TrivialBinary(B, bools[i], op,
nullptr,
nullptr);
742 Value ReduceBoolArray(llvm::IRBuilder<>& B,
const ast::tokens::OperatorToken& op)
const
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);
751 static bool WImplicitScalarToMatrix(Logger* log,
const ax::ast::Node* node)
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);
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;
766 static Value WUnsupportedOp(
const ast::tokens::CoreType& type,
767 const ast::tokens::OperatorToken& op,
769 const ax::ast::Node* node)
771 const std::string typestr = ast::tokens::typeStringFromToken(type);
772 return Value::WUnsupportedOp(typestr, op, log, node);
775 static Value WUnsupportedOp(
const std::string& typestr,
776 const ast::tokens::OperatorToken& op,
778 const ax::ast::Node* node)
781 const std::string opstr = ast::tokens::operatorNameFromToken(op);
782 log->error(
"unsupported " + typestr +
" operation \"" + opstr +
"\"", node);
784 return Value::Invalid();
788 llvm::Value* mVal {
nullptr};
789 llvm::Type* mUType {
nullptr};
Provides the definition for every abstract and concrete derived class which represent a particular ab...
#define OPENVDB_ASSERT_MESSAGE(X, MSG)
Definition Assert.h:42
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
Logging system to collect errors and warnings throughout the different stages of parsing and compilat...
Various function and operator tokens used throughout the AST and code generation.
Consolidated llvm types for most supported types.
Logger for collecting errors and warnings that occur during AX compilation.
Definition Logger.h:58
Intermediate representation wrapper for supported value types in AX as immutable instances.
Definition Value.h:63
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
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)....
bool IsPtr() const
Return true if this Value is a pointer type.
Definition Value.h:296
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
size_t GetArrayNumElements() const
Return the number of elements in this array type.
Definition Value.h:309
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
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
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
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
static Value Create(llvm::LLVMContext &C, const ValueType &value)
Create an arithmetic literal.
Definition Value.h:92
llvm::Type * GetUnderlyingScalarType() const
Access the underlying scalar type. This method assumes the current value is a scalar or array.
Definition Value.h:680
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.
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
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
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
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
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
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
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
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
Value ScalarBoolComparison(llvm::IRBuilder<> &B) const
Emit IR to perform standard boolean comparison on this scalar i.e. bool(scalar) or bool(scalar == 0)....
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.
bool operator!() const
See bool operator.
Definition Value.h:204
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 ...
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
llvm::Value * GetValue() const
Access the underlying llvm Value.
Definition Value.h:673
bool IsMatrix() const
Return true if the underlying type is an matrix 3/4 type.
Definition Value.h:278
Value(const Value &)=default
Value(llvm::Constant *costant)
Initialize from a constant value.
Definition Value.h:77
Value & operator=(const Value &)=default
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.
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
bool IsVector() const
Return true if the underlying type is an vector 2/3/4 type.
Definition Value.h:269
bool IsString() const
Return true if the underlying type is a string type.
Definition Value.h:289
bool IsInteger() const
Return true if the underlying type is an integer type.
Definition Value.h:240
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,...
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
bool IsConstant() const
Return true if this Value is a constant.
Definition Value.h:303
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
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
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)....
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 ...
Value One() const
Create a new one scalar Value using the underlying scalar precision of this Value....
Definition Value.h:190
Value & operator=(Value &&)=default
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.
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
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
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
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...
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.
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
void Print() const
Dump this value/type to llvm::errs.
llvm::Type * GetUnderlyingType() const
Access the underlying llvm Type.
Definition Value.h:676
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.
Value TruncatedModulo(llvm::IRBuilder<> &B, Value rhs) const
Emit IR to perform a TRUNCATED % operation on two values.
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 ...
Value Zero() const
Create a new zero scalar Value using the underlying scalar precision of this Value....
Definition Value.h:182
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
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.
bool IsArray() const
Return true if the underlying type is an array type.
Definition Value.h:260
bool IsFloat() const
Return true if the underlying type is an floating point type (float or double).
Definition Value.h:251
bool IsBool() const
Return true if the underlying type is a bool type.
Definition Value.h:219
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....
Value(llvm::Value *val, llvm::Type *utype)
Create a Value with a provided underlying type.
Definition Value.h:71
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
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
bool IsScalar() const
Return true if the underlying type is a scalar type (bool, int or float).
Definition Value.h:230
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
Definition FunctionRegistry.h:23
OperatorToken
Definition Tokens.h:151
@ BITOR
Definition Tokens.h:181
@ DIVIDE
Definition Tokens.h:158
@ LESSTHANOREQUAL
Definition Tokens.h:174
@ SHIFTRIGHT
Definition Tokens.h:179
@ MORETHANOREQUAL
Definition Tokens.h:173
@ EQUALSEQUALS
RELATIONAL.
Definition Tokens.h:169
@ BITXOR
Definition Tokens.h:182
@ BITAND
Definition Tokens.h:180
@ AND
LOGICAL.
Definition Tokens.h:163
@ PLUS
ARITHMETIC.
Definition Tokens.h:155
@ LESSTHAN
Definition Tokens.h:172
@ OR
Definition Tokens.h:164
@ MODULO
Definition Tokens.h:159
@ MORETHAN
Definition Tokens.h:171
@ NOTEQUALS
Definition Tokens.h:170
@ MULTIPLY
Definition Tokens.h:157
@ SHIFTLEFT
BITWISE.
Definition Tokens.h:178
@ MINUS
Definition Tokens.h:156
bool AssertOpaquePtrs(llvm::Value *opaque, llvm::Type *type)
Definition Utils.h:43
llvm::Constant * llvmConstant(const T t, llvm::Type *type)
Returns an llvm Constant holding a scalar value.
Definition Types.h:360
Definition Exceptions.h:13
Utility code generation methods for performing various llvm operations.
The base abstract node which determines the interface and required methods for all derived concrete n...
Definition AST.h:103
static llvm::Type * get(llvm::LLVMContext &C)
Return an LLVM type which represents T.
Definition Types.h:81
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218