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/CodeGen.cpp ----------------------------------- -*- C++ -*-===// 00002 // 00003 // This file is distributed under the MIT license. See LICENSE.txt for details. 00004 // 00005 // Copyright (C) 2009-2010, Stephen Wilson 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 // Generate an InstanceInfo object for this domain. 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 // Continuously compile from the set of required instances so long as there 00061 // exist entries which need to be codegened. 00062 while (instancesPending()) 00063 emitNextInstance(); 00064 } 00065 00066 void CodeGen::emitCapsule(InstanceInfo *info) 00067 { 00068 CGContext CGC(*this, info); 00069 00070 // Codegen each subroutine. 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 // Basic sanity checks on the declaration. 00086 assert(pdecl->getArity() == 0 && "Entry procedures must be nullary!"); 00087 00088 // Get the procedures declarative region. This must be an instance of a 00089 // non-parameterized domain. 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 // Lookup the previously codegened function for this decl. 00096 SRInfo *info = getSRInfo(context, pdecl); 00097 llvm::Value *func = info->getLLVMFunction(); 00098 00099 // Build the function type for the entry stub. 00100 // 00101 // FIXME: This should be a target dependent operation. 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 // Get an external function to populate with the entry code. 00109 // 00110 // FIXME: The name of main function is a target dependent operation. 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 // Lookup the domain info object for the needed domain. 00120 llvm::GlobalValue *domainInfo = lookupCapsuleInfo(context->getDefinition()); 00121 assert(domainInfo && "Could not find domain_info for entry function!"); 00122 00123 // Build the get_domain call. Since this domain is not parameterized, only 00124 // the domain_info object is required as an argument. 00125 llvm::Value *domainInstance = CRT->getDomain(Builder, domainInfo); 00126 00127 // Invoke our entry function with the generated instance as its only 00128 // argument. 00129 llvm::SmallVector<llvm::Value*, 2> args; 00130 args.push_back(domainInstance); 00131 Builder.CreateInvoke(func, returnBB, landingBB, args.begin(), args.end()); 00132 00133 // Switch to normal return. 00134 Builder.SetInsertPoint(returnBB); 00135 Builder.CreateRet(llvm::ConstantInt::get(getInt32Ty(), uint64_t(0))); 00136 00137 // Switch to landing pad. 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 // The exception object produced by a call to _comma_raise. 00144 llvm::Value *except = Builder.CreateCall(eh_except); 00145 00146 // Build an exception selector with a null exception info entry. This is a 00147 // catch-all selector. 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 // Call into _comma_unhandled_exception and pass it the exception object. 00155 // This function never returns. 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 // If there is already and entry for this instance we will codegen it 00236 // eventually (if we have not already). 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 // All instances should be fully resolved. 00334 assert(!instance->isDependent() && "Unexpected dependent instance!"); 00335 00336 // Mark the function as sret if needed. 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 // Lazily construct the global on first call to this method. 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 // Generator 00408 00409 Generator *Generator::create(llvm::Module *M, const llvm::TargetData &data, 00410 AstResource &resource) 00411 { 00412 return new CodeGen(M, data, resource); 00413 }