forked from OSchip/llvm-project
Provide half floating point support as a storage only type.
Lack of half FP was a regression compared to llvm-gcc. llvm-svn: 142016
This commit is contained in:
parent
1f64b59872
commit
f0c267e6e0
|
@ -493,6 +493,7 @@ public:
|
|||
CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
|
||||
CanQualType UnsignedLongLongTy, UnsignedInt128Ty;
|
||||
CanQualType FloatTy, DoubleTy, LongDoubleTy;
|
||||
CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON
|
||||
CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
|
||||
CanQualType VoidPtrTy, NullPtrTy;
|
||||
CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy;
|
||||
|
|
|
@ -1392,6 +1392,7 @@ public:
|
|||
bool isComplexType() const; // C99 6.2.5p11 (complex)
|
||||
bool isAnyComplexType() const; // C99 6.2.5p11 (complex) + Complex Int.
|
||||
bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex)
|
||||
bool isHalfType() const; // OpenCL 6.1.1.1, NEON (IEEE 754-2008 half)
|
||||
bool isRealType() const; // C99 6.2.5p17 (real floating + integer)
|
||||
bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating)
|
||||
bool isVoidType() const; // C99 6.2.5p19
|
||||
|
@ -1699,6 +1700,8 @@ public:
|
|||
LongLong,
|
||||
Int128, // __int128_t
|
||||
|
||||
Half, // This is the 'half' type in OpenCL,
|
||||
// __fp16 in case of ARM NEON.
|
||||
Float, Double, LongDouble,
|
||||
|
||||
NullPtr, // This is the type of C++0x 'nullptr'.
|
||||
|
@ -1779,7 +1782,7 @@ public:
|
|||
}
|
||||
|
||||
bool isFloatingPoint() const {
|
||||
return getKind() >= Float && getKind() <= LongDouble;
|
||||
return getKind() >= Half && getKind() <= LongDouble;
|
||||
}
|
||||
|
||||
/// Determines whether this type is a placeholder type, i.e. a type
|
||||
|
|
|
@ -312,6 +312,8 @@ def err_statically_allocated_object : Error<
|
|||
def err_object_cannot_be_passed_returned_by_value : Error<
|
||||
"interface type %1 cannot be %select{returned|passed}0 by value"
|
||||
"; did you forget * in %1">;
|
||||
def err_parameters_retval_cannot_have_fp16_type : Error<
|
||||
"%select{parameters|function return value}0 cannot have __fp16 type; did you forget * ?">;
|
||||
def warn_enum_value_overflow : Warning<"overflow in enumeration value">;
|
||||
def warn_pragma_options_align_unsupported_option : Warning<
|
||||
"unsupported alignment option in '#pragma options align'">;
|
||||
|
|
|
@ -40,6 +40,7 @@ namespace clang {
|
|||
TST_char16, // C++0x char16_t
|
||||
TST_char32, // C++0x char32_t
|
||||
TST_int,
|
||||
TST_half, // OpenCL half, ARM NEON __fp16
|
||||
TST_float,
|
||||
TST_double,
|
||||
TST_bool, // _Bool
|
||||
|
|
|
@ -69,6 +69,7 @@ protected:
|
|||
unsigned char PointerWidth, PointerAlign;
|
||||
unsigned char BoolWidth, BoolAlign;
|
||||
unsigned char IntWidth, IntAlign;
|
||||
unsigned char HalfWidth, HalfAlign;
|
||||
unsigned char FloatWidth, FloatAlign;
|
||||
unsigned char DoubleWidth, DoubleAlign;
|
||||
unsigned char LongDoubleWidth, LongDoubleAlign;
|
||||
|
@ -79,7 +80,8 @@ protected:
|
|||
const char *DescriptionString;
|
||||
const char *UserLabelPrefix;
|
||||
const char *MCountName;
|
||||
const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat;
|
||||
const llvm::fltSemantics *HalfFormat, *FloatFormat, *DoubleFormat,
|
||||
*LongDoubleFormat;
|
||||
unsigned char RegParmMax, SSERegParmMax;
|
||||
TargetCXXABI CXXABI;
|
||||
const LangAS::Map *AddrSpaceMap;
|
||||
|
@ -224,6 +226,11 @@ public:
|
|||
unsigned getChar32Width() const { return getTypeWidth(Char32Type); }
|
||||
unsigned getChar32Align() const { return getTypeAlign(Char32Type); }
|
||||
|
||||
/// getHalfWidth/Align/Format - Return the size/align/format of 'half'.
|
||||
unsigned getHalfWidth() const { return HalfWidth; }
|
||||
unsigned getHalfAlign() const { return HalfAlign; }
|
||||
const llvm::fltSemantics &getHalfFormat() const { return *HalfFormat; }
|
||||
|
||||
/// getFloatWidth/Align/Format - Return the size/align/format of 'float'.
|
||||
unsigned getFloatWidth() const { return FloatWidth; }
|
||||
unsigned getFloatAlign() const { return FloatAlign; }
|
||||
|
|
|
@ -441,6 +441,12 @@ KEYWORD(__pascal , KEYALL)
|
|||
KEYWORD(__vector , KEYALTIVEC)
|
||||
KEYWORD(__pixel , KEYALTIVEC)
|
||||
|
||||
// ARM NEON extensions.
|
||||
ALIAS("__fp16", half , KEYALL)
|
||||
|
||||
// OpenCL Extension.
|
||||
KEYWORD(half , KEYOPENCL)
|
||||
|
||||
// Objective-C ARC keywords.
|
||||
KEYWORD(__bridge , KEYARC)
|
||||
KEYWORD(__bridge_transfer , KEYARC)
|
||||
|
|
|
@ -243,6 +243,7 @@ public:
|
|||
static const TST TST_char16 = clang::TST_char16;
|
||||
static const TST TST_char32 = clang::TST_char32;
|
||||
static const TST TST_int = clang::TST_int;
|
||||
static const TST TST_half = clang::TST_half;
|
||||
static const TST TST_float = clang::TST_float;
|
||||
static const TST TST_double = clang::TST_double;
|
||||
static const TST TST_bool = clang::TST_bool;
|
||||
|
|
|
@ -552,7 +552,9 @@ namespace clang {
|
|||
/// \brief The "auto" deduction type.
|
||||
PREDEF_TYPE_AUTO_DEDUCT = 31,
|
||||
/// \brief The "auto &&" deduction type.
|
||||
PREDEF_TYPE_AUTO_RREF_DEDUCT = 32
|
||||
PREDEF_TYPE_AUTO_RREF_DEDUCT = 32,
|
||||
/// \brief The OpenCL 'half' / ARM NEON __fp16 type.
|
||||
PREDEF_TYPE_HALF_ID = 33
|
||||
};
|
||||
|
||||
/// \brief The number of predefined type IDs that are reserved for
|
||||
|
|
|
@ -50,7 +50,7 @@ unsigned ASTContext::NumImplicitDestructors;
|
|||
unsigned ASTContext::NumImplicitDestructorsDeclared;
|
||||
|
||||
enum FloatingRank {
|
||||
FloatRank, DoubleRank, LongDoubleRank
|
||||
HalfRank, FloatRank, DoubleRank, LongDoubleRank
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -483,6 +483,9 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
|
|||
|
||||
// nullptr type (C++0x 2.14.7)
|
||||
InitBuiltinType(NullPtrTy, BuiltinType::NullPtr);
|
||||
|
||||
// half type (OpenCL 6.1.1.1) / ARM NEON __fp16
|
||||
InitBuiltinType(HalfTy, BuiltinType::Half);
|
||||
}
|
||||
|
||||
DiagnosticsEngine &ASTContext::getDiagnostics() const {
|
||||
|
@ -683,6 +686,7 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
|
|||
assert(BT && "Not a floating point type!");
|
||||
switch (BT->getKind()) {
|
||||
default: llvm_unreachable("Not a floating point type!");
|
||||
case BuiltinType::Half: return Target->getHalfFormat();
|
||||
case BuiltinType::Float: return Target->getFloatFormat();
|
||||
case BuiltinType::Double: return Target->getDoubleFormat();
|
||||
case BuiltinType::LongDouble: return Target->getLongDoubleFormat();
|
||||
|
@ -905,6 +909,10 @@ ASTContext::getTypeInfo(const Type *T) const {
|
|||
Width = 128;
|
||||
Align = 128; // int128_t is 128-bit aligned on all targets.
|
||||
break;
|
||||
case BuiltinType::Half:
|
||||
Width = Target->getHalfWidth();
|
||||
Align = Target->getHalfAlign();
|
||||
break;
|
||||
case BuiltinType::Float:
|
||||
Width = Target->getFloatWidth();
|
||||
Align = Target->getFloatAlign();
|
||||
|
@ -3483,6 +3491,7 @@ static FloatingRank getFloatingRank(QualType T) {
|
|||
assert(T->getAs<BuiltinType>() && "getFloatingRank(): not a floating type");
|
||||
switch (T->getAs<BuiltinType>()->getKind()) {
|
||||
default: llvm_unreachable("getFloatingRank(): not a floating type");
|
||||
case BuiltinType::Half: return HalfRank;
|
||||
case BuiltinType::Float: return FloatRank;
|
||||
case BuiltinType::Double: return DoubleRank;
|
||||
case BuiltinType::LongDouble: return LongDoubleRank;
|
||||
|
|
|
@ -1374,6 +1374,7 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
|
|||
case BuiltinType::Long : return Importer.getToContext().LongTy;
|
||||
case BuiltinType::LongLong : return Importer.getToContext().LongLongTy;
|
||||
case BuiltinType::Int128 : return Importer.getToContext().Int128Ty;
|
||||
case BuiltinType::Half: return Importer.getToContext().HalfTy;
|
||||
case BuiltinType::Float: return Importer.getToContext().FloatTy;
|
||||
case BuiltinType::Double: return Importer.getToContext().DoubleTy;
|
||||
case BuiltinType::LongDouble: return Importer.getToContext().LongDoubleTy;
|
||||
|
|
|
@ -1704,7 +1704,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
|
|||
// UNSUPPORTED: ::= Dd # IEEE 754r decimal floating point (64 bits)
|
||||
// UNSUPPORTED: ::= De # IEEE 754r decimal floating point (128 bits)
|
||||
// UNSUPPORTED: ::= Df # IEEE 754r decimal floating point (32 bits)
|
||||
// UNSUPPORTED: ::= Dh # IEEE 754r half-precision floating point (16 bits)
|
||||
// ::= Dh # IEEE 754r half-precision floating point (16 bits)
|
||||
// ::= Di # char32_t
|
||||
// ::= Ds # char16_t
|
||||
// ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
|
||||
|
@ -1729,6 +1729,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
|
|||
case BuiltinType::Long: Out << 'l'; break;
|
||||
case BuiltinType::LongLong: Out << 'x'; break;
|
||||
case BuiltinType::Int128: Out << 'n'; break;
|
||||
case BuiltinType::Half: Out << "Dh"; break;
|
||||
case BuiltinType::Float: Out << 'f'; break;
|
||||
case BuiltinType::Double: Out << 'd'; break;
|
||||
case BuiltinType::LongDouble: Out << 'e'; break;
|
||||
|
|
|
@ -713,6 +713,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T) {
|
|||
|
||||
case BuiltinType::Char16:
|
||||
case BuiltinType::Char32:
|
||||
case BuiltinType::Half:
|
||||
case BuiltinType::NullPtr:
|
||||
llvm_unreachable("Don't know how to mangle this type");
|
||||
}
|
||||
|
|
|
@ -766,9 +766,16 @@ bool Type::hasUnsignedIntegerRepresentation() const {
|
|||
return isUnsignedIntegerType();
|
||||
}
|
||||
|
||||
bool Type::isHalfType() const {
|
||||
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
|
||||
return BT->getKind() == BuiltinType::Half;
|
||||
// FIXME: Should we allow complex __fp16? Probably not.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Type::isFloatingType() const {
|
||||
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
|
||||
return BT->getKind() >= BuiltinType::Float &&
|
||||
return BT->getKind() >= BuiltinType::Half &&
|
||||
BT->getKind() <= BuiltinType::LongDouble;
|
||||
if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
|
||||
return CT->getElementType()->isFloatingType();
|
||||
|
@ -1475,6 +1482,7 @@ const char *BuiltinType::getName(const PrintingPolicy &Policy) const {
|
|||
case ULong: return "unsigned long";
|
||||
case ULongLong: return "unsigned long long";
|
||||
case UInt128: return "__uint128_t";
|
||||
case Half: return "half";
|
||||
case Float: return "float";
|
||||
case Double: return "double";
|
||||
case LongDouble: return "long double";
|
||||
|
|
|
@ -206,7 +206,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
|
|||
case BuiltinType::Char_S:
|
||||
return TST_char;
|
||||
case BuiltinType::Char16:
|
||||
return TST_char16;
|
||||
return TST_char16;
|
||||
case BuiltinType::Char32:
|
||||
return TST_char32;
|
||||
case BuiltinType::WChar_S:
|
||||
|
@ -225,6 +225,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
|
|||
case BuiltinType::Long:
|
||||
case BuiltinType::LongLong:
|
||||
case BuiltinType::Int128:
|
||||
case BuiltinType::Half:
|
||||
case BuiltinType::Float:
|
||||
case BuiltinType::Double:
|
||||
case BuiltinType::LongDouble:
|
||||
|
|
|
@ -387,6 +387,7 @@ bool PrintfSpecifier::fixType(QualType QT) {
|
|||
case BuiltinType::Char32:
|
||||
case BuiltinType::UInt128:
|
||||
case BuiltinType::Int128:
|
||||
case BuiltinType::Half:
|
||||
// Integral types which are non-trivial to correct.
|
||||
return false;
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
|
|||
IntWidth = IntAlign = 32;
|
||||
LongWidth = LongAlign = 32;
|
||||
LongLongWidth = LongLongAlign = 64;
|
||||
HalfWidth = 16;
|
||||
HalfAlign = 16;
|
||||
FloatWidth = 32;
|
||||
FloatAlign = 32;
|
||||
DoubleWidth = 64;
|
||||
|
@ -57,6 +59,7 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
|
|||
UseBitFieldTypeAlignment = true;
|
||||
UseZeroLengthBitfieldAlignment = false;
|
||||
ZeroLengthBitfieldBoundary = 0;
|
||||
HalfFormat = &llvm::APFloat::IEEEhalf;
|
||||
FloatFormat = &llvm::APFloat::IEEEsingle;
|
||||
DoubleFormat = &llvm::APFloat::IEEEdouble;
|
||||
LongDoubleFormat = &llvm::APFloat::IEEEdouble;
|
||||
|
|
|
@ -391,6 +391,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
|
|||
case BuiltinType::WChar_S:
|
||||
case BuiltinType::LongLong: Encoding = llvm::dwarf::DW_ATE_signed; break;
|
||||
case BuiltinType::Bool: Encoding = llvm::dwarf::DW_ATE_boolean; break;
|
||||
case BuiltinType::Half:
|
||||
case BuiltinType::Float:
|
||||
case BuiltinType::LongDouble:
|
||||
case BuiltinType::Double: Encoding = llvm::dwarf::DW_ATE_float; break;
|
||||
|
|
|
@ -1026,8 +1026,13 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E,
|
|||
NULL);
|
||||
return llvm::ConstantStruct::get(STy, Complex);
|
||||
}
|
||||
case APValue::Float:
|
||||
return llvm::ConstantFP::get(VMContext, Result.Val.getFloat());
|
||||
case APValue::Float: {
|
||||
const llvm::APFloat &Init = Result.Val.getFloat();
|
||||
if (&Init.getSemantics() == &llvm::APFloat::IEEEhalf)
|
||||
return llvm::ConstantInt::get(VMContext, Init.bitcastToAPInt());
|
||||
else
|
||||
return llvm::ConstantFP::get(VMContext, Init);
|
||||
}
|
||||
case APValue::ComplexFloat: {
|
||||
llvm::Constant *Complex[2];
|
||||
|
||||
|
|
|
@ -552,6 +552,16 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
|
|||
|
||||
if (DstType->isVoidType()) return 0;
|
||||
|
||||
llvm::Type *SrcTy = Src->getType();
|
||||
|
||||
// Floating casts might be a bit special: if we're doing casts to / from half
|
||||
// FP, we should go via special intrinsics.
|
||||
if (SrcType->isHalfType()) {
|
||||
Src = Builder.CreateCall(CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16), Src);
|
||||
SrcType = CGF.getContext().FloatTy;
|
||||
SrcTy = llvm::Type::getFloatTy(VMContext);
|
||||
}
|
||||
|
||||
// Handle conversions to bool first, they are special: comparisons against 0.
|
||||
if (DstType->isBooleanType())
|
||||
return EmitConversionToBool(Src, SrcType);
|
||||
|
@ -559,7 +569,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
|
|||
llvm::Type *DstTy = ConvertType(DstType);
|
||||
|
||||
// Ignore conversions like int -> uint.
|
||||
if (Src->getType() == DstTy)
|
||||
if (SrcTy == DstTy)
|
||||
return Src;
|
||||
|
||||
// Handle pointer conversions next: pointers can only be converted to/from
|
||||
|
@ -567,7 +577,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
|
|||
// some native types (like Obj-C id) may map to a pointer type.
|
||||
if (isa<llvm::PointerType>(DstTy)) {
|
||||
// The source value may be an integer, or a pointer.
|
||||
if (isa<llvm::PointerType>(Src->getType()))
|
||||
if (isa<llvm::PointerType>(SrcTy))
|
||||
return Builder.CreateBitCast(Src, DstTy, "conv");
|
||||
|
||||
assert(SrcType->isIntegerType() && "Not ptr->ptr or int->ptr conversion?");
|
||||
|
@ -581,7 +591,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
|
|||
return Builder.CreateIntToPtr(IntResult, DstTy, "conv");
|
||||
}
|
||||
|
||||
if (isa<llvm::PointerType>(Src->getType())) {
|
||||
if (isa<llvm::PointerType>(SrcTy)) {
|
||||
// Must be an ptr to int cast.
|
||||
assert(isa<llvm::IntegerType>(DstTy) && "not ptr->int?");
|
||||
return Builder.CreatePtrToInt(Src, DstTy, "conv");
|
||||
|
@ -610,34 +620,47 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
|
|||
}
|
||||
|
||||
// Allow bitcast from vector to integer/fp of the same size.
|
||||
if (isa<llvm::VectorType>(Src->getType()) ||
|
||||
if (isa<llvm::VectorType>(SrcTy) ||
|
||||
isa<llvm::VectorType>(DstTy))
|
||||
return Builder.CreateBitCast(Src, DstTy, "conv");
|
||||
|
||||
// Finally, we have the arithmetic types: real int/float.
|
||||
if (isa<llvm::IntegerType>(Src->getType())) {
|
||||
Value *Res = NULL;
|
||||
llvm::Type *ResTy = DstTy;
|
||||
|
||||
// Cast to half via float
|
||||
if (DstType->isHalfType())
|
||||
DstTy = llvm::Type::getFloatTy(VMContext);
|
||||
|
||||
if (isa<llvm::IntegerType>(SrcTy)) {
|
||||
bool InputSigned = SrcType->isSignedIntegerOrEnumerationType();
|
||||
if (isa<llvm::IntegerType>(DstTy))
|
||||
return Builder.CreateIntCast(Src, DstTy, InputSigned, "conv");
|
||||
Res = Builder.CreateIntCast(Src, DstTy, InputSigned, "conv");
|
||||
else if (InputSigned)
|
||||
return Builder.CreateSIToFP(Src, DstTy, "conv");
|
||||
Res = Builder.CreateSIToFP(Src, DstTy, "conv");
|
||||
else
|
||||
return Builder.CreateUIToFP(Src, DstTy, "conv");
|
||||
}
|
||||
|
||||
assert(Src->getType()->isFloatingPointTy() && "Unknown real conversion");
|
||||
if (isa<llvm::IntegerType>(DstTy)) {
|
||||
Res = Builder.CreateUIToFP(Src, DstTy, "conv");
|
||||
} else if (isa<llvm::IntegerType>(DstTy)) {
|
||||
assert(SrcTy->isFloatingPointTy() && "Unknown real conversion");
|
||||
if (DstType->isSignedIntegerOrEnumerationType())
|
||||
return Builder.CreateFPToSI(Src, DstTy, "conv");
|
||||
Res = Builder.CreateFPToSI(Src, DstTy, "conv");
|
||||
else
|
||||
return Builder.CreateFPToUI(Src, DstTy, "conv");
|
||||
Res = Builder.CreateFPToUI(Src, DstTy, "conv");
|
||||
} else {
|
||||
assert(SrcTy->isFloatingPointTy() && DstTy->isFloatingPointTy() &&
|
||||
"Unknown real conversion");
|
||||
if (DstTy->getTypeID() < SrcTy->getTypeID())
|
||||
Res = Builder.CreateFPTrunc(Src, DstTy, "conv");
|
||||
else
|
||||
Res = Builder.CreateFPExt(Src, DstTy, "conv");
|
||||
}
|
||||
|
||||
assert(DstTy->isFloatingPointTy() && "Unknown real conversion");
|
||||
if (DstTy->getTypeID() < Src->getType()->getTypeID())
|
||||
return Builder.CreateFPTrunc(Src, DstTy, "conv");
|
||||
else
|
||||
return Builder.CreateFPExt(Src, DstTy, "conv");
|
||||
if (DstTy != ResTy) {
|
||||
assert(ResTy->isIntegerTy(16) && "Only half FP requires extra conversion");
|
||||
Res = Builder.CreateCall(CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16), Res);
|
||||
}
|
||||
|
||||
return Res;
|
||||
}
|
||||
|
||||
/// EmitComplexToScalarConversion - Emit a conversion from the specified complex
|
||||
|
@ -1202,7 +1225,6 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
|
|||
case CK_FloatingToIntegral:
|
||||
case CK_FloatingCast:
|
||||
return EmitScalarConversion(Visit(E), E->getType(), DestTy);
|
||||
|
||||
case CK_IntegralToBoolean:
|
||||
return EmitIntToBoolConversion(Visit(E));
|
||||
case CK_PointerToBoolean:
|
||||
|
@ -1356,6 +1378,14 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
|
|||
} else if (type->isRealFloatingType()) {
|
||||
// Add the inc/dec to the real part.
|
||||
llvm::Value *amt;
|
||||
|
||||
if (type->isHalfType()) {
|
||||
// Another special case: half FP increment should be done via float
|
||||
value =
|
||||
Builder.CreateCall(CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16),
|
||||
input);
|
||||
}
|
||||
|
||||
if (value->getType()->isFloatTy())
|
||||
amt = llvm::ConstantFP::get(VMContext,
|
||||
llvm::APFloat(static_cast<float>(amount)));
|
||||
|
@ -1371,6 +1401,11 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
|
|||
}
|
||||
value = Builder.CreateFAdd(value, amt, isInc ? "inc" : "dec");
|
||||
|
||||
if (type->isHalfType())
|
||||
value =
|
||||
Builder.CreateCall(CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16),
|
||||
value);
|
||||
|
||||
// Objective-C pointer types.
|
||||
} else {
|
||||
const ObjCObjectPointerType *OPT = type->castAs<ObjCObjectPointerType>();
|
||||
|
@ -1387,13 +1422,13 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
|
|||
value = Builder.CreateInBoundsGEP(value, sizeValue, "incdec.objptr");
|
||||
value = Builder.CreateBitCast(value, input->getType());
|
||||
}
|
||||
|
||||
|
||||
// Store the updated result through the lvalue.
|
||||
if (LV.isBitField())
|
||||
CGF.EmitStoreThroughBitfieldLValue(RValue::get(value), LV, &value);
|
||||
else
|
||||
CGF.EmitStoreThroughLValue(RValue::get(value), LV);
|
||||
|
||||
|
||||
// If this is a postinc, return the value read from memory, otherwise use the
|
||||
// updated value.
|
||||
return isPre ? value : input;
|
||||
|
|
|
@ -185,6 +185,7 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
|
|||
case BuiltinType::ULong:
|
||||
case BuiltinType::LongLong:
|
||||
case BuiltinType::ULongLong:
|
||||
case BuiltinType::Half:
|
||||
case BuiltinType::Float:
|
||||
case BuiltinType::Double:
|
||||
case BuiltinType::LongDouble:
|
||||
|
|
|
@ -263,6 +263,8 @@ void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) {
|
|||
|
||||
static llvm::Type *getTypeForFormat(llvm::LLVMContext &VMContext,
|
||||
const llvm::fltSemantics &format) {
|
||||
if (&format == &llvm::APFloat::IEEEhalf)
|
||||
return llvm::Type::getInt16Ty(VMContext);
|
||||
if (&format == &llvm::APFloat::IEEEsingle)
|
||||
return llvm::Type::getFloatTy(VMContext);
|
||||
if (&format == &llvm::APFloat::IEEEdouble)
|
||||
|
@ -341,6 +343,14 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
|
|||
static_cast<unsigned>(Context.getTypeSize(T)));
|
||||
break;
|
||||
|
||||
case BuiltinType::Half:
|
||||
// Half is special: it might be lowered to i16 (and will be storage-only
|
||||
// type),. or can be represented as a set of native operations.
|
||||
|
||||
// FIXME: Ask target which kind of half FP it prefers (storage only vs
|
||||
// native).
|
||||
ResultType = llvm::Type::getInt16Ty(getLLVMContext());
|
||||
break;
|
||||
case BuiltinType::Float:
|
||||
case BuiltinType::Double:
|
||||
case BuiltinType::LongDouble:
|
||||
|
|
|
@ -2075,6 +2075,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
|||
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec,
|
||||
DiagID);
|
||||
break;
|
||||
case tok::kw_half:
|
||||
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec,
|
||||
DiagID);
|
||||
break;
|
||||
case tok::kw_float:
|
||||
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec,
|
||||
DiagID);
|
||||
|
@ -2383,6 +2387,9 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
|
|||
case tok::kw_int:
|
||||
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID);
|
||||
break;
|
||||
case tok::kw_half:
|
||||
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, DiagID);
|
||||
break;
|
||||
case tok::kw_float:
|
||||
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID);
|
||||
break;
|
||||
|
@ -3116,6 +3123,7 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const {
|
|||
case tok::kw_char16_t:
|
||||
case tok::kw_char32_t:
|
||||
case tok::kw_int:
|
||||
case tok::kw_half:
|
||||
case tok::kw_float:
|
||||
case tok::kw_double:
|
||||
case tok::kw_bool:
|
||||
|
@ -3185,6 +3193,7 @@ bool Parser::isTypeSpecifierQualifier() {
|
|||
case tok::kw_char16_t:
|
||||
case tok::kw_char32_t:
|
||||
case tok::kw_int:
|
||||
case tok::kw_half:
|
||||
case tok::kw_float:
|
||||
case tok::kw_double:
|
||||
case tok::kw_bool:
|
||||
|
@ -3319,6 +3328,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
|
|||
case tok::kw_char32_t:
|
||||
|
||||
case tok::kw_int:
|
||||
case tok::kw_half:
|
||||
case tok::kw_float:
|
||||
case tok::kw_double:
|
||||
case tok::kw_bool:
|
||||
|
|
|
@ -920,6 +920,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
|
|||
case tok::kw___int64:
|
||||
case tok::kw_signed:
|
||||
case tok::kw_unsigned:
|
||||
case tok::kw_half:
|
||||
case tok::kw_float:
|
||||
case tok::kw_double:
|
||||
case tok::kw_void:
|
||||
|
|
|
@ -1239,6 +1239,7 @@ bool Parser::isCXXSimpleTypeSpecifier() const {
|
|||
case tok::kw_void:
|
||||
case tok::kw_char:
|
||||
case tok::kw_int:
|
||||
case tok::kw_half:
|
||||
case tok::kw_float:
|
||||
case tok::kw_double:
|
||||
case tok::kw_wchar_t:
|
||||
|
@ -1343,6 +1344,9 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
|
|||
case tok::kw_int:
|
||||
DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID);
|
||||
break;
|
||||
case tok::kw_half:
|
||||
DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, DiagID);
|
||||
break;
|
||||
case tok::kw_float:
|
||||
DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID);
|
||||
break;
|
||||
|
|
|
@ -685,6 +685,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
|
|||
case tok::kw_const:
|
||||
case tok::kw_double:
|
||||
case tok::kw_enum:
|
||||
case tok::kw_half:
|
||||
case tok::kw_float:
|
||||
case tok::kw_int:
|
||||
case tok::kw_long:
|
||||
|
@ -994,6 +995,7 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
|
|||
case tok::kw___int64:
|
||||
case tok::kw_signed:
|
||||
case tok::kw_unsigned:
|
||||
case tok::kw_half:
|
||||
case tok::kw_float:
|
||||
case tok::kw_double:
|
||||
case tok::kw_void:
|
||||
|
|
|
@ -257,6 +257,7 @@ bool Declarator::isDeclarationOfFunction() const {
|
|||
case TST_enum:
|
||||
case TST_error:
|
||||
case TST_float:
|
||||
case TST_half:
|
||||
case TST_int:
|
||||
case TST_struct:
|
||||
case TST_union:
|
||||
|
@ -373,6 +374,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
|
|||
case DeclSpec::TST_char16: return "char16_t";
|
||||
case DeclSpec::TST_char32: return "char32_t";
|
||||
case DeclSpec::TST_int: return "int";
|
||||
case DeclSpec::TST_half: return "half";
|
||||
case DeclSpec::TST_float: return "float";
|
||||
case DeclSpec::TST_double: return "double";
|
||||
case DeclSpec::TST_bool: return "_Bool";
|
||||
|
|
|
@ -4729,7 +4729,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
diag::err_object_cannot_be_passed_returned_by_value) << 0
|
||||
<< R->getAs<FunctionType>()->getResultType()
|
||||
<< FixItHint::CreateInsertion(D.getIdentifierLoc(), "*");
|
||||
|
||||
|
||||
QualType T = R->getAs<FunctionType>()->getResultType();
|
||||
T = Context.getObjCObjectPointerType(T);
|
||||
if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(R)) {
|
||||
|
@ -4740,7 +4740,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
else if (isa<FunctionNoProtoType>(R))
|
||||
R = Context.getFunctionNoProtoType(T);
|
||||
}
|
||||
|
||||
|
||||
bool isFriend = false;
|
||||
FunctionTemplateDecl *FunctionTemplate = 0;
|
||||
bool isExplicitSpecialization = false;
|
||||
|
@ -5065,6 +5065,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
assert(R->isFunctionNoProtoType() && NewFD->getNumParams() == 0 &&
|
||||
"Should not need args for typedef of non-prototype fn");
|
||||
}
|
||||
|
||||
// Finally, we know we have the right number of parameters, install them.
|
||||
NewFD->setParams(Params);
|
||||
|
||||
|
|
|
@ -396,12 +396,14 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
|
|||
// C99 6.3.2.1p2:
|
||||
// If the lvalue has qualified type, the value has the unqualified
|
||||
// version of the type of the lvalue; otherwise, the value has the
|
||||
// type of the lvalue.
|
||||
// type of the lvalue.
|
||||
if (T.hasQualifiers())
|
||||
T = T.getUnqualifiedType();
|
||||
|
||||
return Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue,
|
||||
E, 0, VK_RValue));
|
||||
|
||||
ExprResult Res = Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue,
|
||||
E, 0, VK_RValue));
|
||||
|
||||
return Res;
|
||||
}
|
||||
|
||||
ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E) {
|
||||
|
@ -426,10 +428,15 @@ ExprResult Sema::UsualUnaryConversions(Expr *E) {
|
|||
if (Res.isInvalid())
|
||||
return Owned(E);
|
||||
E = Res.take();
|
||||
|
||||
|
||||
QualType Ty = E->getType();
|
||||
assert(!Ty.isNull() && "UsualUnaryConversions - missing type");
|
||||
|
||||
|
||||
// Half FP is a bit different: it's a storage-only type, meaning that any
|
||||
// "use" of it should be promoted to float.
|
||||
if (Ty->isHalfType())
|
||||
return ImpCastExprToType(Res.take(), Context.FloatTy, CK_FloatingCast);
|
||||
|
||||
// Try to perform integral promotions if the object has a theoretically
|
||||
// promotable type.
|
||||
if (Ty->isIntegralOrUnscopedEnumerationType()) {
|
||||
|
@ -446,7 +453,7 @@ ExprResult Sema::UsualUnaryConversions(Expr *E) {
|
|||
// value is converted to an int; otherwise, it is converted to an
|
||||
// unsigned int. These are called the integer promotions. All
|
||||
// other types are unchanged by the integer promotions.
|
||||
|
||||
|
||||
QualType PTy = Context.isPromotableBitField(E);
|
||||
if (!PTy.isNull()) {
|
||||
E = ImpCastExprToType(E, PTy, CK_IntegralCast).take();
|
||||
|
@ -8103,6 +8110,13 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
|
|||
Input = DefaultFunctionArrayLvalueConversion(Input.take());
|
||||
if (Input.isInvalid()) return ExprError();
|
||||
resultType = Input.get()->getType();
|
||||
|
||||
// Though we still have to promote half FP to float...
|
||||
if (resultType->isHalfType()) {
|
||||
Input = ImpCastExprToType(Input.take(), Context.FloatTy, CK_FloatingCast).take();
|
||||
resultType = Context.FloatTy;
|
||||
}
|
||||
|
||||
if (resultType->isDependentType())
|
||||
break;
|
||||
if (resultType->isScalarType()) {
|
||||
|
|
|
@ -2416,6 +2416,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
|
|||
}
|
||||
|
||||
case ICK_Boolean_Conversion:
|
||||
// Perform half-to-boolean conversion via float.
|
||||
if (From->getType()->isHalfType()) {
|
||||
From = ImpCastExprToType(From, Context.FloatTy, CK_FloatingCast).take();
|
||||
FromType = Context.FloatTy;
|
||||
}
|
||||
|
||||
From = ImpCastExprToType(From, Context.BoolTy,
|
||||
ScalarTypeToBooleanCastKind(FromType),
|
||||
VK_RValue, /*BasePath=*/0, CCK).take();
|
||||
|
|
|
@ -1469,10 +1469,10 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
|
|||
/// FromType to ToType is a floating point promotion (C++ 4.6). If so,
|
||||
/// returns true and sets PromotedType to the promoted type.
|
||||
bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) {
|
||||
/// An rvalue of type float can be converted to an rvalue of type
|
||||
/// double. (C++ 4.6p1).
|
||||
if (const BuiltinType *FromBuiltin = FromType->getAs<BuiltinType>())
|
||||
if (const BuiltinType *ToBuiltin = ToType->getAs<BuiltinType>()) {
|
||||
/// An rvalue of type float can be converted to an rvalue of type
|
||||
/// double. (C++ 4.6p1).
|
||||
if (FromBuiltin->getKind() == BuiltinType::Float &&
|
||||
ToBuiltin->getKind() == BuiltinType::Double)
|
||||
return true;
|
||||
|
@ -1485,6 +1485,11 @@ bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) {
|
|||
FromBuiltin->getKind() == BuiltinType::Double) &&
|
||||
(ToBuiltin->getKind() == BuiltinType::LongDouble))
|
||||
return true;
|
||||
|
||||
// Half can be promoted to float.
|
||||
if (FromBuiltin->getKind() == BuiltinType::Half &&
|
||||
ToBuiltin->getKind() == BuiltinType::Float)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -641,6 +641,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
|
|||
case TST_char16:
|
||||
case TST_char32:
|
||||
case TST_int:
|
||||
case TST_half:
|
||||
case TST_float:
|
||||
case TST_double:
|
||||
case TST_bool:
|
||||
|
|
|
@ -711,6 +711,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case DeclSpec::TST_half: Result = Context.HalfTy; break;
|
||||
case DeclSpec::TST_float: Result = Context.FloatTy; break;
|
||||
case DeclSpec::TST_double:
|
||||
if (DS.getTypeSpecWidth() == DeclSpec::TSW_long)
|
||||
|
@ -1434,13 +1435,26 @@ QualType Sema::BuildFunctionType(QualType T,
|
|||
<< T->isFunctionType() << T;
|
||||
return QualType();
|
||||
}
|
||||
|
||||
|
||||
// Functions cannot return half FP.
|
||||
if (T->isHalfType()) {
|
||||
Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 1 <<
|
||||
FixItHint::CreateInsertion(Loc, "*");
|
||||
return QualType();
|
||||
}
|
||||
|
||||
bool Invalid = false;
|
||||
for (unsigned Idx = 0; Idx < NumParamTypes; ++Idx) {
|
||||
// FIXME: Loc is too inprecise here, should use proper locations for args.
|
||||
QualType ParamType = Context.getAdjustedParameterType(ParamTypes[Idx]);
|
||||
if (ParamType->isVoidType()) {
|
||||
Diag(Loc, diag::err_param_with_void_type);
|
||||
Invalid = true;
|
||||
} else if (ParamType->isHalfType()) {
|
||||
// Disallow half FP arguments.
|
||||
Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 0 <<
|
||||
FixItHint::CreateInsertion(Loc, "*");
|
||||
Invalid = true;
|
||||
}
|
||||
|
||||
ParamTypes[Idx] = ParamType;
|
||||
|
@ -2062,6 +2076,15 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|||
D.setInvalidType(true);
|
||||
}
|
||||
|
||||
// Do not allow returning half FP value.
|
||||
// FIXME: This really should be in BuildFunctionType.
|
||||
if (T->isHalfType()) {
|
||||
S.Diag(D.getIdentifierLoc(),
|
||||
diag::err_parameters_retval_cannot_have_fp16_type) << 1
|
||||
<< FixItHint::CreateInsertion(D.getIdentifierLoc(), "*");
|
||||
D.setInvalidType(true);
|
||||
}
|
||||
|
||||
// cv-qualifiers on return types are pointless except when the type is a
|
||||
// class type in C++.
|
||||
if (isa<PointerType>(T) && T.getLocalCVRQualifiers() &&
|
||||
|
@ -2185,6 +2208,13 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|||
// Do not add 'void' to the ArgTys list.
|
||||
break;
|
||||
}
|
||||
} else if (ArgTy->isHalfType()) {
|
||||
// Disallow half FP arguments.
|
||||
// FIXME: This really should be in BuildFunctionType.
|
||||
S.Diag(Param->getLocation(),
|
||||
diag::err_parameters_retval_cannot_have_fp16_type) << 0
|
||||
<< FixItHint::CreateInsertion(Param->getLocation(), "*");
|
||||
D.setInvalidType();
|
||||
} else if (!FTI.hasPrototype) {
|
||||
if (ArgTy->isPromotableIntegerType()) {
|
||||
ArgTy = Context.getPromotedIntegerType(ArgTy);
|
||||
|
|
|
@ -43,6 +43,7 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
|
|||
case BuiltinType::Long: ID = PREDEF_TYPE_LONG_ID; break;
|
||||
case BuiltinType::LongLong: ID = PREDEF_TYPE_LONGLONG_ID; break;
|
||||
case BuiltinType::Int128: ID = PREDEF_TYPE_INT128_ID; break;
|
||||
case BuiltinType::Half: ID = PREDEF_TYPE_HALF_ID; break;
|
||||
case BuiltinType::Float: ID = PREDEF_TYPE_FLOAT_ID; break;
|
||||
case BuiltinType::Double: ID = PREDEF_TYPE_DOUBLE_ID; break;
|
||||
case BuiltinType::LongDouble: ID = PREDEF_TYPE_LONGDOUBLE_ID; break;
|
||||
|
|
|
@ -3819,6 +3819,7 @@ QualType ASTReader::GetType(TypeID ID) {
|
|||
case PREDEF_TYPE_LONG_ID: T = Context.LongTy; break;
|
||||
case PREDEF_TYPE_LONGLONG_ID: T = Context.LongLongTy; break;
|
||||
case PREDEF_TYPE_INT128_ID: T = Context.Int128Ty; break;
|
||||
case PREDEF_TYPE_HALF_ID: T = Context.HalfTy; break;
|
||||
case PREDEF_TYPE_FLOAT_ID: T = Context.FloatTy; break;
|
||||
case PREDEF_TYPE_DOUBLE_ID: T = Context.DoubleTy; break;
|
||||
case PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break;
|
||||
|
|
|
@ -1359,6 +1359,7 @@ bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
|
|||
case BuiltinType::Long:
|
||||
case BuiltinType::LongLong:
|
||||
case BuiltinType::Int128:
|
||||
case BuiltinType::Half:
|
||||
case BuiltinType::Float:
|
||||
case BuiltinType::Double:
|
||||
case BuiltinType::LongDouble:
|
||||
|
|
|
@ -570,6 +570,8 @@ void USRGenerator::VisitType(QualType T) {
|
|||
c = 'K'; break;
|
||||
case BuiltinType::Int128:
|
||||
c = 'J'; break;
|
||||
case BuiltinType::Half:
|
||||
c = 'h'; break;
|
||||
case BuiltinType::Float:
|
||||
c = 'f'; break;
|
||||
case BuiltinType::Double:
|
||||
|
|
Loading…
Reference in New Issue