12 #ifndef OPENVDB_AX_CODEGEN_UTILS_HAS_BEEN_INCLUDED
13 #define OPENVDB_AX_CODEGEN_UTILS_HAS_BEEN_INCLUDED
17 #include "../ast/Tokens.h"
18 #include "../Exceptions.h"
22 #include <llvm/IR/IRBuilder.h>
23 #include <llvm/IR/LLVMContext.h>
31 #include <llvm/Support/raw_ostream.h>
44 (llvm::IRBuilder<>&, llvm::Value*, llvm::Type*)>;
47 (llvm::IRBuilder<>&, llvm::Value*, llvm::Value*)>;
56 std::vector<llvm::Type*>& types)
58 types.reserve(values.size());
59 for (
const auto& v : values) {
60 types.emplace_back(v->getType());
72 llvm::raw_string_ostream os(str);
86 llvm::Type* elementType = type;
87 while (elementType->isPointerTy()) {
88 elementType = elementType->getContainedType(0);
102 template <
typename ValueT>
105 llvm::IRBuilder<>& builder)
107 llvm::Value* address =
108 llvm::ConstantInt::get(llvm::Type::getIntNTy(builder.getContext(),
sizeof(uintptr_t)*8),
109 reinterpret_cast<uintptr_t
>(ptr));
125 llvm::Value* size =
nullptr)
128 llvm::Function* parent = B.GetInsertBlock()->getParent();
129 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);
139 inline llvm::Argument*
142 if (!F)
return nullptr;
143 if (idx >= F->arg_size())
return nullptr;
144 return llvm::cast<llvm::Argument>(F->arg_begin() + idx);
147 inline llvm::Argument*
150 if (!F)
return nullptr;
151 for (
auto iter = F->arg_begin(); iter != F->arg_end(); ++iter) {
152 llvm::Argument* arg = llvm::cast<llvm::Argument>(iter);
153 if (arg->getName() == name)
return arg;
165 llvm::Type*
const typeB)
167 assert(typeA && (typeA->isIntegerTy() || typeA->isFloatingPointTy()) &&
168 "First Type in typePrecedence is not a scalar type");
169 assert(typeB && (typeB->isIntegerTy() || typeB->isFloatingPointTy()) &&
170 "Second Type in typePrecedence is not a scalar type");
175 if (typeA->isDoubleTy())
return typeA;
176 if (typeB->isDoubleTy())
return typeB;
178 if (typeA->isFloatTy())
return typeA;
179 if (typeB->isFloatTy())
return typeB;
181 if (typeA->isIntegerTy(64))
return typeA;
182 if (typeB->isIntegerTy(64))
return typeB;
184 if (typeA->isIntegerTy(32))
return typeA;
185 if (typeB->isIntegerTy(32))
return typeB;
187 if (typeA->isIntegerTy(16))
return typeA;
188 if (typeB->isIntegerTy(16))
return typeB;
190 if (typeA->isIntegerTy(8))
return typeA;
191 if (typeB->isIntegerTy(8))
return typeB;
193 if (typeA->isIntegerTy(1))
return typeA;
194 if (typeB->isIntegerTy(1))
return typeB;
196 assert(
false &&
"invalid LLVM type precedence");
211 const llvm::Type*
const targetType,
212 const std::string& twine =
"")
215 #define BIND_ARITHMETIC_CAST_OP(Function, Twine) \
216 std::bind(&Function, \
217 std::placeholders::_1, \
218 std::placeholders::_2, \
219 std::placeholders::_3, \
222 if (targetType->isDoubleTy()) {
230 else if (targetType->isFloatTy()) {
238 else if (targetType->isIntegerTy(64)) {
246 else if (targetType->isIntegerTy(32)) {
254 else if (targetType->isIntegerTy(16)) {
262 else if (targetType->isIntegerTy(8)) {
270 else if (targetType->isIntegerTy(1)) {
279 #undef BIND_ARITHMETIC_CAST_OP
280 assert(
false &&
"invalid LLVM type conversion");
301 const std::string& twine =
"")
304 #define BIND_BINARY_OP(Function) \
305 [twine](llvm::IRBuilder<>& B, llvm::Value* L, llvm::Value* R) \
306 -> llvm::Value* { return B.Function(L, R, twine); }
312 if (type->isFloatingPointTy()) {
315 &&
"unable to perform logical or bitwise operation on floating point values");
328 assert(
false &&
"unrecognised binary operator");
330 else if (type->isIntegerTy()) {
349 assert(
false &&
"unrecognised binary operator");
352 #undef BIND_BINARY_OP
353 assert(
false &&
"invalid LLVM type for binary operation");
361 assert(from &&
"llvm Type 'from' is null in isValidCast");
362 assert(to &&
"llvm Type 'to' is null in isValidCast");
364 if ((from->isIntegerTy() || from->isFloatingPointTy()) &&
365 (to->isIntegerTy() || to->isFloatingPointTy())) {
368 if (from->isArrayTy() && to->isArrayTy()) {
369 llvm::ArrayType* af = llvm::cast<llvm::ArrayType>(from);
370 llvm::ArrayType* at = llvm::cast<llvm::ArrayType>(to);
371 if (af->getArrayNumElements() == at->getArrayNumElements()) {
373 at->getArrayElementType());
388 llvm::Type* targetType,
389 llvm::IRBuilder<>& builder)
391 assert(value && (value->getType()->isIntegerTy() || value->getType()->isFloatingPointTy()) &&
392 "First Value in arithmeticConversion is not a scalar type");
393 assert(targetType && (targetType->isIntegerTy() || targetType->isFloatingPointTy()) &&
394 "Target Type in arithmeticConversion is not a scalar type");
396 const llvm::Type*
const valueType = value->getType();
397 if (valueType == targetType)
return value;
400 return llvmCastFunction(builder, value, targetType);
414 llvm::Type* targetElementType,
415 llvm::IRBuilder<>& builder)
417 assert(targetElementType && (targetElementType->isIntegerTy() ||
418 targetElementType->isFloatingPointTy()) &&
419 "Target element type is not a scalar type");
420 assert(ptrToArray && ptrToArray->getType()->isPointerTy() &&
421 "Input to arrayCast is not a pointer type.");
423 llvm::Type* arrayType = ptrToArray->getType()->getContainedType(0);
424 assert(arrayType && llvm::isa<llvm::ArrayType>(arrayType));
427 llvm::Type* sourceElementType = arrayType->getArrayElementType();
428 assert(sourceElementType && (sourceElementType->isIntegerTy() ||
429 sourceElementType->isFloatingPointTy()) &&
430 "Source element type is not a scalar type");
432 if (sourceElementType == targetElementType)
return ptrToArray;
436 const size_t elementSize = arrayType->getArrayNumElements();
437 llvm::Value* targetArray =
439 llvm::ArrayType::get(targetElementType, elementSize));
441 for (
size_t i = 0; i < elementSize; ++i) {
442 llvm::Value* target = builder.CreateConstGEP2_64(targetArray, 0, i);
443 llvm::Value* source = builder.CreateConstGEP2_64(ptrToArray, 0, i);
444 source = builder.CreateLoad(source);
445 source = llvmCastFunction(builder, source, targetElementType);
446 builder.CreateStore(source, target);
463 llvm::Type* targetElementType,
464 llvm::IRBuilder<>& builder)
466 assert(targetElementType && (targetElementType->isIntegerTy() ||
467 targetElementType->isFloatingPointTy()) &&
468 "Target element type is not a scalar type");
470 llvm::Type* sourceElementType = values.front()->getType();
471 assert(sourceElementType && (sourceElementType->isIntegerTy() ||
472 sourceElementType->isFloatingPointTy()) &&
473 "Source element type is not a scalar type");
475 if (sourceElementType == targetElementType)
return;
479 for (llvm::Value*& value : values) {
480 value = llvmCastFunction(builder, value, targetElementType);
492 llvm::IRBuilder<>& builder)
495 for (llvm::Value*& value : values) {
496 llvm::Type* type = value->getType();
497 if (type->isIntegerTy() || type->isFloatingPointTy()) {
516 llvm::Value*& valueB,
517 llvm::IRBuilder<>& builder)
519 llvm::Type* type =
typePrecedence(valueA->getType(), valueB->getType());
531 llvm::IRBuilder<>& builder)
533 llvm::Type* type = value->getType();
535 if (type->isFloatingPointTy())
return builder.CreateFCmpONE(value, llvm::ConstantFP::get(type, 0.0));
536 else if (type->isIntegerTy(1))
return builder.CreateICmpNE(value, llvm::ConstantInt::get(type, 0));
537 else if (type->isIntegerTy())
return builder.CreateICmpNE(value, llvm::ConstantInt::getSigned(type, 0));
538 assert(
false &&
"Invalid type for bool conversion");
553 llvm::IRBuilder<>& builder)
555 llvm::Type* lhsType = lhs->getType();
556 assert(lhsType == rhs->getType());
563 lhsType = lhs->getType();
567 return llvmBinaryFunction(builder, lhs, rhs);
580 llvm::IRBuilder<>& builder)
582 return builder.CreateConstGEP2_64(ptrToArray, 0, index);
597 std::vector<llvm::Value*>& values,
598 llvm::IRBuilder<>& builder,
599 const bool loadElements =
false)
601 const size_t elements =
602 ptrToArray->getType()->getContainedType(0)->getArrayNumElements();
604 values.reserve(elements);
605 for (
size_t i = 0; i < elements; ++i) {
606 llvm::Value* value = builder.CreateConstGEP2_64(ptrToArray, 0, i);
607 if (loadElements) value = builder.CreateLoad(value);
608 values.push_back(value);
624 llvm::Value*& value1,
625 llvm::Value*& value2,
626 llvm::Value*& value3,
627 llvm::IRBuilder<>& builder)
629 assert(ptrToArray && ptrToArray->getType()->isPointerTy() &&
630 "Input to array3Unpack is not a pointer type.");
632 value1 = builder.CreateConstGEP2_64(ptrToArray, 0, 0);
633 value2 = builder.CreateConstGEP2_64(ptrToArray, 0, 1);
634 value3 = builder.CreateConstGEP2_64(ptrToArray, 0, 2);
651 llvm::IRBuilder<>& builder)
653 llvm::Type* type =
typePrecedence(value1->getType(), value2->getType());
660 llvm::Type* vectorType = llvm::ArrayType::get(type, 3);
663 llvm::Value* e1 = builder.CreateConstGEP2_64(vector, 0, 0);
664 llvm::Value* e2 = builder.CreateConstGEP2_64(vector, 0, 1);
665 llvm::Value* e3 = builder.CreateConstGEP2_64(vector, 0, 2);
667 builder.CreateStore(value1, e1);
668 builder.CreateStore(value2, e2);
669 builder.CreateStore(value3, e3);
684 llvm::IRBuilder<>& builder,
685 const size_t size = 3)
687 assert(value && (value->getType()->isIntegerTy() ||
688 value->getType()->isFloatingPointTy()) &&
689 "value type is not a scalar type");
691 llvm::Type* type = value->getType();
694 llvm::ArrayType::get(type, size));
696 for (
size_t i = 0; i < size; ++i) {
697 llvm::Value* element = builder.CreateConstGEP2_64(array, 0, i);
698 builder.CreateStore(value, element);
712 llvm::IRBuilder<>& builder)
714 llvm::Type* type = values.front()->getType();
716 llvm::ArrayType::get(type, values.size()));
719 for (llvm::Value*
const& value : values) {
720 llvm::Value* element = builder.CreateConstGEP2_64(array, 0, idx++);
721 builder.CreateStore(value, element);
738 llvm::IRBuilder<>& builder)
743 for (llvm::Value*
const& value : values) {
749 for (llvm::Value*& value : values) {
758 llvm::IRBuilder<>& builder,
759 const size_t dim = 3)
761 assert(scalar && (scalar->getType()->isIntegerTy() ||
762 scalar->getType()->isFloatingPointTy()) &&
763 "value type is not a scalar type");
765 llvm::Type* type = scalar->getType();
768 llvm::ArrayType::get(type, dim*dim));
770 llvm::Value* zero = llvm::ConstantFP::get(type, 0.0);
772 for (
size_t i = 0; i < dim*dim; ++i) {
773 llvm::Value* m = ((i % (dim+1) == 0) ? scalar : zero);
774 llvm::Value* element = builder.CreateConstGEP2_64(array, 0, i);
775 builder.CreateStore(m, element);
Consolidated llvm types for most supported types.
@ BITOR
Definition: axparser.h:128
@ DIVIDE
Definition: axparser.h:142
@ LESSTHANOREQUAL
Definition: axparser.h:136
@ SHIFTRIGHT
Definition: axparser.h:138
@ MORETHANOREQUAL
Definition: axparser.h:135
@ EQUALSEQUALS
Definition: axparser.h:131
@ BITXOR
Definition: axparser.h:129
@ BITAND
Definition: axparser.h:130
@ AND
Definition: axparser.h:127
@ PLUS
Definition: axparser.h:139
@ LESSTHAN
Definition: axparser.h:134
@ OR
Definition: axparser.h:126
@ MODULO
Definition: axparser.h:143
@ MORETHAN
Definition: axparser.h:133
@ NOTEQUALS
Definition: axparser.h:132
@ MULTIPLY
Definition: axparser.h:141
@ SHIFTLEFT
Definition: axparser.h:137
@ MINUS
Definition: axparser.h:140
OperatorType operatorType(const OperatorToken token)
Definition: Tokens.h:210
OperatorToken
Definition: Tokens.h:151
OperatorType
Definition: Tokens.h:201
@ LOGICAL
Definition: Tokens.h:203
@ BITWISE
Definition: Tokens.h:205
void llvmTypeToString(const llvm::Type *const type, std::string &str)
Prints an llvm type to a std string.
Definition: openvdb_ax/openvdb_ax/codegen/Utils.h:70
llvm::Value * boolComparison(llvm::Value *value, llvm::IRBuilder<> &builder)
Performs a C style boolean comparison from a given scalar LLVM value.
Definition: openvdb_ax/openvdb_ax/codegen/Utils.h:530
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: openvdb_ax/openvdb_ax/codegen/Utils.h:596
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: openvdb_ax/openvdb_ax/codegen/Utils.h:413
llvm::Value * llvmPointerFromAddress(const ValueT *const &ptr, llvm::IRBuilder<> &builder)
Return an llvm value representing a pointer to the provided ptr builtin ValueT.
Definition: openvdb_ax/openvdb_ax/codegen/Utils.h:104
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: openvdb_ax/openvdb_ax/codegen/Utils.h:711
llvm::Argument * extractArgument(llvm::Function *F, const std::string &name)
Definition: openvdb_ax/openvdb_ax/codegen/Utils.h:148
llvm::Value * array3Pack(llvm::Value *value1, llvm::Value *value2, llvm::Value *value3, llvm::IRBuilder<> &builder)
Pack three values into a new array and return a pointer to the newly allocated array....
Definition: openvdb_ax/openvdb_ax/codegen/Utils.h:648
std::function< llvm::Value *(llvm::IRBuilder<> &, llvm::Value *, llvm::Type *)> CastFunction
Definition: openvdb_ax/openvdb_ax/codegen/Utils.h:44
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: openvdb_ax/openvdb_ax/codegen/Utils.h:737
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: openvdb_ax/openvdb_ax/codegen/Utils.h:55
llvm::Value * scalarToMatrix(llvm::Value *scalar, llvm::IRBuilder<> &builder, const size_t dim=3)
Definition: openvdb_ax/openvdb_ax/codegen/Utils.h:757
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: openvdb_ax/openvdb_ax/codegen/Utils.h:623
BinaryFunction llvmBinaryConversion(const llvm::Type *const type, const ast::tokens::OperatorToken &token, const std::string &twine="")
Returns a BinaryFunction representing the corresponding instruction to peform on two scalar values,...
Definition: openvdb_ax/openvdb_ax/codegen/Utils.h:299
llvm::Type * typePrecedence(llvm::Type *const typeA, llvm::Type *const typeB)
Returns the highest order type from two LLVM Scalar types.
Definition: openvdb_ax/openvdb_ax/codegen/Utils.h:164
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: openvdb_ax/openvdb_ax/codegen/Utils.h:123
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: openvdb_ax/openvdb_ax/codegen/Utils.h:515
llvm::Value * binaryOperator(llvm::Value *lhs, llvm::Value *rhs, const ast::tokens::OperatorToken &token, llvm::IRBuilder<> &builder)
Definition: openvdb_ax/openvdb_ax/codegen/Utils.h:551
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: openvdb_ax/openvdb_ax/codegen/Utils.h:578
bool isValidCast(llvm::Type *from, llvm::Type *to)
Returns true if the llvm Type 'from' can be safely cast to the llvm Type 'to'.
Definition: openvdb_ax/openvdb_ax/codegen/Utils.h:359
llvm::Type * getBaseContainedType(llvm::Type *const type)
Return the base llvm value which is being pointed to through any number of layered pointers.
Definition: openvdb_ax/openvdb_ax/codegen/Utils.h:84
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: openvdb_ax/openvdb_ax/codegen/Utils.h:210
std::function< llvm::Value *(llvm::IRBuilder<> &, llvm::Value *, llvm::Value *)> BinaryFunction
Definition: openvdb_ax/openvdb_ax/codegen/Utils.h:47
Definition: openvdb/Exceptions.h:13
#define BIND_ARITHMETIC_CAST_OP(Function, Twine)
#define BIND_BINARY_OP(Function)
LLVM type mapping from pod types.
Definition: ax/openvdb_ax/codegen/Types.h:55
Library and file format version numbers.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:101
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:153