mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
SILGen: Support mutable consuming parameters.
Emit a box like we would for a local variable, and move the parameter value into the box, as part of the prolog.
This commit is contained in:
@@ -6387,9 +6387,9 @@ Type VarDecl::getType() const {
|
|||||||
/// is a let member in an initializer.
|
/// is a let member in an initializer.
|
||||||
bool VarDecl::isSettable(const DeclContext *UseDC,
|
bool VarDecl::isSettable(const DeclContext *UseDC,
|
||||||
const DeclRefExpr *base) const {
|
const DeclRefExpr *base) const {
|
||||||
// Only inout parameters are settable.
|
// Parameters are settable or not depending on their ownership convention.
|
||||||
if (auto *PD = dyn_cast<ParamDecl>(this))
|
if (auto *PD = dyn_cast<ParamDecl>(this))
|
||||||
return PD->isInOut();
|
return !PD->isImmutableInFunctionBody();
|
||||||
|
|
||||||
// If this is a 'var' decl, then we're settable if we have storage or a
|
// If this is a 'var' decl, then we're settable if we have storage or a
|
||||||
// setter.
|
// setter.
|
||||||
|
|||||||
@@ -429,18 +429,20 @@ struct ArgumentInitHelper {
|
|||||||
ManagedValue argrv = makeArgument(ty, pd->isInOut(), isNoImplicitCopy,
|
ManagedValue argrv = makeArgument(ty, pd->isInOut(), isNoImplicitCopy,
|
||||||
lifetimeAnnotation, parent, loc);
|
lifetimeAnnotation, parent, loc);
|
||||||
|
|
||||||
|
SILValue value = argrv.getValue();
|
||||||
if (pd->isInOut()) {
|
if (pd->isInOut()) {
|
||||||
assert(argrv.getType().isAddress() && "expected inout to be address");
|
assert(argrv.getType().isAddress() && "expected inout to be address");
|
||||||
} else {
|
} else if (!pd->isImmutableInFunctionBody()) {
|
||||||
#warning "todo"
|
// If it's a locally mutable parameter, then we need to move the argument
|
||||||
assert(pd->isImmutableInFunctionBody()
|
// value into a local box to hold the mutated value.
|
||||||
&& "consuming mutable params not implemented yet");
|
auto mutableBox = SGF.emitLocalVariableWithCleanup(pd,
|
||||||
// If the variable is immutable, we can bind the value as is.
|
MarkUninitializedInst::Var);
|
||||||
// Leave the cleanup on the argument, if any, in place to consume the
|
argrv.ensurePlusOne(SGF, loc).forwardInto(SGF, loc, mutableBox.get());
|
||||||
// argument if we're responsible for it.
|
return;
|
||||||
}
|
}
|
||||||
SILValue value = argrv.getValue();
|
// If the variable is immutable, we can bind the value as is.
|
||||||
#warning "todo"
|
// Leave the cleanup on the argument, if any, in place to consume the
|
||||||
|
// argument if we're responsible for it.
|
||||||
SILDebugVariable varinfo(pd->isImmutableInFunctionBody(), ArgNo);
|
SILDebugVariable varinfo(pd->isImmutableInFunctionBody(), ArgNo);
|
||||||
if (!argrv.getType().isAddress()) {
|
if (!argrv.getType().isAddress()) {
|
||||||
// NOTE: We setup SGF.VarLocs[pd] in updateArgumentValueForBinding.
|
// NOTE: We setup SGF.VarLocs[pd] in updateArgumentValueForBinding.
|
||||||
|
|||||||
@@ -3358,9 +3358,9 @@ StorageImplInfoRequest::evaluate(Evaluator &evaluator,
|
|||||||
AbstractStorageDecl *storage) const {
|
AbstractStorageDecl *storage) const {
|
||||||
if (auto *param = dyn_cast<ParamDecl>(storage)) {
|
if (auto *param = dyn_cast<ParamDecl>(storage)) {
|
||||||
return StorageImplInfo::getSimpleStored(
|
return StorageImplInfo::getSimpleStored(
|
||||||
param->isInOut()
|
param->isImmutableInFunctionBody()
|
||||||
? StorageIsMutable
|
? StorageIsNotMutable
|
||||||
: StorageIsNotMutable);
|
: StorageIsMutable);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto *var = dyn_cast<VarDecl>(storage)) {
|
if (auto *var = dyn_cast<VarDecl>(storage)) {
|
||||||
|
|||||||
29
test/SILGen/consuming_parameter.swift
Normal file
29
test/SILGen/consuming_parameter.swift
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// RUN: %target-swift-emit-silgen %s | %FileCheck %s
|
||||||
|
|
||||||
|
func bar(_: String) {}
|
||||||
|
|
||||||
|
// CHECK-LABEL: sil {{.*}} @${{.*}}3foo
|
||||||
|
func foo(y: consuming String, z: String) -> () -> String {
|
||||||
|
// CHECK: bb0(%0 : @owned $String, %1 : @guaranteed $String):
|
||||||
|
// CHECK: [[BOX:%.*]] = alloc_box ${ var String }
|
||||||
|
// CHECK: [[BOX0:%.*]] = mark_uninitialized [var] [[BOX]]
|
||||||
|
// CHECK: [[BOX1:%.*]] = begin_borrow [lexical] [[BOX0]]
|
||||||
|
// CHECK: [[Y:%.*]] = project_box [[BOX1]]
|
||||||
|
// CHECK: store %0 to [init] [[Y]]
|
||||||
|
|
||||||
|
// CHECK: [[YCAPTURE:%.*]] = copy_value [[BOX1]]
|
||||||
|
// CHECK: partial_apply {{.*}} {{%.*}}([[YCAPTURE]])
|
||||||
|
let r = { y }
|
||||||
|
|
||||||
|
// CHECK: [[ZCOPY:%.*]] = copy_value %1
|
||||||
|
// CHECK: [[YACCESS:%.*]] = begin_access [modify] [unknown] [[Y]]
|
||||||
|
// CHECK: assign [[ZCOPY]] to [[YACCESS]]
|
||||||
|
y = z
|
||||||
|
|
||||||
|
// CHECK: [[YACCESS:%.*]] = begin_access [read] [unknown] [[Y]]
|
||||||
|
// CHECK: [[YVAL:%.*]] = load [copy] [[YACCESS]]
|
||||||
|
// CHECK: apply {{%.*}}([[YVAL]]
|
||||||
|
bar(y)
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user