mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #72479 from meg-gupta/fixsilcombineagain
Fix SILCombine of inject_enum_addr to correctly check for unreferenceable storage
This commit is contained in:
@@ -604,6 +604,10 @@ bool specializeAppliesInFunction(SILFunction &F,
|
||||
/// types aggregated together at each level.
|
||||
SILValue createEmptyAndUndefValue(SILType ty, SILInstruction *insertionPoint,
|
||||
SILBuilderContext &ctx, bool noUndef = false);
|
||||
|
||||
/// Check if a struct or its fields can have unreferenceable storage.
|
||||
bool findUnreferenceableStorage(StructDecl *decl, SILType structType,
|
||||
SILFunction *func);
|
||||
} // end namespace swift
|
||||
|
||||
#endif // SWIFT_SILOPTIMIZER_UTILS_INSTOPTUTILS_H
|
||||
|
||||
@@ -1246,7 +1246,7 @@ SILCombiner::visitInjectEnumAddrInst(InjectEnumAddrInst *IEAI) {
|
||||
|
||||
// We cannot create a struct when it has unreferenceable storage.
|
||||
if (elemType.isEmpty(*IEAI->getFunction()) && structDecl &&
|
||||
structDecl->hasUnreferenceableStorage()) {
|
||||
findUnreferenceableStorage(structDecl, elemType, IEAI->getFunction())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -2009,3 +2009,21 @@ SILValue swift::createEmptyAndUndefValue(SILType ty,
|
||||
assert(!noUndef);
|
||||
return SILUndef::get(insertionPoint->getFunction(), ty);
|
||||
}
|
||||
|
||||
bool swift::findUnreferenceableStorage(StructDecl *decl, SILType structType,
|
||||
SILFunction *func) {
|
||||
if (decl->hasUnreferenceableStorage()) {
|
||||
return true;
|
||||
}
|
||||
// Check if any fields have unreferenceable stoage
|
||||
for (auto *field : decl->getStoredProperties()) {
|
||||
TypeExpansionContext tec = *func;
|
||||
auto fieldTy = structType.getFieldType(field, func->getModule(), tec);
|
||||
if (auto *fieldStructDecl = fieldTy.getStructOrBoundGenericStruct()) {
|
||||
if (findUnreferenceableStorage(fieldStructDecl, fieldTy, func)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -362,3 +362,33 @@ bb3:
|
||||
%8 = tuple ()
|
||||
return %8 : $()
|
||||
}
|
||||
|
||||
struct NestedUnreferenceableStorage {
|
||||
let e: EmptyCUnion
|
||||
}
|
||||
|
||||
sil @no_init_nested_c_union : $@convention(thin) () -> (@out NestedUnreferenceableStorage)
|
||||
|
||||
// CHECK-LABEL: sil @test_empty_nested_c_union : $@convention(thin) () -> () {
|
||||
// CHECK: inject_enum_addr
|
||||
// CHECK-LABEL: } // end sil function 'test_empty_nested_c_union'
|
||||
sil @test_empty_nested_c_union : $@convention(thin) () -> () {
|
||||
bb0:
|
||||
%0 = alloc_stack $Optional<NestedUnreferenceableStorage>
|
||||
%1 = init_enum_data_addr %0 : $*Optional<NestedUnreferenceableStorage>, #Optional.some!enumelt
|
||||
%f = function_ref @no_init_nested_c_union : $@convention(thin) () -> (@out NestedUnreferenceableStorage)
|
||||
apply %f(%1) : $@convention(thin) () -> (@out NestedUnreferenceableStorage)
|
||||
inject_enum_addr %0 : $*Optional<NestedUnreferenceableStorage>, #Optional.some!enumelt
|
||||
switch_enum_addr %0 : $*Optional<NestedUnreferenceableStorage>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
|
||||
|
||||
bb1:
|
||||
br bb3
|
||||
|
||||
bb2:
|
||||
br bb3
|
||||
|
||||
bb3:
|
||||
dealloc_stack %0 : $*Optional<NestedUnreferenceableStorage>
|
||||
%8 = tuple ()
|
||||
return %8 : $()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user