Skip to content
Merged
6 changes: 4 additions & 2 deletions include/swift/SIL/SILBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -797,9 +797,11 @@ class SILBuilder {
}

ConvertEscapeToNoEscapeInst *
createConvertEscapeToNoEscape(SILLocation Loc, SILValue Op, SILType Ty) {
createConvertEscapeToNoEscape(SILLocation Loc, SILValue Op, SILType Ty,
bool lifetimeGuaranteed) {
return insert(ConvertEscapeToNoEscapeInst::create(
getSILDebugLocation(Loc), Op, Ty, getFunction(), OpenedArchetypes));
getSILDebugLocation(Loc), Op, Ty, getFunction(), OpenedArchetypes,
lifetimeGuaranteed));
}

ThinFunctionToPointerInst *
Expand Down
8 changes: 4 additions & 4 deletions include/swift/SIL/SILCloner.h
Original file line number Diff line number Diff line change
Expand Up @@ -984,10 +984,10 @@ template <typename ImplClass>
void SILCloner<ImplClass>::visitConvertEscapeToNoEscapeInst(
ConvertEscapeToNoEscapeInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(Inst, getBuilder().createConvertEscapeToNoEscape(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
doPostProcess(
Inst, getBuilder().createConvertEscapeToNoEscape(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
getOpType(Inst->getType()), Inst->isLifetimeGuaranteed()));
}

template<typename ImplClass>
Expand Down
16 changes: 12 additions & 4 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -3946,18 +3946,26 @@ class ConvertEscapeToNoEscapeInst final
ConvertEscapeToNoEscapeInst, ConversionInst> {
friend SILBuilder;

bool lifetimeGuaranteed;

ConvertEscapeToNoEscapeInst(SILDebugLocation DebugLoc, SILValue Operand,
ArrayRef<SILValue> TypeDependentOperands,
SILType Ty)
ArrayRef<SILValue> TypeDependentOperands,
SILType Ty, bool isLifetimeGuaranteed)
: UnaryInstructionWithTypeDependentOperandsBase(
DebugLoc, Operand, TypeDependentOperands, Ty) {
DebugLoc, Operand, TypeDependentOperands, Ty),
lifetimeGuaranteed(isLifetimeGuaranteed) {
assert(!Operand->getType().castTo<SILFunctionType>()->isNoEscape());
assert(Ty.castTo<SILFunctionType>()->isNoEscape());
}

static ConvertEscapeToNoEscapeInst *
create(SILDebugLocation DebugLoc, SILValue Operand, SILType Ty,
SILFunction &F, SILOpenedArchetypesState &OpenedArchetypes);
SILFunction &F, SILOpenedArchetypesState &OpenedArchetypes,
bool lifetimeGuaranteed);
public:
bool isLifetimeGuaranteed() const {
return lifetimeGuaranteed;
}
};

/// ThinFunctionToPointerInst - Convert a thin function pointer to a
Expand Down
2 changes: 1 addition & 1 deletion include/swift/Serialization/ModuleFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
/// Don't worry about adhering to the 80-column limit for this line.
const uint16_t VERSION_MINOR = 404; // Last change: inheritsSuperclassInitializers
const uint16_t VERSION_MINOR = 407; // Last change: convert_escape_to_noescape

using DeclIDField = BCFixed<31>;

