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