| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1 | //===--- CGDecl.cpp - Emit LLVM Code for declarations ---------------------===// | 
 | 2 | // | 
 | 3 | //                     The LLVM Compiler Infrastructure | 
 | 4 | // | 
| Chris Lattner | 0bc735f | 2007-12-29 19:59:25 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
 | 6 | // License. See LICENSE.TXT for details. | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 7 | // | 
 | 8 | //===----------------------------------------------------------------------===// | 
 | 9 | // | 
 | 10 | // This contains code to emit Decl nodes as LLVM code. | 
 | 11 | // | 
 | 12 | //===----------------------------------------------------------------------===// | 
 | 13 |  | 
| Sanjiv Gupta | cc9b163 | 2008-05-30 10:30:31 +0000 | [diff] [blame] | 14 | #include "CGDebugInfo.h" | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 15 | #include "CodeGenFunction.h" | 
| Anders Carlsson | 1a86b33 | 2007-10-17 00:52:43 +0000 | [diff] [blame] | 16 | #include "CodeGenModule.h" | 
| Daniel Dunbar | de7fb84 | 2008-08-11 05:00:27 +0000 | [diff] [blame] | 17 | #include "clang/AST/ASTContext.h" | 
| Daniel Dunbar | c4a1dea | 2008-08-11 05:35:13 +0000 | [diff] [blame] | 18 | #include "clang/AST/Decl.h" | 
| Anders Carlsson | 19567ee | 2008-08-25 01:38:19 +0000 | [diff] [blame] | 19 | #include "clang/AST/DeclObjC.h" | 
| Nate Begeman | 8bd4afe | 2008-04-19 04:17:09 +0000 | [diff] [blame] | 20 | #include "clang/Basic/SourceManager.h" | 
| Chris Lattner | 2621fd1 | 2008-05-08 05:58:21 +0000 | [diff] [blame] | 21 | #include "clang/Basic/TargetInfo.h" | 
| Anders Carlsson | 1a86b33 | 2007-10-17 00:52:43 +0000 | [diff] [blame] | 22 | #include "llvm/GlobalVariable.h" | 
| Anders Carlsson | 5d46315 | 2008-12-12 07:38:43 +0000 | [diff] [blame] | 23 | #include "llvm/Intrinsics.h" | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 24 | #include "llvm/Target/TargetData.h" | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 25 | #include "llvm/Type.h" | 
 | 26 | using namespace clang; | 
 | 27 | using namespace CodeGen; | 
 | 28 |  | 
 | 29 |  | 
 | 30 | void CodeGenFunction::EmitDecl(const Decl &D) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 31 |   switch (D.getKind()) { | 
 | 32 |   default: assert(0 && "Unknown decl kind!"); | 
| Chris Lattner | aa9fc46 | 2007-10-08 21:37:32 +0000 | [diff] [blame] | 33 |   case Decl::ParmVar: | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 34 |     assert(0 && "Parmdecls should not be in declstmts!"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 35 |   case Decl::Function:  // void X(); | 
| Argyrios Kyrtzidis | 35bc082 | 2008-10-15 00:42:39 +0000 | [diff] [blame] | 36 |   case Decl::Record:    // struct/union/class X; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 37 |   case Decl::Enum:      // enum X; | 
| Daniel Dunbar | 662174c8 | 2008-08-29 17:28:43 +0000 | [diff] [blame] | 38 |   case Decl::EnumConstant: // enum ? { X = ? }  | 
| Argyrios Kyrtzidis | 35bc082 | 2008-10-15 00:42:39 +0000 | [diff] [blame] | 39 |   case Decl::CXXRecord: // struct/union/class X; [C++] | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 40 |     // None of these decls require codegen support. | 
 | 41 |     return; | 
 | 42 |      | 
| Daniel Dunbar | 662174c8 | 2008-08-29 17:28:43 +0000 | [diff] [blame] | 43 |   case Decl::Var: { | 
 | 44 |     const VarDecl &VD = cast<VarDecl>(D); | 
 | 45 |     assert(VD.isBlockVarDecl() &&  | 
 | 46 |            "Should not see file-scope variables inside a function!"); | 
 | 47 |     return EmitBlockVarDecl(VD); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 48 |   } | 
| Anders Carlsson | fcdbb93 | 2008-12-20 21:51:53 +0000 | [diff] [blame] | 49 |          | 
 | 50 |   case Decl::Typedef: {   // typedef int X; | 
 | 51 |     const TypedefDecl &TD = cast<TypedefDecl>(D); | 
 | 52 |     QualType Ty = TD.getUnderlyingType(); | 
 | 53 |      | 
 | 54 |     if (Ty->isVariablyModifiedType()) | 
 | 55 |       EmitVLASize(Ty); | 
 | 56 |   } | 
| Daniel Dunbar | 662174c8 | 2008-08-29 17:28:43 +0000 | [diff] [blame] | 57 |   } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 58 | } | 
 | 59 |  | 
 | 60 | /// EmitBlockVarDecl - This method handles emission of any variable declaration | 
 | 61 | /// inside a function, including static vars etc. | 
