| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright Contributors to the OpenVDB Project | ||
| 2 | // SPDX-License-Identifier: MPL-2.0 | ||
| 3 | |||
| 4 | /// @file codegen/Types.h | ||
| 5 | /// | ||
| 6 | /// @authors Nick Avramoussis | ||
| 7 | /// | ||
| 8 | /// @brief Consolidated llvm types for most supported types | ||
| 9 | /// | ||
| 10 | |||
| 11 | #ifndef OPENVDB_AX_CODEGEN_TYPES_HAS_BEEN_INCLUDED | ||
| 12 | #define OPENVDB_AX_CODEGEN_TYPES_HAS_BEEN_INCLUDED | ||
| 13 | |||
| 14 | #include "openvdb_ax/ast/Tokens.h" | ||
| 15 | #include "openvdb_ax/Exceptions.h" | ||
| 16 | #include "String.h" | ||
| 17 | |||
| 18 | #include <openvdb/version.h> | ||
| 19 | #include <openvdb/Types.h> | ||
| 20 | #include <openvdb/math/Mat3.h> | ||
| 21 | #include <openvdb/math/Mat4.h> | ||
| 22 | #include <openvdb/math/Vec3.h> | ||
| 23 | |||
| 24 | #include <llvm/IR/Constants.h> | ||
| 25 | #include <llvm/IR/IRBuilder.h> | ||
| 26 | #include <llvm/IR/LLVMContext.h> | ||
| 27 | |||
| 28 | #include <type_traits> | ||
| 29 | |||
| 30 | namespace openvdb { | ||
| 31 | OPENVDB_USE_VERSION_NAMESPACE | ||
| 32 | namespace OPENVDB_VERSION_NAME { | ||
| 33 | |||
| 34 | namespace ax { | ||
| 35 | namespace codegen { | ||
| 36 | |||
| 37 | template <size_t Bits> struct int_t; | ||
| 38 | template <> struct int_t<8> { using type = int8_t; }; | ||
| 39 | template <> struct int_t<16> { using type = int16_t; }; | ||
| 40 | template <> struct int_t<32> { using type = int32_t; }; | ||
| 41 | template <> struct int_t<64> { using type = int64_t; }; | ||
| 42 | |||
| 43 | /// @brief LLVM type mapping from pod types | ||
| 44 | /// @note LLVM Types do not store information about the value sign, only meta | ||
| 45 | /// information about the primitive type (i.e. float, int, pointer) and | ||
| 46 | /// the precision width. LLVMType<uint64_t>::get(C) will provide the same | ||
| 47 | /// type as LLVMType<int64_t>::get(C), however sign is taken into account | ||
| 48 | /// during construction of LLVM constants. | ||
| 49 | /// @note LLVMType classes are importantly used to provided automatic external | ||
| 50 | /// function mapping. Note that references are not supported, pointers | ||
| 51 | /// should be used instead. | ||
| 52 | /// @note Provide your own custom class mapping by specializing the below. | ||
| 53 | template <typename T> | ||
| 54 | struct LLVMType | ||
| 55 | { | ||
| 56 | static_assert(!std::is_reference<T>::value, | ||
| 57 | "Reference types/arguments are not supported for automatic " | ||
| 58 | "LLVM Type conversion. Use pointers instead."); | ||
| 59 | static_assert(!std::is_class<T>::value, | ||
| 60 | "Object types/arguments are not supported for automatic " | ||
| 61 | "LLVM Type conversion."); | ||
| 62 | |||
| 63 | /// @brief Return an LLVM type which represents T | ||
| 64 | /// @param C The LLVMContext to request the Type from. | ||
| 65 | static inline llvm::Type* | ||
| 66 | get(llvm::LLVMContext& C) | ||
| 67 | { | ||
| 68 | // @note bools always treated as i1 values as the constants | ||
| 69 | // true and false from the IRBuilder are i1 | ||
| 70 | if (std::is_same<T, bool>::value) { | ||
| 71 |
4/8✓ Branch 1 taken 209 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 16 times.
✗ Branch 11 not taken.
|
126733 | return llvm::Type::getInt1Ty(C); |
| 72 | } | ||
| 73 | |||
| 74 | #if LLVM_VERSION_MAJOR > 6 | ||
| 75 | return llvm::Type::getScalarTy<T>(C); | ||
| 76 | #else | ||
| 77 | int bits = sizeof(T) * CHAR_BIT; | ||
| 78 | if (std::is_integral<T>::value) { | ||
| 79 | return llvm::Type::getIntNTy(C, bits); | ||
| 80 | } | ||
| 81 | else if (std::is_floating_point<T>::value) { | ||
| 82 | switch (bits) { | ||
| 83 | case 16: return llvm::Type::getHalfTy(C); | ||
| 84 | case 32: return llvm::Type::getFloatTy(C); | ||
| 85 | case 64: return llvm::Type::getDoubleTy(C); | ||
| 86 | } | ||
| 87 | } | ||
| 88 | OPENVDB_THROW(AXCodeGenError, "LLVMType called with an unsupported type \"" + | ||
| 89 | std::string(typeNameAsString<T>()) + "\"."); | ||
| 90 | #endif | ||
| 91 | } | ||
| 92 | |||
| 93 | /// @brief Return an LLVM constant Value which represents T value | ||
| 94 | /// @param C The LLVMContext | ||
| 95 | /// @param V The value to convert to an LLVM constant | ||
| 96 | /// @return If successful, returns a pointer to an LLVM constant which | ||
| 97 | /// holds the value T. | ||
| 98 | static inline llvm::Constant* | ||
| 99 | 105849 | get(llvm::LLVMContext& C, const T V) | |
| 100 | { | ||
| 101 | llvm::Type* type = LLVMType<T>::get(C); | ||
| 102 | llvm::Constant* constant = nullptr; | ||
| 103 | |||
| 104 | if (std::is_floating_point<T>::value) { | ||
| 105 |
2/4✓ Branch 2 taken 29281 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 29281 times.
|
58562 | assert(llvm::ConstantFP::isValueValidForType(type, |
| 106 | llvm::APFloat(static_cast<typename std::conditional | ||
| 107 | <std::is_floating_point<T>::value, T, double>::type>(V)))); | ||
| 108 | 58562 | constant = llvm::ConstantFP::get(type, static_cast<double>(V)); | |
| 109 | } | ||
| 110 | else if (std::is_integral<T>::value) { | ||
| 111 | const constexpr bool isSigned = std::is_signed<T>::value; | ||
| 112 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 30604 times.
|
47287 | assert((isSigned && llvm::ConstantInt::isValueValidForType(type, static_cast<int64_t>(V))) || |
| 113 | (!isSigned && llvm::ConstantInt::isValueValidForType(type, static_cast<uint64_t>(V)))); | ||
| 114 | 47287 | constant = llvm::ConstantInt::get(type, static_cast<uint64_t>(V), isSigned); | |
| 115 | } | ||
| 116 | |||
| 117 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 59885 times.
|
105849 | assert(constant); |
| 118 | 105849 | return constant; | |
| 119 | } | ||
| 120 | |||
| 121 | /// @brief Return an LLVM constant which holds an uintptr_t, representing | ||
| 122 | /// the current address of the given value. | ||
| 123 | /// @param C The LLVMContext | ||
| 124 | /// @param V The address of a given type to convert to an LLVM constant | ||
| 125 | static inline llvm::Constant* | ||
| 126 | get(llvm::LLVMContext& C, const T* const V) | ||
| 127 | { | ||
| 128 | 21 | return LLVMType<uintptr_t>::get(C, | |
| 129 | reinterpret_cast<uintptr_t>(V)); | ||
| 130 | } | ||
| 131 | }; | ||
| 132 | |||
| 133 | template <typename T, size_t S> | ||
| 134 | struct LLVMType<T[S]> | ||
| 135 | { | ||
| 136 | static_assert(S != 0, | ||
| 137 | "Zero size array types are not supported for automatic LLVM " | ||
| 138 | "Type conversion"); | ||
| 139 | |||
| 140 | static inline llvm::Type* | ||
| 141 | 1227527 | get(llvm::LLVMContext& C) { | |
| 142 |
75/171✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 85 times.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 84 times.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 12 times.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 12 times.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 20 times.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 20 times.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 20 times.
✓ Branch 31 taken 1 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 20 times.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 148 times.
✓ Branch 37 taken 1 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 8 times.
✗ Branch 40 not taken.
✓ Branch 42 taken 4 times.
✗ Branch 43 not taken.
✓ Branch 45 taken 8 times.
✗ Branch 46 not taken.
✓ Branch 48 taken 8 times.
✗ Branch 49 not taken.
✓ Branch 51 taken 16 times.
✗ Branch 52 not taken.
✓ Branch 54 taken 4 times.
✗ Branch 55 not taken.
✓ Branch 57 taken 8 times.
✗ Branch 58 not taken.
✓ Branch 60 taken 4 times.
✗ Branch 61 not taken.
✓ Branch 63 taken 4 times.
✗ Branch 64 not taken.
✓ Branch 66 taken 4 times.
✗ Branch 67 not taken.
✓ Branch 69 taken 8 times.
✗ Branch 70 not taken.
✓ Branch 72 taken 4 times.
✗ Branch 73 not taken.
✓ Branch 75 taken 8 times.
✗ Branch 76 not taken.
✓ Branch 78 taken 4 times.
✗ Branch 79 not taken.
✓ Branch 81 taken 8 times.
✗ Branch 82 not taken.
✓ Branch 84 taken 4 times.
✗ Branch 85 not taken.
✓ Branch 87 taken 8 times.
✗ Branch 88 not taken.
✓ Branch 90 taken 4 times.
✗ Branch 91 not taken.
✓ Branch 93 taken 8 times.
✗ Branch 94 not taken.
✓ Branch 96 taken 4 times.
✗ Branch 97 not taken.
✓ Branch 99 taken 8 times.
✗ Branch 100 not taken.
✓ Branch 102 taken 4 times.
✗ Branch 103 not taken.
✓ Branch 105 taken 8 times.
✗ Branch 106 not taken.
✓ Branch 108 taken 4 times.
✗ Branch 109 not taken.
✓ Branch 111 taken 8 times.
✗ Branch 112 not taken.
✓ Branch 114 taken 4 times.
✗ Branch 115 not taken.
✓ Branch 117 taken 8 times.
✗ Branch 118 not taken.
✓ Branch 120 taken 12 times.
✗ Branch 121 not taken.
✗ Branch 123 not taken.
✗ Branch 124 not taken.
✓ Branch 126 taken 12 times.
✗ Branch 127 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✓ Branch 132 taken 12 times.
✗ Branch 133 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✓ Branch 138 taken 12 times.
✗ Branch 139 not taken.
✗ Branch 141 not taken.
✗ Branch 142 not taken.
✓ Branch 144 taken 8 times.
✗ Branch 145 not taken.
✓ Branch 147 taken 16 times.
✗ Branch 148 not taken.
✗ Branch 150 not taken.
✗ Branch 151 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✓ Branch 156 taken 16 times.
✗ Branch 157 not taken.
✓ Branch 159 taken 32 times.
✗ Branch 160 not taken.
✗ Branch 162 not taken.
✗ Branch 163 not taken.
✗ Branch 165 not taken.
✗ Branch 166 not taken.
✓ Branch 168 taken 8 times.
✗ Branch 169 not taken.
✓ Branch 171 taken 16 times.
✗ Branch 172 not taken.
✗ Branch 174 not taken.
✗ Branch 175 not taken.
✗ Branch 177 not taken.
✗ Branch 178 not taken.
✓ Branch 180 taken 8 times.
✗ Branch 181 not taken.
✓ Branch 183 taken 16 times.
✗ Branch 184 not taken.
✗ Branch 186 not taken.
✗ Branch 187 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✓ Branch 192 taken 16 times.
✗ Branch 193 not taken.
✓ Branch 195 taken 32 times.
✗ Branch 196 not taken.
✗ Branch 198 not taken.
✗ Branch 199 not taken.
✗ Branch 201 not taken.
✗ Branch 202 not taken.
✓ Branch 204 taken 8 times.
✗ Branch 205 not taken.
✓ Branch 207 taken 16 times.
✗ Branch 208 not taken.
✗ Branch 210 not taken.
✗ Branch 211 not taken.
✗ Branch 213 not taken.
✗ Branch 214 not taken.
✓ Branch 216 taken 24 times.
✗ Branch 217 not taken.
✓ Branch 219 taken 40 times.
✗ Branch 220 not taken.
✓ Branch 222 taken 24 times.
✗ Branch 223 not taken.
✓ Branch 225 taken 40 times.
✗ Branch 226 not taken.
✓ Branch 228 taken 4 times.
✗ Branch 229 not taken.
✓ Branch 231 taken 8 times.
✗ Branch 232 not taken.
✓ Branch 234 taken 4 times.
✗ Branch 235 not taken.
✓ Branch 237 taken 8 times.
✗ Branch 238 not taken.
✓ Branch 240 taken 14 times.
✗ Branch 241 not taken.
|
1392603 | return llvm::ArrayType::get(LLVMType<T>::get(C), S); |
| 143 | } | ||
| 144 | static inline llvm::Constant* | ||
| 145 | get(llvm::LLVMContext& C, const T(&array)[S]) { | ||
| 146 | return llvm::ConstantDataArray::get(C, array); | ||
| 147 | } | ||
| 148 | static inline llvm::Constant* | ||
| 149 | get(llvm::LLVMContext& C, const T(*array)[S]) | ||
| 150 | { | ||
| 151 | 52 | return LLVMType<uintptr_t>::get(C, | |
| 152 | reinterpret_cast<uintptr_t>(array)); | ||
| 153 | } | ||
| 154 | }; | ||
| 155 | |||
| 156 | template <typename T> | ||
| 157 | struct LLVMType<T*> | ||
| 158 | { | ||
| 159 | static inline llvm::PointerType* | ||
| 160 | 2265428 | get(llvm::LLVMContext& C) { | |
| 161 |
27/49✓ Branch 15 taken 484 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 484 times.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 256 times.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 256 times.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 349 times.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 349 times.
✓ Branch 31 taken 1 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 328 times.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 316 times.
✓ Branch 37 taken 1 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 204 times.
✓ Branch 40 taken 1 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 144 times.
✓ Branch 43 taken 1 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 24 times.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 24 times.
✓ Branch 49 taken 1 times.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✓ Branch 52 taken 1 times.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✓ Branch 55 taken 1 times.
✗ Branch 56 not taken.
✓ Branch 134 taken 12 times.
✗ Branch 135 not taken.
✗ Branch 137 not taken.
✗ Branch 138 not taken.
✓ Branch 140 taken 14 times.
✗ Branch 141 not taken.
✗ Branch 143 not taken.
✗ Branch 144 not taken.
|
2693702 | return LLVMType<T>::get(C)->getPointerTo(0); |
| 162 | } | ||
| 163 | }; | ||
| 164 | |||
| 165 | template <> | ||
| 166 | struct LLVMType<char> : public LLVMType<uint8_t> | ||
| 167 | { | ||
| 168 | static_assert(std::is_same<uint8_t, unsigned char>::value, | ||
| 169 | "This library requires std::uint8_t to be implemented as unsigned char."); | ||
| 170 | }; | ||
| 171 | |||
| 172 | template <> | ||
| 173 | struct LLVMType<codegen::String> | ||
| 174 | { | ||
| 175 | static inline llvm::StructType* | ||
| 176 | 354140 | get(llvm::LLVMContext& C) { | |
| 177 | const std::vector<llvm::Type*> types { | ||
| 178 | 354140 | LLVMType<char*>::get(C), // ptr | |
| 179 | 354140 | LLVMType<char[codegen::String::SSO_LENGTH]>::get(C), // SSO | |
| 180 | LLVMType<int64_t>::get(C) // size | ||
| 181 |
1/2✓ Branch 4 taken 354140 times.
✗ Branch 5 not taken.
|
354140 | }; |
| 182 |
2/6✓ Branch 1 taken 354140 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 354140 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
708280 | return llvm::StructType::get(C, types); |
| 183 | } | ||
| 184 | static inline llvm::Constant* | ||
| 185 | get(llvm::LLVMContext& C, const codegen::String* const string) | ||
| 186 | { | ||
| 187 | 4 | return LLVMType<uintptr_t>::get(C, | |
| 188 | reinterpret_cast<uintptr_t>(string)); | ||
| 189 | } | ||
| 190 | }; | ||
| 191 | |||
| 192 | template <> | ||
| 193 | struct LLVMType<void> | ||
| 194 | { | ||
| 195 | static inline llvm::Type* | ||
| 196 | get(llvm::LLVMContext& C) { | ||
| 197 |
5/11✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
|
355872 | return llvm::Type::getVoidTy(C); |
| 198 | } | ||
| 199 | }; | ||
| 200 | |||
| 201 | /// @note void* implemented as signed int_t* to match clang IR generation | ||
| 202 | template <> struct LLVMType<void*> : public LLVMType<int_t<sizeof(void*)>::type*> {}; | ||
| 203 | template <> struct LLVMType<openvdb::math::half> | ||
| 204 | { | ||
| 205 | // @note LLVM has a special representation of half types. Don't alias to | ||
| 206 | // uint16_t as we want type->isFloatingPointTy() to still return true. | ||
| 207 | |||
| 208 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
14828 | static inline llvm::Type* get(llvm::LLVMContext& C) { return llvm::Type::getHalfTy(C); } |
| 209 | static inline llvm::Constant* get(llvm::LLVMContext& C, const openvdb::math::half V) | ||
| 210 | { | ||
| 211 | llvm::Type* type = LLVMType<openvdb::math::half>::get(C); | ||
| 212 | assert(llvm::ConstantFP::isValueValidForType(type, llvm::APFloat(V))); | ||
| 213 | llvm::Constant* constant = llvm::ConstantFP::get(type, static_cast<double>(V)); | ||
| 214 | assert(constant); | ||
| 215 | return constant; | ||
| 216 | } | ||
| 217 | static inline llvm::Constant* get(llvm::LLVMContext& C, const openvdb::math::half* const V) | ||
| 218 | { | ||
| 219 | return LLVMType<uintptr_t>::get(C, reinterpret_cast<uintptr_t>(V)); | ||
| 220 | } | ||
| 221 | }; | ||
| 222 | |||
| 223 | template <typename T> struct LLVMType<const T> : public LLVMType<T> {}; | ||
| 224 | template <typename T> struct LLVMType<const T*> : public LLVMType<T*> {}; | ||
| 225 | |||
| 226 | /// @brief Alias mapping between two types, a frontend type T1 and a backend | ||
| 227 | /// type T2. This class is the intended interface for binding objects | ||
| 228 | /// which implement supported backend AX/IR types to this given backend | ||
| 229 | /// type. More specifically, it's current and expected usage is limited | ||
| 230 | /// to objects which hold a single member of a supported backend type | ||
| 231 | /// and implements a StandardLayoutType as defined by the standard. | ||
| 232 | /// Fundamentally, T1->T2 mapping should be supported by | ||
| 233 | /// reinterpret_cast<> as defined by the type aliasing rules. | ||
| 234 | /// @note The static asserts provide preliminary checks but are by no means | ||
| 235 | /// a guarantee that a provided mapping is correct. Ensure the above | ||
| 236 | /// requirements are met when instantiating an alias. | ||
| 237 | template <typename T1, typename T2> | ||
| 238 | struct AliasTypeMap | ||
| 239 | { | ||
| 240 | using LLVMTypeT = LLVMType<T2>; | ||
| 241 | |||
| 242 | static_assert(sizeof(T1) == sizeof(T2), | ||
| 243 | "T1 differs in size to T2 during alias mapping. Types should have " | ||
| 244 | "the same memory layout."); | ||
| 245 | static_assert(std::is_standard_layout<T1>::value, | ||
| 246 | "T1 in instantiation of an AliasTypeMap does not have a standard layout. " | ||
| 247 | "This will most likely cause undefined behaviour when attempting to map " | ||
| 248 | "T1->T2."); | ||
| 249 | |||
| 250 | static inline llvm::Type* | ||
| 251 | get(llvm::LLVMContext& C) { | ||
| 252 |
20/56✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 20 taken 72 times.
✗ Branch 21 not taken.
✓ Branch 23 taken 12 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 60 times.
✗ Branch 27 not taken.
✓ Branch 29 taken 12 times.
✗ Branch 30 not taken.
✓ Branch 32 taken 96 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 24 times.
✗ Branch 36 not taken.
✓ Branch 38 taken 36 times.
✗ Branch 39 not taken.
✓ Branch 41 taken 12 times.
✗ Branch 42 not taken.
✓ Branch 44 taken 24 times.
✗ Branch 45 not taken.
✓ Branch 47 taken 12 times.
✗ Branch 48 not taken.
✓ Branch 50 taken 24 times.
✗ Branch 51 not taken.
✓ Branch 53 taken 24 times.
✗ Branch 54 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✓ Branch 98 taken 12 times.
✗ Branch 99 not taken.
✓ Branch 101 taken 12 times.
✗ Branch 102 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 107 not taken.
✗ Branch 108 not taken.
✓ Branch 110 taken 14 times.
✗ Branch 111 not taken.
✓ Branch 113 taken 14 times.
✗ Branch 114 not taken.
✗ Branch 116 not taken.
✗ Branch 117 not taken.
✗ Branch 119 not taken.
✗ Branch 120 not taken.
|
252529 | return LLVMTypeT::get(C); |
| 253 | } | ||
| 254 | static inline llvm::Constant* | ||
| 255 | get(llvm::LLVMContext& C, const T1& value) { | ||
| 256 | return LLVMTypeT::get(C, reinterpret_cast<const T2&>(value)); | ||
| 257 | } | ||
| 258 | static inline llvm::Constant* | ||
| 259 | get(llvm::LLVMContext& C, const T1* const value) { | ||
| 260 | return LLVMTypeT::get(C, reinterpret_cast<const T2* const>(value)); | ||
| 261 | } | ||
| 262 | }; | ||
| 263 | |||
| 264 | /// @brief Supported aliasing for VDB math types, allowing use in external | ||
| 265 | /// function signatures. | ||
| 266 | template <typename T> struct LLVMType<openvdb::math::Vec2<T>> : public AliasTypeMap<openvdb::math::Vec2<T>, T[2]> {}; | ||
| 267 | template <typename T> struct LLVMType<openvdb::math::Vec3<T>> : public AliasTypeMap<openvdb::math::Vec3<T>, T[3]> {}; | ||
| 268 | template <typename T> struct LLVMType<openvdb::math::Vec4<T>> : public AliasTypeMap<openvdb::math::Vec4<T>, T[4]> {}; | ||
| 269 | template <typename T> struct LLVMType<openvdb::math::Mat3<T>> : public AliasTypeMap<openvdb::math::Mat3<T>, T[9]> {}; | ||
| 270 | template <typename T> struct LLVMType<openvdb::math::Mat4<T>> : public AliasTypeMap<openvdb::math::Mat4<T>, T[16]> {}; | ||
| 271 | |||
| 272 | /////////////////////////////////////////////////////////////////////////// | ||
| 273 | /////////////////////////////////////////////////////////////////////////// | ||
| 274 | |||
| 275 | /// @brief Templated function traits which provides compile-time index access to | ||
| 276 | /// the types of the function signature | ||
| 277 | /// | ||
| 278 | template<typename SignatureT> | ||
| 279 | struct FunctionTraits; | ||
| 280 | |||
| 281 | template<typename R, typename... Args> | ||
| 282 | struct FunctionTraits<R(&)(Args...)> : public FunctionTraits<R(Args...)> {}; | ||
| 283 | |||
| 284 | template<typename R, typename... Args> | ||
| 285 | struct FunctionTraits<R(*)(Args...)> : public FunctionTraits<R(Args...)> {}; | ||
| 286 | |||
| 287 | // Only enable noexcept signatures from C++17 onwards when it is actually | ||
| 288 | // respected. Otherwise the compiler ignores it and we get duplicating | ||
| 289 | // definitions for FunctionTraits specializations. | ||
| 290 | #if __cplusplus >= 201703L | ||
| 291 | template<typename R, typename... Args> | ||
| 292 | struct FunctionTraits<R(Args...) noexcept> : public FunctionTraits<R(Args...)> {}; | ||
| 293 | |||
| 294 | template<typename R, typename... Args> | ||
| 295 | struct FunctionTraits<R(*)(Args...) noexcept> : public FunctionTraits<R(Args...)> {}; | ||
| 296 | #endif | ||
| 297 | |||
| 298 | template<typename ReturnT, typename ...Args> | ||
| 299 | struct FunctionTraits<ReturnT(Args...)> | ||
| 300 | { | ||
| 301 | using ReturnType = ReturnT; | ||
| 302 | using SignatureType = ReturnType(Args...); | ||
| 303 | static const size_t N_ARGS = sizeof...(Args); | ||
| 304 | |||
| 305 | template <size_t I> | ||
| 306 | struct Arg | ||
| 307 | { | ||
| 308 | public: | ||
| 309 | static_assert(I < N_ARGS, | ||
| 310 | "Invalid index specified for function argument access"); | ||
| 311 | using Type = typename std::tuple_element<I, std::tuple<Args...>>::type; | ||
| 312 | static_assert(!std::is_reference<Type>::value, | ||
| 313 | "Reference types/arguments are not supported for automatic " | ||
| 314 | "LLVM Type conversion. Use pointers instead."); | ||
| 315 | }; | ||
| 316 | }; | ||
| 317 | |||
| 318 | /////////////////////////////////////////////////////////////////////////// | ||
| 319 | /////////////////////////////////////////////////////////////////////////// | ||
| 320 | |||
| 321 | /// @brief Returns an llvm Constant holding a scalar value | ||
| 322 | /// @param t The scalar constant | ||
| 323 | /// @param type The LLVM type. Can differ from the type of t, in which | ||
| 324 | /// case the value will be cast to the llvm type | ||
| 325 | /// | ||
| 326 | template <typename T> | ||
| 327 | inline llvm::Constant* | ||
| 328 |
2/2✓ Branch 0 taken 66 times.
✓ Branch 1 taken 208 times.
|
274 | llvmConstant(const T t, llvm::Type* type) |
| 329 | { | ||
| 330 | static_assert(std::is_floating_point<T>::value || std::is_integral<T>::value, | ||
| 331 | "T type for llvmConstant must be a floating point or integral type."); | ||
| 332 | |||
| 333 |
2/2✓ Branch 0 taken 66 times.
✓ Branch 1 taken 208 times.
|
274 | if (type->isIntegerTy()) { |
| 334 | 66 | return llvm::ConstantInt::get(type, static_cast<uint64_t>(t), /*signed*/true); | |
| 335 | } | ||
| 336 | else { | ||
| 337 | ✗ | assert(type->isFloatingPointTy()); | |
| 338 | 208 | return llvm::ConstantFP::get(type, static_cast<double>(t)); | |
| 339 | } | ||
| 340 | } | ||
| 341 | |||
| 342 | /// @brief Returns an llvm IntegerType given a requested size and context | ||
| 343 | /// @param size The number of bits of the integer type | ||
| 344 | /// @param C The LLVMContext to request the Type from. | ||
| 345 | /// | ||
| 346 | OPENVDB_AX_API llvm::IntegerType* llvmIntType(const uint32_t size, llvm::LLVMContext& C); | ||
| 347 | |||
| 348 | /// @brief Returns an llvm floating point Type given a requested size and context | ||
| 349 | /// @param size The size of the float to request, i.e. float - 32, double - 64 etc. | ||
| 350 | /// @param C The LLVMContext to request the Type from. | ||
| 351 | /// | ||
| 352 | OPENVDB_AX_API llvm::Type* llvmFloatType(const uint32_t size, llvm::LLVMContext& C); | ||
| 353 | |||
| 354 | /// @brief Returns an llvm type representing a type defined by a string. | ||
| 355 | /// @note For string types, this function returns the element type, not the | ||
| 356 | /// object type! The llvm type representing a char block of memory | ||
| 357 | /// is LLVMType<char*>::get(C); | ||
| 358 | /// @param type The AX token type | ||
| 359 | /// @param C The LLVMContext to request the Type from. | ||
| 360 | /// | ||
| 361 | OPENVDB_AX_API llvm::Type* llvmTypeFromToken(const ast::tokens::CoreType& type, llvm::LLVMContext& C); | ||
| 362 | |||
| 363 | /// @brief Return a corresponding AX token which represents the given LLVM Type. | ||
| 364 | /// @note If the type does not exist in AX, ast::tokens::UNKNOWN is returned. | ||
| 365 | /// Must not be a nullptr. | ||
| 366 | /// @param type a valid LLVM Type | ||
| 367 | /// | ||
| 368 | OPENVDB_AX_API ast::tokens::CoreType tokenFromLLVMType(const llvm::Type* type); | ||
| 369 | |||
| 370 | } // namespace codegen | ||
| 371 | } // namespace ax | ||
| 372 | } // namespace OPENVDB_VERSION_NAME | ||
| 373 | } // namespace openvdb | ||
| 374 | |||
| 375 | #endif // OPENVDB_AX_CODEGEN_TYPES_HAS_BEEN_INCLUDED | ||
| 376 | |||
| 377 |