11 #ifndef OPENVDB_AX_CODEGEN_VALUE_HAS_BEEN_INCLUDED 12 #define OPENVDB_AX_CODEGEN_VALUE_HAS_BEEN_INCLUDED 17 #include "../ast/AST.h" 18 #include "../ast/Tokens.h" 19 #include "../compiler/Logger.h" 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());
164 Value array = Value::Alloc(B, arrayType);
167 for (
const Value& value : values)
173 B.CreateStore(value.GetValue(), element.GetValue());
184 return Value(llvmConstant<uint64_t>(0, this->GetUnderlyingScalarType()));
192 return Value(llvmConstant<uint64_t>(1, this->GetUnderlyingScalarType()));
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() &&
283 (this->GetArrayNumElements() == 9 || this->GetArrayNumElements() == 16);
299 return mVal->getType()->isPointerTy();
305 return bool(llvm::dyn_cast<llvm::Constant>(this->GetValue()));
312 return mUType->getArrayNumElements();
327 Value self = this->LoadIfPtr(B);
328 llvm::Value* result = B.CreateFCmpUNO(
self.GetValue(),
self.GetValue());
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 399 const size_t size = this->GetArrayNumElements();
400 elements.reserve(size);
402 for (
size_t i = 0; i < size; ++i)
404 Value elem = this->GetArrayElement(B, i);
405 if (load) elem = elem.
Load(B);
407 elements.emplace_back(elem);
421 Value scalar = this->LoadIfPtr(B);
424 Value array = Value::Alloc(B, type);
425 for (
size_t i = 0; i < size; ++i) {
437 return this->ScalarToIdentMatrixN<3>(B);
445 return this->ScalarToIdentMatrixN<4>(B);
451 Value ScalarBoolComparison(llvm::IRBuilder<>& B)
const;
456 Value Select(llvm::IRBuilder<>& B,
const Value& trueval,
const Value& falseval)
const;
466 Value CastToPrecision(llvm::IRBuilder<>& B, llvm::Type* precision)
const;
537 default:
return Value::Invalid();
594 Value TruncatedModulo(llvm::IRBuilder<>& B,
Value rhs)
const;
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);
697 Value array = Value::Alloc(B, type);
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,
715 Value Bitwise(llvm::IRBuilder<>& B,
721 Value Relational(llvm::IRBuilder<>& B,
728 static Value Reduce(llvm::IRBuilder<>& B,
729 const std::vector<Value>& bools,
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);
746 std::vector<Value> elements;
747 this->ArrayToScalars(B, elements);
748 return Value::Reduce(B, elements, op);
753 if (!node)
return true;
754 if (
auto* child = node->
child(0)) {
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;
772 return Value::WUnsupportedOp(typestr, op, log, node);
775 static Value WUnsupportedOp(
const std::string& typestr,
782 log->
error(
"unsupported " + typestr +
" operation \"" + opstr +
"\"", node);
784 return Value::Invalid();
788 llvm::Value* mVal {
nullptr};
789 llvm::Type* mUType {
nullptr};
797 #endif // OPENVDB_AX_CODEGEN_VALUE_HAS_BEEN_INCLUDED Definition: axparser.h:140
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
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(llvm::Value *val, llvm::Type *utype)
Create a Value with a provided underlying type.
Definition: Value.h:71
Definition: FunctionRegistry.h:23
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
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
Definition: axparser.h:141
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
bool IsArray() const
Return true if the underlying type is an array type.
Definition: Value.h:260
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
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
Definition: axparser.h:147
std::string typeStringFromToken(const CoreType type)
Definition: Tokens.h:118
Definition: axparser.h:144
Value One() const
Create a new one scalar Value using the underlying scalar precision of this Value. Does not generate IR, however will return an invalid constant if this Value is a string.
Definition: Value.h:190
#define OPENVDB_ASSERT_MESSAGE(X, MSG)
Definition: Assert.h:42
bool IsInteger() const
Return true if the underlying type is an integer type.
Definition: Value.h:240
Definition: axparser.h:136
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
ArrayPacks represent temporary container creations of arbitrary sizes, typically generated through th...
Definition: AST.h:1785
Definition: axparser.h:145
LLVM type mapping from pod types.
Definition: Types.h:67
Consolidated llvm types for most supported types.
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
Definition: axparser.h:143
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
bool error(const std::string &message, const CodeLocation &lineCol=CodeLocation(0, 0))
Log a compiler error and its offending code location. If the offending location is (0...
llvm::Type * GetUnderlyingScalarType() const
Access the underlying scalar type. This method assumes the current value is a scalar or array...
Definition: Value.h:680
size_t GetArrayNumElements() const
Return the number of elements in this array type.
Definition: Value.h:309
bool IsFloat() const
Return true if the underlying type is an floating point type (float or double).
Definition: Value.h:251
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
bool IsBool() const
Return true if the underlying type is a bool type.
Definition: Value.h:219
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
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
virtual const Node * child(const size_t index) const =0
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Value ScalarBoolComparison(llvm::IRBuilder<> &B) const
Emit IR to perform standard boolean comparison on this scalar i.e. bool(scalar) or bool(scalar == 0)...
CoreType
Definition: Tokens.h:31
Definition: axparser.h:151
Definition: axparser.h:137
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
Definition: axparser.h:146
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
bool operator!() const
See bool operator.
Definition: Value.h:204
static Value Create(llvm::LLVMContext &C, const ValueType &value)
Create an arithmetic literal.
Definition: Value.h:92
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
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
Value Zero() const
Create a new zero scalar Value using the underlying scalar precision of this Value. Does not generate IR, however will return an invalid constant if this Value is a string.
Definition: Value.h:182
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
Definition: Exceptions.h:13
bool IsVector() const
Return true if the underlying type is an vector 2/3/4 type.
Definition: Value.h:269
Definition: axparser.h:135
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
Definition: axparser.h:150
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
std::string operatorNameFromToken(const OperatorToken token)
Definition: Tokens.h:257
Definition: axparser.h:142
Definition: axparser.h:149
llvm::Type * GetUnderlyingType() const
Access the underlying llvm Type.
Definition: Value.h:676
bool IsScalar() const
Return true if the underlying type is a scalar type (bool, int or float).
Definition: Value.h:230
Definition: axparser.h:148
Definition: axparser.h:139
bool warning(const std::string &message, const CodeLocation &lineCol=CodeLocation(0, 0))
Log a compiler warning and its offending code location. If the offending location is (0...
Logger for collecting errors and warnings that occur during AX compilation.
Definition: Logger.h:57
bool AssertOpaquePtrs([[maybe_unused]]llvm::Value *opaque, [[maybe_unused]]llvm::Type *type)
Definition: Utils.h:43
Definition: axparser.h:152
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
Definition: axparser.h:138
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 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
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
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
bool IsConstant() const
Return true if this Value is a constant.
Definition: Value.h:303
Intermediate representation wrapper for supported value types in AX as immutable instances.
Definition: Value.h:62
Utility code generation methods for performing various llvm operations.
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
OperatorToken
Definition: Tokens.h:150
The base abstract node which determines the interface and required methods for all derived concrete n...
Definition: AST.h:102
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
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
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
bool IsPtr() const
Return true if this Value is a pointer type.
Definition: Value.h:296
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
bool IsString() const
Return true if the underlying type is a string type.
Definition: Value.h:289
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218
Value(llvm::Constant *costant)
Initialize from a constant value.
Definition: Value.h:77