00001
00002
00003
00004
00005
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
00098
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
00108 emitRecordExpr(expr, returnValue, false);
00109 }
00110 else if (targetTy->isFatAccessType()) {
00111
00112
00113 llvm::Value *res = emitValue(ret->getReturnExpr()).first();
00114 Builder.CreateStore(Builder.CreateLoad(res), returnValue);
00115 }
00116 else {
00117
00118
00119 llvm::Value *res = emitValue(ret->getReturnExpr()).first();
00120 Builder.CreateStore(res, returnValue);
00121 }
00122
00123
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
00143
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
00150
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
00162
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
00203
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
00224
00225 llvm::BasicBlock *mergeBB = SRF->makeBasicBlock("handler.merge");
00226 if (!Builder.GetInsertBlock()->getTerminator())
00227 Builder.CreateBr(mergeBB);
00228
00229
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
00256
00257 SRF->pushFrame(thenBB);
00258 emitStmt(ite->getConsequent());
00259 if (!Builder.GetInsertBlock()->getTerminator())
00260 Builder.CreateBr(mergeBB);
00261 SRF->popFrame();
00262
00263
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
00305
00306
00307 Builder.CreateBr(entryBB);
00308 Builder.SetInsertPoint(entryBB);
00309 CValue condition = emitValue(stmt->getCondition());
00310
00311
00312 Builder.CreateCondBr(condition.first(), bodyBB, mergeBB);
00313
00314
00315 Builder.SetInsertPoint(bodyBB);
00316 SRF->pushFrame(bodyBB);
00317 emitStmt(stmt->getBody());
00318 SRF->popFrame();
00319
00320
00321
00322 if (!Builder.GetInsertBlock()->getTerminator())
00323 Builder.CreateBr(entryBB);
00324
00325
00326 Builder.SetInsertPoint(mergeBB);
00327 }
00328
00329 void CodeGenRoutine::emitForStmt(ForStmt *loop)
00330 {
00331 llvm::Value *iter;
00332 llvm::Value *sentinal;
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
00351 if (loop->isReversed())
00352 std::swap(iter, sentinal);
00353
00354
00355
00356
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
00369
00370 iterSlot = SRF->createTemp(iterTy);
00371 Builder.CreateStore(iter, iterSlot);
00372
00373
00374
00375
00376
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
00384
00385
00386
00387
00388
00389 Builder.SetInsertPoint(entryBB);
00390 next = Builder.CreateLoad(iterSlot);
00391 pred = Builder.CreateICmpEQ(next, sentinal);
00392 Builder.CreateCondBr(pred, mergeBB, iterBB);
00393
00394
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
00404
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
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
00426 Builder.CreateBr(bodyBB);
00427 Builder.SetInsertPoint(bodyBB);
00428
00429
00430 SRF->pushFrame(bodyBB);
00431 emitStmt(stmt->getBody());
00432 SRF->popFrame();
00433
00434
00435
00436 if (!Builder.GetInsertBlock()->getTerminator())
00437 Builder.CreateBr(bodyBB);
00438
00439
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
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 }