| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1 | //===--- CodeGenFunction.cpp - Emit LLVM Code from ASTs for a Function ----===// | 
 | 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 coordinates the per-function state used while generating code. | 
 | 11 | // | 
 | 12 | //===----------------------------------------------------------------------===// | 
 | 13 |  | 
 | 14 | #include "CodeGenFunction.h" | 
 | 15 | #include "CodeGenModule.h" | 
| Eli Friedman | 3f2af10 | 2008-05-22 01:40:10 +0000 | [diff] [blame] | 16 | #include "CGDebugInfo.h" | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 17 | #include "clang/Basic/TargetInfo.h" | 
| Chris Lattner | 31a0984 | 2008-11-12 08:04:58 +0000 | [diff] [blame] | 18 | #include "clang/AST/APValue.h" | 
| Daniel Dunbar | de7fb84 | 2008-08-11 05:00:27 +0000 | [diff] [blame] | 19 | #include "clang/AST/ASTContext.h" | 
| Daniel Dunbar | c4a1dea | 2008-08-11 05:35:13 +0000 | [diff] [blame] | 20 | #include "clang/AST/Decl.h" | 
| Anders Carlsson | 2b77ba8 | 2009-04-04 20:47:02 +0000 | [diff] [blame] | 21 | #include "clang/AST/DeclCXX.h" | 
| Mike Stump | 6a1e0eb | 2009-12-04 23:26:17 +0000 | [diff] [blame] | 22 | #include "clang/AST/StmtCXX.h" | 
| Mike Stump | 4e7a1f7 | 2009-02-21 20:00:35 +0000 | [diff] [blame] | 23 | #include "llvm/Target/TargetData.h" | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 24 | using namespace clang; | 
 | 25 | using namespace CodeGen; | 
 | 26 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 27 | CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) | 
| Mike Stump | a4f668f | 2009-03-06 01:33:24 +0000 | [diff] [blame] | 28 |   : BlockFunction(cgm, *this, Builder), CGM(cgm), | 
 | 29 |     Target(CGM.getContext().Target), | 
