From 5f7f6e464f959589e50c8fa50dad3d199de852ed Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Fri, 30 Sep 2022 15:49:56 -0700 Subject: [PATCH] Rename SILBuilder::createUncheckedBitCast to SILBuilder::createUncheckedForwardingCast It would be disastrous to confuse this utility with a bit cast. A bit cast always produces an Unowned value which must immediately be copied to be used. This utility always forwards ownership. It cannot be used to truncate values. Also, be careful not to convert "reinterpret cast" (e.g. Builtin.reinterpretCast) into a "value cast" since ownership will be incorrect and the reinterpreted types might not have equivalent layout. --- include/swift/SIL/SILBuilder.h | 19 +++++++++++++------ lib/SIL/IR/SILBuilder.cpp | 3 ++- .../SILCombiner/SILCombinerApplyVisitors.cpp | 9 +++++---- .../Transforms/EagerSpecializer.cpp | 4 ++-- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h index 32d1389d4d990..f56a62293009f 100644 --- a/include/swift/SIL/SILBuilder.h +++ b/include/swift/SIL/SILBuilder.h @@ -2102,13 +2102,20 @@ class SILBuilder { SingleValueInstruction * createUncheckedReinterpretCast(SILLocation Loc, SILValue Op, SILType Ty); - /// Create an appropriate cast instruction based on result type. + /// Create an appropriate cast instruction based on result type. This cast + /// forwards ownership from the operand to the result. /// - /// NOTE: This assumes that the input and the result cast are layout - /// compatible. Reduces to createUncheckedReinterpretCast when ownership is - /// disabled. - SingleValueInstruction *createUncheckedBitCast(SILLocation Loc, SILValue Op, - SILType Ty); + /// WARNING: Because it forwards ownership, this cast is only valid with the + /// source and destination types are layout equivalent. The destination type + /// must include all the same references in the same positions. + /// + /// Note: Forwarding casts do not exist outside of OSSA. When ownership is + /// disabled, this reduces to createUncheckedReinterpretCast, which may + /// fall-back to unchecked_bitwise_cast. It is the caller's responsibility to + /// emit the correct retains and releases. + SingleValueInstruction *createUncheckedForwardingCast(SILLocation Loc, + SILValue Op, + SILType Ty); //===--------------------------------------------------------------------===// // Runtime failure diff --git a/lib/SIL/IR/SILBuilder.cpp b/lib/SIL/IR/SILBuilder.cpp index d8782af1158d2..05e4ed2baf1ad 100644 --- a/lib/SIL/IR/SILBuilder.cpp +++ b/lib/SIL/IR/SILBuilder.cpp @@ -174,7 +174,8 @@ SILBuilder::createUncheckedReinterpretCast(SILLocation Loc, SILValue Op, // Create the appropriate cast instruction based on result type. SingleValueInstruction * -SILBuilder::createUncheckedBitCast(SILLocation Loc, SILValue Op, SILType Ty) { +SILBuilder::createUncheckedForwardingCast(SILLocation Loc, SILValue Op, + SILType Ty) { // Without ownership, delegate to unchecked reinterpret cast. if (!hasOwnership()) return createUncheckedReinterpretCast(Loc, Op, Ty); diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp index e52a4df73b347..655678e7840c0 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp @@ -169,7 +169,7 @@ SILCombiner::optimizeApplyOfConvertFunctionInst(FullApplySite AI, Args.push_back(UAC); } else if (OldOpType.getASTType() != NewOpType.getASTType()) { auto URC = - Builder.createUncheckedBitCast(AI.getLoc(), Op, NewOpType); + Builder.createUncheckedForwardingCast(AI.getLoc(), Op, NewOpType); Args.push_back(URC); } else { Args.push_back(Op); @@ -221,8 +221,8 @@ SILCombiner::optimizeApplyOfConvertFunctionInst(FullApplySite AI, for (auto e = newOpResultTypes.end(); newRetI != e; ++oldRetI, ++newRetI, ++origArgI) { auto arg = normalBB->createPhiArgument(*newRetI, (*origArgI)->getOwnershipKind()); - auto converted = Builder.createUncheckedBitCast(AI.getLoc(), - arg, *oldRetI); + auto converted = + Builder.createUncheckedForwardingCast(AI.getLoc(), arg, *oldRetI); branchArgs.push_back(converted); } @@ -246,7 +246,8 @@ SILCombiner::optimizeApplyOfConvertFunctionInst(FullApplySite AI, SILInstruction *result = NAI; if (oldResultTy != newResultTy) { - result = Builder.createUncheckedBitCast(AI.getLoc(), NAI, oldResultTy); + result = + Builder.createUncheckedForwardingCast(AI.getLoc(), NAI, oldResultTy); } return result; diff --git a/lib/SILOptimizer/Transforms/EagerSpecializer.cpp b/lib/SILOptimizer/Transforms/EagerSpecializer.cpp index 0793facbd0a15..dd9ef9af2c373 100644 --- a/lib/SILOptimizer/Transforms/EagerSpecializer.cpp +++ b/lib/SILOptimizer/Transforms/EagerSpecializer.cpp @@ -438,7 +438,7 @@ void EagerDispatch::emitDispatchTo(SILFunction *NewFunc) { auto GenResultTy = GenericFunc->mapTypeIntoContext(resultTy); SILValue CastResult = - Builder.createUncheckedBitCast(Loc, Result, GenResultTy); + Builder.createUncheckedForwardingCast(Loc, Result, GenResultTy); addReturnValue(Builder.getInsertionBB(), OldReturnBB, CastResult); } @@ -640,7 +640,7 @@ SILValue EagerDispatch::emitArgumentCast(CanSILFunctionType CalleeSubstFnTy, if (CastTy.isAddress()) return Builder.createUncheckedAddrCast(Loc, OrigArg, CastTy); - return Builder.createUncheckedBitCast(Loc, OrigArg, CastTy); + return Builder.createUncheckedForwardingCast(Loc, OrigArg, CastTy); } /// Converts each generic function argument into a SILValue that can be passed