zcov: / lib/CodeGen/CGDecl.cpp


Files: 1 Branches Taken: 79.2% 145 / 183
Generated: 2010-02-10 01:31 Branches Executed: 95.6% 175 / 183
Line Coverage: 90.3% 290 / 321


Programs: 1 Runs 2897


       1                 : //===--- CGDecl.cpp - Emit LLVM Code for 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 to emit Decl nodes as LLVM code.
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : 
      14                 : #include "CGDebugInfo.h"
      15                 : #include "CodeGenFunction.h"
      16                 : #include "CodeGenModule.h"
      17                 : #include "clang/AST/ASTContext.h"
      18                 : #include "clang/AST/CharUnits.h"
      19                 : #include "clang/AST/Decl.h"
      20                 : #include "clang/AST/DeclObjC.h"
      21                 : #include "clang/Basic/SourceManager.h"
      22                 : #include "clang/Basic/TargetInfo.h"
      23                 : #include "clang/CodeGen/CodeGenOptions.h"
      24                 : #include "llvm/GlobalVariable.h"
      25                 : #include "llvm/Intrinsics.h"
      26                 : #include "llvm/Target/TargetData.h"
      27                 : #include "llvm/Type.h"
      28                 : using namespace clang;
      29                 : using namespace CodeGen;
      30                 : 
      31                 : 
      32             1276: void CodeGenFunction::EmitDecl(const Decl &D) {
                        0: branch 1 not taken
                        0: branch 2 not taken
                       80: branch 3 taken
                     1191: branch 4 taken
                        5: branch 5 taken
      33             1276:   switch (D.getKind()) {
      34                 :   default:
      35                0:     CGM.ErrorUnsupported(&D, "decl");
      36                0:     return;
      37                 :   case Decl::ParmVar:
      38                0:     assert(0 && "Parmdecls should not be in declstmts!");
      39                 :   case Decl::Function:  // void X();
      40                 :   case Decl::Record:    // struct/union/class X;
      41                 :   case Decl::Enum:      // enum X;
      42                 :   case Decl::EnumConstant: // enum ? { X = ? }
      43                 :   case Decl::CXXRecord: // struct/union/class X; [C++]
      44                 :   case Decl::Using:          // using X; [C++]
      45                 :   case Decl::UsingShadow:
      46                 :   case Decl::UsingDirective: // using namespace X; [C++]
      47                 :   case Decl::StaticAssert: // static_assert(X, ""); [C++0x]
      48                 :     // None of these decls require codegen support.
      49               80:     return;
      50                 : 
      51                 :   case Decl::Var: {
      52             1191:     const VarDecl &VD = cast<VarDecl>(D);
      53                 :     assert(VD.isBlockVarDecl() &&
                     1191: branch 1 taken
                        0: branch 2 not taken
      54             1191:            "Should not see file-scope variables inside a function!");
      55             1191:     return EmitBlockVarDecl(VD);
      56                 :   }
      57                 : 
      58                 :   case Decl::Typedef: {   // typedef int X;
      59                5:     const TypedefDecl &TD = cast<TypedefDecl>(D);
      60                5:     QualType Ty = TD.getUnderlyingType();
      61                 : 
                        2: branch 2 taken
                        3: branch 3 taken
      62                5:     if (Ty->isVariablyModifiedType())
      63                2:       EmitVLASize(Ty);
      64                 :   }
      65                 :   }
      66                 : }
      67                 : 
      68                 : /// EmitBlockVarDecl - This method handles emission of any variable declaration
      69                 : /// inside a function, including static vars etc.
      70             1191: void CodeGenFunction::EmitBlockVarDecl(const VarDecl &D) {
                        0: branch 1 not taken
                     1191: branch 2 taken
      71             1191:   if (D.hasAttr<AsmLabelAttr>())
      72                0:     CGM.ErrorUnsupported(&D, "__asm__");
      73                 : 
                     1099: branch 1 taken
                       77: branch 2 taken
                       15: branch 3 taken
                        0: branch 4 not taken
      74             1191:   switch (D.getStorageClass()) {
      75                 :   case VarDecl::None:
      76                 :   case VarDecl::Auto:
      77                 :   case VarDecl::Register:
      78             1099:     return EmitLocalBlockVarDecl(D);
      79                 :   case VarDecl::Static: {
      80                 :     llvm::GlobalValue::LinkageTypes Linkage = 
      81               77:       llvm::GlobalValue::InternalLinkage;
      82                 : 
      83                 :     // If this is a static declaration inside an inline function, it must have
      84                 :     // weak linkage so that the linker will merge multiple definitions of it.
                       18: branch 2 taken
                       59: branch 3 taken
      85               77:     if (getContext().getLangOptions().CPlusPlus) {
                       16: branch 1 taken
                        2: branch 2 taken
      86               18:       if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurFuncDecl)) {
                        5: branch 1 taken
                       11: branch 2 taken
      87               16:         if (FD->isInlined())
      88                5:           Linkage = llvm::GlobalValue::WeakAnyLinkage;
      89                 :       }
      90                 :     }
      91                 :     
      92               77:     return EmitStaticBlockVarDecl(D, Linkage);
      93                 :   }
      94                 :   case VarDecl::Extern:
      95                 :   case VarDecl::PrivateExtern:
      96                 :     // Don't emit it now, allow it to be emitted lazily on its first use.
      97               15:     return;
      98                 :   }
      99                 : 
     100                0:   assert(0 && "Unknown storage class");
     101                 : }
     102                 : 
     103                 : static std::string GetStaticDeclName(CodeGenFunction &CGF, const VarDecl &D,
     104              124:                                      const char *Separator) {
     105              124:   CodeGenModule &CGM = CGF.CGM;
                       20: branch 2 taken
                      104: branch 3 taken
     106              124:   if (CGF.getContext().getLangOptions().CPlusPlus)
     107               20:     return CGM.getMangledName(&D);
     108                 :   
     109              104:   std::string ContextName;
                       99: branch 1 taken
                        5: branch 2 taken
     110              104:   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CGF.CurFuncDecl))
     111               99:     ContextName = CGM.getMangledName(FD);
                        5: branch 1 taken
                        0: branch 2 not taken
     112                5:   else if (isa<ObjCMethodDecl>(CGF.CurFuncDecl))
     113                5:     ContextName = CGF.CurFn->getName();
     114                 :   else
     115                 :     // FIXME: What about in a block??
     116                0:     assert(0 && "Unknown context for block var decl");
     117                 :   
     118              104:   return ContextName + Separator + D.getNameAsString();
     119                 : }
     120                 : 
     121                 : llvm::GlobalVariable *
     122                 : CodeGenFunction::CreateStaticBlockVarDecl(const VarDecl &D,
     123                 :                                           const char *Separator,
     124               79:                                       llvm::GlobalValue::LinkageTypes Linkage) {
     125               79:   QualType Ty = D.getType();
                       79: branch 2 taken
                        0: branch 3 not taken
     126               79:   assert(Ty->isConstantSizeType() && "VLAs can't be static");
     127                 : 
     128               79:   std::string Name = GetStaticDeclName(*this, D, Separator);
     129                 : 
     130               79:   const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(Ty);
     131                 :   llvm::GlobalVariable *GV =
     132                 :     new llvm::GlobalVariable(CGM.getModule(), LTy,
     133                 :                              Ty.isConstant(getContext()), Linkage,
     134                 :                              CGM.EmitNullConstant(D.getType()), Name, 0,
     135               79:                              D.isThreadSpecified(), Ty.getAddressSpace());
     136               79:   GV->setAlignment(getContext().getDeclAlign(&D).getQuantity());
     137               79:   return GV;
     138                 : }
     139                 : 
     140                 : /// AddInitializerToGlobalBlockVarDecl - Add the initializer for 'D' to the
     141                 : /// global variable that has already been created for it.  If the initializer
     142                 : /// has a different type than GV does, this may free GV and return a different
     143                 : /// one.  Otherwise it just returns GV.
     144                 : llvm::GlobalVariable *
     145                 : CodeGenFunction::AddInitializerToGlobalBlockVarDecl(const VarDecl &D,
     146               49:                                                     llvm::GlobalVariable *GV) {
     147               49:   llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), D.getType(), this);
     148                 :   
     149                 :   // If constant emission failed, then this should be a C++ static
     150                 :   // initializer.
                       10: branch 0 taken
                       39: branch 1 taken
     151               49:   if (!Init) {
                        0: branch 2 not taken
                       10: branch 3 taken
     152               10:     if (!getContext().getLangOptions().CPlusPlus)
     153                0:       CGM.ErrorUnsupported(D.getInit(), "constant l-value expression");
     154                 :     else {
     155                 :       // Since we have a static initializer, this global variable can't 
     156                 :       // be constant.
     157               10:       GV->setConstant(false);
     158                 :       
     159               10:       EmitStaticCXXBlockVarDeclInit(D, GV);
     160                 :     }
     161               10:     return GV;
     162                 :   }
     163                 :   
     164                 :   // The initializer may differ in type from the global. Rewrite
     165                 :   // the global to match the initializer.  (We have to do this
     166                 :   // because some types, like unions, can't be completely represented
     167                 :   // in the LLVM type system.)
                       39: branch 2 taken
                        0: branch 3 not taken
     168               39:   if (GV->getType() != Init->getType()) {
     169               39:     llvm::GlobalVariable *OldGV = GV;
     170                 :     
     171                 :     GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(),
     172                 :                                   OldGV->isConstant(),
     173                 :                                   OldGV->getLinkage(), Init, "",
     174                 :                                   0, D.isThreadSpecified(),
     175               39:                                   D.getType().getAddressSpace());
     176                 :     
     177                 :     // Steal the name of the old global
     178               39:     GV->takeName(OldGV);
     179                 :     
     180                 :     // Replace all uses of the old global with the new global
     181                 :     llvm::Constant *NewPtrForOldDecl =
     182               39:     llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
     183               39:     OldGV->replaceAllUsesWith(NewPtrForOldDecl);
     184                 :     
     185                 :     // Erase the old global, since it is no longer used.
     186               39:     OldGV->eraseFromParent();
     187                 :   }
     188                 :   
     189               39:   GV->setInitializer(Init);
     190               39:   return GV;
     191                 : }
     192                 : 
     193                 : void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D,
     194               79:                                       llvm::GlobalValue::LinkageTypes Linkage) {
     195               79:   llvm::Value *&DMEntry = LocalDeclMap[&D];
                        0: branch 0 not taken
                       79: branch 1 taken
     196               79:   assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
     197                 : 
     198               79:   llvm::GlobalVariable *GV = CreateStaticBlockVarDecl(D, ".", Linkage);
     199                 : 
     200                 :   // Store into LocalDeclMap before generating initializer to handle
     201                 :   // circular references.
     202               79:   DMEntry = GV;
     203                 : 
     204                 :   // Make sure to evaluate VLA bounds now so that we have them for later.
     205                 :   //
     206                 :   // FIXME: Can this happen?
                        1: branch 3 taken
                       78: branch 4 taken
     207               79:   if (D.getType()->isVariablyModifiedType())
     208                1:     EmitVLASize(D.getType());
     209                 : 
     210                 :   // If this value has an initializer, emit it.
                       49: branch 1 taken
                       30: branch 2 taken
     211               79:   if (D.getInit())
     212               49:     GV = AddInitializerToGlobalBlockVarDecl(D, GV);
     213                 : 
     214                 :   // FIXME: Merge attribute handling.
                        1: branch 1 taken
                       78: branch 2 taken
     215               79:   if (const AnnotateAttr *AA = D.getAttr<AnnotateAttr>()) {
     216                1:     SourceManager &SM = CGM.getContext().getSourceManager();
     217                 :     llvm::Constant *Ann =
     218                 :       CGM.EmitAnnotateAttr(GV, AA,
     219                1:                            SM.getInstantiationLineNumber(D.getLocation()));
     220                1:     CGM.AddAnnotation(Ann);
     221                 :   }
     222                 : 
                        1: branch 1 taken
                       78: branch 2 taken
     223               79:   if (const SectionAttr *SA = D.getAttr<SectionAttr>())
     224                1:     GV->setSection(SA->getName());
     225                 : 
                        1: branch 1 taken
                       78: branch 2 taken
     226               79:   if (D.hasAttr<UsedAttr>())
     227                1:     CGM.AddUsedGlobal(GV);
     228                 : 
     229                 :   // We may have to cast the constant because of the initializer
     230                 :   // mismatch above.
     231                 :   //
     232                 :   // FIXME: It is really dangerous to store this in the map; if anyone
     233                 :   // RAUW's the GV uses of this constant will be invalid.
     234               79:   const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(D.getType());
     235                 :   const llvm::Type *LPtrTy =
     236               79:     llvm::PointerType::get(LTy, D.getType().getAddressSpace());
     237               79:   DMEntry = llvm::ConstantExpr::getBitCast(GV, LPtrTy);
     238                 : 
     239                 :   // Emit global variable debug descriptor for static vars.
     240               79:   CGDebugInfo *DI = getDebugInfo();
                        1: branch 0 taken
                       78: branch 1 taken
     241               79:   if (DI) {
     242                1:     DI->setLocation(D.getLocation());
     243                1:     DI->EmitGlobalVariable(static_cast<llvm::GlobalVariable *>(GV), &D);
     244                 :   }
     245               79: }
     246                 : 
     247               46: unsigned CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const {
                       46: branch 1 taken
                        0: branch 2 not taken
     248               46:   assert(ByRefValueInfo.count(VD) && "Did not find value!");
     249                 :   
     250               46:   return ByRefValueInfo.find(VD)->second.second;
     251                 : }
     252                 : 
     253                 : /// BuildByRefType - This routine changes a __block variable declared as T x
     254                 : ///   into:
     255                 : ///
     256                 : ///      struct {
     257                 : ///        void *__isa;
     258                 : ///        void *__forwarding;
     259                 : ///        int32_t __flags;
     260                 : ///        int32_t __size;
     261                 : ///        void *__copy_helper;       // only if needed
     262                 : ///        void *__destroy_helper;    // only if needed
     263                 : ///        char padding[X];           // only if needed
     264                 : ///        T x;
     265                 : ///      } x
     266                 : ///
     267               73: const llvm::Type *CodeGenFunction::BuildByRefType(const ValueDecl *D) {
     268               73:   std::pair<const llvm::Type *, unsigned> &Info = ByRefValueInfo[D];
                       26: branch 0 taken
                       47: branch 1 taken
     269               73:   if (Info.first)
     270               26:     return Info.first;
     271                 :   
     272               47:   QualType Ty = D->getType();
     273                 : 
     274               47:   std::vector<const llvm::Type *> Types;
     275                 :   
     276               47:   const llvm::PointerType *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
     277                 : 
     278               47:   llvm::PATypeHolder ByRefTypeHolder = llvm::OpaqueType::get(VMContext);
     279                 :   
     280                 :   // void *__isa;
     281               47:   Types.push_back(Int8PtrTy);
     282                 :   
     283                 :   // void *__forwarding;
     284               47:   Types.push_back(llvm::PointerType::getUnqual(ByRefTypeHolder));
     285                 :   
     286                 :   // int32_t __flags;
     287               47:   Types.push_back(llvm::Type::getInt32Ty(VMContext));
     288                 :     
     289                 :   // int32_t __size;
     290               47:   Types.push_back(llvm::Type::getInt32Ty(VMContext));
     291                 : 
     292               47:   bool HasCopyAndDispose = BlockRequiresCopying(Ty);
                       25: branch 0 taken
                       22: branch 1 taken
     293               47:   if (HasCopyAndDispose) {
     294                 :     /// void *__copy_helper;
     295               25:     Types.push_back(Int8PtrTy);
     296                 :     
     297                 :     /// void *__destroy_helper;
     298               25:     Types.push_back(Int8PtrTy);
     299                 :   }
     300                 : 
     301               47:   bool Packed = false;
     302               47:   CharUnits Align = getContext().getDeclAlign(D);
                        0: branch 3 not taken
                       47: branch 4 taken
     303               47:   if (Align > CharUnits::fromQuantity(Target.getPointerAlign(0) / 8)) {
     304                 :     // We have to insert padding.
     305                 :     
     306                 :     // The struct above has 2 32-bit integers.
     307                0:     unsigned CurrentOffsetInBytes = 4 * 2;
     308                 :     
     309                 :     // And either 2 or 4 pointers.
     310                 :     CurrentOffsetInBytes += (HasCopyAndDispose ? 4 : 2) *
                        0: branch 0 not taken
                        0: branch 1 not taken
     311                0:       CGM.getTargetData().getTypeAllocSize(Int8PtrTy);
     312                 :     
     313                 :     // Align the offset.
     314                 :     unsigned AlignedOffsetInBytes = 
     315                0:       llvm::RoundUpToAlignment(CurrentOffsetInBytes, Align.getQuantity());
     316                 :     
     317                0:     unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes;
                        0: branch 0 not taken
                        0: branch 1 not taken
     318                0:     if (NumPaddingBytes > 0) {
     319                0:       const llvm::Type *Ty = llvm::Type::getInt8Ty(VMContext);
     320                 :       // FIXME: We need a sema error for alignment larger than the minimum of
     321                 :       // the maximal stack alignmint and the alignment of malloc on the system.
                        0: branch 0 not taken
                        0: branch 1 not taken
     322                0:       if (NumPaddingBytes > 1)
     323                0:         Ty = llvm::ArrayType::get(Ty, NumPaddingBytes);
     324                 :     
     325                0:       Types.push_back(Ty);
     326                 : 
     327                 :       // We want a packed struct.
     328                0:       Packed = true;
     329                 :     }
     330                 :   }
     331                 : 
     332                 :   // T x;
     333               47:   Types.push_back(ConvertType(Ty));
     334                 :   
     335               47:   const llvm::Type *T = llvm::StructType::get(VMContext, Types, Packed);
     336                 :   
     337               47:   cast<llvm::OpaqueType>(ByRefTypeHolder.get())->refineAbstractTypeTo(T);
     338                 :   CGM.getModule().addTypeName("struct.__block_byref_" + D->getNameAsString(), 
     339               47:                               ByRefTypeHolder.get());
     340                 :   
     341               47:   Info.first = ByRefTypeHolder.get();
     342                 :   
     343               47:   Info.second = Types.size() - 1;
     344                 :   
     345               47:   return Info.first;
     346                 : }
     347                 : 
     348                 : /// EmitLocalBlockVarDecl - Emit code and set up an entry in LocalDeclMap for a
     349                 : /// variable declaration with auto, register, or no storage class specifier.
     350                 : /// These turn into simple stack objects, or GlobalValues depending on target.
     351             1129: void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
     352             1129:   QualType Ty = D.getType();
     353             1129:   bool isByRef = D.hasAttr<BlocksAttr>();
     354             1129:   bool needsDispose = false;
     355             1129:   CharUnits Align = CharUnits::Zero();
     356             1129:   bool IsSimpleConstantInitializer = false;
     357                 : 
     358                 :   llvm::Value *DeclPtr;
                     1118: branch 2 taken
                       11: branch 3 taken
     359             1129:   if (Ty->isConstantSizeType()) {
                     1118: branch 1 taken
                        0: branch 2 not taken
     360             1118:     if (!Target.useGlobalsForAutomaticVariables()) {
     361                 :       
     362                 :       // If this value is an array or struct, is POD, and if the initializer is
     363                 :       // a staticly determinable constant, try to optimize it.
                      805: branch 1 taken
                      313: branch 2 taken
                      800: branch 3 taken
                        5: branch 4 taken
                      773: branch 7 taken
                       27: branch 8 taken
                      224: branch 11 taken
                      549: branch 12 taken
                       96: branch 15 taken
                      155: branch 16 taken
                       49: branch 20 taken
                       47: branch 21 taken
                       49: branch 22 taken
                     1069: branch 23 taken
     364             1118:       if (D.getInit() && !isByRef &&
     365                 :           (Ty->isArrayType() || Ty->isRecordType()) &&
     366                 :           Ty->isPODType() &&
     367                 :           D.getInit()->isConstantInitializer(getContext())) {
     368                 :         // If this variable is marked 'const', emit the value as a global.
                       49: branch 1 taken
                        0: branch 2 not taken
                        2: branch 5 taken
                       47: branch 6 taken
                        2: branch 7 taken
                       47: branch 8 taken
     369               49:         if (CGM.getCodeGenOpts().MergeAllConstants &&
     370                 :             Ty.isConstant(getContext())) {
     371                2:           EmitStaticBlockVarDecl(D, llvm::GlobalValue::InternalLinkage);
     372                2:           return;
     373                 :         }
     374                 :         
     375               47:         IsSimpleConstantInitializer = true;
     376                 :       }
     377                 :       
     378                 :       // A normal fixed sized variable becomes an alloca in the entry block.
     379             1116:       const llvm::Type *LTy = ConvertTypeForMem(Ty);
                       24: branch 0 taken
                     1092: branch 1 taken
     380             1116:       if (isByRef)
     381               24:         LTy = BuildByRefType(&D);
     382             1116:       llvm::AllocaInst *Alloc = CreateTempAlloca(LTy);
     383             1116:       Alloc->setName(D.getNameAsString());
     384                 : 
     385             1116:       Align = getContext().getDeclAlign(&D);
                       24: branch 0 taken
                     1092: branch 1 taken
     386             1116:       if (isByRef)
     387                 :         Align = std::max(Align, 
     388               24:             CharUnits::fromQuantity(Target.getPointerAlign(0) / 8));
     389             1116:       Alloc->setAlignment(Align.getQuantity());
     390             1116:       DeclPtr = Alloc;
     391                 :     } else {
     392                 :       // Targets that don't support recursion emit locals as globals.
     393                 :       const char *Class =
                        0: branch 1 not taken
                        0: branch 2 not taken
     394                0:         D.getStorageClass() == VarDecl::Register ? ".reg." : ".auto.";
     395                 :       DeclPtr = CreateStaticBlockVarDecl(D, Class,
     396                 :                                          llvm::GlobalValue
     397                0:                                          ::InternalLinkage);
     398                 :     }
     399                 : 
     400                 :     // FIXME: Can this happen?
                        4: branch 2 taken
                     1112: branch 3 taken
     401             1116:     if (Ty->isVariablyModifiedType())
     402                4:       EmitVLASize(Ty);
     403                 :   } else {
     404               11:     EnsureInsertPoint();
     405                 : 
                       11: branch 0 taken
                        0: branch 1 not taken
     406               11:     if (!DidCallStackSave) {
     407                 :       // Save the stack.
     408               11:       const llvm::Type *LTy = llvm::Type::getInt8PtrTy(VMContext);
     409               11:       llvm::Value *Stack = CreateTempAlloca(LTy, "saved_stack");
     410                 : 
     411               11:       llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stacksave);
     412               11:       llvm::Value *V = Builder.CreateCall(F);
     413                 : 
     414               11:       Builder.CreateStore(V, Stack);
     415                 : 
     416               11:       DidCallStackSave = true;
     417                 : 
     418                 :       {
     419                 :         // Push a cleanup block and restore the stack there.
     420               11:         DelayedCleanupBlock scope(*this);
     421                 : 
     422               11:         V = Builder.CreateLoad(Stack, "tmp");
     423               11:         llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stackrestore);
     424               11:         Builder.CreateCall(F, V);
     425                 :       }
     426                 :     }
     427                 : 
     428                 :     // Get the element type.
     429               11:     const llvm::Type *LElemTy = ConvertTypeForMem(Ty);
     430                 :     const llvm::Type *LElemPtrTy =
     431               11:       llvm::PointerType::get(LElemTy, D.getType().getAddressSpace());
     432                 : 
     433               11:     llvm::Value *VLASize = EmitVLASize(Ty);
     434                 : 
     435                 :     // Downcast the VLA size expression
     436                 :     VLASize = Builder.CreateIntCast(VLASize, llvm::Type::getInt32Ty(VMContext),
     437               11:                                     false, "tmp");
     438                 : 
     439                 :     // Allocate memory for the array.
     440                 :     llvm::AllocaInst *VLA = 
     441               11:       Builder.CreateAlloca(llvm::Type::getInt8Ty(VMContext), VLASize, "vla");
     442               11:     VLA->setAlignment(getContext().getDeclAlign(&D).getQuantity());
     443                 : 
     444               11:     DeclPtr = Builder.CreateBitCast(VLA, LElemPtrTy, "tmp");
     445                 :   }
     446                 : 
     447             1127:   llvm::Value *&DMEntry = LocalDeclMap[&D];
                        0: branch 0 not taken
                     1127: branch 1 taken
     448             1127:   assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
     449             1127:   DMEntry = DeclPtr;
     450                 : 
     451                 :   // Emit debug info for local var declaration.
                      138: branch 1 taken
                      989: branch 2 taken
     452             1127:   if (CGDebugInfo *DI = getDebugInfo()) {
                      138: branch 1 taken
                        0: branch 2 not taken
     453              138:     assert(HaveInsertPoint() && "Unexpected unreachable point!");
     454                 : 
     455              138:     DI->setLocation(D.getLocation());
                        0: branch 1 not taken
                      138: branch 2 taken
     456              138:     if (Target.useGlobalsForAutomaticVariables()) {
     457                0:       DI->EmitGlobalVariable(static_cast<llvm::GlobalVariable *>(DeclPtr), &D);
     458                 :     } else
     459              138:       DI->EmitDeclareOfAutoVariable(&D, DeclPtr, Builder);
     460                 :   }
     461                 : 
     462                 :   // If this local has an initializer, emit it now.
     463             1127:   const Expr *Init = D.getInit();
     464                 : 
     465                 :   // If we are at an unreachable point, we don't need to emit the initializer
     466                 :   // unless it contains a label.
                        2: branch 1 taken
                     1125: branch 2 taken
     467             1127:   if (!HaveInsertPoint()) {
                        2: branch 1 taken
                        0: branch 2 not taken
     468                2:     if (!ContainsLabel(Init))
     469                2:       Init = 0;
     470                 :     else
     471                0:       EnsureInsertPoint();
     472                 :   }
     473                 : 
                      802: branch 0 taken
                      325: branch 1 taken
     474             1127:   if (Init) {
     475              802:     llvm::Value *Loc = DeclPtr;
                        5: branch 0 taken
                      797: branch 1 taken
     476              802:     if (isByRef)
     477                 :       Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D), 
     478                5:                                     D.getNameAsString());
     479                 : 
     480                 :     bool isVolatile =
     481              802:       getContext().getCanonicalType(D.getType()).isVolatileQualified();
     482                 :     
     483                 :     // If the initializer was a simple constant initializer, we can optimize it
     484                 :     // in various ways.
                       47: branch 0 taken
                      755: branch 1 taken
     485              802:     if (IsSimpleConstantInitializer) {
     486               47:       llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(),D.getType(),this);
                        0: branch 0 not taken
                       47: branch 1 taken
     487               47:       assert(Init != 0 && "Wasn't a simple constant init?");
     488                 :       
     489                 :       llvm::Value *AlignVal = 
     490                 :         llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 
     491               47:             Align.getQuantity());
     492                 :       const llvm::Type *IntPtr =
     493               47:         llvm::IntegerType::get(VMContext, LLVMPointerWidth);
     494                 :       llvm::Value *SizeVal =
     495                 :         llvm::ConstantInt::get(IntPtr, 
     496               47:             getContext().getTypeSizeInChars(Ty).getQuantity());
     497                 : 
     498               47:       const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext);
                       47: branch 1 taken
                        0: branch 2 not taken
     499               47:       if (Loc->getType() != BP)
     500               47:         Loc = Builder.CreateBitCast(Loc, BP, "tmp");
     501                 :       
     502                 :       // If the initializer is all zeros, codegen with memset.
                        2: branch 1 taken
                       45: branch 2 taken
     503               47:       if (isa<llvm::ConstantAggregateZero>(Init)) {
     504                 :         llvm::Value *Zero =
     505                2:           llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 0);
     506                2:         Builder.CreateCall4(CGM.getMemSetFn(), Loc, Zero, SizeVal, AlignVal);
     507                 :       } else {
     508                 :         // Otherwise, create a temporary global with the initializer then 
     509                 :         // memcpy from the global to the alloca.
     510               45:         std::string Name = GetStaticDeclName(*this, D, ".");
     511                 :         llvm::GlobalVariable *GV =
     512                 :           new llvm::GlobalVariable(CGM.getModule(), Init->getType(), true,
     513                 :                                    llvm::GlobalValue::InternalLinkage,
     514               45:                                    Init, Name, 0, false, 0);
     515               45:         GV->setAlignment(Align.getQuantity());
     516                 : 
     517               45:         llvm::Value *SrcPtr = GV;
                       45: branch 1 taken
                        0: branch 2 not taken
     518               45:         if (SrcPtr->getType() != BP)
     519               45:           SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp");
     520                 :         
     521               45:         Builder.CreateCall4(CGM.getMemCpyFn(), Loc, SrcPtr, SizeVal, AlignVal);
     522                 :       }
                       10: branch 2 taken
                      745: branch 3 taken
     523              755:     } else if (Ty->isReferenceType()) {
     524               10:       RValue RV = EmitReferenceBindingToExpr(Init, /*IsInitializer=*/true);
     525               10:       EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Ty);
                      514: branch 2 taken
                      231: branch 3 taken
     526              745:     } else if (!hasAggregateLLVMType(Init->getType())) {
     527              514:       llvm::Value *V = EmitScalarExpr(Init);
     528              514:       EmitStoreOfScalar(V, Loc, isVolatile, D.getType());
                       23: branch 3 taken
                      208: branch 4 taken
     529              231:     } else if (Init->getType()->isAnyComplexType()) {
     530               23:       EmitComplexExprIntoAddr(Init, Loc, isVolatile);
     531                 :     } else {
     532              208:       EmitAggExpr(Init, Loc, isVolatile);
     533                 :     }
     534                 :   }
     535                 : 
                       24: branch 0 taken
                     1103: branch 1 taken
     536             1127:   if (isByRef) {
     537               24:     const llvm::PointerType *PtrToInt8Ty = llvm::Type::getInt8PtrTy(VMContext);
     538                 : 
     539               24:     EnsureInsertPoint();
     540               24:     llvm::Value *isa_field = Builder.CreateStructGEP(DeclPtr, 0);
     541               24:     llvm::Value *forwarding_field = Builder.CreateStructGEP(DeclPtr, 1);
     542               24:     llvm::Value *flags_field = Builder.CreateStructGEP(DeclPtr, 2);
     543               24:     llvm::Value *size_field = Builder.CreateStructGEP(DeclPtr, 3);
     544                 :     llvm::Value *V;
     545               24:     int flag = 0;
     546               24:     int flags = 0;
     547                 : 
     548               24:     needsDispose = true;
     549                 : 
                        2: branch 2 taken
                       22: branch 3 taken
     550               24:     if (Ty->isBlockPointerType()) {
     551                2:       flag |= BLOCK_FIELD_IS_BLOCK;
     552                2:       flags |= BLOCK_HAS_COPY_DISPOSE;
                       11: branch 1 taken
                       11: branch 2 taken
     553               22:     } else if (BlockRequiresCopying(Ty)) {
     554               11:       flag |= BLOCK_FIELD_IS_OBJECT;
     555               11:       flags |= BLOCK_HAS_COPY_DISPOSE;
     556                 :     }
     557                 : 
     558                 :     // FIXME: Someone double check this.
                        3: branch 1 taken
                       21: branch 2 taken
     559               24:     if (Ty.isObjCGCWeak())
     560                3:       flag |= BLOCK_FIELD_IS_WEAK;
     561                 : 
     562               24:     int isa = 0;
                        3: branch 0 taken
                       21: branch 1 taken
     563               24:     if (flag&BLOCK_FIELD_IS_WEAK)
     564                3:       isa = 1;
     565               24:     V = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), isa);
     566               24:     V = Builder.CreateIntToPtr(V, PtrToInt8Ty, "isa");
     567               24:     Builder.CreateStore(V, isa_field);
     568                 : 
     569               24:     Builder.CreateStore(DeclPtr, forwarding_field);
     570                 : 
     571               24:     V = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), flags);
     572               24:     Builder.CreateStore(V, flags_field);
     573                 : 
     574                 :     const llvm::Type *V1;
     575               24:     V1 = cast<llvm::PointerType>(DeclPtr->getType())->getElementType();
     576                 :     V = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
     577               24:                                CGM.GetTargetTypeStoreSize(V1).getQuantity());
     578               24:     Builder.CreateStore(V, size_field);
     579                 : 
                       13: branch 0 taken
                       11: branch 1 taken
     580               24:     if (flags & BLOCK_HAS_COPY_DISPOSE) {
     581               13:       BlockHasCopyDispose = true;
     582               13:       llvm::Value *copy_helper = Builder.CreateStructGEP(DeclPtr, 4);
     583                 :       Builder.CreateStore(BuildbyrefCopyHelper(DeclPtr->getType(), flag, 
     584                 :                                                Align.getQuantity()),
     585               13:                           copy_helper);
     586                 : 
     587               13:       llvm::Value *destroy_helper = Builder.CreateStructGEP(DeclPtr, 5);
     588                 :       Builder.CreateStore(BuildbyrefDestroyHelper(DeclPtr->getType(), flag,
     589                 :                                                   Align.getQuantity()),
     590               13:                           destroy_helper);
     591                 :     }
     592                 :   }
     593                 : 
     594                 :   // Handle CXX destruction of variables.
     595             1127:   QualType DtorTy(Ty);
                       67: branch 2 taken
                     1127: branch 3 taken
     596             1261:   while (const ArrayType *Array = getContext().getAsArrayType(DtorTy))
     597               67:     DtorTy = getContext().getBaseElementType(Array);
                      299: branch 2 taken
                      828: branch 3 taken
     598             1127:   if (const RecordType *RT = DtorTy->getAs<RecordType>())
                      184: branch 2 taken
                      115: branch 3 taken
     599              299:     if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
                       57: branch 1 taken
                      127: branch 2 taken
     600              184:       if (!ClassDecl->hasTrivialDestructor()) {
     601               57:         const CXXDestructorDecl *D = ClassDecl->getDestructor(getContext());
                        0: branch 0 not taken
                       57: branch 1 taken
     602               57:         assert(D && "EmitLocalBlockVarDecl - destructor is nul");
     603                 :         
                        2: branch 0 taken
                       55: branch 1 taken
     604               57:         if (const ConstantArrayType *Array = 
     605               57:               getContext().getAsConstantArrayType(Ty)) {
     606                 :           {
     607                2:             DelayedCleanupBlock Scope(*this);
     608                2:             QualType BaseElementTy = getContext().getBaseElementType(Array);
     609                2:             const llvm::Type *BasePtr = ConvertType(BaseElementTy);
     610                2:             BasePtr = llvm::PointerType::getUnqual(BasePtr);
     611                 :             llvm::Value *BaseAddrPtr =
     612                2:               Builder.CreateBitCast(DeclPtr, BasePtr);
     613                2:             EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
     614                 :           
     615                 :             // Make sure to jump to the exit block.
     616                2:             EmitBranch(Scope.getCleanupExitBlock());
     617                 :           }
                        0: branch 0 not taken
                        2: branch 1 taken
     618                2:           if (Exceptions) {
     619                0:             EHCleanupBlock Cleanup(*this);
     620                0:             QualType BaseElementTy = getContext().getBaseElementType(Array);
     621                0:             const llvm::Type *BasePtr = ConvertType(BaseElementTy);
     622                0:             BasePtr = llvm::PointerType::getUnqual(BasePtr);
     623                 :             llvm::Value *BaseAddrPtr =
     624                0:               Builder.CreateBitCast(DeclPtr, BasePtr);
     625                0:             EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
     626                 :           }
     627                 :         } else {
     628                 :           {
     629               55:             DelayedCleanupBlock Scope(*this);
     630               55:             EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr);
     631                 : 
     632                 :             // Make sure to jump to the exit block.
     633               55:             EmitBranch(Scope.getCleanupExitBlock());
     634                 :           }
                        5: branch 0 taken
                       50: branch 1 taken
     635               55:           if (Exceptions) {
     636                5:             EHCleanupBlock Cleanup(*this);
     637                5:             EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr);
     638                 :           }
     639                 :         }
     640                 :       }
     641                 :   }
     642                 : 
     643                 :   // Handle the cleanup attribute
                        4: branch 1 taken
                     1123: branch 2 taken
     644             1127:   if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) {
     645                4:     const FunctionDecl *FD = CA->getFunctionDecl();
     646                 : 
     647                4:     llvm::Constant* F = CGM.GetAddrOfFunction(FD);
                        0: branch 0 not taken
                        4: branch 1 taken
     648                4:     assert(F && "Could not find function!");
     649                 : 
     650                4:     const CGFunctionInfo &Info = CGM.getTypes().getFunctionInfo(FD);
     651                 : 
     652                 :     // In some cases, the type of the function argument will be different from
     653                 :     // the type of the pointer. An example of this is
     654                 :     // void f(void* arg);
     655                 :     // __attribute__((cleanup(f))) void *g;
     656                 :     //
     657                 :     // To fix this we insert a bitcast here.
     658                4:     QualType ArgTy = Info.arg_begin()->type;
     659                 :     {
     660                4:       DelayedCleanupBlock scope(*this);
     661                 : 
     662                4:       CallArgList Args;
     663                 :       Args.push_back(std::make_pair(RValue::get(Builder.CreateBitCast(DeclPtr,
     664                 :                                                            ConvertType(ArgTy))),
     665                4:                                     getContext().getPointerType(D.getType())));
     666                4:       EmitCall(Info, F, ReturnValueSlot(), Args);
     667                 :     }
                        0: branch 0 not taken
                        4: branch 1 taken
     668                4:     if (Exceptions) {
     669                0:       EHCleanupBlock Cleanup(*this);
     670                 : 
     671                0:       CallArgList Args;
     672                 :       Args.push_back(std::make_pair(RValue::get(Builder.CreateBitCast(DeclPtr,
     673                 :                                                            ConvertType(ArgTy))),
     674                0:                                     getContext().getPointerType(D.getType())));
     675                0:       EmitCall(Info, F, ReturnValueSlot(), Args);
     676                 :     }
     677                 :   }
     678                 : 
                       24: branch 0 taken
                     1103: branch 1 taken
                       24: branch 4 taken
                        0: branch 5 not taken
                       24: branch 6 taken
                     1103: branch 7 taken
     679             1127:   if (needsDispose && CGM.getLangOptions().getGCMode() != LangOptions::GCOnly) {
     680                 :     {
     681               24:       DelayedCleanupBlock scope(*this);
     682               24:       llvm::Value *V = Builder.CreateStructGEP(DeclPtr, 1, "forwarding");
     683               24:       V = Builder.CreateLoad(V);
     684               24:       BuildBlockRelease(V);
     685                 :     }
     686                 :     // FIXME: Turn this on and audit the codegen
     687                 :     if (0 && Exceptions) {
     688                 :       EHCleanupBlock Cleanup(*this);
     689                 :       llvm::Value *V = Builder.CreateStructGEP(DeclPtr, 1, "forwarding");
     690                 :       V = Builder.CreateLoad(V);
     691                 :       BuildBlockRelease(V);
     692                 :     }
     693                 :   }
     694                 : }
     695                 : 
     696                 : /// Emit an alloca (or GlobalValue depending on target)
     697                 : /// for the specified parameter and set up LocalDeclMap.
     698             2994: void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
     699                 :   // FIXME: Why isn't ImplicitParamDecl a ParmVarDecl?
     700                 :   assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) &&
                     1857: branch 1 taken
                     1137: branch 2 taken
                     1857: branch 4 taken
                        0: branch 5 not taken
     701             2994:          "Invalid argument to EmitParmDecl");
     702             2994:   QualType Ty = D.getType();
     703             2994:   CanQualType CTy = getContext().getCanonicalType(Ty);
     704                 : 
     705                 :   llvm::Value *DeclPtr;
     706                 :   // If this is an aggregate or variable sized value, reuse the input pointer.
                     2994: branch 2 taken
                        0: branch 3 not taken
                      149: branch 5 taken
                     2845: branch 6 taken
                      149: branch 7 taken
                     2845: branch 8 taken
     707             5988:   if (!Ty->isConstantSizeType() ||
     708                 :       CodeGenFunction::hasAggregateLLVMType(Ty)) {
     709              149:     DeclPtr = Arg;
     710                 :   } else {
     711                 :     // Otherwise, create a temporary to hold the value.
     712             2845:     DeclPtr = CreateMemTemp(Ty, D.getName() + ".addr");
     713                 : 
     714                 :     // Store the initial value into the alloca.
     715             2845:     EmitStoreOfScalar(Arg, DeclPtr, CTy.isVolatileQualified(), Ty);
     716                 :   }
     717             2994:   Arg->setName(D.getName());
     718                 : 
     719             2994:   llvm::Value *&DMEntry = LocalDeclMap[&D];
                        0: branch 0 not taken
                     2994: branch 1 taken
     720             2994:   assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
     721             2994:   DMEntry = DeclPtr;
     722                 : 
     723                 :   // Emit debug info for param declaration.
                       71: branch 1 taken
                     2923: branch 2 taken
     724             2994:   if (CGDebugInfo *DI = getDebugInfo()) {
     725               71:     DI->setLocation(D.getLocation());
     726               71:     DI->EmitDeclareOfArgVariable(&D, DeclPtr, Builder);
     727                 :   }
     728             2994: }

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