Make a few related changes:
1) add a new ASTContext::getFloatTypeSemantics method.
2) Use it from SemaExpr.cpp, CodeGenTypes.cpp and other places.
3) Change the TargetInfo.h get*Format methods to return their
fltSemantics byref instead of by pointer.
4) Change CodeGenFunction::EmitBuiltinExpr to allow builtins which
sometimes expand specially and othertimes fall back to libm.
5) Add support for __builtin_nan("") to codegen, cases that don't pass
in an empty string are currently lowered to libm calls.
6) Fix codegen of __builtin_infl.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52914 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 08a2bb1..fa12364 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -182,6 +182,20 @@
// Type Sizing and Analysis
//===----------------------------------------------------------------------===//
+/// getFloatTypeSemantics - Return the APFloat 'semantics' for the specified
+/// scalar floating point type.
+const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
+ const BuiltinType *BT = T->getAsBuiltinType();
+ assert(BT && "Not a floating point type!");
+ switch (BT->getKind()) {
+ default: assert(0 && "Not a floating point type!");
+ case BuiltinType::Float: return Target.getFloatFormat();
+ case BuiltinType::Double: return Target.getDoubleFormat();
+ case BuiltinType::LongDouble: return Target.getLongDoubleFormat();
+ }
+}
+
+
/// getTypeSize - Return the size of the specified type, in bits. This method
/// does not work on incomplete types.
std::pair<uint64_t, unsigned>
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 1113e2f..a6a479a 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -38,74 +38,8 @@
RValue CodeGenFunction::EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E) {
switch (BuiltinID) {
- default: {
- if (getContext().BuiltinInfo.isLibFunction(BuiltinID))
- return EmitCallExpr(CGM.getBuiltinLibFunction(BuiltinID),
- E->getCallee()->getType(), E->arg_begin(),
- E->arg_end());
-
- // See if we have a target specific intrinsic.
- Intrinsic::ID IntrinsicID;
- const char *TargetPrefix = Target.getTargetPrefix();
- const char *BuiltinName = getContext().BuiltinInfo.GetName(BuiltinID);
-#define GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN
-#include "llvm/Intrinsics.gen"
-#undef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN
-
- if (IntrinsicID != Intrinsic::not_intrinsic) {
- SmallVector<Value*, 16> Args;
+ default: break; // Handle intrinsics and libm functions below.
- Function *F = CGM.getIntrinsic(IntrinsicID);
- const llvm::FunctionType *FTy = F->getFunctionType();
-
- for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
- Value *ArgValue = EmitScalarExpr(E->getArg(i));
-
- // If the intrinsic arg type is different from the builtin arg type
- // we need to do a bit cast.
- const llvm::Type *PTy = FTy->getParamType(i);
- if (PTy != ArgValue->getType()) {
- assert(PTy->canLosslesslyBitCastTo(FTy->getParamType(i)) &&
- "Must be able to losslessly bit cast to param");
- ArgValue = Builder.CreateBitCast(ArgValue, PTy);
- }
-
- Args.push_back(ArgValue);
- }
-
- Value *V = Builder.CreateCall(F, &Args[0], &Args[0] + Args.size());
- QualType BuiltinRetType = E->getType();
-
- const llvm::Type *RetTy = llvm::Type::VoidTy;
- if (!BuiltinRetType->isVoidType()) RetTy = ConvertType(BuiltinRetType);
-
- if (RetTy != V->getType()) {
- assert(V->getType()->canLosslesslyBitCastTo(RetTy) &&
- "Must be able to losslessly bit cast result type");
- V = Builder.CreateBitCast(V, RetTy);
- }
-
- return RValue::get(V);
- }
-
- // See if we have a target specific builtin that needs to be lowered.
- Value *V = 0;
-
- if (strcmp(TargetPrefix, "x86") == 0)
- V = EmitX86BuiltinExpr(BuiltinID, E);
- else if (strcmp(TargetPrefix, "ppc") == 0)
- V = EmitPPCBuiltinExpr(BuiltinID, E);
-
- if (V)
- return RValue::get(V);
-
- WarnUnsupported(E, "builtin function");
-
- // Unknown builtin, for now just dump it out and return undef.
- if (hasAggregateLLVMType(E->getType()))
- return RValue::getAggregate(CreateTempAlloca(ConvertType(E->getType())));
- return RValue::get(UndefValue::get(ConvertType(E->getType())));
- }
case Builtin::BI__builtin___CFStringMakeConstantString: {
const Expr *Arg = E->getArg(0);
@@ -214,16 +148,29 @@
Value *F = CGM.getIntrinsic(Intrinsic::bswap, &ArgType, 1);
return RValue::get(Builder.CreateCall(F, ArgValue, "tmp"));
}
- case Builtin::BI__builtin_inff: {
- APFloat f(APFloat::IEEEsingle, APFloat::fcInfinity, false);
- return RValue::get(ConstantFP::get(f));
- }
+ case Builtin::BI__builtin_inff:
case Builtin::BI__builtin_huge_val:
case Builtin::BI__builtin_inf:
- // FIXME: mapping long double onto double.
case Builtin::BI__builtin_infl: {
- APFloat f(APFloat::IEEEdouble, APFloat::fcInfinity, false);
- return RValue::get(ConstantFP::get(f));
+ const llvm::fltSemantics &Sem =
+ CGM.getContext().getFloatTypeSemantics(E->getType());
+ return RValue::get(ConstantFP::get(APFloat::getInf(Sem)));
+ }
+ case Builtin::BI__builtin_nanf:
+ case Builtin::BI__builtin_nan:
+ case Builtin::BI__builtin_nanl: {
+ // If this is __builtin_nan("") turn this into a simple nan, otherwise just
+ // call libm nan.
+ if (const StringLiteral *S =
+ dyn_cast<StringLiteral>(E->getArg(0)->IgnoreParenCasts())) {
+ if (!S->isWide() && S->getByteLength() == 0) { // empty string.
+ const llvm::fltSemantics &Sem =
+ CGM.getContext().getFloatTypeSemantics(E->getType());
+ return RValue::get(ConstantFP::get(APFloat::getNaN(Sem)));
+ }
+ }
+ // Otherwise, call libm 'nan'.
+ break;
}
case Builtin::BI__builtin_isgreater:
case Builtin::BI__builtin_isgreaterequal:
@@ -316,8 +263,76 @@
case Builtin::BI__sync_lock_test_and_set:
return EmitBinaryAtomic(*this, Intrinsic::atomic_swap, E);
}
- return RValue::get(0);
-}
+
+ // If this is an alias for a libm function (e.g. __builtin_sin) turn it into
+ // that function.
+ if (getContext().BuiltinInfo.isLibFunction(BuiltinID))
+ return EmitCallExpr(CGM.getBuiltinLibFunction(BuiltinID),
+ E->getCallee()->getType(), E->arg_begin(),
+ E->arg_end());
+
+ // See if we have a target specific intrinsic.
+ Intrinsic::ID IntrinsicID;
+ const char *TargetPrefix = Target.getTargetPrefix();
+ const char *BuiltinName = getContext().BuiltinInfo.GetName(BuiltinID);
+#define GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN
+#include "llvm/Intrinsics.gen"
+#undef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN
+
+ if (IntrinsicID != Intrinsic::not_intrinsic) {
+ SmallVector<Value*, 16> Args;
+
+ Function *F = CGM.getIntrinsic(IntrinsicID);
+ const llvm::FunctionType *FTy = F->getFunctionType();
+
+ for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
+ Value *ArgValue = EmitScalarExpr(E->getArg(i));
+
+ // If the intrinsic arg type is different from the builtin arg type
+ // we need to do a bit cast.
+ const llvm::Type *PTy = FTy->getParamType(i);
+ if (PTy != ArgValue->getType()) {
+ assert(PTy->canLosslesslyBitCastTo(FTy->getParamType(i)) &&
+ "Must be able to losslessly bit cast to param");
+ ArgValue = Builder.CreateBitCast(ArgValue, PTy);
+ }
+
+ Args.push_back(ArgValue);
+ }
+
+ Value *V = Builder.CreateCall(F, &Args[0], &Args[0] + Args.size());
+ QualType BuiltinRetType = E->getType();
+
+ const llvm::Type *RetTy = llvm::Type::VoidTy;
+ if (!BuiltinRetType->isVoidType()) RetTy = ConvertType(BuiltinRetType);
+
+ if (RetTy != V->getType()) {
+ assert(V->getType()->canLosslesslyBitCastTo(RetTy) &&
+ "Must be able to losslessly bit cast result type");
+ V = Builder.CreateBitCast(V, RetTy);
+ }
+
+ return RValue::get(V);
+ }
+
+ // See if we have a target specific builtin that needs to be lowered.
+ Value *V = 0;
+
+ if (strcmp(TargetPrefix, "x86") == 0)
+ V = EmitX86BuiltinExpr(BuiltinID, E);
+ else if (strcmp(TargetPrefix, "ppc") == 0)
+ V = EmitPPCBuiltinExpr(BuiltinID, E);
+
+ if (V)
+ return RValue::get(V);
+
+ WarnUnsupported(E, "builtin function");
+
+ // Unknown builtin, for now just dump it out and return undef.
+ if (hasAggregateLLVMType(E->getType()))
+ return RValue::getAggregate(CreateTempAlloca(ConvertType(E->getType())));
+ return RValue::get(UndefValue::get(ConvertType(E->getType())));
+}
Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index ce49cb2..5a4236a 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -613,7 +613,7 @@
llvm::ConstantFP::get(llvm::APFloat(static_cast<double>(AmountVal)));
else {
llvm::APFloat F(static_cast<float>(AmountVal));
- F.convert(*CGF.Target.getLongDoubleFormat(), llvm::APFloat::rmTowardZero);
+ F.convert(CGF.Target.getLongDoubleFormat(), llvm::APFloat::rmTowardZero);
NextVal = llvm::ConstantFP::get(F);
}
NextVal = Builder.CreateAdd(InVal, NextVal, isInc ? "inc" : "dec");
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index 9074e81..41ec2dd 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -168,18 +168,18 @@
return ConvertType(T);
}
-static const llvm::Type* getTypeForFormat(const llvm::fltSemantics * format) {
- if (format == &llvm::APFloat::IEEEsingle)
+static const llvm::Type* getTypeForFormat(const llvm::fltSemantics &format) {
+ if (&format == &llvm::APFloat::IEEEsingle)
return llvm::Type::FloatTy;
- if (format == &llvm::APFloat::IEEEdouble)
+ if (&format == &llvm::APFloat::IEEEdouble)
return llvm::Type::DoubleTy;
- if (format == &llvm::APFloat::IEEEquad)
+ if (&format == &llvm::APFloat::IEEEquad)
return llvm::Type::FP128Ty;
- if (format == &llvm::APFloat::PPCDoubleDouble)
+ if (&format == &llvm::APFloat::PPCDoubleDouble)
return llvm::Type::PPC_FP128Ty;
- if (format == &llvm::APFloat::x87DoubleExtended)
+ if (&format == &llvm::APFloat::x87DoubleExtended)
return llvm::Type::X86_FP80Ty;
- assert(9 && "Unknown float format!");
+ assert(0 && "Unknown float format!");
return 0;
}
@@ -218,11 +218,9 @@
static_cast<unsigned>(Context.getTypeSize(T)));
case BuiltinType::Float:
- return getTypeForFormat(Context.Target.getFloatFormat());
case BuiltinType::Double:
- return getTypeForFormat(Context.Target.getDoubleFormat());
case BuiltinType::LongDouble:
- return getTypeForFormat(Context.Target.getLongDoubleFormat());
+ return getTypeForFormat(Context.getFloatTypeSemantics(T));
}
break;
}
diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h
index 6c958e6..536e881 100644
--- a/lib/CodeGen/CodeGenTypes.h
+++ b/lib/CodeGen/CodeGenTypes.h
@@ -143,7 +143,7 @@
const llvm::Type *ConvertTypeForMem(QualType T);
void CollectObjCIvarTypes(ObjCInterfaceDecl *ObjCClass,
- std::vector<const llvm::Type*> &IvarTypes);
+ std::vector<const llvm::Type*> &IvarTypes);
const CGRecordLayout *getCGRecordLayout(const TagDecl*) const;
/// Returns a StructType representing an Objective-C object
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 9008884..b328b2f 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -46,9 +46,8 @@
return true;
return TheCall.take();
case Builtin::BI__builtin_va_start:
- if (SemaBuiltinVAStart(TheCall.get())) {
+ if (SemaBuiltinVAStart(TheCall.get()))
return true;
- }
return TheCall.take();
case Builtin::BI__builtin_isgreater:
case Builtin::BI__builtin_isgreaterequal:
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 8ef9486..32d7a60 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -214,23 +214,18 @@
if (Literal.isFloatingLiteral()) {
QualType Ty;
- const llvm::fltSemantics *Format;
-
- if (Literal.isFloat) {
+ if (Literal.isFloat)
Ty = Context.FloatTy;
- Format = Context.Target.getFloatFormat();
- } else if (!Literal.isLong) {
+ else if (!Literal.isLong)
Ty = Context.DoubleTy;
- Format = Context.Target.getDoubleFormat();
- } else {
+ else
Ty = Context.LongDoubleTy;
- Format = Context.Target.getLongDoubleFormat();
- }
-
+
+ const llvm::fltSemantics &Format = Context.getFloatTypeSemantics(Ty);
+
// isExact will be set by GetFloatValue().
bool isExact = false;
-
- Res = new FloatingLiteral(Literal.GetFloatValue(*Format,&isExact), &isExact,
+ Res = new FloatingLiteral(Literal.GetFloatValue(Format, &isExact), &isExact,
Ty, Tok.getLocation());
} else if (!Literal.isIntegerLiteral()) {