| Owen Anderson | aac8705 | 2009-07-08 20:52:20 +0000 | [diff] [blame] | 30 |     Builder(cgm.getModule().getContext()), | 
| Chris Lattner | d9becd1 | 2009-10-28 23:59:40 +0000 | [diff] [blame] | 31 |     DebugInfo(0), IndirectBranch(0), | 
| Chris Lattner | 3d00fdc | 2009-10-13 06:55:33 +0000 | [diff] [blame] | 32 |     SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0), | 
| Anders Carlsson | f6c56e2 | 2009-11-25 03:15:49 +0000 | [diff] [blame] | 33 |     CXXThisDecl(0), CXXVTTDecl(0), | 
| Mike Stump | 15037ca | 2009-12-15 00:35:12 +0000 | [diff] [blame] | 34 |     ConditionalBranchLevel(0), TerminateHandler(0), TrapBB(0), | 
| Mike Stump | be07f60 | 2009-12-14 21:58:14 +0000 | [diff] [blame] | 35 |     UniqueAggrDestructorCount(0) { | 
| Mike Stump | 4e7a1f7 | 2009-02-21 20:00:35 +0000 | [diff] [blame] | 36 |   LLVMIntTy = ConvertType(getContext().IntTy); | 
 | 37 |   LLVMPointerWidth = Target.getPointerWidth(0); | 
| Mike Stump | d88ea56 | 2009-12-09 03:35:49 +0000 | [diff] [blame] | 38 |   Exceptions = getContext().getLangOptions().Exceptions; | 
| Mike Stump | 9c276ae | 2009-12-12 01:27:46 +0000 | [diff] [blame] | 39 |   CatchUndefined = getContext().getLangOptions().CatchUndefined; | 
| Chris Lattner | 4111024 | 2008-06-17 18:05:57 +0000 | [diff] [blame] | 40 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 41 |  | 
 | 42 | ASTContext &CodeGenFunction::getContext() const { | 
 | 43 |   return CGM.getContext(); | 
 | 44 | } | 
 | 45 |  | 
 | 46 |  | 
 | 47 | llvm::BasicBlock *CodeGenFunction::getBasicBlockForLabel(const LabelStmt *S) { | 
 | 48 |   llvm::BasicBlock *&BB = LabelMap[S]; | 
 | 49 |   if (BB) return BB; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 50 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 51 |   // Create, but don't insert, the new block. | 
| Daniel Dunbar | 55e8742 | 2008-11-11 02:29:29 +0000 | [diff] [blame] | 52 |   return BB = createBasicBlock(S->getName()); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 53 | } | 
 | 54 |  | 
| Daniel Dunbar | 0096acf | 2009-02-25 19:24:29 +0000 | [diff] [blame] | 55 | llvm::Value *CodeGenFunction::GetAddrOfLocalVar(const VarDecl *VD) { | 
 | 56 |   llvm::Value *Res = LocalDeclMap[VD]; | 
 | 57 |   assert(Res && "Invalid argument to GetAddrOfLocalVar(), no decl!"); | 
 | 58 |   return Res; | 
| Lauro Ramos Venancio | 8137335 | 2008-02-26 21:41:45 +0000 | [diff] [blame] | 59 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 60 |  | 
| Daniel Dunbar | 0096acf | 2009-02-25 19:24:29 +0000 | [diff] [blame] | 61 | llvm::Constant * | 
 | 62 | CodeGenFunction::GetAddrOfStaticLocalVar(const VarDecl *BVD) { | 
 | 63 |   return cast<llvm::Constant>(GetAddrOfLocalVar(BVD)); | 
| Anders Carlsson | dde0a94 | 2008-09-11 09:15:33 +0000 | [diff] [blame] | 64 | } | 
 | 65 |  | 
| Daniel Dunbar | 8b1a343 | 2009-02-03 23:03:55 +0000 | [diff] [blame] | 66 | const llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) { | 
 | 67 |   return CGM.getTypes().ConvertTypeForMem(T); | 
 | 68 | } | 
 | 69 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 70 | const llvm::Type *CodeGenFunction::ConvertType(QualType T) { | 
 | 71 |   return CGM.getTypes().ConvertType(T); | 
 | 72 | } | 
 | 73 |  | 
 | 74 | bool CodeGenFunction::hasAggregateLLVMType(QualType T) { | 
| Anders Carlsson | e9d34dc | 2009-09-29 02:09:01 +0000 | [diff] [blame] | 75 |   return T->isRecordType() || T->isArrayType() || T->isAnyComplexType() || | 
 | 76 |     T->isMemberFunctionPointerType(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 77 | } | 
 | 78 |  | 
| Daniel Dunbar | 1c1d607 | 2009-01-26 23:27:52 +0000 | [diff] [blame] | 79 | void CodeGenFunction::EmitReturnBlock() { | 
 | 80 |   // For cleanliness, we try to avoid emitting the return block for | 
 | 81 |   // simple cases. | 
 | 82 |   llvm::BasicBlock *CurBB = Builder.GetInsertBlock(); | 
 | 83 |  | 
 | 84 |   if (CurBB) { | 
 | 85 |     assert(!CurBB->getTerminator() && "Unexpected terminated block."); | 
 | 86 |  | 
| Daniel Dunbar | 96e18b0 | 2009-07-19 08:24:34 +0000 | [diff] [blame] | 87 |     // We have a valid insert point, reuse it if it is empty or there are no | 
 | 88 |     // explicit jumps to the return block. | 
 | 89 |     if (CurBB->empty() || ReturnBlock->use_empty()) { | 
 | 90 |       ReturnBlock->replaceAllUsesWith(CurBB); | 
| Daniel Dunbar | 1c1d607 | 2009-01-26 23:27:52 +0000 | [diff] [blame] | 91 |       delete ReturnBlock; | 
| Daniel Dunbar | 96e18b0 | 2009-07-19 08:24:34 +0000 | [diff] [blame] | 92 |     } else | 
| Daniel Dunbar | 1c1d607 | 2009-01-26 23:27:52 +0000 | [diff] [blame] | 93 |       EmitBlock(ReturnBlock); | 
 | 94 |     return; | 
 | 95 |   } | 
 | 96 |  | 
 | 97 |   // Otherwise, if the return block is the target of a single direct | 
 | 98 |   // branch then we can just put the code in that block instead. This | 
 | 99 |   // cleans up functions which started with a unified return block. | 
 | 100 |   if (ReturnBlock->hasOneUse()) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 101 |     llvm::BranchInst *BI = | 
| Daniel Dunbar | 1c1d607 | 2009-01-26 23:27:52 +0000 | [diff] [blame] | 102 |       dyn_cast<llvm::BranchInst>(*ReturnBlock->use_begin()); | 
 | 103 |     if (BI && BI->isUnconditional() && BI->getSuccessor(0) == ReturnBlock) { | 
 | 104 |       // Reset insertion point and delete the branch. | 
 | 105 |       Builder.SetInsertPoint(BI->getParent()); | 
 | 106 |       BI->eraseFromParent(); | 
 | 107 |       delete ReturnBlock; | 
 | 108 |       return; | 
 | 109 |     } | 
 | 110 |   } | 
 | 111 |  | 
| Mike Stump | f5408fe | 2009-05-16 07:57:57 +0000 | [diff] [blame] | 112 |   // FIXME: We are at an unreachable point, there is no reason to emit the block | 
 | 113 |   // unless it has uses. However, we still need a place to put the debug | 
 | 114 |   // region.end for now. | 
| Daniel Dunbar | 1c1d607 | 2009-01-26 23:27:52 +0000 | [diff] [blame] | 115 |  | 
 | 116 |   EmitBlock(ReturnBlock); | 
 | 117 | } | 
 | 118 |  | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 119 | void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { | 
| Chris Lattner | da13870 | 2007-07-16 21:28:45 +0000 | [diff] [blame] | 120 |   assert(BreakContinueStack.empty() && | 
 | 121 |          "mismatched push/pop in break/continue stack!"); | 
| Anders Carlsson | bd6fa3d | 2009-02-08 00:16:35 +0000 | [diff] [blame] | 122 |   assert(BlockScopes.empty() && | 
 | 123 |          "did not remove all blocks from block scope map!"); | 
 | 124 |   assert(CleanupEntries.empty() && | 
 | 125 |          "mismatched push/pop in cleanup stack!"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 126 |  | 
 | 127 |   // Emit function epilog (to return). | 
| Daniel Dunbar | 1c1d607 | 2009-01-26 23:27:52 +0000 | [diff] [blame] | 128 |   EmitReturnBlock(); | 
| Daniel Dunbar | f5bd45c | 2008-11-11 20:59:54 +0000 | [diff] [blame] | 129 |  | 
 | 130 |   // Emit debug descriptor for function end. | 
| Anders Carlsson | e896d98 | 2009-02-13 08:11:52 +0000 | [diff] [blame] | 131 |   if (CGDebugInfo *DI = getDebugInfo()) { | 
| Daniel Dunbar | f5bd45c | 2008-11-11 20:59:54 +0000 | [diff] [blame] | 132 |     DI->setLocation(EndLoc); | 
 | 133 |     DI->EmitRegionEnd(CurFn, Builder); | 
 | 134 |   } | 
 | 135 |  | 
| Daniel Dunbar | 88b5396 | 2009-02-02 22:03:45 +0000 | [diff] [blame] | 136 |   EmitFunctionEpilog(*CurFnInfo, ReturnValue); | 
| Mike Stump | cce3d4f | 2009-12-07 23:38:24 +0000 | [diff] [blame] | 137 |   EmitEndEHSpec(CurCodeDecl); | 
| Daniel Dunbar | 5ca2084 | 2008-09-09 21:00:17 +0000 | [diff] [blame] | 138 |  | 
| Chris Lattner | d9becd1 | 2009-10-28 23:59:40 +0000 | [diff] [blame] | 139 |   // If someone did an indirect goto, emit the indirect goto block at the end of | 
 | 140 |   // the function. | 
 | 141 |   if (IndirectBranch) { | 
 | 142 |     EmitBlock(IndirectBranch->getParent()); | 
 | 143 |     Builder.ClearInsertionPoint(); | 
 | 144 |   } | 
 | 145 |    | 
| Chris Lattner | 5a2fa14 | 2007-12-02 06:32:24 +0000 | [diff] [blame] | 146 |   // Remove the AllocaInsertPt instruction, which is just a convenience for us. | 
| Chris Lattner | 481769b | 2009-03-31 22:17:44 +0000 | [diff] [blame] | 147 |   llvm::Instruction *Ptr = AllocaInsertPt; | 
| Chris Lattner | 5a2fa14 | 2007-12-02 06:32:24 +0000 | [diff] [blame] | 148 |   AllocaInsertPt = 0; | 
| Chris Lattner | 481769b | 2009-03-31 22:17:44 +0000 | [diff] [blame] | 149 |   Ptr->eraseFromParent(); | 
| Chris Lattner | d9becd1 | 2009-10-28 23:59:40 +0000 | [diff] [blame] | 150 |    | 
 | 151 |   // If someone took the address of a label but never did an indirect goto, we | 
 | 152 |   // made a zero entry PHI node, which is illegal, zap it now. | 
 | 153 |   if (IndirectBranch) { | 
 | 154 |     llvm::PHINode *PN = cast<llvm::PHINode>(IndirectBranch->getAddress()); | 
 | 155 |     if (PN->getNumIncomingValues() == 0) { | 
 | 156 |       PN->replaceAllUsesWith(llvm::UndefValue::get(PN->getType())); | 
 | 157 |       PN->eraseFromParent(); | 
 | 158 |     } | 
 | 159 |   } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 160 | } | 
 | 161 |  | 
| Anders Carlsson | 0ff8baf | 2009-09-11 00:07:24 +0000 | [diff] [blame] | 162 | void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, | 
| Daniel Dunbar | 7c08651 | 2008-09-09 23:14:03 +0000 | [diff] [blame] | 163 |                                     llvm::Function *Fn, | 
| Daniel Dunbar | 2284ac9 | 2008-10-18 18:22:23 +0000 | [diff] [blame] | 164 |                                     const FunctionArgList &Args, | 
 | 165 |                                     SourceLocation StartLoc) { | 
| Anders Carlsson | 0ff8baf | 2009-09-11 00:07:24 +0000 | [diff] [blame] | 166 |   const Decl *D = GD.getDecl(); | 
 | 167 |    | 
| Anders Carlsson | 4cc1a47 | 2009-02-09 20:20:56 +0000 | [diff] [blame] | 168 |   DidCallStackSave = false; | 
| Chris Lattner | b5437d2 | 2009-04-23 05:30:27 +0000 | [diff] [blame] | 169 |   CurCodeDecl = CurFuncDecl = D; | 
| Daniel Dunbar | 7c08651 | 2008-09-09 23:14:03 +0000 | [diff] [blame] | 170 |   FnRetTy = RetTy; | 
| Daniel Dunbar | bd012ff | 2008-07-29 23:18:29 +0000 | [diff] [blame] | 171 |   CurFn = Fn; | 
| Chris Lattner | 4111024 | 2008-06-17 18:05:57 +0000 | [diff] [blame] | 172 |   assert(CurFn->isDeclaration() && "Function already has body?"); | 
 | 173 |  | 
| Daniel Dunbar | 55e8742 | 2008-11-11 02:29:29 +0000 | [diff] [blame] | 174 |   llvm::BasicBlock *EntryBB = createBasicBlock("entry", CurFn); | 
| Daniel Dunbar | 5ca2084 | 2008-09-09 21:00:17 +0000 | [diff] [blame] | 175 |  | 
| Chris Lattner | 4111024 | 2008-06-17 18:05:57 +0000 | [diff] [blame] | 176 |   // Create a marker to make it easy to insert allocas into the entryblock | 
 | 177 |   // later.  Don't create this with the builder, because we don't want it | 
 | 178 |   // folded. | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 179 |   llvm::Value *Undef = llvm::UndefValue::get(llvm::Type::getInt32Ty(VMContext)); | 
| Mike Stump | bcdc0f0 | 2009-09-25 18:11:00 +0000 | [diff] [blame] | 180 |   AllocaInsertPt = new llvm::BitCastInst(Undef, | 
 | 181 |                                          llvm::Type::getInt32Ty(VMContext), "", | 
| Chris Lattner | 4111024 | 2008-06-17 18:05:57 +0000 | [diff] [blame] | 182 |                                          EntryBB); | 
| Chris Lattner | f146684 | 2009-03-22 00:24:14 +0000 | [diff] [blame] | 183 |   if (Builder.isNamePreserving()) | 
 | 184 |     AllocaInsertPt->setName("allocapt"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 185 |  | 
| Daniel Dunbar | 55e8742 | 2008-11-11 02:29:29 +0000 | [diff] [blame] | 186 |   ReturnBlock = createBasicBlock("return"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 187 |  | 
| Chris Lattner | 4111024 | 2008-06-17 18:05:57 +0000 | [diff] [blame] | 188 |   Builder.SetInsertPoint(EntryBB); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 189 |  | 
| Mike Stump | 91cc815 | 2009-10-23 01:52:13 +0000 | [diff] [blame] | 190 |   QualType FnType = getContext().getFunctionType(RetTy, 0, 0, false, 0); | 
 | 191 |  | 
| Sanjiv Gupta | af99417 | 2008-07-04 11:04:26 +0000 | [diff] [blame] | 192 |   // Emit subprogram debug descriptor. | 
| Daniel Dunbar | 7c08651 | 2008-09-09 23:14:03 +0000 | [diff] [blame] | 193 |   // FIXME: The cast here is a huge hack. | 
| Anders Carlsson | e896d98 | 2009-02-13 08:11:52 +0000 | [diff] [blame] | 194 |   if (CGDebugInfo *DI = getDebugInfo()) { | 
| Daniel Dunbar | 2284ac9 | 2008-10-18 18:22:23 +0000 | [diff] [blame] | 195 |     DI->setLocation(StartLoc); | 
| Anders Carlsson | 1860a31 | 2009-09-11 00:11:35 +0000 | [diff] [blame] | 196 |     if (isa<FunctionDecl>(D)) { | 
| Mike Stump | 91cc815 | 2009-10-23 01:52:13 +0000 | [diff] [blame] | 197 |       DI->EmitFunctionStart(CGM.getMangledName(GD), FnType, CurFn, Builder); | 
| Daniel Dunbar | 2284ac9 | 2008-10-18 18:22:23 +0000 | [diff] [blame] | 198 |     } else { | 
 | 199 |       // Just use LLVM function name. | 
| Benjamin Kramer | 155fd79 | 2009-12-08 14:04:35 +0000 | [diff] [blame] | 200 |       DI->EmitFunctionStart(Fn->getName(), FnType, CurFn, Builder); | 
| Sanjiv Gupta | af99417 | 2008-07-04 11:04:26 +0000 | [diff] [blame] | 201 |     } | 
| Sanjiv Gupta | af99417 | 2008-07-04 11:04:26 +0000 | [diff] [blame] | 202 |   } | 
 | 203 |  | 
| Daniel Dunbar | 88b5396 | 2009-02-02 22:03:45 +0000 | [diff] [blame] | 204 |   // FIXME: Leaked. | 
| Daniel Dunbar | 541b63b | 2009-02-02 23:23:47 +0000 | [diff] [blame] | 205 |   CurFnInfo = &CGM.getTypes().getFunctionInfo(FnRetTy, Args); | 
| Eli Friedman | b17daf9 | 2009-12-04 02:43:40 +0000 | [diff] [blame] | 206 |  | 
 | 207 |   if (RetTy->isVoidType()) { | 
 | 208 |     // Void type; nothing to return. | 
 | 209 |     ReturnValue = 0; | 
 | 210 |   } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect && | 
 | 211 |              hasAggregateLLVMType(CurFnInfo->getReturnType())) { | 
 | 212 |     // Indirect aggregate return; emit returned value directly into sret slot. | 
 | 213 |     // This reduces code size, and is also affects correctness in C++. | 
 | 214 |     ReturnValue = CurFn->arg_begin(); | 
 | 215 |   } else { | 
 | 216 |     ReturnValue = CreateTempAlloca(ConvertType(RetTy), "retval"); | 
 | 217 |   } | 
 | 218 |  | 
| Mike Stump | cce3d4f | 2009-12-07 23:38:24 +0000 | [diff] [blame] | 219 |   EmitStartEHSpec(CurCodeDecl); | 
| Daniel Dunbar | 88b5396 | 2009-02-02 22:03:45 +0000 | [diff] [blame] | 220 |   EmitFunctionProlog(*CurFnInfo, CurFn, Args); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 221 |  | 
| Anders Carlsson | 751358f | 2008-12-20 21:28:43 +0000 | [diff] [blame] | 222 |   // If any of the arguments have a variably modified type, make sure to | 
 | 223 |   // emit the type size. | 
 | 224 |   for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); | 
 | 225 |        i != e; ++i) { | 
 | 226 |     QualType Ty = i->second; | 
 | 227 |  | 
 | 228 |     if (Ty->isVariablyModifiedType()) | 
 | 229 |       EmitVLASize(Ty); | 
 | 230 |   } | 
| Daniel Dunbar | 7c08651 | 2008-09-09 23:14:03 +0000 | [diff] [blame] | 231 | } | 
| Eli Friedman | eb4b705 | 2008-08-25 21:31:01 +0000 | [diff] [blame] | 232 |  | 
| Anders Carlsson | f6c56e2 | 2009-11-25 03:15:49 +0000 | [diff] [blame] | 233 | static bool NeedsVTTParameter(GlobalDecl GD) { | 
 | 234 |   const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); | 
 | 235 |    | 
 | 236 |   // We don't have any virtual bases, just return early. | 
 | 237 |   if (!MD->getParent()->getNumVBases()) | 
 | 238 |     return false; | 
 | 239 |    | 
 | 240 |   // Check if we have a base constructor. | 
 | 241 |   if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base) | 
 | 242 |     return true; | 
 | 243 |  | 
 | 244 |   // Check if we have a base destructor. | 
 | 245 |   if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base) | 
 | 246 |     return true; | 
 | 247 |    | 
 | 248 |   return false; | 
 | 249 | } | 
 | 250 |  | 
