Skip to content

Commit 7202dfb

Browse files
committed
---
yaml --- r: 345577 b: refs/heads/master c: 615f7b6 h: refs/heads/master i: 345575: a8f2cdd
1 parent 4dd75b2 commit 7202dfb

File tree

5 files changed

+90
-23
lines changed

5 files changed

+90
-23
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 7818220f84dd95fe0a5057bbb395acc73f1a365d
2+
refs/heads/master: 615f7b6463721f0e29ccd936a952807282c231d6
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/lib/SILGen/SILGenBuilder.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,3 +971,9 @@ void SILGenBuilder::emitDestructureValueOperation(
971971
return func(index, cloner.clone(subValue));
972972
});
973973
}
974+
975+
ManagedValue SILGenBuilder::createProjectBox(SILLocation loc, ManagedValue mv,
976+
unsigned index) {
977+
auto *pbi = SILBuilder::createProjectBox(loc, mv.getValue(), index);
978+
return ManagedValue::forUnmanaged(pbi);
979+
}

trunk/lib/SILGen/SILGenBuilder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,10 @@ class SILGenBuilder : public SILBuilder {
417417
void emitDestructureValueOperation(
418418
SILLocation loc, ManagedValue value,
419419
function_ref<void(unsigned, ManagedValue)> func);
420+
421+
using SILBuilder::createProjectBox;
422+
ManagedValue createProjectBox(SILLocation loc, ManagedValue mv,
423+
unsigned index);
420424
};
421425

422426
} // namespace Lowering

