Skip to content

Commit 5b60ace

Browse files
authored
Merge pull request swiftlang#15333 from rjmccall/metadata-access-file-shuffle
Move metadata-accessing IRGen out of GenMeta. NFC.
2 parents b04155b + aaa40ee commit 5b60ace

19 files changed

+2849
-2783
lines changed

lib/IRGen/GenCast.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@
1919
#include "Explosion.h"
2020
#include "GenEnum.h"
2121
#include "GenExistential.h"
22-
#include "GenMeta.h"
22+
#include "GenHeap.h"
2323
#include "GenProto.h"
2424
#include "IRGenDebugInfo.h"
2525
#include "IRGenFunction.h"
2626
#include "IRGenModule.h"
27+
#include "MetadataRequest.h"
2728
#include "TypeInfo.h"
2829
#include "llvm/IR/Function.h"
2930
#include "llvm/IR/Module.h"

lib/IRGen/GenClass.cpp

Lines changed: 155 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "llvm/IR/GlobalVariable.h"
4040
#include "llvm/Support/raw_ostream.h"
4141

42+
#include "Callee.h"
4243
#include "ConstantBuilder.h"
4344
#include "Explosion.h"
4445
#include "GenFunc.h"
@@ -53,19 +54,12 @@
5354
#include "HeapTypeInfo.h"
5455
#include "MemberAccessStrategy.h"
5556
#include "MetadataLayout.h"
57+
#include "MetadataRequest.h"
5658

5759

5860
using namespace swift;
5961
using namespace irgen;
6062

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-
6963
/// What reference counting mechanism does a class-like type have?
7064
ReferenceCounting irgen::getReferenceCountingForType(IRGenModule &IGM,
7165
CanType type) {
@@ -87,21 +81,6 @@ ReferenceCounting irgen::getReferenceCountingForType(IRGenModule &IGM,
8781
return ReferenceCounting::Unknown;
8882
}
8983

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-
10584
namespace {
10685
/// Layout information for class types.
10786
class ClassTypeInfo : public HeapTypeInfo<ClassTypeInfo> {
@@ -2332,3 +2311,156 @@ bool irgen::doesClassMetadataRequireDynamicInitialization(IRGenModule &IGM,
23322311
auto &layout = selfTI.getClassLayout(IGM, selfType);
23332312
return layout.MetadataRequiresDynamicInitialization;
23342313
}
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+
}

lib/IRGen/GenClass.h

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#ifndef SWIFT_IRGEN_GENCLASS_H
1818
#define SWIFT_IRGEN_GENCLASS_H
1919

20+
#include "swift/AST/Types.h"
2021
#include "llvm/ADT/SmallVector.h"
2122
#include "llvm/ADT/ArrayRef.h"
2223

@@ -27,16 +28,16 @@ namespace llvm {
2728
}
2829

2930
namespace swift {
30-
class CanType;
3131
class ClassDecl;
3232
class ExtensionDecl;
3333
class ProtocolDecl;
34+
struct SILDeclRef;
3435
class SILType;
35-
class Type;
3636
class VarDecl;
3737

3838
namespace irgen {
3939
class ConstantStructBuilder;
40+
class FunctionPointer;
4041
class HeapLayout;
4142
class IRGenFunction;
4243
class IRGenModule;
@@ -48,7 +49,6 @@ namespace irgen {
4849
class TypeInfo;
4950

5051
enum class ReferenceCounting : unsigned char;
51-
enum class IsaEncoding : unsigned char;
5252
enum class ClassDeallocationKind : unsigned char;
5353
enum class FieldAccess : uint8_t;
5454

@@ -163,9 +163,6 @@ namespace irgen {
163163
ReferenceCounting getReferenceCountingForType(IRGenModule &IGM,
164164
CanType type);
165165

166-
/// What isa-encoding mechanism does a type use?
167-
IsaEncoding getIsaEncodingForType(IRGenModule &IGM, CanType type);
168-
169166
ClassDecl *getRootClassForMetaclass(IRGenModule &IGM, ClassDecl *theClass);
170167

171168
/// Does the class metadata for the given class require dynamic
@@ -180,6 +177,48 @@ namespace irgen {
180177
/// the class object at compile time so we need to do runtime layout.
181178
bool classHasIncompleteLayout(IRGenModule &IGM,
182179
ClassDecl *theClass);
180+
181+
/// Load the fragile instance size and alignment mask from a reference to
182+
/// class type metadata of the given type.
183+
std::pair<llvm::Value *, llvm::Value *>
184+
emitClassFragileInstanceSizeAndAlignMask(IRGenFunction &IGF,
185+
ClassDecl *theClass,
186+
llvm::Value *metadata);
187+
188+
/// Load the instance size and alignment mask from a reference to
189+
/// class type metadata of the given type.
190+
std::pair<llvm::Value *, llvm::Value *>
191+
emitClassResilientInstanceSizeAndAlignMask(IRGenFunction &IGF,
192+
ClassDecl *theClass,
193+
llvm::Value *metadata);
194+
195+
/// Given a metadata pointer, emit the callee for the given method.
196+
FunctionPointer emitVirtualMethodValue(IRGenFunction &IGF,
197+
llvm::Value *metadata,
198+
SILDeclRef method,
199+
CanSILFunctionType methodType);
200+
201+
/// Given an instance pointer (or, for a static method, a class
202+
/// pointer), emit the callee for the given method.
203+
FunctionPointer emitVirtualMethodValue(IRGenFunction &IGF,
204+
llvm::Value *base,
205+
SILType baseType,
206+
SILDeclRef method,
207+
CanSILFunctionType methodType,
208+
bool useSuperVTable);
209+
210+
/// Is the given class known to have Swift-compatible metadata?
211+
bool hasKnownSwiftMetadata(IRGenModule &IGM, ClassDecl *theClass);
212+
213+
inline bool isKnownNotTaggedPointer(IRGenModule &IGM, ClassDecl *theClass) {
214+
// For now, assume any class type defined in Clang might be tagged.
215+
return hasKnownSwiftMetadata(IGM, theClass);
216+
}
217+
218+
/// Is the given class-like type known to have Swift-compatible
219+
/// metadata?
220+
bool hasKnownSwiftMetadata(IRGenModule &IGM, CanType theType);
221+
183222
} // end namespace irgen
184223
} // end namespace swift
185224

lib/IRGen/GenDecl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#include "IRGenMangler.h"
6565
#include "IRGenModule.h"
6666
#include "LoadableTypeInfo.h"
67+
#include "MetadataRequest.h"
6768
#include "ProtocolInfo.h"
6869
#include "Signature.h"
6970
#include "StructLayout.h"

lib/IRGen/GenExistential.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "IRGenDebugInfo.h"
4646
#include "IRGenFunction.h"
4747
#include "IRGenModule.h"
48+
#include "MetadataRequest.h"
4849
#include "NonFixedTypeInfo.h"
4950
#include "ProtocolInfo.h"
5051
#include "TypeInfo.h"

0 commit comments

Comments
 (0)