| Steve Naroff | 248a753 | 2008-04-15 22:42:06 +0000 | [diff] [blame] | 62 | void CodeGenFunction::EmitBlockVarDecl(const VarDecl &D) { | 
| Argyrios Kyrtzidis | 40b598e | 2009-06-30 02:34:44 +0000 | [diff] [blame] | 63 |   if (D.hasAttr<AsmLabelAttr>()) | 
| Fariborz Jahanian | ba8639d | 2009-03-30 20:32:06 +0000 | [diff] [blame] | 64 |     CGM.ErrorUnsupported(&D, "__asm__"); | 
 | 65 |    | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 66 |   switch (D.getStorageClass()) { | 
| Daniel Dunbar | 5466c7b | 2009-04-14 02:25:56 +0000 | [diff] [blame] | 67 |   case VarDecl::None: | 
 | 68 |   case VarDecl::Auto: | 
 | 69 |   case VarDecl::Register: | 
 | 70 |     return EmitLocalBlockVarDecl(D); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 71 |   case VarDecl::Static: | 
| Anders Carlsson | 1a86b33 | 2007-10-17 00:52:43 +0000 | [diff] [blame] | 72 |     return EmitStaticBlockVarDecl(D); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 73 |   case VarDecl::Extern: | 
| Daniel Dunbar | 5466c7b | 2009-04-14 02:25:56 +0000 | [diff] [blame] | 74 |   case VarDecl::PrivateExtern: | 
| Lauro Ramos Venancio | fea90b8 | 2008-02-16 22:30:38 +0000 | [diff] [blame] | 75 |     // Don't emit it now, allow it to be emitted lazily on its first use. | 
 | 76 |     return; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 77 |   } | 
| Daniel Dunbar | 5466c7b | 2009-04-14 02:25:56 +0000 | [diff] [blame] | 78 |  | 
 | 79 |   assert(0 && "Unknown storage class"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 80 | } | 
 | 81 |  | 
| Daniel Dunbar | 0096acf | 2009-02-25 19:24:29 +0000 | [diff] [blame] | 82 | llvm::GlobalVariable * | 
 | 83 | CodeGenFunction::CreateStaticBlockVarDecl(const VarDecl &D, | 
 | 84 |                                           const char *Separator, | 
 | 85 |                                           llvm::GlobalValue::LinkageTypes | 
 | 86 |                                           Linkage) { | 
| Chris Lattner | 8bcfc5b | 2008-04-06 23:10:54 +0000 | [diff] [blame] | 87 |   QualType Ty = D.getType(); | 
| Eli Friedman | 3c2b317 | 2008-02-15 12:20:59 +0000 | [diff] [blame] | 88 |   assert(Ty->isConstantSizeType() && "VLAs can't be static"); | 
| Nate Begeman | 8bd4afe | 2008-04-19 04:17:09 +0000 | [diff] [blame] | 89 |  | 
| Anders Carlsson | 17c35ac | 2009-04-02 03:29:47 +0000 | [diff] [blame] | 90 |   std::string Name; | 
 | 91 |   if (getContext().getLangOptions().CPlusPlus) { | 
 | 92 |     Name = CGM.getMangledName(&D); | 
 | 93 |   } else { | 
 | 94 |     std::string ContextName; | 
 | 95 |     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurFuncDecl)) | 
 | 96 |       ContextName = CGM.getMangledName(FD); | 
 | 97 |     else if (isa<ObjCMethodDecl>(CurFuncDecl)) | 
 | 98 |       ContextName = std::string(CurFn->getNameStart(),  | 
 | 99 |                                 CurFn->getNameStart() + CurFn->getNameLen()); | 
 | 100 |     else | 
 | 101 |       assert(0 && "Unknown context for block var decl"); | 
 | 102 |      | 
 | 103 |     Name = ContextName + Separator + D.getNameAsString(); | 
 | 104 |   } | 
| Nate Begeman | 8bd4afe | 2008-04-19 04:17:09 +0000 | [diff] [blame] | 105 |  | 
| Daniel Dunbar | 0096acf | 2009-02-25 19:24:29 +0000 | [diff] [blame] | 106 |   const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(Ty); | 
| Owen Anderson | 1c431b3 | 2009-07-08 19:05:04 +0000 | [diff] [blame] | 107 |   return new llvm::GlobalVariable(CGM.getModule(), LTy, | 
 | 108 |                                   Ty.isConstant(getContext()), Linkage, | 
| Owen Anderson | a1cf15f | 2009-07-14 23:10:40 +0000 | [diff] [blame^] | 109 |                                   VMContext.getNullValue(LTy), Name, | 
| Owen Anderson | 1c431b3 | 2009-07-08 19:05:04 +0000 | [diff] [blame] | 110 |                                   0, D.isThreadSpecified(), | 
| Eli Friedman | 56ebe50 | 2009-04-19 21:05:03 +0000 | [diff] [blame] | 111 |                                   Ty.getAddressSpace()); | 
| Daniel Dunbar | 0096acf | 2009-02-25 19:24:29 +0000 | [diff] [blame] | 112 | } | 
 | 113 |  | 
