CGDeclCXX.cpp revision d6c9a0f06ce7e164024d8e4dbf2423a5c5035084
15ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson//===--- CGDeclCXX.cpp - Emit LLVM Code for C++ declarations --------------===//
25ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson//
35ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson//                     The LLVM Compiler Infrastructure
45ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson//
55ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson// This file is distributed under the University of Illinois Open Source
65ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson// License. See LICENSE.TXT for details.
75ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson//
85ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson//===----------------------------------------------------------------------===//
95ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson//
105ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson// This contains code dealing with code generation of C++ declarations
115ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson//
125ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson//===----------------------------------------------------------------------===//
135ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson
145ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson#include "CodeGenFunction.h"
15ec8051276e5ba5eb3f8dcb0ebb96e17495cbc2bfFariborz Jahanian#include "CGObjCRuntime.h"
164c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall#include "CGCXXABI.h"
1706057cef0bcd7804e80f3ce2bbe352178396c715Chandler Carruth#include "clang/Frontend/CodeGenOptions.h"
1886a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor#include "llvm/Intrinsics.h"
1986a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor
205ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlssonusing namespace clang;
215ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlssonusing namespace CodeGen;
225ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson
23fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlssonstatic void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
24fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson                         llvm::Constant *DeclPtr) {
25fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  assert(D.hasGlobalStorage() && "VarDecl must have global storage!");
26fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  assert(!D.getType()->isReferenceType() &&
27fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson         "Should not call EmitDeclInit on a reference!");
28fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson
29fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  ASTContext &Context = CGF.getContext();
30fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson
315ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson  const Expr *Init = D.getInit();
325ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson  QualType T = D.getType();
33fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  bool isVolatile = Context.getCanonicalType(T).isVolatileQualified();
345ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson
3591a16fa3265686b90054715eea504d9b4a13438bDaniel Dunbar  unsigned Alignment = Context.getDeclAlign(&D).getQuantity();
36fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  if (!CGF.hasAggregateLLVMType(T)) {
37fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson    llvm::Value *V = CGF.EmitScalarExpr(Init);
38ec8051276e5ba5eb3f8dcb0ebb96e17495cbc2bfFariborz Jahanian    CodeGenModule &CGM = CGF.CGM;
390990b00ba0627d76d53432afe729041ca3f4579bFariborz Jahanian    Qualifiers::GC GCAttr = CGM.getContext().getObjCGCAttrKind(T);
400990b00ba0627d76d53432afe729041ca3f4579bFariborz Jahanian    if (GCAttr == Qualifiers::Strong)
41ec8051276e5ba5eb3f8dcb0ebb96e17495cbc2bfFariborz Jahanian      CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, V, DeclPtr,
42ec8051276e5ba5eb3f8dcb0ebb96e17495cbc2bfFariborz Jahanian                                                D.isThreadSpecified());
430990b00ba0627d76d53432afe729041ca3f4579bFariborz Jahanian    else if (GCAttr == Qualifiers::Weak)
44ec8051276e5ba5eb3f8dcb0ebb96e17495cbc2bfFariborz Jahanian      CGM.getObjCRuntime().EmitObjCWeakAssign(CGF, V, DeclPtr);
45ec8051276e5ba5eb3f8dcb0ebb96e17495cbc2bfFariborz Jahanian    else
46ec8051276e5ba5eb3f8dcb0ebb96e17495cbc2bfFariborz Jahanian      CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, Alignment, T);
475ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson  } else if (T->isAnyComplexType()) {
48fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson    CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
495ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson  } else {
50558d2abc7f9fd6801cc7677200992313ae90b5d8John McCall    CGF.EmitAggExpr(Init, AggValueSlot::forAddr(DeclPtr, isVolatile, true));
515ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson  }
525ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson}
535ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson
545cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall/// Emit code to cause the destruction of the given variable with
555cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall/// static storage duration.
56cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregorstatic void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
57cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor                            llvm::Constant *DeclPtr) {
58cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  CodeGenModule &CGM = CGF.CGM;
59cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  ASTContext &Context = CGF.getContext();
60cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
61cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  QualType T = D.getType();
62cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
6385aca0f6a9da02bda705690fd56d0aa713604f08John McCall  // Drill down past array types.
64cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  const ConstantArrayType *Array = Context.getAsConstantArrayType(T);
65cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  if (Array)
66cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    T = Context.getBaseElementType(Array);
67cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
6885aca0f6a9da02bda705690fd56d0aa713604f08John McCall  /// If that's not a record, we're done.
6985aca0f6a9da02bda705690fd56d0aa713604f08John McCall  /// FIXME:  __attribute__((cleanup)) ?
70cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  const RecordType *RT = T->getAs<RecordType>();
71cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  if (!RT)
72cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    return;
73cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
74cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
75cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  if (RD->hasTrivialDestructor())
76cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    return;
77cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
781d110e05e0ff48c1c7a483d6b7fd094cdf28316aDouglas Gregor  CXXDestructorDecl *Dtor = RD->getDestructor();
79cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
80cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  llvm::Constant *DtorFn;
81cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  if (Array) {
82cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    DtorFn =
8302e370a02f05b4a734fe5e8c88efc4ed9dac60faAnders Carlsson      CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor, Array,
8402e370a02f05b4a734fe5e8c88efc4ed9dac60faAnders Carlsson                                                           DeclPtr);
85cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    const llvm::Type *Int8PtrTy =
8602e370a02f05b4a734fe5e8c88efc4ed9dac60faAnders Carlsson      llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
87cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    DeclPtr = llvm::Constant::getNullValue(Int8PtrTy);
88cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  } else
89cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete);
90cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
91cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr);
92cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor}
93cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
94fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlssonvoid CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
95fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson                                               llvm::Constant *DeclPtr) {
96fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson
97fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  const Expr *Init = D.getInit();
98fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  QualType T = D.getType();
99fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson
100fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  if (!T->isReferenceType()) {
101fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson    EmitDeclInit(*this, D, DeclPtr);
102cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    EmitDeclDestroy(*this, D, DeclPtr);
103fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson    return;
104fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  }
105045a6d84a0fa672eb5d914be1bb8f3baa226beb3Anders Carlsson
10691a16fa3265686b90054715eea504d9b4a13438bDaniel Dunbar  unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
107045a6d84a0fa672eb5d914be1bb8f3baa226beb3Anders Carlsson  RValue RV = EmitReferenceBindingToExpr(Init, &D);
10891a16fa3265686b90054715eea504d9b4a13438bDaniel Dunbar  EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, Alignment, T);
109fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson}
110eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
111efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid
112efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel DunbarCodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
113efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                                               llvm::Constant *DeclPtr) {
114efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  // Generate a global destructor entry if not using __cxa_atexit.
115efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  if (!CGM.getCodeGenOpts().CXAAtExit) {
116efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar    CGM.AddCXXDtorEntry(DtorFn, DeclPtr);
117efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar    return;
118efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  }
119efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
120eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  std::vector<const llvm::Type *> Params;
121eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  Params.push_back(Int8PtrTy);
122eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
123eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  // Get the destructor function type
124eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  const llvm::Type *DtorFnTy =
125d16c2cf1cafa413709aa487cbbd5dc392f1ba1ffJohn McCall    llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()),
126d16c2cf1cafa413709aa487cbbd5dc392f1ba1ffJohn McCall                            Params, false);
127eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy);
128eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
129eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  Params.clear();
130eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  Params.push_back(DtorFnTy);
131eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  Params.push_back(Int8PtrTy);
132eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  Params.push_back(Int8PtrTy);
133eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
134eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  // Get the __cxa_atexit function type
135eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d );
136eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  const llvm::FunctionType *AtExitFnTy =
137eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson    llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false);
138eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
139eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy,
140eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                                                       "__cxa_atexit");
141eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
142eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy,
143eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                                                     "__dso_handle");
144eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy),
145eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                           llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy),
146eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                           llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) };
147eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args));
148eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson}
149eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
1503030eb82593097502469a8b3fc26112c79c75605John McCallvoid CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,
1513030eb82593097502469a8b3fc26112c79c75605John McCall                                         llvm::GlobalVariable *DeclPtr) {
1523030eb82593097502469a8b3fc26112c79c75605John McCall  CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr);
1535cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall}
1545cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall
1559dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlssonstatic llvm::Function *
1569dc046e70d189457968e4c3b986da75b5d98ce8eAnders CarlssonCreateGlobalInitOrDestructFunction(CodeGenModule &CGM,
1579dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson                                   const llvm::FunctionType *FTy,
1589dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson                                   llvm::StringRef Name) {
1599dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson  llvm::Function *Fn =
1609dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson    llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
1619dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson                           Name, &CGM.getModule());
162d6c9a0f06ce7e164024d8e4dbf2423a5c5035084Fariborz Jahanian  if (!CGM.getContext().getLangOptions().AppleKext) {
163d6c9a0f06ce7e164024d8e4dbf2423a5c5035084Fariborz Jahanian    // Set the section if needed.
164d6c9a0f06ce7e164024d8e4dbf2423a5c5035084Fariborz Jahanian    if (const char *Section =
165d6c9a0f06ce7e164024d8e4dbf2423a5c5035084Fariborz Jahanian          CGM.getContext().Target.getStaticInitSectionSpecifier())
166d6c9a0f06ce7e164024d8e4dbf2423a5c5035084Fariborz Jahanian      Fn->setSection(Section);
167d6c9a0f06ce7e164024d8e4dbf2423a5c5035084Fariborz Jahanian  }
16818af368c080b9d60e34e670cd01f7d2d3ad2ba48Anders Carlsson
169044cc54a7d83c90857187c4cd4a0fd33664a7f7fJohn McCall  if (!CGM.getLangOptions().Exceptions)
170044cc54a7d83c90857187c4cd4a0fd33664a7f7fJohn McCall    Fn->setDoesNotThrow();
171044cc54a7d83c90857187c4cd4a0fd33664a7f7fJohn McCall
1729dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson  return Fn;
1739dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson}
1749dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson
175efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid
1763030eb82593097502469a8b3fc26112c79c75605John McCallCodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
1773030eb82593097502469a8b3fc26112c79c75605John McCall                                            llvm::GlobalVariable *Addr) {
1786c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman  const llvm::FunctionType *FTy
1796c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
1806c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman                              false);
1816c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman
1826c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman  // Create a variable initialization function.
1836c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman  llvm::Function *Fn =
1849dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson    CreateGlobalInitOrDestructFunction(*this, FTy, "__cxx_global_var_init");
1856c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman
1863030eb82593097502469a8b3fc26112c79c75605John McCall  CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr);
1876c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman
1889f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian  if (D->hasAttr<InitPriorityAttr>()) {
1899f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian    unsigned int order = D->getAttr<InitPriorityAttr>()->getPriority();
190ec2830d930e306124c2ba6bf1060a3c71dced6eaChris Lattner    OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size());
191e0b691a25f801d8be552c9387863637b9526e639Fariborz Jahanian    PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
192bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    DelayedCXXInitPosition.erase(D);
193bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall  }
194bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall  else {
195bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    llvm::DenseMap<const Decl *, unsigned>::iterator I =
196bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall      DelayedCXXInitPosition.find(D);
197bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    if (I == DelayedCXXInitPosition.end()) {
198bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall      CXXGlobalInits.push_back(Fn);
199bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    } else {
200bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall      assert(CXXGlobalInits[I->second] == 0);
201bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall      CXXGlobalInits[I->second] = Fn;
202bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall      DelayedCXXInitPosition.erase(I);
203bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    }
2049f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian  }
2056c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman}
2066c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman
207efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid
208efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel DunbarCodeGenModule::EmitCXXGlobalInitFunc() {
209bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall  while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
210bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    CXXGlobalInits.pop_back();
211bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall
2129f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian  if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty())
213eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson    return;
214eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
215eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  const llvm::FunctionType *FTy
216eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
217eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                              false);
218eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
219eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  // Create our global initialization function.
2209dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson  llvm::Function *Fn =
2219dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson    CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__I_a");
222efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
2239f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian  if (!PrioritizedCXXGlobalInits.empty()) {
224027d7ed9d616d93ae7f02de79d17863725b14866Fariborz Jahanian    llvm::SmallVector<llvm::Constant*, 8> LocalCXXGlobalInits;
225027d7ed9d616d93ae7f02de79d17863725b14866Fariborz Jahanian    llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
226f489688114275c821b1e647e26f71eeb94d8ab24Fariborz Jahanian                         PrioritizedCXXGlobalInits.end());
2279f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian    for (unsigned i = 0; i < PrioritizedCXXGlobalInits.size(); i++) {
2289f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian      llvm::Function *Fn = PrioritizedCXXGlobalInits[i].second;
2299f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian      LocalCXXGlobalInits.push_back(Fn);
2309f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian    }
231bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    LocalCXXGlobalInits.append(CXXGlobalInits.begin(), CXXGlobalInits.end());
2329f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian    CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
2339f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian                                                    &LocalCXXGlobalInits[0],
2349f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian                                                    LocalCXXGlobalInits.size());
2359f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian  }
2369f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian  else
2379f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian    CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
2389f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian                                                     &CXXGlobalInits[0],
2399f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian                                                     CXXGlobalInits.size());
240efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  AddGlobalCtor(Fn);
241efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar}
242efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
243efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid CodeGenModule::EmitCXXGlobalDtorFunc() {
244efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  if (CXXGlobalDtors.empty())
245efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar    return;
246efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
247efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  const llvm::FunctionType *FTy
248efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
249efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                              false);
250eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
251efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  // Create our global destructor function.
252efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  llvm::Function *Fn =
2539dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson    CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__D_a");
254efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
255efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  CodeGenFunction(*this).GenerateCXXGlobalDtorFunc(Fn, CXXGlobalDtors);
256efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  AddGlobalDtor(Fn);
257efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar}
258efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
2593030eb82593097502469a8b3fc26112c79c75605John McCall/// Emit the code necessary to initialize the given global variable.
260efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
2613030eb82593097502469a8b3fc26112c79c75605John McCall                                                       const VarDecl *D,
2623030eb82593097502469a8b3fc26112c79c75605John McCall                                                 llvm::GlobalVariable *Addr) {
2636c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
2646c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman                SourceLocation());
2656c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman
2663030eb82593097502469a8b3fc26112c79c75605John McCall  // Use guarded initialization if the global variable is weak due to
2673030eb82593097502469a8b3fc26112c79c75605John McCall  // being a class template's static data member.
2683030eb82593097502469a8b3fc26112c79c75605John McCall  if (Addr->hasWeakLinkage() && D->getInstantiatedFromStaticDataMember()) {
2693030eb82593097502469a8b3fc26112c79c75605John McCall    EmitCXXGuardedInit(*D, Addr);
2703030eb82593097502469a8b3fc26112c79c75605John McCall  } else {
2713030eb82593097502469a8b3fc26112c79c75605John McCall    EmitCXXGlobalVarDeclInit(*D, Addr);
27292d835a86ac334768d0b75936201e4fea3941c1fFariborz Jahanian  }
2736c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman
2746c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman  FinishFunction();
275efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar}
276eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
277efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
278efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                                                llvm::Constant **Decls,
279efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                                                unsigned NumDecls) {
280efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
281efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                SourceLocation());
282efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
283efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  for (unsigned i = 0; i != NumDecls; ++i)
284bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    if (Decls[i])
285bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall      Builder.CreateCall(Decls[i]);
286efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
287efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  FinishFunction();
288efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar}
289efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
290efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn,
291810112e28dc839715d17b0a786f23aaa19600ac0Chris Lattner                  const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> >
292efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                                                &DtorsAndObjects) {
293efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
294efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                SourceLocation());
295efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
296efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  // Emit the dtors, in reverse order from construction.
297c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner  for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
298810112e28dc839715d17b0a786f23aaa19600ac0Chris Lattner    llvm::Value *Callee = DtorsAndObjects[e - i - 1].first;
299c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner    llvm::CallInst *CI = Builder.CreateCall(Callee,
300c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner                                            DtorsAndObjects[e - i - 1].second);
301c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner    // Make sure the call and the callee agree on calling convention.
302c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner    if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
303c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner      CI->setCallingConv(F->getCallingConv());
304c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner  }
305efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
306efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  FinishFunction();
307eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson}
308eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
309772913659894551b02f342e3577e7219e4f9a701Anders Carlsson/// GenerateCXXAggrDestructorHelper - Generates a helper function which when
310772913659894551b02f342e3577e7219e4f9a701Anders Carlsson/// invoked, calls the default destructor on array elements in reverse order of
311772913659894551b02f342e3577e7219e4f9a701Anders Carlsson/// construction.
312772913659894551b02f342e3577e7219e4f9a701Anders Carlssonllvm::Function *
313772913659894551b02f342e3577e7219e4f9a701Anders CarlssonCodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
314772913659894551b02f342e3577e7219e4f9a701Anders Carlsson                                                 const ArrayType *Array,
315772913659894551b02f342e3577e7219e4f9a701Anders Carlsson                                                 llvm::Value *This) {
316772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  FunctionArgList Args;
317772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  ImplicitParamDecl *Dst =
318772913659894551b02f342e3577e7219e4f9a701Anders Carlsson    ImplicitParamDecl::Create(getContext(), 0,
319772913659894551b02f342e3577e7219e4f9a701Anders Carlsson                              SourceLocation(), 0,
320772913659894551b02f342e3577e7219e4f9a701Anders Carlsson                              getContext().getPointerType(getContext().VoidTy));
321772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  Args.push_back(std::make_pair(Dst, Dst->getType()));
322772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
323772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  const CGFunctionInfo &FI =
324772913659894551b02f342e3577e7219e4f9a701Anders Carlsson    CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args,
325772913659894551b02f342e3577e7219e4f9a701Anders Carlsson                                   FunctionType::ExtInfo());
326772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false);
3279dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson  llvm::Function *Fn =
3289dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson    CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor");
329772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
330772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, Args, SourceLocation());
331772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
332772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  QualType BaseElementTy = getContext().getBaseElementType(Array);
333772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  const llvm::Type *BasePtr = ConvertType(BaseElementTy)->getPointerTo();
334772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  llvm::Value *BaseAddrPtr = Builder.CreateBitCast(This, BasePtr);
335772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
336772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
337772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
338772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  FinishFunction();
339772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
340772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  return Fn;
341772913659894551b02f342e3577e7219e4f9a701Anders Carlsson}
342