Fix ICE for ref/out params of opaque structs

Fixes dmd-testsuite's new compilable/test21668.d.
This commit is contained in:
Martin Kinkelin 2021-03-01 11:12:28 +01:00
parent 3abffca14c
commit 52bcbcc566
3 changed files with 25 additions and 13 deletions

View file

@ -183,22 +183,23 @@ struct X86TargetABI : TargetABI {
// * It is not a floating point type. // * It is not a floating point type.
IrFuncTyArg *last = fty.args.back(); IrFuncTyArg *last = fty.args.back();
Type *lastTy = last->type->toBasetype();
unsigned sz = lastTy->size();
if (last->rewrite == &indirectByvalRewrite || if (last->rewrite == &indirectByvalRewrite ||
(last->byref && !last->isByVal())) { (last->byref && !last->isByVal())) {
Logger::println("Putting last (byref) parameter in register"); Logger::println("Putting last (byref) parameter in register");
last->attrs.addAttribute(LLAttribute::InReg); last->attrs.addAttribute(LLAttribute::InReg);
} else if (!lastTy->isfloating() && (sz == 1 || sz == 2 || sz == 4)) { } else {
// rewrite aggregates as integers to make inreg work Type *lastTy = last->type->toBasetype();
if (lastTy->ty == Tstruct || lastTy->ty == Tsarray) { auto sz = lastTy->size();
integerRewrite.applyTo(*last); if (!lastTy->isfloating() && (sz == 1 || sz == 2 || sz == 4)) {
// undo byval semantics applied via passByVal() returning true // rewrite aggregates as integers to make inreg work
last->byref = false; if (lastTy->ty == Tstruct || lastTy->ty == Tsarray) {
last->attrs.clear(); integerRewrite.applyTo(*last);
// undo byval semantics applied via passByVal() returning true
last->byref = false;
last->attrs.clear();
}
last->attrs.addAttribute(LLAttribute::InReg);
} }
last->attrs.addAttribute(LLAttribute::InReg);
} }
} }
} }

View file

@ -183,7 +183,16 @@ llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
loweredDType = merge(ltd); loweredDType = merge(ltd);
} else if (passPointer) { } else if (passPointer) {
// ref/out // ref/out
attrs.addDereferenceableAttr(loweredDType->size()); auto ts = loweredDType->toBasetype()->isTypeStruct();
if (ts && !ts->sym->members) {
// opaque struct
attrs.addAttribute(LLAttribute::NonNull);
#if LDC_LLVM_VER >= 1100
attrs.addAttribute(LLAttribute::NoUndef);
#endif
} else {
attrs.addDereferenceableAttr(loweredDType->size());
}
} else { } else {
if (abi->passByVal(f, loweredDType)) { if (abi->passByVal(f, loweredDType)) {
// LLVM ByVal parameters are pointers to a copy in the function // LLVM ByVal parameters are pointers to a copy in the function

View file

@ -152,7 +152,9 @@ void DtoDeleteArray(const Loc &loc, DValue *arr) {
unsigned DtoAlignment(Type *type) { unsigned DtoAlignment(Type *type) {
structalign_t alignment = type->alignment(); structalign_t alignment = type->alignment();
if (alignment == STRUCTALIGN_DEFAULT) { if (alignment == STRUCTALIGN_DEFAULT) {
alignment = type->alignsize(); auto ts = type->toBasetype()->isTypeStruct();
if (!ts || ts->sym->members) // not an opaque struct
alignment = type->alignsize();
} }
return (alignment == STRUCTALIGN_DEFAULT ? 0 : alignment); return (alignment == STRUCTALIGN_DEFAULT ? 0 : alignment);
} }