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 | |
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 | |
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(Size: Value); } |
109 | static_assert(aligned(Value: sizeof(void *))); |
110 | |
111 | static inline bool aligned(const void *P) { |
112 | return aligned(Value: 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 | |