| Anders Carlsson | 0ff8baf | 2009-09-11 00:07:24 +0000 | [diff] [blame] | 251 | void CodeGenFunction::GenerateCode(GlobalDecl GD, | 
| Daniel Dunbar | 7c08651 | 2008-09-09 23:14:03 +0000 | [diff] [blame] | 252 |                                    llvm::Function *Fn) { | 
| Anders Carlsson | 0ff8baf | 2009-09-11 00:07:24 +0000 | [diff] [blame] | 253 |   const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); | 
 | 254 |    | 
| Anders Carlsson | e896d98 | 2009-02-13 08:11:52 +0000 | [diff] [blame] | 255 |   // Check if we should generate debug info for this function. | 
| Mike Stump | 1feade8 | 2009-08-26 22:31:08 +0000 | [diff] [blame] | 256 |   if (CGM.getDebugInfo() && !FD->hasAttr<NoDebugAttr>()) | 
| Anders Carlsson | e896d98 | 2009-02-13 08:11:52 +0000 | [diff] [blame] | 257 |     DebugInfo = CGM.getDebugInfo(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 258 |  | 
| Daniel Dunbar | 7c08651 | 2008-09-09 23:14:03 +0000 | [diff] [blame] | 259 |   FunctionArgList Args; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 260 |  | 
| Mike Stump | 6a1e0eb | 2009-12-04 23:26:17 +0000 | [diff] [blame] | 261 |   CurGD = GD; | 
 | 262 |   OuterTryBlock = 0; | 
| Anders Carlsson | 2b77ba8 | 2009-04-04 20:47:02 +0000 | [diff] [blame] | 263 |   if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { | 
 | 264 |     if (MD->isInstance()) { | 
 | 265 |       // Create the implicit 'this' decl. | 
 | 266 |       // FIXME: I'm not entirely sure I like using a fake decl just for code | 
 | 267 |       // generation. Maybe we can come up with a better way? | 
 | 268 |       CXXThisDecl = ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 269 |                                               &getContext().Idents.get("this"), | 
| Anders Carlsson | 2b77ba8 | 2009-04-04 20:47:02 +0000 | [diff] [blame] | 270 |                                               MD->getThisType(getContext())); | 
 | 271 |       Args.push_back(std::make_pair(CXXThisDecl, CXXThisDecl->getType())); | 
| Anders Carlsson | f6c56e2 | 2009-11-25 03:15:49 +0000 | [diff] [blame] | 272 |        | 
 | 273 |       // Check if we need a VTT parameter as well. | 
 | 274 |       if (NeedsVTTParameter(GD)) { | 
 | 275 |         // FIXME: The comment about using a fake decl above applies here too. | 
 | 276 |         QualType T = getContext().getPointerType(getContext().VoidPtrTy); | 
 | 277 |         CXXVTTDecl =  | 
 | 278 |           ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), | 
 | 279 |                                     &getContext().Idents.get("vtt"), T); | 
 | 280 |         Args.push_back(std::make_pair(CXXVTTDecl, CXXVTTDecl->getType())); | 
 | 281 |       } | 
| Anders Carlsson | 2b77ba8 | 2009-04-04 20:47:02 +0000 | [diff] [blame] | 282 |     } | 
 | 283 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 284 |  | 
| Eli Friedman | eb4b705 | 2008-08-25 21:31:01 +0000 | [diff] [blame] | 285 |   if (FD->getNumParams()) { | 
| John McCall | 183700f | 2009-09-21 23:43:11 +0000 | [diff] [blame] | 286 |     const FunctionProtoType* FProto = FD->getType()->getAs<FunctionProtoType>(); | 
| Eli Friedman | eb4b705 | 2008-08-25 21:31:01 +0000 | [diff] [blame] | 287 |     assert(FProto && "Function def must have prototype!"); | 
| Daniel Dunbar | 7c08651 | 2008-09-09 23:14:03 +0000 | [diff] [blame] | 288 |  | 
 | 289 |     for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 290 |       Args.push_back(std::make_pair(FD->getParamDecl(i), | 
| Daniel Dunbar | 7c08651 | 2008-09-09 23:14:03 +0000 | [diff] [blame] | 291 |                                     FProto->getArgType(i))); | 
| Chris Lattner | 4111024 | 2008-06-17 18:05:57 +0000 | [diff] [blame] | 292 |   } | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 293 |  | 
| Argyrios Kyrtzidis | 6fb0aee | 2009-06-30 02:35:26 +0000 | [diff] [blame] | 294 |   if (const CompoundStmt *S = FD->getCompoundBody()) { | 
| Anders Carlsson | 0ff8baf | 2009-09-11 00:07:24 +0000 | [diff] [blame] | 295 |     StartFunction(GD, FD->getResultType(), Fn, Args, S->getLBracLoc()); | 
| Anders Carlsson | 4365bba | 2009-11-06 02:55:43 +0000 | [diff] [blame] | 296 |  | 
 | 297 |     if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) { | 
| Anders Carlsson | de1d26b | 2009-09-14 05:32:02 +0000 | [diff] [blame] | 298 |       EmitCtorPrologue(CD, GD.getCtorType()); | 
| Anders Carlsson | 4365bba | 2009-11-06 02:55:43 +0000 | [diff] [blame] | 299 |       EmitStmt(S); | 
| Anders Carlsson | 5e1b918 | 2009-11-06 04:19:02 +0000 | [diff] [blame] | 300 |        | 
 | 301 |       // If any of the member initializers are temporaries bound to references | 
 | 302 |       // make sure to emit their destructors. | 
 | 303 |       EmitCleanupBlocks(0); | 
 | 304 |        | 
| Anders Carlsson | 4365bba | 2009-11-06 02:55:43 +0000 | [diff] [blame] | 305 |     } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) { | 
 | 306 |       llvm::BasicBlock *DtorEpilogue  = createBasicBlock("dtor.epilogue"); | 
 | 307 |       PushCleanupBlock(DtorEpilogue); | 
 | 308 |  | 
 | 309 |       EmitStmt(S); | 
| Anders Carlsson | c33e4ba | 2009-10-06 18:09:57 +0000 | [diff] [blame] | 310 |        | 
| Anders Carlsson | c33e4ba | 2009-10-06 18:09:57 +0000 | [diff] [blame] | 311 |       CleanupBlockInfo Info = PopCleanupBlock(); | 
 | 312 |  | 
 | 313 |       assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!"); | 
 | 314 |       EmitBlock(DtorEpilogue); | 
| Anders Carlsson | de1d26b | 2009-09-14 05:32:02 +0000 | [diff] [blame] | 315 |       EmitDtorEpilogue(DD, GD.getDtorType()); | 
| Anders Carlsson | c33e4ba | 2009-10-06 18:09:57 +0000 | [diff] [blame] | 316 |        | 
 | 317 |       if (Info.SwitchBlock) | 
 | 318 |         EmitBlock(Info.SwitchBlock); | 
 | 319 |       if (Info.EndBlock) | 
 | 320 |         EmitBlock(Info.EndBlock); | 
| Anders Carlsson | 4365bba | 2009-11-06 02:55:43 +0000 | [diff] [blame] | 321 |     } else { | 
 | 322 |       // Just a regular function, emit its body. | 
 | 323 |       EmitStmt(S); | 
| Anders Carlsson | c33e4ba | 2009-10-06 18:09:57 +0000 | [diff] [blame] | 324 |     } | 
| Anders Carlsson | 4365bba | 2009-11-06 02:55:43 +0000 | [diff] [blame] | 325 |      | 
| Sebastian Redl | d3a413d | 2009-04-26 20:35:05 +0000 | [diff] [blame] | 326 |     FinishFunction(S->getRBracLoc()); | 
| Douglas Gregor | 4513272 | 2009-10-01 20:44:19 +0000 | [diff] [blame] | 327 |   } else if (FD->isImplicit()) { | 
 | 328 |     const CXXRecordDecl *ClassDecl = | 
 | 329 |       cast<CXXRecordDecl>(FD->getDeclContext()); | 
 | 330 |     (void) ClassDecl; | 
| Fariborz Jahanian | c7ff8e1 | 2009-07-30 23:22:00 +0000 | [diff] [blame] | 331 |     if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) { | 
| Douglas Gregor | 4513272 | 2009-10-01 20:44:19 +0000 | [diff] [blame] | 332 |       // FIXME: For C++0x, we want to look for implicit *definitions* of | 
 | 333 |       // these special member functions, rather than implicit *declarations*. | 
| Fariborz Jahanian | 9889652 | 2009-08-06 23:38:16 +0000 | [diff] [blame] | 334 |       if (CD->isCopyConstructor(getContext())) { | 
 | 335 |         assert(!ClassDecl->hasUserDeclaredCopyConstructor() && | 
| Douglas Gregor | 4513272 | 2009-10-01 20:44:19 +0000 | [diff] [blame] | 336 |                "Cannot synthesize a non-implicit copy constructor"); | 
| Anders Carlsson | de1d26b | 2009-09-14 05:32:02 +0000 | [diff] [blame] | 337 |         SynthesizeCXXCopyConstructor(CD, GD.getCtorType(), Fn, Args); | 
| Douglas Gregor | 4513272 | 2009-10-01 20:44:19 +0000 | [diff] [blame] | 338 |       } else if (CD->isDefaultConstructor()) { | 
| Fariborz Jahanian | 9889652 | 2009-08-06 23:38:16 +0000 | [diff] [blame] | 339 |         assert(!ClassDecl->hasUserDeclaredConstructor() && | 
| Douglas Gregor | 4513272 | 2009-10-01 20:44:19 +0000 | [diff] [blame] | 340 |                "Cannot synthesize a non-implicit default constructor."); | 
| Anders Carlsson | de1d26b | 2009-09-14 05:32:02 +0000 | [diff] [blame] | 341 |         SynthesizeDefaultConstructor(CD, GD.getCtorType(), Fn, Args); | 
| Douglas Gregor | 4513272 | 2009-10-01 20:44:19 +0000 | [diff] [blame] | 342 |       } else { | 
 | 343 |         assert(false && "Implicit constructor cannot be synthesized"); | 
| Fariborz Jahanian | 9889652 | 2009-08-06 23:38:16 +0000 | [diff] [blame] | 344 |       } | 
| Douglas Gregor | 4513272 | 2009-10-01 20:44:19 +0000 | [diff] [blame] | 345 |     } else if (const CXXDestructorDecl *CD = dyn_cast<CXXDestructorDecl>(FD)) { | 
 | 346 |       assert(!ClassDecl->hasUserDeclaredDestructor() && | 
 | 347 |              "Cannot synthesize a non-implicit destructor"); | 
 | 348 |       SynthesizeDefaultDestructor(CD, GD.getDtorType(), Fn, Args); | 
 | 349 |     } else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { | 
 | 350 |       assert(MD->isCopyAssignment() &&  | 
 | 351 |              !ClassDecl->hasUserDeclaredCopyAssignment() && | 
 | 352 |              "Cannot synthesize a method that is not an implicit-defined " | 
 | 353 |              "copy constructor"); | 
| Anders Carlsson | de1d26b | 2009-09-14 05:32:02 +0000 | [diff] [blame] | 354 |       SynthesizeCXXCopyAssignment(MD, Fn, Args); | 
| Douglas Gregor | 4513272 | 2009-10-01 20:44:19 +0000 | [diff] [blame] | 355 |     } else { | 
 | 356 |       assert(false && "Cannot synthesize unknown implicit function"); | 
 | 357 |     } | 
