I’m not sure if this a bug r327206 introduced or an existing bug in ASTImporter as there are other bits in RecordDecl that are not copied, but I think I should revert the patch for now.
> On Mar 12, 2018, at 9:57 AM, Eric Liu <[email protected]> wrote: > > I think it's likely as our tests only fail with module enabled (without > module, ASTImporter isn't really used). > > On Mon, Mar 12, 2018 at 5:51 PM Akira Hatanaka <[email protected] > <mailto:[email protected]>> wrote: > The patch I committed moved CXXRecordDecl::CanPassInRegisters to RecordDecl. > It looks like ASTImporter::ImportDefinition no longer copies the bit for > CanPassInRegisters after that change. I’m not sure that is what’s causing > tests to fail. > >> On Mar 12, 2018, at 9:29 AM, Eric Liu <[email protected] >> <mailto:[email protected]>> wrote: >> >> 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 <[email protected] >> <mailto:[email protected]>> wrote: >> Do you have a reproducer? >> >> >>> On Mar 12, 2018, at 9:07 AM, Eric Liu <[email protected] >>> <mailto:[email protected]>> 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 <[email protected] >>> <mailto:[email protected]>> 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 <[email protected] >>> <mailto:[email protected]>> 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 >>> <[email protected] <mailto:[email protected]>> 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 >>> [email protected] <mailto:[email protected]> >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >>> <http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits> >> >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
