//===--- ForeignRepresentationInfo.h - Used in bridging queries -*- 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 // //===----------------------------------------------------------------------===// #ifndef SWIFT_FOREIGNREPRESENTATIONINFO_H #define SWIFT_FOREIGNREPRESENTATIONINFO_H #include "swift/AST/Type.h" #include "swift/Basic/LLVM.h" #include "llvm/ADT/PointerEmbeddedInt.h" #include "llvm/ADT/PointerIntPair.h" namespace swift { class ProtocolConformance; class ForeignRepresentationInfo { using PayloadTy = llvm::PointerEmbeddedInt; /// The low three bits store a ForeignRepresentableKind. /// /// When the ForeignRepresentableKind == None, the upper bits are /// the generation count at which this negative result was last checked. /// When it's Bridged, it's the conformance that describes the bridging. /// When it's Trivial, it's simply a flag stating whether Optional is /// supported. llvm::PointerIntPair Storage; public: /// Retrieve a cache entry for a non-foreign-representable type. static ForeignRepresentationInfo forNone(unsigned generation = 0) { ForeignRepresentationInfo result; result.Storage = { generation, ForeignRepresentableKind::None }; return result; } // Retrieve a cache entry for a trivially representable type. static ForeignRepresentationInfo forTrivial() { ForeignRepresentationInfo result; result.Storage = { 0, ForeignRepresentableKind::Trivial }; return result; } // Retrieve a cache entry for a trivially representable type that can also // be optional. static ForeignRepresentationInfo forTrivialWithOptional() { ForeignRepresentationInfo result; result.Storage = { 1, ForeignRepresentableKind::Trivial }; return result; } // Retrieve a cache entry for a bridged representable type. static ForeignRepresentationInfo forBridged(ProtocolConformance *conformance) { using PayloadTraits = llvm::PointerLikeTypeTraits; ForeignRepresentationInfo result; result.Storage = {PayloadTraits::getFromVoidPointer(conformance), ForeignRepresentableKind::Bridged}; assert(result.getConformance() == conformance && "insufficiently aligned"); return result; } // Retrieve a cache entry for a trivially representable type that can also // be optional. static ForeignRepresentationInfo forBridgedError() { ForeignRepresentationInfo result; result.Storage = { 0, ForeignRepresentableKind::BridgedError }; return result; } /// Retrieve the foreign representable kind. ForeignRepresentableKind getKind() const { return Storage.getInt(); } /// Retrieve the generation for a non-representable type. unsigned getGeneration() const { assert(getKind() == ForeignRepresentableKind::None); return Storage.getPointer(); } /// Retrieve the protocol conformance that makes it representable. ProtocolConformance *getConformance() const { switch (getKind()) { case ForeignRepresentableKind::None: llvm_unreachable("this type is not representable"); case ForeignRepresentableKind::Trivial: case ForeignRepresentableKind::BridgedError: return nullptr; case ForeignRepresentableKind::Bridged: { using PayloadTraits = llvm::PointerLikeTypeTraits; auto payload = PayloadTraits::getAsVoidPointer(Storage.getPointer()); return static_cast(payload); } case ForeignRepresentableKind::Object: case ForeignRepresentableKind::StaticBridged: llvm_unreachable("unexpected kind in ForeignRepresentableCacheEntry"); } llvm_unreachable("Unhandled ForeignRepresentableKind in switch."); } /// Returns true if the optional version of this type is also representable. bool isRepresentableAsOptional() const; }; } // end namespace swift #endif // SWIFT_FOREIGNREPRESENTATIONINFO_H