Skip to content

Commit b4dceb6

Browse files
authored
Merge pull request #59122 from jckarter/result-conversion-fix
SILGen: Complete initialization of FinalContext in ConversionInitialization::tryPeephole
2 parents 93fef05 + 8db31d5 commit b4dceb6

File tree

5 files changed

+126
-79
lines changed

5 files changed

+126
-79
lines changed

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2795,7 +2795,7 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
27952795
if (parseSILDebugLocation(InstLoc, B))
27962796
return true;
27972797
ResultVal = B.createAllocBox(InstLoc, Ty.castTo<SILBoxType>(), VarInfo,
2798-
hasDynamicLifetime);
2798+
hasDynamicLifetime, hasReflection);
27992799
break;
28002800
}
28012801
case SILInstructionKind::ApplyInst:

lib/SILGen/Conversion.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -231,13 +231,6 @@ canPeepholeConversions(SILGenFunction &SGF,
231231
const Conversion &outerConversion,
232232
const Conversion &innerConversion);
233233

234-
ManagedValue emitPeepholedConversions(SILGenFunction &SGF, SILLocation loc,
235-
const Conversion &outerConversion,
236-
const Conversion &innerConversion,
237-
ConversionPeepholeHint hint,
238-
SGFContext C,
239-
ValueProducerRef produceValue);
240-
241234
/// An initialization where we ultimately want to apply a conversion to
242235
/// the value before completing the initialization.
243236
///
@@ -354,8 +347,6 @@ class ConvertingInitialization final : public Initialization {
354347
void finishInitialization(SILGenFunction &SGF) override {
355348
assert(getState() == Initialized);
356349
State = Finished;
357-
if (OwnedSubInitialization)
358-
OwnedSubInitialization->finishInitialization(SGF);
359350
}
360351
};
361352

lib/SILGen/SILGenConvert.cpp

Lines changed: 75 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,69 @@ ConvertingInitialization::finishEmission(SILGenFunction &SGF,
10741074
llvm_unreachable("bad state");
10751075
}
10761076

