зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
0854d70dab
Коммит
88f4280f6b
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
Загрузка…
Ссылка в новой задаче