mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
240 lines
9.6 KiB
C++
240 lines
9.6 KiB
C++
//===--- 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);
|
|
|
|
/// 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);
|
|
|
|
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);
|
|
|
|
/// Emit class deallocation.
|
|
void emitPartialClassDeallocation(IRGenFunction &IGF,
|
|
SILType selfType,
|
|
llvm::Value *selfValue,
|
|
llvm::Value *metadataValue);
|
|
|
|
/// 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,
|
|
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
|