| Daniel Dunbar | a985b31 | 2009-02-25 19:45:19 +0000 | [diff] [blame] | 114 | void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) {  | 
| Daniel Dunbar | 0096acf | 2009-02-25 19:24:29 +0000 | [diff] [blame] | 115 |  | 
| Daniel Dunbar | a985b31 | 2009-02-25 19:45:19 +0000 | [diff] [blame] | 116 |   llvm::Value *&DMEntry = LocalDeclMap[&D]; | 
 | 117 |   assert(DMEntry == 0 && "Decl already exists in localdeclmap!"); | 
 | 118 |    | 
 | 119 |   llvm::GlobalVariable *GV =  | 
 | 120 |     CreateStaticBlockVarDecl(D, ".", llvm::GlobalValue::InternalLinkage); | 
 | 121 |  | 
| Daniel Dunbar | e5731f8 | 2009-02-25 20:08:33 +0000 | [diff] [blame] | 122 |   // Store into LocalDeclMap before generating initializer to handle | 
 | 123 |   // circular references. | 
 | 124 |   DMEntry = GV; | 
 | 125 |  | 
| Eli Friedman | c62aad8 | 2009-04-20 03:54:15 +0000 | [diff] [blame] | 126 |   // Make sure to evaluate VLA bounds now so that we have them for later. | 
 | 127 |   if (D.getType()->isVariablyModifiedType()) | 
 | 128 |     EmitVLASize(D.getType()); | 
 | 129 |  | 
| Anders Carlsson | cc0e354 | 2009-05-18 19:55:29 +0000 | [diff] [blame] | 130 |   if (D.getType()->isReferenceType()) { | 
 | 131 |     CGM.ErrorUnsupported(&D, "static declaration with reference type"); | 
 | 132 |     return; | 
 | 133 |   } | 
 | 134 |  | 
| Daniel Dunbar | a985b31 | 2009-02-25 19:45:19 +0000 | [diff] [blame] | 135 |   if (D.getInit()) { | 
| Anders Carlsson | e9352cc | 2009-04-08 04:48:15 +0000 | [diff] [blame] | 136 |     llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), D.getType(), this); | 
| Daniel Dunbar | 0096acf | 2009-02-25 19:24:29 +0000 | [diff] [blame] | 137 |  | 
 | 138 |     // If constant emission failed, then this should be a C++ static | 
 | 139 |     // initializer. | 
 | 140 |     if (!Init) { | 
 | 141 |       if (!getContext().getLangOptions().CPlusPlus) | 
 | 142 |         CGM.ErrorUnsupported(D.getInit(), "constant l-value expression"); | 
 | 143 |       else | 
 | 144 |         GenerateStaticCXXBlockVarDeclInit(D, GV); | 
 | 145 |     } else { | 
 | 146 |       // The initializer may differ in type from the global. Rewrite | 
| Eli Friedman | 074dda6 | 2009-03-04 04:22:58 +0000 | [diff] [blame] | 147 |       // the global to match the initializer.  (We have to do this | 
 | 148 |       // because some types, like unions, can't be completely represented | 
 | 149 |       // in the LLVM type system.) | 
| Daniel Dunbar | 0096acf | 2009-02-25 19:24:29 +0000 | [diff] [blame] | 150 |       if (GV->getType() != Init->getType()) { | 
 | 151 |         llvm::GlobalVariable *OldGV = GV; | 
 | 152 |          | 
| Owen Anderson | 1c431b3 | 2009-07-08 19:05:04 +0000 | [diff] [blame] | 153 |         GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), | 
 | 154 |                                       OldGV->isConstant(), | 
| Daniel Dunbar | 0096acf | 2009-02-25 19:24:29 +0000 | [diff] [blame] | 155 |                                       OldGV->getLinkage(), Init, "", | 
| Owen Anderson | 1c431b3 | 2009-07-08 19:05:04 +0000 | [diff] [blame] | 156 |                                       0, D.isThreadSpecified(), | 
| Daniel Dunbar | 0096acf | 2009-02-25 19:24:29 +0000 | [diff] [blame] | 157 |                                       D.getType().getAddressSpace()); | 
 | 158 |  | 
 | 159 |         // Steal the name of the old global | 
 | 160 |         GV->takeName(OldGV); | 
 | 161 |  | 
 | 162 |         // Replace all uses of the old global with the new global | 
 | 163 |         llvm::Constant *NewPtrForOldDecl =  | 
| Owen Anderson | a1cf15f | 2009-07-14 23:10:40 +0000 | [diff] [blame^] | 164 |           VMContext.getConstantExprBitCast(GV, OldGV->getType()); | 
| Daniel Dunbar | 0096acf | 2009-02-25 19:24:29 +0000 | [diff] [blame] | 165 |         OldGV->replaceAllUsesWith(NewPtrForOldDecl); | 
 | 166 |  | 
 | 167 |         // Erase the old global, since it is no longer used. | 
 | 168 |         OldGV->eraseFromParent(); | 
 | 169 |       }  | 
 | 170 |  | 
 | 171 |       GV->setInitializer(Init); | 
 | 172 |     } | 
 | 173 |   } | 
| Nate Begeman | 8bd4afe | 2008-04-19 04:17:09 +0000 | [diff] [blame] | 174 |  | 
| Daniel Dunbar | 30510ab | 2009-02-12 23:32:54 +0000 | [diff] [blame] | 175 |   // FIXME: Merge attribute handling. | 
| Argyrios Kyrtzidis | 40b598e | 2009-06-30 02:34:44 +0000 | [diff] [blame] | 176 |   if (const AnnotateAttr *AA = D.getAttr<AnnotateAttr>()) { | 
| Nate Begeman | 8bd4afe | 2008-04-19 04:17:09 +0000 | [diff] [blame] | 177 |     SourceManager &SM = CGM.getContext().getSourceManager(); | 
 | 178 |     llvm::Constant *Ann = | 
| Chris Lattner | f7cf85b | 2009-01-16 07:36:28 +0000 | [diff] [blame] | 179 |       CGM.EmitAnnotateAttr(GV, AA,  | 
 | 180 |                            SM.getInstantiationLineNumber(D.getLocation())); | 
| Nate Begeman | 8bd4afe | 2008-04-19 04:17:09 +0000 | [diff] [blame] | 181 |     CGM.AddAnnotation(Ann); | 
 | 182 |   } | 
 | 183 |  | 
| Argyrios Kyrtzidis | 40b598e | 2009-06-30 02:34:44 +0000 | [diff] [blame] | 184 |   if (const SectionAttr *SA = D.getAttr<SectionAttr>()) | 
| Daniel Dunbar | 30510ab | 2009-02-12 23:32:54 +0000 | [diff] [blame] | 185 |     GV->setSection(SA->getName()); | 
 | 186 |    | 
| Argyrios Kyrtzidis | 40b598e | 2009-06-30 02:34:44 +0000 | [diff] [blame] | 187 |   if (D.hasAttr<UsedAttr>()) | 
| Daniel Dunbar | 5c61d97 | 2009-02-13 22:08:43 +0000 | [diff] [blame] | 188 |     CGM.AddUsedGlobal(GV); | 
 | 189 |  | 
| Daniel Dunbar | e5731f8 | 2009-02-25 20:08:33 +0000 | [diff] [blame] | 190 |   // We may have to cast the constant because of the initializer | 
 | 191 |   // mismatch above. | 
 | 192 |   // | 
 | 193 |   // FIXME: It is really dangerous to store this in the map; if anyone | 
 | 194 |   // RAUW's the GV uses of this constant will be invalid. | 
| Eli Friedman | 2659052 | 2008-06-08 01:23:18 +0000 | [diff] [blame] | 195 |   const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(D.getType()); | 
 | 196 |   const llvm::Type *LPtrTy = | 
| Owen Anderson | a1cf15f | 2009-07-14 23:10:40 +0000 | [diff] [blame^] | 197 |     VMContext.getPointerType(LTy, D.getType().getAddressSpace()); | 
 | 198 |   DMEntry = VMContext.getConstantExprBitCast(GV, LPtrTy); | 
