xref: /freebsd/contrib/llvm-project/clang/lib/AST/ByteCode/PrimType.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 class FixedPoint;
30 template <bool Signed> class IntegralAP;
31 template <unsigned Bits, bool Signed> class Integral;
32 
33 /// Enumeration of the primitive types of the VM.
34 enum PrimType : unsigned {
35   PT_Sint8 = 0,
36   PT_Uint8 = 1,
37   PT_Sint16 = 2,
38   PT_Uint16 = 3,
39   PT_Sint32 = 4,
40   PT_Uint32 = 5,
41   PT_Sint64 = 6,
42   PT_Uint64 = 7,
43   PT_IntAP = 8,
44   PT_IntAPS = 9,
45   PT_Bool = 10,
46   PT_FixedPoint = 11,
47   PT_Float = 12,
48   PT_Ptr = 13,
49   PT_MemberPtr = 14,
50 };
51 
isPtrType(PrimType T)52 inline constexpr bool isPtrType(PrimType T) {
53   return T == PT_Ptr || T == PT_MemberPtr;
54 }
55 
56 enum class CastKind : uint8_t {
57   Reinterpret,
58   Volatile,
59   Dynamic,
60 };
61 
62 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
63                                      interp::CastKind CK) {
64   switch (CK) {
65   case interp::CastKind::Reinterpret:
66     OS << "reinterpret_cast";
67     break;
68   case interp::CastKind::Volatile:
69     OS << "volatile";
70     break;
71   case interp::CastKind::Dynamic:
72     OS << "dynamic";
73     break;
74   }
75   return OS;
76 }
77 
isIntegralType(PrimType T)78 constexpr bool isIntegralType(PrimType T) { return T <= PT_FixedPoint; }
needsAlloc()79 template <typename T> constexpr bool needsAlloc() {
80   return std::is_same_v<T, IntegralAP<false>> ||
81          std::is_same_v<T, IntegralAP<true>> || std::is_same_v<T, Floating>;
82 }
needsAlloc(PrimType T)83 constexpr bool needsAlloc(PrimType T) {
84   return T == PT_IntAP || T == PT_IntAPS || T == PT_Float;
85 }
86 
87 /// Mapping from primitive types to their representation.
88 template <PrimType T> struct PrimConv;
89 template <> struct PrimConv<PT_Sint8> {
90   using T = Integral<8, true>;
91 };
92 template <> struct PrimConv<PT_Uint8> {
93   using T = Integral<8, false>;
94 };
95 template <> struct PrimConv<PT_Sint16> {
96   using T = Integral<16, true>;
97 };
98 template <> struct PrimConv<PT_Uint16> {
99   using T = Integral<16, false>;
100 };
101 template <> struct PrimConv<PT_Sint32> {
102   using T = Integral<32, true>;
103 };
104 template <> struct PrimConv<PT_Uint32> {
105   using T = Integral<32, false>;
106 };
107 template <> struct PrimConv<PT_Sint64> {
108   using T = Integral<64, true>;
109 };
110 template <> struct PrimConv<PT_Uint64> {
111   using T = Integral<64, false>;
112 };
113 template <> struct PrimConv<PT_IntAP> {
114   using T = IntegralAP<false>;
115 };
116 template <> struct PrimConv<PT_IntAPS> {
117   using T = IntegralAP<true>;
118 };
119 template <> struct PrimConv<PT_Float> {
120   using T = Floating;
121 };
122 template <> struct PrimConv<PT_Bool> {
123   using T = Boolean;
124 };
125 template <> struct PrimConv<PT_Ptr> {
126   using T = Pointer;
127 };
128 template <> struct PrimConv<PT_MemberPtr> {
129   using T = MemberPointer;
130 };
131 template <> struct PrimConv<PT_FixedPoint> {
132   using T = FixedPoint;
133 };
134 
135 /// Returns the size of a primitive type in bytes.
136 size_t primSize(PrimType Type);
137 
138 /// Aligns a size to the pointer alignment.
139 constexpr size_t align(size_t Size) {
140   return ((Size + alignof(void *) - 1) / alignof(void *)) * alignof(void *);
141 }
142 
143 constexpr bool aligned(uintptr_t Value) { return Value == align(Value); }
144 static_assert(aligned(sizeof(void *)));
145 
146 static inline bool aligned(const void *P) {
147   return aligned(reinterpret_cast<uintptr_t>(P));
148 }
149 
150 } // namespace interp
151 } // namespace clang
152 
153 /// Helper macro to simplify type switches.
154 /// The macro implicitly exposes a type T in the scope of the inner block.
155 #define TYPE_SWITCH_CASE(Name, B)                                              \
156   case Name: {                                                                 \
157     using T = PrimConv<Name>::T;                                               \
158     B;                                                                         \
159     break;                                                                     \
160   }
161 #define TYPE_SWITCH(Expr, B)                                                   \
162   do {                                                                         \
163     switch (Expr) {                                                            \
164       TYPE_SWITCH_CASE(PT_Sint8, B)                                            \
165       TYPE_SWITCH_CASE(PT_Uint8, B)                                            \
166       TYPE_SWITCH_CASE(PT_Sint16, B)                                           \
167       TYPE_SWITCH_CASE(PT_Uint16, B)                                           \
168       TYPE_SWITCH_CASE(PT_Sint32, B)                                           \
169       TYPE_SWITCH_CASE(PT_Uint32, B)                                           \
170       TYPE_SWITCH_CASE(PT_Sint64, B)                                           \
171       TYPE_SWITCH_CASE(PT_Uint64, B)                                           \
172       TYPE_SWITCH_CASE(PT_IntAP, B)                                            \
173       TYPE_SWITCH_CASE(PT_IntAPS, B)                                           \
174       TYPE_SWITCH_CASE(PT_Float, B)                                            \
175       TYPE_SWITCH_CASE(PT_Bool, B)                                             \
176       TYPE_SWITCH_CASE(PT_Ptr, B)                                              \
177       TYPE_SWITCH_CASE(PT_MemberPtr, B)                                        \
178       TYPE_SWITCH_CASE(PT_FixedPoint, B)                                       \
179     }                                                                          \
180   } while (0)
181 
182 #define INT_TYPE_SWITCH(Expr, B)                                               \
183   do {                                                                         \
184     switch (Expr) {                                                            \
185       TYPE_SWITCH_CASE(PT_Sint8, B)                                            \
186       TYPE_SWITCH_CASE(PT_Uint8, B)                                            \
187       TYPE_SWITCH_CASE(PT_Sint16, B)                                           \
188       TYPE_SWITCH_CASE(PT_Uint16, B)                                           \
189       TYPE_SWITCH_CASE(PT_Sint32, B)                                           \
190       TYPE_SWITCH_CASE(PT_Uint32, B)                                           \
191       TYPE_SWITCH_CASE(PT_Sint64, B)                                           \
192       TYPE_SWITCH_CASE(PT_Uint64, B)                                           \
193       TYPE_SWITCH_CASE(PT_IntAP, B)                                            \
194       TYPE_SWITCH_CASE(PT_IntAPS, B)                                           \
195       TYPE_SWITCH_CASE(PT_Bool, B)                                             \
196     default:                                                                   \
197       llvm_unreachable("Not an integer value");                                \
198     }                                                                          \
199   } while (0)
200 
201 #define INT_TYPE_SWITCH_NO_BOOL(Expr, B)                                       \
202   do {                                                                         \
203     switch (Expr) {                                                            \
204       TYPE_SWITCH_CASE(PT_Sint8, B)                                            \
205       TYPE_SWITCH_CASE(PT_Uint8, B)                                            \
206       TYPE_SWITCH_CASE(PT_Sint16, B)                                           \
207       TYPE_SWITCH_CASE(PT_Uint16, B)                                           \
208       TYPE_SWITCH_CASE(PT_Sint32, B)                                           \
209       TYPE_SWITCH_CASE(PT_Uint32, B)                                           \
210       TYPE_SWITCH_CASE(PT_Sint64, B)                                           \
211       TYPE_SWITCH_CASE(PT_Uint64, B)                                           \
212       TYPE_SWITCH_CASE(PT_IntAP, B)                                            \
213       TYPE_SWITCH_CASE(PT_IntAPS, B)                                           \
214     default:                                                                   \
215       llvm_unreachable("Not an integer value");                                \
216     }                                                                          \
217   } while (0)
218 
219 #define TYPE_SWITCH_ALLOC(Expr, B)                                             \
220   do {                                                                         \
221     switch (Expr) {                                                            \
222       TYPE_SWITCH_CASE(PT_Float, B)                                            \
223       TYPE_SWITCH_CASE(PT_IntAP, B)                                            \
224       TYPE_SWITCH_CASE(PT_IntAPS, B)                                           \
225     default:;                                                                  \
226     }                                                                          \
227   } while (0)
228 
229 #define COMPOSITE_TYPE_SWITCH(Expr, B, D)                                      \
230   do {                                                                         \
231     switch (Expr) {                                                            \
232       TYPE_SWITCH_CASE(PT_Ptr, B)                                              \
233     default: {                                                                 \
234       D;                                                                       \
235       break;                                                                   \
236     }                                                                          \
237     }                                                                          \
238   } while (0)
239 #endif
240