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