mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-02-24 07:33:13 +01:00
Workaround for Voldemort return type handling issues.
See the comment in DtoCallFunction for an explanation of what is going on. The struct zero initialization code was also refactored out to AssignExp::toElem and modified so that it is only triggered on integer->struct assignments, not for any types where the modifier-stripped types don't match up. This would have lead to silently wrong code in the cases where the assert would have been triggered otherwise. Fixes the Phobos testsuite build.
This commit is contained in:
@@ -393,19 +393,7 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs, int op)
|
||||
Type* t2 = rhs->getType()->toBasetype();
|
||||
|
||||
if (t->ty == Tstruct) {
|
||||
if (!stripModifiers(t)->equals(stripModifiers(t2))) {
|
||||
// FIXME: use 'rhs' for something !?!
|
||||
DtoAggrZeroInit(lhs->getLVal());
|
||||
#if DMDV2
|
||||
TypeStruct *ts = static_cast<TypeStruct*>(lhs->getType());
|
||||
if (ts->sym->isNested() && ts->sym->vthis)
|
||||
DtoResolveNestedContext(loc, ts->sym, lhs->getLVal());
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
DtoAggrCopy(lhs->getLVal(), rhs->getRVal());
|
||||
}
|
||||
|
||||
DtoAggrCopy(lhs->getLVal(), rhs->getRVal());
|
||||
}
|
||||
else if (t->ty == Tarray) {
|
||||
// lhs is slice
|
||||
|
||||
@@ -652,7 +652,39 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0 && "unhandled repainting of return value");
|
||||
// Unfortunately, DMD has quirks resp. bugs with regard to name
|
||||
// mangling: For voldemort-type functions which return a nested
|
||||
// struct, the mangled name of the return type changes during
|
||||
// semantic analysis.
|
||||
//
|
||||
// (When the function deco is first computed as part of
|
||||
// determining the return type deco, its return type part is
|
||||
// left off to avoid cycles. If mangle/toDecoBuffer is then
|
||||
// called again for the type, it will pick up the previous
|
||||
// result and return the full deco string for the nested struct
|
||||
// type, consisting of both the full mangled function name, and
|
||||
// the struct identifier.)
|
||||
//
|
||||
// Thus, the type merging in stripModifiers does not work
|
||||
// reliably, and the equality check above can fail even if the
|
||||
// types only differ in a qualifier.
|
||||
//
|
||||
// Because a proper fix for this in the frontend is hard, we
|
||||
// just carry on and hope that the frontend didn't mess up,
|
||||
// i.e. that the LLVM types really match up.
|
||||
//
|
||||
// An example situation where this case occurs is:
|
||||
// ---
|
||||
// auto iota() {
|
||||
// static struct Result {
|
||||
// this(int) {}
|
||||
// inout(Result) test() inout { return cast(inout)Result(0); }
|
||||
// }
|
||||
// return Result.init;
|
||||
// }
|
||||
// void main() { auto r = iota(); }
|
||||
// ---
|
||||
break;
|
||||
}
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "final return value: " << *retllval << '\n';
|
||||
|
||||
18
gen/toir.cpp
18
gen/toir.cpp
@@ -607,10 +607,24 @@ DValue* AssignExp::toElem(IRState* p)
|
||||
}
|
||||
}
|
||||
|
||||
Logger::println("performing normal assignment");
|
||||
|
||||
DValue* l = e1->toElem(p);
|
||||
DValue* r = e2->toElem(p);
|
||||
|
||||
if (e1->type->toBasetype()->ty == Tstruct && e2->op == TOKint64)
|
||||
{
|
||||
Logger::println("performing aggregate zero initialization");
|
||||
assert(e2->toInteger() == 0);
|
||||
DtoAggrZeroInit(l->getLVal());
|
||||
#if DMDV2
|
||||
TypeStruct *ts = static_cast<TypeStruct*>(e1->type);
|
||||
if (ts->sym->isNested() && ts->sym->vthis)
|
||||
DtoResolveNestedContext(loc, ts->sym, l->getLVal());
|
||||
#endif
|
||||
// Return value should be irrelevant.
|
||||
return r;
|
||||
}
|
||||
|
||||
Logger::println("performing normal assignment");
|
||||
DtoAssign(loc, l, r, op);
|
||||
|
||||
if (l->isSlice())
|
||||
|
||||
Reference in New Issue
Block a user