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