xref: /freebsd/contrib/llvm-project/clang/lib/AST/Interp/PrimType.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===--- PrimType.h - Types for the constexpr VM ----------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Defines the VM types and helpers operating on types.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_CLANG_AST_INTERP_TYPE_H
14 #define LLVM_CLANG_AST_INTERP_TYPE_H
15 
16 #include "llvm/Support/raw_ostream.h"
17 #include <climits>
18 #include <cstddef>
19 #include <cstdint>
20 
21 namespace clang {
22 namespace interp {
23 
24 class Pointer;
25 class Boolean;
26 class Floating;
27 class FunctionPointer;
28 class MemberPointer;
29 template <bool Signed> class IntegralAP;
30 template <unsigned Bits, bool Signed> class Integral;
31 
32 /// Enumeration of the primitive types of the VM.
33 enum PrimType : unsigned {
34   PT_Sint8 = 0,
35   PT_Uint8 = 1,
36   PT_Sint16 = 2,
37   PT_Uint16 = 3,
38   PT_Sint32 = 4,
39   PT_Uint32 = 5,
40   PT_Sint64 = 6,
41   PT_Uint64 = 7,
42   PT_IntAP = 8,
43   PT_IntAPS = 9,
44   PT_Bool = 10,
45   PT_Float = 11,
46   PT_Ptr = 12,
47   PT_FnPtr = 13,
48   PT_MemberPtr = 14,
49 };
50 
isPtrType(PrimType T)51 inline constexpr bool isPtrType(PrimType T) {
52   return T == PT_Ptr || T == PT_FnPtr || T == PT_MemberPtr;
53 }
54 
55 enum class CastKind : uint8_t {
56   Reinterpret,
57   Atomic,
58 };
59 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
60                                      interp::CastKind CK) {
61   switch (CK) {
62   case interp::CastKind::Reinterpret:
63     OS << "reinterpret_cast";
64     break;
65   case interp::CastKind::Atomic:
66     OS << "atomic";
67     break;
68   }
69   return OS;
70 }
71 
isIntegralType(PrimType T)72 constexpr bool isIntegralType(PrimType T) { return T <= PT_Bool; }
73 
74 /// Mapping from primitive types to their representation.
75 template <PrimType T> struct PrimConv;
76 template <> struct PrimConv<PT_Sint8> { using T = Integral<8, true>; };
77 template <> struct PrimConv<PT_Uint8> { using T = Integral<8, false>; };
78 template <> struct PrimConv<PT_Sint16> { using T = Integral<16, true>; };
79 template <> struct PrimConv<PT_Uint16> { using T = Integral<16, false>; };
80 template <> struct PrimConv<PT_Sint32> { using T = Integral<32, true>; };
81 template <> struct PrimConv<PT_Uint32> { using T = Integral<32, false>; };
82 template <> struct PrimConv<PT_Sint64> { using T = Integral<64, true>; };
83 template <> struct PrimConv<PT_Uint64> { using T = Integral<64, false>; };
84 template <> struct PrimConv<PT_IntAP> {
85   using T = IntegralAP<false>;
86 };
87 template <> struct PrimConv<PT_IntAPS> {
88   using T = IntegralAP<true>;
89 };
90 template <> struct PrimConv<PT_Float> { using T = Floating; };
91 template <> struct PrimConv<PT_Bool> { using T = Boolean; };
92 template <> struct PrimConv<PT_Ptr> { using T = Pointer; };
93 template <> struct PrimConv<PT_FnPtr> {
94   using T = FunctionPointer;
95 };
96 template <> struct PrimConv<PT_MemberPtr> {
97   using T = MemberPointer;
98 };
99 
100 /// Returns the size of a primitive type in bytes.
101 size_t primSize(PrimType Type);
102 
103 /// Aligns a size to the pointer alignment.
104 constexpr size_t align(size_t Size) {
105   return ((Size + alignof(void *) - 1) / alignof(void *)) * alignof(void *);
106 }
107 
108 constexpr bool aligned(uintptr_t Value) { return Value == align(Value); }
109 static_assert(aligned(sizeof(void *)));
110 
111 static inline bool aligned(const void *P) {
112   return aligned(reinterpret_cast<uintptr_t>(P));
113 }
114 
115 } // namespace interp
116 } // namespace clang
117 
118 /// Helper macro to simplify type switches.
119 /// The macro implicitly exposes a type T in the scope of the inner block.
120 #define TYPE_SWITCH_CASE(Name, B) \
121   case Name: { using T = PrimConv<Name>::T; B; break; }
122 #define TYPE_SWITCH(Expr, B)                                                   \
123   do {                                                                         \
124     switch (Expr) {                                                            \
125       TYPE_SWITCH_CASE(PT_Sint8, B)                                            \
126       TYPE_SWITCH_CASE(PT_Uint8, B)                                            \
127       TYPE_SWITCH_CASE(PT_Sint16, B)                                           \
128       TYPE_SWITCH_CASE(PT_Uint16, B)                                           \
129       TYPE_SWITCH_CASE(PT_Sint32, B)                                           \
130       TYPE_SWITCH_CASE(PT_Uint32, B)                                           \
131       TYPE_SWITCH_CASE(PT_Sint64, B)                                           \
132       TYPE_SWITCH_CASE(PT_Uint64, B)                                           \
133       TYPE_SWITCH_CASE(PT_IntAP, B)                                            \
134       TYPE_SWITCH_CASE(PT_IntAPS, B)                                           \
135       TYPE_SWITCH_CASE(PT_Float, B)                                            \
136       TYPE_SWITCH_CASE(PT_Bool, B)                                             \
137       TYPE_SWITCH_CASE(PT_Ptr, B)                                              \
138       TYPE_SWITCH_CASE(PT_FnPtr, B)                                            \
139       TYPE_SWITCH_CASE(PT_MemberPtr, B)                                        \
140     }                                                                          \
141   } while (0)
142 
143 #define INT_TYPE_SWITCH(Expr, B)                                               \
144   do {                                                                         \
145     switch (Expr) {                                                            \
146       TYPE_SWITCH_CASE(PT_Sint8, B)                                            \
147       TYPE_SWITCH_CASE(PT_Uint8, B)                                            \
148       TYPE_SWITCH_CASE(PT_Sint16, B)                                           \
149       TYPE_SWITCH_CASE(PT_Uint16, B)                                           \
150       TYPE_SWITCH_CASE(PT_Sint32, B)                                           \
151       TYPE_SWITCH_CASE(PT_Uint32, B)                                           \
152       TYPE_SWITCH_CASE(PT_Sint64, B)                                           \
153       TYPE_SWITCH_CASE(PT_Uint64, B)                                           \
154       TYPE_SWITCH_CASE(PT_IntAP, B)                                            \
155       TYPE_SWITCH_CASE(PT_IntAPS, B)                                           \
156       TYPE_SWITCH_CASE(PT_Bool, B)                                             \
157     default:                                                                   \
158       llvm_unreachable("Not an integer value");                                \
159     }                                                                          \
160   } while (0)
161 
162 #define INT_TYPE_SWITCH_NO_BOOL(Expr, B)                                       \
163   do {                                                                         \
164     switch (Expr) {                                                            \
165       TYPE_SWITCH_CASE(PT_Sint8, B)                                            \
166       TYPE_SWITCH_CASE(PT_Uint8, B)                                            \
167       TYPE_SWITCH_CASE(PT_Sint16, B)                                           \
168       TYPE_SWITCH_CASE(PT_Uint16, B)                                           \
169       TYPE_SWITCH_CASE(PT_Sint32, B)                                           \
170       TYPE_SWITCH_CASE(PT_Uint32, B)                                           \
171       TYPE_SWITCH_CASE(PT_Sint64, B)                                           \
172       TYPE_SWITCH_CASE(PT_Uint64, B)                                           \
173       TYPE_SWITCH_CASE(PT_IntAP, B)                                            \
174       TYPE_SWITCH_CASE(PT_IntAPS, B)                                           \
175     default:                                                                   \
176       llvm_unreachable("Not an integer value");                                \
177     }                                                                          \
178   } while (0)
179 
180 #define COMPOSITE_TYPE_SWITCH(Expr, B, D)                                      \
181   do {                                                                         \
182     switch (Expr) {                                                            \
183       TYPE_SWITCH_CASE(PT_Ptr, B)                                              \
184       default: { D; break; }                                                   \
185     }                                                                          \
186   } while (0)
187 #endif
188