From dacf9dda17346c628fdd8c5df53c681738db0dc5 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Wed, 14 Jul 2010 23:39:36 +0000 Subject: [PATCH] CodeGen/ObjC/NeXT: Fix Obj-C message send to match llvm-gcc when choosing whether to use objc_msgSend_fpret; the choice is target dependent, not Obj-C ABI dependent. - arm objc _objc_msgSend_fpret bug git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108379 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/TargetInfo.h | 14 +++++++++++++ lib/Basic/TargetInfo.cpp | 3 +++ lib/Basic/Targets.cpp | 8 ++++++++ lib/CodeGen/CGBlocks.cpp | 2 +- lib/CodeGen/CGCall.cpp | 24 +++++++++++++++++++--- lib/CodeGen/CGObjCMac.cpp | 35 ++++++++------------------------ lib/CodeGen/CodeGenModule.h | 8 ++++++-- 7 files changed, 62 insertions(+), 32 deletions(-) diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 5763a12135..9f7debf9c5 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -61,6 +61,7 @@ protected: std::string CXXABI; unsigned HasAlignMac68kSupport : 1; + unsigned RealTypeUsesObjCFPRet : 3; // TargetInfo Constructor. Default initializes all fields. TargetInfo(const std::string &T); @@ -87,6 +88,13 @@ public: SignedLongLong, UnsignedLongLong }; + + enum RealType { + Float = 0, + Double, + LongDouble + }; + protected: IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType, WIntType, Char16Type, Char32Type, Int64Type, SigAtomicType; @@ -233,6 +241,12 @@ public: /// integer type enum. For example, SignedLong -> "L". static const char *getTypeConstantSuffix(IntType T); + /// \brief Check whether the given real type should use the "fpret" flavor of + /// Obj-C message passing on this target. + bool useObjCFPRetForRealType(RealType T) const { + return RealTypeUsesObjCFPRet & (1 << T); + } + ///===---- Other target property query methods --------------------------===// /// getTargetDefines - Appends the target-specific #define values for this diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index e4eaf63137..7fcf372a36 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/lib/Basic/TargetInfo.cpp @@ -55,6 +55,9 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) { "i64:64:64-f32:32:32-f64:64:64-n32"; UserLabelPrefix = "_"; HasAlignMac68kSupport = false; + + // Default to no types using fpret. + RealTypeUsesObjCFPRet = 0; } // Out of line virtual dtor for TargetInfo. diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 8d793163bc..fdf63e738b 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -1245,6 +1245,11 @@ public: PtrDiffType = SignedInt; IntPtrType = SignedInt; RegParmMax = 3; + + // Use fpret for all types. + RealTypeUsesObjCFPRet = ((1 << TargetInfo::Float) | + (1 << TargetInfo::Double) | + (1 << TargetInfo::LongDouble)); } virtual const char *getVAListDeclaration() const { return "typedef char* __builtin_va_list;"; @@ -1411,6 +1416,9 @@ public: DescriptionString = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-" "a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"; + + // Use fpret only for long double. + RealTypeUsesObjCFPRet = (1 << TargetInfo::LongDouble); } virtual const char *getVAListDeclaration() const { return "typedef struct __va_list_tag {" diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 0d05a62138..cb9e636221 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -253,7 +253,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { CodeGenTypes &Types = CGM.getTypes(); const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, Args, FunctionType::ExtInfo()); - if (CGM.ReturnTypeUsesSret(FnInfo)) + if (CGM.ReturnTypeUsesSRet(FnInfo)) flags |= BLOCK_USE_STRET; } const llvm::IntegerType *IntTy = cast( diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 1632cb3c22..3d1e143dca 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -564,10 +564,28 @@ static void CreateCoercedStore(llvm::Value *Src, /***/ -bool CodeGenModule::ReturnTypeUsesSret(const CGFunctionInfo &FI) { +bool CodeGenModule::ReturnTypeUsesSRet(const CGFunctionInfo &FI) { return FI.getReturnInfo().isIndirect(); } +bool CodeGenModule::ReturnTypeUsesFPRet(QualType ResultType) { + if (const BuiltinType *BT = ResultType->getAs()) { + switch (BT->getKind()) { + default: + return false; + case BuiltinType::Float: + return getContext().Target.useObjCFPRetForRealType(TargetInfo::Float); + case BuiltinType::Double: + return getContext().Target.useObjCFPRetForRealType(TargetInfo::Double); + case BuiltinType::LongDouble: + return getContext().Target.useObjCFPRetForRealType( + TargetInfo::LongDouble); + } + } + + return false; +} + const llvm::FunctionType *CodeGenTypes::GetFunctionType(GlobalDecl GD) { const CGFunctionInfo &FI = getFunctionInfo(GD); @@ -841,7 +859,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, llvm::Function::arg_iterator AI = Fn->arg_begin(); // Name the struct return argument. - if (CGM.ReturnTypeUsesSret(FI)) { + if (CGM.ReturnTypeUsesSRet(FI)) { AI->setName("agg.result"); ++AI; } @@ -1116,7 +1134,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // If the call returns a temporary with struct return, create a temporary // alloca to hold the result, unless one is given to us. - if (CGM.ReturnTypeUsesSret(CallInfo)) { + if (CGM.ReturnTypeUsesSRet(CallInfo)) { llvm::Value *Value = ReturnValue.getValue(); if (!Value) Value = CreateMemTemp(RetTy); diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 2992867cbc..01ead9efe8 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -1650,29 +1650,17 @@ CGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF, "Result type mismatch!"); llvm::Constant *Fn = NULL; - if (CGM.ReturnTypeUsesSret(FnInfo)) { + if (CGM.ReturnTypeUsesSRet(FnInfo)) { Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper) : ObjCTypes.getSendStretFn(IsSuper); - } else if (ResultType->isRealFloatingType()) { - if (ObjCABI == 2) { - if (const BuiltinType *BT = ResultType->getAs()) { - BuiltinType::Kind k = BT->getKind(); - Fn = (k == BuiltinType::LongDouble) ? ObjCTypes.getSendFpretFn2(IsSuper) - : ObjCTypes.getSendFn2(IsSuper); - } else { - Fn = ObjCTypes.getSendFn2(IsSuper); - } - } else - // FIXME. This currently matches gcc's API for x86-32. May need to change - // for others if we have their API. - Fn = ObjCTypes.getSendFpretFn(IsSuper); + } else if (CGM.ReturnTypeUsesFPRet(ResultType)) { + Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper) + : ObjCTypes.getSendFpretFn(IsSuper); } else { Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper) : ObjCTypes.getSendFn(IsSuper); } - assert(Fn && "EmitLegacyMessageSend - unknown API"); - Fn = llvm::ConstantExpr::getBitCast(Fn, - llvm::PointerType::getUnqual(FTy)); + Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy)); return CGF.EmitCall(FnInfo, Fn, Return, ActualArgs); } @@ -5295,7 +5283,7 @@ CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend( FunctionType::ExtInfo()); llvm::Constant *Fn = 0; std::string Name("\01l_"); - if (CGM.ReturnTypeUsesSret(FnInfo)) { + if (CGM.ReturnTypeUsesSRet(FnInfo)) { #if 0 // unlike what is documented. gcc never generates this API!! if (Receiver->getType() == ObjCTypes.ObjectPtrTy) { @@ -5312,14 +5300,9 @@ CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend( Fn = ObjCTypes.getMessageSendStretFixupFn(); Name += "objc_msgSend_stret_fixup"; } - } else if (!IsSuper && ResultType->isRealFloatingType()) { - if (ResultType->isSpecificBuiltinType(BuiltinType::LongDouble)) { - Fn = ObjCTypes.getMessageSendFpretFixupFn(); - Name += "objc_msgSend_fpret_fixup"; - } else { - Fn = ObjCTypes.getMessageSendFixupFn(); - Name += "objc_msgSend_fixup"; - } + } else if (!IsSuper && CGM.ReturnTypeUsesFPRet(ResultType)) { + Fn = ObjCTypes.getMessageSendFpretFixupFn(); + Name += "objc_msgSend_fpret_fixup"; } else { #if 0 // unlike what is documented. gcc never generates this API!! diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index a1ea0ec667..27f15fc018 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -444,9 +444,13 @@ public: /// which only apply to a function definintion. void SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F); - /// ReturnTypeUsesSret - Return true iff the given type uses 'sret' when used + /// ReturnTypeUsesSRet - Return true iff the given type uses 'sret' when used /// as a return type. - bool ReturnTypeUsesSret(const CGFunctionInfo &FI); + bool ReturnTypeUsesSRet(const CGFunctionInfo &FI); + + /// ReturnTypeUsesSret - Return true iff the given type uses 'fpret' when used + /// as a return type. + bool ReturnTypeUsesFPRet(QualType ResultType); /// ConstructAttributeList - Get the LLVM attributes and calling convention to /// use for a particular function type. -- 2.40.0