| Mike Stump | 6a1e0eb | 2009-12-04 23:26:17 +0000 | [diff] [blame] | 358 |   } else if (const Stmt *S = FD->getBody()) { | 
 | 359 |     if (const CXXTryStmt *TS = dyn_cast<CXXTryStmt>(S)) { | 
 | 360 |       OuterTryBlock = TS; | 
 | 361 |       StartFunction(GD, FD->getResultType(), Fn, Args, TS->getTryLoc()); | 
 | 362 |       EmitStmt(TS); | 
 | 363 |       FinishFunction(TS->getEndLoc()); | 
 | 364 |     } | 
| Anders Carlsson | 0ff8baf | 2009-09-11 00:07:24 +0000 | [diff] [blame] | 365 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 366 |  | 
| Anders Carlsson | 2b77ba8 | 2009-04-04 20:47:02 +0000 | [diff] [blame] | 367 |   // Destroy the 'this' declaration. | 
 | 368 |   if (CXXThisDecl) | 
 | 369 |     CXXThisDecl->Destroy(getContext()); | 
| Anders Carlsson | f6c56e2 | 2009-11-25 03:15:49 +0000 | [diff] [blame] | 370 |    | 
 | 371 |   // Destroy the VTT declaration. | 
 | 372 |   if (CXXVTTDecl) | 
 | 373 |     CXXVTTDecl->Destroy(getContext()); | 
| Chris Lattner | 4111024 | 2008-06-17 18:05:57 +0000 | [diff] [blame] | 374 | } | 
 | 375 |  | 
| Chris Lattner | 0946ccd | 2008-11-11 07:41:27 +0000 | [diff] [blame] | 376 | /// ContainsLabel - Return true if the statement contains a label in it.  If | 
 | 377 | /// this statement is not executed normally, it not containing a label means | 
 | 378 | /// that we can just remove the code. | 
 | 379 | bool CodeGenFunction::ContainsLabel(const Stmt *S, bool IgnoreCaseStmts) { | 
 | 380 |   // Null statement, not a label! | 
 | 381 |   if (S == 0) return false; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 382 |  | 
| Chris Lattner | 0946ccd | 2008-11-11 07:41:27 +0000 | [diff] [blame] | 383 |   // If this is a label, we have to emit the code, consider something like: | 
 | 384 |   // if (0) {  ...  foo:  bar(); }  goto foo; | 
 | 385 |   if (isa<LabelStmt>(S)) | 
 | 386 |     return true; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 387 |  | 
| Chris Lattner | 0946ccd | 2008-11-11 07:41:27 +0000 | [diff] [blame] | 388 |   // If this is a case/default statement, and we haven't seen a switch, we have | 
 | 389 |   // to emit the code. | 
 | 390 |   if (isa<SwitchCase>(S) && !IgnoreCaseStmts) | 
 | 391 |     return true; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 392 |  | 
| Chris Lattner | 0946ccd | 2008-11-11 07:41:27 +0000 | [diff] [blame] | 393 |   // If this is a switch statement, we want to ignore cases below it. | 
 | 394 |   if (isa<SwitchStmt>(S)) | 
 | 395 |     IgnoreCaseStmts = true; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 396 |  | 
| Chris Lattner | 0946ccd | 2008-11-11 07:41:27 +0000 | [diff] [blame] | 397 |   // Scan subexpressions for verboten labels. | 
 | 398 |   for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end(); | 
 | 399 |        I != E; ++I) | 
 | 400 |     if (ContainsLabel(*I, IgnoreCaseStmts)) | 
 | 401 |       return true; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 402 |  | 
| Chris Lattner | 0946ccd | 2008-11-11 07:41:27 +0000 | [diff] [blame] | 403 |   return false; | 
 | 404 | } | 
 | 405 |  | 
