I have been trying to reduce a reproducer for this but haven't gotten any luck yet. The error happens in conversion between different version of STL containers and is a bit hard to reduce. I'll keep trying to create a reproducer.
Could you please also take a quick look to see if ASTImporter/Reader/Writer is actually missing something? Thanks, Eric On Mon, Mar 12, 2018 at 5:14 PM Akira Hatanaka <ahatan...@apple.com> wrote: > Do you have a reproducer? > > > On Mar 12, 2018, at 9:07 AM, Eric Liu <ioe...@google.com> wrote: > > I think there is a bug in the ASTImporter/Reader/Writer, but I'm not sure > what's the right way to fix it. I'll revert this commit for now to unblock > integration. Let me know if you need more information from us. > > Regards, > Eric > > On Mon, Mar 12, 2018 at 4:51 PM Eric Liu <ioe...@google.com> wrote: > >> 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