AssignExp: Refactor direct construction by rhs call via sret

This commit is contained in:
Martin 2016-06-26 19:36:30 +02:00
parent 999cd37642
commit 1c14efffde
2 changed files with 31 additions and 49 deletions

View file

@ -914,47 +914,6 @@ void DtoVarDeclaration(VarDeclaration *vd) {
irLocal->value = allocainst;
gIR->DBuilder.EmitLocalVariable(allocainst, vd);
/* NRVO again:
T t = f(); // t's memory address is taken hidden pointer
*/
ExpInitializer *ei = nullptr;
if (vd->_init && (ei = vd->_init->isExpInitializer()) &&
ei->exp->op == TOKconstruct) {
const auto ae = static_cast<AssignExp *>(ei->exp);
Expression *rhs = ae->e2;
Type *const vdBasetype = vd->type->toBasetype();
if (rhs->type->toBasetype() == vdBasetype) {
// Allow casts only emitted because of differing static array
// constness. See runnable.sdtor.test10094.
if (rhs->op == TOKcast && vdBasetype->ty == Tsarray) {
Expression *castSource = static_cast<CastExp *>(rhs)->e1;
Type *rhsElem = castSource->type->toBasetype()->nextOf();
if (rhsElem) {
Type *l = vdBasetype->nextOf()->arrayOf()->immutableOf();
Type *r = rhsElem->arrayOf()->immutableOf();
if (l->equals(r)) {
rhs = castSource;
}
}
}
if (rhs->op == TOKcall) {
auto ce = static_cast<CallExp *>(rhs);
if (DtoIsReturnInArg(ce)) {
if (isSpecialRefVar(vd)) {
LLValue *const val = DtoLVal(ce);
DtoStore(val, irLocal->value);
} else {
DValue *fnval = toElem(ce->e1);
DtoCallFunction(ce->loc, ce->type, fnval, ce->arguments,
irLocal->value);
}
return;
}
}
}
}
}
IF_LOG Logger::cout() << "llvm value for decl: " << *getIrLocal(vd)->value

View file

@ -577,16 +577,39 @@ public:
DValue *l = toElem(e->e1, true);
// NRVO for object field initialization in constructor
if (l->isLVal() && e->op == TOKconstruct && e->e2->op == TOKcall) {
CallExp *ce = static_cast<CallExp *>(e->e2);
// Direct construction by right-hand-side call via sret?
// E.g., `T v = foo();` if the callee `T foo()` uses sret.
// In this case, pass `&v` as hidden sret argument, i.e., let `foo()`
// construct the return value directly into the lhs lvalue.
if (l->isLVal() && e->op == TOKconstruct) {
Type *const lhsBasetype = l->type->toBasetype();
Expression *rhs = e->e2;
if (rhs->type->toBasetype() == lhsBasetype) {
// Skip over rhs casts only emitted because of differing static array
// constness. See runnable.sdtor.test10094.
if (rhs->op == TOKcast && lhsBasetype->ty == Tsarray) {
Expression *castSource = static_cast<CastExp *>(rhs)->e1;
Type *rhsElem = castSource->type->toBasetype()->nextOf();
if (rhsElem) {
Type *l = lhsBasetype->nextOf()->arrayOf()->immutableOf();
Type *r = rhsElem->arrayOf()->immutableOf();
if (l->equals(r))
rhs = castSource;
}
}
if (rhs->op == TOKcall) {
auto ce = static_cast<CallExp *>(rhs);
if (DtoIsReturnInArg(ce)) {
DValue *fnval = toElem(ce->e1);
LLValue *lval = DtoLVal(l);
result = DtoCallFunction(ce->loc, ce->type, fnval, ce->arguments, lval);
DtoCallFunction(ce->loc, ce->type, fnval, ce->arguments,
DtoLVal(l));
result = l;
return;
}
}
}
}
DValue *r = toElem(e->e2);