Files
swift-mirror/lib/IRGen/GenClass.h
Joe Groff fb2fc93cbf IRGen: Followup fixes for handling subclasses of mixed-mode classes with missing ivars.
Following up on the fixes for rdar://problem/35330067. If a class inherits a class from another module with missing fields, we need to treat its size and alignment as opaque, just like the base class itself. We also need to lay out such  class at runtime, since we don't know the size, alignment, or field offsets at compile time; relying on the ObjC runtime alone will slide the ivar offsets, but not the Swift instance size and alignment. Fixes rdar://problem/35747485.
2017-11-29 19:21:36 -08:00

193 lines
8.0 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 "llvm/ADT/SmallVector.h"
#include "llvm/ADT/ArrayRef.h"
namespace llvm {
class Constant;
class Value;
class Function;
}
namespace swift {
class CanType;
class ClassDecl;
class ExtensionDecl;
class ProtocolDecl;
class SILType;
class Type;
class VarDecl;
namespace irgen {
class ConstantStructBuilder;
class HeapLayout;
class IRGenFunction;
class IRGenModule;
class MemberAccessStrategy;
class OwnedAddress;
class Address;
class Size;
class StructLayout;
class TypeInfo;
enum class ReferenceCounting : unsigned char;
enum class IsaEncoding : unsigned char;
enum class ClassDeallocationKind : unsigned char;
enum class FieldAccess : uint8_t;
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
};
std::pair<Size,Size>
emitClassPrivateDataFields(IRGenModule &IGM,
ConstantStructBuilder &builder,
ClassDecl *cls);
llvm::Constant *emitClassPrivateData(IRGenModule &IGM, ClassDecl *theClass);
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);
typedef llvm::ArrayRef<std::pair<SILType, llvm::Value *>> TailArraysRef;
/// Adds the size for tail allocated arrays to \p size and returns the new
/// size value.
llvm::Value *appendSizeForTailAllocatedArrays(IRGenFunction &IGF,
llvm::Value *size,
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, 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, 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 instance size of the class, or null if the class
/// does not have fixed layout. For resilient classes this does not
/// correspond to the runtime alignment of instances of the class.
llvm::Constant *tryEmitClassConstantFragileInstanceSize(IRGenModule &IGM,
ClassDecl *theClass);
/// Emit the constant fragile instance alignment mask of the class, or null if
/// the class does not have fixed layout. For resilient classes this does not
/// correspond to the runtime alignment of instances of the class.
llvm::Constant *tryEmitClassConstantFragileInstanceAlignMask(IRGenModule &IGM,
ClassDecl *theClass);
/// Emit the constant fragile offset of the given property inside an instance
/// of the class.
llvm::Constant *
tryEmitConstantClassFragilePhysicalMemberOffset(IRGenModule &IGM,
SILType baseType,
VarDecl *field);
unsigned getClassFieldIndex(IRGenModule &IGM,
SILType baseType,
VarDecl *field);
FieldAccess getClassFieldAccess(IRGenModule &IGM,
SILType baseType,
VarDecl *field);
/// 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);
/// What reference counting mechanism does a class-like type use?
ReferenceCounting getReferenceCountingForType(IRGenModule &IGM,
CanType type);
/// What isa-encoding mechanism does a type use?
IsaEncoding getIsaEncodingForType(IRGenModule &IGM, CanType type);
ClassDecl *getRootClassForMetaclass(IRGenModule &IGM, ClassDecl *theClass);
/// Does the class metadata for the given class require dynamic
/// initialization beyond what can be achieved automatically by
/// the runtime?
bool doesClassMetadataRequireDynamicInitialization(IRGenModule &IGM,
ClassDecl *theClass);
/// Returns true if a conformance of the \p conformingType references the
/// nominal type descriptor of the type.
///
/// Otherwise the conformance references the foreign metadata of the
/// \p conformingType.
bool doesConformanceReferenceNominalTypeDescriptor(IRGenModule &IGM,
CanType conformingType);
/// If the superclass came from another module, we may have dropped
/// stored properties due to the Swift language version availability of
/// their types. In these cases we can't precisely lay out the ivars in
/// the class object at compile time so we need to do runtime layout.
bool classHasIncompleteLayout(IRGenModule &IGM,
ClassDecl *theClass);
} // end namespace irgen
} // end namespace swift
#endif