| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1 | //===--- CGStmt.cpp - Emit LLVM Code from Statements ----------------------===// | 
 | 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 Stmt nodes as LLVM code. | 
 | 11 | // | 
 | 12 | //===----------------------------------------------------------------------===// | 
 | 13 |  | 
| Sanjiv Gupta | e8b9f5b | 2008-05-08 08:54:20 +0000 | [diff] [blame] | 14 | #include "CGDebugInfo.h" | 
 | 15 | #include "CodeGenModule.h" | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 16 | #include "CodeGenFunction.h" | 
| Daniel Dunbar | de7fb84 | 2008-08-11 05:00:27 +0000 | [diff] [blame^] | 17 | #include "clang/AST/ASTContext.h" | 
 | 18 | #include "clang/AST/StmtVisitor.h" | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 19 | #include "clang/Basic/TargetInfo.h" | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 20 | #include "llvm/Constants.h" | 
 | 21 | #include "llvm/DerivedTypes.h" | 
 | 22 | #include "llvm/Function.h" | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 23 | #include "llvm/InlineAsm.h" | 
 | 24 | #include "llvm/ADT/StringExtras.h" | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 25 | using namespace clang; | 
 | 26 | using namespace CodeGen; | 
 | 27 |  | 
 | 28 | //===----------------------------------------------------------------------===// | 
 | 29 | //                              Statement Emission | 
 | 30 | //===----------------------------------------------------------------------===// | 
 | 31 |  | 
 | 32 | void CodeGenFunction::EmitStmt(const Stmt *S) { | 
 | 33 |   assert(S && "Null statement?"); | 
 | 34 |    | 
| Sanjiv Gupta | e8b9f5b | 2008-05-08 08:54:20 +0000 | [diff] [blame] | 35 |   // Generate stoppoints if we are emitting debug info. | 
 | 36 |   // Beginning of a Compound Statement (e.g. an opening '{') does not produce  | 
 | 37 |   // executable code. So do not generate a stoppoint for that. | 
 | 38 |   CGDebugInfo *DI = CGM.getDebugInfo(); | 
 | 39 |   if (DI && S->getStmtClass() != Stmt::CompoundStmtClass) { | 
 | 40 |     if (S->getLocStart().isValid()) { | 
 | 41 |         DI->setLocation(S->getLocStart()); | 
 | 42 |     } | 
 | 43 |  | 
 | 44 |     DI->EmitStopPoint(CurFn, Builder); | 
 | 45 |   } | 
 | 46 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 47 |   switch (S->getStmtClass()) { | 
 | 48 |   default: | 
| Chris Lattner | 1e4d21e | 2007-08-26 22:58:05 +0000 | [diff] [blame] | 49 |     // Must be an expression in a stmt context.  Emit the value (to get | 
 | 50 |     // side-effects) and ignore the result. | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 51 |     if (const Expr *E = dyn_cast<Expr>(S)) { | 
| Chris Lattner | 1e4d21e | 2007-08-26 22:58:05 +0000 | [diff] [blame] | 52 |       if (!hasAggregateLLVMType(E->getType())) | 
 | 53 |         EmitScalarExpr(E); | 
| Chris Lattner | 9b2dc28 | 2008-04-04 16:54:41 +0000 | [diff] [blame] | 54 |       else if (E->getType()->isAnyComplexType()) | 
| Chris Lattner | 1e4d21e | 2007-08-26 22:58:05 +0000 | [diff] [blame] | 55 |         EmitComplexExpr(E); | 
 | 56 |       else | 
 | 57 |         EmitAggExpr(E, 0, false); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 58 |     } else { | 
| Chris Lattner | dc4d280 | 2007-12-02 01:49:16 +0000 | [diff] [blame] | 59 |       WarnUnsupported(S, "statement"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 60 |     } | 
 | 61 |     break; | 
 | 62 |   case Stmt::NullStmtClass: break; | 
 | 63 |   case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break; | 
 | 64 |   case Stmt::LabelStmtClass:    EmitLabelStmt(cast<LabelStmt>(*S));       break; | 
 | 65 |   case Stmt::GotoStmtClass:     EmitGotoStmt(cast<GotoStmt>(*S));         break; | 
| Daniel Dunbar | 0ffb125 | 2008-08-04 16:51:22 +0000 | [diff] [blame] | 66 |   case Stmt::IndirectGotoStmtClass:   | 
 | 67 |     EmitIndirectGotoStmt(cast<IndirectGotoStmt>(*S)); break; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 68 |  | 
 | 69 |   case Stmt::IfStmtClass:       EmitIfStmt(cast<IfStmt>(*S));             break; | 
 | 70 |   case Stmt::WhileStmtClass:    EmitWhileStmt(cast<WhileStmt>(*S));       break; | 
 | 71 |   case Stmt::DoStmtClass:       EmitDoStmt(cast<DoStmt>(*S));             break; | 
 | 72 |   case Stmt::ForStmtClass:      EmitForStmt(cast<ForStmt>(*S));           break; | 
 | 73 |      | 
 | 74 |   case Stmt::ReturnStmtClass:   EmitReturnStmt(cast<ReturnStmt>(*S));     break; | 
 | 75 |   case Stmt::DeclStmtClass:     EmitDeclStmt(cast<DeclStmt>(*S));         break; | 
| Chris Lattner | da13870 | 2007-07-16 21:28:45 +0000 | [diff] [blame] | 76 |        | 
 | 77 |   case Stmt::BreakStmtClass:    EmitBreakStmt();                          break; | 
 | 78 |   case Stmt::ContinueStmtClass: EmitContinueStmt();                       break; | 
| Devang Patel | 51b09f2 | 2007-10-04 23:45:31 +0000 | [diff] [blame] | 79 |   case Stmt::SwitchStmtClass:   EmitSwitchStmt(cast<SwitchStmt>(*S));     break; | 
 | 80 |   case Stmt::DefaultStmtClass:  EmitDefaultStmt(cast<DefaultStmt>(*S));   break; | 
 | 81 |   case Stmt::CaseStmtClass:     EmitCaseStmt(cast<CaseStmt>(*S));         break; | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 82 |   case Stmt::AsmStmtClass:      EmitAsmStmt(cast<AsmStmt>(*S));           break; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 83 |   } | 
 | 84 | } | 
 | 85 |  | 
| Chris Lattner | 3379320 | 2007-08-31 22:09:40 +0000 | [diff] [blame] | 86 | /// EmitCompoundStmt - Emit a compound statement {..} node.  If GetLast is true, | 
 | 87 | /// this captures the expression result of the last sub-statement and returns it | 
 | 88 | /// (for use by the statement expression extension). | 
| Chris Lattner | 9b65551 | 2007-08-31 22:49:20 +0000 | [diff] [blame] | 89 | RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast, | 
 | 90 |                                          llvm::Value *AggLoc, bool isAggVol) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 91 |   // FIXME: handle vla's etc. | 
| Sanjiv Gupta | 1c6a38b | 2008-05-25 05:15:42 +0000 | [diff] [blame] | 92 |   CGDebugInfo *DI = CGM.getDebugInfo(); | 
 | 93 |   if (DI) { | 
| Chris Lattner | 345f720 | 2008-07-26 20:15:14 +0000 | [diff] [blame] | 94 |     if (S.getLBracLoc().isValid()) | 
| Sanjiv Gupta | 1c6a38b | 2008-05-25 05:15:42 +0000 | [diff] [blame] | 95 |       DI->setLocation(S.getLBracLoc()); | 
| Sanjiv Gupta | 1c6a38b | 2008-05-25 05:15:42 +0000 | [diff] [blame] | 96 |     DI->EmitRegionStart(CurFn, Builder); | 
 | 97 |   } | 
 | 98 |  | 
| Chris Lattner | 3379320 | 2007-08-31 22:09:40 +0000 | [diff] [blame] | 99 |   for (CompoundStmt::const_body_iterator I = S.body_begin(), | 
 | 100 |        E = S.body_end()-GetLast; I != E; ++I) | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 101 |     EmitStmt(*I); | 