| Chris Lattner | 31a0984 | 2008-11-12 08:04:58 +0000 | [diff] [blame] | 406 |  | 
 | 407 | /// ConstantFoldsToSimpleInteger - If the sepcified expression does not fold to | 
 | 408 | /// a constant, or if it does but contains a label, return 0.  If it constant | 
 | 409 | /// folds to 'true' and does not contain a label, return 1, if it constant folds | 
 | 410 | /// to 'false' and does not contain a label, return -1. | 
 | 411 | int CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond) { | 
| Daniel Dunbar | 36bc14c | 2008-11-12 22:37:10 +0000 | [diff] [blame] | 412 |   // FIXME: Rename and handle conversion of other evaluatable things | 
 | 413 |   // to bool. | 
| Anders Carlsson | 64712f1 | 2008-12-01 02:46:24 +0000 | [diff] [blame] | 414 |   Expr::EvalResult Result; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 415 |   if (!Cond->Evaluate(Result, getContext()) || !Result.Val.isInt() || | 
| Anders Carlsson | 64712f1 | 2008-12-01 02:46:24 +0000 | [diff] [blame] | 416 |       Result.HasSideEffects) | 
| Anders Carlsson | ef5a66d | 2008-11-22 22:32:07 +0000 | [diff] [blame] | 417 |     return 0;  // Not foldable, not integer or not fully evaluatable. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 418 |  | 
| Chris Lattner | 31a0984 | 2008-11-12 08:04:58 +0000 | [diff] [blame] | 419 |   if (CodeGenFunction::ContainsLabel(Cond)) | 
 | 420 |     return 0;  // Contains a label. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 421 |  | 
| Anders Carlsson | 64712f1 | 2008-12-01 02:46:24 +0000 | [diff] [blame] | 422 |   return Result.Val.getInt().getBoolValue() ? 1 : -1; | 
| Chris Lattner | 31a0984 | 2008-11-12 08:04:58 +0000 | [diff] [blame] | 423 | } | 
 | 424 |  | 
 | 425 |  | 
 | 426 | /// EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g. for an if | 
 | 427 | /// statement) to the specified blocks.  Based on the condition, this might try | 
 | 428 | /// to simplify the codegen of the conditional based on the branch. | 
 | 429 | /// | 
 | 430 | void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond, | 
 | 431 |                                            llvm::BasicBlock *TrueBlock, | 
 | 432 |                                            llvm::BasicBlock *FalseBlock) { | 
 | 433 |   if (const ParenExpr *PE = dyn_cast<ParenExpr>(Cond)) | 
 | 434 |     return EmitBranchOnBoolExpr(PE->getSubExpr(), TrueBlock, FalseBlock); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 435 |  | 
| Chris Lattner | 31a0984 | 2008-11-12 08:04:58 +0000 | [diff] [blame] | 436 |   if (const BinaryOperator *CondBOp = dyn_cast<BinaryOperator>(Cond)) { | 
 | 437 |     // Handle X && Y in a condition. | 
 | 438 |     if (CondBOp->getOpcode() == BinaryOperator::LAnd) { | 
 | 439 |       // If we have "1 && X", simplify the code.  "0 && X" would have constant | 
 | 440 |       // folded if the case was simple enough. | 
 | 441 |       if (ConstantFoldsToSimpleInteger(CondBOp->getLHS()) == 1) { | 
 | 442 |         // br(1 && X) -> br(X). | 
 | 443 |         return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock); | 
 | 444 |       } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 445 |  | 
| Chris Lattner | 31a0984 | 2008-11-12 08:04:58 +0000 | [diff] [blame] | 446 |       // If we have "X && 1", simplify the code to use an uncond branch. | 
 | 447 |       // "X && 0" would have been constant folded to 0. | 
 | 448 |       if (ConstantFoldsToSimpleInteger(CondBOp->getRHS()) == 1) { | 
 | 449 |         // br(X && 1) -> br(X). | 
 | 450 |         return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock); | 
 | 451 |       } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 452 |  | 
| Chris Lattner | 31a0984 | 2008-11-12 08:04:58 +0000 | [diff] [blame] | 453 |       // Emit the LHS as a conditional.  If the LHS conditional is false, we | 
 | 454 |       // want to jump to the FalseBlock. | 
| Daniel Dunbar | 9615ecb | 2008-11-13 01:38:36 +0000 | [diff] [blame] | 455 |       llvm::BasicBlock *LHSTrue = createBasicBlock("land.lhs.true"); | 
| Chris Lattner | 31a0984 | 2008-11-12 08:04:58 +0000 | [diff] [blame] | 456 |       EmitBranchOnBoolExpr(CondBOp->getLHS(), LHSTrue, FalseBlock); | 
 | 457 |       EmitBlock(LHSTrue); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 458 |  | 
| Chris Lattner | 31a0984 | 2008-11-12 08:04:58 +0000 | [diff] [blame] | 459 |       EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock); | 
 | 460 |       return; | 
 | 461 |     } else if (CondBOp->getOpcode() == BinaryOperator::LOr) { | 
 | 462 |       // If we have "0 || X", simplify the code.  "1 || X" would have constant | 
 | 463 |       // folded if the case was simple enough. | 
 | 464 |       if (ConstantFoldsToSimpleInteger(CondBOp->getLHS()) == -1) { | 
 | 465 |         // br(0 || X) -> br(X). | 
 | 466 |         return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock); | 
 | 467 |       } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 468 |  | 
| Chris Lattner | 31a0984 | 2008-11-12 08:04:58 +0000 | [diff] [blame] | 469 |       // If we have "X || 0", simplify the code to use an uncond branch. | 
 | 470 |       // "X || 1" would have been constant folded to 1. | 
 | 471 |       if (ConstantFoldsToSimpleInteger(CondBOp->getRHS()) == -1) { | 
 | 472 |         // br(X || 0) -> br(X). | 
 | 473 |         return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock); | 
 | 474 |       } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 475 |  | 
| Chris Lattner | 31a0984 | 2008-11-12 08:04:58 +0000 | [diff] [blame] | 476 |       // Emit the LHS as a conditional.  If the LHS conditional is true, we | 
 | 477 |       // want to jump to the TrueBlock. | 
| Daniel Dunbar | 9615ecb | 2008-11-13 01:38:36 +0000 | [diff] [blame] | 478 |       llvm::BasicBlock *LHSFalse = createBasicBlock("lor.lhs.false"); | 
| Chris Lattner | 31a0984 | 2008-11-12 08:04:58 +0000 | [diff] [blame] | 479 |       EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, LHSFalse); | 
 | 480 |       EmitBlock(LHSFalse); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 481 |  | 
| Chris Lattner | 31a0984 | 2008-11-12 08:04:58 +0000 | [diff] [blame] | 482 |       EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock); | 
 | 483 |       return; | 
 | 484 |     } | 
| Chris Lattner | 552f4c4 | 2008-11-12 08:13:36 +0000 | [diff] [blame] | 485 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 486 |  | 
| Chris Lattner | 552f4c4 | 2008-11-12 08:13:36 +0000 | [diff] [blame] | 487 |   if (const UnaryOperator *CondUOp = dyn_cast<UnaryOperator>(Cond)) { | 
 | 488 |     // br(!x, t, f) -> br(x, f, t) | 
 | 489 |     if (CondUOp->getOpcode() == UnaryOperator::LNot) | 
 | 490 |       return EmitBranchOnBoolExpr(CondUOp->getSubExpr(), FalseBlock, TrueBlock); | 
| Chris Lattner | 31a0984 | 2008-11-12 08:04:58 +0000 | [diff] [blame] | 491 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 492 |  | 
| Daniel Dunbar | 09b1489 | 2008-11-12 10:30:32 +0000 | [diff] [blame] | 493 |   if (const ConditionalOperator *CondOp = dyn_cast<ConditionalOperator>(Cond)) { | 
 | 494 |     // Handle ?: operator. | 
 | 495 |  | 
 | 496 |     // Just ignore GNU ?: extension. | 
 | 497 |     if (CondOp->getLHS()) { | 
 | 498 |       // br(c ? x : y, t, f) -> br(c, br(x, t, f), br(y, t, f)) | 
 | 499 |       llvm::BasicBlock *LHSBlock = createBasicBlock("cond.true"); | 
 | 500 |       llvm::BasicBlock *RHSBlock = createBasicBlock("cond.false"); | 
 | 501 |       EmitBranchOnBoolExpr(CondOp->getCond(), LHSBlock, RHSBlock); | 
 | 502 |       EmitBlock(LHSBlock); | 
 | 503 |       EmitBranchOnBoolExpr(CondOp->getLHS(), TrueBlock, FalseBlock); | 
 | 504 |       EmitBlock(RHSBlock); | 
 | 505 |       EmitBranchOnBoolExpr(CondOp->getRHS(), TrueBlock, FalseBlock); | 
 | 506 |       return; | 
 | 507 |     } | 
 | 508 |   } | 
 | 509 |  | 
| Chris Lattner | 31a0984 | 2008-11-12 08:04:58 +0000 | [diff] [blame] | 510 |   // Emit the code with the fully general case. | 
 | 511 |   llvm::Value *CondV = EvaluateExprAsBool(Cond); | 
 | 512 |   Builder.CreateCondBr(CondV, TrueBlock, FalseBlock); | 
 | 513 | } | 
 | 514 |  | 
| Daniel Dunbar | 488e993 | 2008-08-16 00:56:44 +0000 | [diff] [blame] | 515 | /// ErrorUnsupported - Print out an error that codegen doesn't support the | 
| Chris Lattner | dc5e826 | 2007-12-02 01:43:38 +0000 | [diff] [blame] | 516 | /// specified stmt yet. | 
| Daniel Dunbar | 90df4b6 | 2008-09-04 03:43:08 +0000 | [diff] [blame] | 517 | void CodeGenFunction::ErrorUnsupported(const Stmt *S, const char *Type, | 
 | 518 |                                        bool OmitOnError) { | 
 | 519 |   CGM.ErrorUnsupported(S, Type, OmitOnError); | 
| Chris Lattner | dc5e826 | 2007-12-02 01:43:38 +0000 | [diff] [blame] | 520 | } | 
 | 521 |  | 
| Chris Lattner | 88207c9 | 2009-04-21 17:59:23 +0000 | [diff] [blame] | 522 | void CodeGenFunction::EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty) { | 
| Chris Lattner | 36afd38 | 2009-10-13 06:02:42 +0000 | [diff] [blame] | 523 |   const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext); | 
| Anders Carlsson | 3d8400d | 2008-08-30 19:51:14 +0000 | [diff] [blame] | 524 |   if (DestPtr->getType() != BP) | 
 | 525 |     DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp"); | 
 | 526 |  | 
 | 527 |   // Get size and alignment info for this aggregate. | 
 | 528 |   std::pair<uint64_t, unsigned> TypeInfo = getContext().getTypeInfo(Ty); | 
 | 529 |  | 
| Chris Lattner | 88207c9 | 2009-04-21 17:59:23 +0000 | [diff] [blame] | 530 |   // Don't bother emitting a zero-byte memset. | 
 | 531 |   if (TypeInfo.first == 0) | 
 | 532 |     return; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 533 |  | 
| Anders Carlsson | 3d8400d | 2008-08-30 19:51:14 +0000 | [diff] [blame] | 534 |   // FIXME: Handle variable sized types. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 535 |   const llvm::Type *IntPtr = llvm::IntegerType::get(VMContext, | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 536 |                                                     LLVMPointerWidth); | 
| Anders Carlsson | 3d8400d | 2008-08-30 19:51:14 +0000 | [diff] [blame] | 537 |  | 
 | 538 |   Builder.CreateCall4(CGM.getMemSetFn(), DestPtr, | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 539 |                  llvm::Constant::getNullValue(llvm::Type::getInt8Ty(VMContext)), | 
| Anders Carlsson | 3d8400d | 2008-08-30 19:51:14 +0000 | [diff] [blame] | 540 |                       // TypeInfo.first describes size in bits. | 
| Owen Anderson | 4a28d5d | 2009-07-24 23:12:58 +0000 | [diff] [blame] | 541 |                       llvm::ConstantInt::get(IntPtr, TypeInfo.first/8), | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 542 |                       llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), | 
| Anders Carlsson | 3d8400d | 2008-08-30 19:51:14 +0000 | [diff] [blame] | 543 |                                              TypeInfo.second/8)); | 
 | 544 | } | 
 | 545 |  | 