| Sanjiv Gupta | 686226b | 2008-06-05 08:59:10 +0000 | [diff] [blame] | 199 |  | 
 | 200 |   // Emit global variable debug descriptor for static vars. | 
| Anders Carlsson | e896d98 | 2009-02-13 08:11:52 +0000 | [diff] [blame] | 201 |   CGDebugInfo *DI = getDebugInfo(); | 
| Mike Stump | 4451bd9 | 2009-02-20 00:19:45 +0000 | [diff] [blame] | 202 |   if (DI) { | 
| Daniel Dunbar | 66031a5 | 2008-10-17 16:15:48 +0000 | [diff] [blame] | 203 |     DI->setLocation(D.getLocation()); | 
| Sanjiv Gupta | 686226b | 2008-06-05 08:59:10 +0000 | [diff] [blame] | 204 |     DI->EmitGlobalVariable(static_cast<llvm::GlobalVariable *>(GV), &D); | 
 | 205 |   } | 
| Anders Carlsson | 1a86b33 | 2007-10-17 00:52:43 +0000 | [diff] [blame] | 206 | } | 
 | 207 |    | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 208 | /// BuildByRefType - This routine changes a __block variable declared as T x | 
 | 209 | ///   into: | 
 | 210 | /// | 
 | 211 | ///      struct { | 
 | 212 | ///        void *__isa; | 
 | 213 | ///        void *__forwarding; | 
 | 214 | ///        int32_t __flags; | 
 | 215 | ///        int32_t __size; | 
 | 216 | ///        void *__copy_helper; | 
 | 217 | ///        void *__destroy_helper; | 
 | 218 | ///        T x; | 
 | 219 | ///      } x | 
 | 220 | /// | 
 | 221 | /// Align is the alignment needed in bytes for x. | 
 | 222 | const llvm::Type *CodeGenFunction::BuildByRefType(QualType Ty, | 
 | 223 |                                                   uint64_t Align) { | 
 | 224 |   const llvm::Type *LTy = ConvertType(Ty); | 
 | 225 |   bool needsCopyDispose = BlockRequiresCopying(Ty); | 
 | 226 |   std::vector<const llvm::Type *> Types(needsCopyDispose*2+5); | 
 | 227 |   const llvm::PointerType *PtrToInt8Ty | 
| Owen Anderson | a1cf15f | 2009-07-14 23:10:40 +0000 | [diff] [blame^] | 228 |     = VMContext.getPointerTypeUnqual(llvm::Type::Int8Ty); | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 229 |   Types[0] = PtrToInt8Ty; | 
 | 230 |   Types[1] = PtrToInt8Ty; | 
 | 231 |   Types[2] = llvm::Type::Int32Ty; | 
 | 232 |   Types[3] = llvm::Type::Int32Ty; | 
 | 233 |   if (needsCopyDispose) { | 
 | 234 |     Types[4] = PtrToInt8Ty; | 
 | 235 |     Types[5] = PtrToInt8Ty; | 
 | 236 |   } | 
| Mike Stump | 3899a7f | 2009-06-05 23:26:36 +0000 | [diff] [blame] | 237 |   // FIXME: Align this on at least an Align boundary, assert if we can't. | 
 | 238 |   assert((Align <= unsigned(Target.getPointerAlign(0))/8) | 
| Devang Patel | bd0fec9 | 2009-06-26 18:33:42 +0000 | [diff] [blame] | 239 |          && "Can't align more than pointer yet"); | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 240 |   Types[needsCopyDispose*2 + 4] = LTy; | 
| Owen Anderson | a1cf15f | 2009-07-14 23:10:40 +0000 | [diff] [blame^] | 241 |   return VMContext.getStructType(Types, false); | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 242 | } | 
 | 243 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 244 | /// EmitLocalBlockVarDecl - Emit code and set up an entry in LocalDeclMap for a | 
 | 245 | /// variable declaration with auto, register, or no storage class specifier. | 
