This machine mirrors various open-source projects.
20 Gbit/s uplink.
If there are any issues or you want another project mirrored, please contact
mirror-service -=AT=- netcologne DOT de !
00001 //===-- codegen/Frame.cpp ------------------------------------- -*- C++ -*-===// 00002 // 00003 // This file is distributed under the MIT license. See LICENSE.txt for details. 00004 // 00005 // Copyright (C) 2009, Stephen Wilson 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 // If we are generating a function which is using the struct return calling 00102 // convention map the return value to the first parameter of this function. 00103 // If we are generating a vstack return we need not allocate a return value. 00104 // For simple calls, allocate a stack slot for the return value. 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 // Populate the lookup tables with this functions arguments. 00113 injectSubroutineArgs(CGR); 00114 00115 // Create the first implicit subframe. 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 // Iterate over the set of subframes and emit a stackrestore for each before 00184 // branching to the return block. However, ignore the first implicit 00185 // subframe since any stacksaves are redundant. 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 // If this function uses the SRet convention, name the return argument. 00200 if (SRI->hasSRet()) { 00201 argI->setName("return.arg"); 00202 ++argI; 00203 } 00204 00205 // The next argument is the instance structure. Name the arg "percent". 00206 argI->setName("percent"); 00207 implicitContext = argI++; 00208 00209 // For each formal argument, locate the corresponding llvm argument. This 00210 // is mostly a one-to-one mapping except when unconstrained arrays are 00211 // present, in which case there are two arguments (one to the array and one 00212 // to the bounds). 00213 // 00214 // Set the name of each argument to match the corresponding formal. 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 // Create the final return terminator. 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 // Move the return block to the very end of the function. Though by no 00321 // means necessary, this tweak does improve assembly readability a bit. 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