mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-04-30 23:20:40 +03:00
AssignExp: Refactor direct construction by rhs call via sret
This commit is contained in:
parent
999cd37642
commit
1c14efffde
2 changed files with 31 additions and 49 deletions
|
@ -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
|
||||
|
|
33
gen/toir.cpp
33
gen/toir.cpp
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue