CGDeclCXX.cpp revision 85aca0f6a9da02bda705690fd56d0aa713604f08
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"
1506057cef0bcd7804e80f3ce2bbe352178396c715Chandler Carruth#include "clang/Frontend/CodeGenOptions.h"
1686a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor#include "llvm/Intrinsics.h"
1786a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor
185ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlssonusing namespace clang;
195ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlssonusing namespace CodeGen;
205ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson
21fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlssonstatic void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
22fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson                         llvm::Constant *DeclPtr) {
23fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  assert(D.hasGlobalStorage() && "VarDecl must have global storage!");
24fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  assert(!D.getType()->isReferenceType() &&
25fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson         "Should not call EmitDeclInit on a reference!");
26fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson
27fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  ASTContext &Context = CGF.getContext();
28fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson
295ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson  const Expr *Init = D.getInit();
305ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson  QualType T = D.getType();
31fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  bool isVolatile = Context.getCanonicalType(T).isVolatileQualified();
325ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson
33fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  if (!CGF.hasAggregateLLVMType(T)) {
34fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson    llvm::Value *V = CGF.EmitScalarExpr(Init);
35fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson    CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, T);
365ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson  } else if (T->isAnyComplexType()) {
37fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson    CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
385ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson  } else {
39fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson    CGF.EmitAggExpr(Init, DeclPtr, isVolatile);
405ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson  }
415ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson}
425ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson
43cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregorstatic void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
44cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor                            llvm::Constant *DeclPtr) {
45cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  CodeGenModule &CGM = CGF.CGM;
46cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  ASTContext &Context = CGF.getContext();
47cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
48cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  QualType T = D.getType();
49cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
5085aca0f6a9da02bda705690fd56d0aa713604f08John McCall  // Drill down past array types.
51cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  const ConstantArrayType *Array = Context.getAsConstantArrayType(T);
52cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  if (Array)
53cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    T = Context.getBaseElementType(Array);
54cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
5585aca0f6a9da02bda705690fd56d0aa713604f08John McCall  /// If that's not a record, we're done.
5685aca0f6a9da02bda705690fd56d0aa713604f08John McCall  /// FIXME:  __attribute__((cleanup)) ?
57cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  const RecordType *RT = T->getAs<RecordType>();
58cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  if (!RT)
59cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    return;
60cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
61cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
62cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  if (RD->hasTrivialDestructor())
63cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    return;
64cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
651d110e05e0ff48c1c7a483d6b7fd094cdf28316aDouglas Gregor  CXXDestructorDecl *Dtor = RD->getDestructor();
66cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
67cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  llvm::Constant *DtorFn;
68cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  if (Array) {
69cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    DtorFn =
7002e370a02f05b4a734fe5e8c88efc4ed9dac60faAnders Carlsson      CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor, Array,
7102e370a02f05b4a734fe5e8c88efc4ed9dac60faAnders Carlsson                                                           DeclPtr);
72cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    const llvm::Type *Int8PtrTy =
7302e370a02f05b4a734fe5e8c88efc4ed9dac60faAnders Carlsson      llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
74cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    DeclPtr = llvm::Constant::getNullValue(Int8PtrTy);
75cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  } else
76cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete);
77cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
78cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr);
79cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor}
80cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
81fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlssonvoid CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
82fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson                                               llvm::Constant *DeclPtr) {
83fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson
84fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  const Expr *Init = D.getInit();
85fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  QualType T = D.getType();
86fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson
87fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  if (!T->isReferenceType()) {
88fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson    EmitDeclInit(*this, D, DeclPtr);
89cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    EmitDeclDestroy(*this, D, DeclPtr);
90fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson    return;
91fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  }
92045a6d84a0fa672eb5d914be1bb8f3baa226beb3Anders Carlsson
93045a6d84a0fa672eb5d914be1bb8f3baa226beb3Anders Carlsson  RValue RV = EmitReferenceBindingToExpr(Init, &D);
94045a6d84a0fa672eb5d914be1bb8f3baa226beb3Anders Carlsson  EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, T);
95fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson}
96eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
97efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid
98efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel DunbarCodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
99efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                                               llvm::Constant *DeclPtr) {
100efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  // Generate a global destructor entry if not using __cxa_atexit.
101efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  if (!CGM.getCodeGenOpts().CXAAtExit) {
102efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar    CGM.AddCXXDtorEntry(DtorFn, DeclPtr);
103efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar    return;
104efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  }
105efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
106eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  const llvm::Type *Int8PtrTy =
107eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson    llvm::Type::getInt8Ty(VMContext)->getPointerTo();
108eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
109eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  std::vector<const llvm::Type *> Params;
110eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  Params.push_back(Int8PtrTy);
111eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
112eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  // Get the destructor function type
113eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  const llvm::Type *DtorFnTy =
114eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson    llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false);
115eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy);
116eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
117eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  Params.clear();
118eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  Params.push_back(DtorFnTy);
119eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  Params.push_back(Int8PtrTy);
120eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  Params.push_back(Int8PtrTy);
121eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
122eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  // Get the __cxa_atexit function type
123eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d );
124eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  const llvm::FunctionType *AtExitFnTy =
125eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson    llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false);
126eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
127eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy,
128eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                                                       "__cxa_atexit");
129eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
130eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy,
131eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                                                     "__dso_handle");
132eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy),
133eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                           llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy),
134eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                           llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) };
135eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args));
136eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson}
137eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
1389dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlssonstatic llvm::Function *
1399dc046e70d189457968e4c3b986da75b5d98ce8eAnders CarlssonCreateGlobalInitOrDestructFunction(CodeGenModule &CGM,
1409dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson                                   const llvm::FunctionType *FTy,
1419dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson                                   llvm::StringRef Name) {
1429dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson  llvm::Function *Fn =
1439dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson    llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
1449dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson                           Name, &CGM.getModule());
1459dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson
14618af368c080b9d60e34e670cd01f7d2d3ad2ba48Anders Carlsson  // Set the section if needed.
14718af368c080b9d60e34e670cd01f7d2d3ad2ba48Anders Carlsson  if (const char *Section =
14818af368c080b9d60e34e670cd01f7d2d3ad2ba48Anders Carlsson        CGM.getContext().Target.getStaticInitSectionSpecifier())
14918af368c080b9d60e34e670cd01f7d2d3ad2ba48Anders Carlsson    Fn->setSection(Section);
15018af368c080b9d60e34e670cd01f7d2d3ad2ba48Anders Carlsson
151044cc54a7d83c90857187c4cd4a0fd33664a7f7fJohn McCall  if (!CGM.getLangOptions().Exceptions)
152044cc54a7d83c90857187c4cd4a0fd33664a7f7fJohn McCall    Fn->setDoesNotThrow();
153044cc54a7d83c90857187c4cd4a0fd33664a7f7fJohn McCall
1549dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson  return Fn;
1559dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson}
1569dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson
157efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid
158efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel DunbarCodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) {
1596c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman  const llvm::FunctionType *FTy
1606c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
1616c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman                              false);
1626c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman
1636c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman  // Create a variable initialization function.
1646c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman  llvm::Function *Fn =
1659dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson    CreateGlobalInitOrDestructFunction(*this, FTy, "__cxx_global_var_init");
1666c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman
167efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D);
1686c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman
1699f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian  if (D->hasAttr<InitPriorityAttr>()) {
1709f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian    unsigned int order = D->getAttr<InitPriorityAttr>()->getPriority();
171ec2830d930e306124c2ba6bf1060a3c71dced6eaChris Lattner    OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size());
172e0b691a25f801d8be552c9387863637b9526e639Fariborz Jahanian    PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
173bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    DelayedCXXInitPosition.erase(D);
174bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall  }
175bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall  else {
176bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    llvm::DenseMap<const Decl *, unsigned>::iterator I =
177bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall      DelayedCXXInitPosition.find(D);
178bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    if (I == DelayedCXXInitPosition.end()) {
179bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall      CXXGlobalInits.push_back(Fn);
180bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    } else {
181bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall      assert(CXXGlobalInits[I->second] == 0);
182bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall      CXXGlobalInits[I->second] = Fn;
183bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall      DelayedCXXInitPosition.erase(I);
184bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    }
1859f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian  }
1866c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman}
1876c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman
188efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid
189efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel DunbarCodeGenModule::EmitCXXGlobalInitFunc() {
190bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall  while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
191bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    CXXGlobalInits.pop_back();
192bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall
1939f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian  if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty())
194eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson    return;
195eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
196eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  const llvm::FunctionType *FTy
197eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
198eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                              false);
199eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
200eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  // Create our global initialization function.
2019dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson  llvm::Function *Fn =
2029dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson    CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__I_a");
203efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
2049f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian  if (!PrioritizedCXXGlobalInits.empty()) {
205027d7ed9d616d93ae7f02de79d17863725b14866Fariborz Jahanian    llvm::SmallVector<llvm::Constant*, 8> LocalCXXGlobalInits;
206027d7ed9d616d93ae7f02de79d17863725b14866Fariborz Jahanian    llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
207f489688114275c821b1e647e26f71eeb94d8ab24Fariborz Jahanian                         PrioritizedCXXGlobalInits.end());
2089f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian    for (unsigned i = 0; i < PrioritizedCXXGlobalInits.size(); i++) {
2099f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian      llvm::Function *Fn = PrioritizedCXXGlobalInits[i].second;
2109f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian      LocalCXXGlobalInits.push_back(Fn);
2119f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian    }
212bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    LocalCXXGlobalInits.append(CXXGlobalInits.begin(), CXXGlobalInits.end());
2139f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian    CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
2149f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian                                                    &LocalCXXGlobalInits[0],
2159f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian                                                    LocalCXXGlobalInits.size());
2169f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian  }
2179f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian  else
2189f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian    CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
2199f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian                                                     &CXXGlobalInits[0],
2209f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian                                                     CXXGlobalInits.size());
221efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  AddGlobalCtor(Fn);
222efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar}
223efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
224efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid CodeGenModule::EmitCXXGlobalDtorFunc() {
225efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  if (CXXGlobalDtors.empty())
226efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar    return;
227efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
228efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  const llvm::FunctionType *FTy
229efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
230efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                              false);
231eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
232efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  // Create our global destructor function.
233efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  llvm::Function *Fn =
2349dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson    CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__D_a");
235efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
236efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  CodeGenFunction(*this).GenerateCXXGlobalDtorFunc(Fn, CXXGlobalDtors);
237efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  AddGlobalDtor(Fn);
238efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar}
239efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
240efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
241efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                                                       const VarDecl *D) {
2426c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
2436c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman                SourceLocation());
2446c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman
245efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D);
246efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  EmitCXXGlobalVarDeclInit(*D, DeclPtr);
2476c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman
2486c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman  FinishFunction();
249efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar}
250eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
251efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
252efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                                                llvm::Constant **Decls,
253efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                                                unsigned NumDecls) {
254efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
255efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                SourceLocation());
256efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
257efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  for (unsigned i = 0; i != NumDecls; ++i)
258bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    if (Decls[i])
259bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall      Builder.CreateCall(Decls[i]);
260efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
261efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  FinishFunction();
262efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar}
263efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
264efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn,
265810112e28dc839715d17b0a786f23aaa19600ac0Chris Lattner                  const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> >
266efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                                                &DtorsAndObjects) {
267efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
268efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                SourceLocation());
269efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
270efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  // Emit the dtors, in reverse order from construction.
271c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner  for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
272810112e28dc839715d17b0a786f23aaa19600ac0Chris Lattner    llvm::Value *Callee = DtorsAndObjects[e - i - 1].first;
273c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner    llvm::CallInst *CI = Builder.CreateCall(Callee,
274c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner                                            DtorsAndObjects[e - i - 1].second);
275c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner    // Make sure the call and the callee agree on calling convention.
276c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner    if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
277c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner      CI->setCallingConv(F->getCallingConv());
278c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner  }
279efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
280efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  FinishFunction();
281eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson}
282eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
283a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlssonstatic llvm::Constant *getGuardAcquireFn(CodeGenFunction &CGF) {
284a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  // int __cxa_guard_acquire(__int64_t *guard_object);
285a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
286a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  const llvm::Type *Int64PtrTy =
287a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
288a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
289a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  std::vector<const llvm::Type*> Args(1, Int64PtrTy);
290a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
291a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  const llvm::FunctionType *FTy =
292a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    llvm::FunctionType::get(CGF.ConvertType(CGF.getContext().IntTy),
293a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson                            Args, /*isVarArg=*/false);
294a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
295a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire");
296a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson}
297a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
298a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlssonstatic llvm::Constant *getGuardReleaseFn(CodeGenFunction &CGF) {
299a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  // void __cxa_guard_release(__int64_t *guard_object);
300a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
301a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  const llvm::Type *Int64PtrTy =
302a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
303a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
304a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  std::vector<const llvm::Type*> Args(1, Int64PtrTy);
305a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
306a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  const llvm::FunctionType *FTy =
307a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
308a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson                          Args, /*isVarArg=*/false);
309a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
310a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release");
311a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson}
312a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
313a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlssonstatic llvm::Constant *getGuardAbortFn(CodeGenFunction &CGF) {
314a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  // void __cxa_guard_abort(__int64_t *guard_object);
315a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
316a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  const llvm::Type *Int64PtrTy =
317a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
318a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
319a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  std::vector<const llvm::Type*> Args(1, Int64PtrTy);
320a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
321a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  const llvm::FunctionType *FTy =
322a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
323a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson                          Args, /*isVarArg=*/false);
324a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
325a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort");
326a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson}
327a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
328e540e637cbb9e3963c512b179779b8afcc190026John McCallnamespace {
3291f0fca54676cfa8616e7f3cd7a26788ab937e3cdJohn McCall  struct CallGuardAbort : EHScopeStack::Cleanup {
330e540e637cbb9e3963c512b179779b8afcc190026John McCall    llvm::GlobalVariable *Guard;
331e540e637cbb9e3963c512b179779b8afcc190026John McCall    CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
332e540e637cbb9e3963c512b179779b8afcc190026John McCall
333e540e637cbb9e3963c512b179779b8afcc190026John McCall    void Emit(CodeGenFunction &CGF, bool IsForEH) {
334e540e637cbb9e3963c512b179779b8afcc190026John McCall      // It shouldn't be possible for this to throw, but if it can,
335e540e637cbb9e3963c512b179779b8afcc190026John McCall      // this should allow for the possibility of an invoke.
336e540e637cbb9e3963c512b179779b8afcc190026John McCall      CGF.Builder.CreateCall(getGuardAbortFn(CGF), Guard)
337e540e637cbb9e3963c512b179779b8afcc190026John McCall        ->setDoesNotThrow();
338e540e637cbb9e3963c512b179779b8afcc190026John McCall    }
339e540e637cbb9e3963c512b179779b8afcc190026John McCall  };
340e540e637cbb9e3963c512b179779b8afcc190026John McCall}
341e540e637cbb9e3963c512b179779b8afcc190026John McCall
342eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlssonvoid
343eb4072ed06c884f1053047ad88846cbffd5ac62eAnders CarlssonCodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
344eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                                               llvm::GlobalVariable *GV) {
345fe67f3bfc09caa66ab1398c03418c35bea77caf4John McCall  // Bail out early if this initializer isn't reachable.
346fe67f3bfc09caa66ab1398c03418c35bea77caf4John McCall  if (!Builder.GetInsertBlock()) return;
347fe67f3bfc09caa66ab1398c03418c35bea77caf4John McCall
348a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics;
349a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
350eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  llvm::SmallString<256> GuardVName;
351eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  CGM.getMangleContext().mangleGuardVariable(&D, GuardVName);
352eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
353eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  // Create the guard variable.
354e540e637cbb9e3963c512b179779b8afcc190026John McCall  llvm::GlobalVariable *GuardVariable =
355a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    new llvm::GlobalVariable(CGM.getModule(), Int64Ty,
356eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                             false, GV->getLinkage(),
357a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson                             llvm::Constant::getNullValue(Int64Ty),
358eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                             GuardVName.str());
359eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
360eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  // Load the first byte of the guard variable.
361eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  const llvm::Type *PtrTy
362eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson    = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
363a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  llvm::Value *V =
364a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp");
365eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
366a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  llvm::BasicBlock *InitCheckBlock = createBasicBlock("init.check");
367eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  llvm::BasicBlock *EndBlock = createBasicBlock("init.end");
368eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
369a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  // Check if the first byte of the guard variable is zero.
370a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  Builder.CreateCondBr(Builder.CreateIsNull(V, "tobool"),
371a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson                       InitCheckBlock, EndBlock);
372eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
373a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  EmitBlock(InitCheckBlock);
374a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
37586a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor  // Variables used when coping with thread-safe statics and exceptions.
37686a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor  if (ThreadsafeStatics) {
377a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    // Call __cxa_guard_acquire.
378a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    V = Builder.CreateCall(getGuardAcquireFn(*this), GuardVariable);
379a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
380a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    llvm::BasicBlock *InitBlock = createBasicBlock("init");
381a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
382a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),
383a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson                         InitBlock, EndBlock);
384a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
385f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall    // Call __cxa_guard_abort along the exceptional edge.
386e540e637cbb9e3963c512b179779b8afcc190026John McCall    if (Exceptions)
3871f0fca54676cfa8616e7f3cd7a26788ab937e3cdJohn McCall      EHStack.pushCleanup<CallGuardAbort>(EHCleanup, GuardVariable);
38886a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor
38986a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor    EmitBlock(InitBlock);
390a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  }
391eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
392fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  if (D.getType()->isReferenceType()) {
393864143fe14b8059eed1413d38854b689f7b21016Anders Carlsson    QualType T = D.getType();
394045a6d84a0fa672eb5d914be1bb8f3baa226beb3Anders Carlsson    RValue RV = EmitReferenceBindingToExpr(D.getInit(), &D);
395864143fe14b8059eed1413d38854b689f7b21016Anders Carlsson    EmitStoreOfScalar(RV.getScalarVal(), GV, /*Volatile=*/false, T);
396864143fe14b8059eed1413d38854b689f7b21016Anders Carlsson
397fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  } else
398fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson    EmitDeclInit(*this, D, GV);
399eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
400a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  if (ThreadsafeStatics) {
401f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall    // Call __cxa_guard_release.  This cannot throw.
40286a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor    Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable);
403a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  } else {
404a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    llvm::Value *One =
405a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson      llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1);
406a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    Builder.CreateStore(One, Builder.CreateBitCast(GuardVariable, PtrTy));
407a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  }
408eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
409cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  // Register the call to the destructor.
410cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  if (!D.getType()->isReferenceType())
411cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    EmitDeclDestroy(*this, D, GV);
412cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
413eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  EmitBlock(EndBlock);
414eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson}
415772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
416772913659894551b02f342e3577e7219e4f9a701Anders Carlsson/// GenerateCXXAggrDestructorHelper - Generates a helper function which when
417772913659894551b02f342e3577e7219e4f9a701Anders Carlsson/// invoked, calls the default destructor on array elements in reverse order of
418772913659894551b02f342e3577e7219e4f9a701Anders Carlsson/// construction.
419772913659894551b02f342e3577e7219e4f9a701Anders Carlssonllvm::Function *
420772913659894551b02f342e3577e7219e4f9a701Anders CarlssonCodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
421772913659894551b02f342e3577e7219e4f9a701Anders Carlsson                                                 const ArrayType *Array,
422772913659894551b02f342e3577e7219e4f9a701Anders Carlsson                                                 llvm::Value *This) {
423772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  FunctionArgList Args;
424772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  ImplicitParamDecl *Dst =
425772913659894551b02f342e3577e7219e4f9a701Anders Carlsson    ImplicitParamDecl::Create(getContext(), 0,
426772913659894551b02f342e3577e7219e4f9a701Anders Carlsson                              SourceLocation(), 0,
427772913659894551b02f342e3577e7219e4f9a701Anders Carlsson                              getContext().getPointerType(getContext().VoidTy));
428772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  Args.push_back(std::make_pair(Dst, Dst->getType()));
429772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
430772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  const CGFunctionInfo &FI =
431772913659894551b02f342e3577e7219e4f9a701Anders Carlsson    CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args,
432772913659894551b02f342e3577e7219e4f9a701Anders Carlsson                                   FunctionType::ExtInfo());
433772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false);
4349dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson  llvm::Function *Fn =
4359dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson    CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor");
436772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
437772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, Args, SourceLocation());
438772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
439772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  QualType BaseElementTy = getContext().getBaseElementType(Array);
440772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  const llvm::Type *BasePtr = ConvertType(BaseElementTy)->getPointerTo();
441772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  llvm::Value *BaseAddrPtr = Builder.CreateBitCast(This, BasePtr);
442772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
443772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
444772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
445772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  FinishFunction();
446772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
447772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  return Fn;
448772913659894551b02f342e3577e7219e4f9a701Anders Carlsson}
449