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 }