| //===--- GenericRequirement.h - Generic requirements ------------*- 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 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 SubstitutionMap; |
| |
| namespace irgen { |
| class Address; |
| class IRGenFunction; |
| class IRGenModule; |
| |
| /// An abstract generic requirement. |
| struct GenericRequirement { |
| CanType TypeParameter; |
| ProtocolDecl *Protocol; |
| }; |
| |
| using RequirementCallback = |
| llvm::function_ref<void(GenericRequirement requirement)>; |
| |
| /// Enumerate the generic requirements imposed by a generic signature. |
| void enumerateGenericSignatureRequirements(CanGenericSignature signature, |
| const RequirementCallback &callback); |
| |
| /// 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, |
| const SubstitutionMap &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; |
| llvm::SmallVector<GenericRequirement, 4> Requirements; |
| |
| public: |
| GenericTypeRequirements(IRGenModule &IGM, NominalTypeDecl *decl); |
| |
| /// Return the layout chunks. |
| ArrayRef<GenericRequirement> getRequirements() const { |
| return Requirements; |
| } |
| |
| /// 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, const SubstitutionMap &subs, |
| FulfillmentCallback callback); |
| |
| void emitInitOfBuffer(IRGenFunction &IGF, const SubstitutionMap &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 |