| //===--- 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 Impl> |
| class ResilientTypeInfo : public WitnessSizedTypeInfo<Impl> { |
| protected: |
| ResilientTypeInfo(llvm::Type *type) |
| : WitnessSizedTypeInfo<Impl>(type, Alignment(1), |
| IsNotPOD, IsNotBitwiseTakable) {} |
| |
| public: |
| void assignWithCopy(IRGenFunction &IGF, Address dest, Address src, |
| SILType T) 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) 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); |
| } |
| |
| Address initializeBufferWithTakeOfBuffer(IRGenFunction &IGF, |
| Address dest, Address src, |
| SILType T) const override { |
| auto addr = emitInitializeBufferWithTakeOfBufferCall(IGF, T, dest, src); |
| return this->getAddressForPointer(addr); |
| } |
| |
| void initializeWithCopy(IRGenFunction &IGF, |
| Address dest, Address src, SILType T) 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) 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) 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 *getExtraInhabitantIndex(IRGenFunction &IGF, |
| Address src, |
| SILType T) const override { |
| return emitGetExtraInhabitantIndexCall(IGF, T, src); |
| } |
| void storeExtraInhabitant(IRGenFunction &IGF, |
| llvm::Value *index, |
| Address dest, |
| SILType T) const override { |
| emitStoreExtraInhabitantCall(IGF, T, index, dest); |
| } |
| |
| void initializeMetadata(IRGenFunction &IGF, |
| llvm::Value *metadata, |
| llvm::Value *vwtable, |
| SILType T) const override { |
| // Resilient value types and archetypes always refer to an existing type. |
| // A witness table should never be independently initialized for one. |
| llvm_unreachable("initializing value witness table for opaque type?!"); |
| } |
| |
| }; |
| |
| } |
| } |
| |
| #endif |