summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorAnton Korobeynikov <asl@math.spbu.ru>2011-10-14 23:23:15 +0000
committerAnton Korobeynikov <asl@math.spbu.ru>2011-10-14 23:23:15 +0000
commitf0c267e6e05c2583c23fad3aa1c9ddad5e9d4998 (patch)
treeb1c9c50501a95458c2582cbb0593561537f6335f /clang/lib
parent1f64b5987263ac40f0f1b104972afde03f5087a5 (diff)
downloadbcm5719-llvm-f0c267e6e05c2583c23fad3aa1c9ddad5e9d4998.tar.gz
bcm5719-llvm-f0c267e6e05c2583c23fad3aa1c9ddad5e9d4998.zip
Provide half floating point support as a storage only type.
Lack of half FP was a regression compared to llvm-gcc. llvm-svn: 142016
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp11
-rw-r--r--clang/lib/AST/ASTImporter.cpp1
-rw-r--r--clang/lib/AST/ItaniumMangle.cpp3
-rw-r--r--clang/lib/AST/MicrosoftMangle.cpp1
-rw-r--r--clang/lib/AST/Type.cpp10
-rw-r--r--clang/lib/AST/TypeLoc.cpp3
-rw-r--r--clang/lib/Analysis/PrintfFormatString.cpp1
-rw-r--r--clang/lib/Basic/TargetInfo.cpp3
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.cpp1
-rw-r--r--clang/lib/CodeGen/CGExprConstant.cpp9
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp79
-rw-r--r--clang/lib/CodeGen/CGRTTI.cpp1
-rw-r--r--clang/lib/CodeGen/CodeGenTypes.cpp10
-rw-r--r--clang/lib/Parse/ParseDecl.cpp10
-rw-r--r--clang/lib/Parse/ParseExpr.cpp1
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp4
-rw-r--r--clang/lib/Parse/ParseTentative.cpp2
-rw-r--r--clang/lib/Sema/DeclSpec.cpp2
-rw-r--r--clang/lib/Sema/SemaDecl.cpp5
-rw-r--r--clang/lib/Sema/SemaExpr.cpp28
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp6
-rw-r--r--clang/lib/Sema/SemaOverload.cpp9
-rw-r--r--clang/lib/Sema/SemaTemplateVariadic.cpp1
-rw-r--r--clang/lib/Sema/SemaType.cpp32
-rw-r--r--clang/lib/Serialization/ASTCommon.cpp1
-rw-r--r--clang/lib/Serialization/ASTReader.cpp1
26 files changed, 195 insertions, 40 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index ae96dfd1481..462428086dd 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -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;
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index ab5c8cf5fe1..3db75bacbf5 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -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;
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index d4ac7229b25..acedf70f29c 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -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;
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index e327d8b180a..1515db49fe3 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -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");
}
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 0e0548db6ce..44eeec004f5 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -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";
diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp
index 34e7693e307..8e8b227e1f0 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -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:
diff --git a/clang/lib/Analysis/PrintfFormatString.cpp b/clang/lib/Analysis/PrintfFormatString.cpp
index 770cd37e9ce..46ece65a42e 100644
--- a/clang/lib/Analysis/PrintfFormatString.cpp
+++ b/clang/lib/Analysis/PrintfFormatString.cpp
@@ -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;
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index a9285e6e2db..593db2b901c 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -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;
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 39a9ef788f9..c7a9b407d26 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -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;
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index 8711c1fdd5b..3997866ea68 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -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];
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 26a3e948efe..3a9fbeed9d6 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -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;
diff --git a/clang/lib/CodeGen/CGRTTI.cpp b/clang/lib/CodeGen/CGRTTI.cpp
index dbf99fa5d76..fbdb2984830 100644
--- a/clang/lib/CodeGen/CGRTTI.cpp
+++ b/clang/lib/CodeGen/CGRTTI.cpp
@@ -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:
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index 03a15ae67ea..e0d92189658 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -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:
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 228e53c4f07..2aa178f5ebe 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -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:
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 548a599f6ee..bc8bbf56400 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -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:
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 6e36c91a094..60166e880c0 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -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;
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index 0e7d288395e..d53839f3cb0 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -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:
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index 3564f2657b0..f0a763e4ecf 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -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";
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 71b3c526a16..8d993ef6103 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -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);
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 41fcf7299db..170097cc59a 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -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()) {
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index d3c4da8816c..3300444a1c1 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -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();
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 6112e0d4181..b0dd5e280eb 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -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;
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index a2aa1b30264..e383db93506 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -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:
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index dc08320cad7..2b563a50a99 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -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);
diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp
index 782e5c6aa79..445e750834e 100644
--- a/clang/lib/Serialization/ASTCommon.cpp
+++ b/clang/lib/Serialization/ASTCommon.cpp
@@ -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;
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 361c3b79ca7..fe1cc30158d 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -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;
OpenPOWER on IntegriCloud