aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-06-30 18:32:54 +0000
committerChris Lattner <sabre@nondot.org>2008-06-30 18:32:54 +0000
commitb7cfe88e88cb4f46308de89cf3f0c81bfe624128 (patch)
treef167ab0cf639ac9c700baf35135bc4f69b797152
parent3301cb103d5f32056d62f13bde036988f7cf1330 (diff)
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
-rw-r--r--include/clang/AST/ASTContext.h8
-rw-r--r--include/clang/AST/Builtins.def5
-rw-r--r--include/clang/Basic/TargetInfo.h8
-rw-r--r--lib/AST/ASTContext.cpp14
-rw-r--r--lib/CodeGen/CGBuiltin.cpp167
-rw-r--r--lib/CodeGen/CGExprScalar.cpp2
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp18
-rw-r--r--lib/CodeGen/CodeGenTypes.h2
-rw-r--r--lib/Sema/SemaChecking.cpp3
-rw-r--r--lib/Sema/SemaExpr.cpp19
10 files changed, 139 insertions, 107 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index a9100956fc..51a87dd8c5 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -26,6 +26,10 @@
#include "llvm/Support/Allocator.h"
#include <vector>
+namespace llvm {
+ struct fltSemantics;
+}
+
namespace clang {
class TargetInfo;
class IdentifierTable;
@@ -285,6 +289,10 @@ public:
// Type Sizing and Analysis
//===--------------------------------------------------------------------===//
+ /// getFloatTypeSemantics - Return the APFloat 'semantics' for the specified
+ /// scalar floating point type.
+ const llvm::fltSemantics &getFloatTypeSemantics(QualType T) const;
+
/// getTypeInfo - Get the size and alignment of the specified complete type in
/// bits.
std::pair<uint64_t, unsigned> getTypeInfo(QualType T);
diff --git a/include/clang/AST/Builtins.def b/include/clang/AST/Builtins.def
index 4de5744ad2..de755f5d5f 100644
--- a/include/clang/AST/Builtins.def
+++ b/include/clang/AST/Builtins.def
@@ -54,14 +54,17 @@
// F -> this is a libc/libm function with a '__builtin_' prefix added.
// Standard libc/libm functions:
+BUILTIN(__builtin_huge_val, "d", "nc")
BUILTIN(__builtin_inf , "d" , "nc")
BUILTIN(__builtin_inff , "f" , "nc")
BUILTIN(__builtin_infl , "Ld" , "nc")
+BUILTIN(__builtin_nan, "dcC*" , "ncF")
+BUILTIN(__builtin_nanf, "fcC*" , "ncF")
+BUILTIN(__builtin_nanl, "LdcC*", "ncF")
BUILTIN(__builtin_abs , "ii" , "ncF")
BUILTIN(__builtin_fabs , "dd" , "ncF")
BUILTIN(__builtin_fabsf, "ff" , "ncF")
BUILTIN(__builtin_fabsl, "LdLd", "ncF")
-BUILTIN(__builtin_huge_val, "d", "nc")
BUILTIN(__builtin_copysign, "ddd", "ncF")
BUILTIN(__builtin_copysignf, "fff", "ncF")
BUILTIN(__builtin_copysignl, "LdLdLd", "ncF")
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index 0196de2d7e..083aaf0e68 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -118,19 +118,19 @@ public:
/// getFloatWidth/Align/Format - Return the size/align/format of 'float'.
unsigned getFloatWidth() const { return FloatWidth; }
unsigned getFloatAlign() const { return FloatAlign; }
- const llvm::fltSemantics *getFloatFormat() const { return FloatFormat; }
+ const llvm::fltSemantics &getFloatFormat() const { return *FloatFormat; }
/// getDoubleWidth/Align/Format - Return the size/align/format of 'double'.
unsigned getDoubleWidth() const { return DoubleWidth; }
unsigned getDoubleAlign() const { return DoubleAlign; }
- const llvm::fltSemantics *getDoubleFormat() const { return DoubleFormat; }
+ const llvm::fltSemantics &getDoubleFormat() const { return *DoubleFormat; }
/// getLongDoubleWidth/Align/Format - Return the size/align/format of 'long
/// double'.
unsigned getLongDoubleWidth() const { return LongDoubleWidth; }
unsigned getLongDoubleAlign() const { return LongDoubleAlign; }
- const llvm::fltSemantics *getLongDoubleFormat() const {
- return LongDoubleFormat;
+ const llvm::fltSemantics &getLongDoubleFormat() const {
+ return *LongDoubleFormat;
}
/// getIntMaxTWidth - Return the size of intmax_t and uintmax_t for this
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 08a2bb1357..fa12364c52 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -182,6 +182,20 @@ void ASTContext::InitBuiltinTypes() {
// 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 1113e2f422..a6a479a87d 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -38,74 +38,8 @@ static RValue EmitBinaryAtomic(CodeGenFunction& CFG,
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;
-
- Function *F = CGM.getIntrinsic(IntrinsicID);
- const llvm::FunctionType *FTy = F->getFunctionType();
+ default: break; // Handle intrinsics and libm functions below.
- 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 @@ RValue CodeGenFunction::EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E) {
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 @@ RValue CodeGenFunction::EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E) {
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 ce49cb20d3..5a4236a42c 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -613,7 +613,7 @@ Value *ScalarExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
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 9074e8179c..41ec2dd0f7 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -168,18 +168,18 @@ const llvm::Type *CodeGenTypes::ConvertReturnType(QualType T) {
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 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
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 6c958e65e8..536e881f8d 100644
--- a/lib/CodeGen/CodeGenTypes.h
+++ b/lib/CodeGen/CodeGenTypes.h
@@ -143,7 +143,7 @@ public:
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 9008884909..b328b2fbb3 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -46,9 +46,8 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCallRaw) {
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 8ef9486459..32d7a6086d 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -214,23 +214,18 @@ Action::ExprResult Sema::ActOnNumericConstant(const Token &Tok) {
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()) {