mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
"minimal" is defined as the set of requirements that would be passed to a function with the type's generic signature that takes the thick metadata of the parent type as its only argument.
179 lines
6.0 KiB
C++
179 lines
6.0 KiB
C++
//===--- GenericRequirement.h - Generic requirements ------------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This class describes types for working with requirements of generic
|
|
// signatures and the layout of the generic arguments section of
|
|
// generic type metadata.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_IRGEN_GENERICREQUIREMENT_H
|
|
#define SWIFT_IRGEN_GENERICREQUIREMENT_H
|
|
|
|
#include "swift/AST/Type.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/ADT/DenseMapInfo.h"
|
|
|
|
namespace llvm {
|
|
class Value;
|
|
}
|
|
|
|
namespace swift {
|
|
class CanGenericSignature;
|
|
class ModuleDecl;
|
|
class NominalTypeDecl;
|
|
class ProtocolDecl;
|
|
class Substitution;
|
|
|
|
namespace irgen {
|
|
class Address;
|
|
class IRGenFunction;
|
|
class IRGenModule;
|
|
|
|
/// An abstract generic requirement.
|
|
struct GenericRequirement {
|
|
CanType TypeParameter;
|
|
ProtocolDecl *Protocol;
|
|
};
|
|
|
|
/// Given an array of substitutions that parallel the dependent
|
|
/// signature for which a requirement was emitted, emit the required
|
|
/// value.
|
|
llvm::Value *
|
|
emitGenericRequirementFromSubstitutions(IRGenFunction &IGF,
|
|
CanGenericSignature signature,
|
|
ModuleDecl &module,
|
|
GenericRequirement requirement,
|
|
ArrayRef<Substitution> subs);
|
|
|
|
using EmitGenericRequirementFn =
|
|
llvm::function_ref<llvm::Value*(GenericRequirement reqt)>;
|
|
void emitInitOfGenericRequirementsBuffer(IRGenFunction &IGF,
|
|
ArrayRef<GenericRequirement> reqts,
|
|
Address buffer,
|
|
EmitGenericRequirementFn emitRequirement);
|
|
|
|
using GetTypeParameterInContextFn =
|
|
llvm::function_ref<CanType(CanType type)>;
|
|
|
|
/// Given a required value, map the requirement into the given
|
|
/// context and bind the value.
|
|
void bindGenericRequirement(IRGenFunction &IGF,
|
|
GenericRequirement requirement,
|
|
llvm::Value *requiredValue,
|
|
GetTypeParameterInContextFn getInContext);
|
|
|
|
void bindFromGenericRequirementsBuffer(IRGenFunction &IGF,
|
|
ArrayRef<GenericRequirement> reqts,
|
|
Address buffer,
|
|
GetTypeParameterInContextFn getInContext);
|
|
|
|
|
|
/// A class describing the layout of the generic requirements of a
|
|
/// nominal type metadata.
|
|
///
|
|
/// The generic requirements are always laid out as a sequence of type
|
|
/// metadata (corresponding to the type parameters of the context established
|
|
/// by the type, minus anything fulfillable from its parent type metadata)
|
|
/// followed by a sequence of protocol witness tables (corresponding to the
|
|
/// root conformances of the context established by the type, again minus
|
|
/// anything fulfillable from its parent type metadata).
|
|
class GenericTypeRequirements {
|
|
NominalTypeDecl *TheDecl;
|
|
CanType ParentType;
|
|
llvm::SmallVector<GenericRequirement, 4> Requirements;
|
|
|
|
public:
|
|
GenericTypeRequirements(IRGenModule &IGM, NominalTypeDecl *decl);
|
|
|
|
/// Return the layout chunks.
|
|
ArrayRef<GenericRequirement> getRequirements() const {
|
|
return Requirements;
|
|
}
|
|
|
|
/// Does this generic type have
|
|
bool hasParentType() const {
|
|
return bool(ParentType);
|
|
}
|
|
|
|
CanType getParentType() const {
|
|
return ParentType;
|
|
}
|
|
|
|
/// Return the number of entries required in order to store this data.
|
|
unsigned getStorageSizeInWords() const {
|
|
return Requirements.size();
|
|
}
|
|
|
|
/// Return the number of type metadata requirements.
|
|
unsigned getNumTypeRequirements() const {
|
|
unsigned count = 0;
|
|
for (auto i = Requirements.begin(), e = Requirements.end(); i != e; ++i) {
|
|
if (!i->Protocol) {
|
|
count++;
|
|
} else {
|
|
#ifndef NDEBUG
|
|
// Assert that the rest of the requirements are conformance
|
|
// requirements.
|
|
for (++i; i != e; ++i) {
|
|
assert(i->Protocol && "type requirement followed conformance!");
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
bool empty() const { return Requirements.empty(); }
|
|
|
|
using FulfillmentCallback =
|
|
llvm::function_ref<void(unsigned requirementIndex,
|
|
CanType type,
|
|
Optional<ProtocolConformanceRef> conf)>;
|
|
void enumerateFulfillments(IRGenModule &IGM, ArrayRef<Substitution> subs,
|
|
FulfillmentCallback callback);
|
|
|
|
void emitInitOfBuffer(IRGenFunction &IGF, ArrayRef<Substitution> subs,
|
|
Address buffer);
|
|
|
|
void bindFromBuffer(IRGenFunction &IGF, Address buffer,
|
|
GetTypeParameterInContextFn getInContext);
|
|
};
|
|
|
|
} // end namespace irgen
|
|
} // end namespace swift
|
|
|
|
namespace llvm {
|
|
template <> struct DenseMapInfo<swift::irgen::GenericRequirement> {
|
|
using GenericRequirement = swift::irgen::GenericRequirement;
|
|
using CanTypeInfo = llvm::DenseMapInfo<swift::CanType>;
|
|
static GenericRequirement getEmptyKey() {
|
|
return { CanTypeInfo::getEmptyKey(), nullptr };
|
|
}
|
|
static GenericRequirement getTombstoneKey() {
|
|
return { CanTypeInfo::getTombstoneKey(), nullptr };
|
|
}
|
|
static llvm::hash_code getHashValue(GenericRequirement req) {
|
|
return hash_combine(CanTypeInfo::getHashValue(req.TypeParameter),
|
|
hash_value(req.Protocol));
|
|
}
|
|
static bool isEqual(GenericRequirement lhs, GenericRequirement rhs) {
|
|
return (lhs.TypeParameter == rhs.TypeParameter &&
|
|
lhs.Protocol == rhs.Protocol);
|
|
}
|
|
};
|
|
}
|
|
|
|
#endif
|