forked from OSchip/llvm-project
[CodeGen] Add additional mangling for struct members of non trivial structs
In https://bugs.llvm.org/show_bug.cgi?id=41206 we observe bad codegen when embedding a non-trivial C struct within a C struct. This is due to the fact that name mangling for non-trivial structs marks the two structs as identical. This diff contains a fix for this issue. Patch by Dan Zimmerman <daniel.zimmerman@me.com>. Differential Revision: https://reviews.llvm.org/D59873 llvm-svn: 357184
This commit is contained in:
parent
1af05df3de
commit
155e26f0f4
|
@ -139,8 +139,8 @@ struct CopyStructVisitor : StructVisitor<Derived>,
|
|||
// <alignment-info> ::= <dst-alignment> ["_" <src-alignment>]
|
||||
// <struct-field-info> ::= <field-info>+
|
||||
// <field-info> ::= <struct-or-scalar-field-info> | <array-field-info>
|
||||
// <struct-or-scalar-field-info> ::= <struct-field-info> | <strong-field-info> |
|
||||
// <trivial-field-info>
|
||||
// <struct-or-scalar-field-info> ::= "_S" <struct-field-info> |
|
||||
// <strong-field-info> | <trivial-field-info>
|
||||
// <array-field-info> ::= "_AB" <array-offset> "s" <element-size> "n"
|
||||
// <num-elements> <innermost-element-info> "_AE"
|
||||
// <innermost-element-info> ::= <struct-or-scalar-field-info>
|
||||
|
@ -175,6 +175,7 @@ template <class Derived> struct GenFuncNameBase {
|
|||
void visitStruct(QualType QT, const FieldDecl *FD,
|
||||
CharUnits CurStructOffset) {
|
||||
CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
|
||||
appendStr("_S");
|
||||
asDerived().visitStructFields(QT, FieldOffset);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
@class I;
|
||||
|
||||
typedef struct {
|
||||
I *name;
|
||||
} Foo;
|
||||
|
||||
typedef struct {
|
||||
Foo foo;
|
||||
} Bar;
|
||||
|
||||
typedef struct {
|
||||
Bar bar;
|
||||
} Baz;
|
||||
|
||||
I *getI();
|
||||
|
||||
void f() {
|
||||
Foo foo = {getI()};
|
||||
Bar bar = {foo};
|
||||
Baz baz = {bar};
|
||||
}
|
||||
|
||||
// CHECK: define linkonce_odr hidden void @__destructor_8_S_S_s0(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 @__destructor_8_S_s0(i8** %[[V0]])
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define linkonce_odr hidden void @__destructor_8_S_s0(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 @__destructor_8_s0(i8** %[[V0]])
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define linkonce_odr hidden void @__destructor_8_s0(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: ret void
|
|
@ -89,12 +89,12 @@ void func(Strong *);
|
|||
// CHECK: define void @test_constructor_destructor_StrongOuter()
|
||||
// CHECK: %[[T:.*]] = alloca %[[STRUCT_STRONGOUTER:.*]], align 8
|
||||
// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T]] to i8**
|
||||
// CHECK: call void @__default_constructor_8_s16_s24(i8** %[[V0]])
|
||||
// CHECK: call void @__default_constructor_8_S_s16_s24(i8** %[[V0]])
|
||||
// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T]] to i8**
|
||||
// CHECK: call void @__destructor_8_s16_s24(i8** %[[V1]])
|
||||
// CHECK: call void @__destructor_8_S_s16_s24(i8** %[[V1]])
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define linkonce_odr hidden void @__default_constructor_8_s16_s24(i8** %[[DST:.*]])
|
||||
// CHECK: define linkonce_odr hidden void @__default_constructor_8_S_s16_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
|
||||
|
@ -117,7 +117,7 @@ void func(Strong *);
|
|||
// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 %[[V4]], i8 0, i64 8, i1 false)
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define linkonce_odr hidden void @__destructor_8_s16_s24(i8** %[[DST:.*]])
|
||||
// CHECK: define linkonce_odr hidden void @__destructor_8_S_s16_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
|
||||
|
@ -149,12 +149,12 @@ void test_constructor_destructor_StrongOuter(void) {
|
|||
// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONGOUTER]]*, %[[STRUCT_STRONGOUTER]]** %[[S_ADDR]], align 8
|
||||
// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T]] to i8**
|
||||
// CHECK: %[[V2:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[V0]] to i8**
|
||||
// CHECK: call void @__copy_constructor_8_8_t0w16_s16_s24_t32w8(i8** %[[V1]], i8** %[[V2]])
|
||||
// CHECK: call void @__copy_constructor_8_8_S_t0w16_s16_s24_t32w8(i8** %[[V1]], i8** %[[V2]])
|
||||
// CHECK: %[[V3:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T]] to i8**
|
||||
// CHECK: call void @__destructor_8_s16_s24(i8** %[[V3]])
|
||||
// CHECK: call void @__destructor_8_S_s16_s24(i8** %[[V3]])
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w16_s16_s24_t32w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
|
||||
// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_S_t0w16_s16_s24_t32w8(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
|
||||
|
@ -208,7 +208,7 @@ void test_copy_constructor_StrongOuter(StrongOuter *s) {
|
|||
StrongOuter t = *s;
|
||||
}
|
||||
|
||||
/// CHECK: define linkonce_odr hidden void @__copy_assignment_8_8_t0w16_s16_s24_t32w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
|
||||
/// CHECK: define linkonce_odr hidden void @__copy_assignment_8_8_S_t0w16_s16_s24_t32w8(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
|
||||
|
@ -231,15 +231,15 @@ void test_copy_assignment_StrongOuter(StrongOuter *d, StrongOuter *s) {
|
|||
// CHECK: define void @test_move_constructor_StrongOuter()
|
||||
// CHECK: %[[T1:.*]] = getelementptr inbounds %[[STRUCT_BLOCK_BYREF_T:.*]], %[[STRUCT_BLOCK_BYREF_T]]* %{{.*}}, i32 0, i32 7
|
||||
// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T1]] to i8**
|
||||
// CHECK: call void @__default_constructor_8_s16_s24(i8** %[[V1]])
|
||||
// CHECK: call void @__default_constructor_8_S_s16_s24(i8** %[[V1]])
|
||||
// CHECK: %[[T2:.*]] = getelementptr inbounds %[[STRUCT_BLOCK_BYREF_T]], %[[STRUCT_BLOCK_BYREF_T]]* %{{.*}}, i32 0, i32 7
|
||||
// CHECK: %[[V9:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T2]] to i8**
|
||||
// CHECK: call void @__destructor_8_s16_s24(i8** %[[V9]])
|
||||
// CHECK: call void @__destructor_8_S_s16_s24(i8** %[[V9]])
|
||||
|
||||
// CHECK: define internal void @__Block_byref_object_copy_(i8*, i8*)
|
||||
// CHECK: call void @__move_constructor_8_8_t0w16_s16_s24_t32w8(
|
||||
// CHECK: call void @__move_constructor_8_8_S_t0w16_s16_s24_t32w8(
|
||||
|
||||
// CHECK: define linkonce_odr hidden void @__move_constructor_8_8_t0w16_s16_s24_t32w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
|
||||
// CHECK: define linkonce_odr hidden void @__move_constructor_8_8_S_t0w16_s16_s24_t32w8(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
|
||||
|
@ -258,14 +258,14 @@ void test_copy_assignment_StrongOuter(StrongOuter *d, StrongOuter *s) {
|
|||
// CHECK: store i8* %[[V8]], i8** %[[V4]], align 8
|
||||
|
||||
// CHECK: define internal void @__Block_byref_object_dispose_(i8*)
|
||||
// CHECK: call void @__destructor_8_s16_s24(
|
||||
// CHECK: call void @__destructor_8_S_s16_s24(
|
||||
|
||||
void test_move_constructor_StrongOuter(void) {
|
||||
__block StrongOuter t;
|
||||
BlockTy b = ^{ (void)t; };
|
||||
}
|
||||
|
||||
// CHECK: define linkonce_odr hidden void @__move_assignment_8_8_t0w16_s16_s24_t32w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
|
||||
// CHECK: define linkonce_odr hidden void @__move_assignment_8_8_S_t0w16_s16_s24_t32w8(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
|
||||
|
@ -480,14 +480,14 @@ void test_constructor_destructor_IDArray(void) {
|
|||
IDArray t;
|
||||
}
|
||||
|
||||
// CHECK: define linkonce_odr hidden void @__default_constructor_8_AB8s24n4_s24_AE(
|
||||
// CHECK: define linkonce_odr hidden void @__default_constructor_8_AB8s24n4_S_s24_AE(
|
||||
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: define linkonce_odr hidden void @__copy_constructor_8_8_t0w8_AB8s24n4_S_t8w16_s24_AE(i8** %[[DST:.*]], i8** %[[SRC:.*]])
|
||||
// CHECK: entry:
|
||||
// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
|
||||
// CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8
|
||||
|
|
Loading…
Reference in New Issue