NonVirtualOffset,
VirtualOffset);
- // Finally, store the address point.
- llvm::Type *AddressPointPtrTy =
- VTableAddressPoint->getType()->getPointerTo();
- VTableField = Builder.CreateBitCast(VTableField, AddressPointPtrTy);
+ // Finally, store the address point. Use the same LLVM types as the field to
+ // support optimization.
+ llvm::Type *VTablePtrTy =
+ llvm::FunctionType::get(CGM.Int32Ty, /*isVarArg=*/true)
+ ->getPointerTo()
+ ->getPointerTo();
+ VTableField = Builder.CreateBitCast(VTableField, VTablePtrTy->getPointerTo());
+ VTableAddressPoint = Builder.CreateBitCast(VTableAddressPoint, VTablePtrTy);
llvm::StoreInst *Store = Builder.CreateStore(VTableAddressPoint, VTableField);
CGM.DecorateInstruction(Store, CGM.getTBAAInfoForVTablePtr());
}
};
// CHECK-LABEL: define void @_ZN10InitVTable1BC2Ev(%"struct.InitVTable::B"* %this) unnamed_addr
- // CHECK: [[T0:%.*]] = bitcast [[B:%.*]]* [[THIS:%.*]] to i8***
- // CHECK-NEXT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2), i8*** [[T0]]
+ // CHECK: [[T0:%.*]] = bitcast [[B:%.*]]* [[THIS:%.*]] to i32 (...)***
+ // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2) to i32 (...)**), i32 (...)*** [[T0]]
// CHECK: [[VTBL:%.*]] = load i32 ([[B]]*)*** {{%.*}}
// CHECK-NEXT: [[FNP:%.*]] = getelementptr inbounds i32 ([[B]]*)** [[VTBL]], i64 0
// CHECK-NEXT: [[FN:%.*]] = load i32 ([[B]]*)** [[FNP]]
// CHECK-NEXT: [[ARG:%.*]] = call i32 [[FN]]([[B]]* [[THIS]])
// CHECK-NEXT: call void @_ZN10InitVTable1AC2Ei({{.*}}* {{%.*}}, i32 [[ARG]])
- // CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* [[THIS]] to i8***
- // CHECK-NEXT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2), i8*** [[T0]]
+ // CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* [[THIS]] to i32 (...)***
+ // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2) to i32 (...)**), i32 (...)*** [[T0]]
// CHECK-NEXT: ret void
B::B() : A(foo()) {}
// CHECK-LABEL: define void @_ZN10InitVTable1BC2Ei(%"struct.InitVTable::B"* %this, i32 %x) unnamed_addr
// CHECK: [[ARG:%.*]] = add nsw i32 {{%.*}}, 5
// CHECK-NEXT: call void @_ZN10InitVTable1AC2Ei({{.*}}* {{%.*}}, i32 [[ARG]])
- // CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* {{%.*}} to i8***
- // CHECK-NEXT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2), i8*** [[T0]]
+ // CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* {{%.*}} to i32 (...)***
+ // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2) to i32 (...)**), i32 (...)*** [[T0]]
// CHECK-NEXT: ret void
B::B(int x) : A(x + 5) {}
}
A x(A& y) { return y; }
// CHECK: define linkonce_odr {{.*}} @_ZN1AC1ERKS_(%struct.A* {{.*}}%this, %struct.A* dereferenceable({{[0-9]+}})) unnamed_addr
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2)
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) to i32 (...)**)
// CHECK-LABEL: define linkonce_odr void @_ZN12rdar138169401AC2ERKS0_(
// CHECK: [[THIS:%.*]] = load [[A]]**
-// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[THIS]] to i8***
-// CHECK-NEXT: store i8** getelementptr inbounds ([4 x i8*]* @_ZTVN12rdar138169401AE, i64 0, i64 2), i8*** [[T0]]
+// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[THIS]] to i32 (...)***
+// CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([4 x i8*]* @_ZTVN12rdar138169401AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** [[T0]]
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[A]]* [[THIS]], i32 0, i32 1
// CHECK-NEXT: [[OTHER:%.*]] = load [[A]]**
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]]* [[OTHER]], i32 0, i32 1
--- /dev/null
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s -O1 | FileCheck %s --check-prefix=O1
+// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s -O1 | FileCheck %s --check-prefix=O1
+
+// Check that GlobalOpt can eliminate static constructors for simple implicit
+// constructors. This is a targetted integration test to make sure that LLVM's
+// optimizers are able to process Clang's IR. GlobalOpt in particular is
+// sensitive to the casts we emit.
+
+// CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }]
+// CHECK: [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_ctor_globalopt.cpp, i8* null }]
+
+// CHECK-LABEL: define internal void @_GLOBAL__sub_I_ctor_globalopt.cpp()
+// CHECK: call void @
+// CHECK-NOT: call
+
+// O1: @llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] zeroinitializer
+
+struct A {
+ virtual void f();
+ int a;
+};
+struct B : virtual A {
+ virtual void g();
+ int b;
+};
+B b;
Left l;
// CHECK: define {{.*}} @"\01??0Left@@QAE@XZ"
// CHECK-NOT: getelementptr
- // CHECK: store [1 x i8*]* @"\01??_7Left@@6B@"
+ // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7Left@@6B@" to i32 (...)**)
// CHECK: ret
Right r;
// CHECK: define {{.*}} @"\01??0Right@@QAE@XZ"
// CHECK-NOT: getelementptr
- // CHECK: store [1 x i8*]* @"\01??_7Right@@6B@"
+ // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7Right@@6B@" to i32 (...)**)
// CHECK: ret
ChildOverride co;
// CHECK: define {{.*}} @"\01??0ChildOverride@@QAE@XZ"
// CHECK: %[[THIS:.*]] = load %struct.ChildOverride**
- // CHECK: %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to [1 x i8*]**
- // CHECK: store [1 x i8*]* @"\01??_7ChildOverride@@6BLeft@@@", [1 x i8*]** %[[VFPTR]]
+ // CHECK: %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i32 (...)***
+ // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7ChildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i8*
// CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 4
- // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [1 x i8*]**
- // CHECK: store [1 x i8*]* @"\01??_7ChildOverride@@6BRight@@@", [1 x i8*]** %[[VFPTR]]
+ // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
+ // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7ChildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// CHECK: ret
GrandchildOverride gc;
// CHECK: define {{.*}} @"\01??0GrandchildOverride@@QAE@XZ"
// CHECK: %[[THIS:.*]] = load %struct.GrandchildOverride**
- // CHECK: %[[VFPTR:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to [1 x i8*]**
- // CHECK: store [1 x i8*]* @"\01??_7GrandchildOverride@@6BLeft@@@", [1 x i8*]** %[[VFPTR]]
+ // CHECK: %[[VFPTR:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i32 (...)***
+ // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7GrandchildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i8*
// CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 4
- // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [1 x i8*]**
- // CHECK: store [1 x i8*]* @"\01??_7GrandchildOverride@@6BRight@@@", [1 x i8*]** %[[VFPTR]]
+ // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
+ // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7GrandchildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// CHECK: ret
}
void check_vftable_offset() {
C c;
// The vftable pointer should point at the beginning of the vftable.
-// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to [2 x i8*]**
-// CHECK: store [2 x i8*]* @"\01??_7C@basic@@6B@", [2 x i8*]** [[THIS_PTR]]
+// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to i32 (...)***
+// CHECK: store i32 (...)** bitcast ([2 x i8*]* @"\01??_7C@basic@@6B@" to i32 (...)**), i32 (...)*** [[THIS_PTR]]
}
void call_complete_dtor(C *obj_ptr) {
// ...
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %{{.*}}
- // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [3 x i8*]**
- // CHECK: store [3 x i8*]* @"\01??_7B@@6B@", [3 x i8*]** %[[VFPTR]]
+ // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
+ // CHECK: store i32 (...)** bitcast ([3 x i8*]* @"\01??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// Initialize vtorDisp:
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// ...
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %{{.*}}
- // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [3 x i8*]**
- // CHECK: store [3 x i8*]* @"\01??_7B@@6B@", [3 x i8*]** %[[VFPTR]]
+ // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
+ // CHECK: store i32 (...)** bitcast ([3 x i8*]* @"\01??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// Initialize vtorDisp:
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
D::D() {
// CHECK-LABEL: define x86_thiscallcc %"struct.multiple_vbases::D"* @"\01??0D@multiple_vbases@@QAE@XZ"
// Just make sure we emit 3 vtordisps after initializing vfptrs.
- // CHECK: store [1 x i8*]* @"\01??_7D@multiple_vbases@@6BA@1@@", [1 x i8*]** %{{.*}}
- // CHECK: store [1 x i8*]* @"\01??_7D@multiple_vbases@@6BB@1@@", [1 x i8*]** %{{.*}}
- // CHECK: store [1 x i8*]* @"\01??_7D@multiple_vbases@@6BC@1@@", [1 x i8*]** %{{.*}}
+ // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7D@multiple_vbases@@6BA@1@@" to i32 (...)**), i32 (...)*** %{{.*}}
+ // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7D@multiple_vbases@@6BB@1@@" to i32 (...)**), i32 (...)*** %{{.*}}
+ // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7D@multiple_vbases@@6BC@1@@" to i32 (...)**), i32 (...)*** %{{.*}}
// ...
// CHECK: store i32 %{{.*}}, i32* %{{.*}}
// CHECK: store i32 %{{.*}}, i32* %{{.*}}
// In this case "this" points to the most derived class, so no GEPs needed.
// CHECK-NOT: getelementptr
// CHECK-NOT: bitcast
- // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::C"* %{{.*}} to [1 x i8*]**
- // CHECK: store [1 x i8*]* @"\01??_7C@test4@@6BB@1@@", [1 x i8*]** %[[VFPTR_i8]]
+ // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::C"* %{{.*}} to i32 (...)***
+ // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7C@test4@@6BB@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
foo(this);
// CHECK: ret
// In this case "this" points to the most derived class, so no GEPs needed.
// CHECK-NOT: getelementptr
// CHECK-NOT: bitcast
- // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::E"* %{{.*}} to [1 x i8*]**
- // CHECK: store [1 x i8*]* @"\01??_7E@test4@@6BD@1@@", [1 x i8*]** %[[VFPTR_i8]]
+ // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::E"* %{{.*}} to i32 (...)***
+ // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7E@test4@@6BD@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
foo(this);
}
// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1SC2Ev(%struct.S* %this)
// CHECK: call x86_thiscallcc void @_ZN1IC2Ev(%__interface.I* %{{[.0-9A-Z_a-z]+}})
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1S, i64 0, i64 2), i8*** %{{[.0-9A-Z_a-z]+}}
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTV1S, i64 0, i64 2) to i32 (...)**), i32 (...)*** %{{[.0-9A-Z_a-z]+}}
// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1IC2Ev(%__interface.I* %this)
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1I, i64 0, i64 2), i8*** %{{[.0-9A-Z_a-z]+}}
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTV1I, i64 0, i64 2) to i32 (...)**), i32 (...)*** %{{[.0-9A-Z_a-z]+}}
};
// CHECK-LABEL: define void @_ZN5Test11AD2Ev
-// CHECK-NOT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test11AE, i64 0, i64 2), i8***
+// CHECK-NOT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test11AE, i64 0, i64 2) to i32 (...)**), i32 (...)***
A::~A()
{
}
};
// CHECK-LABEL: define void @_ZN5Test21AD2Ev
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test21AE, i64 0, i64 2), i8***
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test21AE, i64 0, i64 2) to i32 (...)**), i32 (...)***
A::~A() {
f();
}
};
// CHECK-LABEL: define void @_ZN5Test31AD2Ev
-// CHECK-NOT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test31AE, i64 0, i64 2), i8***
+// CHECK-NOT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test31AE, i64 0, i64 2) to i32 (...)**), i32 (...)***
A::~A() {
}
};
// CHECK-LABEL: define void @_ZN5Test41AD2Ev
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test41AE, i64 0, i64 2), i8***
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test41AE, i64 0, i64 2) to i32 (...)**), i32 (...)***
A::~A()
{
}
};
// CHECK-LABEL: define void @_ZN5Test51AD2Ev
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test51AE, i64 0, i64 2), i8***
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test51AE, i64 0, i64 2) to i32 (...)**), i32 (...)***
A::~A()
{
}
};
// CHECK-LABEL: define void @_ZN5Test61AD2Ev
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test61AE, i64 0, i64 2), i8***
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test61AE, i64 0, i64 2) to i32 (...)**), i32 (...)***
A::~A()
{
}
};
// CHECK-LABEL: define void @_ZN5Test71AD2Ev
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test71AE, i64 0, i64 2), i8***
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test71AE, i64 0, i64 2) to i32 (...)**), i32 (...)***
A::~A()
{
}
};
// CHECK-LABEL: define void @_ZN5Test81AD2Ev
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test81AE, i64 0, i64 2), i8***
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test81AE, i64 0, i64 2) to i32 (...)**), i32 (...)***
A::~A()
{
}
// CHECK-LABEL: define void @_ZN1AC2Ev(%struct.A* %this) unnamed_addr
// CHECK: call void @_ZN4BaseC2Ev(
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2)
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) to i32 (...)**)
// CHECK: call void @_ZN5FieldC1Ev(
// CHECK: ret void
A::A() { }
// CHECK-LABEL: define void @_ZN1AD2Ev(%struct.A* %this) unnamed_addr
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2)
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) to i32 (...)**)
// CHECK: call void @_ZN5FieldD1Ev(
// CHECK: call void @_ZN4BaseD2Ev(
// CHECK: ret void
// CHECK: call void @_ZN1BC2Ev(
// CHECK-LABEL: define linkonce_odr void @_ZN1BD1Ev(%struct.B* %this) unnamed_addr
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2)
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2) to i32 (...)**)
// CHECK: call void @_ZN5FieldD1Ev(
// CHECK: call void @_ZN4BaseD2Ev(
// CHECK: ret void
// CHECK-LABEL: define linkonce_odr void @_ZN1BC2Ev(%struct.B* %this) unnamed_addr
// CHECK: call void @_ZN4BaseC2Ev(
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2)
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2) to i32 (...)**)
// CHECK: call void @_ZN5FieldC1Ev
// CHECK: ret void