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/DomainInfo.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 "CommaRT.h" 00010 #include "DependencySet.h" 00011 #include "DomainInfo.h" 00012 #include "DomainInstance.h" 00013 #include "comma/ast/SignatureSet.h" 00014 #include "comma/codegen/Mangle.h" 00015 00016 #include "llvm/ADT/IndexedMap.h" 00017 #include "llvm/Support/Casting.h" 00018 #include "llvm/DerivedTypes.h" 00019 00020 using namespace comma; 00021 00022 using llvm::dyn_cast; 00023 using llvm::cast; 00024 using llvm::isa; 00025 00026 DomainInfo::DomainInfo(CommaRT &CRT) 00027 : CRT(CRT), 00028 CG(CRT.getCodeGen()), 00029 TD(CG.getTargetData()), 00030 theType(CG.getOpaqueTy()) { } 00031 00032 void DomainInfo::init() 00033 { 00034 std::vector<const llvm::Type*> members; 00035 00036 members.push_back(CG.getInt32Ty()); 00037 members.push_back(CG.getPointerType(CG.getInt8Ty())); 00038 members.push_back(CRT.getType<CommaRT::CRT_DomainCtor>()); 00039 members.push_back(CRT.getType<CommaRT::CRT_ITable>()); 00040 00041 llvm::StructType *InfoTy = CG.getStructTy(members); 00042 cast<llvm::OpaqueType>(theType.get())->refineAbstractTypeTo(InfoTy); 00043 } 00044 00045 const std::string DomainInfo::theTypeName("comma_domain_info_t"); 00046 00047 const llvm::StructType *DomainInfo::getType() const 00048 { 00049 return cast<llvm::StructType>(theType.get()); 00050 } 00051 00052 const llvm::PointerType *DomainInfo::getPointerTypeTo() const 00053 { 00054 return llvm::PointerType::getUnqual(theType.get()); 00055 } 00056 00057 const llvm::PointerType *DomainInfo::getCtorPtrType() const 00058 { 00059 std::vector<const llvm::Type*> args; 00060 const llvm::Type *ctorTy; 00061 00062 args.push_back(CRT.getType<CommaRT::CRT_DomainInstance>()); 00063 00064 ctorTy = llvm::FunctionType::get(CG.getVoidTy(), args, false); 00065 return CG.getPointerType(ctorTy); 00066 } 00067 00068 llvm::GlobalVariable *DomainInfo::emit(const Domoid *domoid) 00069 { 00070 std::vector<llvm::Constant *> elts; 00071 00072 elts.push_back(genArity(domoid)); 00073 elts.push_back(genName(domoid)); 00074 elts.push_back(genConstructor(domoid)); 00075 elts.push_back(genITable(domoid)); 00076 00077 llvm::Constant *theInfo = llvm::ConstantStruct::get(getType(), elts); 00078 return CG.makeExternGlobal(theInfo, false, mangle::getLinkName(domoid)); 00079 } 00080 00081 std::string DomainInfo::getLinkName(const Domoid *domoid) 00082 { 00083 return mangle::getLinkName(domoid) + "__0domain_info"; 00084 } 00085 00086 std::string DomainInfo::getCtorName(const Domoid *domoid) 00087 { 00088 return mangle::getLinkName(domoid) + "__0ctor"; 00089 } 00090 00092 llvm::Constant *DomainInfo::genName(const Domoid *domoid) 00093 { 00094 const llvm::PointerType *NameTy = getFieldType<Name>(); 00095 00096 llvm::Constant *capsuleName = CG.emitInternString(domoid->getString()); 00097 return CG.getPointerCast(capsuleName, NameTy); 00098 } 00099 00101 llvm::Constant *DomainInfo::genArity(const Domoid *domoid) 00102 { 00103 const llvm::IntegerType *ArityTy = getFieldType<Arity>(); 00104 00105 if (const FunctorDecl *functor = dyn_cast<FunctorDecl>(domoid)) 00106 return llvm::ConstantInt::get(ArityTy, functor->getArity()); 00107 else 00108 return llvm::ConstantInt::get(ArityTy, 0); 00109 } 00110 00112 llvm::Constant *DomainInfo::genConstructor(const Domoid *domoid) 00113 { 00114 const DependencySet &DS = CG.getDependencySet(domoid); 00115 00116 // If the capsule in question does not have any dependencies, do not build a 00117 // function -- just return 0. The runtime will not call thru null 00118 // constructors. 00119 if (DS.size() == 0) 00120 return CG.getNullPointer(getFieldType<Ctor>()); 00121 00122 std::string ctorName = getCtorName(domoid); 00123 const llvm::FunctionType *ctorTy; 00124 llvm::Function *ctor; 00125 00126 ctorTy = cast<llvm::FunctionType>( 00127 CRT.getType<CommaRT::CRT_DomainCtor>()->getElementType()); 00128 ctor = CG.makeInternFunction(ctorTy, ctorName); 00129 00130 CG.insertGlobal(ctorName, ctor); 00131 00132 // Create a basic block to hold a sequence of get_domain calls which 00133 // populates the "required capsules" vector with the needed instances. Once 00134 // we have generated this block, we will generate code to allocate an 00135 // appropriately sized array. 00136 llvm::BasicBlock *constructBB = CG.makeBasicBlock("construct", ctor); 00137 llvm::IRBuilder<> builder(CG.getLLVMContext()); 00138 builder.SetInsertPoint(constructBB); 00139 00140 // The first (and only) argument of the constructor is a domain_instance_t. 00141 llvm::Value *instance = &(ctor->getArgumentList().front()); 00142 00143 // Extract a pointer to the "required capsules" array. 00144 llvm::Value *capsules = 00145 CRT.getDomainInstance()->loadLocalVec(builder, instance); 00146 00147 // Iterate over the set of capsule dependencies and emit calls to 00148 // get_domain for each, keeping track of the number of dependents. 00149 typedef DependencySet::iterator iterator; 00150 iterator E = DS.end(); 00151 for (iterator I = DS.begin(); I != E; ++I) { 00152 unsigned ID = DS.getDependentID(I); 00153 genInstanceRequirement(builder, DS, ID, capsules, instance); 00154 } 00155 00156 // Now that we have the full size of the vector, allocate an array of 00157 // sufficient size to accommodate all the required instances. 00158 llvm::BasicBlock *initBB = CG.makeBasicBlock("init", ctor, constructBB); 00159 builder.SetInsertPoint(initBB); 00160 00161 llvm::Value *size = llvm::ConstantInt::get(CG.getInt32Ty(), DS.size()); 00162 capsules = builder.CreateMalloc(CRT.getType<CommaRT::CRT_DomainInstance>(), size); 00163 CRT.getDomainInstance()->setLocalVec(builder, instance, capsules); 00164 builder.CreateBr(constructBB); 00165 00166 // Generate a return. 00167 builder.SetInsertPoint(constructBB); 00168 builder.CreateRetVoid(); 00169 00170 return ctor; 00171 } 00172 00180 void DomainInfo::genInstanceRequirement(llvm::IRBuilder<> &builder, 00181 const DependencySet &DS, 00182 unsigned ID, 00183 llvm::Value *destVector, 00184 llvm::Value *percent) 00185 { 00186 const DomainInstanceDecl *instance = DS.getDependent(ID); 00187 const Domoid *domoid = instance->getDefinition(); 00188 00189 if (isa<DomainDecl>(domoid)) 00190 genDomainRequirement(builder, DS, ID, destVector); 00191 else 00192 genFunctorRequirement(builder, DS, ID, destVector, percent); 00193 } 00194 00199 void DomainInfo::genDomainRequirement(llvm::IRBuilder<> &builder, 00200 const DependencySet &DS, 00201 unsigned ID, 00202 llvm::Value *destVector) 00203 { 00204 const DomainInstanceDecl *instance = DS.getDependent(ID); 00205 const DomainDecl *domain = instance->getDefiningDomain(); 00206 assert(domain && "Cannot gen requirement for this type of instance!"); 00207 00208 llvm::GlobalValue *info = CG.lookupCapsuleInfo(domain); 00209 assert(info && "Could not resolve capsule info!"); 00210 00211 llvm::Value *ptr = CRT.getDomain(builder, info); 00212 llvm::Value *slotIndex = llvm::ConstantInt::get(CG.getInt32Ty(), ID); 00213 builder.CreateStore(ptr, builder.CreateGEP(destVector, slotIndex)); 00214 } 00215 00220 void DomainInfo::genFunctorRequirement(llvm::IRBuilder<> &builder, 00221 const DependencySet &DS, 00222 unsigned ID, 00223 llvm::Value *destVector, 00224 llvm::Value *percent) 00225 { 00226 const DomainInstanceDecl *instance = DS.getDependent(ID); 00227 const FunctorDecl *functor = instance->getDefiningFunctor(); 00228 assert(functor && "Cannot gen requirement for this type of instance!"); 00229 00230 const DomainInstance *DInstance = CRT.getDomainInstance(); 00231 00232 llvm::Value *info = CG.lookupCapsuleInfo(functor); 00233 if (!info) { 00234 // The only case where the lookup can fail is when the functor being 00235 // applied is the current capsule for which we are generating a 00236 // constructor for. Fortunately, the runtime provides this info via 00237 // this instances percent node. 00238 assert(functor == cast<FunctorDecl>(DS.getCapsule()) && 00239 "Could not resolve capsule info!"); 00240 info = DInstance->loadInfo(builder, percent); 00241 } 00242 00243 std::vector<llvm::Value *> arguments; 00244 arguments.push_back(info); 00245 00246 for (unsigned i = 0; i < instance->getArity(); ++i) { 00247 const DomainType *argTy = cast<DomainType>(instance->getActualParamType(i)); 00248 00249 if (const PercentDecl *pdecl = argTy->getPercentDecl()) { 00250 assert(pdecl->getDefinition() == DS.getCapsule() && 00251 "Percent node does not represent the current domain!"); 00252 ((void*)pdecl); 00253 00254 // The argument to this functor is %. Simply push the given percent 00255 // value onto get_domains argument list. 00256 arguments.push_back(percent); 00257 } 00258 else if (const DomainInstanceDecl *arg = argTy->getInstanceDecl()) { 00259 DependencySet::iterator argPos = DS.find(arg); 00260 assert(argPos != DS.end() && "Dependency lookup failed!"); 00261 unsigned argIndex = DS.getDependentID(argPos); 00262 00263 // Load the instance from the destination vector and push it onto 00264 // the argument list. 00265 llvm::Value *instanceSlot = 00266 llvm::ConstantInt::get(CG.getInt32Ty(), argIndex); 00267 llvm::Value *argInstance = 00268 builder.CreateLoad(builder.CreateGEP(destVector, instanceSlot)); 00269 arguments.push_back(argInstance); 00270 } 00271 else { 00272 const AbstractDomainDecl *arg = argTy->getAbstractDecl(); 00273 unsigned paramIdx = DS.getCapsule()->getFormalIndex(arg); 00274 00275 // Load the instance corresponding to the formal parameter and push 00276 // as an argument. 00277 llvm::Value *param = DInstance->loadParam(builder, percent, paramIdx); 00278 arguments.push_back(param); 00279 } 00280 } 00281 00282 llvm::Value *theInstance = CRT.getDomain(builder, arguments); 00283 llvm::Value *slotIndex = llvm::ConstantInt::get(CG.getInt32Ty(), ID); 00284 builder.CreateStore(theInstance, builder.CreateGEP(destVector, slotIndex)); 00285 } 00286 00287 00289 llvm::Constant *DomainInfo::genITable(const Domoid *domoid) 00290 { 00291 // Initially the instance table is always null. A table is allocated at 00292 // runtime when needed. 00293 return CG.getNullPointer(getFieldType<ITable>()); 00294 } 00295