Home | History | Annotate | Download | only in src
      1 //===- subzero/src/IceTypes.h - Primitive ICE types -------------*- C++ -*-===//
      2 //
      3 //                        The Subzero Code Generator
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 ///
     10 /// \file
     11 /// \brief Declares a few properties of the primitive types allowed in Subzero.
     12 /// Every Subzero source file is expected to include IceTypes.h.
     13 ///
     14 //===----------------------------------------------------------------------===//
     15 
     16 #ifndef SUBZERO_SRC_ICETYPES_H
     17 #define SUBZERO_SRC_ICETYPES_H
     18 
     19 #include "IceDefs.h"
     20 #include "IceTypes.def"
     21 
     22 namespace Ice {
     23 
     24 enum Type {
     25 #define X(tag, sizeLog2, align, elts, elty, str, rcstr) IceType_##tag,
     26   ICETYPE_TABLE
     27 #undef X
     28       IceType_NUM
     29 };
     30 
     31 /// RegClass indicates the physical register class that a Variable may be
     32 /// register-allocated from.  By default, a variable's register class is
     33 /// directly associated with its type.  However, the target lowering may define
     34 /// additional target-specific register classes by extending the set of enum
     35 /// values.
     36 enum RegClass : uint8_t {
     37 // Define RC_void, RC_i1, RC_i8, etc.
     38 #define X(tag, sizeLog2, align, elts, elty, str, rcstr)                        \
     39   RC_##tag = IceType_##tag,
     40   ICETYPE_TABLE
     41 #undef X
     42       RC_Target,
     43   // Leave plenty of space for target-specific values.
     44   RC_Max = std::numeric_limits<uint8_t>::max()
     45 };
     46 static_assert(RC_Target == static_cast<RegClass>(IceType_NUM),
     47               "Expected RC_Target and IceType_NUM to be the same");
     48 
     49 enum TargetArch {
     50 #define X(tag, str, is_elf64, e_machine, e_flags) tag,
     51   TARGETARCH_TABLE
     52 #undef X
     53       TargetArch_NUM
     54 };
     55 
     56 const char *targetArchString(TargetArch Arch);
     57 
     58 inline Ostream &operator<<(Ostream &Stream, TargetArch Arch) {
     59   return Stream << targetArchString(Arch);
     60 }
     61 
     62 /// The list of all target instruction sets. Individual targets will map this to
     63 /// include only what is valid for the target.
     64 enum TargetInstructionSet {
     65   // Represents baseline that can be assumed for a target (usually "Begin").
     66   BaseInstructionSet,
     67   X86InstructionSet_Begin,
     68   X86InstructionSet_SSE2 = X86InstructionSet_Begin,
     69   X86InstructionSet_SSE4_1,
     70   X86InstructionSet_End,
     71   ARM32InstructionSet_Begin,
     72   ARM32InstructionSet_Neon = ARM32InstructionSet_Begin,
     73   ARM32InstructionSet_HWDivArm,
     74   ARM32InstructionSet_End,
     75 };
     76 
     77 enum OptLevel { Opt_m1, Opt_0, Opt_1, Opt_2 };
     78 
     79 size_t typeWidthInBytes(Type Ty);
     80 int8_t typeWidthInBytesLog2(Type Ty);
     81 size_t typeAlignInBytes(Type Ty);
     82 size_t typeNumElements(Type Ty);
     83 Type typeElementType(Type Ty);
     84 const char *typeString(Type Ty);
     85 inline std::string typeStdString(Type Ty) { return typeString(Ty); }
     86 const char *regClassString(RegClass C);
     87 
     88 Type getPointerType();
     89 
     90 bool isVectorType(Type Ty);
     91 
     92 bool isBooleanType(Type Ty); // scalar or vector
     93 bool isIntegerType(Type Ty); // scalar or vector
     94 bool isScalarIntegerType(Type Ty);
     95 bool isVectorIntegerType(Type Ty);
     96 bool isIntegerArithmeticType(Type Ty);
     97 
     98 bool isFloatingType(Type Ty); // scalar or vector
     99 bool isScalarFloatingType(Type Ty);
    100 bool isVectorFloatingType(Type Ty);
    101 
    102 /// Returns true if the given type can be used in a load instruction.
    103 bool isLoadStoreType(Type Ty);
    104 
    105 /// Returns true if the given type can be used as a parameter type in a call.
    106 bool isCallParameterType(Type Ty);
    107 
    108 /// Returns true if the given type can be used as the return type of a call.
    109 inline bool isCallReturnType(Type Ty) {
    110   return Ty == IceType_void || isCallParameterType(Ty);
    111 }
    112 
    113 /// Returns type generated by applying the compare instructions (icmp and fcmp)
    114 /// to arguments of the given type. Returns IceType_void if compare is not
    115 /// allowed.
    116 Type getCompareResultType(Type Ty);
    117 
    118 /// Returns the number of bits in a scalar integer type.
    119 SizeT getScalarIntBitWidth(Type Ty);
    120 
    121 /// Check if a type is byte sized (slight optimization over typeWidthInBytes).
    122 inline bool isByteSizedType(Type Ty) {
    123   bool result = Ty == IceType_i8 || Ty == IceType_i1;
    124   assert(result == (1 == typeWidthInBytes(Ty)));
    125   return result;
    126 }
    127 
    128 /// Check if Ty is byte sized and specifically i8. Assert that it's not byte
    129 /// sized due to being an i1.
    130 inline bool isByteSizedArithType(Type Ty) {
    131   assert(Ty != IceType_i1);
    132   return Ty == IceType_i8;
    133 }
    134 
    135 /// Return true if Ty is i32. This asserts that Ty is either i32 or i64.
    136 inline bool isInt32Asserting32Or64(Type Ty) {
    137   bool result = Ty == IceType_i32;
    138   assert(result || Ty == IceType_i64);
    139   return result;
    140 }
    141 
    142 /// Return true if Ty is f32. This asserts that Ty is either f32 or f64.
    143 inline bool isFloat32Asserting32Or64(Type Ty) {
    144   bool result = Ty == IceType_f32;
    145   assert(result || Ty == IceType_f64);
    146   return result;
    147 }
    148 
    149 template <typename StreamType>
    150 inline StreamType &operator<<(StreamType &Str, const Type &Ty) {
    151   Str << typeString(Ty);
    152   return Str;
    153 }
    154 
    155 /// Models a type signature for a function.
    156 class FuncSigType {
    157   FuncSigType &operator=(const FuncSigType &Ty) = delete;
    158 
    159 public:
    160   using ArgListType = std::vector<Type>;
    161 
    162   /// Creates a function signature type with the given return type. Parameter
    163   /// types should be added using calls to appendArgType.
    164   FuncSigType() = default;
    165   FuncSigType(const FuncSigType &Ty) = default;
    166 
    167   void appendArgType(Type ArgType) { ArgList.push_back(ArgType); }
    168 
    169   Type getReturnType() const { return ReturnType; }
    170   void setReturnType(Type NewType) { ReturnType = NewType; }
    171   SizeT getNumArgs() const { return ArgList.size(); }
    172   Type getArgType(SizeT Index) const {
    173     assert(Index < ArgList.size());
    174     return ArgList[Index];
    175   }
    176   const ArgListType &getArgList() const { return ArgList; }
    177   void dump(Ostream &Stream) const;
    178 
    179 private:
    180   /// The return type.
    181   Type ReturnType = IceType_void;
    182   /// The list of parameters.
    183   ArgListType ArgList;
    184 };
    185 
    186 inline Ostream &operator<<(Ostream &Stream, const FuncSigType &Sig) {
    187   Sig.dump(Stream);
    188   return Stream;
    189 }
    190 
    191 } // end of namespace Ice
    192 
    193 #endif // SUBZERO_SRC_ICETYPES_H
    194