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 | template <bool Signed> class IntegralAP; |
29 | template <unsigned Bits, bool Signed> class Integral; |
30 | |
31 | /// Enumeration of the primitive types of the VM. |
32 | enum PrimType : unsigned { |
33 | PT_Sint8, |
34 | PT_Uint8, |
35 | PT_Sint16, |
36 | PT_Uint16, |
37 | PT_Sint32, |
38 | PT_Uint32, |
39 | PT_Sint64, |
40 | PT_Uint64, |
41 | PT_IntAP, |
42 | PT_IntAPS, |
43 | PT_Bool, |
44 | PT_Float, |
45 | PT_Ptr, |
46 | PT_FnPtr, |
47 | }; |
48 | |
49 | inline constexpr bool isPtrType(PrimType T) { |
50 | return T == PT_Ptr || T == PT_FnPtr; |
51 | } |
52 | |
53 | enum class CastKind : uint8_t { |
54 | Reinterpret, |
55 | Atomic, |
56 | }; |
57 | inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, |
58 | interp::CastKind CK) { |
59 | switch (CK) { |
60 | case interp::CastKind::Reinterpret: |
61 | OS << "reinterpret_cast" ; |
62 | break; |
63 | case interp::CastKind::Atomic: |
64 | OS << "atomic" ; |
65 | break; |
66 | } |
67 | return OS; |
68 | } |
69 | |
70 | constexpr bool isIntegralType(PrimType T) { return T <= PT_Bool; } |
71 | |
72 | /// Mapping from primitive types to their representation. |
73 | template <PrimType T> struct PrimConv; |
74 | template <> struct PrimConv<PT_Sint8> { using T = Integral<8, true>; }; |
75 | template <> struct PrimConv<PT_Uint8> { using T = Integral<8, false>; }; |
76 | template <> struct PrimConv<PT_Sint16> { using T = Integral<16, true>; }; |
77 | template <> struct PrimConv<PT_Uint16> { using T = Integral<16, false>; }; |
78 | template <> struct PrimConv<PT_Sint32> { using T = Integral<32, true>; }; |
79 | template <> struct PrimConv<PT_Uint32> { using T = Integral<32, false>; }; |
80 | template <> struct PrimConv<PT_Sint64> { using T = Integral<64, true>; }; |
81 | template <> struct PrimConv<PT_Uint64> { using T = Integral<64, false>; }; |
82 | template <> struct PrimConv<PT_IntAP> { |
83 | using T = IntegralAP<false>; |
84 | }; |
85 | template <> struct PrimConv<PT_IntAPS> { |
86 | using T = IntegralAP<true>; |
87 | }; |
88 | template <> struct PrimConv<PT_Float> { using T = Floating; }; |
89 | template <> struct PrimConv<PT_Bool> { using T = Boolean; }; |
90 | template <> struct PrimConv<PT_Ptr> { using T = Pointer; }; |
91 | template <> struct PrimConv<PT_FnPtr> { |
92 | using T = FunctionPointer; |
93 | }; |
94 | |
95 | /// Returns the size of a primitive type in bytes. |
96 | size_t primSize(PrimType Type); |
97 | |
98 | /// Aligns a size to the pointer alignment. |
99 | constexpr size_t align(size_t Size) { |
100 | return ((Size + alignof(void *) - 1) / alignof(void *)) * alignof(void *); |
101 | } |
102 | |
103 | constexpr bool aligned(uintptr_t Value) { return Value == align(Size: Value); } |
104 | static_assert(aligned(Value: sizeof(void *))); |
105 | |
106 | static inline bool aligned(const void *P) { |
107 | return aligned(Value: reinterpret_cast<uintptr_t>(P)); |
108 | } |
109 | |
110 | } // namespace interp |
111 | } // namespace clang |
112 | |
113 | /// Helper macro to simplify type switches. |
114 | /// The macro implicitly exposes a type T in the scope of the inner block. |
115 | #define TYPE_SWITCH_CASE(Name, B) \ |
116 | case Name: { using T = PrimConv<Name>::T; B; break; } |
117 | #define TYPE_SWITCH(Expr, B) \ |
118 | do { \ |
119 | switch (Expr) { \ |
120 | TYPE_SWITCH_CASE(PT_Sint8, B) \ |
121 | TYPE_SWITCH_CASE(PT_Uint8, B) \ |
122 | TYPE_SWITCH_CASE(PT_Sint16, B) \ |
123 | TYPE_SWITCH_CASE(PT_Uint16, B) \ |
124 | TYPE_SWITCH_CASE(PT_Sint32, B) \ |
125 | TYPE_SWITCH_CASE(PT_Uint32, B) \ |
126 | TYPE_SWITCH_CASE(PT_Sint64, B) \ |
127 | TYPE_SWITCH_CASE(PT_Uint64, B) \ |
128 | TYPE_SWITCH_CASE(PT_IntAP, B) \ |
129 | TYPE_SWITCH_CASE(PT_IntAPS, B) \ |
130 | TYPE_SWITCH_CASE(PT_Float, B) \ |
131 | TYPE_SWITCH_CASE(PT_Bool, B) \ |
132 | TYPE_SWITCH_CASE(PT_Ptr, B) \ |
133 | TYPE_SWITCH_CASE(PT_FnPtr, B) \ |
134 | } \ |
135 | } while (0) |
136 | |
137 | #define INT_TYPE_SWITCH(Expr, B) \ |
138 | do { \ |
139 | switch (Expr) { \ |
140 | TYPE_SWITCH_CASE(PT_Sint8, B) \ |
141 | TYPE_SWITCH_CASE(PT_Uint8, B) \ |
142 | TYPE_SWITCH_CASE(PT_Sint16, B) \ |
143 | TYPE_SWITCH_CASE(PT_Uint16, B) \ |
144 | TYPE_SWITCH_CASE(PT_Sint32, B) \ |
145 | TYPE_SWITCH_CASE(PT_Uint32, B) \ |
146 | TYPE_SWITCH_CASE(PT_Sint64, B) \ |
147 | TYPE_SWITCH_CASE(PT_Uint64, B) \ |
148 | TYPE_SWITCH_CASE(PT_IntAP, B) \ |
149 | TYPE_SWITCH_CASE(PT_IntAPS, B) \ |
150 | TYPE_SWITCH_CASE(PT_Bool, B) \ |
151 | default: \ |
152 | llvm_unreachable("Not an integer value"); \ |
153 | } \ |
154 | } while (0) |
155 | |
156 | #define INT_TYPE_SWITCH_NO_BOOL(Expr, B) \ |
157 | do { \ |
158 | switch (Expr) { \ |
159 | TYPE_SWITCH_CASE(PT_Sint8, B) \ |
160 | TYPE_SWITCH_CASE(PT_Uint8, B) \ |
161 | TYPE_SWITCH_CASE(PT_Sint16, B) \ |
162 | TYPE_SWITCH_CASE(PT_Uint16, B) \ |
163 | TYPE_SWITCH_CASE(PT_Sint32, B) \ |
164 | TYPE_SWITCH_CASE(PT_Uint32, B) \ |
165 | TYPE_SWITCH_CASE(PT_Sint64, B) \ |
166 | TYPE_SWITCH_CASE(PT_Uint64, B) \ |
167 | TYPE_SWITCH_CASE(PT_IntAP, B) \ |
168 | TYPE_SWITCH_CASE(PT_IntAPS, B) \ |
169 | default: \ |
170 | llvm_unreachable("Not an integer value"); \ |
171 | } \ |
172 | } while (0) |
173 | |
174 | #define COMPOSITE_TYPE_SWITCH(Expr, B, D) \ |
175 | do { \ |
176 | switch (Expr) { \ |
177 | TYPE_SWITCH_CASE(PT_Ptr, B) \ |
178 | default: { D; break; } \ |
179 | } \ |
180 | } while (0) |
181 | #endif |
182 | |