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