| Chris Lattner | 2621fd1 | 2008-05-08 05:58:21 +0000 | [diff] [blame] | 246 | /// These turn into simple stack objects, or GlobalValues depending on target. | 
| Steve Naroff | 248a753 | 2008-04-15 22:42:06 +0000 | [diff] [blame] | 247 | void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { | 
| Chris Lattner | 8bcfc5b | 2008-04-06 23:10:54 +0000 | [diff] [blame] | 248 |   QualType Ty = D.getType(); | 
| Argyrios Kyrtzidis | 40b598e | 2009-06-30 02:34:44 +0000 | [diff] [blame] | 249 |   bool isByRef = D.hasAttr<BlocksAttr>(); | 
| Mike Stump | 797b632 | 2009-03-05 01:23:13 +0000 | [diff] [blame] | 250 |   bool needsDispose = false; | 
| Mike Stump | 3899a7f | 2009-06-05 23:26:36 +0000 | [diff] [blame] | 251 |   unsigned Align = 0; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 252 |  | 
 | 253 |   llvm::Value *DeclPtr; | 
| Eli Friedman | 3c2b317 | 2008-02-15 12:20:59 +0000 | [diff] [blame] | 254 |   if (Ty->isConstantSizeType()) { | 
| Chris Lattner | 2621fd1 | 2008-05-08 05:58:21 +0000 | [diff] [blame] | 255 |     if (!Target.useGlobalsForAutomaticVariables()) { | 
 | 256 |       // A normal fixed sized variable becomes an alloca in the entry block. | 
| Eli Friedman | a3460ac | 2009-03-04 04:25:14 +0000 | [diff] [blame] | 257 |       const llvm::Type *LTy = ConvertTypeForMem(Ty); | 
| Mike Stump | 3899a7f | 2009-06-05 23:26:36 +0000 | [diff] [blame] | 258 |       Align = getContext().getDeclAlignInBytes(&D); | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 259 |       if (isByRef) | 
| Mike Stump | 3899a7f | 2009-06-05 23:26:36 +0000 | [diff] [blame] | 260 |         LTy = BuildByRefType(Ty, Align); | 
| Chris Lattner | f146684 | 2009-03-22 00:24:14 +0000 | [diff] [blame] | 261 |       llvm::AllocaInst *Alloc = CreateTempAlloca(LTy); | 
 | 262 |       Alloc->setName(D.getNameAsString().c_str()); | 
 | 263 |        | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 264 |       if (isByRef) | 
| Mike Stump | 3899a7f | 2009-06-05 23:26:36 +0000 | [diff] [blame] | 265 |         Align = std::max(Align, unsigned(Target.getPointerAlign(0) / 8)); | 
 | 266 |       Alloc->setAlignment(Align); | 
| Eli Friedman | 77eedd6 | 2008-05-31 21:20:41 +0000 | [diff] [blame] | 267 |       DeclPtr = Alloc; | 
| Chris Lattner | 2621fd1 | 2008-05-08 05:58:21 +0000 | [diff] [blame] | 268 |     } else { | 
 | 269 |       // Targets that don't support recursion emit locals as globals. | 
 | 270 |       const char *Class = | 
 | 271 |         D.getStorageClass() == VarDecl::Register ? ".reg." : ".auto."; | 
| Daniel Dunbar | a985b31 | 2009-02-25 19:45:19 +0000 | [diff] [blame] | 272 |       DeclPtr = CreateStaticBlockVarDecl(D, Class,  | 
 | 273 |                                          llvm::GlobalValue | 
 | 274 |                                          ::InternalLinkage); | 
| Chris Lattner | 2621fd1 | 2008-05-08 05:58:21 +0000 | [diff] [blame] | 275 |     } | 
| Anders Carlsson | 60d3541 | 2008-12-20 20:46:34 +0000 | [diff] [blame] | 276 |      | 
 | 277 |     if (Ty->isVariablyModifiedType()) | 
 | 278 |       EmitVLASize(Ty); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 279 |   } else { | 
| Anders Carlsson | 5ecb1b9 | 2009-02-09 20:41:50 +0000 | [diff] [blame] | 280 |     if (!DidCallStackSave) { | 
| Anders Carlsson | 5d46315 | 2008-12-12 07:38:43 +0000 | [diff] [blame] | 281 |       // Save the stack. | 
| Owen Anderson | a1cf15f | 2009-07-14 23:10:40 +0000 | [diff] [blame^] | 282 |       const llvm::Type *LTy = | 
 | 283 |         VMContext.getPointerTypeUnqual(llvm::Type::Int8Ty); | 
| Anders Carlsson | 5d46315 | 2008-12-12 07:38:43 +0000 | [diff] [blame] | 284 |       llvm::Value *Stack = CreateTempAlloca(LTy, "saved_stack"); | 
 | 285 |        | 
 | 286 |       llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stacksave); | 
 | 287 |       llvm::Value *V = Builder.CreateCall(F); | 
 | 288 |        | 
 | 289 |       Builder.CreateStore(V, Stack); | 
| Anders Carlsson | 5ecb1b9 | 2009-02-09 20:41:50 +0000 | [diff] [blame] | 290 |  | 
 | 291 |       DidCallStackSave = true; | 
| Anders Carlsson | 5d46315 | 2008-12-12 07:38:43 +0000 | [diff] [blame] | 292 |        | 
| Anders Carlsson | 5ecb1b9 | 2009-02-09 20:41:50 +0000 | [diff] [blame] | 293 |       { | 
 | 294 |         // Push a cleanup block and restore the stack there. | 
 | 295 |         CleanupScope scope(*this); | 
 | 296 |        | 
 | 297 |         V = Builder.CreateLoad(Stack, "tmp"); | 
 | 298 |         llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stackrestore); | 
 | 299 |         Builder.CreateCall(F, V); | 
 | 300 |       } | 
| Anders Carlsson | 5d46315 | 2008-12-12 07:38:43 +0000 | [diff] [blame] | 301 |     } | 
| Anders Carlsson | 5ecb1b9 | 2009-02-09 20:41:50 +0000 | [diff] [blame] | 302 |      | 
| Anders Carlsson | 5d46315 | 2008-12-12 07:38:43 +0000 | [diff] [blame] | 303 |     // Get the element type. | 
| Eli Friedman | a3460ac | 2009-03-04 04:25:14 +0000 | [diff] [blame] | 304 |     const llvm::Type *LElemTy = ConvertTypeForMem(Ty);     | 
| Anders Carlsson | 5d46315 | 2008-12-12 07:38:43 +0000 | [diff] [blame] | 305 |     const llvm::Type *LElemPtrTy = | 
| Owen Anderson | a1cf15f | 2009-07-14 23:10:40 +0000 | [diff] [blame^] | 306 |       VMContext.getPointerType(LElemTy, D.getType().getAddressSpace()); | 
| Anders Carlsson | 5d46315 | 2008-12-12 07:38:43 +0000 | [diff] [blame] | 307 |  | 
| Anders Carlsson | 60d3541 | 2008-12-20 20:46:34 +0000 | [diff] [blame] | 308 |     llvm::Value *VLASize = EmitVLASize(Ty); | 
| Anders Carlsson | 5d46315 | 2008-12-12 07:38:43 +0000 | [diff] [blame] | 309 |  | 
| Anders Carlsson | 96f2147 | 2009-02-05 19:43:10 +0000 | [diff] [blame] | 310 |     // Downcast the VLA size expression | 
 | 311 |     VLASize = Builder.CreateIntCast(VLASize, llvm::Type::Int32Ty, false, "tmp"); | 
 | 312 |      | 
| Anders Carlsson | 5d46315 | 2008-12-12 07:38:43 +0000 | [diff] [blame] | 313 |     // Allocate memory for the array. | 
 | 314 |     llvm::Value *VLA = Builder.CreateAlloca(llvm::Type::Int8Ty, VLASize, "vla"); | 
| Eli Friedman | 8f39f5e | 2008-12-20 23:11:59 +0000 | [diff] [blame] | 315 |     DeclPtr = Builder.CreateBitCast(VLA, LElemPtrTy, "tmp"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 316 |   } | 
| Eli Friedman | 8f39f5e | 2008-12-20 23:11:59 +0000 | [diff] [blame] | 317 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 318 |   llvm::Value *&DMEntry = LocalDeclMap[&D]; | 
 | 319 |   assert(DMEntry == 0 && "Decl already exists in localdeclmap!"); | 
 | 320 |   DMEntry = DeclPtr; | 
