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/CodeGenCapsule.h"
00013 #include "comma/codegen/CodeGenRoutine.h"
00014 #include "comma/codegen/CodeGenTypes.h"
00015
00016 #include "llvm/Analysis/Verifier.h"
00017
00018 using namespace comma;
00019
00020 using llvm::dyn_cast;
00021 using llvm::dyn_cast_or_null;
00022 using llvm::cast;
00023 using llvm::isa;
00024
00025 CodeGenRoutine::CodeGenRoutine(CodeGenCapsule &CGC)
00026 : CGC(CGC),
00027 CG(CGC.getCodeGen()),
00028 CGTypes(CG.getTypeGenerator()),
00029 CRT(CG.getRuntime()),
00030 SRDecl(0),
00031 SRFn(0),
00032 entryBB(0),
00033 returnBB(0),
00034 returnValue(0) { }
00035
00036 void CodeGenRoutine::declareSubroutine(SubroutineDecl *srDecl)
00037 {
00038 getOrCreateSubroutineDeclaration(srDecl);
00039 }
00040
00041 llvm::Function *
00042 CodeGenRoutine::getOrCreateSubroutineDeclaration(SubroutineDecl *srDecl)
00043 {
00044 const llvm::FunctionType *srTy = CGTypes.lowerType(srDecl->getType());
00045 std::string srName = CG.getLinkName(srDecl);
00046
00047 llvm::Function *fn =
00048 dyn_cast_or_null<llvm::Function>(CG.lookupGlobal(srName));
00049
00050 if (!fn) {
00051 fn = CG.makeFunction(srTy, srName);
00052 CG.insertGlobal(srName, fn);
00053 }
00054
00055 return fn;
00056 }
00057
00058 void CodeGenRoutine::emitSubroutine(SubroutineDecl *srDecl)
00059 {
00060
00061 SRDecl = srDecl;
00062
00063
00064 SRFn = getOrCreateSubroutineDeclaration(srDecl);
00065
00066
00067 if (SRDecl->getDefiningDeclaration())
00068 SRDecl = SRDecl->getDefiningDeclaration();
00069
00070 injectSubroutineArgs();
00071 emitSubroutineBody();
00072 llvm::verifyFunction(*SRFn);
00073 }
00074
00076 void CodeGenRoutine::emitSubroutineBody()
00077 {
00078
00079 returnBB = llvm::BasicBlock::Create("return", SRFn);
00080
00081
00082
00083 entryBB = llvm::BasicBlock::Create("entry", SRFn, returnBB);
00084 Builder.SetInsertPoint(entryBB);
00085
00086
00087
00088 if (isa<FunctionDecl>(SRDecl))
00089 returnValue = Builder.CreateAlloca(SRFn->getReturnType());
00090
00091
00092
00093 llvm::BasicBlock *bodyBB = emitBlockStmt(SRDecl->getBody(), entryBB);
00094 if (!Builder.GetInsertBlock()->getTerminator())
00095 Builder.CreateBr(returnBB);
00096
00097 emitPrologue(bodyBB);
00098 emitEpilogue();
00099 }
00100
00106 void CodeGenRoutine::injectSubroutineArgs()
00107 {
00108
00109 llvm::Function::arg_iterator iter = SRFn->arg_begin();
00110 percent = iter++;
00111
00112
00113
00114 for (unsigned i = 0; iter != SRFn->arg_end(); ++iter, ++i) {
00115 ParamValueDecl *param = SRDecl->getParam(i);
00116 iter->setName(param->getString());
00117 declTable[param] = iter;
00118 }
00119 }
00120
00121 void CodeGenRoutine::emitPrologue(llvm::BasicBlock *bodyBB)
00122 {
00123
00124
00125
00126 llvm::BasicBlock *savedBB = Builder.GetInsertBlock();
00127
00128 Builder.SetInsertPoint(entryBB);
00129 Builder.CreateBr(bodyBB);
00130 Builder.SetInsertPoint(savedBB);
00131 }
00132
00133 void CodeGenRoutine::emitEpilogue()
00134 {
00135 llvm::BasicBlock *savedBB = Builder.GetInsertBlock();
00136
00137 Builder.SetInsertPoint(returnBB);
00138 if (returnValue) {
00139 llvm::Value *V = Builder.CreateLoad(returnValue);
00140 Builder.CreateRet(V);
00141 }
00142 else
00143 Builder.CreateRetVoid();
00144 Builder.SetInsertPoint(savedBB);
00145 }
00146
00147 llvm::Value *CodeGenRoutine::lookupDecl(Decl *decl)
00148 {
00149 DeclMap::iterator iter = declTable.find(decl);
00150
00151 if (iter != declTable.end())
00152 return iter->second;
00153 return 0;
00154 }
00155
00156 bool CodeGenRoutine::isDirectCall(const FunctionCallExpr *expr)
00157 {
00158 const FunctionDecl *decl = dyn_cast<FunctionDecl>(expr->getConnective());
00159 if (decl) {
00160 const DeclRegion *region = decl->getDeclRegion();
00161 return isa<DomainInstanceDecl>(region);
00162 }
00163 return false;
00164 }
00165
00166 bool CodeGenRoutine::isDirectCall(const ProcedureCallStmt *stmt)
00167 {
00168 const ProcedureDecl *pdecl = stmt->getConnective();
00169 const DeclRegion *region = pdecl->getDeclRegion();
00170 return isa<DomainInstanceDecl>(region);
00171 }
00172
00173 bool CodeGenRoutine::isLocalCall(const FunctionCallExpr *expr)
00174 {
00175 const FunctionDecl *decl = dyn_cast<FunctionDecl>(expr->getConnective());
00176 if (decl) {
00177
00178
00179
00180
00181 const DeclRegion *region = decl->getDeclRegion();
00182 return isa<AddDecl>(region);
00183 }
00184 return false;
00185 }
00186
00187 bool CodeGenRoutine::isLocalCall(const ProcedureCallStmt *stmt)
00188 {
00189
00190
00191
00192
00193 const ProcedureDecl *pdecl = stmt->getConnective();
00194 const DeclRegion *region = pdecl->getDeclRegion();
00195 return isa<AddDecl>(region);
00196 }
00197
00198 void CodeGenRoutine::emitObjectDecl(ObjectDecl *objDecl)
00199 {
00200 llvm::Value *stackSlot = createStackSlot(objDecl);
00201
00202 if (objDecl->hasInitializer()) {
00203 llvm::Value *init = emitExpr(objDecl->getInitializer());
00204 Builder.CreateStore(init, stackSlot);
00205 }
00206 }
00207
00208 llvm::Value *CodeGenRoutine::emitScalarLoad(llvm::Value *ptr)
00209 {
00210 return Builder.CreateLoad(ptr);
00211 }
00212
00213 llvm::Value *CodeGenRoutine::getStackSlot(Decl *decl)
00214 {
00215
00216
00217
00218
00219 llvm::Value *stackSlot = lookupDecl(decl);
00220 assert(stackSlot && "Lookup failed!");
00221 return stackSlot;
00222 }
00223
00224 llvm::Value *CodeGenRoutine::createStackSlot(Decl *decl)
00225 {
00226 assert(lookupDecl(decl) == 0 &&
00227 "Cannot create stack slot for preexisting decl!");
00228
00229
00230
00231 ValueDecl *vDecl = cast<ValueDecl>(decl);
00232 const llvm::Type *type = CGTypes.lowerType(vDecl->getType());
00233 llvm::BasicBlock *savedBB = Builder.GetInsertBlock();
00234
00235 Builder.SetInsertPoint(entryBB);
00236 llvm::Value *stackSlot = Builder.CreateAlloca(type);
00237 declTable[decl] = stackSlot;
00238 Builder.SetInsertPoint(savedBB);
00239 return stackSlot;
00240 }
00241
00242 llvm::Value *CodeGenRoutine::getOrCreateStackSlot(Decl *decl)
00243 {
00244 if (llvm::Value *stackSlot = lookupDecl(decl))
00245 return stackSlot;
00246 else
00247 return createStackSlot(decl);
00248 }
00249
00250 llvm::Value *CodeGenRoutine::emitVariableReference(Expr *expr)
00251 {
00252
00253
00254 DeclRefExpr *refExpr = cast<DeclRefExpr>(expr);
00255 Decl *refDecl = refExpr->getDeclaration();
00256
00257 if (ParamValueDecl *pvDecl = dyn_cast<ParamValueDecl>(refDecl)) {
00258 PM::ParameterMode paramMode = pvDecl->getParameterMode();
00259
00260
00261
00262 assert((paramMode == PM::MODE_OUT or paramMode == PM::MODE_IN_OUT) &&
00263 "Cannot take reference to a parameter with mode IN!");
00264
00265 return lookupDecl(pvDecl);
00266 }
00267
00268 if (ObjectDecl *objDecl = dyn_cast<ObjectDecl>(refDecl)) {
00269
00270
00271 return getStackSlot(objDecl);
00272 }
00273
00274 assert(false && "Cannot codegen reference for expression!");
00275 }
00276
00277 llvm::Value *CodeGenRoutine::emitValue(Expr *expr)
00278 {
00279 if (DeclRefExpr *refExpr = dyn_cast<DeclRefExpr>(expr)) {
00280 Decl *refDecl = refExpr->getDeclaration();
00281
00282 if (ParamValueDecl *pvDecl = dyn_cast<ParamValueDecl>(refDecl)) {
00283
00284
00285 llvm::Value *param = lookupDecl(pvDecl);
00286 PM::ParameterMode paramMode = pvDecl->getParameterMode();
00287
00288 if (paramMode == PM::MODE_OUT or paramMode == PM::MODE_IN_OUT)
00289 return Builder.CreateLoad(param);
00290 else
00291 return param;
00292 }
00293
00294
00295
00296 ObjectDecl *objDecl = cast<ObjectDecl>(refDecl);
00297 llvm::Value *stackSlot = lookupDecl(objDecl);
00298 return Builder.CreateLoad(stackSlot);
00299 }
00300
00301
00302 return emitExpr(expr);
00303 }