OpenVDB 10.0.0
Types.h
Go to the documentation of this file.
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
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
30namespace openvdb {
32namespace OPENVDB_VERSION_NAME {
33
34namespace ax {
35namespace codegen {
36
37template <size_t Bits> struct int_t;
38template <> struct int_t<8> { using type = int8_t; };
39template <> struct int_t<16> { using type = int16_t; };
40template <> struct int_t<32> { using type = int32_t; };
41template <> 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.
53template <typename T>
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
71 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;
79 return llvm::Type::getIntNTy(C, bits);
80 }
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 get(llvm::LLVMContext& C, const T V)
100 {
101 llvm::Type* type = LLVMType<T>::get(C);
102 llvm::Constant* constant = nullptr;
103
105 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 constant = llvm::ConstantFP::get(type, static_cast<double>(V));
109 }
111 const constexpr bool isSigned = std::is_signed<T>::value;
112 assert((isSigned && llvm::ConstantInt::isValueValidForType(type, static_cast<int64_t>(V))) ||
113 (!isSigned && llvm::ConstantInt::isValueValidForType(type, static_cast<uint64_t>(V))));
114 constant = llvm::ConstantInt::get(type, static_cast<uint64_t>(V), isSigned);
115 }
116
117 assert(constant);
118 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 {
129 reinterpret_cast<uintptr_t>(V));
130 }
131};
132
133template <typename T, size_t S>
134struct 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 get(llvm::LLVMContext& C) {
142 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 {
152 reinterpret_cast<uintptr_t>(array));
153 }
154};
155
156template <typename T>
157struct LLVMType<T*>
158{
159 static inline llvm::PointerType*
160 get(llvm::LLVMContext& C) {
161 return LLVMType<T>::get(C)->getPointerTo(0);
162 }
163};
164
165template <>
166struct LLVMType<char> : public LLVMType<uint8_t>
167{
169 "This library requires std::uint8_t to be implemented as unsigned char.");
170};
171
172template <>
173struct LLVMType<codegen::String>
174{
175 static inline llvm::StructType*
176 get(llvm::LLVMContext& C) {
177 const std::vector<llvm::Type*> types {
178 LLVMType<char*>::get(C), // ptr
180 LLVMType<int64_t>::get(C) // size
181 };
182 return llvm::StructType::get(C, types);
183 }
184 static inline llvm::Constant*
185 get(llvm::LLVMContext& C, const codegen::String* const string)
186 {
188 reinterpret_cast<uintptr_t>(string));
189 }
190};
191
192template <>
193struct LLVMType<void>
194{
195 static inline llvm::Type*
196 get(llvm::LLVMContext& C) {
197 return llvm::Type::getVoidTy(C);
198 }
199};
200
201/// @note void* implemented as signed int_t* to match clang IR generation
202template <> struct LLVMType<openvdb::math::half>
203{
204 // @note LLVM has a special representation of half types. Don't alias to
205 // uint16_t as we want type->isFloatingPointTy() to still return true.
206
207 static inline llvm::Type* get(llvm::LLVMContext& C) { return llvm::Type::getHalfTy(C); }
208 static inline llvm::Constant* get(llvm::LLVMContext& C, const openvdb::math::half V)
209 {
210 llvm::Type* type = LLVMType<openvdb::math::half>::get(C);
211 assert(llvm::ConstantFP::isValueValidForType(type, llvm::APFloat(V)));
212 llvm::Constant* constant = llvm::ConstantFP::get(type, static_cast<double>(V));
213 assert(constant);
214 return constant;
215 }
216 static inline llvm::Constant* get(llvm::LLVMContext& C, const openvdb::math::half* const V)
217 {
218 return LLVMType<uintptr_t>::get(C, reinterpret_cast<uintptr_t>(V));
219 }
220};
221
222template <typename T> struct LLVMType<const T> : public LLVMType<T> {};
223template <typename T> struct LLVMType<const T*> : public LLVMType<T*> {};
224
225/// @brief Alias mapping between two types, a frontend type T1 and a backend
226/// type T2. This class is the intended interface for binding objects
227/// which implement supported backend AX/IR types to this given backend
228/// type. More specifically, it's current and expected usage is limited
229/// to objects which hold a single member of a supported backend type
230/// and implements a StandardLayoutType as defined by the standard.
231/// Fundamentally, T1->T2 mapping should be supported by
232/// reinterpret_cast<> as defined by the type aliasing rules.
233/// @note The static asserts provide preliminary checks but are by no means
234/// a guarantee that a provided mapping is correct. Ensure the above
235/// requirements are met when instantiating an alias.
236template <typename T1, typename T2>
238{
240
241 static_assert(sizeof(T1) == sizeof(T2),
242 "T1 differs in size to T2 during alias mapping. Types should have "
243 "the same memory layout.");
245 "T1 in instantiation of an AliasTypeMap does not have a standard layout. "
246 "This will most likely cause undefined behaviour when attempting to map "
247 "T1->T2.");
248
249 static inline llvm::Type*
250 get(llvm::LLVMContext& C) {
251 return LLVMTypeT::get(C);
252 }
253 static inline llvm::Constant*
254 get(llvm::LLVMContext& C, const T1& value) {
255 return LLVMTypeT::get(C, reinterpret_cast<const T2&>(value));
256 }
257 static inline llvm::Constant*
258 get(llvm::LLVMContext& C, const T1* const value) {
259 return LLVMTypeT::get(C, reinterpret_cast<const T2* const>(value));
260 }
261};
262
263/// @brief Supported aliasing for VDB math types, allowing use in external
264/// function signatures.
265template <typename T> struct LLVMType<openvdb::math::Vec2<T>> : public AliasTypeMap<openvdb::math::Vec2<T>, T[2]> {};
266template <typename T> struct LLVMType<openvdb::math::Vec3<T>> : public AliasTypeMap<openvdb::math::Vec3<T>, T[3]> {};
267template <typename T> struct LLVMType<openvdb::math::Vec4<T>> : public AliasTypeMap<openvdb::math::Vec4<T>, T[4]> {};
268template <typename T> struct LLVMType<openvdb::math::Mat3<T>> : public AliasTypeMap<openvdb::math::Mat3<T>, T[9]> {};
269template <typename T> struct LLVMType<openvdb::math::Mat4<T>> : public AliasTypeMap<openvdb::math::Mat4<T>, T[16]> {};
270
271///////////////////////////////////////////////////////////////////////////
272///////////////////////////////////////////////////////////////////////////
273
274/// @brief Templated function traits which provides compile-time index access to
275/// the types of the function signature
276///
277template<typename SignatureT>
279
280template<typename R, typename... Args>
281struct FunctionTraits<R(&)(Args...)> : public FunctionTraits<R(Args...)> {};
282
283template<typename R, typename... Args>
284struct FunctionTraits<R(*)(Args...)> : public FunctionTraits<R(Args...)> {};
285
286// Only enable noexcept signatures from C++17 onwards when it is actually
287// respected. Otherwise the compiler ignores it and we get duplicating
288// definitions for FunctionTraits specializations.
289#if __cplusplus >= 201703L
290template<typename R, typename... Args>
291struct FunctionTraits<R(Args...) noexcept> : public FunctionTraits<R(Args...)> {};
292
293template<typename R, typename... Args>
294struct FunctionTraits<R(*)(Args...) noexcept> : public FunctionTraits<R(Args...)> {};
295#endif
296
297template<typename ReturnT, typename ...Args>
298struct FunctionTraits<ReturnT(Args...)>
299{
300 using ReturnType = ReturnT;
301 using SignatureType = ReturnType(Args...);
302 static const size_t N_ARGS = sizeof...(Args);
303
304 template <size_t I>
305 struct Arg
306 {
307 public:
308 static_assert(I < N_ARGS,
309 "Invalid index specified for function argument access");
310 using Type = typename std::tuple_element<I, std::tuple<Args...>>::type;
311 static_assert(!std::is_reference<Type>::value,
312 "Reference types/arguments are not supported for automatic "
313 "LLVM Type conversion. Use pointers instead.");
314 };
315};
316
317///////////////////////////////////////////////////////////////////////////
318///////////////////////////////////////////////////////////////////////////
319
320/// @brief Returns an llvm Constant holding a scalar value
321/// @param t The scalar constant
322/// @param type The LLVM type. Can differ from the type of t, in which
323/// case the value will be cast to the llvm type
324///
325template <typename T>
326inline llvm::Constant*
327llvmConstant(const T t, llvm::Type* type)
328{
330 "T type for llvmConstant must be a floating point or integral type.");
331
332 if (type->isIntegerTy()) {
333 return llvm::ConstantInt::get(type, static_cast<uint64_t>(t), /*signed*/true);
334 }
335 else {
336 assert(type->isFloatingPointTy());
337 return llvm::ConstantFP::get(type, static_cast<double>(t));
338 }
339}
340
341/// @brief Returns an llvm IntegerType given a requested size and context
342/// @param size The number of bits of the integer type
343/// @param C The LLVMContext to request the Type from.
344///
345OPENVDB_AX_API llvm::IntegerType* llvmIntType(const uint32_t size, llvm::LLVMContext& C);
346
347/// @brief Returns an llvm floating point Type given a requested size and context
348/// @param size The size of the float to request, i.e. float - 32, double - 64 etc.
349/// @param C The LLVMContext to request the Type from.
350///
351OPENVDB_AX_API llvm::Type* llvmFloatType(const uint32_t size, llvm::LLVMContext& C);
352
353/// @brief Returns an llvm type representing a type defined by a string.
354/// @note For string types, this function returns the element type, not the
355/// object type! The llvm type representing a char block of memory
356/// is LLVMType<char*>::get(C);
357/// @param type The AX token type
358/// @param C The LLVMContext to request the Type from.
359///
360OPENVDB_AX_API llvm::Type* llvmTypeFromToken(const ast::tokens::CoreType& type, llvm::LLVMContext& C);
361
362/// @brief Return a corresponding AX token which represents the given LLVM Type.
363/// @note If the type does not exist in AX, ast::tokens::UNKNOWN is returned.
364/// Must not be a nullptr.
365/// @param type a valid LLVM Type
366///
368
369} // namespace codegen
370} // namespace ax
371} // namespace OPENVDB_VERSION_NAME
372} // namespace openvdb
373
374#endif // OPENVDB_AX_CODEGEN_TYPES_HAS_BEEN_INCLUDED
375
ValueT value
Definition: GridBuilder.h:1290
#define OPENVDB_AX_API
Definition: Platform.h:272
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:24
Definition: Vec4.h:25
CoreType
Definition: Tokens.h:32
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:327
internal::half half
Definition: Types.h:29
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:238
static llvm::Constant * get(llvm::LLVMContext &C, const T1 *const value)
Definition: Types.h:258
static llvm::Constant * get(llvm::LLVMContext &C, const T1 &value)
Definition: Types.h:254
static llvm::Type * get(llvm::LLVMContext &C)
Definition: Types.h:250
typename std::tuple_element< I, std::tuple< Args... > >::type Type
Definition: Types.h:310
ReturnType(Args...) SignatureType
Definition: Types.h:301
Templated function traits which provides compile-time index access to the types of the function signa...
Definition: Types.h:278
static llvm::PointerType * get(llvm::LLVMContext &C)
Definition: Types.h:160
static llvm::Constant * get(llvm::LLVMContext &C, const T(&array)[S])
Definition: Types.h:145
static llvm::Constant * get(llvm::LLVMContext &C, const T(*array)[S])
Definition: Types.h:149
static llvm::Type * get(llvm::LLVMContext &C)
Definition: Types.h:141
static llvm::StructType * get(llvm::LLVMContext &C)
Definition: Types.h:176
static llvm::Constant * get(llvm::LLVMContext &C, const codegen::String *const string)
Definition: Types.h:185
static llvm::Constant * get(llvm::LLVMContext &C, const openvdb::math::half V)
Definition: Types.h:208
static llvm::Constant * get(llvm::LLVMContext &C, const openvdb::math::half *const V)
Definition: Types.h:216
static llvm::Type * get(llvm::LLVMContext &C)
Definition: Types.h:207
static llvm::Type * get(llvm::LLVMContext &C)
Definition: Types.h:196
LLVM type mapping from pod types.
Definition: Types.h:55
static llvm::Constant * get(llvm::LLVMContext &C, const T V)
Return an LLVM constant Value which represents T value.
Definition: Types.h:99
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:126
static llvm::Type * get(llvm::LLVMContext &C)
Return an LLVM type which represents T.
Definition: Types.h:66
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:39
int32_t type
Definition: Types.h:40
int64_t type
Definition: Types.h:41
int8_t type
Definition: Types.h:38
#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:212