blob: 7c98fdd4bf0b74ca6c6571e2455c62fcd7432656 [file] [log] [blame]
//===- subzero/src/IceTypes.cpp - Primitive type properties ---------------===//
//
// The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Defines a few attributes of Subzero primitive types.
///
//===----------------------------------------------------------------------===//
#include "IceTypes.h"
#include "IceDefs.h"
#include "IceTargetLowering.h"
#include "llvm/Support/ErrorHandling.h"
#include <climits>
namespace Ice {
namespace {
const char *TargetArchName[] = {
#define X(tag, str, is_elf64, e_machine, e_flags) str,
TARGETARCH_TABLE
#undef X
};
// Show tags match between ICETYPE_TABLE and ICETYPE_PROPS_TABLE.
// Define a temporary set of enum values based on ICETYPE_TABLE
enum {
#define X(tag, sizeLog2, align, elts, elty, str, rcstr) _table_tag_##tag,
ICETYPE_TABLE
#undef X
_enum_table_tag_Names
};
// Define a temporary set of enum values based on ICETYPE_PROPS_TABLE
enum {
#define X(tag, IsVec, IsInt, IsFloat, IsIntArith, IsLoadStore, IsParam, \
CompareResult) \
_props_table_tag_##tag,
ICETYPE_PROPS_TABLE
#undef X
_enum_props_table_tag_Names
};
// Assert that tags in ICETYPE_TABLE are also in ICETYPE_PROPS_TABLE.
#define X(tag, sizeLog2, align, elts, elty, str, rcstr) \
static_assert( \
(unsigned)_table_tag_##tag == (unsigned)_props_table_tag_##tag, \
"Inconsistency between ICETYPE_PROPS_TABLE and ICETYPE_TABLE");
ICETYPE_TABLE
#undef X
// Assert that tags in ICETYPE_PROPS_TABLE is in ICETYPE_TABLE.
#define X(tag, IsVec, IsInt, IsFloat, IsIntArith, IsLoadStore, IsParam, \
CompareResult) \
static_assert( \
(unsigned)_table_tag_##tag == (unsigned)_props_table_tag_##tag, \
"Inconsistency between ICETYPE_PROPS_TABLE and ICETYPE_TABLE");
ICETYPE_PROPS_TABLE
#undef X
// Show vector definitions match in ICETYPE_TABLE and ICETYPE_PROPS_TABLE.
// Define constants for each element size in ICETYPE_TABLE.
enum {
#define X(tag, sizeLog2, align, elts, elty, str, rcstr) \
_table_elts_##tag = elts,
ICETYPE_TABLE
#undef X
_enum_table_elts_Elements = 0
};
// Define constants for boolean flag if vector in ICETYPE_PROPS_TABLE.
enum {
#define X(tag, IsVec, IsInt, IsFloat, IsIntArith, IsLoadStore, IsParam, \
CompareResult) \
_props_table_IsVec_##tag = IsVec,
ICETYPE_PROPS_TABLE
#undef X
};
// Verify that the number of vector elements is consistent with IsVec.
#define X(tag, IsVec, IsInt, IsFloat, IsIntArith, IsLoadStore, IsParam, \
CompareResult) \
static_assert((_table_elts_##tag > 1) == _props_table_IsVec_##tag, \
"Inconsistent vector specification in ICETYPE_PROPS_TABLE");
ICETYPE_PROPS_TABLE
#undef X
struct TypeAttributeFields {
int8_t TypeWidthInBytesLog2;
size_t TypeAlignInBytes;
size_t TypeNumElements;
Type TypeElementType;
const char *DisplayString;
const char *RegClassString;
};
const struct TypeAttributeFields TypeAttributes[] = {
#define X(tag, sizeLog2, align, elts, elty, str, rcstr) \
{sizeLog2, align, elts, IceType_##elty, str, rcstr},
ICETYPE_TABLE
#undef X
};
struct TypePropertyFields {
bool TypeIsVectorType;
bool TypeIsIntegerType;
bool TypeIsScalarIntegerType;
bool TypeIsVectorIntegerType;
bool TypeIsIntegerArithmeticType;
bool TypeIsFloatingType;
bool TypeIsScalarFloatingType;
bool TypeIsVectorFloatingType;
bool TypeIsBooleanType;
bool TypeIsCallParameterType;
Type CompareResultType;
};
const TypePropertyFields TypePropertiesTable[] = {
#define X(tag, IsVec, IsInt, IsFloat, IsIntArith, IsBoolean, IsParam, \
CompareResult) \
{IsVec, IsInt, IsInt & !IsVec, IsInt & IsVec, \
IsIntArith, IsFloat, IsFloat & !IsVec, IsFloat & IsVec, \
IsBoolean, IsParam, IceType_##CompareResult},
ICETYPE_PROPS_TABLE
#undef X
};
} // end anonymous namespace
const char *targetArchString(const TargetArch Arch) {
if (Arch < TargetArch_NUM)
return TargetArchName[Arch];
llvm_unreachable("Invalid target arch for targetArchString");
return "???";
}
size_t typeWidthInBytes(Type Ty) {
int8_t Shift = typeWidthInBytesLog2(Ty);
return (Shift < 0) ? 0 : 1 << Shift;
}
int8_t typeWidthInBytesLog2(Type Ty) {
if (Ty < IceType_NUM)
return TypeAttributes[Ty].TypeWidthInBytesLog2;
llvm_unreachable("Invalid type for typeWidthInBytesLog2()");
return 0;
}
size_t typeAlignInBytes(Type Ty) {
if (Ty < IceType_NUM)
return TypeAttributes[Ty].TypeAlignInBytes;
llvm_unreachable("Invalid type for typeAlignInBytes()");
return 1;
}
size_t typeNumElements(Type Ty) {
if (Ty < IceType_NUM)
return TypeAttributes[Ty].TypeNumElements;
llvm_unreachable("Invalid type for typeNumElements()");
return 1;
}
Type typeElementType(Type Ty) {
if (Ty < IceType_NUM)
return TypeAttributes[Ty].TypeElementType;
llvm_unreachable("Invalid type for typeElementType()");
return IceType_void;
}
Type getPointerType() { return TargetLowering::getPointerType(); }
bool isVectorType(Type Ty) {
if (Ty < IceType_NUM)
return TypePropertiesTable[Ty].TypeIsVectorType;
llvm_unreachable("Invalid type for isVectorType()");
return false;
}
bool isBooleanType(Type Ty) {
if (Ty < IceType_NUM)
return TypePropertiesTable[Ty].TypeIsBooleanType;
llvm_unreachable("Invalid type for isBooleanType()");
return false;
}
bool isIntegerType(Type Ty) {
if (Ty < IceType_NUM)
return TypePropertiesTable[Ty].TypeIsIntegerType;
llvm_unreachable("Invalid type for isIntegerType()");
return false;
}
bool isScalarIntegerType(Type Ty) {
if (Ty < IceType_NUM)
return TypePropertiesTable[Ty].TypeIsScalarIntegerType;
llvm_unreachable("Invalid type for isScalIntegerType()");
return false;
}
bool isVectorIntegerType(Type Ty) {
if (Ty < IceType_NUM)
return TypePropertiesTable[Ty].TypeIsVectorIntegerType;
llvm_unreachable("Invalid type for isVectorIntegerType()");
return false;
}
bool isIntegerArithmeticType(Type Ty) {
if (Ty < IceType_NUM)
return TypePropertiesTable[Ty].TypeIsIntegerArithmeticType;
llvm_unreachable("Invalid type for isIntegerArithmeticType()");
return false;
}
bool isFloatingType(Type Ty) {
if (Ty < IceType_NUM)
return TypePropertiesTable[Ty].TypeIsFloatingType;
llvm_unreachable("Invalid type for isFloatingType()");
return false;
}
bool isScalarFloatingType(Type Ty) {
if (Ty < IceType_NUM)
return TypePropertiesTable[Ty].TypeIsScalarFloatingType;
llvm_unreachable("Invalid type for isScalarFloatingType()");
return false;
}
bool isVectorFloatingType(Type Ty) {
if (Ty < IceType_NUM)
return TypePropertiesTable[Ty].TypeIsVectorFloatingType;
llvm_unreachable("Invalid type for isVectorFloatingType()");
return false;
}
bool isLoadStoreType(Type Ty) {
if (Ty < IceType_NUM)
return Ty != IceType_void && !isBooleanType(Ty);
llvm_unreachable("Invalid type for isLoadStoreType()");
return false;
}
bool isCallParameterType(Type Ty) {
if (Ty < IceType_NUM)
return TypePropertiesTable[Ty].TypeIsCallParameterType;
llvm_unreachable("Invalid type for isCallParameterType()");
return false;
}
Type getCompareResultType(Type Ty) {
if (Ty < IceType_NUM)
return TypePropertiesTable[Ty].CompareResultType;
llvm_unreachable("Invalid type for getCompareResultType");
return IceType_void;
}
SizeT getScalarIntBitWidth(Type Ty) {
assert(isScalarIntegerType(Ty));
if (Ty == IceType_i1)
return 1;
return typeWidthInBytes(Ty) * CHAR_BIT;
}
// ======================== Dump routines ======================== //
const char *typeString(Type Ty) {
if (Ty < IceType_NUM)
return TypeAttributes[Ty].DisplayString;
llvm_unreachable("Invalid type for typeString");
return "???";
}
const char *regClassString(RegClass C) {
if (static_cast<size_t>(C) < IceType_NUM)
return TypeAttributes[C].RegClassString;
llvm_unreachable("Invalid type for regClassString");
return "???";
}
void FuncSigType::dump(Ostream &Stream) const {
if (!BuildDefs::dump())
return;
Stream << ReturnType << " (";
bool IsFirst = true;
for (const Type ArgTy : ArgList) {
if (IsFirst) {
IsFirst = false;
} else {
Stream << ", ";
}
Stream << ArgTy;
}
Stream << ")";
}
} // end of namespace Ice