00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "comma/ast/Decl.h"
00010 #include "comma/ast/Expr.h"
00011 #include "comma/ast/Stmt.h"
00012 #include "comma/codegen/CodeGenRoutine.h"
00013 #include "comma/codegen/CodeGenTypes.h"
00014 #include "comma/codegen/CommaRT.h"
00015
00016 using namespace comma;
00017
00018 using llvm::dyn_cast;
00019 using llvm::cast;
00020 using llvm::isa;
00021
00022 void CodeGenRoutine::emitStmt(Stmt *stmt)
00023 {
00024 switch (stmt->getKind()) {
00025
00026 default:
00027 assert(false && "Cannot codegen stmt yet!");
00028
00029 case Ast::AST_ProcedureCallStmt:
00030 emitProcedureCallStmt(cast<ProcedureCallStmt>(stmt));
00031 break;
00032
00033 case Ast::AST_AssignmentStmt:
00034 emitAssignmentStmt(cast<AssignmentStmt>(stmt));
00035 break;
00036
00037 case Ast::AST_StmtSequence:
00038 emitStmtSequence(cast<StmtSequence>(stmt));
00039 break;
00040
00041 case Ast::AST_BlockStmt:
00042 emitBlockStmt(cast<BlockStmt>(stmt));
00043 break;
00044
00045 case Ast::AST_IfStmt:
00046 emitIfStmt(cast<IfStmt>(stmt));
00047 break;
00048
00049 case Ast::AST_ReturnStmt:
00050 emitReturnStmt(cast<ReturnStmt>(stmt));
00051 break;
00052 }
00053 }
00054
00055 void CodeGenRoutine::emitReturnStmt(ReturnStmt *ret)
00056 {
00057 if (ret->hasReturnExpr()) {
00058
00059 assert(returnValue && "Non-empty return from function!");
00060 llvm::Value *res = emitValue(ret->getReturnExpr());
00061 Builder.CreateStore(res, returnValue);
00062 Builder.CreateBr(returnBB);
00063 }
00064 else {
00065
00066
00067 assert(returnValue == 0 && "Empty return from function!");
00068 Builder.CreateBr(returnBB);
00069 }
00070 }
00071
00072 void CodeGenRoutine::emitStmtSequence(StmtSequence *seq)
00073 {
00074 for (StmtSequence::StmtIter iter = seq->beginStatements();
00075 iter != seq->endStatements(); ++iter)
00076 emitStmt(*iter);
00077 }
00078
00079 llvm::BasicBlock *CodeGenRoutine::emitBlockStmt(BlockStmt *block,
00080 llvm::BasicBlock *predecessor)
00081 {
00082 assert(block && "NULL block statement!");
00083 std::string label;
00084
00085 if (block->hasLabel())
00086 label = block->getLabel()->getString();
00087
00088 llvm::BasicBlock *BB = llvm::BasicBlock::Create(label, SRFn);
00089
00090 if (predecessor == 0) {
00091
00092
00093 predecessor = Builder.GetInsertBlock();
00094
00095 assert(!predecessor->getTerminator() &&
00096 "Current insertion block already terminated!");
00097 Builder.CreateBr(BB);
00098 }
00099
00100 BB->moveAfter(predecessor);
00101 Builder.SetInsertPoint(BB);
00102
00103
00104
00105 typedef DeclRegion::DeclIter iterator;
00106 for (iterator I = block->beginDecls(); I != block->endDecls(); ++I)
00107 if (ObjectDecl *objDecl = dyn_cast<ObjectDecl>(*I))
00108 emitObjectDecl(objDecl);
00109 emitStmtSequence(block);
00110 return BB;
00111 }
00112
00113 void CodeGenRoutine::emitIfStmt(IfStmt *ite)
00114 {
00115 llvm::Value *condition = emitExpr(ite->getCondition());
00116 llvm::BasicBlock *thenBB = llvm::BasicBlock::Create("then", SRFn);
00117 llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create("merge", SRFn);
00118 llvm::BasicBlock *elseBB;
00119
00120 if (ite->hasElsif())
00121 elseBB = llvm::BasicBlock::Create("elsif", SRFn);
00122 else if (ite->hasAlternate())
00123 elseBB = llvm::BasicBlock::Create("else", SRFn);
00124 else
00125 elseBB = mergeBB;
00126
00127 Builder.CreateCondBr(condition, thenBB, elseBB);
00128 Builder.SetInsertPoint(thenBB);
00129 emitStmt(ite->getConsequent());
00130
00131
00132
00133 if (!Builder.GetInsertBlock()->getTerminator())
00134 Builder.CreateBr(mergeBB);
00135
00136 for (IfStmt::iterator I = ite->beginElsif(); I != ite->endElsif(); ++I) {
00137 Builder.SetInsertPoint(elseBB);
00138 IfStmt::iterator J = I;
00139 if (++J != ite->endElsif())
00140 elseBB = llvm::BasicBlock::Create("elsif", SRFn);
00141 else if (ite->hasAlternate())
00142 elseBB = llvm::BasicBlock::Create("else", SRFn);
00143 else
00144 elseBB = mergeBB;
00145 llvm::BasicBlock *bodyBB = llvm::BasicBlock::Create("body", SRFn);
00146 llvm::Value *pred = emitExpr(I->getCondition());
00147 Builder.CreateCondBr(pred, bodyBB, elseBB);
00148 Builder.SetInsertPoint(bodyBB);
00149 emitStmt(I->getConsequent());
00150 if (!Builder.GetInsertBlock()->getTerminator())
00151 Builder.CreateBr(mergeBB);
00152 }
00153
00154 if (ite->hasAlternate()) {
00155 Builder.SetInsertPoint(elseBB);
00156 emitStmt(ite->getAlternate());
00157 if (!Builder.GetInsertBlock()->getTerminator())
00158 Builder.CreateBr(mergeBB);
00159 }
00160
00161 Builder.SetInsertPoint(mergeBB);
00162 }
00163
00164 void CodeGenRoutine::emitProcedureCallStmt(ProcedureCallStmt *stmt)
00165 {
00166 ProcedureDecl *pdecl = stmt->getConnective();
00167 std::vector<llvm::Value *> args;
00168
00169 for (unsigned i = 0; i < stmt->getNumArgs(); ++i) {
00170 Expr *arg = stmt->getArg(i);
00171 args.push_back(emitCallArgument(pdecl, arg, i));
00172 }
00173
00174 if (isLocalCall(stmt))
00175 emitLocalCall(pdecl, args);
00176 else if (isDirectCall(stmt))
00177 emitDirectCall(pdecl, args);
00178 else
00179 CRT.genAbstractCall(Builder, percent, pdecl, args);
00180 }
00181
00182 void CodeGenRoutine::emitAssignmentStmt(AssignmentStmt *stmt)
00183 {
00184 llvm::Value *ref = emitVariableReference(stmt->getTarget());
00185 llvm::Value *rhs = emitValue(stmt->getAssignedExpr());
00186
00187 Builder.CreateStore(rhs, ref);
00188 }