Expand Down
3 changes: 2 additions & 1 deletion lib/IRGen/LoadableByAddress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2494,7 +2494,8 @@ void LoadableByAddress::recreateConvInstrs() {
case SILInstructionKind::ConvertEscapeToNoEscapeInst: {
auto instr = cast<ConvertEscapeToNoEscapeInst>(convInstr);
newInstr = convBuilder.createConvertEscapeToNoEscape(
instr->getLoc(), instr->getOperand(), newType);
instr->getLoc(), instr->getOperand(), newType,
instr->isLifetimeGuaranteed());
break;
}
case SILInstructionKind::MarkDependenceInst: {
Expand Down
6 changes: 5 additions & 1 deletion lib/ParseSIL/ParseSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2979,6 +2979,10 @@ bool SILParser::parseSILInstruction(SILBuilder &B) {
SILType Ty;
Identifier ToToken;
SourceLoc ToLoc;
bool guaranteed = true;
if (Opcode == SILInstructionKind::ConvertEscapeToNoEscapeInst)
if(parseSILOptional(guaranteed, *this, "not_guaranteed"))
return true;
if (parseTypedValueRef(Val, B) ||
parseSILIdentifier(ToToken, ToLoc,
diag::expected_tok_in_sil_instr, "to") ||
Expand Down Expand Up @@ -3012,7 +3016,7 @@ bool SILParser::parseSILInstruction(SILBuilder &B) {
ResultVal = B.createConvertFunction(InstLoc, Val, Ty);
break;
case SILInstructionKind::ConvertEscapeToNoEscapeInst:
ResultVal = B.createConvertEscapeToNoEscape(InstLoc, Val, Ty);
ResultVal = B.createConvertEscapeToNoEscape(InstLoc, Val, Ty, guaranteed);
break;
case SILInstructionKind::AddressToPointerInst:
ResultVal = B.createAddressToPointer(InstLoc, Val, Ty);
Expand Down
4 changes: 2 additions & 2 deletions lib/SIL/SILInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1998,7 +1998,7 @@ ConvertFunctionInst::create(SILDebugLocation DebugLoc, SILValue Operand,

ConvertEscapeToNoEscapeInst *ConvertEscapeToNoEscapeInst::create(
SILDebugLocation DebugLoc, SILValue Operand, SILType Ty, SILFunction &F,
SILOpenedArchetypesState &OpenedArchetypes) {
SILOpenedArchetypesState &OpenedArchetypes, bool isLifetimeGuaranteed) {
SILModule &Mod = F.getModule();
SmallVector<SILValue, 8> TypeDependentOperands;
collectTypeDependentOperands(TypeDependentOperands, OpenedArchetypes, F,
Expand All @@ -2007,7 +2007,7 @@ ConvertEscapeToNoEscapeInst *ConvertEscapeToNoEscapeInst::create(
totalSizeToAlloc<swift::Operand>(1 + TypeDependentOperands.size());
void *Buffer = Mod.allocateInst(size, alignof(ConvertEscapeToNoEscapeInst));
auto *CFI = ::new (Buffer) ConvertEscapeToNoEscapeInst(
DebugLoc, Operand, TypeDependentOperands, Ty);
DebugLoc, Operand, TypeDependentOperands, Ty, isLifetimeGuaranteed);
// If we do not have lowered SIL, make sure that are not performing
// ABI-incompatible conversions.
//
Expand Down
3 changes: 2 additions & 1 deletion lib/SIL/SILPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1435,7 +1435,8 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
printUncheckedConversionInst(CI, CI->getOperand());
}
void visitConvertEscapeToNoEscapeInst(ConvertEscapeToNoEscapeInst *CI) {
printUncheckedConversionInst(CI, CI->getOperand());
*this << (CI->isLifetimeGuaranteed() ? "" : "[not_guaranteed] ")
<< getIDAndType(CI->getOperand()) << " to " << CI->getType();
}
void visitThinFunctionToPointerInst(ThinFunctionToPointerInst *CI) {
printUncheckedConversionInst(CI, CI->getOperand());
Expand Down
17 changes: 11 additions & 6 deletions lib/SILGen/SILGenBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,10 @@ ManagedValue SILGenBuilder::createConvertFunction(SILLocation loc,
return cloner.clone(result);
}

ManagedValue SILGenBuilder::createConvertEscapeToNoEscape(SILLocation loc,
ManagedValue fn,
SILType resultTy) {
ManagedValue SILGenBuilder::createConvertEscapeToNoEscape(
SILLocation loc, ManagedValue fn, SILType resultTy,
bool postponeToNoEscapeCleanup) {

auto fnType = fn.getType().castTo<SILFunctionType>();
auto resultFnType = resultTy.castTo<SILFunctionType>();

Expand All @@ -221,9 +222,13 @@ ManagedValue SILGenBuilder::createConvertEscapeToNoEscape(SILLocation loc,
!fnType->isNoEscape() && resultFnType->isNoEscape() &&
"Expect a escaping to noescape conversion");

SILValue fnValue = fn.ensurePlusOne(SGF, loc).forward(SGF);
SILValue result = createConvertEscapeToNoEscape(loc, fnValue, resultTy);
getSILGenFunction().enterPostponedCleanup(fnValue);
SILValue fnValue = postponeToNoEscapeCleanup
? fn.ensurePlusOne(SGF, loc).forward(SGF)
: fn.getValue();
SILValue result = createConvertEscapeToNoEscape(loc, fnValue, resultTy,
postponeToNoEscapeCleanup);
if (postponeToNoEscapeCleanup)
getSILGenFunction().enterPostponedCleanup(fnValue);
return ManagedValue::forTrivialObjectRValue(result);
}

Expand Down
6 changes: 4 additions & 2 deletions lib/SILGen/SILGenBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,10 @@ class SILGenBuilder : public SILBuilder {
SILType resultTy);

using SILBuilder::createConvertEscapeToNoEscape;
ManagedValue createConvertEscapeToNoEscape(SILLocation loc, ManagedValue fn,
SILType resultTy);
ManagedValue
createConvertEscapeToNoEscape(SILLocation loc, ManagedValue fn,
SILType resultTy,
bool postponeToNoEscapeCleanup = true);

using SILBuilder::createStore;
/// Forward \p value into \p address.
Expand Down
7 changes: 5 additions & 2 deletions lib/SILGen/SILGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2090,8 +2090,11 @@ RValue RValueEmitter::visitFunctionConversionExpr(FunctionConversionExpr *e,
if (srcRepTy != srcTy)
result = convertFunctionRepresentation(SGF, e, result, srcRepTy, srcTy);

if (srcTy != destTy)
result = SGF.emitTransformedValue(e, result, srcTy, destTy);
if (srcTy != destTy) {
bool postponeToNoEscapeCleanup = !isa<BindOptionalExpr>(e->getSubExpr());
result = SGF.emitTransformedValue(e, result, srcTy, destTy, SGFContext(),
postponeToNoEscapeCleanup);
}

if (destTy != destRepTy)
result = convertFunctionRepresentation(SGF, e, result, destTy, destRepTy);
Expand Down
6 changes: 4 additions & 2 deletions lib/SILGen/SILGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1617,15 +1617,17 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
ManagedValue emitTransformedValue(SILLocation loc, ManagedValue input,
CanType inputType,
CanType outputType,
SGFContext ctx = SGFContext());
SGFContext ctx = SGFContext(),
bool postponeToNoEscapeCleanup = true);

/// Most general form of the above.
ManagedValue emitTransformedValue(SILLocation loc, ManagedValue input,
AbstractionPattern inputOrigType,
CanType inputSubstType,
AbstractionPattern outputOrigType,
CanType outputSubstType,
SGFContext ctx = SGFContext());
SGFContext ctx = SGFContext(),
bool postponeToNoEscapeCleanup = true);
RValue emitTransformedValue(SILLocation loc, RValue &&input,
AbstractionPattern inputOrigType,
CanType inputSubstType,
Expand Down
29 changes: 19 additions & 10 deletions lib/SILGen/SILGenPoly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ namespace {
CanType inputSubstType,
AbstractionPattern outputOrigType,
CanType outputSubstType,
SGFContext ctxt);
SGFContext ctxt,
bool postponeToNoEscapeCleanup = true);

/// Transform a metatype value.
ManagedValue transformMetatype(ManagedValue fn,
Expand All @@ -159,7 +160,8 @@ namespace {
CanAnyFunctionType inputSubstType,
AbstractionPattern outputOrigType,
CanAnyFunctionType outputSubstType,
const TypeLowering &expectedTL);
const TypeLowering &expectedTL,
bool postponeToNoEscapeCleanup = true);
};
} // end anonymous namespace
;
Expand Down Expand Up @@ -356,7 +358,8 @@ ManagedValue Transform::transform(ManagedValue v,
CanType inputSubstType,
AbstractionPattern outputOrigType,
CanType outputSubstType,
SGFContext ctxt) {
SGFContext ctxt,
bool postponeToNoEscapeCleanup) {
// Look through inout types.
if (isa<InOutType>(inputSubstType))
inputSubstType = CanType(inputSubstType->getInOutObjectType());
Expand Down Expand Up @@ -440,7 +443,8 @@ ManagedValue Transform::transform(ManagedValue v,
return transformFunction(v,
inputOrigType, inputFnType,
outputOrigType, outputFnType,
expectedTL);
expectedTL,
postponeToNoEscapeCleanup);
}

// - tuples of transformable values
Expand Down Expand Up @@ -3041,7 +3045,8 @@ ManagedValue Transform::transformFunction(ManagedValue fn,
CanAnyFunctionType inputSubstType,
AbstractionPattern outputOrigType,
CanAnyFunctionType outputSubstType,
const TypeLowering &expectedTL) {
const TypeLowering &expectedTL,
bool postponeToNoEscapeCleanup) {
assert(fn.getType().isObject() &&
"expected input to emitTransformedFunctionValue to be loaded");

Expand Down Expand Up @@ -3100,7 +3105,8 @@ ManagedValue Transform::transformFunction(ManagedValue fn,
} else if (newFnType != expectedFnType) {
// Escaping to noescape conversion.
SILType resTy = SILType::getPrimitiveObjectType(expectedFnType);
fn = SGF.B.createConvertEscapeToNoEscape(Loc, fn, resTy);
fn = SGF.B.createConvertEscapeToNoEscape(Loc, fn, resTy,
postponeToNoEscapeCleanup);
}

return fn;
Expand Down Expand Up @@ -3196,11 +3202,12 @@ ManagedValue
SILGenFunction::emitTransformedValue(SILLocation loc, ManagedValue v,
CanType inputType,
CanType outputType,
SGFContext ctxt) {
SGFContext ctxt,
bool postponeToNoEscapeCleanup) {
return emitTransformedValue(loc, v,
AbstractionPattern(inputType), inputType,
AbstractionPattern(outputType), outputType,
ctxt);
ctxt, postponeToNoEscapeCleanup);
}

ManagedValue
Expand All @@ -3209,12 +3216,14 @@ SILGenFunction::emitTransformedValue(SILLocation loc, ManagedValue v,
CanType inputSubstType,
AbstractionPattern outputOrigType,
CanType outputSubstType,
SGFContext ctxt) {
SGFContext ctxt,
bool postponeToNoEscapeCleanup) {
return Transform(*this, loc).transform(v,
inputOrigType,
inputSubstType,
outputOrigType,
outputSubstType, ctxt);
outputSubstType, ctxt,
postponeToNoEscapeCleanup);
}

RValue
Expand Down
4 changes: 2 additions & 2 deletions lib/SILOptimizer/IPO/ClosureSpecializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -662,8 +662,8 @@ SILValue ClosureSpecCloner::cloneCalleeConversion(SILValue calleeValue,

auto *Cvt = cast<ConvertEscapeToNoEscapeInst>(calleeValue);
calleeValue = cloneCalleeConversion(Cvt->getOperand(), NewClosure, Builder);
return Builder.createConvertEscapeToNoEscape(CallSiteDesc.getLoc(),
calleeValue, Cvt->getType());
return Builder.createConvertEscapeToNoEscape(
CallSiteDesc.getLoc(), calleeValue, Cvt->getType(), true);
}

/// \brief Populate the body of the cloned closure, modifying instructions as
Expand Down
Loading