This machine mirrors various open-source projects.
20 Gbit/s uplink.
If there are any issues or you want another project mirrored, please contact
mirror-service -=AT=- netcologne DOT de !
00001 //===-- codege/CodeGenStmt.cpp -------------------------------- -*- C++ -*-===// 00002 // 00003 // This file is distributed under the MIT license. See LICENSE.txt for details. 00004 // 00005 // Copyright (C) 2009-2010, Stephen Wilson 00006 // 00007 //===----------------------------------------------------------------------===// 00008 00009 #include "BoundsEmitter.h" 00010 #include "CodeGenRoutine.h" 00011 #include "CodeGenTypes.h" 00012 #include "CommaRT.h" 00013 #include "HandlerEmitter.h" 00014 #include "comma/ast/Decl.h" 00015 #include "comma/ast/DSTDefinition.h" 00016 #include "comma/ast/Expr.h" 00017 #include "comma/ast/Pragma.h" 00018 #include "comma/ast/RangeAttrib.h" 00019 #include "comma/ast/Stmt.h" 00020 00021 using namespace comma; 00022 00023 using llvm::dyn_cast; 00024 using llvm::cast; 00025 using llvm::isa; 00026 00027 void CodeGenRoutine::emitStmt(Stmt *stmt) 00028 { 00029 switch (stmt->getKind()) { 00030 00031 default: 00032 assert(false && "Cannot codegen stmt yet!"); 00033 00034 case Ast::AST_ProcedureCallStmt: 00035 emitProcedureCallStmt(cast<ProcedureCallStmt>(stmt)); 00036 break; 00037 00038 case Ast::AST_AssignmentStmt: 00039 emitAssignmentStmt(cast<AssignmentStmt>(stmt)); 00040 break; 00041 00042 case Ast::AST_StmtSequence: 00043 emitStmtSequence(cast<StmtSequence>(stmt)); 00044 break; 00045 00046 case Ast::AST_BlockStmt: 00047 emitBlockStmt(cast<BlockStmt>(stmt), Builder.GetInsertBlock()); 00048 break; 00049 00050 case Ast::AST_IfStmt: 00051 emitIfStmt(cast<IfStmt>(stmt)); 00052 break; 00053 00054 case Ast::AST_WhileStmt: 00055 emitWhileStmt(cast<WhileStmt>(stmt)); 00056 break; 00057 00058 case Ast::AST_ForStmt: 00059 emitForStmt(cast<ForStmt>(stmt)); 00060 break; 00061 00062 case Ast::AST_LoopStmt: 00063 emitLoopStmt(cast<LoopStmt>(stmt)); 00064 break; 00065 00066 case Ast::AST_ReturnStmt: 00067 emitReturnStmt(cast<ReturnStmt>(stmt)); 00068 break; 00069 00070 case Ast::AST_RaiseStmt: 00071 emitRaiseStmt(cast<RaiseStmt>(stmt)); 00072 break; 00073 00074 case Ast::AST_PragmaStmt: 00075 emitPragmaStmt(cast<PragmaStmt>(stmt)); 00076 break; 00077 00078 case Ast::AST_NullStmt: 00079 break; 00080 } 00081 } 00082 00083 void CodeGenRoutine::emitReturnStmt(ReturnStmt *ret) 00084 { 00085 if (!ret->hasReturnExpr()) { 00086 SRF->emitReturn(); 00087 return; 00088 } 00089 00090 FunctionDecl *fdecl = cast<FunctionDecl>(SRI->getDeclaration()); 00091 FunctionType *fTy = fdecl->getType(); 00092 Type *targetTy = resolveType(fTy->getReturnType()); 00093 Expr *expr = ret->getReturnExpr(); 00094 llvm::Value *returnValue = SRF->getReturnValue(); 00095 00096 if (ArrayType *arrTy = dyn_cast<ArrayType>(targetTy)) { 00097 // Constrained arrays are emitted directly into the sret parameter. 00098 // Unconstrained arrays are propagated thru the vstack. 00099 if (arrTy->isConstrained()) 00100 emitArrayExpr(expr, returnValue, false); 00101 else { 00102 assert(returnValue == 0); 00103 emitVStackReturn(expr, arrTy); 00104 } 00105 } 00106 else if (targetTy->isRecordType()) { 00107 // Emit records directly into the sret return parameter. 00108 emitRecordExpr(expr, returnValue, false); 00109 } 00110 else if (targetTy->isFatAccessType()) { 00111 // Fat access types are represented as pointers to their underlying 00112 // structure. 00113 llvm::Value *res = emitValue(ret->getReturnExpr()).first(); 00114 Builder.CreateStore(Builder.CreateLoad(res), returnValue); 00115 } 00116 else { 00117 // Non-composite return values can be simply evaluated and stored into 00118 // this subroutines return slot. 00119 llvm::Value *res = emitValue(ret->getReturnExpr()).first(); 00120 Builder.CreateStore(res, returnValue); 00121 } 00122 00123 // Branch to the return block. 00124 SRF->emitReturn(); 00125 } 00126 00127 void CodeGenRoutine::emitVStackReturn(Expr *expr, ArrayType *arrTy) 00128 { 00129 if (FunctionCallExpr *call = dyn_cast<FunctionCallExpr>(expr)) { 00130 emitSimpleCall(call); 00131 return; 00132 } 00133 00134 BoundsEmitter emitter(*this); 00135 CValue arrValue = emitArrayExpr(expr, 0, false); 00136 const llvm::Type *componentTy = CGT.lowerType(arrTy->getComponentType()); 00137 llvm::Value *data = arrValue.first(); 00138 llvm::Value *bounds = arrValue.second(); 00139 llvm::Value *length = emitter.computeTotalBoundLength(Builder, bounds); 00140 const llvm::Type *boundsTy = bounds->getType(); 00141 00142 // Compute the size of the data. Note that getSizeOf returns an i64 but we 00143 // need an i32 here. 00144 llvm::Value *dataSize; 00145 dataSize = llvm::ConstantExpr::getSizeOf(componentTy); 00146 dataSize = Builder.CreateTrunc(dataSize, CG.getInt32Ty()); 00147 dataSize = Builder.CreateMul(dataSize, length); 00148 00149 // Compute the size of the bounds structure. This is dependent on if the 00150 // bounds were given as a pointer or an aggregate. 00151 llvm::Value *boundsSize; 00152 if (boundsTy->isAggregateType()) 00153 boundsSize = llvm::ConstantExpr::getSizeOf(boundsTy); 00154 else { 00155 const llvm::PointerType *ptr; 00156 ptr = llvm::cast<llvm::PointerType>(boundsTy); 00157 boundsSize = llvm::ConstantExpr::getSizeOf(ptr->getElementType()); 00158 } 00159 boundsSize = Builder.CreateTrunc(boundsSize, CG.getInt32Ty()); 00160 00161 // Generate a temporary if needed so that we can obtain a pointer to the 00162 // bounds. 00163 if (boundsTy->isAggregateType()) { 00164 llvm::Value *slot = SRF->createTemp(boundsTy); 00165 Builder.CreateStore(bounds, slot); 00166 bounds = slot; 00167 } 00168 00169 CRT.vstack_push(Builder, data, dataSize); 00170 CRT.vstack_push(Builder, bounds, boundsSize); 00171 } 00172 00173 void CodeGenRoutine::emitStmtSequence(StmtSequence *seq) 00174 { 00175 for (StmtSequence::stmt_iter iter = seq->stmt_begin(); 00176 iter != seq->stmt_end(); ++iter) 00177 emitStmt(*iter); 00178 } 00179 00180 llvm::BasicBlock *CodeGenRoutine::emitBlockStmt(BlockStmt *block, 00181 llvm::BasicBlock *predecessor) 00182 { 00183 assert(block && "NULL block statement!"); 00184 00185 std::string label; 00186 if (block->hasLabel()) 00187 label = block->getLabel()->getString(); 00188 00189 llvm::BasicBlock *BB = SRF->makeBasicBlock(label); 00190 SRF->pushFrame(BB); 00191 00192 if (block->isHandled()) 00193 SRF->addLandingPad(); 00194 00195 if (predecessor) { 00196 Builder.CreateBr(BB); 00197 BB->moveAfter(predecessor); 00198 } 00199 00200 Builder.SetInsertPoint(BB); 00201 00202 // Generate any declarations provided by this block, followed by the blocks 00203 // sequence of statements. 00204 typedef DeclRegion::DeclIter iterator; 00205 for (iterator I = block->beginDecls(); I != block->endDecls(); ++I) { 00206 Decl *decl = *I; 00207 switch (decl->getKind()) { 00208 default: 00209 break; 00210 00211 case Ast::AST_ObjectDecl: 00212 emitObjectDecl(cast<ObjectDecl>(decl)); 00213 break; 00214 00215 case Ast::AST_RenamedObjectDecl: 00216 emitRenamedObjectDecl(cast<RenamedObjectDecl>(decl)); 00217 break; 00218 } 00219 } 00220 emitStmtSequence(block); 00221 00222 if (block->isHandled()) { 00223 // Terminate the current insertion point with a branch to a common block 00224 // dominated by the sequence of statements and the exception handlers. 00225 llvm::BasicBlock *mergeBB = SRF->makeBasicBlock("handler.merge"); 00226 if (!Builder.GetInsertBlock()->getTerminator()) 00227 Builder.CreateBr(mergeBB); 00228 00229 // Emit the handlers. Insertion point is set to mergeBB on return. 00230 HandlerEmitter emitter(*this); 00231 emitter.emitHandlers(block, mergeBB); 00232 } 00233 00234 SRF->popFrame(); 00235 return BB; 00236 } 00237 00238 void CodeGenRoutine::emitIfStmt(IfStmt *ite) 00239 { 00240 CValue condition = emitValue(ite->getCondition()); 00241 llvm::BasicBlock *thenBB = SRF->makeBasicBlock("then"); 00242 llvm::BasicBlock *mergeBB = SRF->makeBasicBlock("merge"); 00243 llvm::BasicBlock *elseBB; 00244 00245 if (ite->hasElsif()) 00246 elseBB = SRF->makeBasicBlock("elsif"); 00247 else if (ite->hasAlternate()) 00248 elseBB = SRF->makeBasicBlock("else"); 00249 else 00250 elseBB = mergeBB; 00251 00252 Builder.CreateCondBr(condition.first(), thenBB, elseBB); 00253 Builder.SetInsertPoint(thenBB); 00254 00255 // Emit the true branch in its own frame. If generation of the consequent 00256 // did not result in a terminator, create a branch to the merge block. 00257 SRF->pushFrame(thenBB); 00258 emitStmt(ite->getConsequent()); 00259 if (!Builder.GetInsertBlock()->getTerminator()) 00260 Builder.CreateBr(mergeBB); 00261 SRF->popFrame(); 00262 00263 // Emit each elsif block in its own frame. 00264 for (IfStmt::iterator I = ite->beginElsif(); I != ite->endElsif(); ++I) { 00265 Builder.SetInsertPoint(elseBB); 00266 IfStmt::iterator J = I; 00267 if (++J != ite->endElsif()) 00268 elseBB = SRF->makeBasicBlock("elsif"); 00269 else if (ite->hasAlternate()) 00270 elseBB = SRF->makeBasicBlock("else"); 00271 else 00272 elseBB = mergeBB; 00273 llvm::BasicBlock *bodyBB = SRF->makeBasicBlock("body"); 00274 llvm::Value *pred = emitValue(I->getCondition()).first(); 00275 Builder.CreateCondBr(pred, bodyBB, elseBB); 00276 Builder.SetInsertPoint(bodyBB); 00277 00278 SRF->pushFrame(bodyBB); 00279 emitStmt(I->getConsequent()); 00280 if (!Builder.GetInsertBlock()->getTerminator()) 00281 Builder.CreateBr(mergeBB); 00282 SRF->popFrame(); 00283 } 00284 00285 if (ite->hasAlternate()) { 00286 Builder.SetInsertPoint(elseBB); 00287 00288 SRF->pushFrame(elseBB); 00289 emitStmt(ite->getAlternate()); 00290 if (!Builder.GetInsertBlock()->getTerminator()) 00291 Builder.CreateBr(mergeBB); 00292 SRF->popFrame(); 00293 } 00294 00295 Builder.SetInsertPoint(mergeBB); 00296 } 00297 00298 void CodeGenRoutine::emitWhileStmt(WhileStmt *stmt) 00299 { 00300 llvm::BasicBlock *entryBB = SRF->makeBasicBlock("while.top"); 00301 llvm::BasicBlock *bodyBB = SRF->makeBasicBlock("while.entry"); 00302 llvm::BasicBlock *mergeBB = SRF->makeBasicBlock("while.merge"); 00303 00304 // Branch unconditionally from the current insertion point to the entry 00305 // block and set up our new context. Emit the loop condition into the entry 00306 // block. 00307 Builder.CreateBr(entryBB); 00308 Builder.SetInsertPoint(entryBB); 00309 CValue condition = emitValue(stmt->getCondition()); 00310 00311 // Branch into bodyBB if condition evaluates to true, mergeBB otherwise. 00312 Builder.CreateCondBr(condition.first(), bodyBB, mergeBB); 00313 00314 // Generate the body. 00315 Builder.SetInsertPoint(bodyBB); 00316 SRF->pushFrame(bodyBB); 00317 emitStmt(stmt->getBody()); 00318 SRF->popFrame(); 00319 00320 // If the current insertion point does not have a terminator, 00321 // unconditionally branch to entryBB. 00322 if (!Builder.GetInsertBlock()->getTerminator()) 00323 Builder.CreateBr(entryBB); 00324 00325 // Finally, set mergeBB as the current insertion point. 00326 Builder.SetInsertPoint(mergeBB); 00327 } 00328 00329 void CodeGenRoutine::emitForStmt(ForStmt *loop) 00330 { 00331 llvm::Value *iter; // Iteration variable for the loop. 00332 llvm::Value *sentinal; // Iteration bound. 00333 00334 DSTDefinition *control = loop->getControl(); 00335 if (control->definedUsingAttrib()) { 00336 std::pair<llvm::Value*, llvm::Value*> bounds; 00337 RangeAttrib *attrib = control->getAttrib(); 00338 bounds = emitRangeAttrib(attrib); 00339 iter = bounds.first; 00340 sentinal = bounds.second; 00341 } 00342 else { 00343 BoundsEmitter emitter(*this); 00344 BoundsEmitter::LUPair bounds; 00345 bounds = emitter.getScalarBounds(Builder, control->getType()); 00346 iter = bounds.first; 00347 sentinal = bounds.second; 00348 } 00349 00350 // If the loop is reversed, exchange the iteration variable and bound. 00351 if (loop->isReversed()) 00352 std::swap(iter, sentinal); 00353 00354 // We have the initial value for the iteration variable and the bound for 00355 // the iteration. Emit an entry, iterate, body, and merge block for the 00356 // loop. 00357 llvm::BasicBlock *dominatorBB = Builder.GetInsertBlock(); 00358 llvm::BasicBlock *entryBB = SRF->makeBasicBlock("for.top"); 00359 llvm::BasicBlock *iterBB = SRF->makeBasicBlock("for.iter"); 00360 llvm::BasicBlock *bodyBB = SRF->makeBasicBlock("for.body"); 00361 llvm::BasicBlock *mergeBB = SRF->makeBasicBlock("for.merge"); 00362 llvm::Value *pred; 00363 llvm::Value *iterSlot; 00364 llvm::Value *next; 00365 llvm::PHINode *phi; 00366 const llvm::Type *iterTy = iter->getType(); 00367 00368 // First, allocate a temporary to hold the iteration variable and 00369 // initialize. 00370 iterSlot = SRF->createTemp(iterTy); 00371 Builder.CreateStore(iter, iterSlot); 00372 00373 // First, check if the iteration variable is outside the bound, respecting 00374 // the direction of the iteration. This condition arrises when we have a 00375 // null range. When the range is non-null the iteration variable is valid 00376 // for at least one loop, hense the branch directly into the body. 00377 if (loop->isReversed()) 00378 pred = Builder.CreateICmpSLT(iter, sentinal); 00379 else 00380 pred = Builder.CreateICmpSGT(iter, sentinal); 00381 Builder.CreateCondBr(pred, mergeBB, bodyBB); 00382 00383 // Emit the iteration test. Since the body has been executed once, a test 00384 // for equality between the iteration variable and sentinal determines loop 00385 // termination. If the iteration continues, we branch to iterBB and 00386 // increment the iteration variable for the next pass thru the body. Note 00387 // too that we must load the iteration value from its slot to pick up its 00388 // adjusted value. 00389 Builder.SetInsertPoint(entryBB); 00390 next = Builder.CreateLoad(iterSlot); 00391 pred = Builder.CreateICmpEQ(next, sentinal); 00392 Builder.CreateCondBr(pred, mergeBB, iterBB); 00393 00394 // Adjust the iteration variable respecting the iteration direction. 00395 Builder.SetInsertPoint(iterBB); 00396 if (loop->isReversed()) 00397 next = Builder.CreateSub(next, llvm::ConstantInt::get(iterTy, 1)); 00398 else 00399 next = Builder.CreateAdd(next, llvm::ConstantInt::get(iterTy, 1)); 00400 Builder.CreateStore(next, iterSlot); 00401 Builder.CreateBr(bodyBB); 00402 00403 // Emit the body of the loop and terminate the resulting insertion point 00404 // with a branch to the entry block. 00405 Builder.SetInsertPoint(bodyBB); 00406 SRF->pushFrame(bodyBB); 00407 phi = Builder.CreatePHI(iterTy, "loop.param"); 00408 phi->addIncoming(iter, dominatorBB); 00409 phi->addIncoming(next, iterBB); 00410 SRF->associate(loop->getLoopDecl(), activation::Slot, phi); 00411 emitStmtSequence(loop->getBody()); 00412 SRF->popFrame(); 00413 if (!Builder.GetInsertBlock()->getTerminator()) 00414 Builder.CreateBr(entryBB); 00415 00416 // Finally, set the insertion point to the mergeBB. 00417 Builder.SetInsertPoint(mergeBB); 00418 } 00419 00420 void CodeGenRoutine::emitLoopStmt(LoopStmt *stmt) 00421 { 00422 llvm::BasicBlock *bodyBB = SRF->makeBasicBlock("loop.body"); 00423 llvm::BasicBlock *mergeBB = SRF->makeBasicBlock("loop.merge"); 00424 00425 // Branch unconditionally from the current insertion point to the loop body. 00426 Builder.CreateBr(bodyBB); 00427 Builder.SetInsertPoint(bodyBB); 00428 00429 // Generate the body. 00430 SRF->pushFrame(bodyBB); 00431 emitStmt(stmt->getBody()); 00432 SRF->popFrame(); 00433 00434 // If the current insertion point does not have a terminator, 00435 // unconditionally branch back to the start of the body. 00436 if (!Builder.GetInsertBlock()->getTerminator()) 00437 Builder.CreateBr(bodyBB); 00438 00439 // Finally, set mergeBB as the current insertion point. 00440 Builder.SetInsertPoint(mergeBB); 00441 } 00442 00443 void CodeGenRoutine::emitRaiseStmt(RaiseStmt *stmt) 00444 { 00445 CommaRT &CRT = CG.getRuntime(); 00446 ExceptionDecl *exception = stmt->getExceptionDecl(); 00447 llvm::Value *fileName = CG.getModuleName(); 00448 llvm::Value *lineNum = CG.getSourceLine(stmt->getLocation()); 00449 00450 if (stmt->hasMessage()) { 00451 BoundsEmitter emitter(*this); 00452 CValue arrValue = emitArrayExpr(stmt->getMessage(), 0, false); 00453 llvm::Value *message; 00454 llvm::Value *length; 00455 00456 message = arrValue.first(); 00457 length = emitter.computeBoundLength(Builder, arrValue.second(), 0); 00458 CRT.raise(SRF, exception, fileName, lineNum, message, length); 00459 } 00460 else 00461 CRT.raise(SRF, exception, fileName, lineNum, 0, 0); 00462 } 00463 00464 void CodeGenRoutine::emitPragmaStmt(PragmaStmt *stmt) 00465 { 00466 // Currently, only pragma Assert is supported. 00467 Pragma *pragma = stmt->getPragma(); 00468 00469 switch (pragma->getKind()) { 00470 00471 default: 00472 assert(false && "Cannot codegen pragma yet!"); 00473 break; 00474 00475 case pragma::Assert: 00476 emitPragmaAssert(cast<PragmaAssert>(pragma)); 00477 break; 00478 }; 00479 }