| Sanjiv Gupta | e8b9f5b | 2008-05-08 08:54:20 +0000 | [diff] [blame] | 102 |  | 
| Sanjiv Gupta | 1c6a38b | 2008-05-25 05:15:42 +0000 | [diff] [blame] | 103 |   if (DI) { | 
| Chris Lattner | 345f720 | 2008-07-26 20:15:14 +0000 | [diff] [blame] | 104 |     if (S.getRBracLoc().isValid()) | 
| Sanjiv Gupta | 1c6a38b | 2008-05-25 05:15:42 +0000 | [diff] [blame] | 105 |       DI->setLocation(S.getRBracLoc()); | 
| Sanjiv Gupta | 1c6a38b | 2008-05-25 05:15:42 +0000 | [diff] [blame] | 106 |     DI->EmitRegionEnd(CurFn, Builder); | 
 | 107 |   } | 
 | 108 |  | 
| Chris Lattner | 3379320 | 2007-08-31 22:09:40 +0000 | [diff] [blame] | 109 |   if (!GetLast) | 
 | 110 |     return RValue::get(0); | 
| Chris Lattner | 9b65551 | 2007-08-31 22:49:20 +0000 | [diff] [blame] | 111 |    | 
| Chris Lattner | 91d723d | 2008-07-26 20:23:23 +0000 | [diff] [blame] | 112 |   // We have to special case labels here.  They are statements, but when put at | 
 | 113 |   // the end of a statement expression, they yield the value of their | 
 | 114 |   // subexpression.  Handle this by walking through all labels we encounter, | 
 | 115 |   // emitting them before we evaluate the subexpr. | 
 | 116 |   const Stmt *LastStmt = S.body_back(); | 
 | 117 |   while (const LabelStmt *LS = dyn_cast<LabelStmt>(LastStmt)) { | 
 | 118 |     EmitLabel(*LS); | 
 | 119 |     LastStmt = LS->getSubStmt(); | 
 | 120 |   } | 
 | 121 |    | 
 | 122 |   return EmitAnyExpr(cast<Expr>(LastStmt), AggLoc); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 123 | } | 
 | 124 |  | 
 | 125 | void CodeGenFunction::EmitBlock(llvm::BasicBlock *BB) { | 
 | 126 |   // Emit a branch from this block to the next one if this was a real block.  If | 
 | 127 |   // this was just a fall-through block after a terminator, don't emit it. | 
 | 128 |   llvm::BasicBlock *LastBB = Builder.GetInsertBlock(); | 
 | 129 |    | 
 | 130 |   if (LastBB->getTerminator()) { | 
 | 131 |     // If the previous block is already terminated, don't touch it. | 
| Daniel Dunbar | 16f2357 | 2008-07-25 01:11:38 +0000 | [diff] [blame] | 132 |   } else if (LastBB->empty() && isDummyBlock(LastBB)) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 133 |     // If the last block was an empty placeholder, remove it now. | 
 | 134 |     // TODO: cache and reuse these. | 
| Daniel Dunbar | 16f2357 | 2008-07-25 01:11:38 +0000 | [diff] [blame] | 135 |     LastBB->eraseFromParent(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 136 |   } else { | 
 | 137 |     // Otherwise, create a fall-through branch. | 
 | 138 |     Builder.CreateBr(BB); | 
 | 139 |   } | 
 | 140 |   CurFn->getBasicBlockList().push_back(BB); | 
 | 141 |   Builder.SetInsertPoint(BB); | 
 | 142 | } | 
 | 143 |  | 
| Chris Lattner | 91d723d | 2008-07-26 20:23:23 +0000 | [diff] [blame] | 144 | void CodeGenFunction::EmitLabel(const LabelStmt &S) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 145 |   llvm::BasicBlock *NextBB = getBasicBlockForLabel(&S); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 146 |   EmitBlock(NextBB); | 
| Chris Lattner | 91d723d | 2008-07-26 20:23:23 +0000 | [diff] [blame] | 147 | } | 
 | 148 |  | 
 | 149 |  | 
 | 150 | void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) { | 
 | 151 |   EmitLabel(S); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 152 |   EmitStmt(S.getSubStmt()); | 
 | 153 | } | 
 | 154 |  | 
 | 155 | void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) { | 
 | 156 |   Builder.CreateBr(getBasicBlockForLabel(S.getLabel())); | 
 | 157 |    | 
 | 158 |   // Emit a block after the branch so that dead code after a goto has some place | 
 | 159 |   // to go. | 
| Gabor Greif | 984d0b4 | 2008-04-06 20:42:52 +0000 | [diff] [blame] | 160 |   Builder.SetInsertPoint(llvm::BasicBlock::Create("", CurFn)); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 161 | } | 
 | 162 |  | 
| Daniel Dunbar | 0ffb125 | 2008-08-04 16:51:22 +0000 | [diff] [blame] | 163 | void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) { | 
 | 164 |   // Emit initial switch which will be patched up later by | 
 | 165 |   // EmitIndirectSwitches(). We need a default dest, so we use the | 
 | 166 |   // current BB, but this is overwritten. | 
 | 167 |   llvm::Value *V = Builder.CreatePtrToInt(EmitScalarExpr(S.getTarget()), | 
 | 168 |                                           llvm::Type::Int32Ty,  | 
 | 169 |                                           "addr"); | 
 | 170 |   llvm::SwitchInst *I = Builder.CreateSwitch(V, Builder.GetInsertBlock()); | 
 | 171 |   IndirectSwitches.push_back(I); | 
 | 172 |  | 
 | 173 |   // Emit a block after the branch so that dead code after a goto has some place | 
 | 174 |   // to go. | 
 | 175 |   Builder.SetInsertPoint(llvm::BasicBlock::Create("", CurFn)); | 
 | 176 | } | 
 | 177 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 178 | void CodeGenFunction::EmitIfStmt(const IfStmt &S) { | 
| Daniel Dunbar | 0ffb125 | 2008-08-04 16:51:22 +0000 | [diff] [blame] | 179 |   // FIXME: It would probably be nice for us to skip emission of if | 
 | 180 |   // (0) code here. | 
 | 181 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 182 |   // C99 6.8.4.1: The first substatement is executed if the expression compares | 
 | 183 |   // unequal to 0.  The condition must be a scalar type. | 
 | 184 |   llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond()); | 
 | 185 |    | 
