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 > <mailto: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 > <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 > <mailto: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 <mailto: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 > <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 > <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 > > <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 > > <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 > > <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 > > <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 > > <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 > > <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 > > <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 > > <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 > > <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 > > <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 > > <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 > > <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 > > <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 > > <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 > > <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 > > <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 > > <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 > > <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 <mailto:cfe-commits@lists.llvm.org> > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits > <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