r357229 - [CodeGen][ObjC] Adjust the addresses passed to calls to synthesized

Akira Hatanaka via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 28 17:23:20 PDT 2019


Author: ahatanak
Date: Thu Mar 28 17:23:20 2019
New Revision: 357229

URL: http://llvm.org/viewvc/llvm-project?rev=357229&view=rev
Log:
[CodeGen][ObjC] Adjust the addresses passed to calls to synthesized
copy/move constructor/assignment operator functions for non-trivial C
structs.

This commit fixes a bug where the offset of struct fields weren't being
taken into account when computing the addresses passed to calls to the
special functions.

For example, the copy constructor for S1 (__copy_constructor_8_8_s0_s8)
would pass the start addresses of the destination and source structs to
the call to S0's copy constructor (_copy_constructor_8_8_s0) without
adding the offset of field f1 to the addresses.

typedef struct {
  id f0;
  S0 f1;
} S1;

void test(S1 s1) {
  S1 t = s1;
}

rdar://problem/49400610

Modified:
    cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp
    cfe/trunk/test/CodeGenObjC/strong-in-c-struct.m

Modified: cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp?rev=357229&r1=357228&r2=357229&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp Thu Mar 28 17:23:20 2019
@@ -688,6 +688,8 @@ struct GenCopyConstructor : GenBinaryFun
 
   void callSpecialFunction(QualType FT, CharUnits Offset,
                            std::array<Address, 2> Addrs) {
+    Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
+    Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
     CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
                                     CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
   }
@@ -718,6 +720,8 @@ struct GenMoveConstructor : GenBinaryFun
 
   void callSpecialFunction(QualType FT, CharUnits Offset,
                            std::array<Address, 2> Addrs) {
+    Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
+    Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
     CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
                                     CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
   }
