39
39
#include " llvm/IR/GlobalVariable.h"
40
40
#include " llvm/Support/raw_ostream.h"
41
41
42
+ #include " Callee.h"
42
43
#include " ConstantBuilder.h"
43
44
#include " Explosion.h"
44
45
#include " GenFunc.h"
53
54
#include " HeapTypeInfo.h"
54
55
#include " MemberAccessStrategy.h"
55
56
#include " MetadataLayout.h"
57
+ #include " MetadataRequest.h"
56
58
57
59
58
60
using namespace swift ;
59
61
using namespace irgen ;
60
62
61
- static ClassDecl *getRootClass (ClassDecl *theClass) {
62
- while (theClass->hasSuperclass ()) {
63
- theClass = theClass->getSuperclass ()->getClassOrBoundGenericClass ();
64
- assert (theClass && " base type of class not a class?" );
65
- }
66
- return theClass;
67
- }
68
-
69
63
// / What reference counting mechanism does a class-like type have?
70
64
ReferenceCounting irgen::getReferenceCountingForType (IRGenModule &IGM,
71
65
CanType type) {
@@ -87,21 +81,6 @@ ReferenceCounting irgen::getReferenceCountingForType(IRGenModule &IGM,
87
81
return ReferenceCounting::Unknown;
88
82
}
89
83
90
- // / What isa encoding mechanism does a type have?
91
- IsaEncoding irgen::getIsaEncodingForType (IRGenModule &IGM,
92
- CanType type) {
93
- if (auto theClass = type->getClassOrBoundGenericClass ()) {
94
- // We can access the isas of pure Swift classes directly.
95
- if (getRootClass (theClass)->hasKnownSwiftImplementation ())
96
- return IsaEncoding::Pointer;
97
- // For ObjC or mixed classes, we need to use object_getClass.
98
- return IsaEncoding::ObjC;
99
- }
100
- // Non-class heap objects should be pure Swift, so we can access their isas
101
- // directly.
102
- return IsaEncoding::Pointer;
103
- }
104
-
105
84
namespace {
106
85
// / Layout information for class types.
107
86
class ClassTypeInfo : public HeapTypeInfo <ClassTypeInfo> {
@@ -2332,3 +2311,156 @@ bool irgen::doesClassMetadataRequireDynamicInitialization(IRGenModule &IGM,
2332
2311
auto &layout = selfTI.getClassLayout (IGM, selfType);
2333
2312
return layout.MetadataRequiresDynamicInitialization ;
2334
2313
}
2314
+
2315
+ bool irgen::hasKnownSwiftMetadata (IRGenModule &IGM, CanType type) {
2316
+ if (ClassDecl *theClass = type.getClassOrBoundGenericClass ()) {
2317
+ return hasKnownSwiftMetadata (IGM, theClass);
2318
+ }
2319
+
2320
+ if (auto archetype = dyn_cast<ArchetypeType>(type)) {
2321
+ if (auto superclass = archetype->getSuperclass ()) {
2322
+ return hasKnownSwiftMetadata (IGM, superclass->getCanonicalType ());
2323
+ }
2324
+ }
2325
+
2326
+ // Class existentials, etc.
2327
+ return false ;
2328
+ }
2329
+
2330
+ // / Is the given class known to have Swift-compatible metadata?
2331
+ bool irgen::hasKnownSwiftMetadata (IRGenModule &IGM, ClassDecl *theClass) {
2332
+ // For now, the fact that a declaration was not implemented in Swift
2333
+ // is enough to conclusively force us into a slower path.
2334
+ // Eventually we might have an attribute here or something based on
2335
+ // the deployment target.
2336
+ return theClass->hasKnownSwiftImplementation ();
2337
+ }
2338
+
2339
+ // / Given a reference to class metadata of the given type,
2340
+ // / load the fragile instance size and alignment of the class.
2341
+ std::pair<llvm::Value *, llvm::Value *>
2342
+ irgen::emitClassFragileInstanceSizeAndAlignMask (IRGenFunction &IGF,
2343
+ ClassDecl *theClass,
2344
+ llvm::Value *metadata) {
2345
+ // FIXME: The below checks should capture this property already, but
2346
+ // resilient class metadata layout is not fully implemented yet.
2347
+ auto superClass = theClass;
2348
+ do {
2349
+ if (superClass->getParentModule () != IGF.IGM .getSwiftModule ()) {
2350
+ return emitClassResilientInstanceSizeAndAlignMask (IGF, theClass,
2351
+ metadata);
2352
+ }
2353
+ } while ((superClass = superClass->getSuperclassDecl ()));
2354
+
2355
+ // If the class has fragile fixed layout, return the constant size and
2356
+ // alignment.
2357
+ if (llvm::Constant *size
2358
+ = tryEmitClassConstantFragileInstanceSize (IGF.IGM , theClass)) {
2359
+ llvm::Constant *alignMask
2360
+ = tryEmitClassConstantFragileInstanceAlignMask (IGF.IGM , theClass);
2361
+ assert (alignMask && " static size without static align" );
2362
+ return {size, alignMask};
2363
+ }
2364
+
2365
+ // Otherwise, load it from the metadata.
2366
+ return emitClassResilientInstanceSizeAndAlignMask (IGF, theClass, metadata);
2367
+ }
2368
+
2369
+ std::pair<llvm::Value *, llvm::Value *>
2370
+ irgen::emitClassResilientInstanceSizeAndAlignMask (IRGenFunction &IGF,
2371
+ ClassDecl *theClass,
2372
+ llvm::Value *metadata) {
2373
+ auto &layout = IGF.IGM .getClassMetadataLayout (theClass);
2374
+
2375
+ Address metadataAsBytes (IGF.Builder .CreateBitCast (metadata, IGF.IGM .Int8PtrTy ),
2376
+ IGF.IGM .getPointerAlignment ());
2377
+
2378
+ Address slot = IGF.Builder .CreateConstByteArrayGEP (
2379
+ metadataAsBytes,
2380
+ layout.getInstanceSizeOffset ());
2381
+ slot = IGF.Builder .CreateBitCast (slot, IGF.IGM .Int32Ty ->getPointerTo ());
2382
+ llvm::Value *size = IGF.Builder .CreateLoad (slot);
2383
+ if (IGF.IGM .SizeTy != IGF.IGM .Int32Ty )
2384
+ size = IGF.Builder .CreateZExt (size, IGF.IGM .SizeTy );
2385
+
2386
+ slot = IGF.Builder .CreateConstByteArrayGEP (
2387
+ metadataAsBytes,
2388
+ layout.getInstanceAlignMaskOffset ());
2389
+ slot = IGF.Builder .CreateBitCast (slot, IGF.IGM .Int16Ty ->getPointerTo ());
2390
+ llvm::Value *alignMask = IGF.Builder .CreateLoad (slot);
2391
+ alignMask = IGF.Builder .CreateZExt (alignMask, IGF.IGM .SizeTy );
2392
+
2393
+ return {size, alignMask};
2394
+ }
2395
+
2396
+ FunctionPointer irgen::emitVirtualMethodValue (IRGenFunction &IGF,
2397
+ llvm::Value *metadata,
2398
+ SILDeclRef method,
2399
+ CanSILFunctionType methodType) {
2400
+ Signature signature = IGF.IGM .getSignature (methodType);
2401
+
2402
+ auto classDecl = cast<ClassDecl>(method.getDecl ()->getDeclContext ());
2403
+
2404
+ // Find the vtable entry we're interested in.
2405
+ auto methodInfo =
2406
+ IGF.IGM .getClassMetadataLayout (classDecl).getMethodInfo (IGF, method);
2407
+ auto offset = methodInfo.getOffset ();
2408
+
2409
+ auto slot = IGF.emitAddressAtOffset (metadata, offset,
2410
+ signature.getType ()->getPointerTo (),
2411
+ IGF.IGM .getPointerAlignment ());
2412
+ auto fnPtr = IGF.emitInvariantLoad (slot);
2413
+
2414
+ return FunctionPointer (fnPtr, signature);
2415
+ }
2416
+
2417
+ FunctionPointer irgen::emitVirtualMethodValue (IRGenFunction &IGF,
2418
+ llvm::Value *base,
2419
+ SILType baseType,
2420
+ SILDeclRef method,
2421
+ CanSILFunctionType methodType,
2422
+ bool useSuperVTable) {
2423
+ AbstractFunctionDecl *methodDecl
2424
+ = cast<AbstractFunctionDecl>(method.getDecl ());
2425
+
2426
+ // Find the vtable entry for this method.
2427
+ SILDeclRef overridden = method.getOverriddenVTableEntry ();
2428
+
2429
+ // Find the metadata.
2430
+ llvm::Value *metadata;
2431
+ if (useSuperVTable) {
2432
+ auto instanceTy = baseType;
2433
+ if (auto metaTy = dyn_cast<MetatypeType>(baseType.getSwiftRValueType ()))
2434
+ instanceTy = SILType::getPrimitiveObjectType (metaTy.getInstanceType ());
2435
+
2436
+ if (IGF.IGM .isResilient (instanceTy.getClassOrBoundGenericClass (),
2437
+ ResilienceExpansion::Maximal)) {
2438
+ // The derived type that is making the super call is resilient,
2439
+ // for example we may be in an extension of a class outside of our
2440
+ // resilience domain. So, we need to load the superclass metadata
2441
+ // dynamically.
2442
+
2443
+ metadata = emitClassHeapMetadataRef (IGF, instanceTy.getSwiftRValueType (),
2444
+ MetadataValueType::TypeMetadata);
2445
+ auto superField = emitAddressOfSuperclassRefInClassMetadata (IGF, metadata);
2446
+ metadata = IGF.Builder .CreateLoad (superField);
2447
+ } else {
2448
+ // Otherwise, we can directly load the statically known superclass's
2449
+ // metadata.
2450
+ auto superTy = instanceTy.getSuperclass ();
2451
+ metadata = emitClassHeapMetadataRef (IGF, superTy.getSwiftRValueType (),
2452
+ MetadataValueType::TypeMetadata);
2453
+ }
2454
+ } else {
2455
+ if ((isa<FuncDecl>(methodDecl) && cast<FuncDecl>(methodDecl)->isStatic ()) ||
2456
+ (isa<ConstructorDecl>(methodDecl) &&
2457
+ method.kind == SILDeclRef::Kind::Allocator)) {
2458
+ metadata = base;
2459
+ } else {
2460
+ metadata = emitHeapMetadataRefForHeapObject (IGF, base, baseType,
2461
+ /* suppress cast*/ true );
2462
+ }
2463
+ }
2464
+
2465
+ return emitVirtualMethodValue (IGF, metadata, overridden, methodType);
2466
+ }
0 commit comments