void DtoGetComplexParts(Loc& loc, Type* to, DValue* val, DValue*& re, DValue*& im) { Type* baserety; Type* baseimty; switch (to->toBasetype()->ty) { default: llvm_unreachable("Unexpected complex floating point type"); case Tcomplex32: baserety = Type::tfloat32; baseimty = Type::timaginary32; break; case Tcomplex64: baserety = Type::tfloat64; baseimty = Type::timaginary64; break; case Tcomplex80: baserety = Type::tfloat80; baseimty = Type::timaginary80; break; } Type* t = val->getType()->toBasetype(); if (t->iscomplex()) { DValue* v = DtoCastComplex(loc, val, to); if (to->iscomplex()) { if (v->isLVal()) { LLValue *reVal = DtoGEP(v->getLVal(), DtoConstInt(0), DtoConstInt(0), ".re_part"); LLValue *imVal = DtoGEP(v->getLVal(), DtoConstInt(0), DtoConstInt(1), ".im_part"); re = new DVarValue(baserety, reVal); im = new DVarValue(baseimty, imVal); } else { LLValue *reVal = gIR->ir->CreateExtractValue(v->getRVal(), 0, ".re_part"); LLValue *imVal = gIR->ir->CreateExtractValue(v->getRVal(), 1, ".im_part"); re = new DImValue(baserety, reVal); im = new DImValue(baseimty, imVal); } } else DtoGetComplexParts(loc, to, v, re, im); } else if (t->isimaginary()) { re = NULL; im = DtoCastFloat(loc, val, baseimty); } else if (t->isfloating()) { re = DtoCastFloat(loc, val, baserety); im = NULL; } else if (t->isintegral()) { re = DtoCastInt(loc, val, baserety); im = NULL; } else { assert(0); } }
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; }
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; }
llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance, size_t interfaces_index) { ClassGlobalMap::iterator it = interfaceVtblMap.find(b->base); if (it != interfaceVtblMap.end()) return it->second; IF_LOG Logger::println("Building vtbl for implementation of interface %s in class %s", b->base->toPrettyChars(), aggrdecl->toPrettyChars()); LOG_SCOPE; ClassDeclaration* cd = aggrdecl->isClassDeclaration(); assert(cd && "not a class aggregate"); FuncDeclarations vtbl_array; b->fillVtbl(cd, &vtbl_array, new_instance); std::vector<llvm::Constant*> constants; constants.reserve(vtbl_array.dim); if (!b->base->isCPPinterface()) { // skip interface info for CPP interfaces // start with the interface info VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3); // index into the interfaces array llvm::Constant* idxs[2] = { DtoConstSize_t(0), DtoConstSize_t(interfaces_index) }; llvm::Constant* c = llvm::ConstantExpr::getGetElementPtr( getInterfaceArraySymbol(), idxs, true); constants.push_back(c); } // add virtual function pointers size_t n = vtbl_array.dim; for (size_t i = b->base->vtblOffset(); i < n; i++) { Dsymbol* dsym = static_cast<Dsymbol*>(vtbl_array.data[i]); if (dsym == NULL) { // FIXME // why is this null? // happens for mini/s.d constants.push_back(getNullValue(getVoidPtrType())); continue; } FuncDeclaration* fd = dsym->isFuncDeclaration(); assert(fd && "vtbl entry not a function"); assert((!fd->isAbstract() || fd->fbody) && "null symbol in interface implementation vtable"); fd->codegen(Type::sir); assert(fd->ir.irFunc && "invalid vtbl function"); LLFunction *fn = fd->ir.irFunc->func; // If the base is a cpp interface, 'this' parameter is a pointer to // the interface not the underlying object as expected. Instead of // the function, we place into the vtable a small wrapper, called thunk, // that casts 'this' to the object and then pass it to the real function. if (b->base->isCPPinterface()) { TypeFunction *f = (TypeFunction*)fd->type->toBasetype(); assert(f->fty.arg_this); // create the thunk function OutBuffer name; name.writestring("Th"); name.printf("%i", b->offset); name.writestring(fd->mangle()); LLFunction *thunk = LLFunction::Create(isaFunction(fn->getType()->getContainedType(0)), DtoLinkage(fd), name.toChars(), gIR->module); // create entry and end blocks llvm::BasicBlock* beginbb = llvm::BasicBlock::Create(gIR->context(), "entry", thunk); llvm::BasicBlock* endbb = llvm::BasicBlock::Create(gIR->context(), "endentry", thunk); gIR->scopes.push_back(IRScope(beginbb, endbb)); // copy the function parameters, so later we can pass them to the real function std::vector<LLValue*> args; llvm::Function::arg_iterator iarg = thunk->arg_begin(); for (; iarg != thunk->arg_end(); ++iarg) args.push_back(iarg); // cast 'this' to Object LLValue* &thisArg = args[(f->fty.arg_sret == 0) ? 0 : 1]; LLType* thisType = thisArg->getType(); thisArg = DtoBitCast(thisArg, getVoidPtrType()); thisArg = DtoGEP1(thisArg, DtoConstInt(-b->offset)); thisArg = DtoBitCast(thisArg, thisType); // call the real vtbl function. LLValue *retVal = gIR->ir->CreateCall(fn, args); // return from the thunk if (thunk->getReturnType() == LLType::getVoidTy(gIR->context())) llvm::ReturnInst::Create(gIR->context(), beginbb); else llvm::ReturnInst::Create(gIR->context(), retVal, beginbb); // clean up gIR->scopes.pop_back(); thunk->getBasicBlockList().pop_back(); fn = thunk; } constants.push_back(fn); } // build the vtbl constant llvm::Constant* vtbl_constant = LLConstantStruct::getAnon(gIR->context(), constants, false); // create the global variable to hold it llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl); std::string mangle("_D"); mangle.append(cd->mangle()); mangle.append("11__interface"); mangle.append(b->base->mangle()); mangle.append("6__vtblZ"); llvm::GlobalVariable* GV = getOrCreateGlobal(cd->loc, *gIR->module, vtbl_constant->getType(), true, _linkage, vtbl_constant, mangle ); // insert into the vtbl map interfaceVtblMap.insert(std::make_pair(b->base, GV)); return GV; }