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