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 <climits>
17 #include <cstddef>
18 #include <cstdint>
19 
20 namespace clang {
21 namespace interp {
22 
23 class Pointer;
24 class Boolean;
25 class Floating;
26 class FunctionPointer;
27 template <unsigned Bits, bool Signed> class Integral;
28 
29 /// Enumeration of the primitive types of the VM.
30 enum PrimType : unsigned {
31   PT_Sint8,
32   PT_Uint8,
33   PT_Sint16,
34   PT_Uint16,
35   PT_Sint32,
36   PT_Uint32,
37   PT_Sint64,
38   PT_Uint64,
39   PT_Bool,
40   PT_Float,
41   PT_Ptr,
42   PT_FnPtr,
43 };
44 
45 constexpr bool isIntegralType(PrimType T) { return T <= PT_Uint64; }
46 
47 /// Mapping from primitive types to their representation.
48 template <PrimType T> struct PrimConv;
49 template <> struct PrimConv<PT_Sint8> { using T = Integral<8, true>; };
50 template <> struct PrimConv<PT_Uint8> { using T = Integral<8, false>; };
51 template <> struct PrimConv<PT_Sint16> { using T = Integral<16, true>; };
52 template <> struct PrimConv<PT_Uint16> { using T = Integral<16, false>; };
53 template <> struct PrimConv<PT_Sint32> { using T = Integral<32, true>; };
54 template <> struct PrimConv<PT_Uint32> { using T = Integral<32, false>; };
55 template <> struct PrimConv<PT_Sint64> { using T = Integral<64, true>; };
56 template <> struct PrimConv<PT_Uint64> { using T = Integral<64, false>; };
57 template <> struct PrimConv<PT_Float> { using T = Floating; };
58 template <> struct PrimConv<PT_Bool> { using T = Boolean; };
59 template <> struct PrimConv<PT_Ptr> { using T = Pointer; };
60 template <> struct PrimConv<PT_FnPtr> {
61   using T = FunctionPointer;
62 };
63 
64 /// Returns the size of a primitive type in bytes.
65 size_t primSize(PrimType Type);
66 
67 /// Aligns a size to the pointer alignment.
68 constexpr size_t align(size_t Size) {
69   return ((Size + alignof(void *) - 1) / alignof(void *)) * alignof(void *);
70 }
71 
72 constexpr bool aligned(uintptr_t Value) { return Value == align(Value); }
73 static_assert(aligned(sizeof(void *)));
74 
75 static inline bool aligned(const void *P) {
76   return aligned(reinterpret_cast<uintptr_t>(P));
77 }
78 
79 } // namespace interp
80 } // namespace clang
81 
82 /// Helper macro to simplify type switches.
83 /// The macro implicitly exposes a type T in the scope of the inner block.
84 #define TYPE_SWITCH_CASE(Name, B) \
85   case Name: { using T = PrimConv<Name>::T; B; break; }
86 #define TYPE_SWITCH(Expr, B)                                                   \
87   do {                                                                         \
88     switch (Expr) {                                                            \
89       TYPE_SWITCH_CASE(PT_Sint8, B)                                            \
90       TYPE_SWITCH_CASE(PT_Uint8, B)                                            \
91       TYPE_SWITCH_CASE(PT_Sint16, B)                                           \
92       TYPE_SWITCH_CASE(PT_Uint16, B)                                           \
93       TYPE_SWITCH_CASE(PT_Sint32, B)                                           \
94       TYPE_SWITCH_CASE(PT_Uint32, B)                                           \
95       TYPE_SWITCH_CASE(PT_Sint64, B)                                           \
96       TYPE_SWITCH_CASE(PT_Uint64, B)                                           \
97       TYPE_SWITCH_CASE(PT_Float, B)                                            \
98       TYPE_SWITCH_CASE(PT_Bool, B)                                             \
99       TYPE_SWITCH_CASE(PT_Ptr, B)                                              \
100       TYPE_SWITCH_CASE(PT_FnPtr, B)                                            \
101     }                                                                          \
102   } while (0)
103 #define COMPOSITE_TYPE_SWITCH(Expr, B, D)                                      \
104   do {                                                                         \
105     switch (Expr) {                                                            \
106       TYPE_SWITCH_CASE(PT_Ptr, B)                                              \
107       default: { D; break; }                                                   \
108     }                                                                          \
109   } while (0)
110 #endif
111