zcov: / lib/CodeGen/CGDeclCXX.cpp


Files: 1 Branches Taken: 79.4% 27 / 34
Generated: 2010-02-10 01:31 Branches Executed: 100.0% 34 / 34
Line Coverage: 91.5% 119 / 130


Programs: 1 Runs 2897


       1                 : //===--- CGDeclCXX.cpp - Emit LLVM Code for C++ declarations --------------===//
       2                 : //
       3                 : //                     The LLVM Compiler Infrastructure
       4                 : //
       5                 : // This file is distributed under the University of Illinois Open Source
       6                 : // License. See LICENSE.TXT for details.
       7                 : //
       8                 : //===----------------------------------------------------------------------===//
       9                 : //
      10                 : // This contains code dealing with code generation of C++ declarations
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : 
      14                 : #include "CodeGenFunction.h"
      15                 : using namespace clang;
      16                 : using namespace CodeGen;
      17                 : 
      18                 : static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
      19              119:                          llvm::Constant *DeclPtr) {
                      119: branch 1 taken
                        0: branch 2 not taken
      20              119:   assert(D.hasGlobalStorage() && "VarDecl must have global storage!");
      21                 :   assert(!D.getType()->isReferenceType() && 
                      119: branch 3 taken
                        0: branch 4 not taken
      22              119:          "Should not call EmitDeclInit on a reference!");
      23                 :   
      24              119:   CodeGenModule &CGM = CGF.CGM;
      25              119:   ASTContext &Context = CGF.getContext();
      26                 :     
      27              119:   const Expr *Init = D.getInit();
      28              119:   QualType T = D.getType();
      29              119:   bool isVolatile = Context.getCanonicalType(T).isVolatileQualified();
      30                 : 
                       24: branch 1 taken
                       95: branch 2 taken
      31              119:   if (!CGF.hasAggregateLLVMType(T)) {
      32               24:     llvm::Value *V = CGF.EmitScalarExpr(Init);
      33               24:     CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, T);
                        0: branch 2 not taken
                       95: branch 3 taken
      34               95:   } else if (T->isAnyComplexType()) {
      35                0:     CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
      36                 :   } else {
      37               95:     CGF.EmitAggExpr(Init, DeclPtr, isVolatile);
      38                 :     
      39                 :     // Avoid generating destructor(s) for initialized objects. 
                        0: branch 1 not taken
                       95: branch 2 taken
      40               95:     if (!isa<CXXConstructExpr>(Init))
      41                0:       return;
      42                 :     
      43               95:     const ConstantArrayType *Array = Context.getAsConstantArrayType(T);
                        6: branch 0 taken
                       89: branch 1 taken
      44               95:     if (Array)
      45                6:       T = Context.getBaseElementType(Array);
      46                 :     
      47               95:     const RecordType *RT = T->getAs<RecordType>();
                        0: branch 0 not taken
                       95: branch 1 taken
      48               95:     if (!RT)
      49                0:       return;
      50                 :     
      51               95:     CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
                       75: branch 1 taken
                       20: branch 2 taken
      52               95:     if (RD->hasTrivialDestructor())
      53               75:       return;
      54                 :     
      55               20:     CXXDestructorDecl *Dtor = RD->getDestructor(Context);
      56                 :     
      57                 :     llvm::Constant *DtorFn;
                        6: branch 0 taken
                       14: branch 1 taken
      58               20:     if (Array) {
      59                 :       DtorFn = 
      60                 :         CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor, 
      61                 :                                                              Array, 
      62                6:                                                              DeclPtr);
      63                 :       const llvm::Type *Int8PtrTy =
      64                6:         llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
      65                6:       DeclPtr = llvm::Constant::getNullValue(Int8PtrTy);
      66                 :      } else
      67               14:       DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete);                                
      68                 : 
      69               20:     CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr);
      70                 :   }
      71                 : }
      72                 : 
      73                 : void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
      74              111:                                                llvm::Constant *DeclPtr) {
      75                 : 
      76              111:   const Expr *Init = D.getInit();
      77              111:   QualType T = D.getType();
      78                 : 
                      110: branch 2 taken
                        1: branch 3 taken
      79              111:   if (!T->isReferenceType()) {
      80              110:     EmitDeclInit(*this, D, DeclPtr);
      81              110:     return;
      82                 :   }
                        1: branch 2 taken
                        0: branch 3 not taken
      83                1:   if (Init->isLvalue(getContext()) == Expr::LV_Valid) {
      84                1:     RValue RV = EmitReferenceBindingToExpr(Init, /*IsInitializer=*/true);
      85                1:     EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, T);
      86                1:     return;
      87                 :   }
      88                 :   ErrorUnsupported(Init, 
      89                0:                    "global variable that binds reference to a non-lvalue");
      90                 : }
      91                 : 
      92                 : void
      93                 : CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
      94               20:                                                llvm::Constant *DeclPtr) {
      95                 :   const llvm::Type *Int8PtrTy = 
      96               20:     llvm::Type::getInt8Ty(VMContext)->getPointerTo();
      97                 : 
      98               20:   std::vector<const llvm::Type *> Params;
      99               20:   Params.push_back(Int8PtrTy);
     100                 : 
     101                 :   // Get the destructor function type
     102                 :   const llvm::Type *DtorFnTy =
     103               20:     llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false);
     104               20:   DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy);
     105                 : 
     106               20:   Params.clear();
     107               20:   Params.push_back(DtorFnTy);
     108               20:   Params.push_back(Int8PtrTy);
     109               20:   Params.push_back(Int8PtrTy);
     110                 : 
     111                 :   // Get the __cxa_atexit function type
     112                 :   // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d );
     113                 :   const llvm::FunctionType *AtExitFnTy =
     114               20:     llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false);
     115                 : 
     116                 :   llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy,
     117               20:                                                        "__cxa_atexit");
     118                 : 
     119                 :   llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy,
     120               20:                                                      "__dso_handle");
     121                 :   llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy),
     122                 :                            llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy),
     123               20:                            llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) };
     124               20:   Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args));
     125               20: }
     126                 : 
     127                 : void
     128              111: CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) {
     129                 :   const llvm::FunctionType *FTy
     130                 :     = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
     131              111:                               false);
     132                 : 
     133                 :   // Create a variable initialization function.
     134                 :   llvm::Function *Fn =
     135                 :     llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
     136              111:                            "__cxx_global_var_init", &TheModule);
     137                 : 
     138              111:   CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D);
     139                 : 
     140              111:   CXXGlobalInits.push_back(Fn);
     141              111: }
     142                 : 
     143                 : void
     144              622: CodeGenModule::EmitCXXGlobalInitFunc() {
                      583: branch 1 taken
                       39: branch 2 taken
     145              622:   if (CXXGlobalInits.empty())
     146              583:     return;
     147                 : 
     148                 :   const llvm::FunctionType *FTy
     149                 :     = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
     150               39:                               false);
     151                 : 
     152                 :   // Create our global initialization function.
     153                 :   // FIXME: Should this be tweakable by targets?
     154                 :   llvm::Function *Fn =
     155                 :     llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
     156               39:                            "__cxx_global_initialization", &TheModule);
     157                 : 
     158                 :   CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
     159                 :                                                    &CXXGlobalInits[0],
     160               39:                                                    CXXGlobalInits.size());
     161               39:   AddGlobalCtor(Fn);
     162                 : }
     163                 : 
     164                 : void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
     165              111:                                                        const VarDecl *D) {
     166                 :   StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
     167              111:                 SourceLocation());
     168                 : 
     169              111:   llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D);
     170              111:   EmitCXXGlobalVarDeclInit(*D, DeclPtr);
     171                 : 
     172              111:   FinishFunction();
     173              111: }
     174                 : 
     175                 : void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
     176                 :                                                 llvm::Constant **Decls,
     177               39:                                                 unsigned NumDecls) {
     178                 :   StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
     179               39:                 SourceLocation());
     180                 : 
                      111: branch 0 taken
                       39: branch 1 taken
     181              150:   for (unsigned i = 0; i != NumDecls; ++i)
     182              111:     Builder.CreateCall(Decls[i]);
     183                 : 
     184               39:   FinishFunction();
     185               39: }
     186                 : 
     187                9: static llvm::Constant *getGuardAcquireFn(CodeGenFunction &CGF) {
     188                 :   // int __cxa_guard_acquire(__int64_t *guard_object);
     189                 :   
     190                 :   const llvm::Type *Int64PtrTy = 
     191                9:     llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
     192                 :   
     193                9:   std::vector<const llvm::Type*> Args(1, Int64PtrTy);
     194                 :   
     195                 :   const llvm::FunctionType *FTy =
     196                 :     llvm::FunctionType::get(CGF.ConvertType(CGF.getContext().IntTy),
     197                9:                             Args, /*isVarArg=*/false);
     198                 :   
     199                9:   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire");
     200                 : }
     201                 : 
     202                9: static llvm::Constant *getGuardReleaseFn(CodeGenFunction &CGF) {
     203                 :   // void __cxa_guard_release(__int64_t *guard_object);
     204                 :   
     205                 :   const llvm::Type *Int64PtrTy = 
     206                9:     llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
     207                 :   
     208                9:   std::vector<const llvm::Type*> Args(1, Int64PtrTy);
     209                 :   
     210                 :   const llvm::FunctionType *FTy =
     211                 :   llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
     212                9:                           Args, /*isVarArg=*/false);
     213                 :   
     214                9:   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release");
     215                 : }
     216                 : 
     217                0: static llvm::Constant *getGuardAbortFn(CodeGenFunction &CGF) {
     218                 :   // void __cxa_guard_abort(__int64_t *guard_object);
     219                 :   
     220                 :   const llvm::Type *Int64PtrTy = 
     221                0:     llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
     222                 :   
     223                0:   std::vector<const llvm::Type*> Args(1, Int64PtrTy);
     224                 :   
     225                 :   const llvm::FunctionType *FTy =
     226                 :   llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
     227                0:                           Args, /*isVarArg=*/false);
     228                 :   
     229                0:   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort");
     230                 : }
     231                 : 
     232                 : void
     233                 : CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
     234               10:                                                llvm::GlobalVariable *GV) {
     235               10:   bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics;
     236                 :   
     237               10:   llvm::SmallString<256> GuardVName;
     238               10:   CGM.getMangleContext().mangleGuardVariable(&D, GuardVName);
     239                 : 
     240                 :   // Create the guard variable.
     241               10:   const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(VMContext);
     242                 :   llvm::GlobalValue *GuardVariable =
     243                 :     new llvm::GlobalVariable(CGM.getModule(), Int64Ty,
     244                 :                              false, GV->getLinkage(),
     245                 :                              llvm::Constant::getNullValue(Int64Ty),
     246               10:                              GuardVName.str());
     247                 : 
     248                 :   // Load the first byte of the guard variable.
     249                 :   const llvm::Type *PtrTy
     250               10:     = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
     251                 :   llvm::Value *V = 
     252               10:     Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp");
     253                 : 
     254               10:   llvm::BasicBlock *InitCheckBlock = createBasicBlock("init.check");
     255               10:   llvm::BasicBlock *EndBlock = createBasicBlock("init.end");
     256                 : 
     257                 :   // Check if the first byte of the guard variable is zero.
     258                 :   Builder.CreateCondBr(Builder.CreateIsNull(V, "tobool"), 
     259               10:                        InitCheckBlock, EndBlock);
     260                 : 
     261               10:   EmitBlock(InitCheckBlock);
     262                 : 
                        9: branch 0 taken
                        1: branch 1 taken
     263               10:   if (ThreadsafeStatics) {
     264                 :     // Call __cxa_guard_acquire.
     265                9:     V = Builder.CreateCall(getGuardAcquireFn(*this), GuardVariable);
     266                 :                
     267                9:     llvm::BasicBlock *InitBlock = createBasicBlock("init");
     268                 :   
     269                 :     Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),
     270                9:                          InitBlock, EndBlock);
     271                 :   
     272                9:     EmitBlock(InitBlock);
     273                 : 
                        0: branch 0 not taken
                        9: branch 1 taken
     274                9:     if (Exceptions) {
     275                0:       EHCleanupBlock Cleanup(*this);
     276                 :     
     277                 :       // Call __cxa_guard_abort.
     278                0:       Builder.CreateCall(getGuardAbortFn(*this), GuardVariable);
     279                 :     }
     280                 :   }
     281                 : 
                        1: branch 3 taken
                        9: branch 4 taken
     282               10:   if (D.getType()->isReferenceType()) {
     283                1:     QualType T = D.getType();
     284                 :     // We don't want to pass true for IsInitializer here, because a static
     285                 :     // reference to a temporary does not extend its lifetime.
     286                 :     RValue RV = EmitReferenceBindingToExpr(D.getInit(),
     287                1:                                            /*IsInitializer=*/false);
     288                1:     EmitStoreOfScalar(RV.getScalarVal(), GV, /*Volatile=*/false, T);
     289                 : 
     290                 :   } else
     291                9:     EmitDeclInit(*this, D, GV);
     292                 : 
                        9: branch 0 taken
                        1: branch 1 taken
     293               10:   if (ThreadsafeStatics) {
     294                 :     // Call __cxa_guard_release.
     295                9:     Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable);
     296                 :   } else {
     297                 :     llvm::Value *One = 
     298                1:       llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1);
     299                1:     Builder.CreateStore(One, Builder.CreateBitCast(GuardVariable, PtrTy));
     300                 :   }
     301                 : 
     302               10:   EmitBlock(EndBlock);
     303               10: }

Generated: 2010-02-10 01:31 by zcov