1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
|
//===--- GenClass.h - Swift IR generation for classes -----------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file provides the private interface to the class-emission code.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_IRGEN_GENCLASS_H
#define SWIFT_IRGEN_GENCLASS_H
#include "swift/AST/Types.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/ArrayRef.h"
namespace llvm {
class Constant;
class Value;
class Function;
class MDString;
}
namespace swift {
class ClassDecl;
class ExtensionDecl;
class ProtocolDecl;
struct SILDeclRef;
class SILType;
class VarDecl;
namespace irgen {
class ConstantStructBuilder;
class FunctionPointer;
class HeapLayout;
class IRGenFunction;
class IRGenModule;
class MemberAccessStrategy;
class OwnedAddress;
class Address;
class Size;
class StructLayout;
class TypeInfo;
enum class ClassDeallocationKind : unsigned char;
enum class FieldAccess : uint8_t;
/// Return the lowered type for the class's 'self' type within its context.
SILType getSelfType(const ClassDecl *base);
OwnedAddress projectPhysicalClassMemberAddress(
IRGenFunction &IGF, llvm::Value *base,
SILType baseType, SILType fieldType, VarDecl *field,
GenericSignature fnSig);
/// Return a strategy for accessing the given stored class property.
///
/// This API is used by RemoteAST.
MemberAccessStrategy
getPhysicalClassMemberAccessStrategy(IRGenModule &IGM,
SILType baseType, VarDecl *field);
enum ForMetaClass_t : bool {
ForClass = false,
ForMetaClass = true
};
enum HasUpdateCallback_t : bool {
DoesNotHaveUpdateCallback = false,
HasUpdateCallback = true
};
/// Creates a layout for the class \p classType with allocated tail elements
/// \p tailTypes.
///
/// The caller is responsible for deleting the returned StructLayout.
StructLayout *getClassLayoutWithTailElems(IRGenModule &IGM, SILType classType,
llvm::ArrayRef<SILType> tailTypes);
ClassDecl *getRootClassForMetaclass(IRGenModule &IGM, ClassDecl *theClass);
ClassDecl *getSuperclassDeclForMetadata(IRGenModule &IGM, ClassDecl *theClass);
CanType getSuperclassForMetadata(IRGenModule &IGM, ClassDecl *theClass);
CanType getSuperclassForMetadata(IRGenModule &IGM, CanType theClass,
bool useArchetypes = true);
enum class ClassMetadataStrategy {
/// Does the given class have resilient ancestry, or is the class itself
/// generic?
Resilient,
/// Does the class require at in-place initialization because of
/// non-fixed size properties or generic ancestry? The class does not
/// export a static symbol visible to Objective-C code.
Singleton,
/// A more restricted case of the above. Does the class require at in-place
/// initialization because of non-fixed size properties, while exporting a
/// static symbol visible to Objective-C code? The Objective-C runtime is
/// able to initialize the metadata by calling the update callback stored
/// in rodata. This strategy can only be used if the class availability
/// restricts its use to newer Objective-C runtimes that support this
/// feature.
Update,
/// An even more restricted case of the above. The class requires in-place
/// initialization on newer Objective-C runtimes, but the metadata is
/// statically valid on older runtimes because field offsets were computed
/// assuming type layouts loaded from a legacy type info YAML file.
FixedOrUpdate,
/// The class metadata is completely static and only Objective-C runtime
/// realization (and possibly field offset sliding) must be performed.
Fixed
};
std::pair<Size,Size>
emitClassPrivateDataFields(IRGenModule &IGM,
ConstantStructBuilder &builder,
ClassDecl *cls);
llvm::Constant *emitClassPrivateData(IRGenModule &IGM, ClassDecl *theClass);
llvm::Constant *emitSpecializedGenericClassPrivateData(IRGenModule &IGM,
ClassDecl *theClass,
CanType theType);
void emitGenericClassPrivateDataTemplate(IRGenModule &IGM,
ClassDecl *theClass,
llvm::SmallVectorImpl<llvm::Constant*> &fields,
Size &metaclassOffset,
Size &classRODataOffset,
Size &metaclassRODataOffset,
Size &totalSize);
llvm::Constant *emitCategoryData(IRGenModule &IGM, ExtensionDecl *ext);
llvm::Constant *emitObjCProtocolData(IRGenModule &IGM, ProtocolDecl *ext);
/// Emit a projection from a class instance to the first tail allocated
/// element.
Address emitTailProjection(IRGenFunction &IGF, llvm::Value *Base,
SILType ClassType, SILType TailType,
GenericSignature fnSig);
using TailArraysRef = llvm::ArrayRef<std::pair<SILType, llvm::Value *>>;
/// Adds the size for tail allocated arrays to \p size and returns the new
/// size value. Also updades the alignment mask to represent the alignment of
/// the largest element.
std::pair<llvm::Value *, llvm::Value *>
appendSizeForTailAllocatedArrays(IRGenFunction &IGF,
llvm::Value *size, llvm::Value *alignMask,
TailArraysRef TailArrays);
/// Emit an allocation of a class.
/// The \p StackAllocSize is an in- and out-parameter. The passed value
/// specifies the maximum object size for stack allocation. A negative value
/// means that no stack allocation is possible.
/// The returned \p StackAllocSize value is the actual size if the object is
/// allocated on the stack or -1, if the object is allocated on the heap.
llvm::Value *emitClassAllocation(IRGenFunction &IGF, SILType selfType,
bool objc, bool isBare, int &StackAllocSize, TailArraysRef TailArrays);
/// Emit an allocation of a class using a metadata value.
llvm::Value *emitClassAllocationDynamic(IRGenFunction &IGF,
llvm::Value *metadata,
SILType selfType,
bool objc,
int &StackAllocSize,
TailArraysRef TailArrays);
/// Emit class deallocation.
void emitClassDeallocation(IRGenFunction &IGF,
SILType selfType,
llvm::Value *selfValue,
GenericSignature fnSig);
/// Emit class deallocation.
void emitPartialClassDeallocation(IRGenFunction &IGF,
SILType selfType,
llvm::Value *selfValue,
llvm::Value *metadataValue,
GenericSignature fnSig);
/// Emit the constant fragile offset of the given property inside an instance
/// of the class.
llvm::Constant *tryEmitConstantClassFragilePhysicalMemberOffset(
IRGenModule &IGM, SILType baseType, VarDecl *field);
FieldAccess getClassFieldAccess(IRGenModule &IGM,
SILType baseType,
VarDecl *field);
Size getClassFieldOffset(IRGenModule &IGM,
SILType baseType,
VarDecl *field);
/// Load the instance size and alignment mask from a reference to
/// class type metadata of the given type.
std::pair<llvm::Value *, llvm::Value *>
emitClassResilientInstanceSizeAndAlignMask(IRGenFunction &IGF,
ClassDecl *theClass,
llvm::Value *metadata);
/// For VFE, returns a type identifier for the given base method on a class.
llvm::MDString *typeIdForMethod(IRGenModule &IGM, SILDeclRef method);
/// Given a metadata pointer, emit the callee for the given method.
FunctionPointer emitVirtualMethodValue(IRGenFunction &IGF,
llvm::Value *metadata,
SILDeclRef method,
CanSILFunctionType methodType);
/// Given an instance pointer (or, for a static method, a class
/// pointer), emit the callee for the given method.
FunctionPointer emitVirtualMethodValue(IRGenFunction &IGF, llvm::Value *base,
SILType baseType, SILDeclRef method,
CanSILFunctionType methodType,
GenericSignature fnSig,
bool useSuperVTable);
/// Is the given class known to have Swift-compatible metadata?
bool hasKnownSwiftMetadata(IRGenModule &IGM, ClassDecl *theClass);
inline bool isKnownNotTaggedPointer(IRGenModule &IGM, ClassDecl *theClass) {
// For now, assume any class type defined in Clang might be tagged.
return hasKnownSwiftMetadata(IGM, theClass);
}
/// Is the given class-like type known to have Swift-compatible
/// metadata?
bool hasKnownSwiftMetadata(IRGenModule &IGM, CanType theType);
} // end namespace irgen
} // end namespace swift
#endif
|