@@ -746,6 +750,8 @@ struct GenCopyAssignment : GenBinaryFunc
 
   void callSpecialFunction(QualType FT, CharUnits Offset,
                            std::array<Address, 2> Addrs) {
+    Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
+    Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
     CGF->callCStructCopyAssignmentOperator(
         CGF->MakeAddrLValue(Addrs[DstIdx], FT),
         CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
@@ -780,6 +786,8 @@ struct GenMoveAssignment : GenBinaryFunc
 
   void callSpecialFunction(QualType FT, CharUnits Offset,
                            std::array<Address, 2> Addrs) {
+    Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
+    Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
     CGF->callCStructMoveAssignmentOperator(
         CGF->MakeAddrLValue(Addrs[DstIdx], FT),
         CGF->MakeAddrLValue(Addrs[SrcIdx], FT));

Modified: cfe/trunk/test/CodeGenObjC/strong-in-c-struct.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/strong-in-c-struct.m?rev=357229&r1=357228&r2=357229&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/strong-in-c-struct.m (original)
+++ cfe/trunk/test/CodeGenObjC/strong-in-c-struct.m Thu Mar 28 17:23:20 2019
@@ -30,6 +30,11 @@ typedef struct {
 } StrongOuter;
 
 typedef struct {
+  id f0;
+  Strong f1;
+} StrongOuter2;
+
+typedef struct {
   int f0;
   volatile id f1;
 } StrongVolatile;
@@ -81,6 +86,7 @@ typedef struct {
 
 StrongSmall getStrongSmall(void);
 StrongOuter getStrongOuter(void);
+StrongOuter2 getStrongOuter2(void);
 void calleeStrongSmall(StrongSmall);
 void func(Strong *);
 
@@ -289,6 +295,121 @@ void test_move_assignment_StrongOuter(St
   *p = getStrongOuter();
 }
 
+// CHECK: define linkonce_odr hidden void @__default_constructor_8_s0_S_s24(i8** %[[DST:.*]])
+// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// CHECK: %[[V1:.*]] = bitcast i8** %[[V0]] to i8*
+// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 %[[V1]], i8 0, i64 8, i1 false)
+// CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i8*
+// CHECK: %[[V3:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 8
+// CHECK: %[[V4:.*]] = bitcast i8* %[[V3]] to i8**
+// CHECK: call void @__default_constructor_8_s16(i8** %[[V4]])
+
+// CHECK: define linkonce_odr hidden void @__destructor_8_s0_S_s24(i8** %[[DST:.*]])
+// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// CHECK: call void @llvm.objc.storeStrong(i8** %[[V0]], i8* null)
+// CHECK: %[[V1:.*]] = bitcast i8** %[[V0]] to i8*
+// CHECK: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 8
+// CHECK: %[[V3:.*]] = bitcast i8* %[[V2]] to i8**
+// CHECK: call void @__destructor_8_s16(i8** %[[V3]])
+
+void test_constructor_destructor_StrongOuter2(void) {
+  StrongOuter2 t;
+}
+
+// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_s0_S_t8w16_s24(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// 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:.*]] = load i8*, i8** %[[V1]], align 8
+// CHECK: %[[V3:.*]] = call i8* @llvm.objc.retain(i8* %[[V2]])
+// CHECK: store i8* %[[V3]], i8** %[[V0]], align 8
+// CHECK: %[[V4:.*]] = bitcast i8** %[[V0]] to i8*
+// CHECK: %[[V5:.*]] = getelementptr inbounds i8, i8* %[[V4]], i64 8
+// CHECK: %[[V6:.*]] = bitcast i8* %[[V5]] to i8**
+// CHECK: %[[V7:.*]] = bitcast i8** %[[V1]] to i8*
+// CHECK: %[[V8:.*]] = getelementptr inbounds i8, i8* %[[V7]], i64 8
+// CHECK: %[[V9:.*]] = bitcast i8* %[[V8]] to i8**
+// CHECK: call void @__copy_constructor_8_8_t0w16_s16(i8** %[[V6]], i8** %[[V9]])
+
+void test_copy_constructor_StrongOuter2(StrongOuter2 *s) {
+  StrongOuter2 t = *s;
+}
+
+// CHECK: define linkonce_odr hidden void @__copy_assignment_8_8_s0_S_t8w16_s24(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// 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:.*]] = load i8*, i8** %[[V1]], align 8
+// CHECK: call void @llvm.objc.storeStrong(i8** %[[V0]], i8* %[[V2]])
+// CHECK: %[[V3:.*]] = bitcast i8** %[[V0]] to i8*
+// CHECK: %[[V4:.*]] = getelementptr inbounds i8, i8* %[[V3]], i64 8
+// CHECK: %[[V5:.*]] = bitcast i8* %[[V4]] to i8**
+// CHECK: %[[V6:.*]] = bitcast i8** %[[V1]] to i8*
+// CHECK: %[[V7:.*]] = getelementptr inbounds i8, i8* %[[V6]], i64 8
+// CHECK: %[[V8:.*]] = bitcast i8* %[[V7]] to i8**
+// CHECK: call void @__copy_assignment_8_8_t0w16_s16(i8** %[[V5]], i8** %[[V8]])
+
+void test_copy_assignment_StrongOuter2(StrongOuter2 *d, StrongOuter2 *s) {
+  *d = *s;
+}
+
+// CHECK: define linkonce_odr hidden void @__move_constructor_8_8_s0_S_t8w16_s24(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// 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:.*]] = load i8*, i8** %[[V1]], align 8
+// CHECK: store i8* null, i8** %[[V1]], align 8
+// CHECK: store i8* %[[V2]], i8** %[[V0]], align 8
+// CHECK: %[[V3:.*]] = bitcast i8** %[[V0]] to i8*
+// CHECK: %[[V4:.*]] = getelementptr inbounds i8, i8* %[[V3]], i64 8
+// CHECK: %[[V5:.*]] = bitcast i8* %[[V4]] to i8**
+// CHECK: %[[V6:.*]] = bitcast i8** %[[V1]] to i8*
+// CHECK: %[[V7:.*]] = getelementptr inbounds i8, i8* %[[V6]], i64 8
+// CHECK: %[[V8:.*]] = bitcast i8* %[[V7]] to i8**
+// CHECK: call void @__move_constructor_8_8_t0w16_s16(i8** %[[V5]], i8** %[[V8]])
+
+void test_move_constructor_StrongOuter2(void) {
+  __block StrongOuter2 t;
+  BlockTy b = ^{ (void)t; };
+}
+
+// CHECK: define linkonce_odr hidden void @__move_assignment_8_8_s0_S_t8w16_s24(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// 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:.*]] = load i8*, i8** %[[V1]], align 8
+// CHECK: store i8* null, i8** %[[V1]], align 8
+// CHECK: %[[V3:.*]] = load i8*, i8** %[[V0]], align 8
+// CHECK: store i8* %[[V2]], i8** %[[V0]], align 8
+// CHECK: call void @llvm.objc.release(i8* %[[V3]])
+// CHECK: %[[V4:.*]] = bitcast i8** %[[V0]] to i8*
+// CHECK: %[[V5:.*]] = getelementptr inbounds i8, i8* %[[V4]], i64 8
+// CHECK: %[[V6:.*]] = bitcast i8* %[[V5]] to i8**
+// CHECK: %[[V7:.*]] = bitcast i8** %[[V1]] to i8*
+// CHECK: %[[V8:.*]] = getelementptr inbounds i8, i8* %[[V7]], i64 8
+// CHECK: %[[V9:.*]] = bitcast i8* %[[V8]] to i8**
+// CHECK: call void @__move_assignment_8_8_t0w16_s16(i8** %[[V6]], i8** %[[V9]])
+
+void test_move_assignment_StrongOuter2(StrongOuter2 *p) {
+  *p = getStrongOuter2();
+}
+
 // CHECK: define void @test_parameter_StrongSmall([2 x i64] %[[A_COERCE:.*]])
 // CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONG:.*]], align 8
 // CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONG]]* %[[A]] to [2 x i64]*




More information about the cfe-commits mailing list