| Gabor Greif | 984d0b4 | 2008-04-06 20:42:52 +0000 | [diff] [blame] | 186 |   llvm::BasicBlock *ContBlock = llvm::BasicBlock::Create("ifend"); | 
 | 187 |   llvm::BasicBlock *ThenBlock = llvm::BasicBlock::Create("ifthen"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 188 |   llvm::BasicBlock *ElseBlock = ContBlock; | 
 | 189 |    | 
 | 190 |   if (S.getElse()) | 
| Gabor Greif | 984d0b4 | 2008-04-06 20:42:52 +0000 | [diff] [blame] | 191 |     ElseBlock = llvm::BasicBlock::Create("ifelse"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 192 |    | 
 | 193 |   // Insert the conditional branch. | 
 | 194 |   Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock); | 
 | 195 |    | 
 | 196 |   // Emit the 'then' code. | 
 | 197 |   EmitBlock(ThenBlock); | 
 | 198 |   EmitStmt(S.getThen()); | 
| Devang Patel | d9363c3 | 2007-09-28 21:49:18 +0000 | [diff] [blame] | 199 |   llvm::BasicBlock *BB = Builder.GetInsertBlock(); | 
 | 200 |   if (isDummyBlock(BB)) { | 
 | 201 |     BB->eraseFromParent(); | 
 | 202 |     Builder.SetInsertPoint(ThenBlock); | 
| Chris Lattner | 345f720 | 2008-07-26 20:15:14 +0000 | [diff] [blame] | 203 |   } else { | 
| Devang Patel | d9363c3 | 2007-09-28 21:49:18 +0000 | [diff] [blame] | 204 |     Builder.CreateBr(ContBlock); | 
| Chris Lattner | 345f720 | 2008-07-26 20:15:14 +0000 | [diff] [blame] | 205 |   } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 206 |    | 
 | 207 |   // Emit the 'else' code if present. | 
 | 208 |   if (const Stmt *Else = S.getElse()) { | 
 | 209 |     EmitBlock(ElseBlock); | 
 | 210 |     EmitStmt(Else); | 
| Devang Patel | d9363c3 | 2007-09-28 21:49:18 +0000 | [diff] [blame] | 211 |     llvm::BasicBlock *BB = Builder.GetInsertBlock(); | 
 | 212 |     if (isDummyBlock(BB)) { | 
 | 213 |       BB->eraseFromParent(); | 
 | 214 |       Builder.SetInsertPoint(ElseBlock); | 
| Chris Lattner | 345f720 | 2008-07-26 20:15:14 +0000 | [diff] [blame] | 215 |     } else { | 
| Devang Patel | d9363c3 | 2007-09-28 21:49:18 +0000 | [diff] [blame] | 216 |       Builder.CreateBr(ContBlock); | 
| Chris Lattner | 345f720 | 2008-07-26 20:15:14 +0000 | [diff] [blame] | 217 |     } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 218 |   } | 
 | 219 |    | 
 | 220 |   // Emit the continuation block for code after the if. | 
 | 221 |   EmitBlock(ContBlock); | 
 | 222 | } | 
 | 223 |  | 
 | 224 | void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 225 |   // Emit the header for the loop, insert it, which will create an uncond br to | 
 | 226 |   // it. | 
| Gabor Greif | 984d0b4 | 2008-04-06 20:42:52 +0000 | [diff] [blame] | 227 |   llvm::BasicBlock *LoopHeader = llvm::BasicBlock::Create("whilecond"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 228 |   EmitBlock(LoopHeader); | 
 | 229 |    | 
 | 230 |   // Evaluate the conditional in the while header.  C99 6.8.5.1: The evaluation | 
 | 231 |   // of the controlling expression takes place before each execution of the loop | 
 | 232 |   // body.  | 
 | 233 |   llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond()); | 
| Devang Patel | 2c30d8f | 2007-10-09 20:51:27 +0000 | [diff] [blame] | 234 |  | 
 | 235 |   // while(1) is common, avoid extra exit blocks.  Be sure | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 236 |   // to correctly handle break/continue though. | 
| Devang Patel | 2c30d8f | 2007-10-09 20:51:27 +0000 | [diff] [blame] | 237 |   bool EmitBoolCondBranch = true; | 
 | 238 |   if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal))  | 
 | 239 |     if (C->isOne()) | 
 | 240 |       EmitBoolCondBranch = false; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 241 |    | 
 | 242 |   // Create an exit block for when the condition fails, create a block for the | 
 | 243 |   // body of the loop. | 
| Gabor Greif | 984d0b4 | 2008-04-06 20:42:52 +0000 | [diff] [blame] | 244 |   llvm::BasicBlock *ExitBlock = llvm::BasicBlock::Create("whileexit"); | 
 | 245 |   llvm::BasicBlock *LoopBody  = llvm::BasicBlock::Create("whilebody"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 246 |    | 
 | 247 |   // As long as the condition is true, go to the loop body. | 
| Devang Patel | 2c30d8f | 2007-10-09 20:51:27 +0000 | [diff] [blame] | 248 |   if (EmitBoolCondBranch) | 
 | 249 |     Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock); | 
| Chris Lattner | da13870 | 2007-07-16 21:28:45 +0000 | [diff] [blame] | 250 |  | 
 | 251 |   // Store the blocks to use for break and continue. | 
 | 252 |   BreakContinueStack.push_back(BreakContinue(ExitBlock, LoopHeader)); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 253 |    | 
 | 254 |   // Emit the loop body. | 
 | 255 |   EmitBlock(LoopBody); | 
 | 256 |   EmitStmt(S.getBody()); | 
| Chris Lattner | da13870 | 2007-07-16 21:28:45 +0000 | [diff] [blame] | 257 |  | 
 | 258 |   BreakContinueStack.pop_back(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 259 |    | 
 | 260 |   // Cycle to the condition. | 
 | 261 |   Builder.CreateBr(LoopHeader); | 
 | 262 |    | 
 | 263 |   // Emit the exit block. | 
 | 264 |   EmitBlock(ExitBlock); | 
| Devang Patel | 2c30d8f | 2007-10-09 20:51:27 +0000 | [diff] [blame] | 265 |  | 
 | 266 |   // If LoopHeader is a simple forwarding block then eliminate it. | 
 | 267 |   if (!EmitBoolCondBranch  | 
 | 268 |       && &LoopHeader->front() == LoopHeader->getTerminator()) { | 
 | 269 |     LoopHeader->replaceAllUsesWith(LoopBody); | 
 | 270 |     LoopHeader->getTerminator()->eraseFromParent(); | 
 | 271 |     LoopHeader->eraseFromParent(); | 
 | 272 |   } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 273 | } | 
 | 274 |  | 
 | 275 | void CodeGenFunction::EmitDoStmt(const DoStmt &S) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 276 |   // Emit the body for the loop, insert it, which will create an uncond br to | 
 | 277 |   // it. | 
| Gabor Greif | 984d0b4 | 2008-04-06 20:42:52 +0000 | [diff] [blame] | 278 |   llvm::BasicBlock *LoopBody = llvm::BasicBlock::Create("dobody"); | 
 | 279 |   llvm::BasicBlock *AfterDo = llvm::BasicBlock::Create("afterdo"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 280 |   EmitBlock(LoopBody); | 
| Chris Lattner | da13870 | 2007-07-16 21:28:45 +0000 | [diff] [blame] | 281 |  | 
| Gabor Greif | 984d0b4 | 2008-04-06 20:42:52 +0000 | [diff] [blame] | 282 |   llvm::BasicBlock *DoCond = llvm::BasicBlock::Create("docond"); | 
| Chris Lattner | da13870 | 2007-07-16 21:28:45 +0000 | [diff] [blame] | 283 |    | 
 | 284 |   // Store the blocks to use for break and continue. | 
 | 285 |   BreakContinueStack.push_back(BreakContinue(AfterDo, DoCond)); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 286 |    | 
 | 287 |   // Emit the body of the loop into the block. | 
 | 288 |   EmitStmt(S.getBody()); | 
 | 289 |    | 
| Chris Lattner | da13870 | 2007-07-16 21:28:45 +0000 | [diff] [blame] | 290 |   BreakContinueStack.pop_back(); | 
 | 291 |    | 
 | 292 |   EmitBlock(DoCond); | 
 | 293 |    | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 294 |   // C99 6.8.5.2: "The evaluation of the controlling expression takes place | 
 | 295 |   // after each execution of the loop body." | 
 | 296 |    | 
 | 297 |   // Evaluate the conditional in the while header. | 
 | 298 |   // C99 6.8.5p2/p4: The first substatement is executed if the expression | 
 | 299 |   // compares unequal to 0.  The condition must be a scalar type. | 
 | 300 |   llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond()); | 
| Devang Patel | 05f6e6b | 2007-10-09 20:33:39 +0000 | [diff] [blame] | 301 |  | 
 | 302 |   // "do {} while (0)" is common in macros, avoid extra blocks.  Be sure | 
 | 303 |   // to correctly handle break/continue though. | 
 | 304 |   bool EmitBoolCondBranch = true; | 
 | 305 |   if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal))  | 
 | 306 |     if (C->isZero()) | 
 | 307 |       EmitBoolCondBranch = false; | 
 | 308 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 309 |   // As long as the condition is true, iterate the loop. | 
