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 |