00001 
00002 
00003 
00004 
00005 
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     
00117     
00118     
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     
00133     
00134     
00135     
00136     llvm::BasicBlock *constructBB = CG.makeBasicBlock("construct", ctor);
00137     llvm::IRBuilder<> builder(CG.getLLVMContext());
00138     builder.SetInsertPoint(constructBB);
00139 
00140     
00141     llvm::Value *instance = &(ctor->getArgumentList().front());
00142 
00143     
00144     llvm::Value *capsules =
00145         CRT.getDomainInstance()->loadLocalVec(builder, instance);
00146 
00147     
00148     
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     
00157     
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     
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         
00235         
00236         
00237         
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             
00255             
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             
00264             
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             
00276             
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     
00292     
00293     return CG.getNullPointer(getFieldType<ITable>());
00294 }
00295