Files
swift-mirror/lib/SILGen/ManagedValue.cpp
Andrew Trick e9c559b718 [SILGen] Bootstrapping opaque values (#7113)
[NFC] Add -enable-sil-opaque-values frontend option.

This will be used to change the SIL-level calling convention for opaque values,
such as generics and resilient structs, to pass-by-value.  Under this flag,
opaque values have SSA lifetimes, managed by copy_value and destroy_value.

This will make it easier to optimize copies and verify ownership.

* [SILGen] type lowering support for opaque values.

Add OpaqueValueTypeLowering.
Under EnableSILOpaqueValues, lower address-only types as opaque values.

* [SIL] Fix ValueOwnershipKind to support opaque SIL values.

* Test case: SILGen opaque value support for Parameter/ResultConvention.

* [SILGen] opaque value support for function arguments.

* Future Test case: SILGen opaque value specialDest arguments.

* Future Test case: SILGen opaque values: emitOpenExistential.

* Test case: SIL parsing support for EnableSILOpaqueValues.

* SILGen opaque values: prepareArchetypeCallee.

* [SIL Verify] allow copy_value for EnableSILOpaqueValues.

* Test cast: SIL serializer support for opaque values.

* Add a static_assert for ParameterConvention layout.

* Test case: Mandatory SILOpt support for EnableSILOpaqueValues.

* Test case: SILOpt support for EnableSILOpaqueValues.

* SILGen opaque values: TypeLowering emitCopyValue.

* SILBuilder createLoad. Allow loading opaque values.

* SIL Verifier. Allow loading and storing opaque values.

* SILGen emitSemanticStore support for opaque values.

* Test case for SILGen emitSemanticStore.

* Test case for SIL mandatory support for inout assignment.

* Fix SILGen opaque values test case after rebasing.
2017-01-27 18:56:53 -08:00

107 lines
3.7 KiB
C++

//===--- ManagedValue.cpp - Value with cleanup ----------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// A storage structure for holding a destructured rvalue with an optional
// cleanup(s).
// Ownership of the rvalue can be "forwarded" to disable the associated
// cleanup(s).
//
//===----------------------------------------------------------------------===//
#include "ManagedValue.h"
#include "SILGenFunction.h"
using namespace swift;
using namespace Lowering;
/// Emit a copy of this value with independent ownership.
ManagedValue ManagedValue::copy(SILGenFunction &gen, SILLocation l) {
if (!cleanup.isValid()) {
assert(gen.getTypeLowering(getType()).isTrivial());
return *this;
}
auto &lowering = gen.getTypeLowering(getType());
assert(!lowering.isTrivial() && "trivial value has cleanup?");
if (!lowering.isAddressOnly()) {
return gen.emitManagedRetain(l, getValue(), lowering);
}
SILValue buf = gen.emitTemporaryAllocation(l, getType());
gen.B.createCopyAddr(l, getValue(), buf, IsNotTake, IsInitialization);
return gen.emitManagedRValueWithCleanup(buf, lowering);
}
/// Store a copy of this value with independent ownership into the given
/// uninitialized address.
void ManagedValue::copyInto(SILGenFunction &gen, SILValue dest,
SILLocation loc) {
auto &lowering = gen.getTypeLowering(getType());
if (lowering.isAddressOnly()) {
gen.B.createCopyAddr(loc, getValue(), dest, IsNotTake, IsInitialization);
return;
}
SILValue copy = lowering.emitCopyValue(gen.B, loc, getValue());
lowering.emitStoreOfCopy(gen.B, loc, copy, dest, IsInitialization);
}
/// This is the same operation as 'copy', but works on +0 values that don't
/// have cleanups. It returns a +1 value with one.
ManagedValue ManagedValue::copyUnmanaged(SILGenFunction &gen, SILLocation loc) {
auto &lowering = gen.getTypeLowering(getType());
if (lowering.isTrivial())
return *this;
SILValue result;
if (!lowering.isAddress()) {
result = lowering.emitCopyValue(gen.B, loc, getValue());
} else {
result = gen.emitTemporaryAllocation(loc, getType());
gen.B.createCopyAddr(loc, getValue(), result, IsNotTake,IsInitialization);
}
return gen.emitManagedRValueWithCleanup(result, lowering);
}
/// Disable the cleanup for this value.
void ManagedValue::forwardCleanup(SILGenFunction &gen) const {
assert(hasCleanup() && "value doesn't have cleanup!");
gen.Cleanups.forwardCleanup(getCleanup());
}
/// Forward this value, deactivating the cleanup and returning the
/// underlying value.
SILValue ManagedValue::forward(SILGenFunction &gen) const {
if (hasCleanup())
forwardCleanup(gen);
return getValue();
}
void ManagedValue::forwardInto(SILGenFunction &gen, SILLocation loc,
SILValue address) {
if (hasCleanup())
forwardCleanup(gen);
auto &addrTL = gen.getTypeLowering(address->getType());
gen.emitSemanticStore(loc, getValue(), address, addrTL, IsInitialization);
}
void ManagedValue::assignInto(SILGenFunction &gen, SILLocation loc,
SILValue address) {
if (hasCleanup())
forwardCleanup(gen);
auto &addrTL = gen.getTypeLowering(address->getType());
gen.emitSemanticStore(loc, getValue(), address, addrTL,
IsNotInitialization);
}