| Sanjiv Gupta | cc9b163 | 2008-05-30 10:30:31 +0000 | [diff] [blame] | 321 |  | 
 | 322 |   // Emit debug info for local var declaration. | 
| Anders Carlsson | e896d98 | 2009-02-13 08:11:52 +0000 | [diff] [blame] | 323 |   if (CGDebugInfo *DI = getDebugInfo()) { | 
| Daniel Dunbar | 66031a5 | 2008-10-17 16:15:48 +0000 | [diff] [blame] | 324 |     DI->setLocation(D.getLocation()); | 
| Sanjiv Gupta | 4381d4b | 2009-05-22 13:54:25 +0000 | [diff] [blame] | 325 |     if (Target.useGlobalsForAutomaticVariables()) { | 
 | 326 |       DI->EmitGlobalVariable(static_cast<llvm::GlobalVariable *>(DeclPtr), &D); | 
 | 327 |     } | 
 | 328 |     else if (isByRef) { | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 329 |       llvm::Value *Loc; | 
 | 330 |       bool needsCopyDispose = BlockRequiresCopying(Ty); | 
| Mike Stump | fd0e628 | 2009-05-15 00:29:54 +0000 | [diff] [blame] | 331 |       Loc = Builder.CreateStructGEP(DeclPtr, 1, "forwarding"); | 
 | 332 |       Loc = Builder.CreateLoad(Loc, false); | 
 | 333 |       Loc = Builder.CreateBitCast(Loc, DeclPtr->getType()); | 
 | 334 |       Loc = Builder.CreateStructGEP(Loc, needsCopyDispose*2+4, "x"); | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 335 |       DI->EmitDeclareOfAutoVariable(&D, Loc, Builder); | 
 | 336 |     } else | 
 | 337 |       DI->EmitDeclareOfAutoVariable(&D, DeclPtr, Builder); | 
| Sanjiv Gupta | cc9b163 | 2008-05-30 10:30:31 +0000 | [diff] [blame] | 338 |   } | 
 | 339 |  | 