trunk/lib/SILGen/SILGenDecl.cpp

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -889,23 +889,33 @@ void EnumElementPatternInitialization::emitEnumMatch(
889889

890890
// If the payload is indirect, project it out of the box.
891891
if (eltDecl->isIndirect() || eltDecl->getParentEnum()->isIndirect()) {
892-
SILValue boxedValue = SGF.B.createProjectBox(loc, mv.getValue(), 0);
893-
auto &boxedTL = SGF.getTypeLowering(boxedValue->getType());
894-
// SEMANTIC ARC TODO: Revisit this when the verifier is enabled.
892+
ManagedValue boxedValue = SGF.B.createProjectBox(loc, mv, 0);
893+
auto &boxedTL = SGF.getTypeLowering(boxedValue.getType());
894+
895+
// We must treat the boxed value as +0 since it may be shared. Copy it
896+
// if nontrivial.
897+
//
898+
// NOTE: The APIs that we are usinng here will ensure that if we have
899+
// a trivial value, the load_borrow will become a load [trivial] and
900+
// the copies will be "automagically" elided.
895901
if (boxedTL.isLoadable() || !SGF.silConv.useLoweredAddresses()) {
896902
UnenforcedAccess access;
897-
SILValue accessAddress =
898-
access.beginAccess(SGF, loc, boxedValue, SILAccessKind::Read);
899-
boxedValue = boxedTL.emitLoad(SGF.B, loc, accessAddress,
900-
LoadOwnershipQualifier::Take);
903+
SILValue accessAddress = access.beginAccess(
904+
SGF, loc, boxedValue.getValue(), SILAccessKind::Read);
905+
auto mvAccessAddress = ManagedValue::forUnmanaged(accessAddress);
906+
{
907+
Scope loadScope(SGF, loc);
908+
ManagedValue borrowedVal =
909+
SGF.B.createLoadBorrow(loc, mvAccessAddress);
910+
mv = loadScope.popPreservingValue(
911+
borrowedVal.copyUnmanaged(SGF, loc));
912+
}
901913
access.endAccess(SGF);
914+
} else {
915+
// If we do not have a loadable value, just do a copy of the
916+
// boxedValue.
917+
mv = boxedValue.copyUnmanaged(SGF, loc);
902918
}
903-
// We must treat the boxed value as +0 since it may be shared. Copy it
904-
// if nontrivial.
905-
//
906-
// TODO: Should be able to hand it off at +0 in some cases.
907-
mv = ManagedValue::forUnmanaged(boxedValue);
908-
mv = mv.copyUnmanaged(SGF, loc);
909919
}
910920

911921
// Reabstract to the substituted type, if needed.

trunk/test/SILGen/indirect_enum.swift

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
// RUN: %target-swift-emit-silgen -module-name indirect_enum -Xllvm -sil-print-debuginfo %s | %FileCheck %s
2+
// RUN: %target-swift-emit-silgen -enable-sil-ownership -module-name indirect_enum -Xllvm -sil-print-debuginfo %s | %FileCheck %s
33

44
indirect enum TreeA<T> {
55
case Nil
@@ -151,7 +151,9 @@ func switchTreeA<T>(_ x: TreeA<T>) {
151151
// CHECK: bb0([[ARG:%.*]] : @guaranteed $TreeA<T>):
152152
// -- x +2
153153
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
154-
// CHECK: switch_enum [[ARG_COPY]] : $TreeA<T>,
154+
// CHECK: [[BORROWED_ARG_COPY:%.*]] = begin_borrow [[ARG_COPY]]
155+
// CHECK: [[ARG_COPY_2:%.*]] = copy_value [[BORROWED_ARG_COPY]]
156+
// CHECK: switch_enum [[ARG_COPY_2]] : $TreeA<T>,
155157
// CHECK: case #TreeA.Nil!enumelt: [[NIL_CASE:bb1]],
156158
// CHECK: case #TreeA.Leaf!enumelt.1: [[LEAF_CASE:bb2]],
157159
// CHECK: case #TreeA.Branch!enumelt.1: [[BRANCH_CASE:bb3]],
@@ -177,13 +179,15 @@ func switchTreeA<T>(_ x: TreeA<T>) {
177179
// CHECK: [[TUPLE_ADDR:%.*]] = project_box [[NODE_BOX]]
178180
// CHECK: [[TUPLE:%.*]] = load_borrow [[TUPLE_ADDR]]
179181
// CHECK: ([[LEFT:%.*]], [[RIGHT:%.*]]) = destructure_tuple [[TUPLE]]
180-
// CHECK: switch_enum [[LEFT]] : $TreeA<T>,
182+
// CHECK: [[LEFT_COPY:%.*]] = copy_value [[LEFT]]
183+
// CHECK: switch_enum [[LEFT_COPY]] : $TreeA<T>,
181184
// CHECK: case #TreeA.Leaf!enumelt.1: [[LEAF_CASE_LEFT:bb[0-9]+]],
182185
// CHECK: default [[FAIL_LEFT:bb[0-9]+]]
183186

184187
// CHECK: [[LEAF_CASE_LEFT]]([[LEFT_LEAF_BOX:%.*]] : @owned $<τ_0_0> { var τ_0_0 } <T>):
185188
// CHECK: [[LEFT_LEAF_VALUE:%.*]] = project_box [[LEFT_LEAF_BOX]]
186-
// CHECK: switch_enum [[RIGHT]] : $TreeA<T>,
189+
// CHECK: [[RIGHT_COPY:%.*]] = copy_value [[RIGHT]]
190+
// CHECK: switch_enum [[RIGHT_COPY]] : $TreeA<T>,
187191
// CHECK: case #TreeA.Leaf!enumelt.1: [[LEAF_CASE_RIGHT:bb[0-9]+]],
188192
// CHECK: default [[FAIL_RIGHT:bb[0-9]+]]
189193

@@ -195,10 +199,12 @@ func switchTreeA<T>(_ x: TreeA<T>) {
195199
// CHECK: destroy_value [[NODE_BOX]]
196200
// CHECK: br [[OUTER_CONT]]
197201

198-
// CHECK: [[FAIL_RIGHT]]:
202+
// CHECK: [[FAIL_RIGHT]]([[DEFAULT_VAL:%.*]] :
203+
// CHECK: destroy_value [[DEFAULT_VAL]]
199204
// CHECK: br [[DEFAULT:bb[0-9]+]]
200205

201-
// CHECK: [[FAIL_LEFT]]:
206+
// CHECK: [[FAIL_LEFT]]([[DEFAULT_VAL:%.*]] :
207+
// CHECK: destroy_value [[DEFAULT_VAL]]
202208
// CHECK: br [[DEFAULT]]
203209

204210
case .Branch(.Leaf(let x), .Leaf(let y)):
@@ -310,6 +316,27 @@ func switchTreeB<T>(_ x: TreeB<T>) {
310316
// CHECK: return
311317
}
312318

319+
// Make sure that switchTreeInt obeys ownership invariants.
320+
//
321+
// CHECK-LABEL: sil hidden @$s13indirect_enum13switchTreeInt{{[_0-9a-zA-Z]*}}F
322+
func switchTreeInt(_ x: TreeInt) {
323+
switch x {
324+
325+
case .Nil:
326+
a()
327+
328+
case .Leaf(let x):
329+
b(x)
330+
331+
case .Branch(.Leaf(let x), .Leaf(let y)):
332+
c(x, y)
333+
334+
default:
335+
d()
336+
}
337+
}
338+
// CHECK: } // end sil function '$s13indirect_enum13switchTreeInt{{[_0-9a-zA-Z]*}}F'
339+
313340
// CHECK-LABEL: sil hidden @$s13indirect_enum10guardTreeA{{[_0-9a-zA-Z]*}}F
314341
func guardTreeA<T>(_ tree: TreeA<T>) {
315342
// CHECK: bb0([[ARG:%.*]] : @guaranteed $TreeA<T>):
@@ -340,8 +367,9 @@ func guardTreeA<T>(_ tree: TreeA<T>) {
340367
// CHECK: destroy_value [[ORIGINAL_VALUE]]
341368
// CHECK: [[YES]]([[BOX:%.*]] : @owned $<τ_0_0> { var (left: TreeA<τ_0_0>, right: TreeA<τ_0_0>) } <T>):
342369
// CHECK: [[VALUE_ADDR:%.*]] = project_box [[BOX]]
343-
// CHECK: [[TUPLE:%.*]] = load [take] [[VALUE_ADDR]]
370+
// CHECK: [[TUPLE:%.*]] = load_borrow [[VALUE_ADDR]]
344371
// CHECK: [[TUPLE_COPY:%.*]] = copy_value [[TUPLE]]
372+
// CHECK: end_borrow [[TUPLE]]
345373
// CHECK: ([[L:%.*]], [[R:%.*]]) = destructure_tuple [[TUPLE_COPY]]
346374
// CHECK: destroy_value [[BOX]]
347375
guard case .Branch(left: let l, right: let r) = tree else { return }
@@ -381,16 +409,16 @@ func guardTreeA<T>(_ tree: TreeA<T>) {
381409
// CHECK: destroy_value [[ORIGINAL_VALUE]]
382410
// CHECK: [[YES]]([[BOX:%.*]] : @owned $<τ_0_0> { var (left: TreeA<τ_0_0>, right: TreeA<τ_0_0>) } <T>):
383411
// CHECK: [[VALUE_ADDR:%.*]] = project_box [[BOX]]
384-
// CHECK: [[TUPLE:%.*]] = load [take] [[VALUE_ADDR]]
412+
// CHECK: [[TUPLE:%.*]] = load_borrow [[VALUE_ADDR]]
385413
// CHECK: [[TUPLE_COPY:%.*]] = copy_value [[TUPLE]]
414+
// CHECK: end_borrow [[TUPLE]]
386415
// CHECK: ([[L:%.*]], [[R:%.*]]) = destructure_tuple [[TUPLE_COPY]]
387416
// CHECK: destroy_value [[BOX]]
388417
// CHECK: destroy_value [[R]]
389418
// CHECK: destroy_value [[L]]
390419
if case .Branch(left: let l, right: let r) = tree { }
391420
}
392421
}
393-
394422
// CHECK-LABEL: sil hidden @$s13indirect_enum10guardTreeB{{[_0-9a-zA-Z]*}}F
395423
func guardTreeB<T>(_ tree: TreeB<T>) {
396424
do {
@@ -479,6 +507,25 @@ func guardTreeB<T>(_ tree: TreeB<T>) {
479507
}
480508
}
481509

510+
// Just run guardTreeInt through the ownership verifier
511+
//
512+
// CHECK-LABEL: sil hidden @$s13indirect_enum12guardTreeInt{{[_0-9a-zA-Z]*}}F
513+
func guardTreeInt(_ tree: TreeInt) {
514+
do {
515+
guard case .Nil = tree else { return }
516+
517+
guard case .Leaf(let x) = tree else { return }
518+
519+
guard case .Branch(left: let l, right: let r) = tree else { return }
520+
}
521+
522+
do {
523+
if case .Nil = tree { }
524+
if case .Leaf(let x) = tree { }
525+
if case .Branch(left: let l, right: let r) = tree { }
526+
}
527+
}
528+
482529
// SEMANTIC ARC TODO: This test needs to be made far more comprehensive.
483530
// CHECK-LABEL: sil hidden @$s13indirect_enum35dontDisableCleanupOfIndirectPayloadyyAA010TrivialButG0OF : $@convention(thin) (@guaranteed TrivialButIndirect) -> () {
484531
func dontDisableCleanupOfIndirectPayload(_ x: TrivialButIndirect) {

0 commit comments

Comments
 (0)