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" 20 #include <openvdb/version.h> 23 #include <llvm/IR/IRBuilder.h> 24 #include <llvm/IR/LLVMContext.h> 32 #include <llvm/Support/raw_ostream.h> 45 (llvm::IRBuilder<>&, llvm::Value*, llvm::Type*)>;
48 (llvm::IRBuilder<>&, llvm::Value*, llvm::Value*)>;
55 inline auto ir_load(llvm::IRBuilder<>& B, llvm::Value* ptr,
const char*
Name =
"")
59 #if LLVM_VERSION_MAJOR <= 7 60 return B.CreateLoad(ptr,
Name);
62 return B.CreateLoad(ptr->getType()->getPointerElementType(), ptr,
Name);
67 inline auto ir_gep(llvm::IRBuilder<>& B,
68 llvm::Value* ptr, llvm::ArrayRef<llvm::Value*> IdxList,
const char*
Name =
"")
73 #if LLVM_VERSION_MAJOR <= 7 74 return B.CreateGEP(ptr, IdxList,
Name);
76 return B.CreateGEP(ptr->getType()->getScalarType()->getPointerElementType(),
83 llvm::Value* ptr, uint64_t Idx0, uint64_t Idx1,
const char*
Name =
"")
88 #if LLVM_VERSION_MAJOR <= 7 89 return B.CreateConstGEP2_64(ptr, Idx0, Idx1,
Name);
91 return B.CreateConstGEP2_64(
92 ptr->getType()->getScalarType()->getPointerElementType(), ptr, Idx0,
99 llvm::Value* ptr, uint64_t Idx0, uint64_t Idx1,
const char*
Name =
"")
104 #if LLVM_VERSION_MAJOR <= 7 105 return B.CreateConstInBoundsGEP2_64(ptr, Idx0, Idx1,
Name);
107 return B.CreateConstInBoundsGEP2_64(
108 ptr->getType()->getScalarType()->getPointerElementType(), ptr, Idx0,
120 std::vector<llvm::Type*>& types)
122 types.reserve(values.size());
123 for (
const auto& v : values) {
124 types.emplace_back(v->getType());
136 llvm::raw_string_ostream os(str);
150 llvm::Type* elementType = type;
151 while (elementType->isPointerTy()) {
152 elementType = elementType->getContainedType(0);
166 template <
typename ValueT>
169 llvm::IRBuilder<>& builder)
171 llvm::Value* address =
172 llvm::ConstantInt::get(llvm::Type::getIntNTy(builder.getContext(),
sizeof(uintptr_t)*8),
173 reinterpret_cast<uintptr_t
>(ptr));
189 llvm::Value* size =
nullptr)
193 llvm::Function* parent = B.GetInsertBlock()->getParent();
195 auto IP = B.saveIP();
196 llvm::BasicBlock& block = parent->front();
197 if (block.empty()) B.SetInsertPoint(&block);
198 else B.SetInsertPoint(&(block.front()));
199 llvm::Value* result = B.CreateAlloca(type, size);
206 if (type == strtype) {
207 llvm::Value* cptr = B.CreateStructGEP(strtype, result, 0);
208 llvm::Value* sso = B.CreateStructGEP(strtype, result, 1);
210 llvm::Value* len = B.CreateStructGEP(strtype, result, 2);
211 B.CreateStore(sso_load, cptr);
212 B.CreateStore(B.getInt64(0), len);
218 inline llvm::Argument*
221 if (!F)
return nullptr;
222 if (idx >= F->arg_size())
return nullptr;
223 return llvm::cast<llvm::Argument>(F->arg_begin() + idx);
226 inline llvm::Argument*
229 if (!F)
return nullptr;
230 for (
auto iter = F->arg_begin(); iter != F->arg_end(); ++iter) {
231 llvm::Argument* arg = llvm::cast<llvm::Argument>(iter);
232 if (arg->getName() == name)
return arg;
244 llvm::Type*
const typeB)
246 OPENVDB_ASSERT(typeA && (typeA->isIntegerTy() || typeA->isFloatingPointTy()) &&
247 "First Type in typePrecedence is not a scalar type");
248 OPENVDB_ASSERT(typeB && (typeB->isIntegerTy() || typeB->isFloatingPointTy()) &&
249 "Second Type in typePrecedence is not a scalar type");
254 if (typeA->isDoubleTy())
return typeA;
255 if (typeB->isDoubleTy())
return typeB;
257 if (typeA->isFloatTy())
return typeA;
258 if (typeB->isFloatTy())
return typeB;
260 if (typeA->isIntegerTy(64))
return typeA;
261 if (typeB->isIntegerTy(64))
return typeB;
263 if (typeA->isIntegerTy(32))
return typeA;
264 if (typeB->isIntegerTy(32))
return typeB;
266 if (typeA->isIntegerTy(16))
return typeA;
267 if (typeB->isIntegerTy(16))
return typeB;
269 if (typeA->isIntegerTy(8))
return typeA;
270 if (typeB->isIntegerTy(8))
return typeB;
272 if (typeA->isIntegerTy(1))
return typeA;
273 if (typeB->isIntegerTy(1))
return typeB;
290 const llvm::Type*
const targetType,
291 const std::string& twine =
"")
294 #define BIND_ARITHMETIC_CAST_OP(Function, Twine) \ 295 std::bind(&Function, \ 296 std::placeholders::_1, \ 297 std::placeholders::_2, \ 298 std::placeholders::_3, \ 301 if (targetType->isDoubleTy()) {
310 else if (targetType->isFloatTy()) {
319 else if (targetType->isHalfTy()) {
328 else if (targetType->isIntegerTy(64)) {
337 else if (targetType->isIntegerTy(32)) {
346 else if (targetType->isIntegerTy(16)) {
355 else if (targetType->isIntegerTy(8)) {
364 else if (targetType->isIntegerTy(1)) {
374 #undef BIND_ARITHMETIC_CAST_OP 396 const std::string& twine =
"")
399 #define BIND_BINARY_OP(Function) \ 400 [twine](llvm::IRBuilder<>& B, llvm::Value* L, llvm::Value* R) \ 401 -> llvm::Value* { return B.Function(L, R, twine); } 407 if (type->isFloatingPointTy()) {
410 &&
"unable to perform logical or bitwise operation on floating point values");
425 else if (type->isIntegerTy()) {
447 #undef BIND_BINARY_OP 448 OPENVDB_ASSERT(
false &&
"invalid LLVM type for binary operation");
456 OPENVDB_ASSERT(from &&
"llvm Type 'from' is null in isValidCast");
459 if ((from->isIntegerTy() || from->isFloatingPointTy()) &&
460 (to->isIntegerTy() || to->isFloatingPointTy())) {
463 if (from->isArrayTy() && to->isArrayTy()) {
464 llvm::ArrayType* af = llvm::cast<llvm::ArrayType>(from);
465 llvm::ArrayType* at = llvm::cast<llvm::ArrayType>(to);
466 if (af->getArrayNumElements() == at->getArrayNumElements()) {
468 at->getArrayElementType());
482 llvm::Type* targetType,
483 llvm::IRBuilder<>& builder)
485 OPENVDB_ASSERT(value && (value->getType()->isIntegerTy() || value->getType()->isFloatingPointTy()) &&
486 "First Value in arithmeticConversion is not a scalar type");
487 OPENVDB_ASSERT(targetType && (targetType->isIntegerTy() || targetType->isFloatingPointTy()) &&
488 "Target Type in arithmeticConversion is not a scalar type");
490 const llvm::Type*
const valueType = value->getType();
491 if (valueType == targetType)
return value;
494 return llvmCastFunction(builder, value, targetType);
508 llvm::Type* targetElementType,
509 llvm::IRBuilder<>& builder)
511 OPENVDB_ASSERT(targetElementType && (targetElementType->isIntegerTy() ||
512 targetElementType->isFloatingPointTy()) &&
513 "Target element type is not a scalar type");
514 OPENVDB_ASSERT(ptrToArray && ptrToArray->getType()->isPointerTy() &&
515 "Input to arrayCast is not a pointer type.");
517 llvm::Type* arrayType = ptrToArray->getType()->getContainedType(0);
518 OPENVDB_ASSERT(arrayType && llvm::isa<llvm::ArrayType>(arrayType));
521 llvm::Type* sourceElementType = arrayType->getArrayElementType();
522 OPENVDB_ASSERT(sourceElementType && (sourceElementType->isIntegerTy() ||
523 sourceElementType->isFloatingPointTy()) &&
524 "Source element type is not a scalar type");
526 if (sourceElementType == targetElementType)
return ptrToArray;
530 const size_t elementSize = arrayType->getArrayNumElements();
531 llvm::Value* targetArray =
533 llvm::ArrayType::get(targetElementType, elementSize));
535 for (
size_t i = 0; i < elementSize; ++i) {
538 source =
ir_load(builder, source);
539 source = llvmCastFunction(builder, source, targetElementType);
540 builder.CreateStore(source, target);
556 llvm::Type* targetElementType,
557 llvm::IRBuilder<>& builder)
559 OPENVDB_ASSERT(targetElementType && (targetElementType->isIntegerTy() ||
560 targetElementType->isFloatingPointTy()) &&
561 "Target element type is not a scalar type");
563 llvm::Type* sourceElementType = values.front()->getType();
564 OPENVDB_ASSERT(sourceElementType && (sourceElementType->isIntegerTy() ||
565 sourceElementType->isFloatingPointTy()) &&
566 "Source element type is not a scalar type");
568 if (sourceElementType == targetElementType)
return;
572 for (llvm::Value*& value : values) {
573 value = llvmCastFunction(builder, value, targetElementType);
584 llvm::IRBuilder<>& builder)
587 for (llvm::Value*& value : values) {
588 llvm::Type* type = value->getType();
589 if (type->isIntegerTy() || type->isFloatingPointTy()) {
607 llvm::Value*& valueB,
608 llvm::IRBuilder<>& builder)
610 llvm::Type* type =
typePrecedence(valueA->getType(), valueB->getType());
622 llvm::IRBuilder<>& builder)
624 llvm::Type* type = value->getType();
626 if (type->isFloatingPointTy())
return builder.CreateFCmpONE(value, llvm::ConstantFP::get(type, 0.0));
627 else if (type->isIntegerTy(1))
return builder.CreateICmpNE(value, llvm::ConstantInt::get(type, 0));
628 else if (type->isIntegerTy())
return builder.CreateICmpNE(value, llvm::ConstantInt::getSigned(type, 0));
644 llvm::IRBuilder<>& builder)
646 llvm::Type* lhsType = lhs->getType();
656 lhsType = lhs->getType();
660 return llvmBinaryFunction(builder, lhs, rhs);
673 llvm::IRBuilder<>& builder)
690 std::vector<llvm::Value*>& values,
691 llvm::IRBuilder<>& builder,
692 const bool loadElements =
false)
694 const size_t elements =
695 ptrToArray->getType()->getContainedType(0)->getArrayNumElements();
697 values.reserve(elements);
698 for (
size_t i = 0; i < elements; ++i) {
700 if (loadElements) value =
ir_load(builder, value);
701 values.push_back(value);
717 llvm::Value*& value1,
718 llvm::Value*& value2,
719 llvm::Value*& value3,
720 llvm::IRBuilder<>& builder)
722 OPENVDB_ASSERT(ptrToArray && ptrToArray->getType()->isPointerTy() &&
723 "Input to array3Unpack is not a pointer type.");
744 llvm::IRBuilder<>& builder)
746 llvm::Type* type =
typePrecedence(value1->getType(), value2->getType());
753 llvm::Type* vectorType = llvm::ArrayType::get(type, 3);
760 builder.CreateStore(value1, e1);
761 builder.CreateStore(value2, e2);
762 builder.CreateStore(value3, e3);
777 llvm::IRBuilder<>& builder,
778 const size_t size = 3)
781 value->getType()->isFloatingPointTy()) &&
782 "value type is not a scalar type");
784 llvm::Type* type = value->getType();
787 llvm::ArrayType::get(type, size));
789 for (
size_t i = 0; i < size; ++i) {
791 builder.CreateStore(value, element);
805 llvm::IRBuilder<>& builder)
807 llvm::Type* type = values.front()->getType();
809 llvm::ArrayType::get(type, values.size()));
812 for (llvm::Value*
const& value : values) {
814 builder.CreateStore(value, element);
831 llvm::IRBuilder<>& builder)
836 for (llvm::Value*
const& value : values) {
842 for (llvm::Value*& value : values) {
851 llvm::IRBuilder<>& builder,
852 const size_t dim = 3)
855 scalar->getType()->isFloatingPointTy()) &&
856 "value type is not a scalar type");
858 llvm::Type* type = scalar->getType();
861 llvm::ArrayType::get(type, dim*dim));
864 for (
size_t i = 0; i < dim*dim; ++i) {
865 llvm::Value* m = ((i % (dim+1) == 0) ? scalar : zero);
867 builder.CreateStore(m, element);
878 #endif // OPENVDB_AX_CODEGEN_UTILS_HAS_BEEN_INCLUDED void valuesToTypes(const std::vector< llvm::Value * > &values, std::vector< llvm::Type * > &types)
Populate a vector of llvm Types from a vector of llvm values.
Definition: Utils.h:119
Definition: axparser.h:140
OperatorType
Definition: Tokens.h:200
llvm::Type * getBaseContainedType(llvm::Type *const type)
Return the base llvm value which is being pointed to through any number of layered pointers...
Definition: Utils.h:148
#define BIND_ARITHMETIC_CAST_OP(Function, Twine)
LLVM type mapping from pod types.
Definition: Types.h:55
OperatorType operatorType(const OperatorToken token)
Definition: Tokens.h:210
void arrayUnpack(llvm::Value *ptrToArray, std::vector< llvm::Value * > &values, llvm::IRBuilder<> &builder, const bool loadElements=false)
Unpack an array type into llvm Values which represent all its elements The provided llvm Value is exp...
Definition: Utils.h:689
#define BIND_BINARY_OP(Function)
bool isValidCast(llvm::Type *from, llvm::Type *to)
Returns true if the llvm Type 'from' can be safely cast to the llvm Type 'to'.
Definition: Utils.h:454
Definition: axparser.h:141
Definition: axparser.h:147
std::function< llvm::Value *(llvm::IRBuilder<> &, llvm::Value *, llvm::Type *)> CastFunction
Definition: Utils.h:45
Definition: axparser.h:144
std::function< llvm::Value *(llvm::IRBuilder<> &, llvm::Value *, llvm::Value *)> BinaryFunction
Definition: Utils.h:48
Definition: axparser.h:136
llvm::Type * typePrecedence(llvm::Type *const typeA, llvm::Type *const typeB)
Returns the highest order type from two LLVM Scalar types.
Definition: Utils.h:243
Definition: axparser.h:145
Consolidated llvm types for most supported types.
void array3Unpack(llvm::Value *ptrToArray, llvm::Value *&value1, llvm::Value *&value2, llvm::Value *&value3, llvm::IRBuilder<> &builder)
Unpack the first three elements of an array. The provided llvm Value is expected to be a pointer to a...
Definition: Utils.h:716
llvm::Argument * extractArgument(llvm::Function *F, const std::string &name)
Definition: Utils.h:227
Definition: axparser.h:143
auto ir_gep(llvm::IRBuilder<> &B, llvm::Value *ptr, llvm::ArrayRef< llvm::Value * > IdxList, const char *Name="")
Alias around IR gep inst.
Definition: Utils.h:67
llvm::Constant * llvmConstant(const T t, llvm::Type *type)
Returns an llvm Constant holding a scalar value.
Definition: Types.h:329
auto ir_constgep2_64(llvm::IRBuilder<> &B, llvm::Value *ptr, uint64_t Idx0, uint64_t Idx1, const char *Name="")
Alias around IR gep2_64 inst.
Definition: Utils.h:82
llvm::Value * arrayPackCast(std::vector< llvm::Value * > &values, llvm::IRBuilder<> &builder)
Pack a vector of loaded llvm scalar values into a new array of equal size and return a pointer to the...
Definition: Utils.h:830
void arithmeticConversion(llvm::Value *&valueA, llvm::Value *&valueB, llvm::IRBuilder<> &builder)
Chooses the highest order llvm Type as defined by typePrecedence from either of the two incoming valu...
Definition: Utils.h:606
llvm::Value * llvmPointerFromAddress(const ValueT *const &ptr, llvm::IRBuilder<> &builder)
Return an llvm value representing a pointer to the provided ptr builtin ValueT.
Definition: Utils.h:168
Definition: axparser.h:151
Definition: axparser.h:137
llvm::Value * insertStaticAlloca(llvm::IRBuilder<> &B, llvm::Type *type, llvm::Value *size=nullptr)
Insert a stack allocation at the beginning of the current function of the provided type and size...
Definition: Utils.h:187
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
Definition: axparser.h:146
auto ir_load(llvm::IRBuilder<> &B, llvm::Value *ptr, const char *Name="")
Alias around IR load inst.
Definition: Utils.h:55
llvm::Value * arrayPack(const std::vector< llvm::Value * > &values, llvm::IRBuilder<> &builder)
Pack a vector of loaded llvm scalar values into a new array of equal size and return a pointer to the...
Definition: Utils.h:804
Definition: Exceptions.h:13
BinaryFunction llvmBinaryConversion(const llvm::Type *const type, const ast::tokens::OperatorToken &token, const std::string &twine="")
Returns a BinaryFunction representing the corresponding instruction to perform on two scalar values...
Definition: Utils.h:394
llvm::Value * array3Pack(llvm::Value *value1, llvm::Value *value2, llvm::Value *value3, llvm::IRBuilder<> &builder)
Pack three values into a new array and return a pointer to the newly allocated array. If the values are of a mismatching type, the highets order type is uses, as defined by typePrecedence. All llvm values are expected to a be a loaded scalar type.
Definition: Utils.h:741
Definition: axparser.h:135
Definition: axparser.h:150
llvm::Value * arrayCast(llvm::Value *ptrToArray, llvm::Type *targetElementType, llvm::IRBuilder<> &builder)
Casts an array to another array of equal size but of a different element type. Both source and target...
Definition: Utils.h:507
llvm::Value * arrayIndexUnpack(llvm::Value *ptrToArray, const int16_t index, llvm::IRBuilder<> &builder)
Unpack a particular element of an array and return a pointer to that element The provided llvm Value ...
Definition: Utils.h:671
Definition: axparser.h:142
Definition: axparser.h:149
Definition: axparser.h:148
CastFunction llvmArithmeticConversion(const llvm::Type *const sourceType, const llvm::Type *const targetType, const std::string &twine="")
Returns a CastFunction which represents the corresponding instruction to convert a source llvm Type t...
Definition: Utils.h:289
auto ir_constinboundsgep2_64(llvm::IRBuilder<> &B, llvm::Value *ptr, uint64_t Idx0, uint64_t Idx1, const char *Name="")
Alias around IR in bounds gep2_64 inst.
Definition: Utils.h:98
llvm::Value * scalarToMatrix(llvm::Value *scalar, llvm::IRBuilder<> &builder, const size_t dim=3)
Definition: Utils.h:850
Definition: axparser.h:139
Definition: axparser.h:152
llvm::Value * boolComparison(llvm::Value *value, llvm::IRBuilder<> &builder)
Performs a C style boolean comparison from a given scalar LLVM value.
Definition: Utils.h:621
Definition: axparser.h:138
llvm::Value * binaryOperator(llvm::Value *lhs, llvm::Value *rhs, const ast::tokens::OperatorToken &token, llvm::IRBuilder<> &builder)
Definition: Utils.h:642
std::string Name
Definition: Name.h:19
void llvmTypeToString(const llvm::Type *const type, std::string &str)
Prints an llvm type to a std string.
Definition: Utils.h:134
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
OperatorToken
Definition: Tokens.h:150
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218