//===-- 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 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;
};

}
}

namespace llvm {
template <> struct 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
