CGDeclCXX.cpp revision 91a16fa3265686b90054715eea504d9b4a13438b
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
3391a16fa3265686b90054715eea504d9b4a13438bDaniel Dunbar  unsigned Alignment = Context.getDeclAlign(&D).getQuantity();
34fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  if (!CGF.hasAggregateLLVMType(T)) {
35fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson    llvm::Value *V = CGF.EmitScalarExpr(Init);
3691a16fa3265686b90054715eea504d9b4a13438bDaniel Dunbar    CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, Alignment, T);
375ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson  } else if (T->isAnyComplexType()) {
38fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson    CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
395ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson  } else {
40fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson    CGF.EmitAggExpr(Init, DeclPtr, isVolatile);
415ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson  }
425ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson}
435ec2e7ccb08b2a1598f12b2c6f59c6f31d035b5bAnders Carlsson
44cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregorstatic void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
45cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor                            llvm::Constant *DeclPtr) {
46cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  CodeGenModule &CGM = CGF.CGM;
47cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  ASTContext &Context = CGF.getContext();
48cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
49cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  QualType T = D.getType();
50cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
5185aca0f6a9da02bda705690fd56d0aa713604f08John McCall  // Drill down past array types.
52cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  const ConstantArrayType *Array = Context.getAsConstantArrayType(T);
53cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  if (Array)
54cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    T = Context.getBaseElementType(Array);
55cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
5685aca0f6a9da02bda705690fd56d0aa713604f08John McCall  /// If that's not a record, we're done.
5785aca0f6a9da02bda705690fd56d0aa713604f08John McCall  /// FIXME:  __attribute__((cleanup)) ?
58cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  const RecordType *RT = T->getAs<RecordType>();
59cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  if (!RT)
60cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    return;
61cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
62cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
63cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  if (RD->hasTrivialDestructor())
64cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    return;
65cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
661d110e05e0ff48c1c7a483d6b7fd094cdf28316aDouglas Gregor  CXXDestructorDecl *Dtor = RD->getDestructor();
67cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
68cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  llvm::Constant *DtorFn;
69cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  if (Array) {
70cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    DtorFn =
7102e370a02f05b4a734fe5e8c88efc4ed9dac60faAnders Carlsson      CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor, Array,
7202e370a02f05b4a734fe5e8c88efc4ed9dac60faAnders Carlsson                                                           DeclPtr);
73cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    const llvm::Type *Int8PtrTy =
7402e370a02f05b4a734fe5e8c88efc4ed9dac60faAnders Carlsson      llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
75cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    DeclPtr = llvm::Constant::getNullValue(Int8PtrTy);
76cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  } else
77cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete);
78cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
79cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr);
80cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor}
81cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
82fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlssonvoid CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
83fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson                                               llvm::Constant *DeclPtr) {
84fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson
85fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  const Expr *Init = D.getInit();
86fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  QualType T = D.getType();
87fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson
88fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  if (!T->isReferenceType()) {
89fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson    EmitDeclInit(*this, D, DeclPtr);
90cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    EmitDeclDestroy(*this, D, DeclPtr);
91fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson    return;
92fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  }
93045a6d84a0fa672eb5d914be1bb8f3baa226beb3Anders Carlsson
9491a16fa3265686b90054715eea504d9b4a13438bDaniel Dunbar  unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
95045a6d84a0fa672eb5d914be1bb8f3baa226beb3Anders Carlsson  RValue RV = EmitReferenceBindingToExpr(Init, &D);
9691a16fa3265686b90054715eea504d9b4a13438bDaniel Dunbar  EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, Alignment, T);
97fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson}
98eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
99efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid
100efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel DunbarCodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
101efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                                               llvm::Constant *DeclPtr) {
102efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  // Generate a global destructor entry if not using __cxa_atexit.
103efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  if (!CGM.getCodeGenOpts().CXAAtExit) {
104efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar    CGM.AddCXXDtorEntry(DtorFn, DeclPtr);
105efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar    return;
106efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  }
107efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
108eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  const llvm::Type *Int8PtrTy =
109eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson    llvm::Type::getInt8Ty(VMContext)->getPointerTo();
110eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
111eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  std::vector<const llvm::Type *> Params;
112eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  Params.push_back(Int8PtrTy);
113eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
114eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  // Get the destructor function type
115eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  const llvm::Type *DtorFnTy =
116eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson    llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false);
117eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy);
118eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
119eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  Params.clear();
120eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  Params.push_back(DtorFnTy);
121eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  Params.push_back(Int8PtrTy);
122eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  Params.push_back(Int8PtrTy);
123eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
124eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  // Get the __cxa_atexit function type
125eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d );
126eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  const llvm::FunctionType *AtExitFnTy =
127eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson    llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false);
128eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
129eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy,
130eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                                                       "__cxa_atexit");
131eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
132eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy,
133eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                                                     "__dso_handle");
134eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy),
135eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                           llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy),
136eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                           llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) };
137eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args));
138eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson}
139eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
1409dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlssonstatic llvm::Function *
1419dc046e70d189457968e4c3b986da75b5d98ce8eAnders CarlssonCreateGlobalInitOrDestructFunction(CodeGenModule &CGM,
1429dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson                                   const llvm::FunctionType *FTy,
1439dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson                                   llvm::StringRef Name) {
1449dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson  llvm::Function *Fn =
1459dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson    llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
1469dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson                           Name, &CGM.getModule());
1479dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson
14818af368c080b9d60e34e670cd01f7d2d3ad2ba48Anders Carlsson  // Set the section if needed.
14918af368c080b9d60e34e670cd01f7d2d3ad2ba48Anders Carlsson  if (const char *Section =
15018af368c080b9d60e34e670cd01f7d2d3ad2ba48Anders Carlsson        CGM.getContext().Target.getStaticInitSectionSpecifier())
15118af368c080b9d60e34e670cd01f7d2d3ad2ba48Anders Carlsson    Fn->setSection(Section);
15218af368c080b9d60e34e670cd01f7d2d3ad2ba48Anders Carlsson
153044cc54a7d83c90857187c4cd4a0fd33664a7f7fJohn McCall  if (!CGM.getLangOptions().Exceptions)
154044cc54a7d83c90857187c4cd4a0fd33664a7f7fJohn McCall    Fn->setDoesNotThrow();
155044cc54a7d83c90857187c4cd4a0fd33664a7f7fJohn McCall
1569dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson  return Fn;
1579dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson}
1589dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson
159efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid
160efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel DunbarCodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) {
1616c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman  const llvm::FunctionType *FTy
1626c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
1636c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman                              false);
1646c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman
1656c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman  // Create a variable initialization function.
1666c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman  llvm::Function *Fn =
1679dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson    CreateGlobalInitOrDestructFunction(*this, FTy, "__cxx_global_var_init");
1686c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman
169efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D);
1706c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman
1719f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian  if (D->hasAttr<InitPriorityAttr>()) {
1729f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian    unsigned int order = D->getAttr<InitPriorityAttr>()->getPriority();
173ec2830d930e306124c2ba6bf1060a3c71dced6eaChris Lattner    OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size());
174e0b691a25f801d8be552c9387863637b9526e639Fariborz Jahanian    PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
175bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    DelayedCXXInitPosition.erase(D);
176bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall  }
177bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall  else {
178bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    llvm::DenseMap<const Decl *, unsigned>::iterator I =
179bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall      DelayedCXXInitPosition.find(D);
180bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    if (I == DelayedCXXInitPosition.end()) {
181bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall      CXXGlobalInits.push_back(Fn);
182bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    } else {
183bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall      assert(CXXGlobalInits[I->second] == 0);
184bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall      CXXGlobalInits[I->second] = Fn;
185bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall      DelayedCXXInitPosition.erase(I);
186bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    }
1879f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian  }
1886c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman}
1896c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman
190efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid
191efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel DunbarCodeGenModule::EmitCXXGlobalInitFunc() {
192bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall  while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
193bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    CXXGlobalInits.pop_back();
194bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall
1959f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian  if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty())
196eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson    return;
197eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
198eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  const llvm::FunctionType *FTy
199eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
200eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                              false);
201eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
202eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  // Create our global initialization function.
2039dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson  llvm::Function *Fn =
2049dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson    CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__I_a");
205efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
2069f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian  if (!PrioritizedCXXGlobalInits.empty()) {
207027d7ed9d616d93ae7f02de79d17863725b14866Fariborz Jahanian    llvm::SmallVector<llvm::Constant*, 8> LocalCXXGlobalInits;
208027d7ed9d616d93ae7f02de79d17863725b14866Fariborz Jahanian    llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
209f489688114275c821b1e647e26f71eeb94d8ab24Fariborz Jahanian                         PrioritizedCXXGlobalInits.end());
2109f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian    for (unsigned i = 0; i < PrioritizedCXXGlobalInits.size(); i++) {
2119f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian      llvm::Function *Fn = PrioritizedCXXGlobalInits[i].second;
2129f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian      LocalCXXGlobalInits.push_back(Fn);
2139f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian    }
214bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    LocalCXXGlobalInits.append(CXXGlobalInits.begin(), CXXGlobalInits.end());
2159f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian    CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
2169f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian                                                    &LocalCXXGlobalInits[0],
2179f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian                                                    LocalCXXGlobalInits.size());
2189f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian  }
2199f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian  else
2209f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian    CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
2219f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian                                                     &CXXGlobalInits[0],
2229f967c5e4bbeb48caf6d0e62056b3d3fee20bf7cFariborz Jahanian                                                     CXXGlobalInits.size());
223efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  AddGlobalCtor(Fn);
224efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar}
225efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
226efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid CodeGenModule::EmitCXXGlobalDtorFunc() {
227efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  if (CXXGlobalDtors.empty())
228efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar    return;
229efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
230efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  const llvm::FunctionType *FTy
231efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
232efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                              false);
233eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
234efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  // Create our global destructor function.
235efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  llvm::Function *Fn =
2369dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson    CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__D_a");
237efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
238efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  CodeGenFunction(*this).GenerateCXXGlobalDtorFunc(Fn, CXXGlobalDtors);
239efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  AddGlobalDtor(Fn);
240efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar}
241efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
242efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
243efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                                                       const VarDecl *D) {
2446c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
2456c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman                SourceLocation());
2466c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman
247efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D);
248efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  EmitCXXGlobalVarDeclInit(*D, DeclPtr);
2496c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman
2506c6bda3b0b1d8adaac2ba3f4da7056e9f1eef52eEli Friedman  FinishFunction();
251efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar}
252eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
253efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
254efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                                                llvm::Constant **Decls,
255efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                                                unsigned NumDecls) {
256efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
257efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                SourceLocation());
258efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
259efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  for (unsigned i = 0; i != NumDecls; ++i)
260bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall    if (Decls[i])
261bf40cb518312dde1c07e44fcae59bc4eec65589cJohn McCall      Builder.CreateCall(Decls[i]);
262efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
263efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  FinishFunction();
264efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar}
265efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
266efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbarvoid CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn,
267810112e28dc839715d17b0a786f23aaa19600ac0Chris Lattner                  const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> >
268efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                                                &DtorsAndObjects) {
269efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
270efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar                SourceLocation());
271efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
272efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  // Emit the dtors, in reverse order from construction.
273c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner  for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
274810112e28dc839715d17b0a786f23aaa19600ac0Chris Lattner    llvm::Value *Callee = DtorsAndObjects[e - i - 1].first;
275c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner    llvm::CallInst *CI = Builder.CreateCall(Callee,
276c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner                                            DtorsAndObjects[e - i - 1].second);
277c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner    // Make sure the call and the callee agree on calling convention.
278c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner    if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
279c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner      CI->setCallingConv(F->getCallingConv());
280c9a85f9b4cc8ed95ed7feeff554a74bf52bdc1f7Chris Lattner  }
281efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar
282efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar  FinishFunction();
283eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson}
284eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
285a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlssonstatic llvm::Constant *getGuardAcquireFn(CodeGenFunction &CGF) {
286a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  // int __cxa_guard_acquire(__int64_t *guard_object);
287a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
288a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  const llvm::Type *Int64PtrTy =
289a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
290a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
291a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  std::vector<const llvm::Type*> Args(1, Int64PtrTy);
292a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
293a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  const llvm::FunctionType *FTy =
294a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    llvm::FunctionType::get(CGF.ConvertType(CGF.getContext().IntTy),
295a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson                            Args, /*isVarArg=*/false);
296a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
297a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire");
298a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson}
299a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
300a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlssonstatic llvm::Constant *getGuardReleaseFn(CodeGenFunction &CGF) {
301a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  // void __cxa_guard_release(__int64_t *guard_object);
302a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
303a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  const llvm::Type *Int64PtrTy =
304a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
305a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
306a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  std::vector<const llvm::Type*> Args(1, Int64PtrTy);
307a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
308a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  const llvm::FunctionType *FTy =
309a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
310a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson                          Args, /*isVarArg=*/false);
311a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
312a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release");
313a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson}
314a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
315a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlssonstatic llvm::Constant *getGuardAbortFn(CodeGenFunction &CGF) {
316a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  // void __cxa_guard_abort(__int64_t *guard_object);
317a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
318a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  const llvm::Type *Int64PtrTy =
319a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
320a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
321a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  std::vector<const llvm::Type*> Args(1, Int64PtrTy);
322a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
323a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  const llvm::FunctionType *FTy =
324a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
325a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson                          Args, /*isVarArg=*/false);
326a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
327a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort");
328a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson}
329a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
330e540e637cbb9e3963c512b179779b8afcc190026John McCallnamespace {
3311f0fca54676cfa8616e7f3cd7a26788ab937e3cdJohn McCall  struct CallGuardAbort : EHScopeStack::Cleanup {
332e540e637cbb9e3963c512b179779b8afcc190026John McCall    llvm::GlobalVariable *Guard;
333e540e637cbb9e3963c512b179779b8afcc190026John McCall    CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
334e540e637cbb9e3963c512b179779b8afcc190026John McCall
335e540e637cbb9e3963c512b179779b8afcc190026John McCall    void Emit(CodeGenFunction &CGF, bool IsForEH) {
336e540e637cbb9e3963c512b179779b8afcc190026John McCall      // It shouldn't be possible for this to throw, but if it can,
337e540e637cbb9e3963c512b179779b8afcc190026John McCall      // this should allow for the possibility of an invoke.
338e540e637cbb9e3963c512b179779b8afcc190026John McCall      CGF.Builder.CreateCall(getGuardAbortFn(CGF), Guard)
339e540e637cbb9e3963c512b179779b8afcc190026John McCall        ->setDoesNotThrow();
340e540e637cbb9e3963c512b179779b8afcc190026John McCall    }
341e540e637cbb9e3963c512b179779b8afcc190026John McCall  };
342e540e637cbb9e3963c512b179779b8afcc190026John McCall}
343e540e637cbb9e3963c512b179779b8afcc190026John McCall
344eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlssonvoid
345eb4072ed06c884f1053047ad88846cbffd5ac62eAnders CarlssonCodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
346eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                                               llvm::GlobalVariable *GV) {
347fe67f3bfc09caa66ab1398c03418c35bea77caf4John McCall  // Bail out early if this initializer isn't reachable.
348fe67f3bfc09caa66ab1398c03418c35bea77caf4John McCall  if (!Builder.GetInsertBlock()) return;
349fe67f3bfc09caa66ab1398c03418c35bea77caf4John McCall
350a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics;
351a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
352eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  llvm::SmallString<256> GuardVName;
353eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  CGM.getMangleContext().mangleGuardVariable(&D, GuardVName);
354eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
355eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  // Create the guard variable.
356e540e637cbb9e3963c512b179779b8afcc190026John McCall  llvm::GlobalVariable *GuardVariable =
357a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    new llvm::GlobalVariable(CGM.getModule(), Int64Ty,
358eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                             false, GV->getLinkage(),
359a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson                             llvm::Constant::getNullValue(Int64Ty),
360eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson                             GuardVName.str());
361eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
362eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  // Load the first byte of the guard variable.
363eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  const llvm::Type *PtrTy
364eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson    = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
365a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  llvm::Value *V =
366a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp");
367eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
368a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  llvm::BasicBlock *InitCheckBlock = createBasicBlock("init.check");
369eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  llvm::BasicBlock *EndBlock = createBasicBlock("init.end");
370eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
371a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  // Check if the first byte of the guard variable is zero.
372a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  Builder.CreateCondBr(Builder.CreateIsNull(V, "tobool"),
373a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson                       InitCheckBlock, EndBlock);
374eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
375a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  EmitBlock(InitCheckBlock);
376a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
37786a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor  // Variables used when coping with thread-safe statics and exceptions.
37886a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor  if (ThreadsafeStatics) {
379a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    // Call __cxa_guard_acquire.
380a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    V = Builder.CreateCall(getGuardAcquireFn(*this), GuardVariable);
381a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
382a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    llvm::BasicBlock *InitBlock = createBasicBlock("init");
383a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
384a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),
385a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson                         InitBlock, EndBlock);
386a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson
387f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall    // Call __cxa_guard_abort along the exceptional edge.
388e540e637cbb9e3963c512b179779b8afcc190026John McCall    if (Exceptions)
3891f0fca54676cfa8616e7f3cd7a26788ab937e3cdJohn McCall      EHStack.pushCleanup<CallGuardAbort>(EHCleanup, GuardVariable);
39086a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor
39186a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor    EmitBlock(InitBlock);
392a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  }
393eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
394fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  if (D.getType()->isReferenceType()) {
39591a16fa3265686b90054715eea504d9b4a13438bDaniel Dunbar    unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
396864143fe14b8059eed1413d38854b689f7b21016Anders Carlsson    QualType T = D.getType();
397045a6d84a0fa672eb5d914be1bb8f3baa226beb3Anders Carlsson    RValue RV = EmitReferenceBindingToExpr(D.getInit(), &D);
39891a16fa3265686b90054715eea504d9b4a13438bDaniel Dunbar    EmitStoreOfScalar(RV.getScalarVal(), GV, /*Volatile=*/false, Alignment, T);
399fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson  } else
400fcbfdc1a93325471a262f0d94461273ae67ad3b6Anders Carlsson    EmitDeclInit(*this, D, GV);
401eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
402a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  if (ThreadsafeStatics) {
403224124c7b85596157201a67a7ba12d2b0f5c153cJohn McCall    // Pop the guard-abort cleanup if we pushed one.
404224124c7b85596157201a67a7ba12d2b0f5c153cJohn McCall    if (Exceptions)
405224124c7b85596157201a67a7ba12d2b0f5c153cJohn McCall      PopCleanupBlock();
406224124c7b85596157201a67a7ba12d2b0f5c153cJohn McCall
407f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall    // Call __cxa_guard_release.  This cannot throw.
40886a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor    Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable);
409a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  } else {
410a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    llvm::Value *One =
411a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson      llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1);
412a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson    Builder.CreateStore(One, Builder.CreateBitCast(GuardVariable, PtrTy));
413a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4Anders Carlsson  }
414eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson
415cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  // Register the call to the destructor.
416cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor  if (!D.getType()->isReferenceType())
417cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor    EmitDeclDestroy(*this, D, GV);
418cc6a44b8bdecd9fc70211146e8ba3853b1fac784Douglas Gregor
419eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson  EmitBlock(EndBlock);
420eb4072ed06c884f1053047ad88846cbffd5ac62eAnders Carlsson}
421772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
422772913659894551b02f342e3577e7219e4f9a701Anders Carlsson/// GenerateCXXAggrDestructorHelper - Generates a helper function which when
423772913659894551b02f342e3577e7219e4f9a701Anders Carlsson/// invoked, calls the default destructor on array elements in reverse order of
424772913659894551b02f342e3577e7219e4f9a701Anders Carlsson/// construction.
425772913659894551b02f342e3577e7219e4f9a701Anders Carlssonllvm::Function *
426772913659894551b02f342e3577e7219e4f9a701Anders CarlssonCodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
427772913659894551b02f342e3577e7219e4f9a701Anders Carlsson                                                 const ArrayType *Array,
428772913659894551b02f342e3577e7219e4f9a701Anders Carlsson                                                 llvm::Value *This) {
429772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  FunctionArgList Args;
430772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  ImplicitParamDecl *Dst =
431772913659894551b02f342e3577e7219e4f9a701Anders Carlsson    ImplicitParamDecl::Create(getContext(), 0,
432772913659894551b02f342e3577e7219e4f9a701Anders Carlsson                              SourceLocation(), 0,
433772913659894551b02f342e3577e7219e4f9a701Anders Carlsson                              getContext().getPointerType(getContext().VoidTy));
434772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  Args.push_back(std::make_pair(Dst, Dst->getType()));
435772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
436772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  const CGFunctionInfo &FI =
437772913659894551b02f342e3577e7219e4f9a701Anders Carlsson    CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args,
438772913659894551b02f342e3577e7219e4f9a701Anders Carlsson                                   FunctionType::ExtInfo());
439772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false);
4409dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson  llvm::Function *Fn =
4419dc046e70d189457968e4c3b986da75b5d98ce8eAnders Carlsson    CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor");
442772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
443772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, Args, SourceLocation());
444772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
445772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  QualType BaseElementTy = getContext().getBaseElementType(Array);
446772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  const llvm::Type *BasePtr = ConvertType(BaseElementTy)->getPointerTo();
447772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  llvm::Value *BaseAddrPtr = Builder.CreateBitCast(This, BasePtr);
448772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
449772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
450772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
451772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  FinishFunction();
452772913659894551b02f342e3577e7219e4f9a701Anders Carlsson
453772913659894551b02f342e3577e7219e4f9a701Anders Carlsson  return Fn;
454772913659894551b02f342e3577e7219e4f9a701Anders Carlsson}
455