Skip to content

Commit 3a7c649

Browse files
committed
Mark some builtins as taking an owned argument.
The goal here is for the SILGen of these builtins to receive an owned value so that it will perform an owned->owned conversion and therefore produce a +1 result, as generally expected. Without this, SILGen will perform a borrowed->borrowed conversion, and the copy of the result (if it even happens) may happen after the argument's borrow scope has ended.
1 parent ff9a4fe commit 3a7c649

File tree

7 files changed

+114
-86
lines changed

7 files changed

+114
-86
lines changed

lib/AST/Builtins.cpp

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,9 @@ getBuiltinGenericFunction(Identifier Id,
196196
SmallVector<ParamDecl*, 4> params;
197197
for (unsigned i = 0, e = ArgParamTypes.size(); i < e; i++) {
198198
auto paramIfaceType = ArgParamTypes[i].getPlainType();
199-
auto specifier = (ArgParamTypes[i].getParameterFlags().isInOut())
200-
? VarDecl::Specifier::InOut
201-
: VarDecl::Specifier::Default;
199+
auto specifier =
200+
VarDecl::getParameterSpecifierForValueOwnership(
201+
ArgParamTypes[i].getParameterFlags().getValueOwnership());
202202
auto PD = new (Context) ParamDecl(specifier,
203203
SourceLoc(), SourceLoc(),
204204
Identifier(), SourceLoc(),
@@ -474,19 +474,13 @@ namespace {
474474
}
475475

476476
template <class G>
477-
void addParameter(const G &generator) {
477+
void addParameter(const G &generator,
478+
ValueOwnership ownership = ValueOwnership::Default) {
478479
Type gTyIface = generator.build(*this);
479-
auto flags = ParameterTypeFlags();
480+
auto flags = ParameterTypeFlags().withValueOwnership(ownership);
480481
InterfaceParams.emplace_back(gTyIface, Identifier(), flags);
481482
}
482483

483-
template <class G>
484-
void addInOutParameter(const G &generator) {
485-
Type gTyIface = generator.build(*this);
486-
auto flags = ParameterTypeFlags().withInOut(true);
487-
InterfaceParams.emplace_back(gTyIface, Identifier(), flags);
488-
}
489-
490484
template <class G>
491485
void setResult(const G &generator) {
492486
InterfaceResult = generator.build(*this);
@@ -591,7 +585,7 @@ static ValueDecl *getLoadOperation(ASTContext &Context, Identifier Id) {
591585

592586
static ValueDecl *getStoreOperation(ASTContext &Context, Identifier Id) {
593587
BuiltinGenericSignatureBuilder builder(Context);
594-
builder.addParameter(makeGenericParam());
588+
builder.addParameter(makeGenericParam(), ValueOwnership::Owned);
595589
builder.addParameter(makeConcrete(Context.TheRawPointerType));
596590
builder.setResult(makeConcrete(TupleType::getEmpty(Context)));
597591
return builder.build(Id);
@@ -633,7 +627,7 @@ static ValueDecl *getIsUniqueOperation(ASTContext &Context, Identifier Id) {
633627
Type Int1Ty = BuiltinIntegerType::get(1, Context);
634628

635629
BuiltinGenericSignatureBuilder builder(Context);
636-
builder.addInOutParameter(makeGenericParam());
630+
builder.addParameter(makeGenericParam(), ValueOwnership::InOut);
637631
builder.setResult(makeConcrete(Int1Ty));
638632
return builder.build(Id);
639633
}
@@ -808,21 +802,35 @@ static ValueDecl *getAtomicStoreOperation(ASTContext &Context, Identifier Id,
808802

809803
static ValueDecl *getNativeObjectCast(ASTContext &Context, Identifier Id,
810804
BuiltinValueKind BV) {
811-
Type BuiltinTy;
812-
if (BV == BuiltinValueKind::BridgeToRawPointer ||
813-
BV == BuiltinValueKind::BridgeFromRawPointer)
814-
BuiltinTy = Context.TheRawPointerType;
815-
else
816-
BuiltinTy = Context.TheNativeObjectType;
805+
806+
ValueOwnership ownership;
807+
Type builtinTy;
808+
switch (BV) {
809+
case BuiltinValueKind::CastToNativeObject:
810+
case BuiltinValueKind::UnsafeCastToNativeObject:
811+
case BuiltinValueKind::CastFromNativeObject:
812+
builtinTy = Context.TheNativeObjectType;
813+
ownership = ValueOwnership::Owned;
814+
break;
815+
816+
case BuiltinValueKind::BridgeToRawPointer:
817+
case BuiltinValueKind::BridgeFromRawPointer:
818+
builtinTy = Context.TheRawPointerType;
819+
ownership = ValueOwnership::Default;
820+
break;
821+
822+
default:
823+
llvm_unreachable("unexpected kind");
824+
}
817825

818826
BuiltinGenericSignatureBuilder builder(Context);
819827
if (BV == BuiltinValueKind::CastToNativeObject ||
820828
BV == BuiltinValueKind::UnsafeCastToNativeObject ||
821829
BV == BuiltinValueKind::BridgeToRawPointer) {
822-
builder.addParameter(makeGenericParam());
823-
builder.setResult(makeConcrete(BuiltinTy));
830+
builder.addParameter(makeGenericParam(), ownership);
831+
builder.setResult(makeConcrete(builtinTy));
824832
} else {
825-
builder.addParameter(makeConcrete(BuiltinTy));
833+
builder.addParameter(makeConcrete(builtinTy), ownership);
826834
builder.setResult(makeGenericParam());
827835
}
828836
return builder.build(Id);
@@ -833,7 +841,7 @@ static ValueDecl *getCastToBridgeObjectOperation(ASTContext &C,
833841
auto wordType = BuiltinIntegerType::get(BuiltinIntegerWidth::pointer(),
834842
C);
835843
BuiltinGenericSignatureBuilder builder(C);
836-
builder.addParameter(makeGenericParam());
844+
builder.addParameter(makeGenericParam(), ValueOwnership::Owned);
837845
builder.addParameter(makeConcrete(wordType));
838846
builder.setResult(makeConcrete(C.TheBridgeObjectType));
839847
return builder.build(Id);
@@ -846,7 +854,7 @@ static ValueDecl *getCastFromBridgeObjectOperation(ASTContext &C,
846854
switch (BV) {
847855
case BuiltinValueKind::CastReferenceFromBridgeObject: {
848856
BuiltinGenericSignatureBuilder builder(C);
849-
builder.addParameter(makeConcrete(BridgeTy));
857+
builder.addParameter(makeConcrete(BridgeTy), ValueOwnership::Owned);
850858
builder.setResult(makeGenericParam());
851859
return builder.build(Id);
852860
}
@@ -906,7 +914,7 @@ static ValueDecl *getCastReferenceOperation(ASTContext &ctx,
906914
// <T, U> T -> U
907915
// SILGen and IRGen check additional constraints during lowering.
908916
BuiltinGenericSignatureBuilder builder(ctx, 2);
909-
builder.addParameter(makeGenericParam(0));
917+
builder.addParameter(makeGenericParam(0), ValueOwnership::Owned);
910918
builder.setResult(makeGenericParam(1));
911919
return builder.build(name);
912920
}
@@ -916,7 +924,7 @@ static ValueDecl *getReinterpretCastOperation(ASTContext &ctx,
916924
// <T, U> T -> U
917925
// SILGen and IRGen check additional constraints during lowering.
918926
BuiltinGenericSignatureBuilder builder(ctx, 2);
919-
builder.addParameter(makeGenericParam(0));
927+
builder.addParameter(makeGenericParam(0), ValueOwnership::Owned);
920928
builder.setResult(makeGenericParam(1));
921929
return builder.build(name);
922930
}
@@ -949,7 +957,7 @@ static ValueDecl *getTSanInoutAccess(ASTContext &Context, Identifier Id) {
949957
static ValueDecl *getAddressOfOperation(ASTContext &Context, Identifier Id) {
950958
// <T> (@inout T) -> RawPointer
951959
BuiltinGenericSignatureBuilder builder(Context);
952-
builder.addInOutParameter(makeGenericParam());
960+
builder.addParameter(makeGenericParam(), ValueOwnership::InOut);
953961
builder.setResult(makeConcrete(Context.TheRawPointerType));
954962
return builder.build(Id);
955963
}
@@ -976,7 +984,7 @@ static ValueDecl *getTypeJoinInoutOperation(ASTContext &Context,
976984
Identifier Id) {
977985
// <T,U,V> (inout T, U.Type) -> V.Type
978986
BuiltinGenericSignatureBuilder builder(Context, 3);
979-
builder.addInOutParameter(makeGenericParam(0));
987+
builder.addParameter(makeGenericParam(0), ValueOwnership::InOut);
980988
builder.addParameter(makeMetatype(makeGenericParam(1)));
981989
builder.setResult(makeMetatype(makeGenericParam(2)));
982990
return builder.build(Id);

lib/SILGen/SILGenBuiltin.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@
3030
using namespace swift;
3131
using namespace Lowering;
3232

33+
static bool isTrivialShuffle(TupleShuffleExpr *shuffle) {
34+
// Each element must be mapped to the corresponding element of the input.
35+
auto mapping = shuffle->getElementMapping();
36+
for (auto index : indices(mapping)) {
37+
if (mapping[index] < 0 || unsigned(mapping[index]) != index)
38+
return false;
39+
}
40+
return true;
41+
}
42+
3343
/// Break down an expression that's the formal argument expression to
3444
/// a builtin function, returning its individualized arguments.
3545
///
@@ -43,7 +53,15 @@ static ArrayRef<Expr*> decomposeArguments(SILGenFunction &SGF,
4353
assert(arg->getType()->castTo<TupleType>()->getNumElements()
4454
== expectedCount);
4555

46-
auto tuple = dyn_cast<TupleExpr>(arg->getSemanticsProvidingExpr());
56+
// The use of owned parameters can trip up CSApply enough to introduce
57+
// a trivial tuple shuffle here.
58+
arg = arg->getSemanticsProvidingExpr();
59+
if (auto shuffle = dyn_cast<TupleShuffleExpr>(arg)) {
60+
if (isTrivialShuffle(shuffle))
61+
arg = shuffle->getSubExpr();
62+
}
63+
64+
auto tuple = dyn_cast<TupleExpr>(arg);
4765
if (tuple && tuple->getElements().size() == expectedCount) {
4866
return tuple->getElements();
4967
}

test/SILGen/builtins.swift

Lines changed: 46 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -199,61 +199,61 @@ class D {}
199199
// CHECK-LABEL: sil hidden @$s8builtins22class_to_native_object{{[_0-9a-zA-Z]*}}F
200200
// CHECK: bb0([[ARG:%.*]] : @guaranteed $C):
201201
// CHECK-NEXT: debug_value
202-
// CHECK-NEXT: [[OBJ:%.*]] = unchecked_ref_cast [[ARG:%.*]] to $Builtin.NativeObject
203-
// CHECK-NEXT: [[OBJ_COPY:%.*]] = copy_value [[OBJ]]
204-
// CHECK-NEXT: return [[OBJ_COPY]]
202+
// CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[ARG]]
203+
// CHECK-NEXT: [[OBJ:%.*]] = unchecked_ref_cast [[ARG_COPY]] : $C to $Builtin.NativeObject
204+
// CHECK-NEXT: return [[OBJ]]
205205
func class_to_native_object(_ c:C) -> Builtin.NativeObject {
206206
return Builtin.castToNativeObject(c)
207207
}
208208

209209
// CHECK-LABEL: sil hidden @$s8builtins32class_archetype_to_native_object{{[_0-9a-zA-Z]*}}F
210210
func class_archetype_to_native_object<T : C>(_ t: T) -> Builtin.NativeObject {
211-
// CHECK: [[OBJ:%.*]] = unchecked_ref_cast [[C:%.*]] to $Builtin.NativeObject
212-
// CHECK-NEXT: [[OBJ_COPY:%.*]] = copy_value [[OBJ]]
213-
// CHECK-NOT: destroy_value [[C]]
211+
// CHECK: [[COPY:%.*]] = copy_value %0
212+
// CHECK: [[OBJ:%.*]] = unchecked_ref_cast [[COPY]] : $T to $Builtin.NativeObject
213+
// CHECK-NOT: destroy_value [[COPY]]
214214
// CHECK-NOT: destroy_value [[OBJ]]
215-
// CHECK: return [[OBJ_COPY]]
215+
// CHECK: return [[OBJ]]
216216
return Builtin.castToNativeObject(t)
217217
}
218218

219219
// CHECK-LABEL: sil hidden @$s8builtins34class_existential_to_native_object{{[_0-9a-zA-Z]*}}F
220220
// CHECK: bb0([[ARG:%.*]] : @guaranteed $ClassProto):
221221
// CHECK-NEXT: debug_value
222-
// CHECK-NEXT: [[REF:%[0-9]+]] = open_existential_ref [[ARG]] : $ClassProto
222+
// CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[ARG]]
223+
// CHECK-NEXT: [[REF:%[0-9]+]] = open_existential_ref [[ARG_COPY]] : $ClassProto
223224
// CHECK-NEXT: [[PTR:%[0-9]+]] = unchecked_ref_cast [[REF]] : $@opened({{.*}}) ClassProto to $Builtin.NativeObject
224-
// CHECK-NEXT: [[PTR_COPY:%.*]] = copy_value [[PTR]]
225-
// CHECK-NEXT: return [[PTR_COPY]]
225+
// CHECK-NEXT: return [[PTR]]
226226
func class_existential_to_native_object(_ t:ClassProto) -> Builtin.NativeObject {
227227
return Builtin.unsafeCastToNativeObject(t)
228228
}
229229

230230
// CHECK-LABEL: sil hidden @$s8builtins24class_from_native_object{{[_0-9a-zA-Z]*}}F
231231
func class_from_native_object(_ p: Builtin.NativeObject) -> C {
232-
// CHECK: [[C:%.*]] = unchecked_ref_cast [[OBJ:%.*]] to $C
233-
// CHECK: [[C_RETURN:%.*]] = copy_value [[C]]
234-
// CHECK-NOT: destroy_value [[C]]
235-
// CHECK-NOT: destroy_value [[OBJ]]
236-
// CHECK: return [[C_RETURN]]
232+
// CHECK: [[COPY:%.*]] = copy_value %0
233+
// CHECK: [[CAST:%.*]] = unchecked_ref_cast [[COPY]] : $Builtin.NativeObject to $C
234+
// CHECK-NOT: destroy_value [[COPY]]
235+
// CHECK-NOT: destroy_value [[CAST]]
236+
// CHECK: return [[CAST]]
237237
return Builtin.castFromNativeObject(p)
238238
}
239239

240240
// CHECK-LABEL: sil hidden @$s8builtins34class_archetype_from_native_object{{[_0-9a-zA-Z]*}}F
241241
func class_archetype_from_native_object<T : C>(_ p: Builtin.NativeObject) -> T {
242-
// CHECK: [[C:%.*]] = unchecked_ref_cast [[OBJ:%.*]] : $Builtin.NativeObject to $T
243-
// CHECK: [[C_RETURN:%.*]] = copy_value [[C]]
244-
// CHECK-NOT: destroy_value [[C]]
245-
// CHECK-NOT: destroy_value [[OBJ]]
246-
// CHECK: return [[C_RETURN]]
242+
// CHECK: [[COPY:%.*]] = copy_value %0
243+
// CHECK: [[CAST:%.*]] = unchecked_ref_cast [[COPY]] : $Builtin.NativeObject to $T
244+
// CHECK-NOT: destroy_value [[COPY]]
245+
// CHECK-NOT: destroy_value [[CAST]]
246+
// CHECK: return [[CAST]]
247247
return Builtin.castFromNativeObject(p)
248248
}
249249

250250
// CHECK-LABEL: sil hidden @$s8builtins41objc_class_existential_from_native_object{{[_0-9a-zA-Z]*}}F
251251
func objc_class_existential_from_native_object(_ p: Builtin.NativeObject) -> AnyObject {
252-
// CHECK: [[C:%.*]] = unchecked_ref_cast [[OBJ:%.*]] : $Builtin.NativeObject to $AnyObject
253-
// CHECK: [[C_RETURN:%.*]] = copy_value [[C]]
254-
// CHECK-NOT: destroy_value [[C]]
255-
// CHECK-NOT: destroy_value [[OBJ]]
256-
// CHECK: return [[C_RETURN]]
252+
// CHECK: [[COPY:%.*]] = copy_value %0
253+
// CHECK: [[CAST:%.*]] = unchecked_ref_cast [[COPY]] : $Builtin.NativeObject to $AnyObject
254+
// CHECK-NOT: destroy_value [[COPY]]
255+
// CHECK-NOT: destroy_value [[CAST]]
256+
// CHECK: return [[CAST]]
257257
return Builtin.castFromNativeObject(p)
258258
}
259259

@@ -510,14 +510,16 @@ func unreachable() {
510510
// CHECK: bb0([[ARG1:%.*]] : @guaranteed $C, [[ARG2:%.*]] : @trivial $Builtin.Word):
511511
// CHECK-NEXT: debug_value
512512
// CHECK-NEXT: debug_value
513-
// CHECK-NEXT: [[ARG1_TRIVIAL:%.*]] = unchecked_trivial_bit_cast [[ARG1]] : $C to $Builtin.Word
514-
// CHECK-NEXT: [[ARG1_D:%.*]] = unchecked_ref_cast [[ARG1]] : $C to $D
515-
// CHECK-NEXT: [[ARG1_OPT:%.*]] = unchecked_ref_cast [[ARG1]] : $C to $Optional<C>
513+
// CHECK-NEXT: [[ARG1_COPY1:%.*]] = copy_value [[ARG1]]
514+
// CHECK-NEXT: [[ARG1_TRIVIAL:%.*]] = unchecked_trivial_bit_cast [[ARG1_COPY1]] : $C to $Builtin.Word
515+
// CHECK-NEXT: [[ARG1_COPY2:%.*]] = copy_value [[ARG1]]
516+
// CHECK-NEXT: [[ARG1_D:%.*]] = unchecked_ref_cast [[ARG1_COPY2]] : $C to $D
517+
// CHECK-NEXT: [[ARG1_COPY3:%.*]] = copy_value [[ARG1]]
518+
// CHECK-NEXT: [[ARG1_OPT:%.*]] = unchecked_ref_cast [[ARG1_COPY3]] : $C to $Optional<C>
516519
// CHECK-NEXT: [[ARG2_FROM_WORD:%.*]] = unchecked_bitwise_cast [[ARG2]] : $Builtin.Word to $C
517520
// CHECK-NEXT: [[ARG2_FROM_WORD_COPY:%.*]] = copy_value [[ARG2_FROM_WORD]]
518-
// CHECK-NEXT: [[ARG1_D_COPY:%.*]] = copy_value [[ARG1_D]]
519-
// CHECK-NEXT: [[ARG1_OPT_COPY:%.*]] = copy_value [[ARG1_OPT]]
520-
// CHECK-NEXT: [[RESULT:%.*]] = tuple ([[ARG1_TRIVIAL]] : $Builtin.Word, [[ARG1_D_COPY]] : $D, [[ARG1_OPT_COPY]] : $Optional<C>, [[ARG2_FROM_WORD_COPY:%.*]] : $C)
521+
// CHECK-NEXT: destroy_value [[ARG1_COPY1]]
522+
// CHECK-NEXT: [[RESULT:%.*]] = tuple ([[ARG1_TRIVIAL]] : $Builtin.Word, [[ARG1_D]] : $D, [[ARG1_OPT]] : $Optional<C>, [[ARG2_FROM_WORD_COPY:%.*]] : $C)
521523
// CHECK: return [[RESULT]]
522524
func reinterpretCast(_ c: C, x: Builtin.Word) -> (Builtin.Word, D, C?, C) {
523525
return (Builtin.reinterpretCast(c) as Builtin.Word,
@@ -534,9 +536,10 @@ func reinterpretAddrOnly<T, U>(_ t: T) -> U {
534536

535537
// CHECK-LABEL: sil hidden @$s8builtins28reinterpretAddrOnlyToTrivial{{[_0-9a-zA-Z]*}}F
536538
func reinterpretAddrOnlyToTrivial<T>(_ t: T) -> Int {
537-
// CHECK: [[ADDR:%.*]] = unchecked_addr_cast [[INPUT:%.*]] : $*T to $*Int
539+
// CHECK: copy_addr %0 to [initialization] [[INPUT:%.*]] : $*T
540+
// CHECK: [[ADDR:%.*]] = unchecked_addr_cast [[INPUT]] : $*T to $*Int
538541
// CHECK: [[VALUE:%.*]] = load [trivial] [[ADDR]]
539-
// CHECK-NOT: destroy_addr [[INPUT]]
542+
// CHECK: destroy_addr [[INPUT]]
540543
return Builtin.reinterpretCast(t)
541544
}
542545

@@ -553,9 +556,10 @@ func reinterpretAddrOnlyLoadable<T>(_ a: Int, _ b: T) -> (T, Int) {
553556
}
554557

555558
// CHECK-LABEL: sil hidden @$s8builtins18castToBridgeObject{{[_0-9a-zA-Z]*}}F
556-
// CHECK: [[BO:%.*]] = ref_to_bridge_object {{%.*}} : $C, {{%.*}} : $Builtin.Word
557-
// CHECK: [[BO_COPY:%.*]] = copy_value [[BO]]
558-
// CHECK: return [[BO_COPY]]
559+
// CHECK: [[ARG_COPY:%.*]] = copy_value %0
560+
// CHECK: [[BO:%.*]] = ref_to_bridge_object [[ARG_COPY]] : $C, {{%.*}} : $Builtin.Word
561+
// CHECK-NOT: destroy_value [[ARG_COPY]]
562+
// CHECK: return [[BO]]
559563
func castToBridgeObject(_ c: C, _ w: Builtin.Word) -> Builtin.BridgeObject {
560564
return Builtin.castToBridgeObject(c, w)
561565
}
@@ -653,10 +657,10 @@ func refcast_generic_any<T>(_ o: T) -> AnyObject {
653657

654658
// CHECK-LABEL: sil hidden @$s8builtins17refcast_class_anyyyXlAA1ACF :
655659
// CHECK: bb0([[ARG:%.*]] : @guaranteed $A):
656-
// CHECK: [[ARG_CASTED:%.*]] = unchecked_ref_cast [[ARG]] : $A to $AnyObject
657-
// CHECK: [[ARG_CASTED_COPY:%.*]] = copy_value [[ARG_CASTED]]
660+
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
661+
// CHECK: [[ARG_CASTED:%.*]] = unchecked_ref_cast [[ARG_COPY]] : $A to $AnyObject
658662
// CHECK-NOT: destroy_value [[ARG]]
659-
// CHECK: return [[ARG_CASTED_COPY]]
663+
// CHECK: return [[ARG_CASTED]]
660664
// CHECK: } // end sil function '$s8builtins17refcast_class_anyyyXlAA1ACF'
661665
func refcast_class_any(_ o: A) -> AnyObject {
662666
return Builtin.castReference(o)
@@ -670,9 +674,9 @@ func refcast_punknown_any(_ o: PUnknown) -> AnyObject {
670674

671675
// CHECK-LABEL: sil hidden @$s8builtins18refcast_pclass_anyyyXlAA6PClass_pF :
672676
// CHECK: bb0([[ARG:%.*]] : @guaranteed $PClass):
673-
// CHECK: [[ARG_CAST:%.*]] = unchecked_ref_cast [[ARG]] : $PClass to $AnyObject
674-
// CHECK: [[ARG_CAST_COPY:%.*]] = copy_value [[ARG_CAST]]
675-
// CHECK: return [[ARG_CAST_COPY]]
677+
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
678+
// CHECK: [[ARG_CAST:%.*]] = unchecked_ref_cast [[ARG_COPY]] : $PClass to $AnyObject
679+
// CHECK: return [[ARG_CAST]]
676680
// CHECK: } // end sil function '$s8builtins18refcast_pclass_anyyyXlAA6PClass_pF'
677681
func refcast_pclass_any(_ o: PClass) -> AnyObject {
678682
return Builtin.castReference(o)

test/SILGen/guaranteed_normal_args.swift

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -133,15 +133,10 @@ class KlassWithBuffer {
133133
// CHECK: [[BUF_BORROW:%.*]] = begin_borrow [[BUF]]
134134
// CHECK: [[K:%.*]] = struct_extract [[BUF_BORROW]] : $Buffer, #Buffer.k
135135
// CHECK: [[COPIED_K:%.*]] = copy_value [[K]]
136-
// FIXME: this borrow-and-copy is really dumb and unnecessary
137-
// CHECK: [[COPIED_BORROWED_K:%.*]] = begin_borrow [[COPIED_K]]
138-
// CHECK: [[CASTED_BORROWED_BUF_KLASS:%.*]] = unchecked_ref_cast [[COPIED_BORROWED_K]]
139-
// CHECK: [[COPY_CASTED_BORROWED_BUF_KLASS:%.*]] = copy_value [[CASTED_BORROWED_BUF_KLASS]]
140-
// CHECK: end_borrow [[COPIED_BORROWED_K]]
141-
// CHECK: destroy_value [[COPIED_K]]
136+
// CHECK: [[CASTED_COPIED_K:%.*]] = unchecked_ref_cast [[COPIED_K]]
142137
// CHECK: end_borrow [[BUF_BORROW]]
143138
// CHECK: destroy_value [[BUF]]
144-
// CHECK: return [[COPY_CASTED_BORROWED_BUF_KLASS]]
139+
// CHECK: return [[CASTED_COPIED_K]]
145140
// CHECK: } // end sil function '$ss15KlassWithBufferC03getC14AsNativeObjectBoyF'
146141
func getBufferAsNativeObject() -> Builtin.NativeObject {
147142
return Builtin.unsafeCastToNativeObject(buffer.k)
@@ -154,9 +149,9 @@ struct StructContainingBridgeObject {
154149
// CHECK-LABEL: sil hidden @$ss28StructContainingBridgeObjectV8swiftObjAByXl_tcfC : $@convention(method) (@owned AnyObject, @thin StructContainingBridgeObject.Type) -> @owned StructContainingBridgeObject {
155150
// CHECK: bb0([[ARG:%.*]] : @owned $AnyObject,
156151
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
157-
// CHECK: [[CASTED_ARG:%.*]] = unchecked_ref_cast [[BORROWED_ARG]] : $AnyObject to $Builtin.BridgeObject
158-
// CHECK: [[COPY_CASTED_ARG:%.*]] = copy_value [[CASTED_ARG]]
159-
// CHECK: assign [[COPY_CASTED_ARG]] to
152+
// CHECK: [[COPIED_ARG:%.*]] = copy_value [[BORROWED_ARG]]
153+
// CHECK: [[CASTED_ARG:%.*]] = unchecked_ref_cast [[COPIED_ARG]] : $AnyObject to $Builtin.BridgeObject
154+
// CHECK: assign [[CASTED_ARG]] to
160155
// CHECK: } // end sil function '$ss28StructContainingBridgeObjectV8swiftObjAByXl_tcfC'
161156
init(swiftObj: AnyObject) {
162157
rawValue = Builtin.reinterpretCast(swiftObj)

test/SILGen/opaque_ownership.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,10 @@ public func takeDecoder(from decoder: Decoder) throws -> Builtin.Int1 {
4545
// ---
4646
// CHECK-LABEL: sil @$ss13unsafeBitCast_2toq_x_q_mtr0_lF : $@convention(thin) <T, U> (@in_guaranteed T, @thick U.Type) -> @out U {
4747
// CHECK: bb0([[ARG0:%.*]] : @guaranteed $T, [[ARG1:%.*]] : @trivial $@thick U.Type):
48-
// CHECK: [[RESULT:%.*]] = unchecked_bitwise_cast [[ARG0]] : $T to $U
48+
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG0]] : $T
49+
// CHECK: [[RESULT:%.*]] = unchecked_bitwise_cast [[ARG_COPY]] : $T to $U
4950
// CHECK: [[RESULT_COPY:%.*]] = copy_value [[RESULT]] : $U
51+
// CHECK: destroy_value [[ARG_COPY]] : $T
5052
// CHECK: return [[RESULT_COPY]] : $U
5153
// CHECK-LABEL: } // end sil function '$ss13unsafeBitCast_2toq_x_q_mtr0_lF'
5254
public func unsafeBitCast<T, U>(_ x: T, to type: U.Type) -> U {

0 commit comments

Comments
 (0)