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> 25 #include <llvm/Support/raw_ostream.h> 38 (llvm::IRBuilder<>&, llvm::Value*, llvm::Type*)>;
41 (llvm::IRBuilder<>&, llvm::Value*, llvm::Value*)>;
43 inline bool AssertOpaquePtrs([[maybe_unused]]llvm::Value* opaque, [[maybe_unused]]llvm::Type* type)
45 #if LLVM_VERSION_MAJOR <= 15 46 if (opaque->getType()->getPointerElementType() != type) {
47 #ifdef OPENVDB_ENABLE_ASSERTS 48 llvm::errs() <<
"Opaque ptr check failed:\n";
49 llvm::errs() <<
"Input Value: "; opaque->print(llvm::errs()); llvm::errs() <<
"\n";
50 llvm::errs() <<
"Input Ptr Type: "; opaque->getType()->getPointerElementType()->print(llvm::errs()); llvm::errs() <<
"\n";
51 llvm::errs() <<
"Type: "; type->print(llvm::errs()); llvm::errs() <<
"\n";
66 std::vector<llvm::Type*>& types)
68 types.reserve(values.size());
69 for (
const auto& v : values) {
70 types.emplace_back(v->getType());
82 llvm::raw_string_ostream os(str);
96 template <
typename ValueT>
99 llvm::IRBuilder<>& builder)
101 llvm::Value* address =
102 llvm::ConstantInt::get(llvm::Type::getIntNTy(builder.getContext(),
sizeof(uintptr_t)*8),
103 reinterpret_cast<uintptr_t
>(ptr));
119 llvm::Value* size =
nullptr)
123 llvm::Function* parent = B.GetInsertBlock()->getParent();
125 auto IP = B.saveIP();
126 llvm::BasicBlock& block = parent->front();
127 if (block.empty()) B.SetInsertPoint(&block);
128 else B.SetInsertPoint(&(block.front()));
129 llvm::Value* result = B.CreateAlloca(type, size);
136 if (type == strtype) {
137 llvm::Value* cptr = B.CreateStructGEP(strtype, result, 0);
138 llvm::Value* sso = B.CreateStructGEP(strtype, result, 1);
139 llvm::Value* sso_load = B.CreateConstGEP2_64(strtype->getTypeAtIndex(1), sso, 0, 0);
140 llvm::Value* len = B.CreateStructGEP(strtype, result, 2);
141 B.CreateStore(sso_load, cptr);
142 B.CreateStore(B.getInt64(0), len);
148 inline llvm::Argument*
151 if (!F)
return nullptr;
152 if (idx >= F->arg_size())
return nullptr;
153 return llvm::cast<llvm::Argument>(F->arg_begin() + idx);
156 inline llvm::Argument*
159 if (!F)
return nullptr;
160 for (
auto iter = F->arg_begin(); iter != F->arg_end(); ++iter) {
161 llvm::Argument* arg = llvm::cast<llvm::Argument>(iter);
162 if (arg->getName() == name)
return arg;
174 llvm::Type*
const typeB)
176 OPENVDB_ASSERT(typeA && (typeA->isIntegerTy() || typeA->isFloatingPointTy()) &&
177 "First Type in typePrecedence is not a scalar type");
178 OPENVDB_ASSERT(typeB && (typeB->isIntegerTy() || typeB->isFloatingPointTy()) &&
179 "Second Type in typePrecedence is not a scalar type");
184 if (typeA->isDoubleTy())
return typeA;
185 if (typeB->isDoubleTy())
return typeB;
187 if (typeA->isFloatTy())
return typeA;
188 if (typeB->isFloatTy())
return typeB;
190 if (typeA->isIntegerTy(64))
return typeA;
191 if (typeB->isIntegerTy(64))
return typeB;
193 if (typeA->isIntegerTy(32))
return typeA;
194 if (typeB->isIntegerTy(32))
return typeB;
196 if (typeA->isIntegerTy(16))
return typeA;
197 if (typeB->isIntegerTy(16))
return typeB;
199 if (typeA->isIntegerTy(8))
return typeA;
200 if (typeB->isIntegerTy(8))
return typeB;
202 if (typeA->isIntegerTy(1))
return typeA;
203 if (typeB->isIntegerTy(1))
return typeB;
221 const llvm::Type*
const targetType,
222 const std::string& twine =
"")
225 #define BIND_ARITHMETIC_CAST_OP(Function, Twine) \ 226 std::bind(&Function, \ 227 std::placeholders::_1, \ 228 std::placeholders::_2, \ 229 std::placeholders::_3, \ 232 #if LLVM_VERSION_MAJOR >= 19 234 #define BIND_ARITHMETIC_CAST_OP_TRUNC(Function, Twine) \ 235 std::bind(&Function, \ 236 std::placeholders::_1, \ 237 std::placeholders::_2, \ 238 std::placeholders::_3, \ 243 #define BIND_ARITHMETIC_CAST_OP_TRUNC(Function, Twine) \ 244 std::bind(&Function, \ 245 std::placeholders::_1, \ 246 std::placeholders::_2, \ 247 std::placeholders::_3, \ 251 #if LLVM_VERSION_MAJOR >= 19 253 #define BIND_ARITHMETIC_CAST_OP_UIFP(Function, Twine) \ 254 std::bind(&Function, \ 255 std::placeholders::_1, \ 256 std::placeholders::_2, \ 257 std::placeholders::_3, \ 261 #define BIND_ARITHMETIC_CAST_OP_UIFP(Function, Twine) \ 262 std::bind(&Function, \ 263 std::placeholders::_1, \ 264 std::placeholders::_2, \ 265 std::placeholders::_3, \ 269 #if LLVM_VERSION_MAJOR >= 18 271 #define BIND_ARITHMETIC_CAST_OP_ZEXT(Function, Twine) \ 272 std::bind(&Function, \ 273 std::placeholders::_1, \ 274 std::placeholders::_2, \ 275 std::placeholders::_3, \ 279 #define BIND_ARITHMETIC_CAST_OP_ZEXT(Function, Twine) \ 280 std::bind(&Function, \ 281 std::placeholders::_1, \ 282 std::placeholders::_2, \ 283 std::placeholders::_3, \ 287 #if LLVM_VERSION_MAJOR >= 20 288 #define BIND_ARITHMETIC_CAST_OP_FP(Function, Twine) \ 289 std::bind(&Function, \ 290 std::placeholders::_1, \ 291 std::placeholders::_2, \ 292 std::placeholders::_3, \ 294 nullptr) // MDNode *FPMathTag 296 #define BIND_ARITHMETIC_CAST_OP_FP(Function, Twine) \ 297 std::bind(&Function, \ 298 std::placeholders::_1, \ 299 std::placeholders::_2, \ 300 std::placeholders::_3, \ 304 if (targetType->isDoubleTy()) {
313 else if (targetType->isFloatTy()) {
322 else if (targetType->isHalfTy()) {
331 else if (targetType->isIntegerTy(64)) {
340 else if (targetType->isIntegerTy(32)) {
349 else if (targetType->isIntegerTy(16)) {
358 else if (targetType->isIntegerTy(8)) {
367 else if (targetType->isIntegerTy(1)) {
377 #undef BIND_ARITHMETIC_CAST_OP 399 const std::string& twine =
"")
402 #define BIND_BINARY_OP(Function) \ 403 [twine](llvm::IRBuilder<>& B, llvm::Value* L, llvm::Value* R) \ 404 -> llvm::Value* { return B.Function(L, R, twine); } 410 if (type->isFloatingPointTy()) {
413 &&
"unable to perform logical or bitwise operation on floating point values");
428 else if (type->isIntegerTy()) {
450 #undef BIND_BINARY_OP 451 OPENVDB_ASSERT(
false &&
"invalid LLVM type for binary operation");
459 OPENVDB_ASSERT(from &&
"llvm Type 'from' is null in isValidCast");
462 if ((from->isIntegerTy() || from->isFloatingPointTy()) &&
463 (to->isIntegerTy() || to->isFloatingPointTy())) {
466 if (from->isArrayTy() && to->isArrayTy()) {
467 llvm::ArrayType* af = llvm::cast<llvm::ArrayType>(from);
468 llvm::ArrayType* at = llvm::cast<llvm::ArrayType>(to);
469 if (af->getArrayNumElements() == at->getArrayNumElements()) {
471 at->getArrayElementType());
485 llvm::Type* targetType,
486 llvm::IRBuilder<>& builder)
488 OPENVDB_ASSERT(value && (value->getType()->isIntegerTy() || value->getType()->isFloatingPointTy()) &&
489 "First Value in arithmeticConversion is not a scalar type");
490 OPENVDB_ASSERT(targetType && (targetType->isIntegerTy() || targetType->isFloatingPointTy()) &&
491 "Target Type in arithmeticConversion is not a scalar type");
493 const llvm::Type*
const valueType = value->getType();
494 if (valueType == targetType)
return value;
497 return llvmCastFunction(builder, value, targetType);
510 llvm::Type* targetElementType,
511 llvm::IRBuilder<>& builder)
513 OPENVDB_ASSERT(targetElementType && (targetElementType->isIntegerTy() ||
514 targetElementType->isFloatingPointTy()) &&
515 "Target element type is not a scalar type");
517 llvm::Type* sourceElementType = values.front()->getType();
518 OPENVDB_ASSERT(sourceElementType && (sourceElementType->isIntegerTy() ||
519 sourceElementType->isFloatingPointTy()) &&
520 "Source element type is not a scalar type");
522 if (sourceElementType == targetElementType)
return;
526 for (llvm::Value*& value : values) {
527 value = llvmCastFunction(builder, value, targetElementType);
538 llvm::IRBuilder<>& builder)
541 for (llvm::Value*& value : values) {
542 llvm::Type* type = value->getType();
543 if (type->isIntegerTy() || type->isFloatingPointTy()) {
561 llvm::Value*& valueB,
562 llvm::IRBuilder<>& builder)
564 llvm::Type* type =
typePrecedence(valueA->getType(), valueB->getType());
576 llvm::IRBuilder<>& builder)
578 llvm::Type* type = value->getType();
580 if (type->isFloatingPointTy())
return builder.CreateFCmpONE(value, llvm::ConstantFP::get(type, 0.0));
581 else if (type->isIntegerTy(1))
return builder.CreateICmpNE(value, llvm::ConstantInt::get(type, 0));
582 else if (type->isIntegerTy())
return builder.CreateICmpNE(value, llvm::ConstantInt::getSigned(type, 0));
598 llvm::IRBuilder<>& builder)
600 llvm::Type* lhsType = lhs->getType();
610 lhsType = lhs->getType();
614 return llvmBinaryFunction(builder, lhs, rhs);
622 #endif // OPENVDB_AX_CODEGEN_UTILS_HAS_BEEN_INCLUDED 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:397
Definition: axparser.h:140
#define BIND_ARITHMETIC_CAST_OP(Function, Twine)
#define BIND_ARITHMETIC_CAST_OP_ZEXT(Function, Twine)
std::function< llvm::Value *(llvm::IRBuilder<> &, llvm::Value *, llvm::Value *)> BinaryFunction
Definition: Utils.h:41
#define BIND_BINARY_OP(Function)
Definition: axparser.h:141
OperatorType operatorType(const OperatorToken token)
Definition: Tokens.h:210
Definition: axparser.h:147
Definition: axparser.h:144
OperatorType
Definition: Tokens.h:200
llvm::Value * boolComparison(llvm::Value *value, llvm::IRBuilder<> &builder)
Performs a C style boolean comparison from a given scalar LLVM value.
Definition: Utils.h:575
Definition: axparser.h:136
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:65
std::function< llvm::Value *(llvm::IRBuilder<> &, llvm::Value *, llvm::Type *)> CastFunction
Definition: Utils.h:38
Definition: axparser.h:145
LLVM type mapping from pod types.
Definition: Types.h:67
llvm::Value * binaryOperator(llvm::Value *lhs, llvm::Value *rhs, const ast::tokens::OperatorToken &token, llvm::IRBuilder<> &builder)
Definition: Utils.h:596
Consolidated llvm types for most supported types.
Definition: axparser.h:143
llvm::Argument * extractArgument(llvm::Function *F, const std::string &name)
Definition: Utils.h:157
Definition: axparser.h:151
Definition: axparser.h:137
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
Definition: axparser.h:146
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:117
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:457
#define BIND_ARITHMETIC_CAST_OP_TRUNC(Function, Twine)
Definition: Exceptions.h:13
#define BIND_ARITHMETIC_CAST_OP_UIFP(Function, Twine)
Definition: axparser.h:135
Definition: axparser.h:150
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:98
Definition: axparser.h:142
Definition: axparser.h:149
#define BIND_ARITHMETIC_CAST_OP_FP(Function, Twine)
Definition: axparser.h:148
Definition: axparser.h:139
bool AssertOpaquePtrs([[maybe_unused]]llvm::Value *opaque, [[maybe_unused]]llvm::Type *type)
Definition: Utils.h:43
void llvmTypeToString(const llvm::Type *const type, std::string &str)
Prints an llvm type to a std string.
Definition: Utils.h:80
Definition: axparser.h:152
Definition: axparser.h:138
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:560
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:220
llvm::Type * typePrecedence(llvm::Type *const typeA, llvm::Type *const typeB)
Returns the highest order type from two LLVM Scalar types.
Definition: Utils.h:173
OperatorToken
Definition: Tokens.h:150
#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