| //===-- LocalTypeDataKind.h - Kinds of locally-cached type data -*- 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 the LocalTypeDataKind class, which opaquely |
| // represents a particular kind of local type data that we might |
| // want to cache during emission. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_IRGEN_LOCALTYPEDATAKIND_H |
| #define SWIFT_IRGEN_LOCALTYPEDATAKIND_H |
| |
| #include "swift/AST/ProtocolConformanceRef.h" |
| #include "swift/AST/Type.h" |
| #include <stdint.h> |
| #include "llvm/ADT/DenseMapInfo.h" |
| |
| namespace swift { |
| class NormalProtocolConformance; |
| class ProtocolDecl; |
| |
| namespace irgen { |
| enum class ValueWitness : unsigned; |
| |
| /// The kind of local type data we might want to store for a type. |
| class LocalTypeDataKind { |
| public: |
| using RawType = uintptr_t; |
| private: |
| RawType Value; |
| |
| explicit LocalTypeDataKind(RawType Value) : Value(Value) {} |
| |
| /// Magic values for special kinds of type metadata. These should be |
| /// small so that they should never conflict with a valid pointer. |
| /// |
| /// Since this representation is opaque, we don't worry about being able |
| /// to distinguish different kinds of pointer; we just assume that e.g. a |
| /// ProtocolConformance will never have the same address as a Decl. |
| enum : RawType { |
| FormalTypeMetadata, |
| RepresentationTypeMetadata, |
| ValueWitnessTable, |
| // <- add more special cases here |
| |
| // The first enumerator for an individual value witness. |
| ValueWitnessBase, |
| |
| FirstPayloadValue = 2048, |
| Kind_Decl = 0, |
| Kind_Conformance = 1, |
| KindMask = 0x1, |
| }; |
| |
| public: |
| LocalTypeDataKind() = default; |
| |
| // The magic values are all odd and so do not collide with pointer values. |
| |
| /// A reference to the formal type metadata. |
| static LocalTypeDataKind forFormalTypeMetadata() { |
| return LocalTypeDataKind(FormalTypeMetadata); |
| } |
| |
| /// A reference to type metadata for a representation-compatible type. |
| static LocalTypeDataKind forRepresentationTypeMetadata() { |
| return LocalTypeDataKind(RepresentationTypeMetadata); |
| } |
| |
| /// A reference to the value witness table for a representation-compatible |
| /// type. |
| static LocalTypeDataKind forValueWitnessTable() { |
| return LocalTypeDataKind(ValueWitnessTable); |
| } |
| |
| /// A reference to a specific value witness for a representation-compatible |
| /// type. |
| static LocalTypeDataKind forValueWitness(ValueWitness witness) { |
| return LocalTypeDataKind(ValueWitnessBase + (unsigned)witness); |
| } |
| |
| /// A reference to a protocol witness table for an archetype. |
| /// |
| /// This only works for non-concrete types because in principle we might |
| /// have multiple concrete conformances for a concrete type used in the |
| /// same function. |
| static LocalTypeDataKind |
| forAbstractProtocolWitnessTable(ProtocolDecl *protocol) { |
| assert(protocol && "protocol reference may not be null"); |
| return LocalTypeDataKind(uintptr_t(protocol) | Kind_Decl); |
| } |
| |
| /// A reference to a protocol witness table for an archetype. |
| static LocalTypeDataKind |
| forConcreteProtocolWitnessTable(ProtocolConformance *conformance) { |
| assert(conformance && "conformance reference may not be null"); |
| return LocalTypeDataKind(uintptr_t(conformance) | Kind_Conformance); |
| } |
| |
| static LocalTypeDataKind |
| forProtocolWitnessTable(ProtocolConformanceRef conformance) { |
| if (conformance.isConcrete()) { |
| return forConcreteProtocolWitnessTable(conformance.getConcrete()); |
| } else { |
| return forAbstractProtocolWitnessTable(conformance.getAbstract()); |
| } |
| } |
| |
| LocalTypeDataKind getCachingKind() const; |
| |
| bool isAnyTypeMetadata() const { |
| return Value == FormalTypeMetadata || |
| Value == RepresentationTypeMetadata; |
| } |
| |
| bool isSingletonKind() const { |
| return (Value < FirstPayloadValue); |
| } |
| |
| bool isConcreteProtocolConformance() const { |
| return (!isSingletonKind() && |
| ((Value & KindMask) == Kind_Conformance)); |
| } |
| |
| ProtocolConformance *getConcreteProtocolConformance() const { |
| assert(isConcreteProtocolConformance()); |
| return reinterpret_cast<ProtocolConformance*>(Value - Kind_Conformance); |
| } |
| |
| bool isAbstractProtocolConformance() const { |
| return (!isSingletonKind() && |
| ((Value & KindMask) == Kind_Decl)); |
| } |
| |
| ProtocolDecl *getAbstractProtocolConformance() const { |
| assert(isAbstractProtocolConformance()); |
| return reinterpret_cast<ProtocolDecl*>(Value - Kind_Decl); |
| } |
| |
| ProtocolConformanceRef getProtocolConformance() const { |
| assert(!isSingletonKind()); |
| if ((Value & KindMask) == Kind_Decl) { |
| return ProtocolConformanceRef(getAbstractProtocolConformance()); |
| } else { |
| return ProtocolConformanceRef(getConcreteProtocolConformance()); |
| } |
| } |
| |
| RawType getRawValue() const { |
| return Value; |
| } |
| |
| void dump() const; |
| void print(llvm::raw_ostream &out) const; |
| |
| bool operator==(LocalTypeDataKind other) const { |
| return Value == other.Value; |
| } |
| bool operator!=(LocalTypeDataKind other) const { |
| return Value != other.Value; |
| } |
| }; |
| |
| class LocalTypeDataKey { |
| public: |
| CanType Type; |
| LocalTypeDataKind Kind; |
| |
| LocalTypeDataKey(CanType type, LocalTypeDataKind kind) |
| : Type(type), Kind(kind) {} |
| |
| LocalTypeDataKey getCachingKey() const; |
| |
| bool operator==(const LocalTypeDataKey &other) const { |
| return Type == other.Type && Kind == other.Kind; |
| } |
| |
| void dump() const; |
| void print(llvm::raw_ostream &out) const; |
| }; |
| |
| } |
| } |
| |
| template <> struct llvm::DenseMapInfo<swift::irgen::LocalTypeDataKey> { |
| using LocalTypeDataKey = swift::irgen::LocalTypeDataKey; |
| using CanTypeInfo = DenseMapInfo<swift::CanType>; |
| static inline LocalTypeDataKey getEmptyKey() { |
| return { CanTypeInfo::getEmptyKey(), |
| swift::irgen::LocalTypeDataKind::forFormalTypeMetadata() }; |
| } |
| static inline LocalTypeDataKey getTombstoneKey() { |
| return { CanTypeInfo::getTombstoneKey(), |
| swift::irgen::LocalTypeDataKind::forFormalTypeMetadata() }; |
| } |
| static unsigned getHashValue(const LocalTypeDataKey &key) { |
| return combineHashValue(CanTypeInfo::getHashValue(key.Type), |
| key.Kind.getRawValue()); |
| } |
| static bool isEqual(const LocalTypeDataKey &a, const LocalTypeDataKey &b) { |
| return a == b; |
| } |
| }; |
| |
| #endif |