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