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