mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
This removes the "optimization" where a function type, metatype or tuple type was split up into structural components, because it seems that in general we need this structural type metadata again. Similarly, this no longer tries to split up dependent concrete conformances and instead passes the witness table in the context. This makes the context larger potentially, but it avoids calls to metadata access functions and swift_getWitnessTable() every time the closure is invoked.
175 lines
5.0 KiB
C++
175 lines
5.0 KiB
C++
//===--- GenericRequirement.h - Generic requirement -------------*- 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_AST_GENERIC_REQUIREMENT_H
|
|
#define SWIFT_AST_GENERIC_REQUIREMENT_H
|
|
|
|
#include "swift/AST/Decl.h"
|
|
#include "swift/AST/Type.h"
|
|
#include "swift/AST/Types.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
namespace llvm {
|
|
class Type;
|
|
}
|
|
|
|
namespace swift {
|
|
|
|
class ProtocolDecl;
|
|
namespace irgen {
|
|
class IRGenModule;
|
|
}
|
|
|
|
/// The three kinds of entities passed in the runtime calling convention for
|
|
/// generic code: pack shapes, type metadata, and witness tables.
|
|
///
|
|
/// A pack shape describes an equivalence class of type parameter packs; the
|
|
/// runtime value is a single integer, which is the length of the pack.
|
|
///
|
|
/// Type metadata is emitted for each reduced generic parameter (that is,
|
|
/// not same-type constrained to another generic parameter or concrete type).
|
|
///
|
|
/// A witness table is emitted for each conformance requirement in the
|
|
/// generic signature.
|
|
class GenericRequirement {
|
|
public:
|
|
enum class Kind : uint8_t {
|
|
Shape,
|
|
Metadata,
|
|
WitnessTable,
|
|
MetadataPack,
|
|
WitnessTablePack,
|
|
};
|
|
|
|
private:
|
|
Kind kind;
|
|
CanType type;
|
|
ProtocolDecl *proto;
|
|
|
|
public:
|
|
GenericRequirement(Kind kind, CanType type, ProtocolDecl *proto)
|
|
: kind(kind), type(type), proto(proto) {}
|
|
|
|
Kind getKind() const {
|
|
return kind;
|
|
}
|
|
|
|
CanType getTypeParameter() const {
|
|
return type;
|
|
}
|
|
|
|
ProtocolDecl *getProtocol() const {
|
|
return proto;
|
|
}
|
|
|
|
bool isShape() const {
|
|
return kind == Kind::Shape;
|
|
}
|
|
|
|
static GenericRequirement forShape(CanType type) {
|
|
assert(type->isParameterPack() || isa<PackArchetypeType>(type));
|
|
return GenericRequirement(Kind::Shape, type, nullptr);
|
|
}
|
|
|
|
bool isMetadata() const {
|
|
return kind == Kind::Metadata;
|
|
}
|
|
bool isMetadataPack() const {
|
|
return kind == Kind::MetadataPack;
|
|
}
|
|
bool isAnyMetadata() const {
|
|
return kind == Kind::Metadata || kind == Kind::MetadataPack;
|
|
}
|
|
|
|
static GenericRequirement forMetadata(CanType type) {
|
|
auto kind = ((type->isParameterPack() ||
|
|
isa<PackArchetypeType>(type))
|
|
? Kind::MetadataPack : Kind::Metadata);
|
|
return GenericRequirement(kind, type, nullptr);
|
|
}
|
|
|
|
bool isWitnessTable() const {
|
|
return kind == Kind::WitnessTable;
|
|
}
|
|
bool isWitnessTablePack() const {
|
|
return kind == Kind::WitnessTablePack;
|
|
}
|
|
bool isAnyWitnessTable() const {
|
|
return kind == Kind::WitnessTable || kind == Kind::WitnessTablePack;
|
|
}
|
|
|
|
static GenericRequirement forWitnessTable(CanType type, ProtocolDecl *proto) {
|
|
auto kind = ((type->isParameterPack() ||
|
|
isa<PackArchetypeType>(type))
|
|
? Kind::WitnessTablePack
|
|
: Kind::WitnessTable);
|
|
return GenericRequirement(kind, type, proto);
|
|
}
|
|
|
|
static llvm::Type *typeForKind(irgen::IRGenModule &IGM,
|
|
GenericRequirement::Kind kind);
|
|
|
|
llvm::Type *getType(irgen::IRGenModule &IGM) const {
|
|
return typeForKind(IGM, getKind());
|
|
}
|
|
|
|
void dump(llvm::raw_ostream &out) const {
|
|
switch (kind) {
|
|
case Kind::Shape:
|
|
out << "shape: " << type;
|
|
break;
|
|
case Kind::Metadata:
|
|
out << "metadata: " << type;
|
|
break;
|
|
case Kind::WitnessTable:
|
|
out << "witness_table: " << type << " : " << proto->getName();
|
|
break;
|
|
case Kind::MetadataPack:
|
|
out << "metadata_pack: " << type;
|
|
break;
|
|
case Kind::WitnessTablePack:
|
|
out << "witness_table_pack: " << type << " : " << proto->getName();
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
} // end namespace swift
|
|
|
|
namespace llvm {
|
|
template <> struct DenseMapInfo<swift::GenericRequirement> {
|
|
using GenericRequirement = swift::GenericRequirement;
|
|
using CanTypeInfo = llvm::DenseMapInfo<swift::CanType>;
|
|
static GenericRequirement getEmptyKey() {
|
|
return GenericRequirement(GenericRequirement::Kind::Metadata,
|
|
CanTypeInfo::getEmptyKey(),
|
|
nullptr);
|
|
}
|
|
static GenericRequirement getTombstoneKey() {
|
|
return GenericRequirement(GenericRequirement::Kind::Metadata,
|
|
CanTypeInfo::getTombstoneKey(),
|
|
nullptr);
|
|
}
|
|
static llvm::hash_code getHashValue(GenericRequirement req) {
|
|
return hash_combine(CanTypeInfo::getHashValue(req.getTypeParameter()),
|
|
hash_value(req.getProtocol()));
|
|
}
|
|
static bool isEqual(GenericRequirement lhs, GenericRequirement rhs) {
|
|
return (lhs.getKind() == rhs.getKind() &&
|
|
lhs.getTypeParameter() == rhs.getTypeParameter() &&
|
|
lhs.getProtocol() == rhs.getProtocol());
|
|
}
|
|
};
|
|
} // end namespace llvm
|
|
|
|
#endif // SWIFT_AST_GENERIC_REQUIREMENT_H
|