00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "CodeGenRoutine.h"
00010 #include "Frame.h"
00011
00012 using namespace comma;
00013 using namespace comma::activation;
00014 using llvm::dyn_cast;
00015
00016 activation::Property *SRFrame::ActivationEntry::find(activation::Tag tag)
00017 {
00018 typedef llvm::iplist<activation::Property>::iterator iterator;
00019 iterator I = plist.begin();
00020 iterator E = plist.end();
00021 for ( ; I != E; ++I) {
00022 if (I->getKind() == tag)
00023 return I;
00024 }
00025 return 0;
00026 }
00027
00028 SRFrame::Subframe::Subframe(SRFrame *SRF, Subframe *parent,
00029 llvm::BasicBlock *entryBB)
00030 : SRF(SRF),
00031 parent(parent),
00032 restorePtr(0),
00033 landingPad(0),
00034 entryBB(entryBB) { }
00035
00036 SRFrame::Subframe::~Subframe()
00037 {
00038 emitStackrestore();
00039 }
00040
00041 void SRFrame::Subframe::emitStacksave()
00042 {
00043 if (restorePtr)
00044 return;
00045
00046 llvm::Module *M;
00047 llvm::Function *stacksave;
00048 llvm::BasicBlock *savedBB;
00049 llvm::IRBuilder<> &Builder = SRF->getIRBuilder();
00050
00051 M = SRF->getSRInfo()->getLLVMModule();
00052 stacksave = llvm::Intrinsic::getDeclaration(M, llvm::Intrinsic::stacksave);
00053
00054 savedBB = Builder.GetInsertBlock();
00055 Builder.SetInsertPoint(entryBB, entryBB->begin());
00056 restorePtr = SRF->getIRBuilder().CreateCall(stacksave);
00057 Builder.SetInsertPoint(savedBB);
00058 }
00059
00060 void SRFrame::Subframe::emitStackrestore()
00061 {
00062 if (!restorePtr)
00063 return;
00064
00065 if (SRF->getIRBuilder().GetInsertBlock()->getTerminator())
00066 return;
00067
00068 llvm::Module *M;
00069 llvm::Function *restore;
00070
00071 M = SRF->getSRInfo()->getLLVMModule();
00072 restore = llvm::Intrinsic::getDeclaration(M, llvm::Intrinsic::stackrestore);
00073 SRF->getIRBuilder().CreateCall(restore, restorePtr);
00074 }
00075
00076 void SRFrame::Subframe::addLandingPad()
00077 {
00078 if (landingPad)
00079 return;
00080 landingPad = SRF->makeBasicBlock("landingpad");
00081 }
00082
00083 SRFrame::SRFrame(SRInfo *routineInfo,
00084 CodeGenRoutine &CGR, llvm::IRBuilder<> &Builder)
00085 : SRI(routineInfo),
00086 Builder(Builder),
00087 allocaBB(0),
00088 returnBB(0),
00089 currentSubframe(0),
00090 returnValue(0),
00091 implicitContext(0)
00092 {
00093 llvm::Module *M = SRI->getLLVMModule();
00094 llvm::LLVMContext &Ctx = M->getContext();
00095 llvm::Function *Fn = SRI->getLLVMFunction();
00096 allocaBB = llvm::BasicBlock::Create(Ctx, "alloca", Fn);
00097 returnBB = llvm::BasicBlock::Create(Ctx, "return", Fn);
00098
00099 Builder.SetInsertPoint(allocaBB);
00100
00101
00102
00103
00104
00105 if (SRI->isaFunction()) {
00106 if (SRI->hasSRet())
00107 returnValue = Fn->arg_begin();
00108 else if (!SRI->usesVRet())
00109 returnValue = createTemp(Fn->getReturnType());
00110 }
00111
00112
00113 injectSubroutineArgs(CGR);
00114
00115
00116 pushFrame(allocaBB);
00117 }
00118
00119 SRFrame::~SRFrame()
00120 {
00121 popFrame();
00122
00123 EntryMap::iterator I = entryTable.begin();
00124 EntryMap::iterator E = entryTable.end();
00125 for ( ; I != E; ++I)
00126 delete I->second;
00127 }
00128
00129 void SRFrame::stacksave()
00130 {
00131 currentSubframe->emitStacksave();
00132 }
00133
00134 void SRFrame::addLandingPad()
00135 {
00136 currentSubframe->addLandingPad();
00137 }
00138
00139 bool SRFrame::hasLandingPad()
00140 {
00141 return getLandingPad() != 0;
00142 }
00143
00144 llvm::BasicBlock *SRFrame::getLandingPad()
00145 {
00146 llvm::BasicBlock *lpad = 0;
00147 Subframe *cursor = currentSubframe;
00148 while (cursor) {
00149 if ((lpad = cursor->getLandingPad()))
00150 break;
00151 cursor = cursor->getParent();
00152 }
00153 return lpad;
00154 }
00155
00156 void SRFrame::removeLandingPad()
00157 {
00158 Subframe *cursor = currentSubframe;
00159 while (cursor) {
00160 if (cursor->getLandingPad()) {
00161 cursor->removeLandingPad();
00162 break;
00163 }
00164 cursor = cursor->getParent();
00165 }
00166 }
00167
00168 void SRFrame::pushFrame(llvm::BasicBlock *associatedBB)
00169 {
00170 currentSubframe = new Subframe(this, currentSubframe, associatedBB);
00171 }
00172
00173 void SRFrame::popFrame()
00174 {
00175 assert(currentSubframe && "Subframe imbalance!");
00176 Subframe *old = currentSubframe;
00177 currentSubframe = old->getParent();
00178 delete old;
00179 }
00180
00181 void SRFrame::emitReturn()
00182 {
00183
00184
00185
00186 Subframe *cursor;
00187 for (cursor = currentSubframe; cursor; cursor = cursor->getParent())
00188 if (cursor->getParent())
00189 cursor->emitStackrestore();
00190 Builder.CreateBr(returnBB);
00191 }
00192
00193 void SRFrame::injectSubroutineArgs(CodeGenRoutine &CGR)
00194 {
00195 SubroutineDecl *SRDecl = SRI->getDeclaration();
00196 llvm::Function *Fn = SRI->getLLVMFunction();
00197 llvm::Function::arg_iterator argI = Fn->arg_begin();
00198
00199
00200 if (SRI->hasSRet()) {
00201 argI->setName("return.arg");
00202 ++argI;
00203 }
00204
00205
00206 argI->setName("percent");
00207 implicitContext = argI++;
00208
00209
00210
00211
00212
00213
00214
00215 SubroutineDecl::const_param_iterator paramI = SRDecl->begin_params();
00216 SubroutineDecl::const_param_iterator paramE = SRDecl->end_params();
00217 for ( ; paramI != paramE; ++paramI, ++argI) {
00218 ParamValueDecl *param = *paramI;
00219 argI->setName(param->getString());
00220 associate(param, Slot, argI);
00221
00222 Type *paramTy = CGR.resolveType(param->getType());
00223 if (ArrayType *arrTy = dyn_cast<ArrayType>(paramTy)) {
00224 if (!arrTy->isConstrained()) {
00225 ++argI;
00226 std::string boundName(param->getString());
00227 boundName += ".bounds";
00228 argI->setName(boundName);
00229 associate(param, Bounds, argI);
00230 }
00231 }
00232 }
00233 }
00234
00235 llvm::Value *SRFrame::createTemp(const llvm::Type *type)
00236 {
00237 llvm::BasicBlock *savedBB = Builder.GetInsertBlock();
00238
00239 Builder.SetInsertPoint(allocaBB);
00240 llvm::Value *slot = Builder.CreateAlloca(type);
00241 Builder.SetInsertPoint(savedBB);
00242 return slot;
00243 }
00244
00245 void SRFrame::associate(const ValueDecl *decl, activation::Tag tag,
00246 llvm::Value *slot)
00247 {
00248 EntryMap::value_type &pair = entryTable.FindAndConstruct(decl);
00249 ActivationEntry *&entry = pair.second;
00250
00251 if (!entry)
00252 entry = new ActivationEntry();
00253 assert(!entry->find(tag) && "Decl aready associated with tag!");
00254
00255 entry->add(new Property(tag, slot));
00256 }
00257
00258 llvm::Value *SRFrame::lookup(const ValueDecl *decl, activation::Tag tag)
00259 {
00260 EntryMap::iterator iter = entryTable.find(decl);
00261
00262 if (iter != entryTable.end()) {
00263 ActivationEntry *entry = iter->second;
00264 if (Property *prop = entry->find(tag))
00265 return prop->getValue();
00266 }
00267 return 0;
00268 }
00269
00270 void SRFrame::associate(const PrimaryType *type, activation::Tag tag,
00271 llvm::Value *value)
00272 {
00273 assert(tag != activation::Slot && "Cannot associate types with slots!");
00274 EntryMap::value_type &pair = entryTable.FindAndConstruct(type);
00275 ActivationEntry *&entry = pair.second;
00276
00277 if (!entry)
00278 entry = new ActivationEntry();
00279 assert(!entry->find(tag) && "Type already associated with tag!");
00280
00281 entry->add(new Property(tag, value));
00282 }
00283
00284 llvm::Value *SRFrame::lookup(const PrimaryType *type, activation::Tag tag)
00285 {
00286 EntryMap::iterator iter = entryTable.find(type);
00287
00288 if (iter != entryTable.end()) {
00289 ActivationEntry *entry = iter->second;
00290 if (Property *prop = entry->find(tag))
00291 return prop->getValue();
00292 }
00293 return 0;
00294 }
00295
00296 void SRFrame::emitPrologue(llvm::BasicBlock *bodyBB)
00297 {
00298 llvm::BasicBlock *savedBB = Builder.GetInsertBlock();
00299 Builder.SetInsertPoint(allocaBB);
00300 Builder.CreateBr(bodyBB);
00301 Builder.SetInsertPoint(savedBB);
00302 }
00303
00304 void SRFrame::emitEpilogue()
00305 {
00306 llvm::Function *Fn = SRI->getLLVMFunction();
00307 llvm::BasicBlock *savedBB = Builder.GetInsertBlock();
00308
00309 assert(currentSubframe->getParent() == 0 && "Subframe imbalance!");
00310
00311
00312 Builder.SetInsertPoint(returnBB);
00313 if (returnValue && !SRI->hasSRet()) {
00314 llvm::Value *V = Builder.CreateLoad(returnValue);
00315 Builder.CreateRet(V);
00316 }
00317 else
00318 Builder.CreateRetVoid();
00319
00320
00321
00322 llvm::BasicBlock *lastBB = &Fn->back();
00323 if (returnBB != lastBB)
00324 returnBB->moveAfter(lastBB);
00325
00326 Builder.SetInsertPoint(savedBB);
00327 }
00328
00329 llvm::BasicBlock *SRFrame::makeBasicBlock(const std::string &name,
00330 llvm::BasicBlock *insertBefore)
00331 {
00332 llvm::Function *fn = getLLVMFunction();
00333 llvm::LLVMContext &ctx = fn->getContext();
00334 return llvm::BasicBlock::Create(ctx, name, fn, insertBefore);
00335 }
00336