| Chris Lattner | d9becd1 | 2009-10-28 23:59:40 +0000 | [diff] [blame] | 546 | llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelStmt *L) { | 
 | 547 |   // Make sure that there is a block for the indirect goto. | 
 | 548 |   if (IndirectBranch == 0) | 
 | 549 |     GetIndirectGotoBlock(); | 
| Chris Lattner | 3d00fdc | 2009-10-13 06:55:33 +0000 | [diff] [blame] | 550 |    | 
| Chris Lattner | d9becd1 | 2009-10-28 23:59:40 +0000 | [diff] [blame] | 551 |   llvm::BasicBlock *BB = getBasicBlockForLabel(L); | 
| Chris Lattner | 3d00fdc | 2009-10-13 06:55:33 +0000 | [diff] [blame] | 552 |    | 
| Chris Lattner | d9becd1 | 2009-10-28 23:59:40 +0000 | [diff] [blame] | 553 |   // Make sure the indirect branch includes all of the address-taken blocks. | 
 | 554 |   IndirectBranch->addDestination(BB); | 
 | 555 |   return llvm::BlockAddress::get(CurFn, BB); | 
| Chris Lattner | 3d00fdc | 2009-10-13 06:55:33 +0000 | [diff] [blame] | 556 | } | 
 | 557 |  | 
 | 558 | llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() { | 
| Chris Lattner | d9becd1 | 2009-10-28 23:59:40 +0000 | [diff] [blame] | 559 |   // If we already made the indirect branch for indirect goto, return its block. | 
 | 560 |   if (IndirectBranch) return IndirectBranch->getParent(); | 
| Chris Lattner | 3d00fdc | 2009-10-13 06:55:33 +0000 | [diff] [blame] | 561 |    | 
| Chris Lattner | d9becd1 | 2009-10-28 23:59:40 +0000 | [diff] [blame] | 562 |   CGBuilderTy TmpBuilder(createBasicBlock("indirectgoto")); | 
| Chris Lattner | 3d00fdc | 2009-10-13 06:55:33 +0000 | [diff] [blame] | 563 |    | 
| Chris Lattner | d9becd1 | 2009-10-28 23:59:40 +0000 | [diff] [blame] | 564 |   const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); | 
| Chris Lattner | 85e74ac | 2009-10-28 20:36:47 +0000 | [diff] [blame] | 565 |  | 
| Chris Lattner | 3d00fdc | 2009-10-13 06:55:33 +0000 | [diff] [blame] | 566 |   // Create the PHI node that indirect gotos will add entries to. | 
| Chris Lattner | d9becd1 | 2009-10-28 23:59:40 +0000 | [diff] [blame] | 567 |   llvm::Value *DestVal = TmpBuilder.CreatePHI(Int8PtrTy, "indirect.goto.dest"); | 
| Chris Lattner | 3d00fdc | 2009-10-13 06:55:33 +0000 | [diff] [blame] | 568 |    | 
| Chris Lattner | d9becd1 | 2009-10-28 23:59:40 +0000 | [diff] [blame] | 569 |   // Create the indirect branch instruction. | 
 | 570 |   IndirectBranch = TmpBuilder.CreateIndirectBr(DestVal); | 
 | 571 |   return IndirectBranch->getParent(); | 
| Daniel Dunbar | 0ffb125 | 2008-08-04 16:51:22 +0000 | [diff] [blame] | 572 | } | 
| Anders Carlsson | ddf7cac | 2008-11-04 05:30:00 +0000 | [diff] [blame] | 573 |  | 
| Daniel Dunbar | d286f05 | 2009-07-19 06:58:07 +0000 | [diff] [blame] | 574 | llvm::Value *CodeGenFunction::GetVLASize(const VariableArrayType *VAT) { | 
| Eli Friedman | bbed6b9 | 2009-08-15 02:50:32 +0000 | [diff] [blame] | 575 |   llvm::Value *&SizeEntry = VLASizeMap[VAT->getSizeExpr()]; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 576 |  | 
| Anders Carlsson | f666b77 | 2008-12-20 20:27:15 +0000 | [diff] [blame] | 577 |   assert(SizeEntry && "Did not emit size for type"); | 
 | 578 |   return SizeEntry; | 
 | 579 | } | 
