//===--- ResilientTypeInfo.h - Resilient-layout types -----------*- 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 defines a class used for implementing non-class-bound // archetypes, and resilient structs and enums. Values of these types are // opaque and must be manipulated through value witness function calls. // //===----------------------------------------------------------------------===// #ifndef SWIFT_IRGEN_RESILIENTTYPEINFO_H #define SWIFT_IRGEN_RESILIENTTYPEINFO_H #include "NonFixedTypeInfo.h" namespace swift { namespace irgen { /// An abstract CRTP class designed for types whose values are manipulated /// indirectly through value witness functions. /// /// We build upon WitnessSizedTypeInfo, adding the additional structure /// that the opaque value has the same size as the underlying type with /// no additional metadata, distinguishing this case from other uses of /// WitnessSizedTypeInfo, which are existentials (these add conformance /// tables) and fragile enums with generic payloads (these add tag bits). /// /// This allows us to make use of array value witness functions, and /// more importantly, to forward extra inhabitant information from the /// concrete type. This ensures that enums have the correct layout /// when accessed at different abstraction levels or from different /// resilience scopes. /// template class ResilientTypeInfo : public WitnessSizedTypeInfo { protected: ResilientTypeInfo(llvm::Type *type, IsABIAccessible_t abiAccessible) : WitnessSizedTypeInfo(type, Alignment(1), IsNotPOD, IsNotBitwiseTakable, abiAccessible) {} public: void assignWithCopy(IRGenFunction &IGF, Address dest, Address src, SILType T, bool isOutlined) const override { emitAssignWithCopyCall(IGF, T, dest, src); } void assignArrayWithCopyNoAlias(IRGenFunction &IGF, Address dest, Address src, llvm::Value *count, SILType T) const override { emitAssignArrayWithCopyNoAliasCall(IGF, T, dest, src, count); } void assignArrayWithCopyFrontToBack(IRGenFunction &IGF, Address dest, Address src, llvm::Value *count, SILType T) const override { emitAssignArrayWithCopyFrontToBackCall(IGF, T, dest, src, count); } void assignArrayWithCopyBackToFront(IRGenFunction &IGF, Address dest, Address src, llvm::Value *count, SILType T) const override { emitAssignArrayWithCopyBackToFrontCall(IGF, T, dest, src, count); } void assignWithTake(IRGenFunction &IGF, Address dest, Address src, SILType T, bool isOutlined) const override { emitAssignWithTakeCall(IGF, T, dest, src); } void assignArrayWithTake(IRGenFunction &IGF, Address dest, Address src, llvm::Value *count, SILType T) const override { emitAssignArrayWithTakeCall(IGF, T, dest, src, count); } Address initializeBufferWithCopyOfBuffer(IRGenFunction &IGF, Address dest, Address src, SILType T) const override { auto addr = emitInitializeBufferWithCopyOfBufferCall(IGF, T, dest, src); return this->getAddressForPointer(addr); } void initializeWithCopy(IRGenFunction &IGF, Address dest, Address src, SILType T, bool isOutlined) const override { emitInitializeWithCopyCall(IGF, T, dest, src); } void initializeArrayWithCopy(IRGenFunction &IGF, Address dest, Address src, llvm::Value *count, SILType T) const override { emitInitializeArrayWithCopyCall(IGF, T, dest, src, count); } void initializeWithTake(IRGenFunction &IGF, Address dest, Address src, SILType T, bool isOutlined) const override { emitInitializeWithTakeCall(IGF, T, dest, src); } void initializeArrayWithTakeNoAlias(IRGenFunction &IGF, Address dest, Address src, llvm::Value *count, SILType T) const override { emitInitializeArrayWithTakeNoAliasCall(IGF, T, dest, src, count); } void initializeArrayWithTakeFrontToBack(IRGenFunction &IGF, Address dest, Address src, llvm::Value *count, SILType T) const override { emitInitializeArrayWithTakeFrontToBackCall(IGF, T, dest, src, count); } void initializeArrayWithTakeBackToFront(IRGenFunction &IGF, Address dest, Address src, llvm::Value *count, SILType T) const override { emitInitializeArrayWithTakeBackToFrontCall(IGF, T, dest, src, count); } void destroy(IRGenFunction &IGF, Address addr, SILType T, bool isOutlined) const override { emitDestroyCall(IGF, T, addr); } void destroyArray(IRGenFunction &IGF, Address addr, llvm::Value *count, SILType T) const override { emitDestroyArrayCall(IGF, T, addr, count); } bool mayHaveExtraInhabitants(IRGenModule &IGM) const override { return true; } llvm::Value *getEnumTagSinglePayload(IRGenFunction &IGF, llvm::Value *numEmptyCases, Address enumAddr, SILType T, bool isOutlined) const override { return emitGetEnumTagSinglePayloadCall(IGF, T, numEmptyCases, enumAddr); } void storeEnumTagSinglePayload(IRGenFunction &IGF, llvm::Value *whichCase, llvm::Value *numEmptyCases, Address enumAddr, SILType T, bool isOutlined) const override { emitStoreEnumTagSinglePayloadCall(IGF, T, whichCase, numEmptyCases, enumAddr); } void collectMetadataForOutlining(OutliningMetadataCollector &collector, SILType T) const override { collector.collectTypeMetadataForLayout(T); } }; } } #endif