IRGen: Use deinit to destroy move-only structs that have them.

The `deinit` takes full responsibility for destroying the value, using the
user-defined deinit body and implicitly destroying any remaining resources
not consumed during the deinit.

Remaining to do after this patch:

- Run the deinit for enums
- Pass generic arguments for generic move-only types
- Handle deinits that take their parameter indirectly
- Teach value witness layout about when types are move-only and/or have
  deinits, so that we don't attempt to give move-only types standard
  value witness tables or share box metadata with copyable payloads
This commit is contained in:
Joe Groff
2023-02-22 11:43:18 -08:00
parent 7018c5575e
commit afa5837aeb
14 changed files with 449 additions and 50 deletions

View File

@@ -250,6 +250,18 @@ namespace {
return fields[0].getTypeInfo().isSingleRetainablePointer(expansion, rc);
}
void destroy(IRGenFunction &IGF, Address address, SILType T,
bool isOutlined) const override {
// If the struct has a deinit declared, then call it to destroy the
// value.
if (tryEmitDestroyUsingDeinit(IGF, address, T)) {
return;
}
// Otherwise, perform elementwise destruction of the value.
return super::destroy(IGF, address, T, isOutlined);
}
void verify(IRGenTypeVerifierFunction &IGF,
llvm::Value *metadata,
SILType structType) const override {
@@ -748,6 +760,7 @@ namespace {
/// A type implementation for loadable struct types.
class LoadableStructTypeInfo final
: public StructTypeInfoBase<LoadableStructTypeInfo, LoadableTypeInfo> {
using super = StructTypeInfoBase<LoadableStructTypeInfo, LoadableTypeInfo>;
public:
LoadableStructTypeInfo(ArrayRef<StructFieldInfo> fields,
unsigned explosionSize,
@@ -814,6 +827,18 @@ namespace {
const StructFieldInfo &field) const {
llvm_unreachable("non-fixed field in loadable type?");
}
void consume(IRGenFunction &IGF, Explosion &explosion,
Atomicity atomicity, SILType T) const override {
// If the struct has a deinit declared, then call it to consume the
// value.
if (tryEmitConsumeUsingDeinit(IGF, explosion, T)) {
return;
}
// Otherwise, do elementwise destruction of the value.
return super::consume(IGF, explosion, atomicity, T);
}
};
/// A type implementation for non-loadable but fixed-size struct types.