| Devang Patel | 05f6e6b | 2007-10-09 20:33:39 +0000 | [diff] [blame] | 310 |   if (EmitBoolCondBranch) | 
 | 311 |     Builder.CreateCondBr(BoolCondVal, LoopBody, AfterDo); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 312 |    | 
 | 313 |   // Emit the exit block. | 
 | 314 |   EmitBlock(AfterDo); | 
| Devang Patel | 05f6e6b | 2007-10-09 20:33:39 +0000 | [diff] [blame] | 315 |  | 
 | 316 |   // If DoCond is a simple forwarding block then eliminate it. | 
 | 317 |   if (!EmitBoolCondBranch && &DoCond->front() == DoCond->getTerminator()) { | 
 | 318 |     DoCond->replaceAllUsesWith(AfterDo); | 
 | 319 |     DoCond->getTerminator()->eraseFromParent(); | 
 | 320 |     DoCond->eraseFromParent(); | 
 | 321 |   } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 322 | } | 
 | 323 |  | 
 | 324 | void CodeGenFunction::EmitForStmt(const ForStmt &S) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 325 |   // FIXME: What do we do if the increment (f.e.) contains a stmt expression, | 
 | 326 |   // which contains a continue/break? | 
| Chris Lattner | da13870 | 2007-07-16 21:28:45 +0000 | [diff] [blame] | 327 |   // TODO: We could keep track of whether the loop body contains any | 
 | 328 |   // break/continue statements and not create unnecessary blocks (like | 
 | 329 |   // "afterfor" for a condless loop) if it doesn't. | 
 | 330 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 331 |   // Evaluate the first part before the loop. | 
 | 332 |   if (S.getInit()) | 
 | 333 |     EmitStmt(S.getInit()); | 
 | 334 |  | 
 | 335 |   // Start the loop with a block that tests the condition. | 
| Gabor Greif | 984d0b4 | 2008-04-06 20:42:52 +0000 | [diff] [blame] | 336 |   llvm::BasicBlock *CondBlock = llvm::BasicBlock::Create("forcond"); | 
 | 337 |   llvm::BasicBlock *AfterFor = llvm::BasicBlock::Create("afterfor"); | 
| Chris Lattner | da13870 | 2007-07-16 21:28:45 +0000 | [diff] [blame] | 338 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 339 |   EmitBlock(CondBlock); | 
 | 340 |  | 
 | 341 |   // Evaluate the condition if present.  If not, treat it as a non-zero-constant | 
 | 342 |   // according to 6.8.5.3p2, aka, true. | 
 | 343 |   if (S.getCond()) { | 
 | 344 |     // C99 6.8.5p2/p4: The first substatement is executed if the expression | 
 | 345 |     // compares unequal to 0.  The condition must be a scalar type. | 
 | 346 |     llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond()); | 
 | 347 |      | 
 | 348 |     // As long as the condition is true, iterate the loop. | 
| Gabor Greif | 984d0b4 | 2008-04-06 20:42:52 +0000 | [diff] [blame] | 349 |     llvm::BasicBlock *ForBody = llvm::BasicBlock::Create("forbody"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 350 |     Builder.CreateCondBr(BoolCondVal, ForBody, AfterFor); | 
 | 351 |     EmitBlock(ForBody);     | 
 | 352 |   } else { | 
 | 353 |     // Treat it as a non-zero constant.  Don't even create a new block for the | 
 | 354 |     // body, just fall into it. | 
 | 355 |   } | 
 | 356 |  | 
| Chris Lattner | da13870 | 2007-07-16 21:28:45 +0000 | [diff] [blame] | 357 |   // If the for loop doesn't have an increment we can just use the  | 
 | 358 |   // condition as the continue block. | 
 | 359 |   llvm::BasicBlock *ContinueBlock; | 
 | 360 |   if (S.getInc()) | 
| Gabor Greif | 984d0b4 | 2008-04-06 20:42:52 +0000 | [diff] [blame] | 361 |     ContinueBlock = llvm::BasicBlock::Create("forinc"); | 
| Chris Lattner | da13870 | 2007-07-16 21:28:45 +0000 | [diff] [blame] | 362 |   else | 
 | 363 |     ContinueBlock = CondBlock;   | 
 | 364 |    | 
 | 365 |   // Store the blocks to use for break and continue. | 
 | 366 |   BreakContinueStack.push_back(BreakContinue(AfterFor, ContinueBlock)); | 
 | 367 |    | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 368 |   // If the condition is true, execute the body of the for stmt. | 
 | 369 |   EmitStmt(S.getBody()); | 
| Chris Lattner | da13870 | 2007-07-16 21:28:45 +0000 | [diff] [blame] | 370 |  | 
 | 371 |   BreakContinueStack.pop_back(); | 
 | 372 |    | 
 | 373 |   if (S.getInc()) | 
 | 374 |     EmitBlock(ContinueBlock); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 375 |    | 
 | 376 |   // If there is an increment, emit it next. | 
 | 377 |   if (S.getInc()) | 
| Chris Lattner | 883f6a7 | 2007-08-11 00:04:45 +0000 | [diff] [blame] | 378 |     EmitStmt(S.getInc()); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 379 |        | 
 | 380 |   // Finally, branch back up to the condition for the next iteration. | 
 | 381 |   Builder.CreateBr(CondBlock); | 
 | 382 |  | 
| Chris Lattner | da13870 | 2007-07-16 21:28:45 +0000 | [diff] [blame] | 383 |   // Emit the fall-through block. | 
 | 384 |   EmitBlock(AfterFor); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 385 | } | 
 | 386 |  | 
 | 387 | /// EmitReturnStmt - Note that due to GCC extensions, this can have an operand | 
 | 388 | /// if the function returns void, or may be missing one if the function returns | 
 | 389 | /// non-void.  Fun stuff :). | 
 | 390 | void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 391 |   // Emit the result value, even if unused, to evalute the side effects. | 
 | 392 |   const Expr *RV = S.getRetValue(); | 
| Chris Lattner | 4b0029d | 2007-08-26 07:14:44 +0000 | [diff] [blame] | 393 |  | 
| Eli Friedman | 144ac61 | 2008-05-22 01:22:33 +0000 | [diff] [blame] | 394 |   llvm::Value* RetValue = 0; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 395 |   if (FnRetTy->isVoidType()) { | 
| Eli Friedman | 144ac61 | 2008-05-22 01:22:33 +0000 | [diff] [blame] | 396 |     // Make sure not to return anything | 
 | 397 |     if (RV) { | 
 | 398 |       // Evaluate the expression for side effects | 
 | 399 |       EmitAnyExpr(RV); | 
 | 400 |     } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 401 |   } else if (RV == 0) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 402 |     const llvm::Type *RetTy = CurFn->getFunctionType()->getReturnType(); | 
| Eli Friedman | 144ac61 | 2008-05-22 01:22:33 +0000 | [diff] [blame] | 403 |     if (RetTy != llvm::Type::VoidTy) { | 
 | 404 |       // Handle "return;" in a function that returns a value. | 
 | 405 |       RetValue = llvm::UndefValue::get(RetTy); | 
 | 406 |     } | 
| Chris Lattner | 4b0029d | 2007-08-26 07:14:44 +0000 | [diff] [blame] | 407 |   } else if (!hasAggregateLLVMType(RV->getType())) { | 
| Eli Friedman | 144ac61 | 2008-05-22 01:22:33 +0000 | [diff] [blame] | 408 |     RetValue = EmitScalarExpr(RV); | 
| Chris Lattner | 9b2dc28 | 2008-04-04 16:54:41 +0000 | [diff] [blame] | 409 |   } else if (RV->getType()->isAnyComplexType()) { | 
| Chris Lattner | 345f720 | 2008-07-26 20:15:14 +0000 | [diff] [blame] | 410 |     EmitComplexExprIntoAddr(RV, CurFn->arg_begin(), false); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 411 |   } else { | 
| Chris Lattner | 345f720 | 2008-07-26 20:15:14 +0000 | [diff] [blame] | 412 |     EmitAggExpr(RV, CurFn->arg_begin(), false); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 413 |   } | 
| Eli Friedman | 144ac61 | 2008-05-22 01:22:33 +0000 | [diff] [blame] | 414 |  | 
 | 415 |   if (RetValue) { | 
 | 416 |     Builder.CreateRet(RetValue); | 
 | 417 |   } else { | 
 | 418 |     Builder.CreateRetVoid(); | 
 | 419 |   } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 420 |    | 
 | 421 |   // Emit a block after the branch so that dead code after a return has some | 
 | 422 |   // place to go. | 
