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>
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)
129 llvm::Function* parent = B.GetInsertBlock()->getParent();
130 assert(parent && !parent->empty());
131 auto IP = B.saveIP();
132 llvm::BasicBlock& block = parent->front();
133 if (block.empty()) B.SetInsertPoint(&block);
134 else B.SetInsertPoint(&(block.front()));
135 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);
145 llvm::Value* sso_load = B.CreateConstGEP2_64(sso, 0 ,0);
146 llvm::Value* len = B.CreateStructGEP(strtype, result, 2);
147 B.CreateStore(sso_load, cptr);
148 B.CreateStore(B.getInt64(0), len);
154 inline llvm::Argument*
157 if (!F)
return nullptr;
158 if (idx >= F->arg_size())
return nullptr;
159 return llvm::cast<llvm::Argument>(F->arg_begin() + idx);
162 inline llvm::Argument*
165 if (!F)
return nullptr;
166 for (
auto iter = F->arg_begin(); iter != F->arg_end(); ++iter) {
167 llvm::Argument* arg = llvm::cast<llvm::Argument>(iter);
168 if (arg->getName() == name)
return arg;
180 llvm::Type*
const typeB)
182 assert(typeA && (typeA->isIntegerTy() || typeA->isFloatingPointTy()) &&
183 "First Type in typePrecedence is not a scalar type");
184 assert(typeB && (typeB->isIntegerTy() || typeB->isFloatingPointTy()) &&
185 "Second Type in typePrecedence is not a scalar type");
190 if (typeA->isDoubleTy())
return typeA;
191 if (typeB->isDoubleTy())
return typeB;
193 if (typeA->isFloatTy())
return typeA;
194 if (typeB->isFloatTy())
return typeB;
196 if (typeA->isIntegerTy(64))
return typeA;
197 if (typeB->isIntegerTy(64))
return typeB;
199 if (typeA->isIntegerTy(32))
return typeA;
200 if (typeB->isIntegerTy(32))
return typeB;
202 if (typeA->isIntegerTy(16))
return typeA;
203 if (typeB->isIntegerTy(16))
return typeB;
205 if (typeA->isIntegerTy(8))
return typeA;
206 if (typeB->isIntegerTy(8))
return typeB;
208 if (typeA->isIntegerTy(1))
return typeA;
209 if (typeB->isIntegerTy(1))
return typeB;
211 assert(
false &&
"invalid LLVM type precedence");
226 const llvm::Type*
const targetType,
227 const std::string& twine =
"")
230 #define BIND_ARITHMETIC_CAST_OP(Function, Twine) \
231 std::bind(&Function, \
232 std::placeholders::_1, \
233 std::placeholders::_2, \
234 std::placeholders::_3, \
237 if (targetType->isDoubleTy()) {
245 else if (targetType->isFloatTy()) {
253 else if (targetType->isIntegerTy(64)) {
261 else if (targetType->isIntegerTy(32)) {
269 else if (targetType->isIntegerTy(16)) {
277 else if (targetType->isIntegerTy(8)) {
285 else if (targetType->isIntegerTy(1)) {
294 #undef BIND_ARITHMETIC_CAST_OP
295 assert(
false &&
"invalid LLVM type conversion");
316 const std::string& twine =
"")
319 #define BIND_BINARY_OP(Function) \
320 [twine](llvm::IRBuilder<>& B, llvm::Value* L, llvm::Value* R) \
321 -> llvm::Value* { return B.Function(L, R, twine); }
327 if (type->isFloatingPointTy()) {
330 &&
"unable to perform logical or bitwise operation on floating point values");
343 assert(
false &&
"unrecognised binary operator");
345 else if (type->isIntegerTy()) {
364 assert(
false &&
"unrecognised binary operator");
367 #undef BIND_BINARY_OP
368 assert(
false &&
"invalid LLVM type for binary operation");
376 assert(from &&
"llvm Type 'from' is null in isValidCast");
377 assert(to &&
"llvm Type 'to' is null in isValidCast");
379 if ((from->isIntegerTy() || from->isFloatingPointTy()) &&
380 (to->isIntegerTy() || to->isFloatingPointTy())) {
383 if (from->isArrayTy() && to->isArrayTy()) {
384 llvm::ArrayType* af = llvm::cast<llvm::ArrayType>(from);
385 llvm::ArrayType* at = llvm::cast<llvm::ArrayType>(to);
386 if (af->getArrayNumElements() == at->getArrayNumElements()) {
388 at->getArrayElementType());
403 llvm::Type* targetType,
404 llvm::IRBuilder<>& builder)
406 assert(value && (value->getType()->isIntegerTy() || value->getType()->isFloatingPointTy()) &&
407 "First Value in arithmeticConversion is not a scalar type");
408 assert(targetType && (targetType->isIntegerTy() || targetType->isFloatingPointTy()) &&
409 "Target Type in arithmeticConversion is not a scalar type");
411 const llvm::Type*
const valueType = value->getType();
412 if (valueType == targetType)
return value;
415 return llvmCastFunction(builder, value, targetType);
429 llvm::Type* targetElementType,
430 llvm::IRBuilder<>& builder)
432 assert(targetElementType && (targetElementType->isIntegerTy() ||
433 targetElementType->isFloatingPointTy()) &&
434 "Target element type is not a scalar type");
435 assert(ptrToArray && ptrToArray->getType()->isPointerTy() &&
436 "Input to arrayCast is not a pointer type.");
438 llvm::Type* arrayType = ptrToArray->getType()->getContainedType(0);
439 assert(arrayType && llvm::isa<llvm::ArrayType>(arrayType));
442 llvm::Type* sourceElementType = arrayType->getArrayElementType();
443 assert(sourceElementType && (sourceElementType->isIntegerTy() ||
444 sourceElementType->isFloatingPointTy()) &&
445 "Source element type is not a scalar type");
447 if (sourceElementType == targetElementType)
return ptrToArray;
451 const size_t elementSize = arrayType->getArrayNumElements();
452 llvm::Value* targetArray =
454 llvm::ArrayType::get(targetElementType, elementSize));
456 for (
size_t i = 0; i < elementSize; ++i) {
457 llvm::Value* target = builder.CreateConstGEP2_64(targetArray, 0, i);
458 llvm::Value* source = builder.CreateConstGEP2_64(ptrToArray, 0, i);
459 source = builder.CreateLoad(source);
460 source = llvmCastFunction(builder, source, targetElementType);
461 builder.CreateStore(source, target);
478 llvm::Type* targetElementType,
479 llvm::IRBuilder<>& builder)
481 assert(targetElementType && (targetElementType->isIntegerTy() ||
482 targetElementType->isFloatingPointTy()) &&
483 "Target element type is not a scalar type");
485 llvm::Type* sourceElementType = values.front()->getType();
486 assert(sourceElementType && (sourceElementType->isIntegerTy() ||
487 sourceElementType->isFloatingPointTy()) &&
488 "Source element type is not a scalar type");
490 if (sourceElementType == targetElementType)
return;
494 for (llvm::Value*& value : values) {
495 value = llvmCastFunction(builder, value, targetElementType);
507 llvm::IRBuilder<>& builder)
510 for (llvm::Value*& value : values) {
511 llvm::Type* type = value->getType();
512 if (type->isIntegerTy() || type->isFloatingPointTy()) {
531 llvm::Value*& valueB,
532 llvm::IRBuilder<>& builder)
534 llvm::Type* type =
typePrecedence(valueA->getType(), valueB->getType());
546 llvm::IRBuilder<>& builder)
548 llvm::Type* type = value->getType();
550 if (type->isFloatingPointTy())
return builder.CreateFCmpONE(value, llvm::ConstantFP::get(type, 0.0));
551 else if (type->isIntegerTy(1))
return builder.CreateICmpNE(value, llvm::ConstantInt::get(type, 0));
552 else if (type->isIntegerTy())
return builder.CreateICmpNE(value, llvm::ConstantInt::getSigned(type, 0));
553 assert(
false &&
"Invalid type for bool conversion");
568 llvm::IRBuilder<>& builder)
570 llvm::Type* lhsType = lhs->getType();
571 assert(lhsType == rhs->getType() ||
580 lhsType = lhs->getType();
584 return llvmBinaryFunction(builder, lhs, rhs);
597 llvm::IRBuilder<>& builder)
599 return builder.CreateConstGEP2_64(ptrToArray, 0, index);
614 std::vector<llvm::Value*>& values,
615 llvm::IRBuilder<>& builder,
616 const bool loadElements =
false)
618 const size_t elements =
619 ptrToArray->getType()->getContainedType(0)->getArrayNumElements();
621 values.reserve(elements);
622 for (
size_t i = 0; i < elements; ++i) {
623 llvm::Value* value = builder.CreateConstGEP2_64(ptrToArray, 0, i);
624 if (loadElements) value = builder.CreateLoad(value);
625 values.push_back(value);
641 llvm::Value*& value1,
642 llvm::Value*& value2,
643 llvm::Value*& value3,
644 llvm::IRBuilder<>& builder)
646 assert(ptrToArray && ptrToArray->getType()->isPointerTy() &&
647 "Input to array3Unpack is not a pointer type.");
649 value1 = builder.CreateConstGEP2_64(ptrToArray, 0, 0);
650 value2 = builder.CreateConstGEP2_64(ptrToArray, 0, 1);
651 value3 = builder.CreateConstGEP2_64(ptrToArray, 0, 2);
668 llvm::IRBuilder<>& builder)
670 llvm::Type* type =
typePrecedence(value1->getType(), value2->getType());
677 llvm::Type* vectorType = llvm::ArrayType::get(type, 3);
680 llvm::Value* e1 = builder.CreateConstGEP2_64(vector, 0, 0);
681 llvm::Value* e2 = builder.CreateConstGEP2_64(vector, 0, 1);
682 llvm::Value* e3 = builder.CreateConstGEP2_64(vector, 0, 2);
684 builder.CreateStore(value1, e1);
685 builder.CreateStore(value2, e2);
686 builder.CreateStore(value3, e3);
701 llvm::IRBuilder<>& builder,
702 const size_t size = 3)
704 assert(value && (value->getType()->isIntegerTy() ||
705 value->getType()->isFloatingPointTy()) &&
706 "value type is not a scalar type");
708 llvm::Type* type = value->getType();
711 llvm::ArrayType::get(type, size));
713 for (
size_t i = 0; i < size; ++i) {
714 llvm::Value* element = builder.CreateConstGEP2_64(array, 0, i);
715 builder.CreateStore(value, element);
729 llvm::IRBuilder<>& builder)
731 llvm::Type* type = values.front()->getType();
733 llvm::ArrayType::get(type, values.size()));
736 for (llvm::Value*
const& value : values) {
737 llvm::Value* element = builder.CreateConstGEP2_64(array, 0, idx++);
738 builder.CreateStore(value, element);
755 llvm::IRBuilder<>& builder)
760 for (llvm::Value*
const& value : values) {
766 for (llvm::Value*& value : values) {
775 llvm::IRBuilder<>& builder,
776 const size_t dim = 3)
778 assert(scalar && (scalar->getType()->isIntegerTy() ||
779 scalar->getType()->isFloatingPointTy()) &&
780 "value type is not a scalar type");
782 llvm::Type* type = scalar->getType();
785 llvm::ArrayType::get(type, dim*dim));
788 for (
size_t i = 0; i < dim*dim; ++i) {
789 llvm::Value* m = ((i % (dim+1) == 0) ? scalar : zero);
790 llvm::Value* element = builder.CreateConstGEP2_64(array, 0, i);
791 builder.CreateStore(m, element);
802 #endif // OPENVDB_AX_CODEGEN_UTILS_HAS_BEEN_INCLUDED