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