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