| Anders Carlsson | dcc90d8 | 2008-12-12 07:19:02 +0000 | [diff] [blame] | 580 |  | 
| Daniel Dunbar | d286f05 | 2009-07-19 06:58:07 +0000 | [diff] [blame] | 581 | llvm::Value *CodeGenFunction::EmitVLASize(QualType Ty) { | 
| Anders Carlsson | 60d3541 | 2008-12-20 20:46:34 +0000 | [diff] [blame] | 582 |   assert(Ty->isVariablyModifiedType() && | 
 | 583 |          "Must pass variably modified type to EmitVLASizes!"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 584 |  | 
| Daniel Dunbar | d286f05 | 2009-07-19 06:58:07 +0000 | [diff] [blame] | 585 |   EnsureInsertPoint(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 586 |  | 
| Anders Carlsson | 60d3541 | 2008-12-20 20:46:34 +0000 | [diff] [blame] | 587 |   if (const VariableArrayType *VAT = getContext().getAsVariableArrayType(Ty)) { | 
| Eli Friedman | bbed6b9 | 2009-08-15 02:50:32 +0000 | [diff] [blame] | 588 |     llvm::Value *&SizeEntry = VLASizeMap[VAT->getSizeExpr()]; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 589 |  | 
| Anders Carlsson | fcdbb93 | 2008-12-20 21:51:53 +0000 | [diff] [blame] | 590 |     if (!SizeEntry) { | 
| Anders Carlsson | 96f2147 | 2009-02-05 19:43:10 +0000 | [diff] [blame] | 591 |       const llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 592 |  | 
| Chris Lattner | ec18ddd | 2009-08-15 00:03:43 +0000 | [diff] [blame] | 593 |       // Get the element size; | 
 | 594 |       QualType ElemTy = VAT->getElementType(); | 
 | 595 |       llvm::Value *ElemSize; | 
| Anders Carlsson | fcdbb93 | 2008-12-20 21:51:53 +0000 | [diff] [blame] | 596 |       if (ElemTy->isVariableArrayType()) | 
 | 597 |         ElemSize = EmitVLASize(ElemTy); | 
| Chris Lattner | ec18ddd | 2009-08-15 00:03:43 +0000 | [diff] [blame] | 598 |       else | 
| Owen Anderson | 4a28d5d | 2009-07-24 23:12:58 +0000 | [diff] [blame] | 599 |         ElemSize = llvm::ConstantInt::get(SizeTy, | 
| Anders Carlsson | fcdbb93 | 2008-12-20 21:51:53 +0000 | [diff] [blame] | 600 |                                           getContext().getTypeSize(ElemTy) / 8); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 601 |  | 
| Anders Carlsson | fcdbb93 | 2008-12-20 21:51:53 +0000 | [diff] [blame] | 602 |       llvm::Value *NumElements = EmitScalarExpr(VAT->getSizeExpr()); | 
| Anders Carlsson | 96f2147 | 2009-02-05 19:43:10 +0000 | [diff] [blame] | 603 |       NumElements = Builder.CreateIntCast(NumElements, SizeTy, false, "tmp"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 604 |  | 
| Anders Carlsson | fcdbb93 | 2008-12-20 21:51:53 +0000 | [diff] [blame] | 605 |       SizeEntry = Builder.CreateMul(ElemSize, NumElements); | 
| Anders Carlsson | 60d3541 | 2008-12-20 20:46:34 +0000 | [diff] [blame] | 606 |     } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 607 |  | 
| Anders Carlsson | 60d3541 | 2008-12-20 20:46:34 +0000 | [diff] [blame] | 608 |     return SizeEntry; | 
| Anders Carlsson | dcc90d8 | 2008-12-12 07:19:02 +0000 | [diff] [blame] | 609 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 610 |  | 
| Chris Lattner | ec18ddd | 2009-08-15 00:03:43 +0000 | [diff] [blame] | 611 |   if (const ArrayType *AT = dyn_cast<ArrayType>(Ty)) { | 
 | 612 |     EmitVLASize(AT->getElementType()); | 
 | 613 |     return 0; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 614 |   } | 
 | 615 |  | 
| Chris Lattner | ec18ddd | 2009-08-15 00:03:43 +0000 | [diff] [blame] | 616 |   const PointerType *PT = Ty->getAs<PointerType>(); | 
 | 617 |   assert(PT && "unknown VM type!"); | 
 | 618 |   EmitVLASize(PT->getPointeeType()); | 
| Anders Carlsson | 60d3541 | 2008-12-20 20:46:34 +0000 | [diff] [blame] | 619 |   return 0; | 
| Anders Carlsson | dcc90d8 | 2008-12-12 07:19:02 +0000 | [diff] [blame] | 620 | } | 
| Eli Friedman | 4fd0aa5 | 2009-01-20 17:46:04 +0000 | [diff] [blame] | 621 |  | 
 | 622 | llvm::Value* CodeGenFunction::EmitVAListRef(const Expr* E) { | 
 | 623 |   if (CGM.getContext().getBuiltinVaListType()->isArrayType()) { | 
 | 624 |     return EmitScalarExpr(E); | 
 | 625 |   } | 
 | 626 |   return EmitLValue(E).getAddress(); | 
 | 627 | } | 
| Anders Carlsson | 6ccc476 | 2009-02-07 22:53:43 +0000 | [diff] [blame] | 628 |  | 
| Fariborz Jahanian | 7799621 | 2009-11-04 17:57:40 +0000 | [diff] [blame] | 629 | void CodeGenFunction::PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock, | 
| Mike Stump | 9953383 | 2009-12-02 07:41:41 +0000 | [diff] [blame] | 630 |                                        llvm::BasicBlock *CleanupExitBlock, | 
| Mike Stump | d88ea56 | 2009-12-09 03:35:49 +0000 | [diff] [blame] | 631 |                                        llvm::BasicBlock *PreviousInvokeDest, | 
| Mike Stump | 9953383 | 2009-12-02 07:41:41 +0000 | [diff] [blame] | 632 |                                        bool EHOnly) { | 
 | 633 |   CleanupEntries.push_back(CleanupEntry(CleanupEntryBlock, CleanupExitBlock, | 
| Mike Stump | d88ea56 | 2009-12-09 03:35:49 +0000 | [diff] [blame] | 634 |                                         PreviousInvokeDest, EHOnly)); | 
| Anders Carlsson | 6ccc476 | 2009-02-07 22:53:43 +0000 | [diff] [blame] | 635 | } | 
| Anders Carlsson | c71c845 | 2009-02-07 23:50:39 +0000 | [diff] [blame] | 636 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 637 | void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize) { | 
 | 638 |   assert(CleanupEntries.size() >= OldCleanupStackSize && | 
| Anders Carlsson | c71c845 | 2009-02-07 23:50:39 +0000 | [diff] [blame] | 639 |          "Cleanup stack mismatch!"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 640 |  | 
| Anders Carlsson | c71c845 | 2009-02-07 23:50:39 +0000 | [diff] [blame] | 641 |   while (CleanupEntries.size() > OldCleanupStackSize) | 
 | 642 |     EmitCleanupBlock(); | 
 | 643 | } | 
 | 644 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 645 | CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() { | 
| Anders Carlsson | bb66f9f | 2009-02-08 07:46:24 +0000 | [diff] [blame] | 646 |   CleanupEntry &CE = CleanupEntries.back(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 647 |  | 
| Fariborz Jahanian | 7799621 | 2009-11-04 17:57:40 +0000 | [diff] [blame] | 648 |   llvm::BasicBlock *CleanupEntryBlock = CE.CleanupEntryBlock; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 649 |  | 
| Anders Carlsson | bb66f9f | 2009-02-08 07:46:24 +0000 | [diff] [blame] | 650 |   std::vector<llvm::BasicBlock *> Blocks; | 
 | 651 |   std::swap(Blocks, CE.Blocks); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 652 |  | 
| Anders Carlsson | bb66f9f | 2009-02-08 07:46:24 +0000 | [diff] [blame] | 653 |   std::vector<llvm::BranchInst *> BranchFixups; | 
 | 654 |   std::swap(BranchFixups, CE.BranchFixups); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 655 |  | 
| Mike Stump | 9953383 | 2009-12-02 07:41:41 +0000 | [diff] [blame] | 656 |   bool EHOnly = CE.EHOnly; | 
 | 657 |  | 
| Mike Stump | d88ea56 | 2009-12-09 03:35:49 +0000 | [diff] [blame] | 658 |   setInvokeDest(CE.PreviousInvokeDest); | 
 | 659 |  | 
| Anders Carlsson | bb66f9f | 2009-02-08 07:46:24 +0000 | [diff] [blame] | 660 |   CleanupEntries.pop_back(); | 
 | 661 |  | 
| Anders Carlsson | ad9d00e | 2009-02-08 22:45:15 +0000 | [diff] [blame] | 662 |   // Check if any branch fixups pointed to the scope we just popped. If so, | 
 | 663 |   // we can remove them. | 
 | 664 |   for (size_t i = 0, e = BranchFixups.size(); i != e; ++i) { | 
 | 665 |     llvm::BasicBlock *Dest = BranchFixups[i]->getSuccessor(0); | 
 | 666 |     BlockScopeMap::iterator I = BlockScopes.find(Dest); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 667 |  | 
| Anders Carlsson | ad9d00e | 2009-02-08 22:45:15 +0000 | [diff] [blame] | 668 |     if (I == BlockScopes.end()) | 
 | 669 |       continue; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 670 |  | 
| Anders Carlsson | ad9d00e | 2009-02-08 22:45:15 +0000 | [diff] [blame] | 671 |     assert(I->second <= CleanupEntries.size() && "Invalid branch fixup!"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 672 |  | 
| Anders Carlsson | ad9d00e | 2009-02-08 22:45:15 +0000 | [diff] [blame] | 673 |     if (I->second == CleanupEntries.size()) { | 
 | 674 |       // We don't need to do this branch fixup. | 
 | 675 |       BranchFixups[i] = BranchFixups.back(); | 
 | 676 |       BranchFixups.pop_back(); | 
 | 677 |       i--; | 
 | 678 |       e--; | 
 | 679 |       continue; | 
| Anders Carlsson | 1093c2c | 2009-02-08 01:23:05 +0000 | [diff] [blame] | 680 |     } | 
 | 681 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 682 |  | 
| Fariborz Jahanian | 7799621 | 2009-11-04 17:57:40 +0000 | [diff] [blame] | 683 |   llvm::BasicBlock *SwitchBlock = CE.CleanupExitBlock; | 
| Anders Carlsson | bb66f9f | 2009-02-08 07:46:24 +0000 | [diff] [blame] | 684 |   llvm::BasicBlock *EndBlock = 0; | 
| Anders Carlsson | 1093c2c | 2009-02-08 01:23:05 +0000 | [diff] [blame] | 685 |   if (!BranchFixups.empty()) { | 
| Fariborz Jahanian | 7799621 | 2009-11-04 17:57:40 +0000 | [diff] [blame] | 686 |     if (!SwitchBlock) | 
 | 687 |       SwitchBlock = createBasicBlock("cleanup.switch"); | 
| Anders Carlsson | bb66f9f | 2009-02-08 07:46:24 +0000 | [diff] [blame] | 688 |     EndBlock = createBasicBlock("cleanup.end"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 689 |  | 
| Anders Carlsson | bb66f9f | 2009-02-08 07:46:24 +0000 | [diff] [blame] | 690 |     llvm::BasicBlock *CurBB = Builder.GetInsertBlock(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 691 |  | 
| Anders Carlsson | bb66f9f | 2009-02-08 07:46:24 +0000 | [diff] [blame] | 692 |     Builder.SetInsertPoint(SwitchBlock); | 
 | 693 |  | 
| Mike Stump | 9953383 | 2009-12-02 07:41:41 +0000 | [diff] [blame] | 694 |     llvm::Value *DestCodePtr | 
 | 695 |       = CreateTempAlloca(llvm::Type::getInt32Ty(VMContext), | 
 | 696 |                          "cleanup.dst"); | 
| Anders Carlsson | 1093c2c | 2009-02-08 01:23:05 +0000 | [diff] [blame] | 697 |     llvm::Value *DestCode = Builder.CreateLoad(DestCodePtr, "tmp"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 698 |  | 
| Anders Carlsson | 1093c2c | 2009-02-08 01:23:05 +0000 | [diff] [blame] | 699 |     // Create a switch instruction to determine where to jump next. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 700 |     llvm::SwitchInst *SI = Builder.CreateSwitch(DestCode, EndBlock, | 
| Anders Carlsson | 1093c2c | 2009-02-08 01:23:05 +0000 | [diff] [blame] | 701 |                                                 BranchFixups.size()); | 
| Anders Carlsson | bb66f9f | 2009-02-08 07:46:24 +0000 | [diff] [blame] | 702 |  | 
| Anders Carlsson | 46831a9 | 2009-02-08 22:13:37 +0000 | [diff] [blame] | 703 |     // Restore the current basic block (if any) | 
| Anders Carlsson | 0ae7b2b | 2009-03-17 05:53:35 +0000 | [diff] [blame] | 704 |     if (CurBB) { | 
| Anders Carlsson | 46831a9 | 2009-02-08 22:13:37 +0000 | [diff] [blame] | 705 |       Builder.SetInsertPoint(CurBB); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 706 |  | 
| Anders Carlsson | 0ae7b2b | 2009-03-17 05:53:35 +0000 | [diff] [blame] | 707 |       // If we had a current basic block, we also need to emit an instruction | 
 | 708 |       // to initialize the cleanup destination. | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 709 |       Builder.CreateStore(llvm::Constant::getNullValue(llvm::Type::getInt32Ty(VMContext)), | 
| Anders Carlsson | 0ae7b2b | 2009-03-17 05:53:35 +0000 | [diff] [blame] | 710 |                           DestCodePtr); | 
 | 711 |     } else | 
| Anders Carlsson | 46831a9 | 2009-02-08 22:13:37 +0000 | [diff] [blame] | 712 |       Builder.ClearInsertionPoint(); | 
| Anders Carlsson | bb66f9f | 2009-02-08 07:46:24 +0000 | [diff] [blame] | 713 |  | 
| Anders Carlsson | 1093c2c | 2009-02-08 01:23:05 +0000 | [diff] [blame] | 714 |     for (size_t i = 0, e = BranchFixups.size(); i != e; ++i) { | 
 | 715 |       llvm::BranchInst *BI = BranchFixups[i]; | 
 | 716 |       llvm::BasicBlock *Dest = BI->getSuccessor(0); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 717 |  | 
| Anders Carlsson | 1093c2c | 2009-02-08 01:23:05 +0000 | [diff] [blame] | 718 |       // Fixup the branch instruction to point to the cleanup block. | 
| Fariborz Jahanian | 7799621 | 2009-11-04 17:57:40 +0000 | [diff] [blame] | 719 |       BI->setSuccessor(0, CleanupEntryBlock); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 720 |  | 
| Anders Carlsson | 1093c2c | 2009-02-08 01:23:05 +0000 | [diff] [blame] | 721 |       if (CleanupEntries.empty()) { | 
| Anders Carlsson | cc89920 | 2009-02-08 22:46:50 +0000 | [diff] [blame] | 722 |         llvm::ConstantInt *ID; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 723 |  | 
| Anders Carlsson | cc89920 | 2009-02-08 22:46:50 +0000 | [diff] [blame] | 724 |         // Check if we already have a destination for this block. | 
 | 725 |         if (Dest == SI->getDefaultDest()) | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 726 |           ID = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0); | 
| Anders Carlsson | cc89920 | 2009-02-08 22:46:50 +0000 | [diff] [blame] | 727 |         else { | 
 | 728 |           ID = SI->findCaseDest(Dest); | 
 | 729 |           if (!ID) { | 
 | 730 |             // No code found, get a new unique one by using the number of | 
 | 731 |             // switch successors. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 732 |             ID = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), | 
| Anders Carlsson | cc89920 | 2009-02-08 22:46:50 +0000 | [diff] [blame] | 733 |                                         SI->getNumSuccessors()); | 
 | 734 |             SI->addCase(ID, Dest); | 
 | 735 |           } | 
 | 736 |         } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 737 |  | 
| Anders Carlsson | cc89920 | 2009-02-08 22:46:50 +0000 | [diff] [blame] | 738 |         // Store the jump destination before the branch instruction. | 
 | 739 |         new llvm::StoreInst(ID, DestCodePtr, BI); | 
| Anders Carlsson | 1093c2c | 2009-02-08 01:23:05 +0000 | [diff] [blame] | 740 |       } else { | 
 | 741 |         // We need to jump through another cleanup block. Create a pad block | 
| Mike Stump | 9953383 | 2009-12-02 07:41:41 +0000 | [diff] [blame] | 742 |         // with a branch instruction that jumps to the final destination and add | 
 | 743 |         // it as a branch fixup to the current cleanup scope. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 744 |  | 
| Anders Carlsson | 1093c2c | 2009-02-08 01:23:05 +0000 | [diff] [blame] | 745 |         // Create the pad block. | 
 | 746 |         llvm::BasicBlock *CleanupPad = createBasicBlock("cleanup.pad", CurFn); | 
| Anders Carlsson | cc89920 | 2009-02-08 22:46:50 +0000 | [diff] [blame] | 747 |  | 
 | 748 |         // Create a unique case ID. | 
| Mike Stump | 9953383 | 2009-12-02 07:41:41 +0000 | [diff] [blame] | 749 |         llvm::ConstantInt *ID | 
 | 750 |           = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), | 
 | 751 |                                    SI->getNumSuccessors()); | 
| Anders Carlsson | cc89920 | 2009-02-08 22:46:50 +0000 | [diff] [blame] | 752 |  | 
 | 753 |         // Store the jump destination before the branch instruction. | 
 | 754 |         new llvm::StoreInst(ID, DestCodePtr, BI); | 
 | 755 |  | 
| Anders Carlsson | 1093c2c | 2009-02-08 01:23:05 +0000 | [diff] [blame] | 756 |         // Add it as the destination. | 
| Anders Carlsson | cc89920 | 2009-02-08 22:46:50 +0000 | [diff] [blame] | 757 |         SI->addCase(ID, CleanupPad); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 758 |  | 
| Anders Carlsson | 1093c2c | 2009-02-08 01:23:05 +0000 | [diff] [blame] | 759 |         // Create the branch to the final destination. | 
 | 760 |         llvm::BranchInst *BI = llvm::BranchInst::Create(Dest); | 
 | 761 |         CleanupPad->getInstList().push_back(BI); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 762 |  | 
| Anders Carlsson | 1093c2c | 2009-02-08 01:23:05 +0000 | [diff] [blame] | 763 |         // And add it as a branch fixup. | 
 | 764 |         CleanupEntries.back().BranchFixups.push_back(BI); | 
 | 765 |       } | 
 | 766 |     } | 
 | 767 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 768 |  | 
| Anders Carlsson | bd6fa3d | 2009-02-08 00:16:35 +0000 | [diff] [blame] | 769 |   // Remove all blocks from the block scope map. | 
 | 770 |   for (size_t i = 0, e = Blocks.size(); i != e; ++i) { | 
 | 771 |     assert(BlockScopes.count(Blocks[i]) && | 
 | 772 |            "Did not find block in scope map!"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 773 |  | 
| Anders Carlsson | bd6fa3d | 2009-02-08 00:16:35 +0000 | [diff] [blame] | 774 |     BlockScopes.erase(Blocks[i]); | 
 | 775 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 776 |  | 
| Mike Stump | 9953383 | 2009-12-02 07:41:41 +0000 | [diff] [blame] | 777 |   return CleanupBlockInfo(CleanupEntryBlock, SwitchBlock, EndBlock, EHOnly); | 
| Anders Carlsson | d66a9f9 | 2009-02-08 03:55:35 +0000 | [diff] [blame] | 778 | } | 
 | 779 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 780 | void CodeGenFunction::EmitCleanupBlock() { | 
| Anders Carlsson | bb66f9f | 2009-02-08 07:46:24 +0000 | [diff] [blame] | 781 |   CleanupBlockInfo Info = PopCleanupBlock(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 782 |  | 
| Mike Stump | 9953383 | 2009-12-02 07:41:41 +0000 | [diff] [blame] | 783 |   if (Info.EHOnly) { | 
 | 784 |     // FIXME: Add this to the exceptional edge | 
 | 785 |     if (Info.CleanupBlock->getNumUses() == 0) | 
 | 786 |       delete Info.CleanupBlock; | 
 | 787 |     return; | 
 | 788 |   } | 
 | 789 |  | 
| Anders Carlsson | eb6437a | 2009-05-31 00:33:20 +0000 | [diff] [blame] | 790 |   llvm::BasicBlock *CurBB = Builder.GetInsertBlock(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 791 |   if (CurBB && !CurBB->getTerminator() && | 
| Anders Carlsson | eb6437a | 2009-05-31 00:33:20 +0000 | [diff] [blame] | 792 |       Info.CleanupBlock->getNumUses() == 0) { | 
 | 793 |     CurBB->getInstList().splice(CurBB->end(), Info.CleanupBlock->getInstList()); | 
 | 794 |     delete Info.CleanupBlock; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 795 |   } else | 
| Anders Carlsson | eb6437a | 2009-05-31 00:33:20 +0000 | [diff] [blame] | 796 |     EmitBlock(Info.CleanupBlock); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 797 |  | 
| Anders Carlsson | bb66f9f | 2009-02-08 07:46:24 +0000 | [diff] [blame] | 798 |   if (Info.SwitchBlock) | 
 | 799 |     EmitBlock(Info.SwitchBlock); | 
 | 800 |   if (Info.EndBlock) | 
 | 801 |     EmitBlock(Info.EndBlock); | 
| Anders Carlsson | d66a9f9 | 2009-02-08 03:55:35 +0000 | [diff] [blame] | 802 | } | 
 | 803 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 804 | void CodeGenFunction::AddBranchFixup(llvm::BranchInst *BI) { | 
 | 805 |   assert(!CleanupEntries.empty() && | 
| Anders Carlsson | 87eaf17 | 2009-02-08 00:50:42 +0000 | [diff] [blame] | 806 |          "Trying to add branch fixup without cleanup block!"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 807 |  | 
| Mike Stump | f5408fe | 2009-05-16 07:57:57 +0000 | [diff] [blame] | 808 |   // FIXME: We could be more clever here and check if there's already a branch | 
 | 809 |   // fixup for this destination and recycle it. | 
| Anders Carlsson | 87eaf17 | 2009-02-08 00:50:42 +0000 | [diff] [blame] | 810 |   CleanupEntries.back().BranchFixups.push_back(BI); | 
 | 811 | } | 
 | 812 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 813 | void CodeGenFunction::EmitBranchThroughCleanup(llvm::BasicBlock *Dest) { | 
| Anders Carlsson | 46831a9 | 2009-02-08 22:13:37 +0000 | [diff] [blame] | 814 |   if (!HaveInsertPoint()) | 
 | 815 |     return; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 816 |  | 
| Anders Carlsson | 87eaf17 | 2009-02-08 00:50:42 +0000 | [diff] [blame] | 817 |   llvm::BranchInst* BI = Builder.CreateBr(Dest); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 818 |  | 
| Anders Carlsson | 46831a9 | 2009-02-08 22:13:37 +0000 | [diff] [blame] | 819 |   Builder.ClearInsertionPoint(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 820 |  | 
| Anders Carlsson | 87eaf17 | 2009-02-08 00:50:42 +0000 | [diff] [blame] | 821 |   // The stack is empty, no need to do any cleanup. | 
 | 822 |   if (CleanupEntries.empty()) | 
 | 823 |     return; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 824 |  | 
| Anders Carlsson | 87eaf17 | 2009-02-08 00:50:42 +0000 | [diff] [blame] | 825 |   if (!Dest->getParent()) { | 
 | 826 |     // We are trying to branch to a block that hasn't been inserted yet. | 
 | 827 |     AddBranchFixup(BI); | 
 | 828 |     return; | 
 | 829 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 830 |  | 
| Anders Carlsson | 87eaf17 | 2009-02-08 00:50:42 +0000 | [diff] [blame] | 831 |   BlockScopeMap::iterator I = BlockScopes.find(Dest); | 
 | 832 |   if (I == BlockScopes.end()) { | 
 | 833 |     // We are trying to jump to a block that is outside of any cleanup scope. | 
 | 834 |     AddBranchFixup(BI); | 
 | 835 |     return; | 
 | 836 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 837 |  | 
| Anders Carlsson | 87eaf17 | 2009-02-08 00:50:42 +0000 | [diff] [blame] | 838 |   assert(I->second < CleanupEntries.size() && | 
 | 839 |          "Trying to branch into cleanup region"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 840 |  | 
| Anders Carlsson | 87eaf17 | 2009-02-08 00:50:42 +0000 | [diff] [blame] | 841 |   if (I->second == CleanupEntries.size() - 1) { | 
 | 842 |     // We have a branch to a block in the same scope. | 
 | 843 |     return; | 
 | 844 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 845 |  | 
| Anders Carlsson | 87eaf17 | 2009-02-08 00:50:42 +0000 | [diff] [blame] | 846 |   AddBranchFixup(BI); | 
 | 847 | } |