Skip to content

Commit ae83fdd

Browse files
committed
---
yaml --- r: 347500 b: refs/heads/master c: 98cb213 h: refs/heads/master
1 parent 18129f9 commit ae83fdd

File tree

7 files changed

+125
-59
lines changed

7 files changed

+125
-59
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: 690e0ce56df8b56bb500f97f3dbe0ca73ae797ab
2+
refs/heads/master: 98cb213a07320729d66cebac690521a3856c539d
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/SILGenPattern.cpp

Lines changed: 89 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2497,37 +2497,55 @@ class Lowering::PatternMatchContext {
24972497
PatternMatchEmission &Emission;
24982498
};
24992499

2500+
namespace {
2501+
2502+
struct UnexpectedEnumCaseInfo {
2503+
CanType subjectTy;
2504+
ManagedValue metatype;
2505+
ManagedValue rawValue;
2506+
NullablePtr<const EnumDecl> singleObjCEnum;
2507+
2508+
UnexpectedEnumCaseInfo(CanType subjectTy, ManagedValue metatype,
2509+
ManagedValue rawValue, const EnumDecl *singleObjCEnum)
2510+
: subjectTy(subjectTy), metatype(metatype), rawValue(rawValue),
2511+
singleObjCEnum(singleObjCEnum) {
2512+
assert(isa<MetatypeInst>(metatype));
2513+
assert(bool(rawValue) && isa<UncheckedTrivialBitCastInst>(rawValue));
2514+
assert(singleObjCEnum->hasRawType());
2515+
}
2516+
2517+
UnexpectedEnumCaseInfo(CanType subjectTy, ManagedValue valueMetatype)
2518+
: subjectTy(subjectTy), metatype(valueMetatype), rawValue(),
2519+
singleObjCEnum() {
2520+
assert(isa<ValueMetatypeInst>(valueMetatype));
2521+
}
2522+
2523+
bool isSingleObjCEnum() const { return singleObjCEnum.isNonNull(); }
2524+
2525+
void cleanupInstsIfUnused() {
2526+
auto f = [](SILValue v) {
2527+
if (!v->use_empty())
2528+
return;
2529+
cast<SingleValueInstruction>(v)->eraseFromParent();
2530+
};
2531+
f(metatype.getValue());
2532+
if (rawValue)
2533+
f(rawValue.getValue());
2534+
}
2535+
};
2536+
2537+
} // end anonymous namespace
2538+
25002539
static void emitDiagnoseOfUnexpectedEnumCaseValue(SILGenFunction &SGF,
25012540
SILLocation loc,
2502-
ManagedValue value,
2503-
Type subjectTy,
2504-
const EnumDecl *enumDecl) {
2541+
UnexpectedEnumCaseInfo ueci) {
25052542
ASTContext &ctx = SGF.getASTContext();
25062543
auto diagnoseFailure = ctx.getDiagnoseUnexpectedEnumCaseValue();
25072544
if (!diagnoseFailure) {
25082545
SGF.B.createBuiltinTrap(loc);
25092546
return;
25102547
}
25112548

2512-
assert(enumDecl->isObjC());
2513-
assert(enumDecl->hasRawType());
2514-
assert(value.getType().isTrivial(SGF.F));
2515-
2516-
// Get the enum type as an Any.Type value.
2517-
SILType metatypeType = SGF.getLoweredType(
2518-
AbstractionPattern::getOpaque(),
2519-
MetatypeType::get(subjectTy));
2520-
SILValue metatype = SGF.B.createMetatype(loc, metatypeType);
2521-
2522-
// Bitcast the enum value to its raw type. (This is only safe for @objc
2523-
// enums.)
2524-
SILType loweredRawType = SGF.getLoweredType(enumDecl->getRawType());
2525-
assert(loweredRawType.isTrivial(SGF.F));
2526-
assert(loweredRawType.isObject());
2527-
auto rawValue = SGF.B.createUncheckedTrivialBitCast(loc, value,
2528-
loweredRawType);
2529-
auto materializedRawValue = rawValue.materialize(SGF, loc);
2530-
25312549
auto genericSig = diagnoseFailure->getGenericSignature();
25322550
auto subs = SubstitutionMap::get(
25332551
genericSig,
@@ -2537,49 +2555,40 @@ static void emitDiagnoseOfUnexpectedEnumCaseValue(SILGenFunction &SGF,
25372555
assert(genericParam->getIndex() < 2);
25382556
switch (genericParam->getIndex()) {
25392557
case 0:
2540-
return subjectTy;
2558+
return ueci.subjectTy;
25412559

25422560
case 1:
2543-
return enumDecl->getRawType();
2561+
return ueci.singleObjCEnum.get()->getRawType();
25442562

25452563
default:
25462564
llvm_unreachable("wrong generic signature for expected case value");
25472565
}
25482566
},
25492567
LookUpConformanceInSignature(*genericSig));
25502568

2551-
SGF.emitApplyOfLibraryIntrinsic(loc, diagnoseFailure, subs,
2552-
{ManagedValue::forUnmanaged(metatype),
2553-
materializedRawValue},
2554-
SGFContext());
2569+
SGF.emitApplyOfLibraryIntrinsic(
2570+
loc, diagnoseFailure, subs,
2571+
{ueci.metatype, ueci.rawValue.materialize(SGF, loc)}, SGFContext());
25552572
}
25562573