| Gabor Greif | 984d0b4 | 2008-04-06 20:42:52 +0000 | [diff] [blame] | 423 |   EmitBlock(llvm::BasicBlock::Create()); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 424 | } | 
 | 425 |  | 
 | 426 | void CodeGenFunction::EmitDeclStmt(const DeclStmt &S) { | 
| Steve Naroff | 9474504 | 2007-09-13 23:52:58 +0000 | [diff] [blame] | 427 |   for (const ScopedDecl *Decl = S.getDecl(); Decl;  | 
 | 428 |        Decl = Decl->getNextDeclarator()) | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 429 |     EmitDecl(*Decl); | 
| Chris Lattner | 6fa5f09 | 2007-07-12 15:43:07 +0000 | [diff] [blame] | 430 | } | 
| Chris Lattner | da13870 | 2007-07-16 21:28:45 +0000 | [diff] [blame] | 431 |  | 
 | 432 | void CodeGenFunction::EmitBreakStmt() { | 
 | 433 |   assert(!BreakContinueStack.empty() && "break stmt not in a loop or switch!"); | 
 | 434 |  | 
 | 435 |   llvm::BasicBlock *Block = BreakContinueStack.back().BreakBlock; | 
 | 436 |   Builder.CreateBr(Block); | 
| Gabor Greif | 984d0b4 | 2008-04-06 20:42:52 +0000 | [diff] [blame] | 437 |   EmitBlock(llvm::BasicBlock::Create()); | 
| Chris Lattner | da13870 | 2007-07-16 21:28:45 +0000 | [diff] [blame] | 438 | } | 
 | 439 |  | 
 | 440 | void CodeGenFunction::EmitContinueStmt() { | 
 | 441 |   assert(!BreakContinueStack.empty() && "continue stmt not in a loop!"); | 
 | 442 |  | 
 | 443 |   llvm::BasicBlock *Block = BreakContinueStack.back().ContinueBlock; | 
 | 444 |   Builder.CreateBr(Block); | 
| Gabor Greif | 984d0b4 | 2008-04-06 20:42:52 +0000 | [diff] [blame] | 445 |   EmitBlock(llvm::BasicBlock::Create()); | 
| Chris Lattner | da13870 | 2007-07-16 21:28:45 +0000 | [diff] [blame] | 446 | } | 
| Devang Patel | 51b09f2 | 2007-10-04 23:45:31 +0000 | [diff] [blame] | 447 |  | 
| Devang Patel | c049e4f | 2007-10-08 20:57:48 +0000 | [diff] [blame] | 448 | /// EmitCaseStmtRange - If case statement range is not too big then | 
 | 449 | /// add multiple cases to switch instruction, one for each value within | 
 | 450 | /// the range. If range is too big then emit "if" condition check. | 
 | 451 | void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) { | 
| Daniel Dunbar | 16f2357 | 2008-07-25 01:11:38 +0000 | [diff] [blame] | 452 |   // XXX kill me with param - ddunbar | 
| Daniel Dunbar | 4efde8d | 2008-07-24 01:18:41 +0000 | [diff] [blame] | 453 |   assert(S.getRHS() && "Expected RHS value in CaseStmt"); | 
| Devang Patel | c049e4f | 2007-10-08 20:57:48 +0000 | [diff] [blame] | 454 |  | 
| Daniel Dunbar | 4efde8d | 2008-07-24 01:18:41 +0000 | [diff] [blame] | 455 |   llvm::APSInt LHS = S.getLHS()->getIntegerConstantExprValue(getContext()); | 
 | 456 |   llvm::APSInt RHS = S.getRHS()->getIntegerConstantExprValue(getContext()); | 
 | 457 |  | 
| Daniel Dunbar | 16f2357 | 2008-07-25 01:11:38 +0000 | [diff] [blame] | 458 |   // Emit the code for this case. We do this first to make sure it is | 
 | 459 |   // properly chained from our predecessor before generating the | 
 | 460 |   // switch machinery to enter this block. | 
 | 461 |   StartBlock("sw.bb"); | 
 | 462 |   llvm::BasicBlock *CaseDest = Builder.GetInsertBlock(); | 
 | 463 |   EmitStmt(S.getSubStmt()); | 
 | 464 |  | 
| Daniel Dunbar | 4efde8d | 2008-07-24 01:18:41 +0000 | [diff] [blame] | 465 |   // If range is empty, do nothing. | 
 | 466 |   if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS)) | 
 | 467 |     return; | 
| Devang Patel | c049e4f | 2007-10-08 20:57:48 +0000 | [diff] [blame] | 468 |  | 
 | 469 |   llvm::APInt Range = RHS - LHS; | 
| Daniel Dunbar | 16f2357 | 2008-07-25 01:11:38 +0000 | [diff] [blame] | 470 |   // FIXME: parameters such as this should not be hardcoded. | 
| Devang Patel | c049e4f | 2007-10-08 20:57:48 +0000 | [diff] [blame] | 471 |   if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) { | 
 | 472 |     // Range is small enough to add multiple switch instruction cases. | 
| Daniel Dunbar | 4efde8d | 2008-07-24 01:18:41 +0000 | [diff] [blame] | 473 |     for (unsigned i = 0, e = Range.getZExtValue() + 1; i != e; ++i) { | 
| Devang Patel | 2d79d0f | 2007-10-05 20:54:07 +0000 | [diff] [blame] | 474 |       SwitchInsn->addCase(llvm::ConstantInt::get(LHS), CaseDest); | 
 | 475 |       LHS++; | 
 | 476 |     } | 
| Devang Patel | c049e4f | 2007-10-08 20:57:48 +0000 | [diff] [blame] | 477 |     return; | 
 | 478 |   }  | 
 | 479 |      | 
| Daniel Dunbar | 16f2357 | 2008-07-25 01:11:38 +0000 | [diff] [blame] | 480 |   // The range is too big. Emit "if" condition into a new block, | 
 | 481 |   // making sure to save and restore the current insertion point. | 
 | 482 |   llvm::BasicBlock *RestoreBB = Builder.GetInsertBlock(); | 
| Devang Patel | 2d79d0f | 2007-10-05 20:54:07 +0000 | [diff] [blame] | 483 |  | 
| Daniel Dunbar | 16f2357 | 2008-07-25 01:11:38 +0000 | [diff] [blame] | 484 |   // Push this test onto the chain of range checks (which terminates | 
 | 485 |   // in the default basic block). The switch's default will be changed | 
 | 486 |   // to the top of this chain after switch emission is complete. | 
 | 487 |   llvm::BasicBlock *FalseDest = CaseRangeBlock; | 
 | 488 |   CaseRangeBlock = llvm::BasicBlock::Create("sw.caserange"); | 
| Devang Patel | c049e4f | 2007-10-08 20:57:48 +0000 | [diff] [blame] | 489 |  | 
| Daniel Dunbar | 16f2357 | 2008-07-25 01:11:38 +0000 | [diff] [blame] | 490 |   CurFn->getBasicBlockList().push_back(CaseRangeBlock); | 
 | 491 |   Builder.SetInsertPoint(CaseRangeBlock); | 
| Devang Patel | c049e4f | 2007-10-08 20:57:48 +0000 | [diff] [blame] | 492 |  | 
 | 493 |   // Emit range check. | 
 | 494 |   llvm::Value *Diff =  | 
