static llvm::Function *build_module_shared_ctor(Module *m) { std::string name("_D"); name.append(mangle(m)); name.append("13__shared_ctorZ"); IrModule *irm = getIrModule(m); return build_module_function(name, irm->sharedCtors, irm->sharedGates); }
static llvm::Function* build_module_unittest(Module *m) { std::string name("_D"); name.append(mangle(m)); name.append("10__unittestZ"); return build_module_function(name, getIrModule(m)->unitTests); }
static llvm::Function* build_module_shared_dtor(Module *m) { std::string name("_D"); name.append(mangle(m)); name.append("13__shared_dtorZ"); return build_module_function(name, getIrModule(m)->sharedDtors); }
DValue* DtoAAIndex(Loc& loc, Type* type, DValue* aa, DValue* key, bool lvalue) { // D1: // call: // extern(C) void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey) // or // extern(C) void* _aaIn(AA aa*, TypeInfo keyti, void* pkey) // D2: // call: // extern(C) void* _aaGetX(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey) // or // extern(C) void* _aaInX(AA aa*, TypeInfo keyti, void* pkey) // first get the runtime function #if DMDV2 llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, lvalue?"_aaGetX":"_aaInX"); #else llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, lvalue?"_aaGet":"_aaIn"); #endif LLFunctionType* funcTy = func->getFunctionType(); // aa param LLValue* aaval = lvalue ? aa->getLVal() : aa->getRVal(); aaval = DtoBitCast(aaval, funcTy->getParamType(0)); // keyti param #if DMDV2 LLValue* keyti = to_keyti(aa); #else LLValue* keyti = to_keyti(key); #endif keyti = DtoBitCast(keyti, funcTy->getParamType(1)); // pkey param LLValue* pkey = makeLValue(loc, key); pkey = DtoBitCast(pkey, funcTy->getParamType(lvalue ? 3 : 2)); // call runtime LLValue* ret; if (lvalue) { // valuesize param LLValue* valsize = DtoConstSize_t(getTypePaddedSize(DtoType(type))); ret = gIR->CreateCallOrInvoke4(func, aaval, keyti, valsize, pkey, "aa.index").getInstruction(); } else { ret = gIR->CreateCallOrInvoke3(func, aaval, keyti, pkey, "aa.index").getInstruction(); } // cast return value LLType* targettype = getPtrToType(DtoType(type)); if (ret->getType() != targettype) ret = DtoBitCast(ret, targettype); // Only check bounds for rvalues ('aa[key]'). // Lvalue use ('aa[key] = value') auto-adds an element. if (!lvalue && global.params.useArrayBounds) { llvm::BasicBlock* oldend = gIR->scopeend(); llvm::BasicBlock* failbb = llvm::BasicBlock::Create(gIR->context(), "aaboundscheckfail", gIR->topfunc(), oldend); llvm::BasicBlock* okbb = llvm::BasicBlock::Create(gIR->context(), "aaboundsok", gIR->topfunc(), oldend); LLValue* nullaa = LLConstant::getNullValue(ret->getType()); LLValue* cond = gIR->ir->CreateICmpNE(nullaa, ret, "aaboundscheck"); gIR->ir->CreateCondBr(cond, okbb, failbb); // set up failbb to call the array bounds error runtime function gIR->scope() = IRScope(failbb, okbb); std::vector<LLValue*> args; #if DMDV2 // module param LLValue *moduleInfoSymbol = gIR->func()->decl->getModule()->moduleInfoSymbol(); LLType *moduleInfoType = DtoType(Module::moduleinfo->type); args.push_back(DtoBitCast(moduleInfoSymbol, getPtrToType(moduleInfoType))); #else // file param IrModule* irmod = getIrModule(NULL); args.push_back(DtoLoad(irmod->fileName)); #endif // line param LLConstant* c = DtoConstUint(loc.linnum); args.push_back(c); // call llvm::Function* errorfn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_bounds"); gIR->CreateCallOrInvoke(errorfn, args); // the function does not return gIR->ir->CreateUnreachable(); // if ok, proceed in okbb gIR->scope() = IRScope(okbb, oldend); } return new DVarValue(type, ret); }
llvm::GlobalVariable *genModuleInfo(Module *m) { // check declaration in object.d const auto moduleInfoType = getModuleInfoType(); const auto moduleInfoDecl = Module::moduleinfo; // The "new-style" ModuleInfo records are variable-length, with the presence // of the various fields indicated by a certain flag bit. The base struct // should consist only of the _flags/_index fields (the latter of which is // unused). if (moduleInfoDecl->structsize != 4 + 4) { m->error("Unexpected size of struct `object.ModuleInfo`; " "druntime version does not match compiler (see -v)"); fatal(); } // First, figure out which fields are present and set the flags accordingly. unsigned flags = MInew; const auto fctor = buildModuleCtor(m); if (fctor) { flags |= MItlsctor; } const auto fdtor = buildModuleDtor(m); if (fdtor) { flags |= MItlsdtor; } const auto fsharedctor = buildModuleSharedCtor(m); if (fsharedctor) { flags |= MIctor; } const auto fshareddtor = buildModuleSharedDtor(m); if (fshareddtor) { flags |= MIdtor; } #if 0 if (fgetmembers) flags |= MIxgetMembers; #endif const auto fictor = getIrModule(m)->coverageCtor; if (fictor) flags |= MIictor; const auto funittest = buildModuleUnittest(m); if (funittest) { flags |= MIunitTest; } size_t importedModulesCount; const auto importedModules = buildImportedModules(m, importedModulesCount); if (importedModules) { flags |= MIimportedModules; } size_t localClassesCount; const auto localClasses = buildLocalClasses(m, localClassesCount); if (localClasses) { flags |= MIlocalClasses; } if (!m->needmoduleinfo) { flags |= MIstandalone; } // Now, start building the initialiser for the ModuleInfo instance. RTTIBuilder b(moduleInfoType); b.push_uint(flags); b.push_uint(0); // index if (fctor) { b.push(fctor); } if (fdtor) { b.push(fdtor); } if (fsharedctor) { b.push(fsharedctor); } if (fshareddtor) { b.push(fshareddtor); } #if 0 if (fgetmembers) b.push(fgetmembers); #endif if (fictor) { b.push(fictor); } if (funittest) { b.push(funittest); } if (importedModules) { b.push_size(importedModulesCount); b.push(importedModules); } if (localClasses) { b.push_size(localClassesCount); b.push(localClasses); } // Put out module name as a 0-terminated string. const char *name = m->toPrettyChars(); const size_t len = strlen(name) + 1; const auto it = llvm::IntegerType::getInt8Ty(gIR->context()); const auto at = llvm::ArrayType::get(it, len); b.push(toConstantArray(it, at, name, len, false)); // Create a global symbol with the above initialiser. LLGlobalVariable *moduleInfoSym = getIrModule(m)->moduleInfoSymbol(); b.finalize(moduleInfoSym); setLinkage({LLGlobalValue::ExternalLinkage, supportsCOMDAT()}, moduleInfoSym); return moduleInfoSym; }