25572574
static void emitDiagnoseOfUnexpectedEnumCase(SILGenFunction &SGF,
25582575
SILLocation loc,
2559-
ManagedValue value,
2560-
Type subjectTy) {
2576+
UnexpectedEnumCaseInfo ueci) {
25612577
ASTContext &ctx = SGF.getASTContext();
25622578
auto diagnoseFailure = ctx.getDiagnoseUnexpectedEnumCase();
25632579
if (!diagnoseFailure) {
25642580
SGF.B.createBuiltinTrap(loc);
25652581
return;
25662582
}
25672583

2568-
// Get the switched-upon value's type.
2569-
SILType metatypeType = SGF.getLoweredType(
2570-
AbstractionPattern::getOpaque(),
2571-
MetatypeType::get(subjectTy)->getCanonicalType());
2572-
ManagedValue metatype = SGF.B.createValueMetatype(loc, metatypeType, value);
2573-
25742584
auto diagnoseSignature = diagnoseFailure->getGenericSignature();
25752585
auto genericArgsMap = SubstitutionMap::get(
25762586
diagnoseSignature,
2577-
[&](SubstitutableType *type) -> Type { return subjectTy; },
2587+
[&](SubstitutableType *type) -> Type { return ueci.subjectTy; },
25782588
LookUpConformanceInSignature(*diagnoseSignature));
25792589

25802590
SGF.emitApplyOfLibraryIntrinsic(loc, diagnoseFailure, genericArgsMap,
2581-
metatype,
2582-
SGFContext());
2591+
ueci.metatype, SGFContext());
25832592
}
25842593

25852594
static void switchCaseStmtSuccessCallback(SILGenFunction &SGF,
@@ -2778,6 +2787,38 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
27782787
return {subjectMV.copy(*this, S), CastConsumptionKind::TakeAlways};
27792788
}());
27802789

2790+
// If we need to diagnose an unexpected enum case or unexpected enum case
2791+
// value, we need access to a value metatype for the subject. Emit this state
2792+
// now before we emit the actual switch to ensure that the subject has not
2793+
// been consumed.
2794+
auto unexpectedEnumCaseInfo = ([&]() -> UnexpectedEnumCaseInfo {
2795+
SILLocation loc = RegularLocation::getAutoGeneratedLocation();
2796+
CanType canSubjectTy = subjectTy->getCanonicalType();
2797+
CanType metatypeType = MetatypeType::get(canSubjectTy)->getCanonicalType();
2798+
SILType loweredMetatypeType =
2799+
getLoweredType(AbstractionPattern::getOpaque(), metatypeType);
2800+
ManagedValue value = subject.getFinalManagedValue();
2801+
2802+
if (auto *singleEnumDecl = canSubjectTy->getEnumOrBoundGenericEnum()) {
2803+
if (singleEnumDecl->isObjC()) {
2804+
auto metatype = ManagedValue::forUnmanaged(
2805+
B.createMetatype(loc, loweredMetatypeType));
2806+
2807+
// Bitcast the enum value to its raw type. (This is only safe for @objc
2808+
// enums.)
2809+
SILType loweredRawType = getLoweredType(singleEnumDecl->getRawType());
2810+
assert(loweredRawType.isTrivial(F));
2811+
assert(loweredRawType.isObject());
2812+
auto rawValue =
2813+
B.createUncheckedTrivialBitCast(loc, value, loweredRawType);
2814+
return {canSubjectTy, metatype, rawValue, singleEnumDecl};
2815+
}
2816+
}
2817+
2818+
return {canSubjectTy,
2819+
B.createValueMetatype(loc, loweredMetatypeType, value)};
2820+
}());
2821+
27812822
auto failure = [&](SILLocation location) {
27822823
// If we fail to match anything, we trap. This can happen with a switch
27832824
// over an @objc enum, which may contain any value of its underlying type,
@@ -2786,18 +2827,12 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
27862827
SWIFT_DEFER { B.createUnreachable(location); };
27872828

27882829
// Special case: if it's a single @objc enum, we can print the raw value.
2789-
CanType ty = S->getSubjectExpr()->getType()->getCanonicalType();
2790-
if (auto *singleEnumDecl = ty->getEnumOrBoundGenericEnum()) {
2791-
if (singleEnumDecl->isObjC()) {
2792-
emitDiagnoseOfUnexpectedEnumCaseValue(*this, location,
2793-
subject.getFinalManagedValue(),
2794-
subjectTy, singleEnumDecl);
2795-
return;
2796-
}
2830+
if (unexpectedEnumCaseInfo.isSingleObjCEnum()) {
2831+
emitDiagnoseOfUnexpectedEnumCaseValue(*this, location,
2832+
unexpectedEnumCaseInfo);
2833+
return;
27972834
}
2798-
emitDiagnoseOfUnexpectedEnumCase(*this, location,
2799-
subject.getFinalManagedValue(),
2800-
subjectTy);
2835+
emitDiagnoseOfUnexpectedEnumCase(*this, location, unexpectedEnumCaseInfo);
28012836
};
28022837

28032838
// Set up an initial clause matrix.
@@ -2823,6 +2858,10 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
28232858
} else {
28242859
B.emitBlock(contBB);
28252860
}
2861+
2862+
// Now that we have emitted everything, see if our unexpected enum case info
2863+
// metatypes were actually used. If not, delete them.
2864+
unexpectedEnumCaseInfo.cleanupInstsIfUnused();
28262865
}
28272866

