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 <ahatan...@apple.com> 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 <ioe...@google.com> 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 <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