LLValue* DtoAAEquals(Loc& loc, TOK op, DValue* l, DValue* r) { Type* t = l->getType()->toBasetype(); assert(t == r->getType()->toBasetype() && "aa equality is only defined for aas of same type"); #if DMDV2 llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaEqual"); LLFunctionType* funcTy = func->getFunctionType(); LLValue* aaval = DtoBitCast(l->getRVal(), funcTy->getParamType(1)); LLValue* abval = DtoBitCast(r->getRVal(), funcTy->getParamType(2)); LLValue* aaTypeInfo = DtoTypeInfoOf(t); LLValue* res = gIR->CreateCallOrInvoke3(func, aaTypeInfo, aaval, abval, "aaEqRes").getInstruction(); #else llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaEq"); LLFunctionType* funcTy = func->getFunctionType(); LLValue* aaval = DtoBitCast(l->getRVal(), funcTy->getParamType(0)); LLValue* abval = DtoBitCast(r->getRVal(), funcTy->getParamType(1)); LLValue* aaTypeInfo = DtoTypeInfoOf(t); LLValue* res = gIR->CreateCallOrInvoke3(func, aaval, abval, aaTypeInfo, "aaEqRes").getInstruction(); #endif res = gIR->ir->CreateICmpNE(res, DtoConstInt(0), "tmp"); if (op == TOKnotequal) res = gIR->ir->CreateNot(res, "tmp"); return res; }
// returns the keytype typeinfo static LLValue* to_keyti(DValue* aa) { // keyti param assert(aa->type->toBasetype()->ty == Taarray); TypeAArray * aatype = static_cast<TypeAArray*>(aa->type->toBasetype()); return DtoTypeInfoOf(aatype->index, false); }
void TypeInfoTupleDeclaration::llvmDefine() { Logger::println("TypeInfoTupleDeclaration::llvmDefine() %s", toChars()); LOG_SCOPE; // create elements array assert(tinfo->ty == Ttuple); TypeTuple *tu = static_cast<TypeTuple *>(tinfo); size_t dim = tu->arguments->dim; std::vector<LLConstant*> arrInits; arrInits.reserve(dim); LLType* tiTy = DtoType(Type::typeinfo->type); for (size_t i = 0; i < dim; i++) { Parameter *arg = static_cast<Parameter *>(tu->arguments->data[i]); arrInits.push_back(DtoTypeInfoOf(arg->type, true)); } // build array LLArrayType* arrTy = LLArrayType::get(tiTy, dim); LLConstant* arrC = LLConstantArray::get(arrTy, arrInits); RTTIBuilder b(Type::typeinfotypelist); // push TypeInfo[] b.push_array(arrC, dim, Type::typeinfo->type, NULL); // finish b.finalize(ir.irGlobal); }
void DtoResolveStruct(StructDeclaration* sd) { // Make sure to resolve each struct type exactly once. if (sd->ir.resolved) return; sd->ir.resolved = true; Logger::println("Resolving struct type: %s (%s)", sd->toChars(), sd->loc.toChars()); LOG_SCOPE; // make sure type exists DtoType(sd->type); // if it's a forward declaration, all bets are off. The type should be enough if (sd->sizeok != 1) return; // create the IrAggr IrAggr* irstruct = new IrAggr(sd); sd->ir.irStruct = irstruct; // Set up our field metadata. for (ArrayIter<VarDeclaration> it(sd->fields); !it.done(); it.next()) { VarDeclaration* vd = it.get(); assert(!vd->ir.irField); (void)new IrField(vd); } // perform definition bool emitGlobalData = mustDefineSymbol(sd); if (emitGlobalData) { // emit the initZ symbol LLGlobalVariable* initZ = irstruct->getInitSymbol(); // set initZ initializer initZ->setInitializer(irstruct->getDefaultInit()); } // emit members if (sd->members) { for (ArrayIter<Dsymbol> it(sd->members); !it.done(); it.next()) { it.get()->codegen(Type::sir); } } if (emitGlobalData) { // emit typeinfo DtoTypeInfoOf(sd->type); } }
void TypedefDeclaration::codegen(Ir*) { Logger::print("TypedefDeclaration::codegen: %s\n", toChars()); LOG_SCOPE; if (type->ty == Terror) { error("had semantic errors when compiling"); return; } // generate typeinfo DtoTypeInfoOf(type, false); }
LLValue *DtoAAEquals(Loc &loc, TOK op, DValue *l, DValue *r) { Type *t = l->type->toBasetype(); assert(t == r->type->toBasetype() && "aa equality is only defined for aas of same type"); llvm::Function *func = getRuntimeFunction(loc, gIR->module, "_aaEqual"); LLFunctionType *funcTy = func->getFunctionType(); LLValue *aaval = DtoBitCast(DtoRVal(l), funcTy->getParamType(1)); LLValue *abval = DtoBitCast(DtoRVal(r), funcTy->getParamType(2)); LLValue *aaTypeInfo = DtoTypeInfoOf(t); LLValue *res = gIR->CreateCallOrInvoke(func, aaTypeInfo, aaval, abval, "aaEqRes") .getInstruction(); const auto predicate = eqTokToICmpPred(op, /* invert = */ true); res = gIR->ir->CreateICmp(predicate, res, DtoConstInt(0)); return res; }
// build a single element for the OffsetInfo[] of ClassInfo static LLConstant* build_offti_entry(ClassDeclaration* cd, VarDeclaration* vd) { std::vector<LLConstant*> inits(2); // size_t offset; // assert(vd->ir.irField); // grab the offset from llvm and the formal class type size_t offset = gDataLayout->getStructLayout(isaStruct(cd->type->ir.type->get()))->getElementOffset(vd->ir.irField->index); // offset nested struct/union fields offset += vd->ir.irField->unionOffset; // assert that it matches DMD Logger::println("offsets: %lu vs %u", offset, vd->offset); assert(offset == vd->offset); inits[0] = DtoConstSize_t(offset); // TypeInfo ti; inits[1] = DtoTypeInfoOf(vd->type, true); // done return llvm::ConstantStruct::get(inits); }
DValue *DtoAAIndex(Loc &loc, Type *type, DValue *aa, DValue *key, bool lvalue) { // D2: // call: // extern(C) void* _aaGetY(AA* aa, TypeInfo aati, size_t valuesize, void* // pkey) // or // extern(C) void* _aaInX(AA aa*, TypeInfo keyti, void* pkey) // first get the runtime function llvm::Function *func = getRuntimeFunction( loc, gIR->module, lvalue ? "_aaGetY" : "_aaInX"); LLFunctionType *funcTy = func->getFunctionType(); // aa param LLValue *aaval = lvalue ? aa->getLVal() : aa->getRVal(); aaval = DtoBitCast(aaval, funcTy->getParamType(0)); // pkey param LLValue *pkey = makeLValue(loc, key); pkey = DtoBitCast(pkey, funcTy->getParamType(lvalue ? 3 : 2)); // call runtime LLValue *ret; if (lvalue) { LLValue *rawAATI = DtoTypeInfoOf(aa->type->unSharedOf()->mutableOf(), false); LLValue *castedAATI = DtoBitCast(rawAATI, funcTy->getParamType(1)); LLValue *valsize = DtoConstSize_t(getTypePaddedSize(DtoType(type))); ret = gIR->CreateCallOrInvoke(func, aaval, castedAATI, valsize, pkey, "aa.index") .getInstruction(); } else { LLValue *keyti = DtoBitCast(to_keyti(aa), funcTy->getParamType(1)); ret = gIR->CreateCallOrInvoke(func, aaval, keyti, pkey, "aa.index") .getInstruction(); } // cast return value LLType *targettype = DtoPtrToType(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 && gIR->emitArrayBoundsChecks()) { llvm::BasicBlock *failbb = llvm::BasicBlock::Create( gIR->context(), "aaboundscheckfail", gIR->topfunc()); llvm::BasicBlock *okbb = llvm::BasicBlock::Create(gIR->context(), "aaboundsok", gIR->topfunc()); 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); llvm::Function *errorfn = getRuntimeFunction(loc, gIR->module, "_d_arraybounds"); gIR->CreateCallOrInvoke( errorfn, DtoModuleFileName(gIR->func()->decl->getModule(), loc), DtoConstUint(loc.linnum)); // the function does not return gIR->ir->CreateUnreachable(); // if ok, proceed in okbb gIR->scope() = IRScope(okbb); } return new DVarValue(type, ret); }
// returns the keytype typeinfo static LLValue* to_keyti(DValue* key) { // keyti param Type* keytype = key->getType(); return DtoTypeInfoOf(keytype, false); }
void DtoResolveStruct(StructDeclaration* sd) { // don't do anything if already been here if (sd->ir.resolved) return; // make sure above works :P sd->ir.resolved = true; // log what we're doing Logger::println("Resolving struct type: %s (%s)", sd->toChars(), sd->loc.toChars()); LOG_SCOPE; // make sure type exists DtoType(sd->type); // if it's a forward declaration, all bets are off. The type should be enough if (sd->sizeok != 1) return; // create the IrStruct IrStruct* irstruct = new IrStruct(sd); sd->ir.irStruct = irstruct; // make sure all fields really get their ir field ArrayIter<VarDeclaration> it(sd->fields); for (; !it.done(); it.next()) { VarDeclaration* vd = it.get(); if (vd->ir.irField == NULL) { new IrField(vd); } else { IF_LOG Logger::println("struct field already exists!!!"); } } // perform definition bool needs_def = mustDefineSymbol(sd); if (needs_def) { // emit the initZ symbol LLGlobalVariable* initZ = irstruct->getInitSymbol(); // set initZ initializer initZ->setInitializer(irstruct->getDefaultInit()); } // emit members if (sd->members) { ArrayIter<Dsymbol> it(*sd->members); while (!it.done()) { Dsymbol* member = it.get(); if (member) member->codegen(Type::sir); it.next(); } } if (needs_def) { // emit typeinfo DtoTypeInfoOf(sd->type); } }
void DtoResolveClass(ClassDeclaration* cd) { // make sure the base classes are processed first ArrayIter<BaseClass> base_iter(cd->baseclasses); while (base_iter.more()) { BaseClass* bc = base_iter.get(); if (bc) { bc->base->codegen(Type::sir); } base_iter.next(); } if (cd->ir.resolved) return; cd->ir.resolved = true; Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); LOG_SCOPE; // make sure type exists DtoType(cd->type); // create IrStruct assert(cd->ir.irStruct == NULL); IrStruct* irstruct = new IrStruct(cd); cd->ir.irStruct = irstruct; // make sure all fields really get their ir field ArrayIter<VarDeclaration> it(cd->fields); for (; !it.done(); it.next()) { VarDeclaration* vd = it.get(); if (vd->ir.irField == NULL) { new IrField(vd); } else { IF_LOG Logger::println("class field already exists!!!"); } } bool needs_def = mustDefineSymbol(cd); // emit the ClassZ symbol LLGlobalVariable* ClassZ = irstruct->getClassInfoSymbol(); // emit the interfaceInfosZ symbol if necessary if (cd->vtblInterfaces && cd->vtblInterfaces->dim > 0) irstruct->getInterfaceArraySymbol(); // initializer is applied when it's built // interface only emit typeinfo and classinfo if (cd->isInterfaceDeclaration()) { irstruct->initializeInterface(); } else { // emit the initZ symbol LLGlobalVariable* initZ = irstruct->getInitSymbol(); // emit the vtblZ symbol LLGlobalVariable* vtblZ = irstruct->getVtblSymbol(); // perform definition if (needs_def) { // set symbol initializers initZ->setInitializer(irstruct->getDefaultInit()); vtblZ->setInitializer(irstruct->getVtblInit()); } } // emit members if (cd->members) { ArrayIter<Dsymbol> it(*cd->members); while (!it.done()) { Dsymbol* member = it.get(); if (member) member->codegen(Type::sir); it.next(); } } if (needs_def) { // emit typeinfo DtoTypeInfoOf(cd->type); // define classinfo ClassZ->setInitializer(irstruct->getClassInfoInit()); } }
void RTTIBuilder::push_typeinfo(Type* t) { inits.push_back(DtoTypeInfoOf(t, true)); }
void RTTIBuilder::push_typeinfo(Type *t) { push(DtoTypeInfoOf(t, true)); }