1077+
static ManagedValue
1078+
emitPeepholedConversions(SILGenFunction &SGF, SILLocation loc,
1079+
const Conversion &outerConversion,
1080+
const Conversion &innerConversion,
1081+
ConversionPeepholeHint hint,
1082+
SGFContext C,
1083+
ValueProducerRef produceOrigValue) {
1084+
auto produceValue = [&](SGFContext C) {
1085+
if (!hint.isForced()) {
1086+
return produceOrigValue(SGF, loc, C);
1087+
}
1088+
1089+
auto value = produceOrigValue(SGF, loc, SGFContext());
1090+
auto &optTL = SGF.getTypeLowering(value.getType());
1091+
// isForceUnwrap is hardcoded true because hint.isForced() is only
1092+
// set by implicit force unwraps.
1093+
return SGF.emitCheckedGetOptionalValueFrom(loc, value,
1094+
/*isForceUnwrap*/ true,
1095+
optTL, C);
1096+
};
1097+
1098+
auto getBridgingSourceType = [&] {
1099+
CanType sourceType = innerConversion.getBridgingSourceType();
1100+
if (hint.isForced())
1101+
sourceType = sourceType.getOptionalObjectType();
1102+
return sourceType;
1103+
};
1104+
auto getBridgingResultType = [&] {
1105+
return outerConversion.getBridgingResultType();
1106+
};
1107+
auto getBridgingLoweredResultType = [&] {
1108+
return outerConversion.getBridgingLoweredResultType();
1109+
};
1110+
1111+
switch (hint.getKind()) {
1112+
case ConversionPeepholeHint::Identity:
1113+
return produceValue(C);
1114+
1115+
case ConversionPeepholeHint::BridgeToAnyObject: {
1116+
auto value = produceValue(SGFContext());
1117+
return SGF.emitNativeToBridgedValue(loc, value, getBridgingSourceType(),
1118+
getBridgingResultType(),
1119+
getBridgingLoweredResultType(), C);
1120+
}
1121+
1122+
case ConversionPeepholeHint::Subtype: {
1123+
// Otherwise, emit and convert.
1124+
// TODO: if the context allows +0, use it in more situations.
1125+
auto value = produceValue(SGFContext());
1126+
SILType loweredResultTy = getBridgingLoweredResultType();
1127+
1128+
// Nothing to do if the value already has the right representation.
1129+
if (value.getType().getObjectType() == loweredResultTy.getObjectType())
1130+
return value;
1131+
1132+
CanType sourceType = getBridgingSourceType();
1133+
CanType resultType = getBridgingResultType();
1134+
return SGF.emitTransformedValue(loc, value, sourceType, resultType, C);
1135+
}
1136+
}
1137+
llvm_unreachable("bad kind");
1138+
}
1139+
10771140
bool ConvertingInitialization::tryPeephole(SILGenFunction &SGF,
10781141
SILLocation loc,
10791142
ManagedValue origValue,
@@ -1104,6 +1167,15 @@ bool ConvertingInitialization::tryPeephole(SILGenFunction &SGF, SILLocation loc,
11041167
ManagedValue value = emitPeepholedConversions(SGF, loc, outerConversion,
11051168
innerConversion, *hint,
11061169
FinalContext, produceValue);
1170+
1171+
// The callers to tryPeephole assume that the initialization is ready to be
1172+
// finalized after returning. If this conversion sits on top of another
1173+
// initialization, forward the value into the underlying initialization and
1174+
// report the value as emitted in context.
1175+
if (FinalContext.getEmitInto() && !value.isInContext()) {
1176+
value.ensurePlusOne(SGF, loc).forwardInto(SGF, loc, FinalContext.getEmitInto());
1177+
value = ManagedValue::forInContext();
1178+
}
11071179
setConvertedValue(value);
11081180
return true;
11091181
}
@@ -1117,15 +1189,11 @@ void ConvertingInitialization::copyOrInitValueInto(SILGenFunction &SGF,
11171189
// TODO: take advantage of borrowed inputs?
11181190
if (!isInit) formalValue = formalValue.copy(SGF, loc);
11191191
State = Initialized;
1120-
SGFContext emissionContext = OwnedSubInitialization
1121-
? SGFContext() : FinalContext;
11221192

1123-
Value = TheConversion.emit(SGF, loc, formalValue, emissionContext);
1193+
Value = TheConversion.emit(SGF, loc, formalValue, FinalContext);
11241194

1125-
if (OwnedSubInitialization) {
1126-
OwnedSubInitialization->copyOrInitValueInto(SGF, loc,
1127-
Value,
1128-
isInit);
1195+
if (FinalContext.getEmitInto() && !Value.isInContext()) {
1196+
Value.forwardInto(SGF, loc, FinalContext.getEmitInto());
11291197
Value = ManagedValue::forInContext();
11301198
}
11311199
}
@@ -1512,65 +1580,3 @@ Lowering::canPeepholeConversions(SILGenFunction &SGF,
15121580
llvm_unreachable("bad kind");
15131581
}
15141582

1515-
ManagedValue
1516-
Lowering::emitPeepholedConversions(SILGenFunction &SGF, SILLocation loc,
1517-
const Conversion &outerConversion,
1518-
const Conversion &innerConversion,
1519-
ConversionPeepholeHint hint,
1520-
SGFContext C,
1521-
ValueProducerRef produceOrigValue) {
1522-
auto produceValue = [&](SGFContext C) {
1523-
if (!hint.isForced()) {
1524-
return produceOrigValue(SGF, loc, C);
1525-
}
1526-
1527-
auto value = produceOrigValue(SGF, loc, SGFContext());
1528-
auto &optTL = SGF.getTypeLowering(value.getType());
1529-
// isForceUnwrap is hardcoded true because hint.isForced() is only
1530-
// set by implicit force unwraps.
1531-
return SGF.emitCheckedGetOptionalValueFrom(loc, value,
1532-
/*isForceUnwrap*/ true,
1533-
optTL, C);
1534-
};
1535-
1536-
auto getBridgingSourceType = [&] {
1537-
CanType sourceType = innerConversion.getBridgingSourceType();
1538-
if (hint.isForced())
1539-
sourceType = sourceType.getOptionalObjectType();
1540-
return sourceType;
1541-
};
1542-
auto getBridgingResultType = [&] {
1543-
return outerConversion.getBridgingResultType();
1544-
};
1545-
auto getBridgingLoweredResultType = [&] {
1546-
return outerConversion.getBridgingLoweredResultType();
1547-
};
1548-
1549-
switch (hint.getKind()) {
1550-
case ConversionPeepholeHint::Identity:
1551-
return produceValue(C);
1552-
1553-
case ConversionPeepholeHint::BridgeToAnyObject: {
1554-
auto value = produceValue(SGFContext());
1555-
return SGF.emitNativeToBridgedValue(loc, value, getBridgingSourceType(),
1556-
getBridgingResultType(),
1557-
getBridgingLoweredResultType(), C);
1558-
}
1559-
1560-
case ConversionPeepholeHint::Subtype: {
1561-
// Otherwise, emit and convert.
1562-
// TODO: if the context allows +0, use it in more situations.
1563-
auto value = produceValue(SGFContext());
1564-
SILType loweredResultTy = getBridgingLoweredResultType();
1565-
1566-
// Nothing to do if the value already has the right representation.
1567-
if (value.getType().getObjectType() == loweredResultTy.getObjectType())
1568-
return value;
1569-
1570-
CanType sourceType = getBridgingSourceType();
1571-
CanType resultType = getBridgingResultType();
1572-
return SGF.emitTransformedValue(loc, value, sourceType, resultType, C);
1573-
}
1574-
}
1575-
llvm_unreachable("bad kind");
1576-
}

test/SIL/Parser/boxes.sil

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,21 @@ sil [ossa] @address_of_box : $@convention(thin) (@in { var Int }, @in <T> { let
8989
entry(%0 : $*{ var Int }, %1 : $*<T> { let T } <Int>):
9090
unreachable
9191
}
92+
93+
// CHECK-LABEL: sil [ossa] @alloc_box_attrs
94+
sil [ossa] @alloc_box_attrs : $@convention(thin) () -> () {
95+
entry:
96+
// CHECK: %0 = alloc_box $
97+
%0 = alloc_box ${ let Int }
98+
// CHECK: %1 = alloc_box [dynamic_lifetime] $
99+
%1 = alloc_box [dynamic_lifetime] ${ let Int }
100+
// CHECK: %2 = alloc_box [reflection] $
101+
%2 = alloc_box [reflection] ${ let Int }
102+
// CHECK: %3 = alloc_box [dynamic_lifetime] [reflection] $
103+
%3 = alloc_box [dynamic_lifetime] [reflection] ${ let Int }
104+
dealloc_box %3: ${ let Int }
105+
dealloc_box %2: ${ let Int }
106+
dealloc_box %1: ${ let Int }
107+
dealloc_box %0: ${ let Int }
108+
return undef : $()
109+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %target-swift-emit-silgen -verify %s
2+
3+
fileprivate typealias Closure = () -> Void
4+
5+
func crash1() {
6+
let closure1: Closure? = nil
7+
let closure2: Closure? = nil
8+
let closure3: Closure? = nil
9+
print("Closures: \(String(describing: closure1)), \(String(describing: closure2)), \(String(describing: closure3))")
10+
11+
let closure = closure1 ?? closure2 ?? closure3
12+
13+
print("\(#line): \(String(describing: closure))")
14+
closure?() // <- EXC_BAD_ACCESS
15+
assert(closure == nil)
16+
}
17+
18+
func crash2() {
19+
let closure1: Closure? = nil
20+
let closure2: Closure? = nil
21+
let closure3: Closure? = { }
22+
print("Closures: \(String(describing: closure1)), \(String(describing: closure2)), \(String(describing: closure3))")
23+
24+
let closure = closure1 ?? closure2 ?? closure3
25+
26+
print("\(#line): \(String(describing: closure))")
27+
closure?() // <- EXC_BAD_ACCESS
28+
assert(closure != nil)
29+
}
30+
31+
crash1()
32+
crash2()

0 commit comments

Comments
 (0)