r327206 - [ObjC] Allow declaring __weak pointer fields in C structs in ARC.
Eric Liu via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 12 07:56:43 PDT 2018
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 at 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 at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180312/96cfb072/attachment-0001.html>
More information about the cfe-commits
mailing list