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