From 9d34307788056d8be15863697e1b7ec7ec3f204e Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Tue, 2 Oct 2018 01:00:44 +0000 Subject: [PATCH] [CodeGen] Before entering the loop that copies a non-trivial array field of a non-trivial C struct, copy the preceding trivial fields that haven't been copied. This commit fixes a bug where the instructions used to copy the preceding trivial fields were emitted inside the loop body. rdar://problem/44185064 llvm-svn: 343556 --- clang/lib/CodeGen/CGNonTrivialStruct.cpp | 2 ++ clang/test/CodeGenObjC/strong-in-c-struct.m | 31 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/clang/lib/CodeGen/CGNonTrivialStruct.cpp index e9f60a9..d44d156 100644 --- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp +++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp @@ -187,6 +187,7 @@ template struct GenFuncNameBase { if (!FK) return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset); + asDerived().flushTrivialFields(); CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD); ASTContext &Ctx = asDerived().getContext(); const ConstantArrayType *CAT = cast(AT); @@ -336,6 +337,7 @@ template struct GenFuncBase { return asDerived().visitTrivial(QualType(AT, 0), FD, CurStackOffset, Addrs); + asDerived().flushTrivialFields(Addrs); CodeGenFunction &CGF = *this->CGF; ASTContext &Ctx = CGF.getContext(); diff --git a/clang/test/CodeGenObjC/strong-in-c-struct.m b/clang/test/CodeGenObjC/strong-in-c-struct.m index 9c28404..494b3b2 100644 --- a/clang/test/CodeGenObjC/strong-in-c-struct.m +++ b/clang/test/CodeGenObjC/strong-in-c-struct.m @@ -485,8 +485,39 @@ void test_constructor_destructor_StructArray(void) { StructArray t; } +// Test that StructArray's field 'd' is copied before entering the loop. + +// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w8_AB8s24n4_t8w16_s24_AE(i8** %[[DST:.*]], i8** %[[SRC:.*]]) +// CHECK: entry: +// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8 +// CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8 +// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 +// CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 +// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 +// CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 +// CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i64* +// CHECK: %[[V3:.*]] = bitcast i8** %[[V1]] to i64* +// CHECK: %[[V4:.*]] = load i64, i64* %[[V3]], align 8 +// CHECK: store i64 %[[V4]], i64* %[[V2]], align 8 + +// CHECK: phi i8** +// CHECK: phi i8** + +// CHECK: phi i8** +// CHECK: phi i8** + +// CHECK-NOT: load i64, i64* % +// CHECK-NOT: store i64 % +// CHECK: call void @__copy_constructor_8_8_t0w16_s16( + +void test_copy_constructor_StructArray(StructArray a) { + StructArray t = a; +} + // Check that IRGen copies the 9-bit bitfield emitting i16 load and store. +// CHECK: define void @test_copy_constructor_Bitfield0( + // CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_s0_t8w2( // CHECK: %[[V4:.*]] = bitcast i8** %{{.*}} to i8* // CHECK: %[[V5:.*]] = getelementptr inbounds i8, i8* %[[V4]], i64 8 -- 2.7.4