| Chris Lattner | 1978596 | 2007-07-12 00:39:48 +0000 | [diff] [blame] | 340 |   // If this local has an initializer, emit it now. | 
| Chris Lattner | 7f02f72 | 2007-08-24 05:35:26 +0000 | [diff] [blame] | 341 |   if (const Expr *Init = D.getInit()) { | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 342 |     llvm::Value *Loc = DeclPtr; | 
 | 343 |     if (isByRef) { | 
 | 344 |       bool needsCopyDispose = BlockRequiresCopying(Ty); | 
 | 345 |       Loc = Builder.CreateStructGEP(DeclPtr, needsCopyDispose*2+4, "x"); | 
 | 346 |     } | 
| Eli Friedman | 4a18784 | 2009-05-27 05:39:06 +0000 | [diff] [blame] | 347 |     if (Ty->isReferenceType()) { | 
 | 348 |       llvm::Value *V = EmitReferenceBindingToExpr(Init, Ty).getScalarVal(); | 
 | 349 |       EmitStoreOfScalar(V, Loc, false, Ty); | 
 | 350 |     } else if (!hasAggregateLLVMType(Init->getType())) { | 
| Chris Lattner | d31beb1 | 2007-08-26 07:29:23 +0000 | [diff] [blame] | 351 |       llvm::Value *V = EmitScalarExpr(Init); | 
| Anders Carlsson | b4aa466 | 2009-05-19 18:50:41 +0000 | [diff] [blame] | 352 |       EmitStoreOfScalar(V, Loc, D.getType().isVolatileQualified(),  | 
 | 353 |                         D.getType()); | 
| Chris Lattner | 9b2dc28 | 2008-04-04 16:54:41 +0000 | [diff] [blame] | 354 |     } else if (Init->getType()->isAnyComplexType()) { | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 355 |       EmitComplexExprIntoAddr(Init, Loc, D.getType().isVolatileQualified()); | 
| Chris Lattner | 9a19edf | 2007-08-26 05:13:54 +0000 | [diff] [blame] | 356 |     } else { | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 357 |       EmitAggExpr(Init, Loc, D.getType().isVolatileQualified()); | 
 | 358 |     } | 
 | 359 |   } | 
 | 360 |   if (isByRef) { | 
 | 361 |     const llvm::PointerType *PtrToInt8Ty | 
| Owen Anderson | a1cf15f | 2009-07-14 23:10:40 +0000 | [diff] [blame^] | 362 |       = VMContext.getPointerTypeUnqual(llvm::Type::Int8Ty); | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 363 |  | 
 | 364 |     llvm::Value *isa_field = Builder.CreateStructGEP(DeclPtr, 0); | 
 | 365 |     llvm::Value *forwarding_field = Builder.CreateStructGEP(DeclPtr, 1); | 
 | 366 |     llvm::Value *flags_field = Builder.CreateStructGEP(DeclPtr, 2); | 
 | 367 |     llvm::Value *size_field = Builder.CreateStructGEP(DeclPtr, 3); | 
 | 368 |     llvm::Value *V; | 
 | 369 |     int flag = 0; | 
 | 370 |     int flags = 0; | 
 | 371 |  | 
| Mike Stump | f4bc312 | 2009-03-07 06:04:31 +0000 | [diff] [blame] | 372 |     needsDispose = true; | 
| Mike Stump | 00470a1 | 2009-03-05 08:32:30 +0000 | [diff] [blame] | 373 |  | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 374 |     if (Ty->isBlockPointerType()) { | 
 | 375 |       flag |= BLOCK_FIELD_IS_BLOCK; | 
 | 376 |       flags |= BLOCK_HAS_COPY_DISPOSE; | 
 | 377 |     } else if (BlockRequiresCopying(Ty)) { | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 378 |       flag |= BLOCK_FIELD_IS_OBJECT; | 
| Mike Stump | 1851b68 | 2009-03-06 04:53:30 +0000 | [diff] [blame] | 379 |       flags |= BLOCK_HAS_COPY_DISPOSE; | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 380 |     } | 
| Mike Stump | f4bc312 | 2009-03-07 06:04:31 +0000 | [diff] [blame] | 381 |  | 
 | 382 |     // FIXME: Someone double check this. | 
 | 383 |     if (Ty.isObjCGCWeak()) | 
 | 384 |       flag |= BLOCK_FIELD_IS_WEAK; | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 385 |  | 
 | 386 |     int isa = 0; | 
 | 387 |     if (flag&BLOCK_FIELD_IS_WEAK) | 
 | 388 |       isa = 1; | 
| Owen Anderson | a1cf15f | 2009-07-14 23:10:40 +0000 | [diff] [blame^] | 389 |     V = VMContext.getConstantInt(llvm::Type::Int32Ty, isa); | 
| Mike Stump | a4f668f | 2009-03-06 01:33:24 +0000 | [diff] [blame] | 390 |     V = Builder.CreateIntToPtr(V, PtrToInt8Ty, "isa"); | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 391 |     Builder.CreateStore(V, isa_field); | 
 | 392 |  | 
| Mike Stump | a4f668f | 2009-03-06 01:33:24 +0000 | [diff] [blame] | 393 |     V = Builder.CreateBitCast(DeclPtr, PtrToInt8Ty, "forwarding"); | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 394 |     Builder.CreateStore(V, forwarding_field); | 
 | 395 |  | 
| Owen Anderson | a1cf15f | 2009-07-14 23:10:40 +0000 | [diff] [blame^] | 396 |     V = VMContext.getConstantInt(llvm::Type::Int32Ty, flags); | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 397 |     Builder.CreateStore(V, flags_field); | 
 | 398 |  | 
| Mike Stump | 00470a1 | 2009-03-05 08:32:30 +0000 | [diff] [blame] | 399 |     const llvm::Type *V1; | 
 | 400 |     V1 = cast<llvm::PointerType>(DeclPtr->getType())->getElementType(); | 
| Owen Anderson | a1cf15f | 2009-07-14 23:10:40 +0000 | [diff] [blame^] | 401 |     V = VMContext.getConstantInt(llvm::Type::Int32Ty, | 
| Mike Stump | 00470a1 | 2009-03-05 08:32:30 +0000 | [diff] [blame] | 402 |                                (CGM.getTargetData().getTypeStoreSizeInBits(V1) | 
 | 403 |                                 / 8)); | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 404 |     Builder.CreateStore(V, size_field); | 
 | 405 |  | 
 | 406 |     if (flags & BLOCK_HAS_COPY_DISPOSE) { | 
| Mike Stump | 00470a1 | 2009-03-05 08:32:30 +0000 | [diff] [blame] | 407 |       BlockHasCopyDispose = true; | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 408 |       llvm::Value *copy_helper = Builder.CreateStructGEP(DeclPtr, 4); | 
| Mike Stump | 3899a7f | 2009-06-05 23:26:36 +0000 | [diff] [blame] | 409 |       Builder.CreateStore(BuildbyrefCopyHelper(DeclPtr->getType(), flag, Align), | 
| Mike Stump | ee09422 | 2009-03-06 06:12:24 +0000 | [diff] [blame] | 410 |                           copy_helper); | 
| Mike Stump | dab514f | 2009-03-04 03:23:46 +0000 | [diff] [blame] | 411 |  | 
| Mike Stump | 1851b68 | 2009-03-06 04:53:30 +0000 | [diff] [blame] | 412 |       llvm::Value *destroy_helper = Builder.CreateStructGEP(DeclPtr, 5); | 
| Mike Stump | 3899a7f | 2009-06-05 23:26:36 +0000 | [diff] [blame] | 413 |       Builder.CreateStore(BuildbyrefDestroyHelper(DeclPtr->getType(), flag, | 
 | 414 |                                                   Align), | 
| Mike Stump | 1851b68 | 2009-03-06 04:53:30 +0000 | [diff] [blame] | 415 |                           destroy_helper); | 
| Chris Lattner | 9a19edf | 2007-08-26 05:13:54 +0000 | [diff] [blame] | 416 |     } | 
| Chris Lattner | 7f02f72 | 2007-08-24 05:35:26 +0000 | [diff] [blame] | 417 |   } | 
| Anders Carlsson | 69c68b7 | 2009-02-07 23:51:38 +0000 | [diff] [blame] | 418 |  | 
 | 419 |   // Handle the cleanup attribute | 
| Argyrios Kyrtzidis | 40b598e | 2009-06-30 02:34:44 +0000 | [diff] [blame] | 420 |   if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) { | 
| Anders Carlsson | 69c68b7 | 2009-02-07 23:51:38 +0000 | [diff] [blame] | 421 |     const FunctionDecl *FD = CA->getFunctionDecl(); | 
 | 422 |      | 
| Chris Lattner | b4880ba | 2009-05-12 21:21:08 +0000 | [diff] [blame] | 423 |     llvm::Constant* F = CGM.GetAddrOfFunction(GlobalDecl(FD)); | 
| Anders Carlsson | 69c68b7 | 2009-02-07 23:51:38 +0000 | [diff] [blame] | 424 |     assert(F && "Could not find function!"); | 
 | 425 |    | 
 | 426 |     CleanupScope scope(*this); | 
 | 427 |  | 
| Anders Carlsson | cabec03 | 2009-04-26 00:34:20 +0000 | [diff] [blame] | 428 |     const CGFunctionInfo &Info = CGM.getTypes().getFunctionInfo(FD); | 
 | 429 |  | 
 | 430 |     // In some cases, the type of the function argument will be different from | 
 | 431 |     // the type of the pointer. An example of this is | 
 | 432 |     // void f(void* arg); | 
 | 433 |     // __attribute__((cleanup(f))) void *g; | 
 | 434 |     //  | 
 | 435 |     // To fix this we insert a bitcast here. | 
 | 436 |     QualType ArgTy = Info.arg_begin()->type; | 
 | 437 |     DeclPtr = Builder.CreateBitCast(DeclPtr, ConvertType(ArgTy)); | 
 | 438 |      | 
| Anders Carlsson | 69c68b7 | 2009-02-07 23:51:38 +0000 | [diff] [blame] | 439 |     CallArgList Args; | 
 | 440 |     Args.push_back(std::make_pair(RValue::get(DeclPtr),  | 
 | 441 |                                   getContext().getPointerType(D.getType()))); | 
| Anders Carlsson | cabec03 | 2009-04-26 00:34:20 +0000 | [diff] [blame] | 442 |      | 
 | 443 |     EmitCall(Info, F, Args); | 
| Anders Carlsson | 69c68b7 | 2009-02-07 23:51:38 +0000 | [diff] [blame] | 444 |   } | 
| Mike Stump | 797b632 | 2009-03-05 01:23:13 +0000 | [diff] [blame] | 445 |  | 
| Mike Stump | d9e0fae | 2009-03-05 02:34:38 +0000 | [diff] [blame] | 446 |   if (needsDispose && CGM.getLangOptions().getGCMode() != LangOptions::GCOnly) { | 
| Mike Stump | 797b632 | 2009-03-05 01:23:13 +0000 | [diff] [blame] | 447 |     CleanupScope scope(*this); | 
| Mike Stump | 1851b68 | 2009-03-06 04:53:30 +0000 | [diff] [blame] | 448 |     llvm::Value *V = Builder.CreateStructGEP(DeclPtr, 1, "forwarding"); | 
 | 449 |     V = Builder.CreateLoad(V, false); | 
 | 450 |     BuildBlockRelease(V); | 
| Mike Stump | 797b632 | 2009-03-05 01:23:13 +0000 | [diff] [blame] | 451 |   } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 452 | } | 
 | 453 |  | 