28282867
void SILGenFunction::emitSwitchFallthrough(FallthroughStmt *S) {

trunk/test/SILGen/enum.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,8 @@ enum SR7799 {
249249
// CHECK: bb0(%0 : $Optional<SR7799>):
250250
// CHECK-NEXT: debug_value %0 : $Optional<SR7799>, let, name "bar", argno 1
251251
// CHECK-NEXT: switch_enum %0 : $Optional<SR7799>, case #Optional.some!enumelt.1: bb1, default bb4
252-
// CHECK: bb1(%3 : $SR7799):
253-
// CHECK-NEXT: switch_enum %3 : $SR7799, case #SR7799.one!enumelt: bb2, case #SR7799.two!enumelt: bb3
252+
// CHECK: bb1([[PHI_ARG:%.*]] : $SR7799):
253+
// CHECK-NEXT: switch_enum [[PHI_ARG]] : $SR7799, case #SR7799.one!enumelt: bb2, case #SR7799.two!enumelt: bb3
254254
func sr7799(bar: SR7799?) {
255255
switch bar {
256256
case .one: print("one")

trunk/test/SILGen/enum_resilience.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import resilient_enum
1212
// CHECK-LABEL: sil hidden [ossa] @$s15enum_resilience15resilientSwitchyy0c1_A06MediumOF : $@convention(thin) (@in_guaranteed Medium) -> ()
1313
// CHECK: [[BOX:%.*]] = alloc_stack $Medium
1414
// CHECK-NEXT: copy_addr %0 to [initialization] [[BOX]]
15+
// CHECK-NEXT: [[METATYPE:%.+]] = value_metatype $@thick Medium.Type, [[BOX]] : $*Medium
1516
// CHECK-NEXT: switch_enum_addr [[BOX]] : $*Medium, case #Medium.Paper!enumelt: bb1, case #Medium.Canvas!enumelt: bb2, case #Medium.Pamphlet!enumelt.1: bb3, case #Medium.Postcard!enumelt.1: bb4, default bb5
1617
// CHECK: bb1:
1718
// CHECK-NEXT: dealloc_stack [[BOX]]
@@ -32,7 +33,6 @@ import resilient_enum
3233
// CHECK-NEXT: dealloc_stack [[BOX]]
3334
// CHECK-NEXT: br bb6
3435
// CHECK: bb5:
35-
// CHECK-NEXT: [[METATYPE:%.+]] = value_metatype $@thick Medium.Type, [[BOX]] : $*Medium
3636
// CHECK-NEXT: // function_ref
3737
// CHECK-NEXT: [[DIAGNOSE:%.+]] = function_ref @$ss27_diagnoseUnexpectedEnumCase
3838
// CHECK-NEXT: = apply [[DIAGNOSE]]<Medium>([[METATYPE]]) : $@convention(thin) <τ_0_0> (@thick τ_0_0.Type) -> Never

trunk/test/SILGen/enum_resilience_testable.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
// CHECK-LABEL: sil hidden [ossa] @$s24enum_resilience_testable15resilientSwitchyy0d1_A06MediumOF : $@convention(thin) (@in_guaranteed Medium) -> ()
1818
// CHECK: [[BOX:%.*]] = alloc_stack $Medium
1919
// CHECK-NEXT: copy_addr %0 to [initialization] [[BOX]]
20+
// CHECK-NEXT: [[METATYPE:%.+]] = value_metatype $@thick Medium.Type, [[BOX]] : $*Medium
2021
// CHECK-NEXT: switch_enum_addr [[BOX]] : $*Medium, case #Medium.Paper!enumelt: bb1, case #Medium.Canvas!enumelt: bb2, case #Medium.Pamphlet!enumelt.1: bb3, case #Medium.Postcard!enumelt.1: bb4, default bb5
2122
// CHECK: bb1:
2223
// CHECK-NEXT: dealloc_stack [[BOX]]
@@ -37,7 +38,6 @@
3738
// CHECK-NEXT: dealloc_stack [[BOX]]
3839
// CHECK-NEXT: br bb6
3940
// CHECK: bb5:
40-
// CHECK-NEXT: [[METATYPE:%.+]] = value_metatype $@thick Medium.Type, [[BOX]] : $*Medium
4141
// CHECK-NEXT: // function_ref
4242
// CHECK-NEXT: [[DIAGNOSE:%.+]] = function_ref @$ss27_diagnoseUnexpectedEnumCase
4343
// CHECK-NEXT: = apply [[DIAGNOSE]]<Medium>([[METATYPE]]) : $@convention(thin) <τ_0_0> (@thick τ_0_0.Type) -> Never

trunk/test/SILGen/switch.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,8 +1029,8 @@ func testOptionalEnumMix(_ a : Int?) -> Int {
10291029
case let x?:
10301030
return 0
10311031

1032-
// CHECK: [[SOMEBB]](%3 : $Int):
1033-
// CHECK-NEXT: debug_value %3 : $Int, let, name "x"
1032+
// CHECK: [[SOMEBB]]([[X:%.*]] : $Int):
1033+
// CHECK-NEXT: debug_value [[X]] : $Int, let, name "x"
10341034
// CHECK: integer_literal $Builtin.IntLiteral, 0
10351035

10361036
case .none:
@@ -1051,8 +1051,8 @@ func testOptionalEnumMixWithNil(_ a : Int?) -> Int {
10511051
case let x?:
10521052
return 0
10531053

1054-
// CHECK: [[SOMEBB]](%3 : $Int):
1055-
// CHECK-NEXT: debug_value %3 : $Int, let, name "x"
1054+
// CHECK: [[SOMEBB]]([[X:%.*]] : $Int):
1055+
// CHECK-NEXT: debug_value [[X]] : $Int, let, name "x"
10561056
// CHECK: integer_literal $Builtin.IntLiteral, 0
10571057

10581058
case nil:

trunk/test/SILGen/switch_objc.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,30 @@ func matchesEither(input: Hive, a: Hive, b: Hive) -> Bool {
2525
return false
2626
}
2727
}
28+
29+
@objc enum ObjCEnum : UInt8 {
30+
case first
31+
case second
32+
}
33+
34+
// CHECK-LABEL: sil hidden [ossa] @$s11switch_objc44checkObjCEnumUnhandledCaseDiagnosticEmission1xyAA0dE0O_tF : $@convention(thin) (ObjCEnum) -> () {
35+
// CHECK: bb0([[ARG:%.*]] :
36+
// CHECK: [[METATYPE:%.*]] = metatype $@thick ObjCEnum.Type
37+
// CHECK: [[ARG_INT_REPR:%.*]] = unchecked_trivial_bit_cast [[ARG]]
38+
// CHECK: switch_enum [[ARG]] : $ObjCEnum, {{.*}}, default [[DEFAULT_BB:bb[0-9]+]]
39+
//
40+
// CHECK: [[DEFAULT_BB]](
41+
// CHECK: [[STACK_SLOT:%.*]] = alloc_stack $UInt8
42+
// CHECK: store [[ARG_INT_REPR]] to [trivial] [[STACK_SLOT]]
43+
// CHECK: [[DIAGNOSE_FUNC:%.*]] = function_ref @$ss32_diagnoseUnexpectedEnumCaseValue4type03rawE0s5NeverOxm_q_tr0_lF : $@convention(thin) <τ_0_0, τ_0_1> (@thick τ_0_0.Type, @in_guaranteed τ_0_1) -> Never
44+
// CHECK: apply [[DIAGNOSE_FUNC]]<ObjCEnum, UInt8>([[METATYPE]], [[STACK_SLOT]])
45+
// CHECK: unreachable
46+
// CHECK: } // end sil function '$s11switch_objc44checkObjCEnumUnhandledCaseDiagnosticEmission1xyAA0dE0O_tF'
47+
func checkObjCEnumUnhandledCaseDiagnosticEmission(x: ObjCEnum) {
48+
switch x {
49+
case .first:
50+
break
51+
case .second:
52+
break
53+
}
54+
}

0 commit comments

Comments
 (0)