LLConstant* DtoConstString(const char* str) { llvm::StringRef s(str ? str : ""); #if LDC_LLVM_VER == 300 LLConstant* init = LLConstantArray::get(gIR->context(), s, true); #else LLConstant* init = llvm::ConstantDataArray::getString(gIR->context(), s, true); #endif llvm::GlobalVariable* gvar = new llvm::GlobalVariable( *gIR->module, init->getType(), true, llvm::GlobalValue::InternalLinkage, init, ".str"); LLConstant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) }; return DtoConstSlice( DtoConstSize_t(s.size()), llvm::ConstantExpr::getGetElementPtr(gvar, idxs, true), Type::tchar->arrayOf() ); }
LLConstant *DtoConstString(const char *str) { llvm::StringRef s(str ? str : ""); llvm::GlobalVariable *gvar = (gIR->stringLiteral1ByteCache.find(s) == gIR->stringLiteral1ByteCache.end()) ? nullptr : gIR->stringLiteral1ByteCache[s]; if (gvar == nullptr) { llvm::Constant *init = llvm::ConstantDataArray::getString(gIR->context(), s, true); gvar = new llvm::GlobalVariable(gIR->module, init->getType(), true, llvm::GlobalValue::PrivateLinkage, init, ".str"); gvar->setUnnamedAddr(true); gIR->stringLiteral1ByteCache[s] = gvar; } LLConstant *idxs[] = {DtoConstUint(0), DtoConstUint(0)}; return DtoConstSlice(DtoConstSize_t(s.size()), llvm::ConstantExpr::getGetElementPtr( #if LDC_LLVM_VER >= 307 gvar->getInitializer()->getType(), #endif gvar, idxs, true), Type::tchar->arrayOf()); }
LLConstant * IrStruct::getClassInfoInterfaces() { IF_LOG Logger::println("Building ClassInfo.interfaces"); LOG_SCOPE; ClassDeclaration* cd = aggrdecl->isClassDeclaration(); assert(cd); size_t n = interfacesWithVtbls.size(); assert(stripModifiers(type)->irtype->isClass()->getNumInterfaceVtbls() == n && "inconsistent number of interface vtables in this class"); VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3); if (n == 0) return getNullValue(DtoType(interfaces_idx->type)); // Build array of: // // struct Interface // { // ClassInfo classinfo; // void*[] vtbl; // ptrdiff_t offset; // } LLSmallVector<LLConstant*, 6> constants; constants.reserve(cd->vtblInterfaces->dim); LLType* classinfo_type = DtoType(ClassDeclaration::classinfo->type); LLType* voidptrptr_type = DtoType( Type::tvoid->pointerTo()->pointerTo()); VarDeclarationIter idx(ClassDeclaration::classinfo->fields, 3); LLStructType* interface_type = isaStruct(DtoType(idx->type->nextOf())); assert(interface_type); for (size_t i = 0; i < n; ++i) { BaseClass* it = interfacesWithVtbls[i]; IF_LOG Logger::println("Adding interface %s", it->base->toPrettyChars()); IrStruct* irinter = it->base->ir.irStruct; assert(irinter && "interface has null IrStruct"); IrTypeClass* itc = stripModifiers(irinter->type)->irtype->isClass(); assert(itc && "null interface IrTypeClass"); // classinfo LLConstant* ci = irinter->getClassInfoSymbol(); ci = DtoBitCast(ci, classinfo_type); // vtbl LLConstant* vtb; // interface get a null if (cd->isInterfaceDeclaration()) { vtb = DtoConstSlice(DtoConstSize_t(0), getNullValue(voidptrptr_type)); } else { ClassGlobalMap::iterator itv = interfaceVtblMap.find(it->base); assert(itv != interfaceVtblMap.end() && "interface vtbl not found"); vtb = itv->second; vtb = DtoBitCast(vtb, voidptrptr_type); vtb = DtoConstSlice(DtoConstSize_t(itc->getVtblSize()), vtb); } // offset LLConstant* off = DtoConstSize_t(it->offset); // create Interface struct LLConstant* inits[3] = { ci, vtb, off }; LLConstant* entry = LLConstantStruct::get(interface_type, llvm::makeArrayRef(inits, 3)); constants.push_back(entry); } // create Interface[N] LLArrayType* array_type = llvm::ArrayType::get(interface_type, n); // create and apply initializer LLConstant* arr = LLConstantArray::get(array_type, constants); classInterfacesArray->setInitializer(arr); // return null, only baseclass provide interfaces if (cd->vtblInterfaces->dim == 0) { return getNullValue(DtoType(interfaces_idx->type)); } // only the interface explicitly implemented by this class // (not super classes) should show in ClassInfo LLConstant* idxs[2] = { DtoConstSize_t(0), DtoConstSize_t(n - cd->vtblInterfaces->dim) }; LLConstant* ptr = llvm::ConstantExpr::getGetElementPtr( classInterfacesArray, idxs, true); // return as a slice return DtoConstSlice( DtoConstSize_t(cd->vtblInterfaces->dim), ptr ); }
LLConstant *DtoConstString(const char *str) { LLConstant *cString = DtoConstCString(str); LLConstant *length = DtoConstSize_t(str ? strlen(str) : 0); return DtoConstSlice(length, cString, Type::tchar->arrayOf()); }
void RTTIBuilder::push_array(uint64_t dim, llvm::Constant * ptr) { inits.push_back(DtoConstSlice(DtoConstSize_t(dim), ptr)); }
void RTTIBuilder::push_void_array(uint64_t dim, llvm::Constant *ptr) { push(DtoConstSlice(DtoConstSize_t(dim), DtoBitCast(ptr, getVoidPtrType()))); }