| Daniel Dunbar | 4efde8d | 2008-07-24 01:18:41 +0000 | [diff] [blame] | 495 |     Builder.CreateSub(SwitchInsn->getCondition(), llvm::ConstantInt::get(LHS),  | 
 | 496 |                       "tmp"); | 
| Devang Patel | c049e4f | 2007-10-08 20:57:48 +0000 | [diff] [blame] | 497 |   llvm::Value *Cond =  | 
 | 498 |     Builder.CreateICmpULE(Diff, llvm::ConstantInt::get(Range), "tmp"); | 
 | 499 |   Builder.CreateCondBr(Cond, CaseDest, FalseDest); | 
 | 500 |  | 
| Daniel Dunbar | 16f2357 | 2008-07-25 01:11:38 +0000 | [diff] [blame] | 501 |   // Restore the appropriate insertion point. | 
 | 502 |   Builder.SetInsertPoint(RestoreBB); | 
| Devang Patel | c049e4f | 2007-10-08 20:57:48 +0000 | [diff] [blame] | 503 | } | 
 | 504 |  | 
 | 505 | void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) { | 
 | 506 |   if (S.getRHS()) { | 
 | 507 |     EmitCaseStmtRange(S); | 
 | 508 |     return; | 
 | 509 |   } | 
 | 510 |      | 
 | 511 |   StartBlock("sw.bb"); | 
 | 512 |   llvm::BasicBlock *CaseDest = Builder.GetInsertBlock(); | 
| Daniel Dunbar | 4efde8d | 2008-07-24 01:18:41 +0000 | [diff] [blame] | 513 |   llvm::APSInt CaseVal = S.getLHS()->getIntegerConstantExprValue(getContext()); | 
 | 514 |   SwitchInsn->addCase(llvm::ConstantInt::get(CaseVal),  | 
 | 515 |                       CaseDest); | 
| Devang Patel | 51b09f2 | 2007-10-04 23:45:31 +0000 | [diff] [blame] | 516 |   EmitStmt(S.getSubStmt()); | 
 | 517 | } | 
 | 518 |  | 
 | 519 | void CodeGenFunction::EmitDefaultStmt(const DefaultStmt &S) { | 
| Daniel Dunbar | 16f2357 | 2008-07-25 01:11:38 +0000 | [diff] [blame] | 520 |   llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest(); | 
 | 521 |   assert(DefaultBlock->empty() && "EmitDefaultStmt: Default block already defined?"); | 
 | 522 |   EmitBlock(DefaultBlock); | 
| Devang Patel | 51b09f2 | 2007-10-04 23:45:31 +0000 | [diff] [blame] | 523 |   EmitStmt(S.getSubStmt()); | 
 | 524 | } | 
 | 525 |  | 
 | 526 | void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) { | 
 | 527 |   llvm::Value *CondV = EmitScalarExpr(S.getCond()); | 
 | 528 |  | 
 | 529 |   // Handle nested switch statements. | 
 | 530 |   llvm::SwitchInst *SavedSwitchInsn = SwitchInsn; | 
| Devang Patel | c049e4f | 2007-10-08 20:57:48 +0000 | [diff] [blame] | 531 |   llvm::BasicBlock *SavedCRBlock = CaseRangeBlock; | 
| Devang Patel | 51b09f2 | 2007-10-04 23:45:31 +0000 | [diff] [blame] | 532 |  | 
| Daniel Dunbar | 16f2357 | 2008-07-25 01:11:38 +0000 | [diff] [blame] | 533 |   // Create basic block to hold stuff that comes after switch | 
 | 534 |   // statement. We also need to create a default block now so that | 
 | 535 |   // explicit case ranges tests can have a place to jump to on | 
 | 536 |   // failure. | 
 | 537 |   llvm::BasicBlock *NextBlock = llvm::BasicBlock::Create("sw.epilog"); | 
 | 538 |   llvm::BasicBlock *DefaultBlock = llvm::BasicBlock::Create("sw.default"); | 
 | 539 |   SwitchInsn = Builder.CreateSwitch(CondV, DefaultBlock); | 
 | 540 |   CaseRangeBlock = DefaultBlock; | 
| Devang Patel | 51b09f2 | 2007-10-04 23:45:31 +0000 | [diff] [blame] | 541 |  | 
| Eli Friedman | d28a80d | 2008-05-12 16:08:04 +0000 | [diff] [blame] | 542 |   // Create basic block for body of switch | 
| Daniel Dunbar | 16f2357 | 2008-07-25 01:11:38 +0000 | [diff] [blame] | 543 |   StartBlock("sw.body"); | 
| Eli Friedman | d28a80d | 2008-05-12 16:08:04 +0000 | [diff] [blame] | 544 |  | 
| Devang Patel | e9b8c0a | 2007-10-30 20:59:40 +0000 | [diff] [blame] | 545 |   // All break statements jump to NextBlock. If BreakContinueStack is non empty | 
 | 546 |   // then reuse last ContinueBlock. | 
| Devang Patel | 51b09f2 | 2007-10-04 23:45:31 +0000 | [diff] [blame] | 547 |   llvm::BasicBlock *ContinueBlock = NULL; | 
 | 548 |   if (!BreakContinueStack.empty()) | 
 | 549 |     ContinueBlock = BreakContinueStack.back().ContinueBlock; | 
 | 550 |   BreakContinueStack.push_back(BreakContinue(NextBlock, ContinueBlock)); | 
 | 551 |  | 
 | 552 |   // Emit switch body. | 
 | 553 |   EmitStmt(S.getBody()); | 
 | 554 |   BreakContinueStack.pop_back(); | 
 | 555 |  | 
| Daniel Dunbar | 16f2357 | 2008-07-25 01:11:38 +0000 | [diff] [blame] | 556 |   // Update the default block in case explicit case range tests have | 
 | 557 |   // been chained on top. | 
 | 558 |   SwitchInsn->setSuccessor(0, CaseRangeBlock); | 
| Devang Patel | c049e4f | 2007-10-08 20:57:48 +0000 | [diff] [blame] | 559 |    | 
| Daniel Dunbar | 16f2357 | 2008-07-25 01:11:38 +0000 | [diff] [blame] | 560 |   // If a default was never emitted then reroute any jumps to it and | 
 | 561 |   // discard. | 
 | 562 |   if (!DefaultBlock->getParent()) { | 
 | 563 |     DefaultBlock->replaceAllUsesWith(NextBlock); | 
 | 564 |     delete DefaultBlock; | 
 | 565 |   } | 
| Devang Patel | 51b09f2 | 2007-10-04 23:45:31 +0000 | [diff] [blame] | 566 |  | 
| Daniel Dunbar | 16f2357 | 2008-07-25 01:11:38 +0000 | [diff] [blame] | 567 |   // Emit continuation. | 
 | 568 |   EmitBlock(NextBlock); | 
 | 569 |  | 
| Devang Patel | 51b09f2 | 2007-10-04 23:45:31 +0000 | [diff] [blame] | 570 |   SwitchInsn = SavedSwitchInsn; | 
| Devang Patel | c049e4f | 2007-10-08 20:57:48 +0000 | [diff] [blame] | 571 |   CaseRangeBlock = SavedCRBlock; | 
| Devang Patel | 51b09f2 | 2007-10-04 23:45:31 +0000 | [diff] [blame] | 572 | } | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 573 |  | 
| Chris Lattner | 345f720 | 2008-07-26 20:15:14 +0000 | [diff] [blame] | 574 | static std::string ConvertAsmString(const char *Start, unsigned NumOperands, | 
 | 575 |                                     bool IsSimple) { | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 576 |   static unsigned AsmCounter = 0; | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 577 |   AsmCounter++; | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 578 |   std::string Result; | 
| Anders Carlsson | 2abd25f | 2008-02-05 23:18:57 +0000 | [diff] [blame] | 579 |   if (IsSimple) { | 
 | 580 |     while (*Start) { | 
 | 581 |       switch (*Start) { | 
 | 582 |       default: | 
 | 583 |         Result += *Start; | 
 | 584 |         break; | 
 | 585 |       case '$': | 
 | 586 |         Result += "$$"; | 
 | 587 |         break; | 
 | 588 |       } | 
| Anders Carlsson | 2abd25f | 2008-02-05 23:18:57 +0000 | [diff] [blame] | 589 |       Start++; | 
 | 590 |     } | 
 | 591 |      | 
 | 592 |     return Result; | 
 | 593 |   } | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 594 |    | 
 | 595 |   while (*Start) { | 
 | 596 |     switch (*Start) { | 
 | 597 |     default: | 
 | 598 |       Result += *Start; | 
 | 599 |       break; | 
 | 600 |     case '$': | 
 | 601 |       Result += "$$"; | 
 | 602 |       break; | 
 | 603 |     case '%': | 
 | 604 |       // Escaped character | 
 | 605 |       Start++; | 
 | 606 |       if (!*Start) { | 
 | 607 |         // FIXME: This should be caught during Sema. | 
 | 608 |         assert(0 && "Trailing '%' in asm string."); | 
 | 609 |       } | 
 | 610 |        | 
 | 611 |       char EscapedChar = *Start; | 
 | 612 |       if (EscapedChar == '%') { | 
 | 613 |         // Escaped percentage sign. | 
 | 614 |         Result += '%'; | 
| Chris Lattner | 345f720 | 2008-07-26 20:15:14 +0000 | [diff] [blame] | 615 |       } else if (EscapedChar == '=') { | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 616 |         // Generate an unique ID. | 
 | 617 |         Result += llvm::utostr(AsmCounter); | 
 | 618 |       } else if (isdigit(EscapedChar)) { | 
 | 619 |         // %n - Assembler operand n | 
 | 620 |         char *End; | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 621 |         unsigned long n = strtoul(Start, &End, 10); | 
 | 622 |         if (Start == End) { | 
 | 623 |           // FIXME: This should be caught during Sema. | 
 | 624 |           assert(0 && "Missing operand!"); | 
 | 625 |         } else if (n >= NumOperands) { | 
 | 626 |           // FIXME: This should be caught during Sema. | 
 | 627 |           assert(0 && "Operand number out of range!"); | 
 | 628 |         } | 
 | 629 |          | 
 | 630 |         Result += '$' + llvm::utostr(n); | 
| Lauro Ramos Venancio | 7695f70 | 2008-02-26 19:19:58 +0000 | [diff] [blame] | 631 |         Start = End - 1; | 
| Anders Carlsson | 2abd25f | 2008-02-05 23:18:57 +0000 | [diff] [blame] | 632 |       } else if (isalpha(EscapedChar)) { | 
 | 633 |         char *End; | 
 | 634 |          | 
 | 635 |         unsigned long n = strtoul(Start + 1, &End, 10); | 
 | 636 |         if (Start == End) { | 
 | 637 |           // FIXME: This should be caught during Sema. | 
 | 638 |           assert(0 && "Missing operand!"); | 
 | 639 |         } else if (n >= NumOperands) { | 
 | 640 |           // FIXME: This should be caught during Sema. | 
 | 641 |           assert(0 && "Operand number out of range!"); | 
 | 642 |         } | 
 | 643 |          | 
 | 644 |         Result += "${" + llvm::utostr(n) + ':' + EscapedChar + '}'; | 
| Lauro Ramos Venancio | 7695f70 | 2008-02-26 19:19:58 +0000 | [diff] [blame] | 645 |         Start = End - 1; | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 646 |       } else { | 
 | 647 |         assert(0 && "Unhandled asm escaped character!"); | 
 | 648 |       } | 
 | 649 |     } | 
 | 650 |     Start++; | 
 | 651 |   } | 
 | 652 |    | 
 | 653 |   return Result; | 
 | 654 | } | 
 | 655 |  | 