| Chris Lattner | 2621fd1 | 2008-05-08 05:58:21 +0000 | [diff] [blame] | 454 | /// Emit an alloca (or GlobalValue depending on target)  | 
 | 455 | /// for the specified parameter and set up LocalDeclMap. | 
| Daniel Dunbar | b7ec246 | 2008-08-16 03:19:19 +0000 | [diff] [blame] | 456 | void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) { | 
 | 457 |   // FIXME: Why isn't ImplicitParamDecl a ParmVarDecl? | 
| Sanjiv Gupta | 31fc07d | 2008-10-31 09:52:39 +0000 | [diff] [blame] | 458 |   assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) && | 
| Daniel Dunbar | b7ec246 | 2008-08-16 03:19:19 +0000 | [diff] [blame] | 459 |          "Invalid argument to EmitParmDecl"); | 
| Chris Lattner | 8bcfc5b | 2008-04-06 23:10:54 +0000 | [diff] [blame] | 460 |   QualType Ty = D.getType(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 461 |    | 
 | 462 |   llvm::Value *DeclPtr; | 
| Eli Friedman | 3c2b317 | 2008-02-15 12:20:59 +0000 | [diff] [blame] | 463 |   if (!Ty->isConstantSizeType()) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 464 |     // Variable sized values always are passed by-reference. | 
 | 465 |     DeclPtr = Arg; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 466 |   } else { | 
| Dan Gohman | d79a726 | 2008-05-22 22:12:56 +0000 | [diff] [blame] | 467 |     // A fixed sized single-value variable becomes an alloca in the entry block. | 
| Eli Friedman | a3460ac | 2009-03-04 04:25:14 +0000 | [diff] [blame] | 468 |     const llvm::Type *LTy = ConvertTypeForMem(Ty); | 
| Dan Gohman | d79a726 | 2008-05-22 22:12:56 +0000 | [diff] [blame] | 469 |     if (LTy->isSingleValueType()) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 470 |       // TODO: Alignment | 
| Chris Lattner | 39f34e9 | 2008-11-24 04:00:27 +0000 | [diff] [blame] | 471 |       std::string Name = D.getNameAsString(); | 
| Daniel Dunbar | 5627377 | 2008-09-17 00:51:38 +0000 | [diff] [blame] | 472 |       Name += ".addr"; | 
| Chris Lattner | f146684 | 2009-03-22 00:24:14 +0000 | [diff] [blame] | 473 |       DeclPtr = CreateTempAlloca(LTy); | 
 | 474 |       DeclPtr->setName(Name.c_str()); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 475 |        | 
 | 476 |       // Store the initial value into the alloca. | 
| Anders Carlsson | b4aa466 | 2009-05-19 18:50:41 +0000 | [diff] [blame] | 477 |       EmitStoreOfScalar(Arg, DeclPtr, Ty.isVolatileQualified(), Ty); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 478 |     } else { | 
 | 479 |       // Otherwise, if this is an aggregate, just use the input pointer. | 
 | 480 |       DeclPtr = Arg; | 
 | 481 |     } | 
| Chris Lattner | 39f34e9 | 2008-11-24 04:00:27 +0000 | [diff] [blame] | 482 |     Arg->setName(D.getNameAsString()); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 483 |   } | 
 | 484 |  | 
 | 485 |   llvm::Value *&DMEntry = LocalDeclMap[&D]; | 
 | 486 |   assert(DMEntry == 0 && "Decl already exists in localdeclmap!"); | 
 | 487 |   DMEntry = DeclPtr; | 
| Sanjiv Gupta | cc9b163 | 2008-05-30 10:30:31 +0000 | [diff] [blame] | 488 |  | 
 | 489 |   // Emit debug info for param declaration. | 
| Anders Carlsson | e896d98 | 2009-02-13 08:11:52 +0000 | [diff] [blame] | 490 |   if (CGDebugInfo *DI = getDebugInfo()) { | 
| Daniel Dunbar | 66031a5 | 2008-10-17 16:15:48 +0000 | [diff] [blame] | 491 |     DI->setLocation(D.getLocation()); | 
| Chris Lattner | 9c85ba3 | 2008-11-10 06:08:34 +0000 | [diff] [blame] | 492 |     DI->EmitDeclareOfArgVariable(&D, DeclPtr, Builder); | 
| Sanjiv Gupta | cc9b163 | 2008-05-30 10:30:31 +0000 | [diff] [blame] | 493 |   } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 494 | } | 
 | 495 |  |