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 23 namespace clang { 24 namespace interp { 25 26 /// Enumeration of the primitive types of the VM. 27 enum 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. 41 template <PrimType T> struct PrimConv; 42 template <> struct PrimConv<PT_Sint8> { using T = Integral<8, true>; }; 43 template <> struct PrimConv<PT_Uint8> { using T = Integral<8, false>; }; 44 template <> struct PrimConv<PT_Sint16> { using T = Integral<16, true>; }; 45 template <> struct PrimConv<PT_Uint16> { using T = Integral<16, false>; }; 46 template <> struct PrimConv<PT_Sint32> { using T = Integral<32, true>; }; 47 template <> struct PrimConv<PT_Uint32> { using T = Integral<32, false>; }; 48 template <> struct PrimConv<PT_Sint64> { using T = Integral<64, true>; }; 49 template <> struct PrimConv<PT_Uint64> { using T = Integral<64, false>; }; 50 template <> struct PrimConv<PT_Bool> { using T = Boolean; }; 51 template <> struct PrimConv<PT_Ptr> { using T = Pointer; }; 52 53 /// Returns the size of a primitive type in bytes. 54 size_t primSize(PrimType Type); 55 56 /// Aligns a size to the pointer alignment. 57 constexpr size_t align(size_t Size) { 58 return ((Size + alignof(void *) - 1) / alignof(void *)) * alignof(void *); 59 } 60 61 inline 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