| Lauro Ramos Venancio | a5694b8 | 2008-02-26 18:33:46 +0000 | [diff] [blame] | 656 | static std::string SimplifyConstraint(const char* Constraint, | 
 | 657 |                                       TargetInfo &Target) { | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 658 |   std::string Result; | 
 | 659 |    | 
 | 660 |   while (*Constraint) { | 
 | 661 |     switch (*Constraint) { | 
 | 662 |     default: | 
| Lauro Ramos Venancio | a5694b8 | 2008-02-26 18:33:46 +0000 | [diff] [blame] | 663 |       Result += Target.convertConstraint(*Constraint); | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 664 |       break; | 
 | 665 |     // Ignore these | 
 | 666 |     case '*': | 
 | 667 |     case '?': | 
 | 668 |     case '!': | 
 | 669 |       break; | 
 | 670 |     case 'g': | 
 | 671 |       Result += "imr"; | 
 | 672 |       break; | 
 | 673 |     } | 
 | 674 |      | 
 | 675 |     Constraint++; | 
 | 676 |   } | 
 | 677 |    | 
 | 678 |   return Result; | 
 | 679 | } | 
 | 680 |  | 
 | 681 | void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { | 
 | 682 |   std::string AsmString =  | 
 | 683 |     ConvertAsmString(std::string(S.getAsmString()->getStrData(), | 
 | 684 |                                  S.getAsmString()->getByteLength()).c_str(), | 
| Anders Carlsson | 2abd25f | 2008-02-05 23:18:57 +0000 | [diff] [blame] | 685 |                      S.getNumOutputs() + S.getNumInputs(), S.isSimple()); | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 686 |    | 
 | 687 |   std::string Constraints; | 
 | 688 |    | 
 | 689 |   llvm::Value *ResultAddr = 0; | 
 | 690 |   const llvm::Type *ResultType = llvm::Type::VoidTy; | 
 | 691 |    | 
 | 692 |   std::vector<const llvm::Type*> ArgTypes; | 
 | 693 |   std::vector<llvm::Value*> Args; | 
| Anders Carlsson | f39a421 | 2008-02-05 20:01:53 +0000 | [diff] [blame] | 694 |  | 
 | 695 |   // Keep track of inout constraints. | 
 | 696 |   std::string InOutConstraints; | 
 | 697 |   std::vector<llvm::Value*> InOutArgs; | 
 | 698 |   std::vector<const llvm::Type*> InOutArgTypes; | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 699 |    | 
 | 700 |   for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) {     | 
 | 701 |     std::string OutputConstraint(S.getOutputConstraint(i)->getStrData(), | 
 | 702 |                                  S.getOutputConstraint(i)->getByteLength()); | 
 | 703 |      | 
 | 704 |     TargetInfo::ConstraintInfo Info; | 
 | 705 |     bool result = Target.validateOutputConstraint(OutputConstraint.c_str(),  | 
 | 706 |                                                   Info); | 
 | 707 |     assert(result && "Failed to parse output constraint"); | 
 | 708 |      | 
 | 709 |     // Simplify the output constraint. | 
| Lauro Ramos Venancio | a5694b8 | 2008-02-26 18:33:46 +0000 | [diff] [blame] | 710 |     OutputConstraint = SimplifyConstraint(OutputConstraint.c_str() + 1, Target); | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 711 |      | 
 | 712 |     LValue Dest = EmitLValue(S.getOutputExpr(i)); | 
 | 713 |     const llvm::Type *DestValueType =  | 
 | 714 |       cast<llvm::PointerType>(Dest.getAddress()->getType())->getElementType(); | 
 | 715 |      | 
 | 716 |     // If the first output operand is not a memory dest, we'll | 
 | 717 |     // make it the return value. | 
 | 718 |     if (i == 0 && !(Info & TargetInfo::CI_AllowsMemory) && | 
| Dan Gohman | d79a726 | 2008-05-22 22:12:56 +0000 | [diff] [blame] | 719 |         DestValueType->isSingleValueType()) { | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 720 |       ResultAddr = Dest.getAddress(); | 
 | 721 |       ResultType = DestValueType; | 
 | 722 |       Constraints += "=" + OutputConstraint; | 
 | 723 |     } else { | 
 | 724 |       ArgTypes.push_back(Dest.getAddress()->getType()); | 
| Anders Carlsson | cad3ab6 | 2008-02-05 16:57:38 +0000 | [diff] [blame] | 725 |       Args.push_back(Dest.getAddress()); | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 726 |       if (i != 0) | 
 | 727 |         Constraints += ','; | 
| Anders Carlsson | f39a421 | 2008-02-05 20:01:53 +0000 | [diff] [blame] | 728 |       Constraints += "=*"; | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 729 |       Constraints += OutputConstraint; | 
| Anders Carlsson | f39a421 | 2008-02-05 20:01:53 +0000 | [diff] [blame] | 730 |     } | 
 | 731 |      | 
 | 732 |     if (Info & TargetInfo::CI_ReadWrite) { | 
 | 733 |       // FIXME: This code should be shared with the code that handles inputs. | 
 | 734 |       InOutConstraints += ','; | 
 | 735 |        | 
 | 736 |       const Expr *InputExpr = S.getOutputExpr(i); | 
 | 737 |       llvm::Value *Arg; | 
 | 738 |       if ((Info & TargetInfo::CI_AllowsRegister) || | 
 | 739 |           !(Info & TargetInfo::CI_AllowsMemory)) {       | 
| Dan Gohman | d79a726 | 2008-05-22 22:12:56 +0000 | [diff] [blame] | 740 |         if (ConvertType(InputExpr->getType())->isSingleValueType()) { | 
| Anders Carlsson | f39a421 | 2008-02-05 20:01:53 +0000 | [diff] [blame] | 741 |           Arg = EmitScalarExpr(InputExpr); | 
 | 742 |         } else { | 
| Dan Gohman | d79a726 | 2008-05-22 22:12:56 +0000 | [diff] [blame] | 743 |           assert(0 && "FIXME: Implement passing multiple-value types as inputs"); | 
| Anders Carlsson | f39a421 | 2008-02-05 20:01:53 +0000 | [diff] [blame] | 744 |         } | 
 | 745 |       } else { | 
 | 746 |         LValue Dest = EmitLValue(InputExpr); | 
 | 747 |         Arg = Dest.getAddress(); | 
 | 748 |         InOutConstraints += '*'; | 
 | 749 |       } | 
 | 750 |        | 
 | 751 |       InOutArgTypes.push_back(Arg->getType()); | 
 | 752 |       InOutArgs.push_back(Arg); | 
 | 753 |       InOutConstraints += OutputConstraint; | 
 | 754 |     } | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 755 |   } | 
 | 756 |    | 
 | 757 |   unsigned NumConstraints = S.getNumOutputs() + S.getNumInputs(); | 
 | 758 |    | 
 | 759 |   for (unsigned i = 0, e = S.getNumInputs(); i != e; i++) { | 
 | 760 |     const Expr *InputExpr = S.getInputExpr(i); | 
 | 761 |  | 
 | 762 |     std::string InputConstraint(S.getInputConstraint(i)->getStrData(), | 
 | 763 |                                 S.getInputConstraint(i)->getByteLength()); | 
 | 764 |      | 
 | 765 |     TargetInfo::ConstraintInfo Info; | 
 | 766 |     bool result = Target.validateInputConstraint(InputConstraint.c_str(), | 
 | 767 |                                                  NumConstraints,  | 
 | 768 |                                                  Info); | 
 | 769 |     assert(result && "Failed to parse input constraint"); | 
 | 770 |      | 
 | 771 |     if (i != 0 || S.getNumOutputs() > 0) | 
 | 772 |       Constraints += ','; | 
 | 773 |      | 
 | 774 |     // Simplify the input constraint. | 
| Lauro Ramos Venancio | a5694b8 | 2008-02-26 18:33:46 +0000 | [diff] [blame] | 775 |     InputConstraint = SimplifyConstraint(InputConstraint.c_str(), Target); | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 776 |  | 
 | 777 |     llvm::Value *Arg; | 
 | 778 |      | 
 | 779 |     if ((Info & TargetInfo::CI_AllowsRegister) || | 
 | 780 |         !(Info & TargetInfo::CI_AllowsMemory)) {       | 
| Dan Gohman | d79a726 | 2008-05-22 22:12:56 +0000 | [diff] [blame] | 781 |       if (ConvertType(InputExpr->getType())->isSingleValueType()) { | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 782 |         Arg = EmitScalarExpr(InputExpr); | 
 | 783 |       } else { | 
| Dan Gohman | d79a726 | 2008-05-22 22:12:56 +0000 | [diff] [blame] | 784 |         assert(0 && "FIXME: Implement passing multiple-value types as inputs"); | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 785 |       } | 
 | 786 |     } else { | 
 | 787 |       LValue Dest = EmitLValue(InputExpr); | 
 | 788 |       Arg = Dest.getAddress(); | 
 | 789 |       Constraints += '*'; | 
 | 790 |     } | 
 | 791 |      | 
 | 792 |     ArgTypes.push_back(Arg->getType()); | 
 | 793 |     Args.push_back(Arg); | 
 | 794 |     Constraints += InputConstraint; | 
 | 795 |   } | 
 | 796 |    | 
