mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[IRGen][runtime] Prepare to change the is-Swift bit in class metadata. (#13595)
Swift class metadata has a bit to distinguish it from non-Swift Objective-C classes. The stable ABI will use a different bit so that stable Swift and pre-stable Swift can be distinguished from each other. No bits are actually changed yet. Enabling the new bit needs to wait for other coordination such as libobjc. rdar://35767811
This commit is contained in:
@@ -207,6 +207,10 @@ option(SWIFT_RUNTIME_CRASH_REPORTER_CLIENT
|
||||
"Whether to enable CrashReporter integration"
|
||||
FALSE)
|
||||
|
||||
option(SWIFT_DARWIN_ENABLE_STABLE_ABI_BIT
|
||||
"Enable the Swift stable ABI's class marker bit"
|
||||
FALSE)
|
||||
|
||||
set(SWIFT_DARWIN_XCRUN_TOOLCHAIN "XcodeDefault" CACHE STRING
|
||||
"The name of the toolchain to pass to 'xcrun'")
|
||||
|
||||
|
||||
@@ -86,12 +86,16 @@ inline DynamicCastFlags &operator|=(DynamicCastFlags &a, DynamicCastFlags b) {
|
||||
}
|
||||
|
||||
/// Swift class flags.
|
||||
/// These flags are valid only when isTypeMetadata().
|
||||
/// When !isTypeMetadata() these flags will collide with other Swift ABIs.
|
||||
enum class ClassFlags : uint32_t {
|
||||
/// Is this a Swift 1 class?
|
||||
IsSwift1 = 0x1,
|
||||
/// Is this a Swift class from the Darwin pre-stable ABI?
|
||||
/// This bit is clear in stable ABI Swift classes.
|
||||
/// The Objective-C runtime also reads this bit.
|
||||
IsSwiftPreStableABI = 0x1,
|
||||
|
||||
/// Does this class use Swift 1.0 refcounting?
|
||||
UsesSwift1Refcounting = 0x2,
|
||||
/// Does this class use Swift refcounting?
|
||||
UsesSwiftRefcounting = 0x2,
|
||||
|
||||
/// Has this class a custom name, specified with the @objc attribute?
|
||||
HasCustomObjCName = 0x4
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#ifndef SWIFT_BASIC_LANGOPTIONS_H
|
||||
#define SWIFT_BASIC_LANGOPTIONS_H
|
||||
|
||||
#include "swift/Config.h"
|
||||
#include "swift/Basic/LLVM.h"
|
||||
#include "swift/Basic/Version.h"
|
||||
#include "clang/Basic/VersionTuple.h"
|
||||
@@ -128,6 +129,10 @@ namespace swift {
|
||||
/// configuration options.
|
||||
bool EnableObjCInterop = true;
|
||||
|
||||
/// On Darwin platforms, use the pre-stable ABI's mark bit for Swift
|
||||
/// classes instead of the stable ABI's bit.
|
||||
bool UseDarwinPreStableABIBit = !bool(SWIFT_DARWIN_ENABLE_STABLE_ABI_BIT);
|
||||
|
||||
/// Enables checking that uses of @objc require importing
|
||||
/// the Foundation module.
|
||||
/// This is enabled by default because SILGen can crash in such a case, but
|
||||
|
||||
@@ -8,4 +8,6 @@
|
||||
|
||||
#cmakedefine HAVE_UNICODE_LIBEDIT 1
|
||||
|
||||
#cmakedefine01 SWIFT_DARWIN_ENABLE_STABLE_ABI_BIT
|
||||
|
||||
#endif // SWIFT_CONFIG_H
|
||||
|
||||
@@ -65,6 +65,16 @@
|
||||
#error Masking ISAs are incompatible with opaque ISAs
|
||||
#endif
|
||||
|
||||
/// Which bits in the class metadata are used to distinguish Swift classes
|
||||
/// from ObjC classes?
|
||||
#ifndef SWIFT_CLASS_IS_SWIFT_MASK
|
||||
# if __APPLE__ && SWIFT_OBJC_INTEROP && SWIFT_DARWIN_ENABLE_STABLE_ABI_BIT
|
||||
# define SWIFT_CLASS_IS_SWIFT_MASK 2ULL
|
||||
# else
|
||||
# define SWIFT_CLASS_IS_SWIFT_MASK 1ULL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// We try to avoid global constructors in the runtime as much as possible.
|
||||
// These macros delimit allowed global ctors.
|
||||
#if __clang__
|
||||
|
||||
@@ -1355,7 +1355,7 @@ struct TargetClassMetadata : public TargetHeapMetadata<Runtime> {
|
||||
|
||||
/// Is this object a valid swift type metadata?
|
||||
bool isTypeMetadata() const {
|
||||
return (Data & 1);
|
||||
return (Data & SWIFT_CLASS_IS_SWIFT_MASK);
|
||||
}
|
||||
/// A different perspective on the same bit
|
||||
bool isPureObjC() const {
|
||||
|
||||
@@ -1184,6 +1184,12 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
|
||||
Target.isOSDarwin());
|
||||
Opts.EnableSILOpaqueValues |= Args.hasArg(OPT_enable_sil_opaque_values);
|
||||
|
||||
#if SWIFT_DARWIN_ENABLE_STABLE_ABI_BIT
|
||||
Opts.UseDarwinPreStableABIBit = false;
|
||||
#else
|
||||
Opts.UseDarwinPreStableABIBit = true;
|
||||
#endif
|
||||
|
||||
// Must be processed after any other language options that could affect
|
||||
// platform conditions.
|
||||
bool UnsupportedOS, UnsupportedArch;
|
||||
|
||||
@@ -3333,16 +3333,16 @@ namespace {
|
||||
}
|
||||
|
||||
void addClassFlags() {
|
||||
// Always set a flag saying that this is a Swift 1.0 class.
|
||||
ClassFlags flags = ClassFlags::IsSwift1;
|
||||
auto flags = ClassFlags();
|
||||
|
||||
// Set a flag if the class uses Swift 1.0 refcounting.
|
||||
// Set a flag if the class uses Swift refcounting.
|
||||
auto type = Target->getDeclaredType()->getCanonicalType();
|
||||
if (getReferenceCountingForType(IGM, type)
|
||||
== ReferenceCounting::Native) {
|
||||
flags |= ClassFlags::UsesSwift1Refcounting;
|
||||
flags |= ClassFlags::UsesSwiftRefcounting;
|
||||
}
|
||||
|
||||
// Set a flag if the class has a custom ObjC name.
|
||||
DeclAttributes attrs = Target->getAttrs();
|
||||
if (auto objc = attrs.getAttribute<ObjCAttr>()) {
|
||||
if (objc->getName())
|
||||
@@ -3411,17 +3411,21 @@ namespace {
|
||||
if (!IGM.ObjCInterop) {
|
||||
// with no Objective-C runtime, just give an empty pointer with the
|
||||
// swift bit set.
|
||||
// FIXME: Remove null data altogether rdar://problem/18801263
|
||||
B.addInt(IGM.IntPtrTy, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Derive the RO-data.
|
||||
llvm::Constant *data = emitClassPrivateData(IGM, Target);
|
||||
|
||||
// We always set the low bit to indicate this is a Swift class.
|
||||
data = llvm::ConstantExpr::getPtrToInt(data, IGM.IntPtrTy);
|
||||
data = llvm::ConstantExpr::getAdd(data,
|
||||
llvm::ConstantInt::get(IGM.IntPtrTy, 1));
|
||||
// Set a low bit to indicate this class has Swift metadata.
|
||||
auto bit = llvm::ConstantInt::get(IGM.IntPtrTy,
|
||||
IGM.UseDarwinPreStableABIBit ? 1 : 2);
|
||||
|
||||
// Emit data + bit.
|
||||
data = llvm::ConstantExpr::getPtrToInt(data, IGM.IntPtrTy);
|
||||
data = llvm::ConstantExpr::getAdd(data, bit);
|
||||
B.add(data);
|
||||
}
|
||||
|
||||
|
||||
@@ -134,6 +134,7 @@ IRGenModule::IRGenModule(IRGenerator &irgen,
|
||||
OutputFilename(OutputFilename),
|
||||
TargetInfo(SwiftTargetInfo::get(*this)), DebugInfo(nullptr),
|
||||
ModuleHash(nullptr), ObjCInterop(Context.LangOpts.EnableObjCInterop),
|
||||
UseDarwinPreStableABIBit(Context.LangOpts.UseDarwinPreStableABIBit),
|
||||
Types(*new TypeConverter(*this)) {
|
||||
irgen.addGenModule(SF, this);
|
||||
|
||||
|
||||
@@ -413,6 +413,9 @@ public:
|
||||
/// Does the current target require Objective-C interoperation?
|
||||
bool ObjCInterop = true;
|
||||
|
||||
/// Is the current target using the Darwin pre-stable ABI's class marker bit?
|
||||
bool UseDarwinPreStableABIBit = true;
|
||||
|
||||
/// Should we add value names to local IR values?
|
||||
bool EnableValueNames = false;
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
set(swift_runtime_compile_flags ${SWIFT_RUNTIME_CORE_CXX_FLAGS})
|
||||
set(swift_runtime_linker_flags ${SWIFT_RUNTIME_CORE_LINK_FLAGS})
|
||||
|
||||
if(SWIFT_DARWIN_ENABLE_STABLE_ABI_BIT)
|
||||
list(APPEND swift_runtime_compile_flags
|
||||
"-DSWIFT_DARWIN_ENABLE_STABLE_ABI_BIT=1")
|
||||
endif()
|
||||
|
||||
if(SWIFT_RUNTIME_CLOBBER_FREED_OBJECTS)
|
||||
list(APPEND swift_runtime_compile_flags
|
||||
"-DSWIFT_RUNTIME_CLOBBER_FREED_OBJECTS=1")
|
||||
|
||||
@@ -443,7 +443,7 @@ static NSString *_getClassDescription(Class cls) {
|
||||
bool swift::usesNativeSwiftReferenceCounting(const ClassMetadata *theClass) {
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
if (!theClass->isTypeMetadata()) return false;
|
||||
return (theClass->getFlags() & ClassFlags::UsesSwift1Refcounting);
|
||||
return (theClass->getFlags() & ClassFlags::UsesSwiftRefcounting);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
// CHECK-native-SAME: %swift.opaque* null,
|
||||
// CHECK-objc-SAME: %swift.opaque* @_objc_empty_cache,
|
||||
// CHECK-SAME: %swift.opaque* null,
|
||||
// CHECK-SAME: i64 1,
|
||||
// CHECK-SAME: i32 3,
|
||||
// CHECK-SAME: i64 {{1|2}},
|
||||
// CHECK-SAME: i32 2,
|
||||
// CHECK-SAME: i32 0,
|
||||
// CHECK-SAME: i32 24,
|
||||
// CHECK-SAME: i16 7,
|
||||
@@ -52,8 +52,8 @@
|
||||
// CHECK-native-SAME: %swift.opaque* null,
|
||||
// CHECK-objc-SAME: %swift.opaque* @_objc_empty_cache,
|
||||
// CHECK-SAME: %swift.opaque* null,
|
||||
// CHECK-SAME: i64 1,
|
||||
// CHECK-SAME: i32 3,
|
||||
// CHECK-SAME: i64 {{1|2}},
|
||||
// CHECK-SAME: i32 2,
|
||||
// CHECK-SAME: i32 0,
|
||||
// CHECK-SAME: i32 24,
|
||||
// CHECK-SAME: i16 7,
|
||||
@@ -74,8 +74,8 @@
|
||||
// CHECK-native-SAME: %swift.opaque* null,
|
||||
// CHECK-objc-SAME: %swift.opaque* @_objc_empty_cache,
|
||||
// CHECK-SAME: %swift.opaque* null,
|
||||
// CHECK-SAME: i64 1,
|
||||
// CHECK-SAME: i32 3,
|
||||
// CHECK-SAME: i64 {{1|2}},
|
||||
// CHECK-SAME: i32 2,
|
||||
// CHECK-SAME: i32 0,
|
||||
// CHECK-SAME: i32 24,
|
||||
// CHECK-SAME: i16 7,
|
||||
@@ -96,8 +96,8 @@
|
||||
// CHECK-native-SAME: %swift.opaque* null,
|
||||
// CHECK-objc-SAME: %swift.opaque* @_objc_empty_cache,
|
||||
// CHECK-SAME: %swift.opaque* null,
|
||||
// CHECK-SAME: i64 1,
|
||||
// CHECK-SAME: i32 3,
|
||||
// CHECK-SAME: i64 {{1|2}},
|
||||
// CHECK-SAME: i32 2,
|
||||
// CHECK-SAME: i32 0,
|
||||
// CHECK-SAME: i32 24,
|
||||
// CHECK-SAME: i16 7,
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
// \ CHECK: [[TYPE]]* bitcast (i64* getelementptr inbounds (<{ {{.*}} }>, <{ {{.*}} }>* @_T014ivar_destroyer11TrivialBaseCMf, i32 0, i32 2) to [[TYPE]]*),
|
||||
// \ CHECK: [[OPAQUE]]* @_objc_empty_cache,
|
||||
// \ CHECK: [[OPAQUE]]* null,
|
||||
// \ CHECK: i64 add (i64 ptrtoint ({{.*}}* @_DATA__TtC14ivar_destroyer17NonTrivialDerived to i64), i64 1),
|
||||
// \ CHECK: i32 3,
|
||||
// \ CHECK: i64 add (i64 ptrtoint ({{.*}}* @_DATA__TtC14ivar_destroyer17NonTrivialDerived to i64), i64 {{1|2}}),
|
||||
// \ CHECK: i32 2,
|
||||
// \ CHECK: i32 0,
|
||||
// \ CHECK: i32 24,
|
||||
// \ CHECK: i16 7,
|
||||
|
||||
@@ -27,7 +27,7 @@ sil_vtable X {}
|
||||
// The getter/setter should not show up in the Swift metadata.
|
||||
/* FIXME: sil_vtable parser picks the wrong 'init' overload. Both vtable entries
|
||||
ought to be nonnull here. rdar://problem/19572342 */
|
||||
// CHECK: @_T019objc_attr_NSManaged10SwiftGizmoCMf = internal global <{ {{.*}} }> <{ void (%T19objc_attr_NSManaged10SwiftGizmoC*)* @_T019objc_attr_NSManaged10SwiftGizmoCfD, i8** @_T0BOWV, i64 ptrtoint (%objc_class* @"OBJC_METACLASS_$__TtC19objc_attr_NSManaged10SwiftGizmo" to i64), %objc_class* @"OBJC_CLASS_$_Gizmo", %swift.opaque* @_objc_empty_cache, %swift.opaque* null, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, { i32, i32, [2 x { i8*, i8*, i8* }] }*, i8*, i8*, i8*, { i32, i32, [1 x { i8*, i8* }] }* }* @_DATA__TtC19objc_attr_NSManaged10SwiftGizmo to i64), i64 1), i32 1, i32 0, i32 8, i16 7, i16 0, i32 112, i32 16, {{.*}}* @_T019objc_attr_NSManaged10SwiftGizmoCMn, i8* null, %T19objc_attr_NSManaged10SwiftGizmoC* (i64, %T19objc_attr_NSManaged10SwiftGizmoC*)* @_T019objc_attr_NSManaged10SwiftGizmoC7bellsOnACSi_tcfc, i8* bitcast (void ()* @swift_deletedMethodError to i8*) }>
|
||||
// CHECK: @_T019objc_attr_NSManaged10SwiftGizmoCMf = internal global <{ {{.*}} }> <{ void (%T19objc_attr_NSManaged10SwiftGizmoC*)* @_T019objc_attr_NSManaged10SwiftGizmoCfD, i8** @_T0BOWV, i64 ptrtoint (%objc_class* @"OBJC_METACLASS_$__TtC19objc_attr_NSManaged10SwiftGizmo" to i64), %objc_class* @"OBJC_CLASS_$_Gizmo", %swift.opaque* @_objc_empty_cache, %swift.opaque* null, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, { i32, i32, [2 x { i8*, i8*, i8* }] }*, i8*, i8*, i8*, { i32, i32, [1 x { i8*, i8* }] }* }* @_DATA__TtC19objc_attr_NSManaged10SwiftGizmo to i64), i64 {{1|2}}), i32 0, i32 0, i32 8, i16 7, i16 0, i32 112, i32 16, {{.*}}* @_T019objc_attr_NSManaged10SwiftGizmoCMn, i8* null, %T19objc_attr_NSManaged10SwiftGizmoC* (i64, %T19objc_attr_NSManaged10SwiftGizmoC*)* @_T019objc_attr_NSManaged10SwiftGizmoC7bellsOnACSi_tcfc, i8* bitcast (void ()* @swift_deletedMethodError to i8*) }>
|
||||
|
||||
@objc class SwiftGizmo : Gizmo {
|
||||
@objc @NSManaged var x: X
|
||||
|
||||
@@ -26,8 +26,8 @@ sil @_T06vtable1CCfD : $@convention(method) (@owned C) -> ()
|
||||
// CHECK-objc: %objc_class* @"OBJC_CLASS_$_SwiftObject",
|
||||
// CHECK-objc: %swift.opaque* @_objc_empty_cache,
|
||||
// CHECK-objc: %swift.opaque* null,
|
||||
// CHECK-objc: i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @_DATA__TtC6vtable1C to i64), i64 1),
|
||||
// CHECK-objc: i32 3, i32 0, i32 16, i16 7, i16 0,
|
||||
// CHECK-objc: i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @_DATA__TtC6vtable1C to i64), i64 {{1|2}}),
|
||||
// CHECK-objc: i32 2, i32 0, i32 16, i16 7, i16 0,
|
||||
// CHECK-objc: i32 112, i32 16,
|
||||
// CHECK-objc: @_T06vtable1CCMn
|
||||
// CHECK-objc: [[C]]* (%swift.type*)* @_T06vtable1CCACycACmcfC,
|
||||
@@ -42,7 +42,7 @@ sil @_T06vtable1CCfD : $@convention(method) (@owned C) -> ()
|
||||
// CHECK-native: %swift.opaque* null,
|
||||
// CHECK-native: %swift.opaque* null,
|
||||
// CHECK-native: i64 1,
|
||||
// CHECK-native: i32 3, i32 0, i32 16, i16 7, i16 0,
|
||||
// CHECK-native: i32 2, i32 0, i32 16, i16 7, i16 0,
|
||||
// CHECK-native: i32 112, i32 16,
|
||||
// CHECK-native: @_T06vtable1CCMn
|
||||
// CHECK-native: [[C]]* (%swift.type*)* @_T06vtable1CCACycACmcfC,
|
||||
|
||||
@@ -80,8 +80,8 @@ static SWIFT_CC(swift) void destroyTestObject(SWIFT_CONTEXT HeapObject *_object)
|
||||
|
||||
static const FullMetadata<ClassMetadata> TestClassObjectMetadata = {
|
||||
{ { &destroyTestObject }, { &VALUE_WITNESS_SYM(Bo) } },
|
||||
{ { { MetadataKind::Class } }, 0, /*rodata*/ 1,
|
||||
ClassFlags::UsesSwift1Refcounting, 0, 0, 0, 0, 0, 0 }
|
||||
{ { { MetadataKind::Class } }, 0, SWIFT_CLASS_IS_SWIFT_MASK,
|
||||
ClassFlags::UsesSwiftRefcounting, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
/// Create an object that, when deallocated, stores the given value to
|
||||
|
||||
@@ -98,8 +98,8 @@ static SWIFT_CC(swift) void deinitTestObject(SWIFT_CONTEXT HeapObject *_object)
|
||||
|
||||
static const FullMetadata<ClassMetadata> TestClassObjectMetadata = {
|
||||
{ { &deinitTestObject }, { &VALUE_WITNESS_SYM(Bo) } },
|
||||
{ { { MetadataKind::Class } }, 0, /*rodata*/ 1,
|
||||
ClassFlags::UsesSwift1Refcounting, 0, 0, 0, 0, 0, 0 }
|
||||
{ { { MetadataKind::Class } }, 0, SWIFT_CLASS_IS_SWIFT_MASK,
|
||||
ClassFlags::UsesSwiftRefcounting, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
/// Create an object that, when deinited, stores the given value to
|
||||
|
||||
@@ -31,8 +31,8 @@ static SWIFT_CC(swift) void destroyTestObject(SWIFT_CONTEXT HeapObject *_object)
|
||||
|
||||
static const FullMetadata<ClassMetadata> TestClassObjectMetadata = {
|
||||
{ { &destroyTestObject }, { &VALUE_WITNESS_SYM(Bo) } },
|
||||
{ { { MetadataKind::Class } }, 0, /*rodata*/ 1,
|
||||
ClassFlags::UsesSwift1Refcounting, 0, 0, 0, 0, 0, 0 }
|
||||
{ { { MetadataKind::Class } }, 0, SWIFT_CLASS_IS_SWIFT_MASK,
|
||||
ClassFlags::UsesSwiftRefcounting, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
/// Create an object that, when deallocated, stores the given value to
|
||||
|
||||
Reference in New Issue
Block a user