Home | History | Annotate | Line # | Download | only in Interp
      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