Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IRGen: Use swift_getObjectType to get the type(of:) mixed classes. #16923

Merged
merged 1 commit into from Jun 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 28 additions & 12 deletions lib/IRGen/GenHeap.cpp
Expand Up @@ -1967,16 +1967,30 @@ llvm::Value *irgen::emitDynamicTypeOfHeapObject(IRGenFunction &IGF,
llvm::Value *object,
MetatypeRepresentation repr,
SILType objectType,
bool suppressCast) {
// If it is known to have swift metadata, just load. A swift class is both
// heap metadata and type metadata.
if (hasKnownSwiftMetadata(IGF.IGM, objectType.getASTType())) {
return emitLoadOfHeapMetadataRef(IGF, object,
getIsaEncodingForType(IGF.IGM, objectType.getASTType()),
suppressCast);
bool allowArtificialSubclasses){
switch (auto isaEncoding =
getIsaEncodingForType(IGF.IGM, objectType.getASTType())) {
case IsaEncoding::Pointer:
// Directly load the isa pointer from a pure Swift class.
return emitLoadOfHeapMetadataRef(IGF, object, isaEncoding,
/*suppressCast*/ false);
case IsaEncoding::ObjC:
// A class defined in Swift that inherits from an Objective-C class may
// end up dynamically subclassed by ObjC runtime hackery. The artificial
// subclass isn't a formal Swift type, so isn't appropriate as the result
// of `type(of:)`, but is still a physical subtype of the real class object,
// so can be used for some purposes like satisfying type parameters in
// generic signatures.
if (allowArtificialSubclasses
&& hasKnownSwiftMetadata(IGF.IGM, objectType.getASTType()))
return emitLoadOfHeapMetadataRef(IGF, object, isaEncoding,
/*suppressCast*/ false);

// Ask the Swift runtime to find the dynamic type. This will look through
// dynamic subclasses of Swift classes, and use the -class message for
// ObjC classes.
return emitDynamicTypeOfOpaqueHeapObject(IGF, object, repr);
}

return emitDynamicTypeOfOpaqueHeapObject(IGF, object, repr);
}

static ClassDecl *getRootClass(ClassDecl *theClass) {
Expand All @@ -2001,6 +2015,11 @@ IsaEncoding irgen::getIsaEncodingForType(IRGenModule &IGM,
// For ObjC or mixed classes, we need to use object_getClass.
return IsaEncoding::ObjC;
}

// Existentials use the encoding of the enclosed dynamic type.
if (type->isAnyExistentialType()) {
return getIsaEncodingForType(IGM, ArchetypeType::getOpened(type));
}

if (auto archetype = dyn_cast<ArchetypeType>(type)) {
// If we have a concrete superclass constraint, just recurse.
Expand All @@ -2013,9 +2032,6 @@ IsaEncoding irgen::getIsaEncodingForType(IRGenModule &IGM,
return IsaEncoding::ObjC;
}

// We should never be working with an unopened existential type here.
assert(!type->isAnyExistentialType());

// Non-class heap objects should be pure Swift, so we can access their isas
// directly.
return IsaEncoding::Pointer;
Expand Down
2 changes: 1 addition & 1 deletion lib/IRGen/GenHeap.h
Expand Up @@ -152,7 +152,7 @@ llvm::Value *emitDynamicTypeOfHeapObject(IRGenFunction &IGF,
llvm::Value *object,
MetatypeRepresentation rep,
SILType objectType,
bool suppressCast = false);
bool allowArtificialSubclasses = false);

/// Given a non-tagged object pointer, load a pointer to its class object.
llvm::Value *emitLoadOfObjCHeapMetadataRef(IRGenFunction &IGF,
Expand Down
10 changes: 6 additions & 4 deletions lib/IRGen/GenProto.cpp
Expand Up @@ -627,9 +627,10 @@ bindParameterSource(SILParameterInfo param, unsigned paramIndex,
llvm::Value *instanceRef = getParameter(paramIndex);
SILType instanceType = SILType::getPrimitiveObjectType(paramType);
llvm::Value *metadata =
emitDynamicTypeOfHeapObject(IGF, instanceRef,
MetatypeRepresentation::Thick,
instanceType);
emitDynamicTypeOfHeapObject(IGF, instanceRef,
MetatypeRepresentation::Thick,
instanceType,
/*allow artificial subclasses*/ true);
IGF.bindLocalTypeDataFromTypeMetadata(paramType, IsInexact, metadata,
MetadataState::Complete);
return;
Expand Down Expand Up @@ -690,7 +691,8 @@ void BindPolymorphicParameter::emit(Explosion &nativeParam, unsigned paramIndex)
llvm::Value *metadata =
emitDynamicTypeOfHeapObject(IGF, instanceRef,
MetatypeRepresentation::Thick,
instanceType);
instanceType,
/* allow artificial subclasses */ true);
IGF.bindLocalTypeDataFromTypeMetadata(paramType, IsInexact, metadata,
MetadataState::Complete);
}
Expand Down
36 changes: 36 additions & 0 deletions test/IRGen/objc_typeof.swift
@@ -0,0 +1,36 @@
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-ir %s | %FileCheck %s
// REQUIRES: objc_interop

import Foundation

open class AllSwift {}

open class Mixed: NSObject {}

// CHECK-LABEL: define{{.*@.*}}14typeOfAllSwift
public func typeOfAllSwift(_ x: AllSwift) -> AllSwift.Type {
// CHECK: [[ISA:%.*]] = load %swift.type*
// CHECK: ret %swift.type* [[ISA]]
return type(of: x)
}

// CHECK-LABEL: define{{.*@.*}}11typeOfMixed
public func typeOfMixed(_ x: Mixed) -> Mixed.Type {
// CHECK: [[ISA:%.*]] = call %swift.type* @swift_getObjectType
// CHECK: ret %swift.type* [[ISA]]
return type(of: x)
}

// CHECK-LABEL: define{{.*@.*}}14typeOfNSObject
public func typeOfNSObject(_ x: NSObject) -> NSObject.Type {
// CHECK: [[ISA:%.*]] = call %swift.type* @swift_getObjectType
// CHECK: ret %swift.type* [[ISA]]
return type(of: x)
}

// CHECK-LABEL: define{{.*@.*}}13typeOfUnknown
public func typeOfUnknown(_ x: AnyObject) -> AnyObject.Type {
// CHECK: [[ISA:%.*]] = call %swift.type* @swift_getObjectType
// CHECK: ret %swift.type* [[ISA]]
return type(of: x)
}