00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 #include "CodeGen.h"
00010 #include "SRInfo.h"
00011 #include "CGContext.h"
00012 #include "CodeGenRoutine.h"
00013 #include "CommaRT.h"
00014 #include "DependencySet.h"
00015 #include "comma/ast/AstResource.h"
00016 #include "comma/ast/Decl.h"
00017 #include "comma/basic/TextProvider.h"
00018 #include "comma/codegen/Mangle.h"
00019 
00020 using namespace comma;
00021 
00022 using llvm::dyn_cast;
00023 using llvm::cast;
00024 using llvm::isa;
00025 
00026 CodeGen::CodeGen(llvm::Module *M, const llvm::TargetData &data,
00027                  AstResource &resource)
00028     : M(M),
00029       TD(data),
00030       Resource(resource),
00031       CRT(new CommaRT(*this)),
00032       moduleName(0) { }
00033 
00034 CodeGen::~CodeGen()
00035 {
00036     delete CRT;
00037 }
00038 
00039 void CodeGen::emitToplevelDecl(Decl *decl)
00040 {
00041     if (DomainDecl *domain = dyn_cast<DomainDecl>(decl)) {
00042         DependencySet *DS = new DependencySet(domain);
00043         dependenceTable[domain] = DS;
00044 
00045         
00046         InstanceInfo *info = createInstanceInfo(domain->getInstance());
00047         emitCapsule(info);
00048         capsuleInfoTable[info->getLinkName()] = CRT->registerCapsule(domain);
00049     }
00050     else if (FunctorDecl *functor = dyn_cast<FunctorDecl>(decl)) {
00051         DependencySet *DS = new DependencySet(functor);
00052         dependenceTable[functor] = DS;
00053 
00054         std::string name = mangle::getLinkName(functor);
00055         capsuleInfoTable[name] = CRT->registerCapsule(functor);
00056     }
00057     else
00058         return;
00059 
00060     
00061     
00062     while (instancesPending())
00063         emitNextInstance();
00064 }
00065 
00066 void CodeGen::emitCapsule(InstanceInfo *info)
00067 {
00068     CGContext CGC(*this, info);
00069 
00070     
00071     const AddDecl *add = info->getDefinition()->getImplementation();
00072     for (DeclRegion::ConstDeclIter I = add->beginDecls(), E = add->endDecls();
00073          I != E; ++I) {
00074         if (SubroutineDecl *SRD = dyn_cast<SubroutineDecl>(*I)) {
00075             SRInfo *SRI = getSRInfo(info->getInstanceDecl(), SRD);
00076             CodeGenRoutine CGR(CGC, SRI);
00077             CGR.emit();
00078         }
00079     }
00080     info->markAsCompiled();
00081 }
00082 
00083 void CodeGen::emitEntry(ProcedureDecl *pdecl)
00084 {
00085     
00086     assert(pdecl->getArity() == 0 && "Entry procedures must be nullary!");
00087 
00088     
00089     
00090     DeclRegion *region = pdecl->getDeclRegion();
00091     DomainInstanceDecl *context = cast<DomainInstanceDecl>(region);
00092     assert(!context->isParameterized() &&
00093            "Cannot call entry procedures in a parameterized context!");
00094 
00095     
00096     SRInfo *info = getSRInfo(context, pdecl);
00097     llvm::Value *func = info->getLLVMFunction();
00098 
00099     
00100     
00101     
00102     std::vector<const llvm::Type*> argTypes;
00103     argTypes.push_back(getInt32Ty());
00104     argTypes.push_back(getPointerType(getInt8PtrTy()));
00105     llvm::FunctionType *entryTy =
00106         llvm::FunctionType::get(getInt32Ty(), argTypes, false);
00107 
00108     
00109     
00110     
00111     llvm::Function *entry = makeFunction(entryTy, "main");
00112 
00113     llvm::IRBuilder<> Builder(getLLVMContext());
00114     llvm::BasicBlock *entryBB = makeBasicBlock("entry", entry);
00115     llvm::BasicBlock *landingBB = makeBasicBlock("landingpad", entry);
00116     llvm::BasicBlock *returnBB  = makeBasicBlock("return", entry);
00117     Builder.SetInsertPoint(entryBB);
00118 
00119     
00120     llvm::GlobalValue *domainInfo = lookupCapsuleInfo(context->getDefinition());
00121     assert(domainInfo && "Could not find domain_info for entry function!");
00122 
00123     
00124     
00125     llvm::Value *domainInstance = CRT->getDomain(Builder, domainInfo);
00126 
00127     
00128     
00129     llvm::SmallVector<llvm::Value*, 2> args;
00130     args.push_back(domainInstance);
00131     Builder.CreateInvoke(func, returnBB, landingBB, args.begin(), args.end());
00132 
00133     
00134     Builder.SetInsertPoint(returnBB);
00135     Builder.CreateRet(llvm::ConstantInt::get(getInt32Ty(), uint64_t(0)));
00136 
00137     
00138     Builder.SetInsertPoint(landingBB);
00139     llvm::Value *eh_person = CRT->getEHPersonality();
00140     llvm::Function *eh_except = getEHExceptionIntrinsic();
00141     llvm::Function *eh_select = getEHSelectorIntrinsic();
00142 
00143     
00144     llvm::Value *except = Builder.CreateCall(eh_except);
00145 
00146     
00147     
00148     args.clear();
00149     args.push_back(except);
00150     args.push_back(eh_person);
00151     args.push_back(getNullPointer(getInt8PtrTy()));
00152     Builder.CreateCall(eh_select, args.begin(), args.end());
00153 
00154     
00155     
00156     CRT->unhandledException(Builder, except);
00157 }
00158 
00159 llvm::Function *CodeGen::getMemcpy64() const
00160 {
00161     const llvm::Type *Tys[1] = { getInt64Ty() };
00162     return llvm::Intrinsic::getDeclaration(M, llvm::Intrinsic::memcpy, Tys, 1);
00163 }
00164 
00165 llvm::Function *CodeGen::getMemcpy32() const
00166 {
00167     const llvm::Type *Tys[1] = { getInt32Ty() };
00168     return llvm::Intrinsic::getDeclaration(M, llvm::Intrinsic::memcpy, Tys, 1);
00169 }
00170 
00171 llvm::Function *CodeGen::getMemset32() const
00172 {
00173     const llvm::Type *Tys[1] = { getInt32Ty() };
00174     return llvm::Intrinsic::getDeclaration(M, llvm::Intrinsic::memset, Tys, 1);
00175 }
00176 
00177 llvm::Function *CodeGen::getEHExceptionIntrinsic() const
00178 {
00179     return getLLVMIntrinsic(llvm::Intrinsic::eh_exception);
00180 }
00181 
00182 llvm::Function *CodeGen::getEHSelectorIntrinsic() const
00183 {
00184     if (TD.getPointerSizeInBits() == 32)
00185         return getLLVMIntrinsic(llvm::Intrinsic::eh_selector_i32);
00186     else
00187         return getLLVMIntrinsic(llvm::Intrinsic::eh_selector_i64);
00188 }
00189 
00190 llvm::Function *CodeGen::getEHTypeidIntrinsic() const
00191 {
00192     if (TD.getPointerSizeInBits() == 32)
00193         return getLLVMIntrinsic(llvm::Intrinsic::eh_typeid_for_i32);
00194     else
00195         return getLLVMIntrinsic(llvm::Intrinsic::eh_typeid_for_i64);
00196 }
00197 
00198 InstanceInfo *CodeGen::createInstanceInfo(DomainInstanceDecl *instance)
00199 {
00200     assert(!lookupInstanceInfo(instance) &&
00201            "Instance already has associated info!");
00202 
00203     InstanceInfo *info = new InstanceInfo(*this, instance);
00204     instanceTable[instance] = info;
00205     return info;
00206 }
00207 
00208 bool CodeGen::instancesPending() const
00209 {
00210     typedef InstanceMap::const_iterator iterator;
00211     iterator E = instanceTable.end();
00212     for (iterator I = instanceTable.begin(); I != E; ++I) {
00213         if (!I->second->isCompiled())
00214             return true;
00215     }
00216     return false;
00217 }
00218 
00219 void CodeGen::emitNextInstance()
00220 {
00221     typedef InstanceMap::iterator iterator;
00222     iterator E = instanceTable.end();
00223     for (iterator I = instanceTable.begin(); I != E; ++I) {
00224         if (I->second->isCompiled())
00225             continue;
00226         emitCapsule(I->second);
00227         return;
00228     }
00229 }
00230 
00231 bool CodeGen::extendWorklist(DomainInstanceDecl *instance)
00232 {
00233     assert(!instance->isDependent() && "Cannot codegen dependent instances!");
00234 
00235     
00236     
00237     if (lookupInstanceInfo(instance))
00238         return false;
00239 
00240     createInstanceInfo(instance);
00241     return true;
00242 }
00243 
00244 SRInfo *CodeGen::getSRInfo(DomainInstanceDecl *instance,
00245                            SubroutineDecl *srDecl)
00246 {
00247     InstanceInfo *IInfo = getInstanceInfo(instance);
00248     return IInfo->getSRInfo(srDecl);
00249 }
00250 
00251 bool CodeGen::insertGlobal(const std::string &linkName, llvm::GlobalValue *GV)
00252 {
00253     assert(GV && "Cannot insert null values into the global table!");
00254 
00255     if (lookupGlobal(linkName))
00256         return false;
00257 
00258     globalTable[linkName] = GV;
00259     return true;
00260 }
00261 
00262 llvm::GlobalValue *CodeGen::lookupGlobal(const std::string &linkName) const
00263 {
00264     return M->getGlobalVariable(linkName);
00265 }
00266 
00267 llvm::GlobalValue *CodeGen::lookupCapsuleInfo(const Domoid *domoid) const
00268 {
00269     std::string name = mangle::getLinkName(domoid);
00270     StringGlobalMap::const_iterator iter = capsuleInfoTable.find(name);
00271 
00272     if (iter != capsuleInfoTable.end())
00273         return iter->second;
00274     else
00275         return 0;
00276 }
00277 
00278 llvm::GlobalVariable *CodeGen::emitInternString(const llvm::StringRef &elems,
00279                                                 bool addNull,
00280                                                 bool isConstant,
00281                                                 const std::string &name)
00282 {
00283     llvm::LLVMContext &ctx = getLLVMContext();
00284     llvm::Constant *string = llvm::ConstantArray::get(ctx, elems, addNull);
00285     return new llvm::GlobalVariable(*M, string->getType(), isConstant,
00286                                     llvm::GlobalValue::InternalLinkage,
00287                                     string, name);
00288 }
00289 
00290 llvm::BasicBlock *CodeGen::makeBasicBlock(const std::string &name,
00291                                           llvm::Function *parent,
00292                                           llvm::BasicBlock *insertBefore) const
00293 {
00294     llvm::LLVMContext &ctx = getLLVMContext();
00295     return llvm::BasicBlock::Create(ctx, name, parent, insertBefore);
00296 }
00297 
00298 llvm::GlobalVariable *CodeGen::makeExternGlobal(llvm::Constant *init,
00299                                                 bool isConstant,
00300                                                 const std::string &name)
00301 
00302 {
00303     return new llvm::GlobalVariable(*M, init->getType(), isConstant,
00304                                     llvm::GlobalValue::ExternalLinkage,
00305                                     init, name);
00306 }
00307 
00308 llvm::GlobalVariable *CodeGen::makeInternGlobal(llvm::Constant *init,
00309                                                 bool isConstant,
00310                                                 const std::string &name)
00311 {
00312     return new llvm::GlobalVariable(*M, init->getType(), isConstant,
00313                                     llvm::GlobalValue::InternalLinkage,
00314                                     init, name);
00315 }
00316 
00317 llvm::Function *CodeGen::makeFunction(const llvm::FunctionType *Ty,
00318                                       const std::string &name)
00319 {
00320     llvm::Function *fn =
00321         llvm::Function::Create(Ty, llvm::Function::ExternalLinkage, name, M);
00322     return fn;
00323 }
00324 
00325 llvm::Function *CodeGen::makeFunction(const DomainInstanceDecl *instance,
00326                                       const SubroutineDecl *srDecl,
00327                                       CodeGenTypes &CGT)
00328 {
00329     const llvm::FunctionType *fnTy = CGT.lowerSubroutine(srDecl);
00330     std::string fnName = mangle::getLinkName(instance, srDecl);
00331     llvm::Function *fn = makeFunction(fnTy, fnName);
00332 
00333     
00334     assert(!instance->isDependent() && "Unexpected dependent instance!");
00335 
00336     
00337     if (CGT.getConvention(srDecl) == CodeGenTypes::CC_Sret)
00338         fn->addAttribute(1, llvm::Attribute::StructRet);
00339     return fn;
00340 }
00341 
00342 llvm::Function *CodeGen::makeInternFunction(const llvm::FunctionType *Ty,
00343                                             const std::string &name)
00344 {
00345     llvm::Function *fn =
00346         llvm::Function::Create(Ty, llvm::Function::InternalLinkage, name, M);
00347     return fn;
00348 }
00349 
00350 
00351 llvm::ConstantInt *CodeGen::getConstantInt(const llvm::IntegerType *type,
00352                                            const llvm::APInt &value) const
00353 {
00354     llvm::Constant *res = 0;
00355 
00356     unsigned typeWidth = type->getBitWidth();
00357     unsigned valueWidth = value.getBitWidth();
00358 
00359     if (typeWidth == valueWidth)
00360         res = llvm::ConstantInt::get(type, value);
00361     else if (typeWidth > valueWidth) {
00362         llvm::APInt tmp(value);
00363         tmp.sext(typeWidth);
00364         res = llvm::ConstantInt::get(type, tmp);
00365     }
00366     else {
00367         llvm::APInt tmp(value);
00368         assert(tmp.getMinSignedBits() < typeWidth &&
00369                "Value to wide for supplied type!");
00370 
00371         tmp.trunc(typeWidth);
00372         res = llvm::ConstantInt::get(type, tmp);
00373     }
00374 
00375     return cast<llvm::ConstantInt>(res);
00376 }
00377 
00378 const DependencySet &CodeGen::getDependencySet(const Domoid *domoid)
00379 {
00380     DependenceMap::value_type &entry = dependenceTable.FindAndConstruct(domoid);
00381 
00382     if (entry.second)
00383         return *entry.second;
00384 
00385     DependencySet *DS = new DependencySet(domoid);
00386     entry.second = DS;
00387     return *DS;
00388 }
00389 
00390 llvm::Constant *CodeGen::getModuleName()
00391 {
00392     
00393     if (moduleName)
00394         return moduleName;
00395 
00396     moduleName = emitInternString(M->getModuleIdentifier());
00397     moduleName = getPointerCast(moduleName, getInt8PtrTy());
00398     return moduleName;
00399 }
00400 
00401 SourceLocation CodeGen::getSourceLocation(Location loc)
00402 {
00403     return getAstResource().getTextProvider().getSourceLocation(loc);
00404 }
00405 
00406 
00407 
00408 
00409 Generator *Generator::create(llvm::Module *M, const llvm::TargetData &data,
00410                              AstResource &resource)
00411 {
00412     return new CodeGen(M, data, resource);
00413 }