The tests only failed with module enabled. FWIW, I think the change in ASTImporter (https://reviews.llvm.org/rL327206#change-1q8vFFjJ6Cqk) needs additional changes to make imports work for RecordDecl.
On Mon, Mar 12, 2018 at 3:56 PM Eric Liu <ioe...@google.com> wrote: > Hi Akira, > > It seems that this commit also changes behavior for compiling C++ code as > we are seeing test failures caused by this change in our internal tests. > > I'm still trying to reduce a reproducer for the failure. In the meantime, > could you please double check if this affects C++? > > Thanks, > Eric > > On Sat, Mar 10, 2018 at 7:38 AM Akira Hatanaka via cfe-commits < > cfe-commits@lists.llvm.org> wrote: > >> Author: ahatanak >> Date: Fri Mar 9 22:36:08 2018 >> New Revision: 327206 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=327206&view=rev >> Log: >> [ObjC] Allow declaring __weak pointer fields in C structs in ARC. >> >> This patch uses the infrastructure added in r326307 for enabling >> non-trivial fields to be declared in C structs to allow __weak fields in >> C structs in ARC. >> >> rdar://problem/33599681 >> >> Differential Revision: https://reviews.llvm.org/D44095 >> >> Added: >> cfe/trunk/test/CodeGenObjC/weak-in-c-struct.m >> Modified: >> cfe/trunk/include/clang/AST/Decl.h >> cfe/trunk/include/clang/AST/DeclCXX.h >> cfe/trunk/include/clang/AST/Type.h >> cfe/trunk/lib/AST/ASTImporter.cpp >> cfe/trunk/lib/AST/Decl.cpp >> cfe/trunk/lib/AST/DeclCXX.cpp >> cfe/trunk/lib/AST/Type.cpp >> cfe/trunk/lib/CodeGen/CGBlocks.cpp >> cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp >> cfe/trunk/lib/CodeGen/CGObjC.cpp >> cfe/trunk/lib/CodeGen/CodeGenFunction.h >> cfe/trunk/lib/CodeGen/TargetInfo.cpp >> cfe/trunk/lib/Sema/SemaDecl.cpp >> cfe/trunk/lib/Serialization/ASTReaderDecl.cpp >> cfe/trunk/lib/Serialization/ASTWriter.cpp >> cfe/trunk/lib/Serialization/ASTWriterDecl.cpp >> cfe/trunk/test/CodeGenObjC/nontrivial-c-struct-exception.m >> >> Modified: cfe/trunk/include/clang/AST/Decl.h >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=327206&r1=327205&r2=327206&view=diff >> >> ============================================================================== >> --- cfe/trunk/include/clang/AST/Decl.h (original) >> +++ cfe/trunk/include/clang/AST/Decl.h Fri Mar 9 22:36:08 2018 >> @@ -3553,6 +3553,12 @@ class RecordDecl : public TagDecl { >> bool NonTrivialToPrimitiveCopy : 1; >> bool NonTrivialToPrimitiveDestroy : 1; >> >> + /// True if this class can be passed in a non-address-preserving >> fashion >> + /// (such as in registers). >> + /// This does not imply anything about how the ABI in use will actually >> + /// pass an object of this class. >> + bool CanPassInRegisters : 1; >> + >> protected: >> RecordDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC, >> SourceLocation StartLoc, SourceLocation IdLoc, >> @@ -3636,6 +3642,18 @@ public: >> NonTrivialToPrimitiveDestroy = true; >> } >> >> + /// Determine whether this class can be passed in registers. In C++ >> mode, >> + /// it must have at least one trivial, non-deleted copy or move >> constructor. >> + /// FIXME: This should be set as part of completeDefinition. >> + bool canPassInRegisters() const { >> + return CanPassInRegisters; >> + } >> + >> + /// Set that we can pass this RecordDecl in registers. >> + void setCanPassInRegisters(bool CanPass) { >> + CanPassInRegisters = CanPass; >> + } >> + >> /// \brief Determines whether this declaration represents the >> /// injected class name. >> /// >> >> Modified: cfe/trunk/include/clang/AST/DeclCXX.h >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=327206&r1=327205&r2=327206&view=diff >> >> ============================================================================== >> --- cfe/trunk/include/clang/AST/DeclCXX.h (original) >> +++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Mar 9 22:36:08 2018 >> @@ -467,12 +467,6 @@ class CXXRecordDecl : public RecordDecl >> /// constructor. >> unsigned HasDefaultedDefaultConstructor : 1; >> >> - /// \brief True if this class can be passed in a >> non-address-preserving >> - /// fashion (such as in registers) according to the C++ language >> rules. >> - /// This does not imply anything about how the ABI in use will >> actually >> - /// pass an object of this class. >> - unsigned CanPassInRegisters : 1; >> - >> /// \brief True if a defaulted default constructor for this class >> would >> /// be constexpr. >> unsigned DefaultedDefaultConstructorIsConstexpr : 1; >> @@ -1474,18 +1468,6 @@ public: >> return data().HasIrrelevantDestructor; >> } >> >> - /// \brief Determine whether this class has at least one trivial, >> non-deleted >> - /// copy or move constructor. >> - bool canPassInRegisters() const { >> - return data().CanPassInRegisters; >> - } >> - >> - /// \brief Set that we can pass this RecordDecl in registers. >> - // FIXME: This should be set as part of completeDefinition. >> - void setCanPassInRegisters(bool CanPass) { >> - data().CanPassInRegisters = CanPass; >> - } >> - >> /// Determine whether the triviality for the purpose of calls for this >> class >> /// is overridden to be trivial because this class or the type of one >> of its >> /// subobjects has attribute "trivial_abi". >> >> Modified: cfe/trunk/include/clang/AST/Type.h >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=327206&r1=327205&r2=327206&view=diff >> >> ============================================================================== >> --- cfe/trunk/include/clang/AST/Type.h (original) >> +++ cfe/trunk/include/clang/AST/Type.h Fri Mar 9 22:36:08 2018 >> @@ -1097,6 +1097,10 @@ public: >> /// with the ARC __strong qualifier. >> PDIK_ARCStrong, >> >> + /// The type is an Objective-C retainable pointer type that is >> qualified >> + /// with the ARC __weak qualifier. >> + PDIK_ARCWeak, >> + >> /// The type is a struct containing a field whose type is not >> PCK_Trivial. >> PDIK_Struct >> }; >> @@ -1124,6 +1128,10 @@ public: >> /// with the ARC __strong qualifier. >> PCK_ARCStrong, >> >> + /// The type is an Objective-C retainable pointer type that is >> qualified >> + /// with the ARC __weak qualifier. >> + PCK_ARCWeak, >> + >> /// The type is a struct containing a field whose type is neither >> /// PCK_Trivial nor PCK_VolatileTrivial. >> /// Note that a C++ struct type does not necessarily match this; C++ >> copying >> @@ -1146,6 +1154,8 @@ public: >> /// source object is placed in an uninitialized state. >> PrimitiveCopyKind isNonTrivialToPrimitiveDestructiveMove() const; >> >> + bool canPassInRegisters() const; >> + >> enum DestructionKind { >> DK_none, >> DK_cxx_destructor, >> >> Modified: cfe/trunk/lib/AST/ASTImporter.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=327206&r1=327205&r2=327206&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/AST/ASTImporter.cpp (original) >> +++ cfe/trunk/lib/AST/ASTImporter.cpp Fri Mar 9 22:36:08 2018 >> @@ -1105,7 +1105,6 @@ bool ASTNodeImporter::ImportDefinition(R >> = FromData.HasConstexprNonCopyMoveConstructor; >> ToData.HasDefaultedDefaultConstructor >> = FromData.HasDefaultedDefaultConstructor; >> - ToData.CanPassInRegisters = FromData.CanPassInRegisters; >> ToData.DefaultedDefaultConstructorIsConstexpr >> = FromData.DefaultedDefaultConstructorIsConstexpr; >> ToData.HasConstexprDefaultConstructor >> >> Modified: cfe/trunk/lib/AST/Decl.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=327206&r1=327205&r2=327206&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/AST/Decl.cpp (original) >> +++ cfe/trunk/lib/AST/Decl.cpp Fri Mar 9 22:36:08 2018 >> @@ -3931,7 +3931,8 @@ RecordDecl::RecordDecl(Kind DK, TagKind >> HasObjectMember(false), HasVolatileMember(false), >> LoadedFieldsFromExternalStorage(false), >> NonTrivialToPrimitiveDefaultInitialize(false), >> - NonTrivialToPrimitiveCopy(false), >> NonTrivialToPrimitiveDestroy(false) { >> + NonTrivialToPrimitiveCopy(false), >> NonTrivialToPrimitiveDestroy(false), >> + CanPassInRegisters(true) { >> assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!"); >> } >> >> >> Modified: cfe/trunk/lib/AST/DeclCXX.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=327206&r1=327205&r2=327206&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/AST/DeclCXX.cpp (original) >> +++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Mar 9 22:36:08 2018 >> @@ -93,7 +93,6 @@ CXXRecordDecl::DefinitionData::Definitio >> DeclaredNonTrivialSpecialMembersForCall(0), >> HasIrrelevantDestructor(true), >> HasConstexprNonCopyMoveConstructor(false), >> HasDefaultedDefaultConstructor(false), >> - CanPassInRegisters(true), >> DefaultedDefaultConstructorIsConstexpr(true), >> HasConstexprDefaultConstructor(false), >> HasNonLiteralTypeFieldsOrBases(false), >> ComputedVisibleConversions(false), >> >> Modified: cfe/trunk/lib/AST/Type.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=327206&r1=327205&r2=327206&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/AST/Type.cpp (original) >> +++ cfe/trunk/lib/AST/Type.cpp Fri Mar 9 22:36:08 2018 >> @@ -2214,11 +2214,14 @@ QualType::isNonTrivialToPrimitiveDefault >> if (RT->getDecl()->isNonTrivialToPrimitiveDefaultInitialize()) >> return PDIK_Struct; >> >> - Qualifiers::ObjCLifetime Lifetime = getQualifiers().getObjCLifetime(); >> - if (Lifetime == Qualifiers::OCL_Strong) >> + switch (getQualifiers().getObjCLifetime()) { >> + case Qualifiers::OCL_Strong: >> return PDIK_ARCStrong; >> - >> - return PDIK_Trivial; >> + case Qualifiers::OCL_Weak: >> + return PDIK_ARCWeak; >> + default: >> + return PDIK_Trivial; >> + } >> } >> >> QualType::PrimitiveCopyKind QualType::isNonTrivialToPrimitiveCopy() >> const { >> @@ -2228,10 +2231,14 @@ QualType::PrimitiveCopyKind QualType::is >> return PCK_Struct; >> >> Qualifiers Qs = getQualifiers(); >> - if (Qs.getObjCLifetime() == Qualifiers::OCL_Strong) >> + switch (Qs.getObjCLifetime()) { >> + case Qualifiers::OCL_Strong: >> return PCK_ARCStrong; >> - >> - return Qs.hasVolatile() ? PCK_VolatileTrivial : PCK_Trivial; >> + case Qualifiers::OCL_Weak: >> + return PCK_ARCWeak; >> + default: >> + return Qs.hasVolatile() ? PCK_VolatileTrivial : PCK_Trivial; >> + } >> } >> >> QualType::PrimitiveCopyKind >> @@ -2239,6 +2246,17 @@ QualType::isNonTrivialToPrimitiveDestruc >> return isNonTrivialToPrimitiveCopy(); >> } >> >> +bool QualType::canPassInRegisters() const { >> + if (const auto *RT = >> + getTypePtr()->getBaseElementTypeUnsafe()->getAs<RecordType>()) >> + return RT->getDecl()->canPassInRegisters(); >> + >> + if (getQualifiers().getObjCLifetime() == Qualifiers::OCL_Weak) >> + return false; >> + >> + return true; >> +} >> + >> bool Type::isLiteralType(const ASTContext &Ctx) const { >> if (isDependentType()) >> return false; >> >> Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=327206&r1=327205&r2=327206&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original) >> +++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Fri Mar 9 22:36:08 2018 >> @@ -1525,6 +1525,9 @@ computeCopyInfoForBlockCapture(const Blo >> case QualType::PCK_Struct: >> return std::make_pair(BlockCaptureEntityKind::NonTrivialCStruct, >> BlockFieldFlags()); >> + case QualType::PCK_ARCWeak: >> + // We need to register __weak direct captures with the runtime. >> + return std::make_pair(BlockCaptureEntityKind::ARCWeak, Flags); >> case QualType::PCK_ARCStrong: >> // We need to retain the copied value for __strong direct captures. >> // If it's a block pointer, we have to copy the block and assign >> that to >> @@ -1542,10 +1545,6 @@ computeCopyInfoForBlockCapture(const Blo >> // Special rules for ARC captures: >> Qualifiers QS = T.getQualifiers(); >> >> - // We need to register __weak direct captures with the runtime. >> - if (QS.getObjCLifetime() == Qualifiers::OCL_Weak) >> - return std::make_pair(BlockCaptureEntityKind::ARCWeak, Flags); >> - >> // Non-ARC captures of retainable pointers are strong and >> // therefore require a call to _Block_object_assign. >> if (!QS.getObjCLifetime() && !LangOpts.ObjCAutoRefCount) >> >> Modified: cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp?rev=327206&r1=327205&r2=327206&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp (original) >> +++ cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp Fri Mar 9 22:36:08 2018 >> @@ -77,6 +77,8 @@ struct DefaultInitializedTypeVisitor { >> switch (PDIK) { >> case QualType::PDIK_ARCStrong: >> return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...); >> + case QualType::PDIK_ARCWeak: >> + return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...); >> case QualType::PDIK_Struct: >> return asDerived().visitStruct(FT, std::forward<Ts>(Args)...); >> case QualType::PDIK_Trivial: >> @@ -108,6 +110,8 @@ struct CopiedTypeVisitor { >> switch (PCK) { >> case QualType::PCK_ARCStrong: >> return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...); >> + case QualType::PCK_ARCWeak: >> + return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...); >> case QualType::PCK_Struct: >> return asDerived().visitStruct(FT, std::forward<Ts>(Args)...); >> case QualType::PCK_Trivial: >> @@ -141,11 +145,6 @@ template <class Derived> struct StructVi >> >> template <class... Ts> void visitTrivial(Ts... Args) {} >> >> - template <class... Ts> void visitARCWeak(Ts... Args) { >> - // FIXME: remove this when visitARCWeak is implemented in the >> subclasses. >> - llvm_unreachable("weak field is not expected"); >> - } >> - >> template <class... Ts> void visitCXXDestructor(Ts... Args) { >> llvm_unreachable("field of a C++ struct type is not expected"); >> } >> @@ -245,6 +244,13 @@ template <class Derived> struct GenFuncN >> appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), >> FieldOffset)); >> } >> >> + void visitARCWeak(QualType FT, const FieldDecl *FD, >> + CharUnits CurStructOffset) { >> + appendStr("_w"); >> + CharUnits FieldOffset = CurStructOffset + >> asDerived().getFieldOffset(FD); >> + appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), >> FieldOffset)); >> + } >> + >> void visitStruct(QualType QT, const FieldDecl *FD, >> CharUnits CurStructOffset) { >> CharUnits FieldOffset = CurStructOffset + >> asDerived().getFieldOffset(FD); >> @@ -615,6 +621,12 @@ struct GenDestructor : StructVisitor<Gen >> *CGF, getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT); >> } >> >> + void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits >> CurStackOffset, >> + std::array<Address, 1> Addrs) { >> + CGF->destroyARCWeak( >> + *CGF, getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT); >> + } >> + >> void callSpecialFunction(QualType FT, CharUnits Offset, >> std::array<Address, 1> Addrs) { >> CGF->callCStructDestructor( >> @@ -636,6 +648,12 @@ struct GenDefaultInitialize >> getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT); >> } >> >> + void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits >> CurStackOffset, >> + std::array<Address, 1> Addrs) { >> + CGF->EmitNullInitialization( >> + getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT); >> + } >> + >> template <class FieldKind, size_t... Is> >> void visitArray(FieldKind FK, QualType QT, const FieldDecl *FD, >> CharUnits CurStackOffset, std::array<Address, 1> >> Addrs) { >> @@ -678,6 +696,14 @@ struct GenCopyConstructor : GenBinaryFun >> llvm::Value *Val = CGF->EmitARCRetain(QT, SrcVal); >> CGF->EmitStoreOfScalar(Val, CGF->MakeAddrLValue(Addrs[DstIdx], QT), >> true); >> } >> + >> + void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits >> CurStackOffset, >> + std::array<Address, 2> Addrs) { >> + Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD); >> + Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD); >> + CGF->EmitARCCopyWeak(Addrs[DstIdx], Addrs[SrcIdx]); >> + } >> + >> void callSpecialFunction(QualType FT, CharUnits Offset, >> std::array<Address, 2> Addrs) { >> CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], >> FT), >> @@ -700,6 +726,14 @@ struct GenMoveConstructor : GenBinaryFun >> CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], >> QT), >> /* isInitialization */ true); >> } >> + >> + void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits >> CurStackOffset, >> + std::array<Address, 2> Addrs) { >> + Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD); >> + Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD); >> + CGF->EmitARCMoveWeak(Addrs[DstIdx], Addrs[SrcIdx]); >> + } >> + >> void callSpecialFunction(QualType FT, CharUnits Offset, >> std::array<Address, 2> Addrs) { >> CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], >> FT), >> @@ -720,6 +754,14 @@ struct GenCopyAssignment : GenBinaryFunc >> CGF->EmitARCStoreStrong(CGF->MakeAddrLValue(Addrs[DstIdx], QT), >> SrcVal, >> false); >> } >> + >> + void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits >> CurStackOffset, >> + std::array<Address, 2> Addrs) { >> + Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD); >> + Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD); >> + CGF->emitARCCopyAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]); >> + } >> + >> void callSpecialFunction(QualType FT, CharUnits Offset, >> std::array<Address, 2> Addrs) { >> CGF->callCStructCopyAssignmentOperator( >> @@ -747,6 +789,13 @@ struct GenMoveAssignment : GenBinaryFunc >> CGF->EmitARCRelease(DstVal, ARCImpreciseLifetime); >> } >> >> + void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits >> CurStackOffset, >> + std::array<Address, 2> Addrs) { >> + Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD); >> + Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD); >> + CGF->emitARCMoveAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]); >> + } >> + >> void callSpecialFunction(QualType FT, CharUnits Offset, >> std::array<Address, 2> Addrs) { >> CGF->callCStructMoveAssignmentOperator( >> >> Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=327206&r1=327205&r2=327206&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/CodeGen/CGObjC.cpp (original) >> +++ cfe/trunk/lib/CodeGen/CGObjC.cpp Fri Mar 9 22:36:08 2018 >> @@ -2307,6 +2307,21 @@ void CodeGenFunction::EmitARCCopyWeak(Ad >> "objc_copyWeak"); >> } >> >> +void CodeGenFunction::emitARCCopyAssignWeak(QualType Ty, Address DstAddr, >> + Address SrcAddr) { >> + llvm::Value *Object = EmitARCLoadWeakRetained(SrcAddr); >> + Object = EmitObjCConsumeObject(Ty, Object); >> + EmitARCStoreWeak(DstAddr, Object, false); >> +} >> + >> +void CodeGenFunction::emitARCMoveAssignWeak(QualType Ty, Address DstAddr, >> + Address SrcAddr) { >> + llvm::Value *Object = EmitARCLoadWeakRetained(SrcAddr); >> + Object = EmitObjCConsumeObject(Ty, Object); >> + EmitARCStoreWeak(DstAddr, Object, false); >> + EmitARCDestroyWeak(SrcAddr); >> +} >> + >> /// Produce the code to do a objc_autoreleasepool_push. >> /// call i8* \@objc_autoreleasePoolPush(void) >> llvm::Value *CodeGenFunction::EmitObjCAutoreleasePoolPush() { >> >> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=327206&r1=327205&r2=327206&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original) >> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Fri Mar 9 22:36:08 2018 >> @@ -3548,6 +3548,8 @@ public: >> llvm::Value *EmitARCLoadWeak(Address addr); >> llvm::Value *EmitARCLoadWeakRetained(Address addr); >> llvm::Value *EmitARCStoreWeak(Address addr, llvm::Value *value, bool >> ignored); >> + void emitARCCopyAssignWeak(QualType Ty, Address DstAddr, Address >> SrcAddr); >> + void emitARCMoveAssignWeak(QualType Ty, Address DstAddr, Address >> SrcAddr); >> void EmitARCCopyWeak(Address dst, Address src); >> void EmitARCMoveWeak(Address dst, Address src); >> llvm::Value *EmitARCRetainAutorelease(QualType type, llvm::Value >> *value); >> >> Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=327206&r1=327205&r2=327206&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original) >> +++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Fri Mar 9 22:36:08 2018 >> @@ -140,8 +140,11 @@ bool SwiftABIInfo::isLegalVectorTypeForS >> static CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT, >> CGCXXABI &CXXABI) { >> const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); >> - if (!RD) >> + if (!RD) { >> + if (!RT->getDecl()->canPassInRegisters()) >> + return CGCXXABI::RAA_Indirect; >> return CGCXXABI::RAA_Default; >> + } >> return CXXABI.getRecordArgABI(RD); >> } >> >> @@ -153,6 +156,20 @@ static CGCXXABI::RecordArgABI getRecordA >> return getRecordArgABI(RT, CXXABI); >> } >> >> +static bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo >> &FI, >> + const ABIInfo &Info) { >> + QualType Ty = FI.getReturnType(); >> + >> + if (const auto *RT = Ty->getAs<RecordType>()) >> + if (!isa<CXXRecordDecl>(RT->getDecl()) && >> + !RT->getDecl()->canPassInRegisters()) { >> + FI.getReturnInfo() = Info.getNaturalAlignIndirect(Ty); >> + return true; >> + } >> + >> + return CXXABI.classifyReturnType(FI); >> +} >> + >> /// Pass transparent unions as if they were the type of the first >> element. Sema >> /// should ensure that all elements of the union have the same "machine >> type". >> static QualType useFirstFieldIfTransparentUnion(QualType Ty) { >> @@ -1749,7 +1766,7 @@ void X86_32ABIInfo::computeInfo(CGFuncti >> } else >> State.FreeRegs = DefaultNumRegisterParameters; >> >> - if (!getCXXABI().classifyReturnType(FI)) { >> + if (!::classifyReturnType(getCXXABI(), FI, *this)) { >> FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), State); >> } else if (FI.getReturnInfo().isIndirect()) { >> // The C++ ABI is not aware of register usage, so we have to check >> if the >> @@ -3545,7 +3562,7 @@ void X86_64ABIInfo::computeInfo(CGFuncti >> unsigned FreeSSERegs = IsRegCall ? 16 : 8; >> unsigned NeededInt, NeededSSE; >> >> - if (!getCXXABI().classifyReturnType(FI)) { >> + if (!::classifyReturnType(getCXXABI(), FI, *this)) { >> if (IsRegCall && FI.getReturnType()->getTypePtr()->isRecordType() && >> !FI.getReturnType()->getTypePtr()->isUnionType()) { >> FI.getReturnInfo() = >> @@ -4895,7 +4912,7 @@ private: >> bool isIllegalVectorType(QualType Ty) const; >> >> void computeInfo(CGFunctionInfo &FI) const override { >> - if (!getCXXABI().classifyReturnType(FI)) >> + if (!::classifyReturnType(getCXXABI(), FI, *this)) >> FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); >> >> for (auto &it : FI.arguments()) >> @@ -5626,7 +5643,7 @@ void WindowsARMTargetCodeGenInfo::setTar >> } >> >> void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const { >> - if (!getCXXABI().classifyReturnType(FI)) >> + if (!::classifyReturnType(getCXXABI(), FI, *this)) >> FI.getReturnInfo() = >> classifyReturnType(FI.getReturnType(), FI.isVariadic()); >> >> >> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=327206&r1=327205&r2=327206&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) >> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Mar 9 22:36:08 2018 >> @@ -15260,7 +15260,6 @@ void Sema::ActOnFields(Scope *S, SourceL >> >> // Get the type for the field. >> const Type *FDTy = FD->getType().getTypePtr(); >> - Qualifiers QS = FD->getType().getQualifiers(); >> >> if (!FD->isAnonymousStructOrUnion()) { >> // Remember all fields written by the user. >> @@ -15401,10 +15400,7 @@ void Sema::ActOnFields(Scope *S, SourceL >> QualType T = Context.getObjCObjectPointerType(FD->getType()); >> FD->setType(T); >> } else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && >> - Record && !ObjCFieldLifetimeErrReported && >> - ((!getLangOpts().CPlusPlus && >> - QS.getObjCLifetime() == Qualifiers::OCL_Weak) || >> - Record->isUnion())) { >> + Record && !ObjCFieldLifetimeErrReported && >> Record->isUnion()) { >> // It's an error in ARC or Weak if a field has lifetime. >> // We don't want to report this in a system header, though, >> // so we just make the field unavailable. >> @@ -15450,6 +15446,8 @@ void Sema::ActOnFields(Scope *S, SourceL >> Record->setNonTrivialToPrimitiveCopy(); >> if (FT.isDestructedType()) >> Record->setNonTrivialToPrimitiveDestroy(); >> + if (!FT.canPassInRegisters()) >> + Record->setCanPassInRegisters(false); >> } >> >> if (Record && FD->getType().isVolatileQualified()) >> >> Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=327206&r1=327205&r2=327206&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) >> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Mar 9 22:36:08 2018 >> @@ -739,6 +739,7 @@ ASTDeclReader::VisitRecordDeclImpl(Recor >> RD->setAnonymousStructOrUnion(Record.readInt()); >> RD->setHasObjectMember(Record.readInt()); >> RD->setHasVolatileMember(Record.readInt()); >> + RD->setCanPassInRegisters(Record.readInt()); >> return Redecl; >> } >> >> @@ -1584,7 +1585,6 @@ void ASTDeclReader::ReadCXXDefinitionDat >> Data.HasIrrelevantDestructor = Record.readInt(); >> Data.HasConstexprNonCopyMoveConstructor = Record.readInt(); >> Data.HasDefaultedDefaultConstructor = Record.readInt(); >> - Data.CanPassInRegisters = Record.readInt(); >> Data.DefaultedDefaultConstructorIsConstexpr = Record.readInt(); >> Data.HasConstexprDefaultConstructor = Record.readInt(); >> Data.HasNonLiteralTypeFieldsOrBases = Record.readInt(); >> @@ -1724,7 +1724,6 @@ void ASTDeclReader::MergeDefinitionData( >> MATCH_FIELD(HasIrrelevantDestructor) >> OR_FIELD(HasConstexprNonCopyMoveConstructor) >> OR_FIELD(HasDefaultedDefaultConstructor) >> - MATCH_FIELD(CanPassInRegisters) >> MATCH_FIELD(DefaultedDefaultConstructorIsConstexpr) >> OR_FIELD(HasConstexprDefaultConstructor) >> MATCH_FIELD(HasNonLiteralTypeFieldsOrBases) >> >> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=327206&r1=327205&r2=327206&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original) >> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Fri Mar 9 22:36:08 2018 >> @@ -6018,7 +6018,6 @@ void ASTRecordWriter::AddCXXDefinitionDa >> Record->push_back(Data.HasIrrelevantDestructor); >> Record->push_back(Data.HasConstexprNonCopyMoveConstructor); >> Record->push_back(Data.HasDefaultedDefaultConstructor); >> - Record->push_back(Data.CanPassInRegisters); >> Record->push_back(Data.DefaultedDefaultConstructorIsConstexpr); >> Record->push_back(Data.HasConstexprDefaultConstructor); >> Record->push_back(Data.HasNonLiteralTypeFieldsOrBases); >> >> Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=327206&r1=327205&r2=327206&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original) >> +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Fri Mar 9 22:36:08 2018 >> @@ -465,6 +465,7 @@ void ASTDeclWriter::VisitRecordDecl(Reco >> Record.push_back(D->isAnonymousStructOrUnion()); >> Record.push_back(D->hasObjectMember()); >> Record.push_back(D->hasVolatileMember()); >> + Record.push_back(D->canPassInRegisters()); >> >> if (D->getDeclContext() == D->getLexicalDeclContext() && >> !D->hasAttrs() && >> @@ -1899,6 +1900,7 @@ void ASTWriter::WriteDeclAbbrevs() { >> Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // >> AnonymousStructUnion >> Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // >> hasObjectMember >> Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // >> hasVolatileMember >> + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // >> canPassInRegisters >> // DC >> Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalOffset >> Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // VisibleOffset >> >> Modified: cfe/trunk/test/CodeGenObjC/nontrivial-c-struct-exception.m >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/nontrivial-c-struct-exception.m?rev=327206&r1=327205&r2=327206&view=diff >> >> ============================================================================== >> --- cfe/trunk/test/CodeGenObjC/nontrivial-c-struct-exception.m (original) >> +++ cfe/trunk/test/CodeGenObjC/nontrivial-c-struct-exception.m Fri Mar 9 >> 22:36:08 2018 >> @@ -1,12 +1,18 @@ >> -// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks >> -fobjc-runtime=ios-11.0 -fobjc-exceptions -fexceptions >> -fobjc-arc-exceptions -emit-llvm -o - %s | FileCheck %s >> +// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks >> -fobjc-runtime=ios-11.0 -fobjc-exceptions -fexceptions -emit-llvm -o - %s | >> FileCheck %s >> >> // CHECK: %[[STRUCT_STRONG:.*]] = type { i32, i8* } >> +// CHECK: %[[STRUCT_WEAK:.*]] = type { i32, i8* } >> >> typedef struct { >> int i; >> id f1; >> } Strong; >> >> +typedef struct { >> + int i; >> + __weak id f1; >> +} Weak; >> + >> // CHECK: define void @testStrongException() >> // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONG]], align 8 >> // CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_STRONG]], align 8 >> @@ -31,3 +37,26 @@ void calleeStrong(Strong, Strong); >> void testStrongException(void) { >> calleeStrong(genStrong(), genStrong()); >> } >> + >> +// CHECK: define void @testWeakException() >> +// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_WEAK]], align 8 >> +// CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_WEAK]], align 8 >> +// CHECK: call void @genWeak(%[[STRUCT_WEAK]]* sret %[[AGG_TMP]]) >> +// CHECK: invoke void @genWeak(%[[STRUCT_WEAK]]* sret %[[AGG_TMP1]]) >> + >> +// CHECK: call void @calleeWeak(%[[STRUCT_WEAK]]* %[[AGG_TMP]], >> %[[STRUCT_WEAK]]* %[[AGG_TMP1]]) >> +// CHECK: ret void >> + >> +// CHECK: landingpad { i8*, i32 } >> +// CHECK: %[[V3:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_TMP]] to i8** >> +// CHECK: call void @__destructor_8_w8(i8** %[[V3]]) >> +// CHECK: br label >> + >> +// CHECK: resume >> + >> +Weak genWeak(void); >> +void calleeWeak(Weak, Weak); >> + >> +void testWeakException(void) { >> + calleeWeak(genWeak(), genWeak()); >> +} >> >> Added: cfe/trunk/test/CodeGenObjC/weak-in-c-struct.m >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/weak-in-c-struct.m?rev=327206&view=auto >> >> ============================================================================== >> --- cfe/trunk/test/CodeGenObjC/weak-in-c-struct.m (added) >> +++ cfe/trunk/test/CodeGenObjC/weak-in-c-struct.m Fri Mar 9 22:36:08 2018 >> @@ -0,0 +1,193 @@ >> +// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks >> -fobjc-runtime=ios-11.0 -emit-llvm -o - %s | FileCheck -check-prefix=ARM64 >> -check-prefix=COMMON %s >> +// RUN: %clang_cc1 -triple thumbv7-apple-ios10 -fobjc-arc -fblocks >> -fobjc-runtime=ios-10.0 -emit-llvm -o - %s | FileCheck -check-prefix=COMMON >> %s >> +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13 -fobjc-arc -fblocks >> -fobjc-runtime=macosx-10.13.0 -emit-llvm -o - %s | FileCheck >> -check-prefix=COMMON %s >> +// RUN: %clang_cc1 -triple i386-apple-macosx10.13.0 -fobjc-arc -fblocks >> -fobjc-runtime=macosx-fragile-10.13.0 -emit-llvm -o - %s | FileCheck >> -check-prefix=COMMON %s >> + >> +typedef void (^BlockTy)(void); >> + >> +// COMMON: %[[STRUCT_WEAK:.*]] = type { i32, i8* } >> + >> +typedef struct { >> + int f0; >> + __weak id f1; >> +} Weak; >> + >> +Weak getWeak(void); >> +void calleeWeak(Weak); >> + >> +// ARM64: define void @test_constructor_destructor_Weak() >> +// ARM64: %[[T:.*]] = alloca %[[STRUCT_WEAK]], align 8 >> +// ARM64: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[T]] to i8** >> +// ARM64: call void @__default_constructor_8_w8(i8** %[[V0]]) >> +// ARM64: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[T]] to i8** >> +// ARM64: call void @__destructor_8_w8(i8** %[[V1]]) >> +// ARM64: ret void >> + >> +// ARM64: define linkonce_odr hidden void >> @__default_constructor_8_w8(i8** %[[DST:.*]]) >> +// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8 >> +// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 >> +// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 >> +// ARM64: %[[V1]] = bitcast i8** %[[V0]] to i8* >> +// ARM64: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 8 >> +// ARM64: %[[V3:.*]] = bitcast i8* %[[V2]] to i8** >> +// ARM64: %[[V4:.*]] = bitcast i8** %[[V3]] to i8* >> +// ARM64: call void @llvm.memset.p0i8.i64(i8* align 8 %[[V4]], i8 0, i64 >> 8, i1 false) >> + >> +// ARM64: define linkonce_odr hidden void @__destructor_8_w8(i8** >> %[[DST:.*]]) >> +// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8 >> +// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 >> +// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 >> +// ARM64: %[[V1:.*]] = bitcast i8** %[[V0]] to i8* >> +// ARM64: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 8 >> +// ARM64: %[[V3:.*]] = bitcast i8* %[[V2]] to i8** >> +// ARM64: call void @objc_destroyWeak(i8** %[[V3]]) >> + >> +void test_constructor_destructor_Weak(void) { >> + Weak t; >> +} >> + >> +// ARM64: define void @test_copy_constructor_Weak(%[[STRUCT_WEAK]]* >> %{{.*}}) >> +// ARM64: call void @__copy_constructor_8_8_t0w4_w8(i8** %{{.*}}, i8** >> %{{.*}}) >> +// ARM64: call void @__destructor_8_w8(i8** %{{.*}}) >> + >> +// ARM64: define linkonce_odr hidden void >> @__copy_constructor_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]]) >> +// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8 >> +// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8 >> +// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 >> +// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 >> +// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 >> +// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 >> +// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32* >> +// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32* >> +// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8 >> +// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8 >> +// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8* >> +// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8 >> +// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8** >> +// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8* >> +// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8 >> +// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8** >> +// ARM64: call void @objc_copyWeak(i8** %[[V7]], i8** %[[V10]]) >> + >> +void test_copy_constructor_Weak(Weak *s) { >> + Weak t = *s; >> +} >> + >> +// ARM64: define void @test_copy_assignment_Weak(%[[STRUCT_WEAK]]* >> %{{.*}}, %[[STRUCT_WEAK]]* %{{.*}}) >> +// ARM64: call void @__copy_assignment_8_8_t0w4_w8(i8** %{{.*}}, i8** >> %{{.*}}) >> + >> +// ARM64: define linkonce_odr hidden void >> @__copy_assignment_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]]) >> +// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8 >> +// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8 >> +// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 >> +// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 >> +// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 >> +// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 >> +// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32* >> +// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32* >> +// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8 >> +// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8 >> +// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8* >> +// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8 >> +// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8** >> +// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8* >> +// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8 >> +// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8** >> +// ARM64: %[[V11:.*]] = call i8* @objc_loadWeakRetained(i8** %[[V10]]) >> +// ARM64: %[[V12:.*]] = call i8* @objc_storeWeak(i8** %[[V7]], i8* >> %[[V11]]) >> +// ARM64: call void @objc_release(i8* %[[V11]]) >> + >> +void test_copy_assignment_Weak(Weak *d, Weak *s) { >> + *d = *s; >> +} >> + >> +// ARM64: define internal void @__Block_byref_object_copy_(i8*, i8*) >> +// ARM64: call void @__move_constructor_8_8_t0w4_w8(i8** %{{.*}}, i8** >> %{{.*}}) >> + >> +// ARM64: define linkonce_odr hidden void >> @__move_constructor_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]]) >> +// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8 >> +// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8 >> +// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 >> +// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 >> +// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 >> +// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 >> +// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32* >> +// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32* >> +// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8 >> +// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8 >> +// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8* >> +// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8 >> +// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8** >> +// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8* >> +// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8 >> +// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8** >> +// ARM64: call void @objc_moveWeak(i8** %[[V7]], i8** %[[V10]]) >> + >> +void test_move_constructor_Weak(void) { >> + __block Weak t; >> + BlockTy b = ^{ (void)t; }; >> +} >> + >> +// ARM64: define void @test_move_assignment_Weak(%[[STRUCT_WEAK]]* >> %{{.*}}) >> +// ARM64: call void @__move_assignment_8_8_t0w4_w8(i8** %{{.*}}, i8** >> %{{.*}}) >> + >> +// ARM64: define linkonce_odr hidden void >> @__move_assignment_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]]) >> +// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8 >> +// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8 >> +// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 >> +// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 >> +// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 >> +// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 >> +// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32* >> +// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32* >> +// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8 >> +// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8 >> +// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8* >> +// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8 >> +// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8** >> +// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8* >> +// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8 >> +// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8** >> +// ARM64: %[[V11:.*]] = call i8* @objc_loadWeakRetained(i8** %[[V10]]) >> +// ARM64: %[[V12:.*]] = call i8* @objc_storeWeak(i8** %[[V7]], i8* >> %[[V11]]) >> +// ARM64: call void @objc_destroyWeak(i8** %[[V10]]) >> +// ARM64: call void @objc_release(i8* %[[V11]]) >> + >> +void test_move_assignment_Weak(Weak *p) { >> + *p = getWeak(); >> +} >> + >> +// COMMON: define void @test_parameter_Weak(%[[STRUCT_WEAK]]* %[[A:.*]]) >> +// COMMON: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[A]] to i8** >> +// COMMON: call void @__destructor_{{.*}}(i8** %[[V0]]) >> + >> +void test_parameter_Weak(Weak a) { >> +} >> + >> +// COMMON: define void @test_argument_Weak(%[[STRUCT_WEAK]]* %[[A:.*]]) >> +// COMMON: %[[A_ADDR:.*]] = alloca %[[STRUCT_WEAK]]* >> +// COMMON: %[[AGG_TMP:.*]] = alloca %[[STRUCT_WEAK]] >> +// COMMON: store %[[STRUCT_WEAK]]* %[[A]], %[[STRUCT_WEAK]]** %[[A_ADDR]] >> +// COMMON: %[[V0:.*]] = load %[[STRUCT_WEAK]]*, %[[STRUCT_WEAK]]** >> %[[A_ADDR]] >> +// COMMON: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_TMP]] to i8** >> +// COMMON: %[[V2:.*]] = bitcast %[[STRUCT_WEAK]]* %[[V0]] to i8** >> +// COMMON: call void @__copy_constructor_{{.*}}(i8** %[[V1]], i8** >> %[[V2]]) >> +// COMMON: call void @calleeWeak(%[[STRUCT_WEAK]]* %[[AGG_TMP]]) >> +// COMMON-NEXT: ret >> + >> +void test_argument_Weak(Weak *a) { >> + calleeWeak(*a); >> +} >> + >> +// COMMON: define void @test_return_Weak(%[[STRUCT_WEAK]]* noalias sret >> %[[AGG_RESULT:.*]], %[[STRUCT_WEAK]]* %[[A:.*]]) >> +// COMMON: %[[A_ADDR:.*]] = alloca %[[STRUCT_WEAK]]* >> +// COMMON: store %[[STRUCT_WEAK]]* %[[A]], %[[STRUCT_WEAK]]** %[[A_ADDR]] >> +// COMMON: %[[V0:.*]] = load %[[STRUCT_WEAK]]*, %[[STRUCT_WEAK]]** >> %[[A_ADDR]] >> +// COMMON: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8** >> +// COMMON: %[[V2:.*]] = bitcast %[[STRUCT_WEAK]]* %[[V0]] to i8** >> +// COMMON: call void @__copy_constructor_{{.*}}(i8** %[[V1]], i8** >> %[[V2]]) >> +// COMMON: ret void >> + >> +Weak test_return_Weak(Weak *a) { >> + return *a; >> +} >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits@lists.llvm.org >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >> >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits