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
21namespace clang {
22namespace interp {
23
24class Pointer;
25class Boolean;
26class Floating;
27class FunctionPointer;
28template <bool Signed> class IntegralAP;
29template <unsigned Bits, bool Signed> class Integral;
30
31/// Enumeration of the primitive types of the VM.
32enum 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
49inline constexpr bool isPtrType(PrimType T) {
50 return T == PT_Ptr || T == PT_FnPtr;
51}
52
53enum class CastKind : uint8_t {
54 Reinterpret,
55 Atomic,
56};
57inline 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
70constexpr bool isIntegralType(PrimType T) { return T <= PT_Bool; }
71
72/// Mapping from primitive types to their representation.
73template <PrimType T> struct PrimConv;
74template <> struct PrimConv<PT_Sint8> { using T = Integral<8, true>; };
75template <> struct PrimConv<PT_Uint8> { using T = Integral<8, false>; };
76template <> struct PrimConv<PT_Sint16> { using T = Integral<16, true>; };
77template <> struct PrimConv<PT_Uint16> { using T = Integral<16, false>; };
78template <> struct PrimConv<PT_Sint32> { using T = Integral<32, true>; };
79template <> struct PrimConv<PT_Uint32> { using T = Integral<32, false>; };
80template <> struct PrimConv<PT_Sint64> { using T = Integral<64, true>; };
81template <> struct PrimConv<PT_Uint64> { using T = Integral<64, false>; };
82template <> struct PrimConv<PT_IntAP> {
83 using T = IntegralAP<false>;
84};
85template <> struct PrimConv<PT_IntAPS> {
86 using T = IntegralAP<true>;
87};
88template <> struct PrimConv<PT_Float> { using T = Floating; };
89template <> struct PrimConv<PT_Bool> { using T = Boolean; };
90template <> struct PrimConv<PT_Ptr> { using T = Pointer; };
91template <> struct PrimConv<PT_FnPtr> {
92 using T = FunctionPointer;
93};
94
95/// Returns the size of a primitive type in bytes.
96size_t primSize(PrimType Type);
97
98/// Aligns a size to the pointer alignment.
99constexpr size_t align(size_t Size) {
100 return ((Size + alignof(void *) - 1) / alignof(void *)) * alignof(void *);
101}
102
103constexpr bool aligned(uintptr_t Value) { return Value == align(Size: Value); }
104static_assert(aligned(Value: sizeof(void *)));
105
106static 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

source code of clang/lib/AST/Interp/PrimType.h