DValue *DtoNewClass(Loc &loc, TypeClass *tc, NewExp *newexp) { // resolve type DtoResolveClass(tc->sym); // allocate LLValue *mem; bool doInit = true; if (newexp->onstack) { unsigned alignment = tc->sym->alignsize; if (alignment == STRUCTALIGN_DEFAULT) alignment = 0; mem = DtoRawAlloca(DtoType(tc)->getContainedType(0), alignment, ".newclass_alloca"); } // custom allocator else if (newexp->allocator) { DtoResolveFunction(newexp->allocator); DFuncValue dfn(newexp->allocator, DtoCallee(newexp->allocator)); DValue *res = DtoCallFunction(newexp->loc, nullptr, &dfn, newexp->newargs); mem = DtoBitCast(DtoRVal(res), DtoType(tc), ".newclass_custom"); } // default allocator else { const bool useEHAlloc = global.params.ehnogc && newexp->thrownew; llvm::Function *fn = getRuntimeFunction( loc, gIR->module, useEHAlloc ? "_d_newThrowable" : "_d_allocclass"); LLConstant *ci = DtoBitCast(getIrAggr(tc->sym)->getClassInfoSymbol(), DtoType(getClassInfoType())); mem = gIR->CreateCallOrInvoke(fn, ci, useEHAlloc ? ".newthrowable_alloc" : ".newclass_gc_alloc") .getInstruction(); mem = DtoBitCast(mem, DtoType(tc), useEHAlloc ? ".newthrowable" : ".newclass_gc"); doInit = !useEHAlloc; } // init if (doInit) DtoInitClass(tc, mem); // init inner-class outer reference if (newexp->thisexp) { Logger::println("Resolving outer class"); LOG_SCOPE; unsigned idx = getFieldGEPIndex(tc->sym, tc->sym->vthis); LLValue *src = DtoRVal(newexp->thisexp); LLValue *dst = DtoGEPi(mem, 0, idx); IF_LOG Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n'; DtoStore(src, DtoBitCast(dst, getPtrToType(src->getType()))); } // set the context for nested classes else if (tc->sym->isNested() && tc->sym->vthis) { DtoResolveNestedContext(loc, tc->sym, mem); } // call constructor if (newexp->member) { // evaluate argprefix if (newexp->argprefix) { toElemDtor(newexp->argprefix); } Logger::println("Calling constructor"); assert(newexp->arguments != NULL); DtoResolveFunction(newexp->member); DFuncValue dfn(newexp->member, DtoCallee(newexp->member), mem); // ignore ctor return value (C++ ctors on Posix may not return `this`) DtoCallFunction(newexp->loc, tc, &dfn, newexp->arguments); return new DImValue(tc, mem); } assert(newexp->argprefix == NULL); // return default constructed class return new DImValue(tc, mem); }
DValue *DtoNewClass(Loc &loc, TypeClass *tc, NewExp *newexp) { // resolve type DtoResolveClass(tc->sym); // allocate LLValue *mem; if (newexp->onstack) { mem = DtoRawAlloca(DtoType(tc)->getContainedType(0), DtoAlignment(tc), ".newclass_alloca"); } // custom allocator else if (newexp->allocator) { DtoResolveFunction(newexp->allocator); DFuncValue dfn(newexp->allocator, DtoCallee(newexp->allocator)); DValue *res = DtoCallFunction(newexp->loc, nullptr, &dfn, newexp->newargs); mem = DtoBitCast(DtoRVal(res), DtoType(tc), ".newclass_custom"); } // default allocator else { llvm::Function *fn = getRuntimeFunction(loc, gIR->module, "_d_allocclass"); LLConstant *ci = DtoBitCast(getIrAggr(tc->sym)->getClassInfoSymbol(), DtoType(Type::typeinfoclass->type)); mem = gIR->CreateCallOrInvoke(fn, ci, ".newclass_gc_alloc").getInstruction(); mem = DtoBitCast(mem, DtoType(tc), ".newclass_gc"); } // init DtoInitClass(tc, mem); // init inner-class outer reference if (newexp->thisexp) { Logger::println("Resolving outer class"); LOG_SCOPE; unsigned idx = getFieldGEPIndex(tc->sym, tc->sym->vthis); LLValue *src = DtoRVal(newexp->thisexp); LLValue *dst = DtoGEPi(mem, 0, idx); IF_LOG Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n'; DtoStore(src, DtoBitCast(dst, getPtrToType(src->getType()))); } // set the context for nested classes else if (tc->sym->isNested() && tc->sym->vthis) { DtoResolveNestedContext(loc, tc->sym, mem); } // call constructor if (newexp->member) { // evaluate argprefix if (newexp->argprefix) { toElemDtor(newexp->argprefix); } Logger::println("Calling constructor"); assert(newexp->arguments != NULL); DtoResolveFunction(newexp->member); DFuncValue dfn(newexp->member, DtoCallee(newexp->member), mem); return DtoCallFunction(newexp->loc, tc, &dfn, newexp->arguments); } assert(newexp->argprefix == NULL); // return default constructed class return new DImValue(tc, mem); }