This patch makes the dead_on_return parameter attribute optionally require a number
of bytes to be passed in to specify the number of bytes known to be dead
upon function return/unwind. This is aimed at enabling annotating the
this pointer in C++ destructors with dead_on_return in clang. We need
this to handle cases like the following:
```
struct X {
int n;
~X() {
this[n].n = 0;
}
};
void f() {
X xs[] = {42, -1};
}
```
Where we only certain that sizeof(X) bytes are dead upon return of ~X.
Otherwise DSE would be able to eliminate the store in ~X which would not
be correct.
This patch only does the wiring within IR. Future patches will make
clang emit correct sizing information and update DSE to only delete
stores to objects marked dead_on_return that are provably in bounds of
the number of bytes specified to be dead_on_return.
Reviewers: nikic, alinas, antoniofrighetto
Pull Request: https://github.com/llvm/llvm-project/pull/171712
77 lines
3.4 KiB
C++
77 lines
3.4 KiB
C++
// RUN: %clang_cc1 -mconstructor-aliases -std=c++11 -fexceptions -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s -check-prefix=X86
|
|
// RUN: %clang_cc1 -mconstructor-aliases -std=c++11 -fexceptions -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck %s -check-prefix=X64
|
|
|
|
struct A {
|
|
A(int a);
|
|
A(const A &o);
|
|
~A();
|
|
int a;
|
|
};
|
|
|
|
void foo(A a, A b, A c) {
|
|
}
|
|
|
|
// Order of destruction should be left to right.
|
|
//
|
|
// X86-LABEL: define dso_local void @"?foo@@YAXUA@@00@Z"
|
|
// X86: (ptr inalloca([[argmem_ty:<{ %struct.A, %struct.A, %struct.A }>]]) %0)
|
|
// X86: %[[a:[^ ]*]] = getelementptr inbounds nuw [[argmem_ty]], ptr %0, i32 0, i32 0
|
|
// X86: %[[b:[^ ]*]] = getelementptr inbounds nuw [[argmem_ty]], ptr %0, i32 0, i32 1
|
|
// X86: %[[c:[^ ]*]] = getelementptr inbounds nuw [[argmem_ty]], ptr %0, i32 0, i32 2
|
|
// X86: call x86_thiscallcc void @"??1A@@QAE@XZ"(ptr {{[^,]*}} %[[a]])
|
|
// X86: call x86_thiscallcc void @"??1A@@QAE@XZ"(ptr {{[^,]*}} %[[b]])
|
|
// X86: call x86_thiscallcc void @"??1A@@QAE@XZ"(ptr {{[^,]*}} %[[c]])
|
|
// X86: ret void
|
|
|
|
// X64-LABEL: define dso_local void @"?foo@@YAXUA@@00@Z"
|
|
// X64: (ptr noundef dead_on_return %[[a:[^,]*]], ptr noundef dead_on_return %[[b:[^,]*]], ptr noundef dead_on_return %[[c:[^)]*]])
|
|
// X64: call void @"??1A@@QEAA@XZ"(ptr {{[^,]*}} %[[a]])
|
|
// X64: call void @"??1A@@QEAA@XZ"(ptr {{[^,]*}} %[[b]])
|
|
// X64: call void @"??1A@@QEAA@XZ"(ptr {{[^,]*}} %[[c]])
|
|
// X64: ret void
|
|
|
|
|
|
void call_foo() {
|
|
foo(A(1), A(2), A(3));
|
|
}
|
|
|
|
// Order of evaluation should be right to left, and we should clean up the right
|
|
// things as we unwind.
|
|
//
|
|
// X86-LABEL: define dso_local void @"?call_foo@@YAXXZ"()
|
|
// X86: call ptr @llvm.stacksave.p0()
|
|
// X86: %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty]]
|
|
// X86: %[[arg3:[^ ]*]] = getelementptr inbounds nuw [[argmem_ty]], ptr %[[argmem]], i32 0, i32 2
|
|
// X86: call x86_thiscallcc noundef ptr @"??0A@@QAE@H@Z"(ptr {{[^,]*}} %[[arg3]], i32 noundef 3)
|
|
// X86: %[[arg2:[^ ]*]] = getelementptr inbounds nuw [[argmem_ty]], ptr %[[argmem]], i32 0, i32 1
|
|
// X86: invoke x86_thiscallcc noundef ptr @"??0A@@QAE@H@Z"(ptr {{[^,]*}} %[[arg2]], i32 noundef 2)
|
|
// X86: %[[arg1:[^ ]*]] = getelementptr inbounds nuw [[argmem_ty]], ptr %[[argmem]], i32 0, i32 0
|
|
// X86: invoke x86_thiscallcc noundef ptr @"??0A@@QAE@H@Z"(ptr {{[^,]*}} %[[arg1]], i32 noundef 1)
|
|
// X86: call void @"?foo@@YAXUA@@00@Z"(ptr inalloca([[argmem_ty]]) %[[argmem]])
|
|
// X86: call void @llvm.stackrestore.p0
|
|
// X86: ret void
|
|
//
|
|
// lpad2:
|
|
// X86: cleanuppad within none []
|
|
// X86: call x86_thiscallcc void @"??1A@@QAE@XZ"(ptr {{[^,]*}} %[[arg2]])
|
|
// X86: cleanupret
|
|
//
|
|
// ehcleanup:
|
|
// X86: call x86_thiscallcc void @"??1A@@QAE@XZ"(ptr {{[^,]*}} %[[arg3]])
|
|
|
|
// X64-LABEL: define dso_local void @"?call_foo@@YAXXZ"()
|
|
// X64: call noundef ptr @"??0A@@QEAA@H@Z"(ptr {{[^,]*}} %[[arg3:[^,]*]], i32 noundef 3)
|
|
// X64: invoke noundef ptr @"??0A@@QEAA@H@Z"(ptr {{[^,]*}} %[[arg2:[^,]*]], i32 noundef 2)
|
|
// X64: invoke noundef ptr @"??0A@@QEAA@H@Z"(ptr {{[^,]*}} %[[arg1:[^,]*]], i32 noundef 1)
|
|
// X64: call void @"?foo@@YAXUA@@00@Z"
|
|
// X64: (ptr noundef dead_on_return %[[arg1]], ptr noundef dead_on_return %[[arg2]], ptr noundef dead_on_return %[[arg3]])
|
|
// X64: ret void
|
|
//
|
|
// lpad2:
|
|
// X64: cleanuppad within none []
|
|
// X64: call void @"??1A@@QEAA@XZ"(ptr {{[^,]*}} %[[arg2]])
|
|
// X64: cleanupret
|
|
//
|
|
// ehcleanup:
|
|
// X64: call void @"??1A@@QEAA@XZ"(ptr {{[^,]*}} %[[arg3]])
|