Skip to content

Commit 81ea860

Browse files
committed
IRGen: Builtin.UnknownObject should not be hardcoded to use ObjC refcounting.
It's more appropriate to use `Unknown` refcounting, which we correctly handle in the face of non-ObjC-interop elsewhere. Fixes a problem where the Linux standard library would contain an unresolvable reference to `objc_release`.
1 parent 101788d commit 81ea860

File tree

4 files changed

+46
-17
lines changed

4 files changed

+46
-17
lines changed

lib/IRGen/GenObjC.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -210,25 +210,32 @@ llvm::Value *irgen::emitObjCAutoreleaseReturnValue(IRGenFunction &IGF,
210210
}
211211

212212
namespace {
213-
/// A type-info implementation suitable for an ObjC pointer type.
214-
class ObjCTypeInfo : public HeapTypeInfo<ObjCTypeInfo> {
213+
/// A type-info implementation suitable for Builtin.UnknownObject.
214+
class UnknownTypeInfo : public HeapTypeInfo<UnknownTypeInfo> {
215215
public:
216-
ObjCTypeInfo(llvm::PointerType *storageType, Size size,
216+
UnknownTypeInfo(llvm::PointerType *storageType, Size size,
217217
SpareBitVector spareBits, Alignment align)
218218
: HeapTypeInfo(storageType, size, spareBits, align) {
219219
}
220220

221221
/// Builtin.UnknownObject requires ObjC reference-counting.
222222
ReferenceCounting getReferenceCounting() const {
223-
return ReferenceCounting::ObjC;
223+
return ReferenceCounting::Unknown;
224224
}
225225
};
226226
} // end anonymous namespace
227227

228228
const LoadableTypeInfo *TypeConverter::convertBuiltinUnknownObject() {
229-
return new ObjCTypeInfo(IGM.ObjCPtrTy, IGM.getPointerSize(),
230-
IGM.getHeapObjectSpareBits(),
231-
IGM.getPointerAlignment());
229+
// UnknownObject is only interestingly different from NativeObject on
230+
// platforms with ObjC interop.
231+
if (IGM.Context.LangOpts.EnableObjCInterop) {
232+
return new UnknownTypeInfo(IGM.ObjCPtrTy, IGM.getPointerSize(),
233+
IGM.getHeapObjectSpareBits(),
234+
IGM.getPointerAlignment());
235+
}
236+
237+
// Without ObjC interop, UnknownObject handles just like a NativeObject.
238+
return convertBuiltinNativeObject();
232239
}
233240

234241
namespace {

test/IRGen/builtins.swift

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -646,29 +646,34 @@ func acceptsBuiltinUnknownObject(_ ref: inout Builtin.UnknownObject?) {}
646646
// ObjC
647647
// CHECK-LABEL: define hidden {{.*}}i1 @_T08builtins8isUniqueBi1_BOSgzF({{%.*}}* nocapture dereferenceable({{.*}})) {{.*}} {
648648
// CHECK-NEXT: entry:
649-
// CHECK-NEXT: bitcast [[BUILTIN_UNKNOWN_OBJECT_TY]]* %0 to %objc_object**
650-
// CHECK-NEXT: load %objc_object*, %objc_object** %1
651-
// CHECK-NEXT: call i1 @swift_isUniquelyReferencedNonObjC(%objc_object* %2)
649+
// CHECK-NEXT: bitcast [[BUILTIN_UNKNOWN_OBJECT_TY]]* %0 to [[UNKNOWN_OBJECT:%objc_object|%swift\.refcounted]]**
650+
// CHECK-NEXT: load [[UNKNOWN_OBJECT]]*, [[UNKNOWN_OBJECT]]** %1
651+
// CHECK-objc-NEXT: call i1 @swift_isUniquelyReferencedNonObjC([[UNKNOWN_OBJECT]]* %2)
652+
// CHECK-native-NEXT: call i1 @swift_isUniquelyReferenced_native([[UNKNOWN_OBJECT]]* %2)
652653
// CHECK-NEXT: ret i1 %3
653654
func isUnique(_ ref: inout Builtin.UnknownObject?) -> Bool {
654655
return Builtin.isUnique(&ref)
655656
}
656657

657658
// ObjC nonNull
658-
// CHECK-LABEL: define hidden {{.*}}i1 @_T08builtins8isUniqueBi1_BOzF(%objc_object** nocapture dereferenceable({{.*}})) {{.*}} {
659+
// CHECK-LABEL: define hidden {{.*}}i1 @_T08builtins8isUniqueBi1_BOzF
660+
// CHECK-SAME: ([[UNKNOWN_OBJECT]]** nocapture dereferenceable({{.*}})) {{.*}} {
659661
// CHECK-NEXT: entry:
660-
// CHECK-NEXT: load %objc_object*, %objc_object** %0
661-
// CHECK-NEXT: call i1 @swift_isUniquelyReferencedNonObjC_nonNull(%objc_object* %1)
662+
// CHECK-NEXT: load [[UNKNOWN_OBJECT]]*, [[UNKNOWN_OBJECT]]** %0
663+
// CHECK-objc-NEXT: call i1 @swift_isUniquelyReferencedNonObjC_nonNull([[UNKNOWN_OBJECT]]* %1)
664+
// CHECK-native-NEXT: call i1 @swift_rt_swift_isUniquelyReferenced_nonNull_native([[UNKNOWN_OBJECT]]* %1)
662665
// CHECK-NEXT: ret i1 %2
663666
func isUnique(_ ref: inout Builtin.UnknownObject) -> Bool {
664667
return Builtin.isUnique(&ref)
665668
}
666669

667670
// ObjC pinned nonNull
668-
// CHECK-LABEL: define hidden {{.*}}i1 @_T08builtins16isUniqueOrPinnedBi1_BOzF(%objc_object** nocapture dereferenceable({{.*}})) {{.*}} {
671+
// CHECK-LABEL: define hidden {{.*}}i1 @_T08builtins16isUniqueOrPinnedBi1_BOzF
672+
// CHECK-SAME: ([[UNKNOWN_OBJECT]]** nocapture dereferenceable({{.*}})) {{.*}} {
669673
// CHECK-NEXT: entry:
670-
// CHECK-NEXT: load %objc_object*, %objc_object** %0
671-
// CHECK-NEXT: call i1 @swift_isUniquelyReferencedOrPinnedNonObjC_nonNull(%objc_object* %1)
674+
// CHECK-NEXT: load [[UNKNOWN_OBJECT]]*, [[UNKNOWN_OBJECT]]** %0
675+
// CHECK-native-NEXT: call i1 @swift_rt_swift_isUniquelyReferencedOrPinned_nonNull_native([[UNKNOWN_OBJECT]]* %1)
676+
// CHECK-objc-NEXT: call i1 @swift_isUniquelyReferencedOrPinnedNonObjC_nonNull([[UNKNOWN_OBJECT]]* %1)
672677
// CHECK-NEXT: ret i1 %2
673678
func isUniqueOrPinned(_ ref: inout Builtin.UnknownObject) -> Bool {
674679
return Builtin.isUniqueOrPinned(&ref)

test/IRGen/enum_value_semantics_special_cases_objc.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ enum NullableObjCRefcounted {
1515
// CHECK: %0 = bitcast %swift.opaque* %object to %T39enum_value_semantics_special_cases_objc22NullableObjCRefcountedO*
1616
// CHECK: %1 = bitcast %T39enum_value_semantics_special_cases_objc22NullableObjCRefcountedO* %0 to %objc_object**
1717
// CHECK: %2 = load %objc_object*, %objc_object** %1, align 8
18-
// CHECK: call void @objc_release(%objc_object* %2) {{#[0-9]+}}
18+
// CHECK: call void @swift_unknownRelease(%objc_object* %2) {{#[0-9]+}}
1919
// CHECK: ret void
2020
// CHECK: }
2121

test/IRGen/unknown_object.sil

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-swift-frontend -emit-ir %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-runtime %s
2+
3+
sil_stage canonical
4+
5+
import Builtin
6+
7+
// CHECK-LABEL: @retain_release_unknown_object
8+
sil @retain_release_unknown_object : $@convention(thin) (@guaranteed Builtin.UnknownObject) -> () {
9+
entry(%x : $Builtin.UnknownObject):
10+
// CHECK-native: swift_retain
11+
// CHECK-objc: swift_unknownRetain
12+
%y = copy_value %x : $Builtin.UnknownObject
13+
// CHECK-native: swift_release
14+
// CHECK-objc: swift_unknownRelease
15+
destroy_value %y : $Builtin.UnknownObject
16+
return undef : $()
17+
}

0 commit comments

Comments
 (0)