aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2009-11-10 19:24:06 +0000
committerFariborz Jahanian <fjahanian@apple.com>2009-11-10 19:24:06 +0000
commit88f4280f6b60edcbdea6a38a3da8b17d66473ad6 (patch)
treefebcfc7a00862cbe41dcb3b5a43c8337b9ffe5d2
parent0854d70dabe11d9b3df6c4b65b9b53a1fd65739e (diff)
This patch implements Code gen. for destruction of
global array of objects. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86701 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/CGCXX.cpp70
-rw-r--r--lib/CodeGen/CodeGenFunction.h6
-rw-r--r--test/CodeGenCXX/global-array-destruction.cpp33
3 files changed, 101 insertions, 8 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 56b38e57e3..bb8041f567 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -27,7 +27,7 @@ using namespace clang;
using namespace CodeGen;
void
-CodeGenFunction::EmitCXXGlobalDtorRegistration(const CXXDestructorDecl *Dtor,
+CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
llvm::Constant *DeclPtr) {
const llvm::Type *Int8PtrTy =
llvm::Type::getInt8Ty(VMContext)->getPointerTo();
@@ -55,9 +55,6 @@ CodeGenFunction::EmitCXXGlobalDtorRegistration(const CXXDestructorDecl *Dtor,
llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy,
"__dso_handle");
-
- llvm::Constant *DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete);
-
llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy),
llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy),
llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) };
@@ -82,11 +79,26 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
} else {
EmitAggExpr(Init, DeclPtr, isVolatile);
-
+ const ConstantArrayType *Array = getContext().getAsConstantArrayType(T);
+ if (Array)
+ T = getContext().getBaseElementType(Array);
+
if (const RecordType *RT = T->getAs<RecordType>()) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- if (!RD->hasTrivialDestructor())
- EmitCXXGlobalDtorRegistration(RD->getDestructor(getContext()), DeclPtr);
+ if (!RD->hasTrivialDestructor()) {
+ llvm::Constant *DtorFn;
+ if (Array) {
+ DtorFn = CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(
+ RD->getDestructor(getContext()),
+ Array, DeclPtr);
+ DeclPtr =
+ llvm::Constant::getNullValue(llvm::Type::getInt8PtrTy(VMContext));
+ }
+ else
+ DtorFn = CGM.GetAddrOfCXXDestructor(RD->getDestructor(getContext()),
+ Dtor_Complete);
+ EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr);
+ }
}
}
}
@@ -559,6 +571,50 @@ CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
EmitBlock(AfterFor, true);
}
+/// EmitCXXAggrDestructorCall - Generates a helper function which when invoked,
+/// calls the default destructor on array elements in reverse order of
+/// construction.
+llvm::Constant *
+CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
+ const ArrayType *Array,
+ llvm::Value *This) {
+ static int UniqueCount;
+ FunctionArgList Args;
+ ImplicitParamDecl *Dst =
+ ImplicitParamDecl::Create(getContext(), 0,
+ SourceLocation(), 0,
+ getContext().getPointerType(getContext().VoidTy));
+ Args.push_back(std::make_pair(Dst, Dst->getType()));
+
+ llvm::SmallString<16> Name;
+ llvm::raw_svector_ostream(Name) << "__tcf_" << (++UniqueCount);
+ QualType R = getContext().VoidTy;
+ const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(R, Args);
+ const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false);
+ llvm::Function *Fn =
+ llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
+ Name.c_str(),
+ &CGM.getModule());
+ IdentifierInfo *II
+ = &CGM.getContext().Idents.get(Name.c_str());
+ FunctionDecl *FD = FunctionDecl::Create(getContext(),
+ getContext().getTranslationUnitDecl(),
+ SourceLocation(), II, R, 0,
+ FunctionDecl::Static,
+ false, true);
+ StartFunction(FD, R, Fn, Args, SourceLocation());
+ QualType BaseElementTy = getContext().getBaseElementType(Array);
+ const llvm::Type *BasePtr = ConvertType(BaseElementTy);
+ BasePtr = llvm::PointerType::getUnqual(BasePtr);
+ llvm::Value *BaseAddrPtr = Builder.CreateBitCast(This, BasePtr);
+ EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
+ FinishFunction();
+ llvm::Type *Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),
+ 0);
+ llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty);
+ return m;
+}
+
void
CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
CXXCtorType Type,
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 593840213a..f42376b623 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -646,6 +646,10 @@ public:
const ArrayType *Array,
llvm::Value *This);
+ llvm::Constant * GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
+ const ArrayType *Array,
+ llvm::Value *This);
+
void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type,
llvm::Value *This);
@@ -994,7 +998,7 @@ public:
/// EmitCXXGlobalDtorRegistration - Emits a call to register the global ptr
/// with the C++ runtime so that its destructor will be called at exit.
- void EmitCXXGlobalDtorRegistration(const CXXDestructorDecl *Dtor,
+ void EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
llvm::Constant *DeclPtr);
/// GenerateCXXGlobalInitFunc - Generates code for initializing global
diff --git a/test/CodeGenCXX/global-array-destruction.cpp b/test/CodeGenCXX/global-array-destruction.cpp
new file mode 100644
index 0000000000..ebea9c156e
--- /dev/null
+++ b/test/CodeGenCXX/global-array-destruction.cpp
@@ -0,0 +1,33 @@
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+
+extern "C" int printf(...);
+
+int count;
+
+struct S {
+ S() : iS(++count) { printf("S::S(%d)\n", iS); }
+ ~S() { printf("S::~S(%d)\n", iS); }
+ int iS;
+};
+
+
+S arr[2][1];
+S s1;
+S arr1[3];
+static S sarr[4];
+
+int main () {}
+S arr2[2];
+static S sarr1[4];
+S s2;
+S arr3[3];
+
+// CHECK-LP64: call ___cxa_atexit
+// CHECK-LP64: call ___cxa_atexit
+// CHECK-LP64: call ___cxa_atexit
+// CHECK-LP64: call ___cxa_atexit
+// CHECK-LP64: call ___cxa_atexit
+// CHECK-LP64: call ___cxa_atexit
+// CHECK-LP64: call ___cxa_atexit
+// CHECK-LP64: call ___cxa_atexit