diff options
author | Chris Lattner <sabre@nondot.org> | 2008-06-30 18:32:54 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-06-30 18:32:54 +0000 |
commit | b7cfe88e88cb4f46308de89cf3f0c81bfe624128 (patch) | |
tree | f167ab0cf639ac9c700baf35135bc4f69b797152 | |
parent | 3301cb103d5f32056d62f13bde036988f7cf1330 (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.h | 8 | ||||
-rw-r--r-- | include/clang/AST/Builtins.def | 5 | ||||
-rw-r--r-- | include/clang/Basic/TargetInfo.h | 8 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 14 | ||||
-rw-r--r-- | lib/CodeGen/CGBuiltin.cpp | 167 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenTypes.cpp | 18 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenTypes.h | 2 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 19 |
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()) { |