00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "ExportMap.h"
00010 #include "DomainInfo.h"
00011 #include "DomainInstance.h"
00012 #include "DomainView.h"
00013 #include "comma/ast/SignatureSet.h"
00014 #include "comma/codegen/CodeGenCapsule.h"
00015 #include "comma/codegen/CommaRT.h"
00016
00017 #include "llvm/ADT/IndexedMap.h"
00018 #include "llvm/Support/Casting.h"
00019 #include "llvm/DerivedTypes.h"
00020
00021 using namespace comma;
00022
00023 using llvm::dyn_cast;
00024 using llvm::cast;
00025 using llvm::isa;
00026
00027 DomainInfo::DomainInfo(CommaRT &CRT)
00028 : CRT(CRT),
00029 CG(CRT.getCodeGen()),
00030 TD(CG.getTargetData()),
00031 theType(llvm::OpaqueType::get()) { }
00032
00033 void DomainInfo::init()
00034 {
00035 std::vector<const llvm::Type*> members;
00036 const llvm::Type* IntPtrTy = TD.getIntPtrType();
00037
00038 members.push_back(llvm::Type::Int32Ty);
00039 members.push_back(llvm::Type::Int32Ty);
00040 members.push_back(CG.getPointerType(llvm::Type::Int8Ty));
00041 members.push_back(CRT.getType<CommaRT::CRT_DomainCtor>());
00042 members.push_back(CRT.getType<CommaRT::CRT_ITable>());
00043 members.push_back(CG.getPointerType(IntPtrTy));
00044 members.push_back(CG.getPointerType(CRT.getType<CommaRT::CRT_ExportFn>()));
00045
00046 llvm::StructType *InfoTy = llvm::StructType::get(members);
00047 cast<llvm::OpaqueType>(theType.get())->refineAbstractTypeTo(InfoTy);
00048 }
00049
00050 const std::string DomainInfo::theTypeName("comma_domain_info_t");
00051
00052 const llvm::StructType *DomainInfo::getType() const
00053 {
00054 return cast<llvm::StructType>(theType.get());
00055 }
00056
00057 const llvm::PointerType *DomainInfo::getPointerTypeTo() const
00058 {
00059 return llvm::PointerType::getUnqual(theType.get());
00060 }
00061
00062 const llvm::PointerType *DomainInfo::getCtorPtrType() const
00063 {
00064 std::vector<const llvm::Type*> args;
00065 const llvm::Type *ctorTy;
00066
00067 args.push_back(CRT.getType<CommaRT::CRT_DomainInstance>());
00068
00069 ctorTy = llvm::FunctionType::get(llvm::Type::VoidTy, args, false);
00070 return CG.getPointerType(ctorTy);
00071 }
00072
00073 llvm::GlobalVariable *DomainInfo::generateInstance(CodeGenCapsule &CGC)
00074 {
00075 std::vector<llvm::Constant *> elts;
00076
00077 elts.push_back(genArity(CGC));
00078 elts.push_back(genSignatureCount(CGC));
00079 elts.push_back(genName(CGC));
00080 elts.push_back(genConstructor(CGC));
00081 elts.push_back(genITable(CGC));
00082 elts.push_back(genSignatureOffsets(CGC));
00083 elts.push_back(genExportArray(CGC));
00084
00085 llvm::Constant *theInfo = llvm::ConstantStruct::get(getType(), elts);
00086 return CG.makeExternGlobal(theInfo, false, getLinkName(CGC));
00087 }
00088
00089 std::string DomainInfo::getLinkName(const CodeGenCapsule &CGC) const
00090 {
00091 return CGC.getLinkName() + "__0domain_info";
00092 }
00093
00095 llvm::Constant *DomainInfo::genName(CodeGenCapsule &CGC)
00096 {
00097 Domoid *theCapsule = CGC.getCapsule();
00098 const llvm::PointerType *NameTy = getFieldType<Name>();
00099
00100 llvm::Constant *capsuleName = CG.emitStringLiteral(theCapsule->getString());
00101 return CG.getPointerCast(capsuleName, NameTy);
00102 }
00103
00105 llvm::Constant *DomainInfo::genArity(CodeGenCapsule &CGC)
00106 {
00107 Domoid *theCapsule = CGC.getCapsule();
00108 const llvm::IntegerType *ArityTy = getFieldType<Arity>();
00109
00110 if (FunctorDecl *functor = dyn_cast<FunctorDecl>(theCapsule))
00111 return llvm::ConstantInt::get(ArityTy, functor->getArity());
00112 else
00113 return llvm::ConstantInt::get(ArityTy, 0);
00114 }
00115
00117 llvm::Constant *DomainInfo::genSignatureCount(CodeGenCapsule &CGC)
00118 {
00119 Domoid *theCapsule = CGC.getCapsule();
00120 SignatureSet &sigSet = theCapsule->getSignatureSet();
00121 const llvm::Type *intTy = getFieldType<NumSigs>();
00122
00123 return llvm::ConstantInt::get(intTy, sigSet.numSignatures());
00124 }
00125
00127 llvm::Constant *DomainInfo::genConstructor(CodeGenCapsule &CGC)
00128 {
00129
00130
00131
00132 if (CGC.dependencyCount() == 0)
00133 return CG.getNullPointer(getFieldType<Ctor>());
00134
00135 std::string ctorName = CGC.getLinkName() + "__0ctor";
00136 const llvm::FunctionType *ctorTy;
00137 llvm::Function *ctor;
00138
00139 ctorTy = cast<llvm::FunctionType>(
00140 CRT.getType<CommaRT::CRT_DomainCtor>()->getElementType());
00141 ctor = CG.makeInternFunction(ctorTy, ctorName);
00142
00143 CG.insertGlobal(ctorName, ctor);
00144
00145
00146
00147
00148
00149 llvm::BasicBlock *constructBB = llvm::BasicBlock::Create("construct", ctor);
00150 llvm::IRBuilder<> builder;
00151 builder.SetInsertPoint(constructBB);
00152
00153
00154 llvm::Value *instance = &(ctor->getArgumentList().front());
00155
00156
00157 llvm::Value *capsules = builder.CreateStructGEP(instance, 4);
00158 capsules = builder.CreateLoad(capsules);
00159
00160
00161
00162 unsigned numDependents = CGC.dependencyCount();
00163 for (unsigned ID = 1; ID <= numDependents; ++ID)
00164 genInstanceRequirement(builder, CGC, ID, capsules, instance);
00165
00166
00167
00168 llvm::BasicBlock *initBB = llvm::BasicBlock::Create("init", ctor, constructBB);
00169 builder.SetInsertPoint(initBB);
00170
00171 llvm::Value *size =
00172 llvm::ConstantInt::get(llvm::Type::Int32Ty, numDependents);
00173 capsules = builder.CreateMalloc(CRT.getType<CommaRT::CRT_DomainInstance>(), size);
00174 llvm::Value *dst = builder.CreateStructGEP(instance, 4);
00175 builder.CreateStore(capsules, dst);
00176 builder.CreateBr(constructBB);
00177
00178
00179 builder.SetInsertPoint(constructBB);
00180 builder.CreateRetVoid();
00181
00182 return ctor;
00183 }
00184
00192 void DomainInfo::genInstanceRequirement(llvm::IRBuilder<> &builder,
00193 CodeGenCapsule &CGC,
00194 unsigned ID,
00195 llvm::Value *destVector,
00196 llvm::Value *percent)
00197 {
00198 DomainInstanceDecl *instance = CGC.getDependency(ID);
00199 Domoid *domoid = instance->getDefiningDecl();
00200
00201 if (isa<DomainDecl>(domoid))
00202 genDomainRequirement(builder, CGC, ID, destVector);
00203 else
00204 genFunctorRequirement(builder, CGC, ID, destVector, percent);
00205 }
00206
00211 void DomainInfo::genDomainRequirement(llvm::IRBuilder<> &builder,
00212 CodeGenCapsule &CGC,
00213 unsigned ID,
00214 llvm::Value *destVector)
00215 {
00216 DomainInstanceDecl *instance = CGC.getDependency(ID);
00217 DomainDecl *domain = instance->getDefiningDomain();
00218 assert(domain && "Cannot gen requirement for this type of instance!");
00219
00220 llvm::GlobalValue *info = CG.lookupCapsuleInfo(domain);
00221 assert(info && "Could not resolve capsule info!");
00222
00223 llvm::Value *ptr = CRT.getDomain(builder, info);
00224 llvm::Value *slotIndex = llvm::ConstantInt::get(llvm::Type::Int32Ty, ID - 1);
00225 builder.CreateStore(ptr, builder.CreateGEP(destVector, slotIndex));
00226 }
00227
00232 void DomainInfo::genFunctorRequirement(llvm::IRBuilder<> &builder,
00233 CodeGenCapsule &CGC,
00234 unsigned ID,
00235 llvm::Value *destVector,
00236 llvm::Value *percent)
00237 {
00238 DomainInstanceDecl *instance = CGC.getDependency(ID);
00239 FunctorDecl *functor = instance->getDefiningFunctor();
00240 assert(functor && "Cannot gen requirement for this type of instance!");
00241
00242 llvm::GlobalValue *info = CG.lookupCapsuleInfo(functor);
00243 assert(info && "Could not resolve capsule info!");
00244
00245 std::vector<llvm::Value *> arguments;
00246 arguments.push_back(info);
00247
00248 const DomainInstance *DInstance = CRT.getDomainInstance();
00249 const DomainView *DView = CRT.getDomainView();
00250
00251 for (unsigned i = 0; i < instance->getArity(); ++i) {
00252 DomainType *argTy = cast<DomainType>(instance->getActualParameter(i));
00253 SignatureType *targetTy = functor->getFormalSignature(i);
00254
00255 if (DomainInstanceDecl *arg = argTy->getInstanceDecl()) {
00256 unsigned argIndex = CGC.getDependencyID(arg) - 1;
00257
00258
00259 llvm::Value *instanceSlot =
00260 llvm::ConstantInt::get(llvm::Type::Int32Ty, argIndex);
00261 llvm::Value *argInstance =
00262 builder.CreateLoad(builder.CreateGEP(destVector, instanceSlot));
00263
00264
00265
00266
00267 unsigned sigOffset = CRT.getSignatureOffset(arg, targetTy);
00268 llvm::Value *view =
00269 DInstance->loadView(builder, argInstance, sigOffset);
00270 arguments.push_back(view);
00271 }
00272 else {
00273 AbstractDomainDecl *arg = argTy->getAbstractDecl();
00274
00275 unsigned paramIdx = functor->getFormalIndex(arg);
00276 SignatureType *targetTy = functor->getFormalSignature(paramIdx);
00277 unsigned sigOffset = CRT.getSignatureOffset(arg, targetTy);
00278
00279
00280 llvm::Value *paramView =
00281 DInstance->loadParam(builder, percent, paramIdx);
00282
00283
00284
00285 llvm::Value *argView =
00286 DView->downcast(builder, paramView, sigOffset);
00287
00288 arguments.push_back(argView);
00289 }
00290 }
00291
00292 llvm::Value *theInstance = CRT.getDomain(builder, arguments);
00293 llvm::Value *slotIndex = llvm::ConstantInt::get(llvm::Type::Int32Ty, ID - 1);
00294 builder.CreateStore(theInstance, builder.CreateGEP(destVector, slotIndex));
00295 }
00296
00297
00299 llvm::Constant *DomainInfo::genITable(CodeGenCapsule &CGC)
00300 {
00301
00302
00303 return CG.getNullPointer(getFieldType<ITable>());
00304 }
00305
00307 llvm::Constant *DomainInfo::genSignatureOffsets(CodeGenCapsule &CGC)
00308 {
00309 Domoid *theCapsule = CGC.getCapsule();
00310 SignatureSet &sigSet = theCapsule->getSignatureSet();
00311 const llvm::PointerType *vectorTy = getFieldType<SigOffsets>();
00312 const llvm::Type *elemTy = vectorTy->getElementType();
00313
00314
00315
00316 if (!sigSet.numSignatures())
00317 return CG.getNullPointer(vectorTy);
00318
00319
00320 typedef SignatureSet::const_iterator iterator;
00321 std::vector<llvm::Constant *> offsets;
00322 unsigned index = 0;
00323
00324 for (iterator iter = sigSet.beginDirect();
00325 iter != sigSet.endDirect(); ++iter)
00326 index = getOffsetsForSignature(*iter, index, offsets);
00327
00328 llvm::Constant *offsetInit = CG.getConstantArray(elemTy, offsets);
00329 llvm::GlobalVariable *offsetVal = CG.makeInternGlobal(offsetInit, true);
00330 return CG.getPointerCast(offsetVal, vectorTy);
00331 }
00332
00338 unsigned
00339 DomainInfo::getOffsetsForSignature(SignatureType *sig,
00340 unsigned index,
00341 std::vector<llvm::Constant *> &offsets)
00342 {
00343 typedef SignatureSet::const_iterator sig_iterator;
00344 typedef DeclRegion::ConstDeclIter decl_iterator;
00345
00346 const Sigoid *sigoid = sig->getSigoid();
00347 ExportMap::SignatureKey key = CRT.getExportMap().lookupSignature(sigoid);
00348 const llvm::Type *elemTy = getFieldType<SigOffsets>()->getElementType();
00349
00350 for (ExportMap::offset_iterator iter = ExportMap::begin_offsets(key);
00351 iter != ExportMap::end_offsets(key); ++iter) {
00352 unsigned i = index + *iter;
00353 offsets.push_back(llvm::ConstantInt::get(elemTy, i));
00354 }
00355
00356 return index + ExportMap::numberOfExports(key);
00357 }
00358
00360 llvm::Constant *DomainInfo::genExportArray(CodeGenCapsule &CGC)
00361 {
00362 Domoid *theCapsule = CGC.getCapsule();
00363 const llvm::PointerType *exportVecTy = getFieldType<Exvec>();
00364 const llvm::PointerType *exportFnTy =
00365 cast<llvm::PointerType>(exportVecTy->getElementType());
00366 llvm::IndexedMap<llvm::Constant *> exportMap;
00367
00368 for (Domoid::ConstDeclIter iter = theCapsule->beginDecls();
00369 iter != theCapsule->endDecls(); ++iter) {
00370 const SubroutineDecl *srDecl = dyn_cast<SubroutineDecl>(*iter);
00371 if (srDecl && !srDecl->isImmediate()) {
00372 std::string linkName = CodeGen::getLinkName(srDecl);
00373 llvm::GlobalValue *fn = CG.lookupGlobal(linkName);
00374 unsigned index = CRT.getExportMap().getIndex(srDecl);
00375
00376 assert(fn && "Export lookup failed!");
00377 exportMap.grow(index);
00378 exportMap[index] = fn;
00379 }
00380 }
00381
00382
00383
00384
00385 std::vector<llvm::Constant *> ptrs;
00386 for (unsigned i = 0; i < exportMap.size(); ++i) {
00387 llvm::Constant *fn = exportMap[i];
00388 assert(fn && "Empty entry in export map!");
00389 ptrs.push_back(CG.getPointerCast(fn, exportFnTy));
00390 }
00391
00392 llvm::Constant *exportInit = CG.getConstantArray(exportFnTy, ptrs);
00393 llvm::GlobalVariable *exportVec = CG.makeInternGlobal(exportInit, true);
00394 return CG.getPointerCast(exportVec, exportVecTy);
00395 }
00396
00397
00400 llvm::Value *DomainInfo::indexSigOffset(llvm::IRBuilder<> &builder,
00401 llvm::Value *DInfo,
00402 llvm::Value *index) const
00403 {
00404 assert(DInfo->getType() == getPointerTypeTo() &&
00405 "Wrong type of LLVM Value!");
00406
00407 llvm::Value *offVecAdr = builder.CreateStructGEP(DInfo, SigOffsets);
00408 llvm::Value *offVec = builder.CreateLoad(offVecAdr);
00409 llvm::Value *offAdr = builder.CreateGEP(offVec, index);
00410 return builder.CreateLoad(offAdr);
00411 }
00412
00413
00416 llvm::Value *DomainInfo::loadExportVec(llvm::IRBuilder<> &builder,
00417 llvm::Value *DInfo) const
00418 {
00419 assert(DInfo->getType() == getPointerTypeTo() &&
00420 "Wrong type of LLVM Value!");
00421
00422 llvm::Value *exportsAddr = builder.CreateStructGEP(DInfo, Exvec);
00423 return builder.CreateLoad(exportsAddr);
00424 }
00425
00427 llvm::Value *DomainInfo::loadExportFn(llvm::IRBuilder<> &builder,
00428 llvm::Value *DInfo,
00429 llvm::Value *exportIdx) const
00430 {
00431 assert(DInfo->getType() == getPointerTypeTo() &&
00432 "Wrong type of LLVM Value!");
00433
00434 llvm::Value *exportVec = loadExportVec(builder, DInfo);
00435 llvm::Value *exportAddr = builder.CreateGEP(exportVec, exportIdx);
00436 return builder.CreateLoad(exportAddr);
00437 }