mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[irgen] Use object_getClass instead of object_getType() when lowering objc existential_metatype instructions.
Previously, we were not respecting the representation of the existential metatype and were treating all existential metatypes as if the metatype was a thick metatype. Instead now we properly grab the instance of the class from the existential and then query the runtime for the objc_class. This is done via the new entrypoint emitHeapMetadataRefForUnknownHeapObject. I also modified emitHeapMetadataRefForHeapObject to use emitHeapMetadataRefForUnknownHeapObject instead of emitLoadOfObjCHeapMetadataRef since the latter does not properly handle tagged pointers. This bug was found on inspection when Joe and I were talking about this change. rdar://18841292 Swift SVN r23308
This commit is contained in:
@@ -3516,14 +3516,13 @@ llvm::Value *irgen::emitHeapMetadataRefForHeapObject(IRGenFunction &IGF,
|
||||
CanType objectType,
|
||||
bool suppressCast) {
|
||||
ClassDecl *theClass = objectType.getClassOrBoundGenericClass();
|
||||
if (isKnownNotTaggedPointer(IGF.IGM, theClass))
|
||||
if (theClass && isKnownNotTaggedPointer(IGF.IGM, theClass))
|
||||
return emitLoadOfHeapMetadataRef(IGF, object,
|
||||
getIsaEncodingForType(IGF.IGM, objectType),
|
||||
suppressCast);
|
||||
|
||||
// OK, ask the runtime for the class pointer of this
|
||||
// potentially-ObjC object.
|
||||
return emitLoadOfObjCHeapMetadataRef(IGF, object);
|
||||
// OK, ask the runtime for the class pointer of this potentially-ObjC object.
|
||||
return emitHeapMetadataRefForUnknownHeapObject(IGF, object);
|
||||
}
|
||||
|
||||
llvm::Value *irgen::emitHeapMetadataRefForHeapObject(IRGenFunction &IGF,
|
||||
@@ -3549,6 +3548,20 @@ llvm::Value *irgen::emitDynamicTypeOfOpaqueHeapObject(IRGenFunction &IGF,
|
||||
return metadata;
|
||||
}
|
||||
|
||||
llvm::Value *irgen::
|
||||
emitHeapMetadataRefForUnknownHeapObject(IRGenFunction &IGF,
|
||||
llvm::Value *object) {
|
||||
object = IGF.Builder.CreateBitCast(object, IGF.IGM.ObjCPtrTy);
|
||||
auto metadata = IGF.Builder.CreateCall(IGF.IGM.getGetObjectClassFn(),
|
||||
object,
|
||||
object->getName() + ".Type");
|
||||
metadata->setCallingConv(IGF.IGM.RuntimeCC);
|
||||
metadata->setDoesNotThrow();
|
||||
metadata->addAttribute(llvm::AttributeSet::FunctionIndex,
|
||||
llvm::Attribute::ReadOnly);
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/// Given an object of class type, produce the type metadata reference
|
||||
/// as a %type*.
|
||||
llvm::Value *irgen::emitDynamicTypeOfHeapObject(IRGenFunction &IGF,
|
||||
|
||||
@@ -167,6 +167,11 @@ namespace irgen {
|
||||
SILType objectType,
|
||||
bool suppressCast = false);
|
||||
|
||||
/// Given a heap-object instance, with some heap-object type, produce a
|
||||
/// reference to its heap metadata by dynamically asking the runtime for it.
|
||||
llvm::Value *emitHeapMetadataRefForUnknownHeapObject(IRGenFunction &IGF,
|
||||
llvm::Value *object);
|
||||
|
||||
/// Given a heap-object instance, with some heap-object type,
|
||||
/// produce a reference to its heap metadata.
|
||||
llvm::Value *emitHeapMetadataRefForHeapObject(IRGenFunction &IGF,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -169,8 +169,8 @@ namespace irgen {
|
||||
|
||||
/// Emit the existential metatype of a class existential value.
|
||||
void emitMetatypeOfClassExistential(IRGenFunction &IGF,
|
||||
Explosion &value,
|
||||
SILType type, Explosion &out);
|
||||
Explosion &value, SILType metatypeType,
|
||||
SILType existentialType, Explosion &out);
|
||||
|
||||
std::pair<Address, llvm::Value*>
|
||||
emitIndirectExistentialProjectionWithMetadata(IRGenFunction &IGF,
|
||||
|
||||
@@ -1521,9 +1521,10 @@ void IRGenSILFunction::visitExistentialMetatypeInst(
|
||||
swift::ExistentialMetatypeInst *i) {
|
||||
Explosion result;
|
||||
if (i->getOperand().getType().isClassExistentialType()) {
|
||||
Explosion existential = getLoweredExplosion(i->getOperand());
|
||||
emitMetatypeOfClassExistential(*this, existential,
|
||||
i->getOperand().getType(), result);
|
||||
SILValue op = i->getOperand();
|
||||
Explosion existential = getLoweredExplosion(op);
|
||||
emitMetatypeOfClassExistential(*this, existential, i->getType(),
|
||||
op.getType(), result);
|
||||
} else {
|
||||
Address existential = getLoweredAddress(i->getOperand());
|
||||
emitMetatypeOfOpaqueExistential(*this, existential,
|
||||
|
||||
@@ -82,3 +82,14 @@ entry:
|
||||
%m = metatype $@objc_metatype T.Type
|
||||
return %m : $@objc_metatype T.Type
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define %objc_class* @existential_objc_metatype(%objc_object*) {
|
||||
// CHECK: entry:
|
||||
// CHECK-NEXT: [[METATYPE:%.*]] = call %objc_class* @object_getClass(%objc_object* %0) #1
|
||||
// CHECK-NEXT: ret %objc_class* [[METATYPE]]
|
||||
// CHECK-NEXT: }
|
||||
sil @existential_objc_metatype : $@thin (AnyObject) -> (@objc_metatype AnyObject.Type) {
|
||||
bb0(%0 : $AnyObject):
|
||||
%1 = existential_metatype $@objc_metatype AnyObject.Type, %0 : $AnyObject
|
||||
return %1 : $@objc_metatype AnyObject.Type
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user