2014-07-18 09:48:10 +08:00
|
|
|
// RUN: %clang_cc1 -emit-llvm -fno-rtti %s -std=c++11 -o - -mconstructor-aliases -triple=i386-pc-win32 -fno-rtti > %t
|
2013-02-13 16:37:51 +08:00
|
|
|
// RUN: FileCheck %s < %t
|
[ms-cxxabi] Emit linkonce complete dtors in TUs that need them
Based on Peter Collingbourne's destructor patches.
Prior to this change, clang was considering ?1 to be the complete
destructor and the base destructor, which was wrong. This lead to
crashes when clang tried to emit two LLVM functions with the same name.
In this ABI, TUs with non-inline dtors might not emit a complete
destructor. They are emitted as inline thunks in TUs that need them,
and they always delegate to the base dtors of the complete class and its
virtual bases. This change uses the DeferredDecls machinery to emit
complete dtors as needed.
Currently in clang try body destructors can catch exceptions thrown by
virtual base destructors. In the Microsoft C++ ABI, clang may not have
the destructor definition, in which case clang won't wrap the virtual
virtual base destructor calls in a try-catch. Diagnosing this in user
code is TODO.
Finally, for classes that don't use virtual inheritance, MSVC always
calls the base destructor (?1) directly. This is a useful code size
optimization that avoids emitting lots of extra thunks or aliases.
Implementing it also means our existing tests continue to pass, and is
consistent with MSVC's output.
We can do the same for Itanium by tweaking GetAddrOfCXXDestructor, but
it will require further testing.
Reviewers: rjmccall
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1066
llvm-svn: 186828
2013-07-22 21:51:44 +08:00
|
|
|
// vftables are emitted very late, so do another pass to try to keep the checks
|
|
|
|
// in source order.
|
|
|
|
// RUN: FileCheck --check-prefix DTORS %s < %t
|
2014-02-19 06:51:52 +08:00
|
|
|
// RUN: FileCheck --check-prefix DTORS2 %s < %t
|
|
|
|
// RUN: FileCheck --check-prefix DTORS3 %s < %t
|
2015-09-15 05:29:57 +08:00
|
|
|
// RUN: FileCheck --check-prefix DTORS4 %s < %t
|
2013-08-26 18:32:04 +08:00
|
|
|
//
|
2016-05-14 04:05:09 +08:00
|
|
|
// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -triple=x86_64-pc-win32 -fno-rtti -std=c++11 | FileCheck --check-prefix DTORS-X64 %s
|
2012-04-20 16:05:00 +08:00
|
|
|
|
2013-02-27 21:46:31 +08:00
|
|
|
namespace basic {
|
|
|
|
|
2012-04-20 16:05:00 +08:00
|
|
|
class A {
|
|
|
|
public:
|
|
|
|
A() { }
|
[ms-cxxabi] Emit linkonce complete dtors in TUs that need them
Based on Peter Collingbourne's destructor patches.
Prior to this change, clang was considering ?1 to be the complete
destructor and the base destructor, which was wrong. This lead to
crashes when clang tried to emit two LLVM functions with the same name.
In this ABI, TUs with non-inline dtors might not emit a complete
destructor. They are emitted as inline thunks in TUs that need them,
and they always delegate to the base dtors of the complete class and its
virtual bases. This change uses the DeferredDecls machinery to emit
complete dtors as needed.
Currently in clang try body destructors can catch exceptions thrown by
virtual base destructors. In the Microsoft C++ ABI, clang may not have
the destructor definition, in which case clang won't wrap the virtual
virtual base destructor calls in a try-catch. Diagnosing this in user
code is TODO.
Finally, for classes that don't use virtual inheritance, MSVC always
calls the base destructor (?1) directly. This is a useful code size
optimization that avoids emitting lots of extra thunks or aliases.
Implementing it also means our existing tests continue to pass, and is
consistent with MSVC's output.
We can do the same for Itanium by tweaking GetAddrOfCXXDestructor, but
it will require further testing.
Reviewers: rjmccall
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1066
llvm-svn: 186828
2013-07-22 21:51:44 +08:00
|
|
|
~A();
|
2012-04-20 16:05:00 +08:00
|
|
|
};
|
|
|
|
|
2013-02-12 21:22:47 +08:00
|
|
|
void no_constructor_destructor_infinite_recursion() {
|
2012-04-20 16:05:00 +08:00
|
|
|
A a;
|
|
|
|
|
2015-01-16 23:37:11 +08:00
|
|
|
// CHECK: define linkonce_odr x86_thiscallcc %"class.basic::A"* @"\01??0A@basic@@QAE@XZ"(%"class.basic::A"* returned %this) {{.*}} comdat {{.*}} {
|
2013-02-27 21:46:31 +08:00
|
|
|
// CHECK: [[THIS_ADDR:%[.0-9A-Z_a-z]+]] = alloca %"class.basic::A"*, align 4
|
|
|
|
// CHECK-NEXT: store %"class.basic::A"* %this, %"class.basic::A"** [[THIS_ADDR]], align 4
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK-NEXT: [[T1:%[.0-9A-Z_a-z]+]] = load %"class.basic::A"*, %"class.basic::A"** [[THIS_ADDR]]
|
2013-02-27 21:46:31 +08:00
|
|
|
// CHECK-NEXT: ret %"class.basic::A"* [[T1]]
|
2012-09-25 16:00:39 +08:00
|
|
|
// CHECK-NEXT: }
|
[ms-cxxabi] Emit linkonce complete dtors in TUs that need them
Based on Peter Collingbourne's destructor patches.
Prior to this change, clang was considering ?1 to be the complete
destructor and the base destructor, which was wrong. This lead to
crashes when clang tried to emit two LLVM functions with the same name.
In this ABI, TUs with non-inline dtors might not emit a complete
destructor. They are emitted as inline thunks in TUs that need them,
and they always delegate to the base dtors of the complete class and its
virtual bases. This change uses the DeferredDecls machinery to emit
complete dtors as needed.
Currently in clang try body destructors can catch exceptions thrown by
virtual base destructors. In the Microsoft C++ ABI, clang may not have
the destructor definition, in which case clang won't wrap the virtual
virtual base destructor calls in a try-catch. Diagnosing this in user
code is TODO.
Finally, for classes that don't use virtual inheritance, MSVC always
calls the base destructor (?1) directly. This is a useful code size
optimization that avoids emitting lots of extra thunks or aliases.
Implementing it also means our existing tests continue to pass, and is
consistent with MSVC's output.
We can do the same for Itanium by tweaking GetAddrOfCXXDestructor, but
it will require further testing.
Reviewers: rjmccall
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1066
llvm-svn: 186828
2013-07-22 21:51:44 +08:00
|
|
|
}
|
2012-04-20 16:05:00 +08:00
|
|
|
|
[ms-cxxabi] Emit linkonce complete dtors in TUs that need them
Based on Peter Collingbourne's destructor patches.
Prior to this change, clang was considering ?1 to be the complete
destructor and the base destructor, which was wrong. This lead to
crashes when clang tried to emit two LLVM functions with the same name.
In this ABI, TUs with non-inline dtors might not emit a complete
destructor. They are emitted as inline thunks in TUs that need them,
and they always delegate to the base dtors of the complete class and its
virtual bases. This change uses the DeferredDecls machinery to emit
complete dtors as needed.
Currently in clang try body destructors can catch exceptions thrown by
virtual base destructors. In the Microsoft C++ ABI, clang may not have
the destructor definition, in which case clang won't wrap the virtual
virtual base destructor calls in a try-catch. Diagnosing this in user
code is TODO.
Finally, for classes that don't use virtual inheritance, MSVC always
calls the base destructor (?1) directly. This is a useful code size
optimization that avoids emitting lots of extra thunks or aliases.
Implementing it also means our existing tests continue to pass, and is
consistent with MSVC's output.
We can do the same for Itanium by tweaking GetAddrOfCXXDestructor, but
it will require further testing.
Reviewers: rjmccall
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1066
llvm-svn: 186828
2013-07-22 21:51:44 +08:00
|
|
|
A::~A() {
|
2012-04-20 16:05:00 +08:00
|
|
|
// Make sure that the destructor doesn't call itself:
|
2013-02-27 21:46:31 +08:00
|
|
|
// CHECK: define {{.*}} @"\01??1A@basic@@QAE@XZ"
|
|
|
|
// CHECK-NOT: call void @"\01??1A@basic@@QAE@XZ"
|
2012-04-20 16:05:00 +08:00
|
|
|
// CHECK: ret
|
|
|
|
}
|
2012-09-25 16:00:39 +08:00
|
|
|
|
2013-01-21 21:02:41 +08:00
|
|
|
struct B {
|
2013-02-27 21:46:31 +08:00
|
|
|
B();
|
|
|
|
};
|
|
|
|
|
|
|
|
// Tests that we can define constructors outside the class (PR12784).
|
|
|
|
B::B() {
|
2013-07-01 04:40:16 +08:00
|
|
|
// CHECK: define x86_thiscallcc %"struct.basic::B"* @"\01??0B@basic@@QAE@XZ"(%"struct.basic::B"* returned %this)
|
2013-02-27 21:46:31 +08:00
|
|
|
// CHECK: ret
|
|
|
|
}
|
|
|
|
|
|
|
|
struct C {
|
|
|
|
virtual ~C() {
|
2015-01-16 23:37:11 +08:00
|
|
|
// DTORS: define linkonce_odr x86_thiscallcc i8* @"\01??_GC@basic@@UAEPAXI@Z"(%"struct.basic::C"* %this, i32 %should_call_delete) {{.*}} comdat {{.*}} {
|
2013-08-27 18:38:19 +08:00
|
|
|
// DTORS: store i32 %should_call_delete, i32* %[[SHOULD_DELETE_VAR:[0-9a-z._]+]], align 4
|
2014-11-01 04:09:12 +08:00
|
|
|
// DTORS: store i8* %{{.*}}, i8** %[[RETVAL:[0-9a-z._]+]]
|
2015-02-28 05:19:58 +08:00
|
|
|
// DTORS: %[[SHOULD_DELETE_VALUE:[0-9a-z._]+]] = load i32, i32* %[[SHOULD_DELETE_VAR]]
|
2013-02-27 21:46:31 +08:00
|
|
|
// DTORS: call x86_thiscallcc void @"\01??1C@basic@@UAE@XZ"(%"struct.basic::C"* %[[THIS:[0-9a-z]+]])
|
2013-08-27 18:38:19 +08:00
|
|
|
// DTORS-NEXT: %[[CONDITION:[0-9]+]] = icmp eq i32 %[[SHOULD_DELETE_VALUE]], 0
|
2013-02-13 20:14:25 +08:00
|
|
|
// DTORS-NEXT: br i1 %[[CONDITION]], label %[[CONTINUE_LABEL:[0-9a-z._]+]], label %[[CALL_DELETE_LABEL:[0-9a-z._]+]]
|
|
|
|
//
|
|
|
|
// DTORS: [[CALL_DELETE_LABEL]]
|
2013-02-27 21:46:31 +08:00
|
|
|
// DTORS-NEXT: %[[THIS_AS_VOID:[0-9a-z]+]] = bitcast %"struct.basic::C"* %[[THIS]] to i8*
|
[ms-cxxabi] Emit linkonce complete dtors in TUs that need them
Based on Peter Collingbourne's destructor patches.
Prior to this change, clang was considering ?1 to be the complete
destructor and the base destructor, which was wrong. This lead to
crashes when clang tried to emit two LLVM functions with the same name.
In this ABI, TUs with non-inline dtors might not emit a complete
destructor. They are emitted as inline thunks in TUs that need them,
and they always delegate to the base dtors of the complete class and its
virtual bases. This change uses the DeferredDecls machinery to emit
complete dtors as needed.
Currently in clang try body destructors can catch exceptions thrown by
virtual base destructors. In the Microsoft C++ ABI, clang may not have
the destructor definition, in which case clang won't wrap the virtual
virtual base destructor calls in a try-catch. Diagnosing this in user
code is TODO.
Finally, for classes that don't use virtual inheritance, MSVC always
calls the base destructor (?1) directly. This is a useful code size
optimization that avoids emitting lots of extra thunks or aliases.
Implementing it also means our existing tests continue to pass, and is
consistent with MSVC's output.
We can do the same for Itanium by tweaking GetAddrOfCXXDestructor, but
it will require further testing.
Reviewers: rjmccall
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1066
llvm-svn: 186828
2013-07-22 21:51:44 +08:00
|
|
|
// DTORS-NEXT: call void @"\01??3@YAXPAX@Z"(i8* %[[THIS_AS_VOID]])
|
2013-02-13 20:14:25 +08:00
|
|
|
// DTORS-NEXT: br label %[[CONTINUE_LABEL]]
|
|
|
|
//
|
|
|
|
// DTORS: [[CONTINUE_LABEL]]
|
2015-02-28 05:19:58 +08:00
|
|
|
// DTORS-NEXT: %[[RET:.*]] = load i8*, i8** %[[RETVAL]]
|
2014-11-01 04:09:12 +08:00
|
|
|
// DTORS-NEXT: ret i8* %[[RET]]
|
2013-08-26 18:32:04 +08:00
|
|
|
|
|
|
|
// Check that we do the mangling correctly on x64.
|
|
|
|
// DTORS-X64: @"\01??_GC@basic@@UEAAPEAXI@Z"
|
2013-02-13 16:37:51 +08:00
|
|
|
}
|
2013-01-21 21:02:41 +08:00
|
|
|
virtual void foo();
|
|
|
|
};
|
|
|
|
|
2013-02-13 16:37:51 +08:00
|
|
|
// Emits the vftable in the output.
|
2013-02-27 21:46:31 +08:00
|
|
|
void C::foo() {}
|
2013-02-13 16:37:51 +08:00
|
|
|
|
2013-01-21 21:02:41 +08:00
|
|
|
void check_vftable_offset() {
|
2013-02-27 21:46:31 +08:00
|
|
|
C c;
|
2013-01-21 21:02:41 +08:00
|
|
|
// The vftable pointer should point at the beginning of the vftable.
|
2014-12-04 05:00:21 +08:00
|
|
|
// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to i32 (...)***
|
2016-12-14 04:40:39 +08:00
|
|
|
// CHECK: store i32 (...)** bitcast ({ [2 x i8*] }* @"\01??_7C@basic@@6B@" to i32 (...)**), i32 (...)*** [[THIS_PTR]]
|
2013-01-21 21:02:41 +08:00
|
|
|
}
|
2013-02-13 16:37:51 +08:00
|
|
|
|
2013-02-27 21:46:31 +08:00
|
|
|
void call_complete_dtor(C *obj_ptr) {
|
|
|
|
// CHECK: define void @"\01?call_complete_dtor@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
|
|
|
|
obj_ptr->~C();
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK: %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"*, %"struct.basic::C"** %{{.*}}, align 4
|
2014-11-01 04:09:12 +08:00
|
|
|
// CHECK-NEXT: %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to i8* (%"struct.basic::C"*, i32)***
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK-NEXT: %[[VTABLE:.*]] = load i8* (%"struct.basic::C"*, i32)**, i8* (%"struct.basic::C"*, i32)*** %[[PVTABLE]]
|
2015-02-28 03:18:17 +08:00
|
|
|
// CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds i8* (%"struct.basic::C"*, i32)*, i8* (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK-NEXT: %[[VDTOR:.*]] = load i8* (%"struct.basic::C"*, i32)*, i8* (%"struct.basic::C"*, i32)** %[[PVDTOR]]
|
2014-11-01 04:09:12 +08:00
|
|
|
// CHECK-NEXT: call x86_thiscallcc i8* %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i32 0)
|
2013-02-15 22:45:22 +08:00
|
|
|
// CHECK-NEXT: ret void
|
2013-02-13 16:37:51 +08:00
|
|
|
}
|
|
|
|
|
2013-02-27 21:46:31 +08:00
|
|
|
void call_deleting_dtor(C *obj_ptr) {
|
|
|
|
// CHECK: define void @"\01?call_deleting_dtor@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
|
2013-02-13 16:37:51 +08:00
|
|
|
delete obj_ptr;
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK: %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"*, %"struct.basic::C"** %{{.*}}, align 4
|
2013-02-27 21:46:31 +08:00
|
|
|
// CHECK: br i1 {{.*}}, label %[[DELETE_NULL:.*]], label %[[DELETE_NOTNULL:.*]]
|
|
|
|
|
|
|
|
// CHECK: [[DELETE_NOTNULL]]
|
2014-11-01 04:09:12 +08:00
|
|
|
// CHECK-NEXT: %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to i8* (%"struct.basic::C"*, i32)***
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK-NEXT: %[[VTABLE:.*]] = load i8* (%"struct.basic::C"*, i32)**, i8* (%"struct.basic::C"*, i32)*** %[[PVTABLE]]
|
2015-02-28 03:18:17 +08:00
|
|
|
// CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds i8* (%"struct.basic::C"*, i32)*, i8* (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK-NEXT: %[[VDTOR:.*]] = load i8* (%"struct.basic::C"*, i32)*, i8* (%"struct.basic::C"*, i32)** %[[PVDTOR]]
|
2014-11-01 04:09:12 +08:00
|
|
|
// CHECK-NEXT: call x86_thiscallcc i8* %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i32 1)
|
|
|
|
// CHECK: ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
void call_deleting_dtor_and_global_delete(C *obj_ptr) {
|
|
|
|
// CHECK: define void @"\01?call_deleting_dtor_and_global_delete@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
|
|
|
|
::delete obj_ptr;
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK: %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"*, %"struct.basic::C"** %{{.*}}, align 4
|
2014-11-01 04:09:12 +08:00
|
|
|
// CHECK: br i1 {{.*}}, label %[[DELETE_NULL:.*]], label %[[DELETE_NOTNULL:.*]]
|
|
|
|
|
|
|
|
// CHECK: [[DELETE_NOTNULL]]
|
|
|
|
// CHECK-NEXT: %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to i8* (%"struct.basic::C"*, i32)***
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK-NEXT: %[[VTABLE:.*]] = load i8* (%"struct.basic::C"*, i32)**, i8* (%"struct.basic::C"*, i32)*** %[[PVTABLE]]
|
2015-02-28 03:18:17 +08:00
|
|
|
// CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds i8* (%"struct.basic::C"*, i32)*, i8* (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK-NEXT: %[[VDTOR:.*]] = load i8* (%"struct.basic::C"*, i32)*, i8* (%"struct.basic::C"*, i32)** %[[PVDTOR]]
|
2014-11-01 04:09:12 +08:00
|
|
|
// CHECK-NEXT: %[[CALL:.*]] = call x86_thiscallcc i8* %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i32 0)
|
|
|
|
// CHECK-NEXT: call void @"\01??3@YAXPAX@Z"(i8* %[[CALL]])
|
2013-02-15 22:45:22 +08:00
|
|
|
// CHECK: ret void
|
2013-02-13 16:37:51 +08:00
|
|
|
}
|
|
|
|
|
2013-02-27 21:46:31 +08:00
|
|
|
struct D {
|
2013-02-13 16:37:51 +08:00
|
|
|
static int foo();
|
|
|
|
|
2013-02-27 21:46:31 +08:00
|
|
|
D() {
|
2013-02-13 16:37:51 +08:00
|
|
|
static int ctor_static = foo();
|
|
|
|
// CHECK that the static in the ctor gets mangled correctly:
|
2013-02-27 21:46:31 +08:00
|
|
|
// CHECK: @"\01?ctor_static@?1???0D@basic@@QAE@XZ@4HA"
|
2013-02-13 16:37:51 +08:00
|
|
|
}
|
2013-02-27 21:46:31 +08:00
|
|
|
~D() {
|
2013-02-13 16:37:51 +08:00
|
|
|
static int dtor_static = foo();
|
|
|
|
// CHECK that the static in the dtor gets mangled correctly:
|
2013-02-27 21:46:31 +08:00
|
|
|
// CHECK: @"\01?dtor_static@?1???1D@basic@@QAE@XZ@4HA"
|
2013-02-13 16:37:51 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-02-27 21:46:31 +08:00
|
|
|
void use_D() { D c; }
|
2013-02-22 17:10:20 +08:00
|
|
|
|
2013-02-27 21:46:31 +08:00
|
|
|
} // end namespace basic
|
|
|
|
|
2014-02-19 06:51:52 +08:00
|
|
|
namespace dtor_in_second_nvbase {
|
|
|
|
|
|
|
|
struct A {
|
|
|
|
virtual void f(); // A needs vftable to be primary.
|
|
|
|
};
|
|
|
|
struct B {
|
|
|
|
virtual ~B();
|
|
|
|
};
|
|
|
|
struct C : A, B {
|
|
|
|
virtual ~C();
|
|
|
|
};
|
|
|
|
|
|
|
|
C::~C() {
|
|
|
|
// CHECK-LABEL: define x86_thiscallcc void @"\01??1C@dtor_in_second_nvbase@@UAE@XZ"
|
|
|
|
// CHECK: (%"struct.dtor_in_second_nvbase::C"* %this)
|
|
|
|
// No this adjustment!
|
|
|
|
// CHECK-NOT: getelementptr
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK: load %"struct.dtor_in_second_nvbase::C"*, %"struct.dtor_in_second_nvbase::C"** %{{.*}}
|
2014-02-19 06:51:52 +08:00
|
|
|
// Now we this-adjust before calling ~B.
|
|
|
|
// CHECK: bitcast %"struct.dtor_in_second_nvbase::C"* %{{.*}} to i8*
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
// CHECK: getelementptr inbounds i8, i8* %{{.*}}, i32 4
|
2014-02-19 06:51:52 +08:00
|
|
|
// CHECK: bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::B"*
|
|
|
|
// CHECK: call x86_thiscallcc void @"\01??1B@dtor_in_second_nvbase@@UAE@XZ"
|
|
|
|
// CHECK: (%"struct.dtor_in_second_nvbase::B"* %{{.*}})
|
|
|
|
// CHECK: ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
void foo() {
|
|
|
|
C c;
|
|
|
|
}
|
2014-11-01 04:09:12 +08:00
|
|
|
// DTORS2-LABEL: define linkonce_odr x86_thiscallcc i8* @"\01??_EC@dtor_in_second_nvbase@@W3AEPAXI@Z"
|
2014-02-19 06:51:52 +08:00
|
|
|
// DTORS2: (%"struct.dtor_in_second_nvbase::C"* %this, i32 %should_call_delete)
|
|
|
|
// Do an adjustment from B* to C*.
|
2015-02-28 03:18:17 +08:00
|
|
|
// DTORS2: getelementptr i8, i8* %{{.*}}, i32 -4
|
2014-02-19 06:51:52 +08:00
|
|
|
// DTORS2: bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::C"*
|
2015-08-06 19:57:15 +08:00
|
|
|
// DTORS2: %[[CALL:.*]] = tail call x86_thiscallcc i8* @"\01??_GC@dtor_in_second_nvbase@@UAEPAXI@Z"
|
2014-11-01 04:09:12 +08:00
|
|
|
// DTORS2: ret i8* %[[CALL]]
|
2014-02-19 06:51:52 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace test2 {
|
|
|
|
// Just like dtor_in_second_nvbase, except put that in a vbase of a diamond.
|
|
|
|
|
|
|
|
// C's dtor is in the non-primary base.
|
|
|
|
struct A { virtual void f(); };
|
|
|
|
struct B { virtual ~B(); };
|
|
|
|
struct C : A, B { virtual ~C(); int c; };
|
|
|
|
|
|
|
|
// Diamond hierarchy, with C as the shared vbase.
|
|
|
|
struct D : virtual C { int d; };
|
|
|
|
struct E : virtual C { int e; };
|
|
|
|
struct F : D, E { ~F(); int f; };
|
|
|
|
|
|
|
|
F::~F() {
|
2016-09-08 02:21:30 +08:00
|
|
|
// CHECK-LABEL: define x86_thiscallcc void @"\01??1F@test2@@UAE@XZ"(%"struct.test2::F"*{{[^,]*}})
|
2014-02-19 06:51:52 +08:00
|
|
|
// Do an adjustment from C vbase subobject to F as though F was the
|
|
|
|
// complete type.
|
2015-02-28 03:18:17 +08:00
|
|
|
// CHECK: getelementptr inbounds i8, i8* %{{.*}}, i32 -20
|
2014-02-19 06:51:52 +08:00
|
|
|
// CHECK: bitcast i8* %{{.*}} to %"struct.test2::F"*
|
|
|
|
// CHECK: store %"struct.test2::F"*
|
|
|
|
}
|
|
|
|
|
|
|
|
void foo() {
|
|
|
|
F f;
|
|
|
|
}
|
2017-02-14 08:54:11 +08:00
|
|
|
// DTORS3-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_DF@test2@@QAEXXZ"({{.*}} {{.*}} comdat
|
2014-02-19 06:51:52 +08:00
|
|
|
// Do an adjustment from C* to F*.
|
2015-02-28 03:18:17 +08:00
|
|
|
// DTORS3: getelementptr i8, i8* %{{.*}}, i32 20
|
2014-02-19 06:51:52 +08:00
|
|
|
// DTORS3: bitcast i8* %{{.*}} to %"struct.test2::F"*
|
|
|
|
// DTORS3: call x86_thiscallcc void @"\01??1F@test2@@UAE@XZ"
|
|
|
|
// DTORS3: ret void
|
|
|
|
|
|
|
|
}
|
2013-02-27 21:46:31 +08:00
|
|
|
|
|
|
|
namespace constructors {
|
|
|
|
|
|
|
|
struct A {
|
|
|
|
A() {}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct B : A {
|
|
|
|
B();
|
|
|
|
~B();
|
|
|
|
};
|
|
|
|
|
|
|
|
B::B() {
|
2013-07-01 04:40:16 +08:00
|
|
|
// CHECK: define x86_thiscallcc %"struct.constructors::B"* @"\01??0B@constructors@@QAE@XZ"(%"struct.constructors::B"* returned %this)
|
2013-02-27 21:46:31 +08:00
|
|
|
// CHECK: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
|
|
|
|
// CHECK: ret
|
|
|
|
}
|
|
|
|
|
|
|
|
struct C : virtual A {
|
|
|
|
C();
|
|
|
|
};
|
|
|
|
|
|
|
|
C::C() {
|
2013-07-01 04:40:16 +08:00
|
|
|
// CHECK: define x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* returned %this, i32 %is_most_derived)
|
2013-02-27 21:46:31 +08:00
|
|
|
// TODO: make sure this works in the Release build too;
|
|
|
|
// CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, i32* %[[IS_MOST_DERIVED_VAR]]
|
2013-02-27 21:46:31 +08:00
|
|
|
// CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
|
|
|
|
// CHECK: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
|
|
|
|
//
|
|
|
|
// CHECK: [[INIT_VBASES]]
|
2013-06-19 23:20:38 +08:00
|
|
|
// CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::C"* %{{.*}} to i8*
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
// CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 0
|
2014-10-23 01:26:00 +08:00
|
|
|
// CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32**
|
2015-03-14 02:21:46 +08:00
|
|
|
// CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"\01??_8C@constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]]
|
2013-10-12 04:19:00 +08:00
|
|
|
// CHECK-NEXT: bitcast %"struct.constructors::C"* %{{.*}} to i8*
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
// CHECK-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i32 4
|
2013-10-12 04:19:00 +08:00
|
|
|
// CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*
|
2013-02-27 21:46:31 +08:00
|
|
|
// CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
|
|
|
|
// CHECK-NEXT: br label %[[SKIP_VBASES]]
|
|
|
|
//
|
|
|
|
// CHECK: [[SKIP_VBASES]]
|
2013-09-27 22:48:01 +08:00
|
|
|
// Class C does not define or override methods, so shouldn't change the vfptr.
|
|
|
|
// CHECK-NOT: @"\01??_7C@constructors@@6B@"
|
2013-02-27 21:46:31 +08:00
|
|
|
// CHECK: ret
|
|
|
|
}
|
|
|
|
|
|
|
|
void create_C() {
|
|
|
|
C c;
|
|
|
|
// CHECK: define void @"\01?create_C@constructors@@YAXXZ"()
|
|
|
|
// CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %c, i32 1)
|
|
|
|
// CHECK: ret
|
|
|
|
}
|
|
|
|
|
|
|
|
struct D : C {
|
|
|
|
D();
|
|
|
|
};
|
|
|
|
|
|
|
|
D::D() {
|
2013-07-01 04:40:16 +08:00
|
|
|
// CHECK: define x86_thiscallcc %"struct.constructors::D"* @"\01??0D@constructors@@QAE@XZ"(%"struct.constructors::D"* returned %this, i32 %is_most_derived) unnamed_addr
|
2013-02-27 21:46:31 +08:00
|
|
|
// CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, i32* %[[IS_MOST_DERIVED_VAR]]
|
2013-02-27 21:46:31 +08:00
|
|
|
// CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
|
|
|
|
// CHECK: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
|
|
|
|
//
|
|
|
|
// CHECK: [[INIT_VBASES]]
|
2013-06-19 23:20:38 +08:00
|
|
|
// CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::D"* %{{.*}} to i8*
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
// CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 0
|
2014-10-23 01:26:00 +08:00
|
|
|
// CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32**
|
2015-03-14 02:21:46 +08:00
|
|
|
// CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"\01??_8D@constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]]
|
2013-10-12 04:19:00 +08:00
|
|
|
// CHECK-NEXT: bitcast %"struct.constructors::D"* %{{.*}} to i8*
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
// CHECK-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i32 4
|
2013-10-12 04:19:00 +08:00
|
|
|
// CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*
|
2013-02-27 21:46:31 +08:00
|
|
|
// CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
|
|
|
|
// CHECK-NEXT: br label %[[SKIP_VBASES]]
|
|
|
|
//
|
|
|
|
// CHECK: [[SKIP_VBASES]]
|
|
|
|
// CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %{{.*}}, i32 0)
|
|
|
|
// CHECK: ret
|
|
|
|
}
|
|
|
|
|
|
|
|
struct E : virtual C {
|
|
|
|
E();
|
|
|
|
};
|
|
|
|
|
|
|
|
E::E() {
|
2013-07-01 04:40:16 +08:00
|
|
|
// CHECK: define x86_thiscallcc %"struct.constructors::E"* @"\01??0E@constructors@@QAE@XZ"(%"struct.constructors::E"* returned %this, i32 %is_most_derived) unnamed_addr
|
2013-02-27 21:46:31 +08:00
|
|
|
// CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, i32* %[[IS_MOST_DERIVED_VAR]]
|
2013-02-27 21:46:31 +08:00
|
|
|
// CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
|
|
|
|
// CHECK: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
|
|
|
|
//
|
|
|
|
// CHECK: [[INIT_VBASES]]
|
2013-06-19 23:20:38 +08:00
|
|
|
// CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::E"* %{{.*}} to i8*
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
// CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 0
|
2014-10-23 01:26:00 +08:00
|
|
|
// CHECK-NEXT: %[[vbptr_E:.*]] = bitcast i8* %[[offs]] to i32**
|
2015-03-14 02:21:46 +08:00
|
|
|
// CHECK-NEXT: store i32* getelementptr inbounds ([3 x i32], [3 x i32]* @"\01??_8E@constructors@@7B01@@", i32 0, i32 0), i32** %[[vbptr_E]]
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
// CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 4
|
2014-10-23 01:26:00 +08:00
|
|
|
// CHECK-NEXT: %[[vbptr_C:.*]] = bitcast i8* %[[offs]] to i32**
|
2015-03-14 02:21:46 +08:00
|
|
|
// CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"\01??_8E@constructors@@7BC@1@@", i32 0, i32 0), i32** %[[vbptr_C]]
|
2013-10-12 04:19:00 +08:00
|
|
|
// CHECK-NEXT: bitcast %"struct.constructors::E"* %{{.*}} to i8*
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
// CHECK-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i32 4
|
2013-10-12 04:19:00 +08:00
|
|
|
// CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*
|
2013-02-27 21:46:31 +08:00
|
|
|
// CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
|
|
|
|
// CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %{{.*}}, i32 0)
|
|
|
|
// CHECK-NEXT: br label %[[SKIP_VBASES]]
|
|
|
|
//
|
|
|
|
// CHECK: [[SKIP_VBASES]]
|
|
|
|
// CHECK: ret
|
|
|
|
}
|
|
|
|
|
2013-08-05 01:30:04 +08:00
|
|
|
// PR16735 - even abstract classes should have a constructor emitted.
|
|
|
|
struct F {
|
|
|
|
F();
|
|
|
|
virtual void f() = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
F::F() {}
|
|
|
|
// CHECK: define x86_thiscallcc %"struct.constructors::F"* @"\01??0F@constructors@@QAE@XZ"
|
|
|
|
|
2013-02-27 21:46:31 +08:00
|
|
|
} // end namespace constructors
|
[ms-cxxabi] Emit linkonce complete dtors in TUs that need them
Based on Peter Collingbourne's destructor patches.
Prior to this change, clang was considering ?1 to be the complete
destructor and the base destructor, which was wrong. This lead to
crashes when clang tried to emit two LLVM functions with the same name.
In this ABI, TUs with non-inline dtors might not emit a complete
destructor. They are emitted as inline thunks in TUs that need them,
and they always delegate to the base dtors of the complete class and its
virtual bases. This change uses the DeferredDecls machinery to emit
complete dtors as needed.
Currently in clang try body destructors can catch exceptions thrown by
virtual base destructors. In the Microsoft C++ ABI, clang may not have
the destructor definition, in which case clang won't wrap the virtual
virtual base destructor calls in a try-catch. Diagnosing this in user
code is TODO.
Finally, for classes that don't use virtual inheritance, MSVC always
calls the base destructor (?1) directly. This is a useful code size
optimization that avoids emitting lots of extra thunks or aliases.
Implementing it also means our existing tests continue to pass, and is
consistent with MSVC's output.
We can do the same for Itanium by tweaking GetAddrOfCXXDestructor, but
it will require further testing.
Reviewers: rjmccall
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1066
llvm-svn: 186828
2013-07-22 21:51:44 +08:00
|
|
|
|
|
|
|
namespace dtors {
|
|
|
|
|
|
|
|
struct A {
|
|
|
|
~A();
|
|
|
|
};
|
|
|
|
|
|
|
|
void call_nv_complete(A *a) {
|
|
|
|
a->~A();
|
|
|
|
// CHECK: define void @"\01?call_nv_complete@dtors@@YAXPAUA@1@@Z"
|
|
|
|
// CHECK: call x86_thiscallcc void @"\01??1A@dtors@@QAE@XZ"
|
|
|
|
// CHECK: ret
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK: declare x86_thiscallcc void @"\01??1A@dtors@@QAE@XZ"
|
|
|
|
|
|
|
|
// Now try some virtual bases, where we need the complete dtor.
|
|
|
|
|
|
|
|
struct B : virtual A { ~B(); };
|
|
|
|
struct C : virtual A { ~C(); };
|
|
|
|
struct D : B, C { ~D(); };
|
|
|
|
|
|
|
|
void call_vbase_complete(D *d) {
|
|
|
|
d->~D();
|
|
|
|
// CHECK: define void @"\01?call_vbase_complete@dtors@@YAXPAUD@1@@Z"
|
2017-02-14 08:54:11 +08:00
|
|
|
// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}})
|
[ms-cxxabi] Emit linkonce complete dtors in TUs that need them
Based on Peter Collingbourne's destructor patches.
Prior to this change, clang was considering ?1 to be the complete
destructor and the base destructor, which was wrong. This lead to
crashes when clang tried to emit two LLVM functions with the same name.
In this ABI, TUs with non-inline dtors might not emit a complete
destructor. They are emitted as inline thunks in TUs that need them,
and they always delegate to the base dtors of the complete class and its
virtual bases. This change uses the DeferredDecls machinery to emit
complete dtors as needed.
Currently in clang try body destructors can catch exceptions thrown by
virtual base destructors. In the Microsoft C++ ABI, clang may not have
the destructor definition, in which case clang won't wrap the virtual
virtual base destructor calls in a try-catch. Diagnosing this in user
code is TODO.
Finally, for classes that don't use virtual inheritance, MSVC always
calls the base destructor (?1) directly. This is a useful code size
optimization that avoids emitting lots of extra thunks or aliases.
Implementing it also means our existing tests continue to pass, and is
consistent with MSVC's output.
We can do the same for Itanium by tweaking GetAddrOfCXXDestructor, but
it will require further testing.
Reviewers: rjmccall
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1066
llvm-svn: 186828
2013-07-22 21:51:44 +08:00
|
|
|
// CHECK: ret
|
|
|
|
}
|
|
|
|
|
|
|
|
// The complete dtor should call the base dtors for D and the vbase A (once).
|
2017-02-14 08:54:11 +08:00
|
|
|
// CHECK: define linkonce_odr x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"({{.*}}) {{.*}} comdat
|
[ms-cxxabi] Emit linkonce complete dtors in TUs that need them
Based on Peter Collingbourne's destructor patches.
Prior to this change, clang was considering ?1 to be the complete
destructor and the base destructor, which was wrong. This lead to
crashes when clang tried to emit two LLVM functions with the same name.
In this ABI, TUs with non-inline dtors might not emit a complete
destructor. They are emitted as inline thunks in TUs that need them,
and they always delegate to the base dtors of the complete class and its
virtual bases. This change uses the DeferredDecls machinery to emit
complete dtors as needed.
Currently in clang try body destructors can catch exceptions thrown by
virtual base destructors. In the Microsoft C++ ABI, clang may not have
the destructor definition, in which case clang won't wrap the virtual
virtual base destructor calls in a try-catch. Diagnosing this in user
code is TODO.
Finally, for classes that don't use virtual inheritance, MSVC always
calls the base destructor (?1) directly. This is a useful code size
optimization that avoids emitting lots of extra thunks or aliases.
Implementing it also means our existing tests continue to pass, and is
consistent with MSVC's output.
We can do the same for Itanium by tweaking GetAddrOfCXXDestructor, but
it will require further testing.
Reviewers: rjmccall
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1066
llvm-svn: 186828
2013-07-22 21:51:44 +08:00
|
|
|
// CHECK-NOT: call
|
|
|
|
// CHECK: call x86_thiscallcc void @"\01??1D@dtors@@QAE@XZ"
|
|
|
|
// CHECK-NOT: call
|
|
|
|
// CHECK: call x86_thiscallcc void @"\01??1A@dtors@@QAE@XZ"
|
|
|
|
// CHECK-NOT: call
|
|
|
|
// CHECK: ret
|
|
|
|
|
|
|
|
void destroy_d_complete() {
|
|
|
|
D d;
|
|
|
|
// CHECK: define void @"\01?destroy_d_complete@dtors@@YAXXZ"
|
2017-02-14 08:54:11 +08:00
|
|
|
// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}})
|
[ms-cxxabi] Emit linkonce complete dtors in TUs that need them
Based on Peter Collingbourne's destructor patches.
Prior to this change, clang was considering ?1 to be the complete
destructor and the base destructor, which was wrong. This lead to
crashes when clang tried to emit two LLVM functions with the same name.
In this ABI, TUs with non-inline dtors might not emit a complete
destructor. They are emitted as inline thunks in TUs that need them,
and they always delegate to the base dtors of the complete class and its
virtual bases. This change uses the DeferredDecls machinery to emit
complete dtors as needed.
Currently in clang try body destructors can catch exceptions thrown by
virtual base destructors. In the Microsoft C++ ABI, clang may not have
the destructor definition, in which case clang won't wrap the virtual
virtual base destructor calls in a try-catch. Diagnosing this in user
code is TODO.
Finally, for classes that don't use virtual inheritance, MSVC always
calls the base destructor (?1) directly. This is a useful code size
optimization that avoids emitting lots of extra thunks or aliases.
Implementing it also means our existing tests continue to pass, and is
consistent with MSVC's output.
We can do the same for Itanium by tweaking GetAddrOfCXXDestructor, but
it will require further testing.
Reviewers: rjmccall
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1066
llvm-svn: 186828
2013-07-22 21:51:44 +08:00
|
|
|
// CHECK: ret
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: Clang manually inlines the deletion, so we don't get a call to the
|
|
|
|
// deleting dtor (_G). The only way to call deleting dtors currently is through
|
|
|
|
// a vftable.
|
|
|
|
void call_nv_deleting_dtor(D *d) {
|
|
|
|
delete d;
|
|
|
|
// CHECK: define void @"\01?call_nv_deleting_dtor@dtors@@YAXPAUD@1@@Z"
|
2017-02-14 08:54:11 +08:00
|
|
|
// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}})
|
[ms-cxxabi] Emit linkonce complete dtors in TUs that need them
Based on Peter Collingbourne's destructor patches.
Prior to this change, clang was considering ?1 to be the complete
destructor and the base destructor, which was wrong. This lead to
crashes when clang tried to emit two LLVM functions with the same name.
In this ABI, TUs with non-inline dtors might not emit a complete
destructor. They are emitted as inline thunks in TUs that need them,
and they always delegate to the base dtors of the complete class and its
virtual bases. This change uses the DeferredDecls machinery to emit
complete dtors as needed.
Currently in clang try body destructors can catch exceptions thrown by
virtual base destructors. In the Microsoft C++ ABI, clang may not have
the destructor definition, in which case clang won't wrap the virtual
virtual base destructor calls in a try-catch. Diagnosing this in user
code is TODO.
Finally, for classes that don't use virtual inheritance, MSVC always
calls the base destructor (?1) directly. This is a useful code size
optimization that avoids emitting lots of extra thunks or aliases.
Implementing it also means our existing tests continue to pass, and is
consistent with MSVC's output.
We can do the same for Itanium by tweaking GetAddrOfCXXDestructor, but
it will require further testing.
Reviewers: rjmccall
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1066
llvm-svn: 186828
2013-07-22 21:51:44 +08:00
|
|
|
// CHECK: call void @"\01??3@YAXPAX@Z"
|
|
|
|
// CHECK: ret
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2013-12-12 03:21:27 +08:00
|
|
|
|
2013-12-18 03:46:40 +08:00
|
|
|
namespace test1 {
|
|
|
|
struct A { };
|
|
|
|
struct B : virtual A {
|
|
|
|
B(int *a);
|
|
|
|
B(const char *a, ...);
|
|
|
|
__cdecl B(short *a);
|
|
|
|
};
|
|
|
|
B::B(int *a) {}
|
|
|
|
B::B(const char *a, ...) {}
|
|
|
|
B::B(short *a) {}
|
|
|
|
// CHECK: define x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAH@Z"
|
|
|
|
// CHECK: (%"struct.test1::B"* returned %this, i32* %a, i32 %is_most_derived)
|
|
|
|
// CHECK: define %"struct.test1::B"* @"\01??0B@test1@@QAA@PBDZZ"
|
|
|
|
// CHECK: (%"struct.test1::B"* returned %this, i32 %is_most_derived, i8* %a, ...)
|
2015-09-15 05:29:57 +08:00
|
|
|
// CHECK: define x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAF@Z"
|
2013-12-18 03:46:40 +08:00
|
|
|
// CHECK: (%"struct.test1::B"* returned %this, i16* %a, i32 %is_most_derived)
|
|
|
|
|
|
|
|
void construct_b() {
|
|
|
|
int a;
|
|
|
|
B b1(&a);
|
|
|
|
B b2("%d %d", 1, 2);
|
|
|
|
}
|
|
|
|
// CHECK-LABEL: define void @"\01?construct_b@test1@@YAXXZ"()
|
|
|
|
// CHECK: call x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAH@Z"
|
|
|
|
// CHECK: (%"struct.test1::B"* {{.*}}, i32* {{.*}}, i32 1)
|
2015-04-17 07:25:00 +08:00
|
|
|
// CHECK: call %"struct.test1::B"* (%"struct.test1::B"*, i32, i8*, ...) @"\01??0B@test1@@QAA@PBDZZ"
|
2013-12-18 03:46:40 +08:00
|
|
|
// CHECK: (%"struct.test1::B"* {{.*}}, i32 1, i8* {{.*}}, i32 1, i32 2)
|
|
|
|
}
|
|
|
|
|
2014-07-18 09:48:10 +08:00
|
|
|
namespace implicit_copy_vtable {
|
|
|
|
// This was a crash that only reproduced in ABIs without key functions.
|
|
|
|
struct ImplicitCopy {
|
|
|
|
// implicit copy ctor
|
|
|
|
virtual ~ImplicitCopy();
|
|
|
|
};
|
|
|
|
void CreateCopy(ImplicitCopy *a) {
|
|
|
|
new ImplicitCopy(*a);
|
|
|
|
}
|
|
|
|
// CHECK: store {{.*}} @"\01??_7ImplicitCopy@implicit_copy_vtable@@6B@"
|
|
|
|
|
|
|
|
struct MoveOnly {
|
|
|
|
MoveOnly(MoveOnly &&o) = default;
|
|
|
|
virtual ~MoveOnly();
|
|
|
|
};
|
|
|
|
MoveOnly &&f();
|
|
|
|
void g() { new MoveOnly(f()); }
|
|
|
|
// CHECK: store {{.*}} @"\01??_7MoveOnly@implicit_copy_vtable@@6B@"
|
|
|
|
}
|
|
|
|
|
2016-05-14 04:05:09 +08:00
|
|
|
namespace delegating_ctor {
|
|
|
|
struct Y {};
|
|
|
|
struct X : virtual Y {
|
|
|
|
X(int);
|
|
|
|
X();
|
|
|
|
};
|
|
|
|
X::X(int) : X() {}
|
|
|
|
}
|
|
|
|
// CHECK: define x86_thiscallcc %"struct.delegating_ctor::X"* @"\01??0X@delegating_ctor@@QAE@H@Z"(
|
|
|
|
// CHECK: %[[is_most_derived_addr:.*]] = alloca i32, align 4
|
|
|
|
// CHECK: store i32 %is_most_derived, i32* %[[is_most_derived_addr]]
|
|
|
|
// CHECK: %[[is_most_derived:.*]] = load i32, i32* %[[is_most_derived_addr]]
|
|
|
|
// CHECK: call x86_thiscallcc {{.*}}* @"\01??0X@delegating_ctor@@QAE@XZ"({{.*}} i32 %[[is_most_derived]])
|
|
|
|
|
2013-12-12 03:21:27 +08:00
|
|
|
// Dtor thunks for classes in anonymous namespaces should be internal, not
|
|
|
|
// linkonce_odr.
|
|
|
|
namespace {
|
|
|
|
struct A {
|
|
|
|
virtual ~A() { }
|
|
|
|
};
|
|
|
|
}
|
|
|
|
void *getA() {
|
|
|
|
return (void*)new A();
|
|
|
|
}
|
2014-11-01 04:09:12 +08:00
|
|
|
// CHECK: define internal x86_thiscallcc i8* @"\01??_GA@?A@@UAEPAXI@Z"
|
2014-04-02 13:58:29 +08:00
|
|
|
// CHECK: (%"struct.(anonymous namespace)::A"* %this, i32 %should_call_delete)
|
2013-12-12 03:21:27 +08:00
|
|
|
// CHECK: define internal x86_thiscallcc void @"\01??1A@?A@@UAE@XZ"
|
2014-04-02 13:58:29 +08:00
|
|
|
// CHECK: (%"struct.(anonymous namespace)::A"* %this)
|
2015-09-15 05:29:57 +08:00
|
|
|
|
|
|
|
// Check that we correctly transform __stdcall to __thiscall for ctors and
|
|
|
|
// dtors.
|
|
|
|
class G {
|
|
|
|
public:
|
|
|
|
__stdcall G() {};
|
|
|
|
// DTORS4: define linkonce_odr x86_thiscallcc %class.G* @"\01??0G@@QAE@XZ"
|
|
|
|
__stdcall ~G() {};
|
|
|
|
// DTORS4: define linkonce_odr x86_thiscallcc void @"\01??1G@@QAE@XZ"
|
|
|
|
};
|
|
|
|
|
|
|
|
extern void testG() {
|
|
|
|
G g;
|
|
|
|
}
|