| Anders Carlsson | f39a421 | 2008-02-05 20:01:53 +0000 | [diff] [blame] | 797 |   // Append the "input" part of inout constraints last. | 
 | 798 |   for (unsigned i = 0, e = InOutArgs.size(); i != e; i++) { | 
 | 799 |     ArgTypes.push_back(InOutArgTypes[i]); | 
 | 800 |     Args.push_back(InOutArgs[i]); | 
 | 801 |   } | 
 | 802 |   Constraints += InOutConstraints; | 
 | 803 |    | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 804 |   // Clobbers | 
 | 805 |   for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) { | 
 | 806 |     std::string Clobber(S.getClobber(i)->getStrData(), | 
 | 807 |                         S.getClobber(i)->getByteLength()); | 
 | 808 |  | 
 | 809 |     Clobber = Target.getNormalizedGCCRegisterName(Clobber.c_str()); | 
 | 810 |      | 
| Anders Carlsson | ea04175 | 2008-02-06 00:11:32 +0000 | [diff] [blame] | 811 |     if (i != 0 || NumConstraints != 0) | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 812 |       Constraints += ','; | 
| Anders Carlsson | ea04175 | 2008-02-06 00:11:32 +0000 | [diff] [blame] | 813 |      | 
 | 814 |     Constraints += "~{"; | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 815 |     Constraints += Clobber; | 
| Anders Carlsson | ea04175 | 2008-02-06 00:11:32 +0000 | [diff] [blame] | 816 |     Constraints += '}'; | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 817 |   } | 
 | 818 |    | 
 | 819 |   // Add machine specific clobbers | 
 | 820 |   if (const char *C = Target.getClobbers()) { | 
 | 821 |     if (!Constraints.empty()) | 
 | 822 |       Constraints += ','; | 
 | 823 |     Constraints += C; | 
 | 824 |   } | 
| Anders Carlsson | f39a421 | 2008-02-05 20:01:53 +0000 | [diff] [blame] | 825 |      | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 826 |   const llvm::FunctionType *FTy =  | 
 | 827 |     llvm::FunctionType::get(ResultType, ArgTypes, false); | 
 | 828 |    | 
 | 829 |   llvm::InlineAsm *IA =  | 
 | 830 |     llvm::InlineAsm::get(FTy, AsmString, Constraints,  | 
 | 831 |                          S.isVolatile() || S.getNumOutputs() == 0); | 
 | 832 |   llvm::Value *Result = Builder.CreateCall(IA, Args.begin(), Args.end(), ""); | 
| Eli Friedman | 1e692ac | 2008-06-13 23:01:12 +0000 | [diff] [blame] | 833 |   if (ResultAddr) // FIXME: volatility | 
| Anders Carlsson | fb1aeb8 | 2008-02-05 16:35:33 +0000 | [diff] [blame] | 834 |     Builder.CreateStore(Result, ResultAddr); | 
 | 835 | } |