| //===- subzero/src/IceTypes.h - Primitive ICE types -------------*- C++ -*-===// |
| // |
| // The Subzero Code Generator |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// \brief Declares a few properties of the primitive types allowed in Subzero. |
| /// Every Subzero source file is expected to include IceTypes.h. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SUBZERO_SRC_ICETYPES_H |
| #define SUBZERO_SRC_ICETYPES_H |
| |
| #include "IceDefs.h" |
| #include "IceTypes.def" |
| |
| namespace Ice { |
| |
| enum Type { |
| #define X(tag, sizeLog2, align, elts, elty, str, rcstr) IceType_##tag, |
| ICETYPE_TABLE |
| #undef X |
| IceType_NUM |
| }; |
| |
| /// RegClass indicates the physical register class that a Variable may be |
| /// register-allocated from. By default, a variable's register class is |
| /// directly associated with its type. However, the target lowering may define |
| /// additional target-specific register classes by extending the set of enum |
| /// values. |
| enum RegClass : uint8_t { |
| // Define RC_void, RC_i1, RC_i8, etc. |
| #define X(tag, sizeLog2, align, elts, elty, str, rcstr) \ |
| RC_##tag = IceType_##tag, |
| ICETYPE_TABLE |
| #undef X |
| RC_Target, |
| // Leave plenty of space for target-specific values. |
| RC_Max = std::numeric_limits<uint8_t>::max() |
| }; |
| static_assert(RC_Target == static_cast<RegClass>(IceType_NUM), |
| "Expected RC_Target and IceType_NUM to be the same"); |
| |
| enum TargetArch { |
| #define X(tag, str, is_elf64, e_machine, e_flags) tag, |
| TARGETARCH_TABLE |
| #undef X |
| TargetArch_NUM |
| }; |
| |
| const char *targetArchString(TargetArch Arch); |
| |
| inline Ostream &operator<<(Ostream &Stream, TargetArch Arch) { |
| return Stream << targetArchString(Arch); |
| } |
| |
| /// The list of all target instruction sets. Individual targets will map this to |
| /// include only what is valid for the target. |
| enum TargetInstructionSet { |
| // Represents baseline that can be assumed for a target (usually "Begin"). |
| BaseInstructionSet, |
| X86InstructionSet_Begin, |
| X86InstructionSet_SSE2 = X86InstructionSet_Begin, |
| X86InstructionSet_SSE4_1, |
| X86InstructionSet_End, |
| ARM32InstructionSet_Begin, |
| ARM32InstructionSet_Neon = ARM32InstructionSet_Begin, |
| ARM32InstructionSet_HWDivArm, |
| ARM32InstructionSet_End, |
| }; |
| |
| enum OptLevel { Opt_m1, Opt_0, Opt_1, Opt_2 }; |
| |
| size_t typeWidthInBytes(Type Ty); |
| int8_t typeWidthInBytesLog2(Type Ty); |
| size_t typeAlignInBytes(Type Ty); |
| size_t typeNumElements(Type Ty); |
| Type typeElementType(Type Ty); |
| const char *typeString(Type Ty); |
| inline std::string typeStdString(Type Ty) { return typeString(Ty); } |
| const char *regClassString(RegClass C); |
| |
| Type getPointerType(); |
| |
| bool isVectorType(Type Ty); |
| |
| bool isBooleanType(Type Ty); // scalar or vector |
| bool isIntegerType(Type Ty); // scalar or vector |
| bool isScalarIntegerType(Type Ty); |
| bool isVectorIntegerType(Type Ty); |
| bool isIntegerArithmeticType(Type Ty); |
| |
| bool isFloatingType(Type Ty); // scalar or vector |
| bool isScalarFloatingType(Type Ty); |
| bool isVectorFloatingType(Type Ty); |
| |
| /// Returns true if the given type can be used in a load instruction. |
| bool isLoadStoreType(Type Ty); |
| |
| /// Returns true if the given type can be used as a parameter type in a call. |
| bool isCallParameterType(Type Ty); |
| |
| /// Returns true if the given type can be used as the return type of a call. |
| inline bool isCallReturnType(Type Ty) { |
| return Ty == IceType_void || isCallParameterType(Ty); |
| } |
| |
| /// Returns type generated by applying the compare instructions (icmp and fcmp) |
| /// to arguments of the given type. Returns IceType_void if compare is not |
| /// allowed. |
| Type getCompareResultType(Type Ty); |
| |
| /// Returns the number of bits in a scalar integer type. |
| SizeT getScalarIntBitWidth(Type Ty); |
| |
| /// Check if a type is byte sized (slight optimization over typeWidthInBytes). |
| inline bool isByteSizedType(Type Ty) { |
| bool result = Ty == IceType_i8 || Ty == IceType_i1; |
| assert(result == (1 == typeWidthInBytes(Ty))); |
| return result; |
| } |
| |
| /// Check if Ty is byte sized and specifically i8. Assert that it's not byte |
| /// sized due to being an i1. |
| inline bool isByteSizedArithType(Type Ty) { |
| assert(Ty != IceType_i1); |
| return Ty == IceType_i8; |
| } |
| |
| /// Return true if Ty is i32. This asserts that Ty is either i32 or i64. |
| inline bool isInt32Asserting32Or64(Type Ty) { |
| bool result = Ty == IceType_i32; |
| assert(result || Ty == IceType_i64); |
| return result; |
| } |
| |
| /// Return true if Ty is f32. This asserts that Ty is either f32 or f64. |
| inline bool isFloat32Asserting32Or64(Type Ty) { |
| bool result = Ty == IceType_f32; |
| assert(result || Ty == IceType_f64); |
| return result; |
| } |
| |
| template <typename StreamType> |
| inline StreamType &operator<<(StreamType &Str, const Type &Ty) { |
| Str << typeString(Ty); |
| return Str; |
| } |
| |
| /// Models a type signature for a function. |
| class FuncSigType { |
| FuncSigType &operator=(const FuncSigType &Ty) = delete; |
| |
| public: |
| using ArgListType = std::vector<Type>; |
| |
| /// Creates a function signature type with the given return type. Parameter |
| /// types should be added using calls to appendArgType. |
| FuncSigType() = default; |
| FuncSigType(const FuncSigType &Ty) = default; |
| |
| void appendArgType(Type ArgType) { ArgList.push_back(ArgType); } |
| |
| Type getReturnType() const { return ReturnType; } |
| void setReturnType(Type NewType) { ReturnType = NewType; } |
| SizeT getNumArgs() const { return ArgList.size(); } |
| Type getArgType(SizeT Index) const { |
| assert(Index < ArgList.size()); |
| return ArgList[Index]; |
| } |
| const ArgListType &getArgList() const { return ArgList; } |
| void dump(Ostream &Stream) const; |
| |
| private: |
| /// The return type. |
| Type ReturnType = IceType_void; |
| /// The list of parameters. |
| ArgListType ArgList; |
| }; |
| |
| inline Ostream &operator<<(Ostream &Stream, const FuncSigType &Sig) { |
| Sig.dump(Stream); |
| return Stream; |
| } |
| |
| } // end of namespace Ice |
| |
| #endif // SUBZERO_SRC_ICETYPES_H |