//===--- GenProto.h - Swift IR generation for prototypes --------*- 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 provides the private interface to the protocol-emission code. // //===----------------------------------------------------------------------===// #ifndef SWIFT_IRGEN_GENPROTO_H #define SWIFT_IRGEN_GENPROTO_H #include "swift/SIL/SILFunction.h" #include "Fulfillment.h" #include "GenericRequirement.h" namespace llvm { class Type; } namespace swift { class AssociatedConformance; class AssociatedType; class CanType; class FuncDecl; enum class MetadataState : size_t; class ProtocolConformanceRef; struct SILDeclRef; class SILType; class SILFunction; namespace irgen { class Address; class DynamicMetadataRequest; class Explosion; class FunctionPointer; class IRGenFunction; class IRGenModule; class MetadataPath; class MetadataResponse; class ProtocolInfo; class TypeInfo; /// Set an LLVM value name for the given type metadata. void setTypeMetadataName(IRGenModule &IGM, llvm::Value *value, CanType type); /// Set an LLVM value name for the given protocol witness table. void setProtocolWitnessTableName(IRGenModule &IGM, llvm::Value *value, CanType type, ProtocolDecl *protocol); /// Extract the method pointer from the given witness table /// as a function value. FunctionPointer emitWitnessMethodValue(IRGenFunction &IGF, llvm::Value *wtable, SILDeclRef member); /// Extract the method pointer from an archetype's witness table /// as a function value. FunctionPointer emitWitnessMethodValue(IRGenFunction &IGF, CanType baseTy, llvm::Value **baseMetadataCache, SILDeclRef member, ProtocolConformanceRef conformance); /// Compute the index into a witness table for a resilient protocol given /// a reference to a descriptor of one of the requirements in that witness /// table. llvm::Value *computeResilientWitnessTableIndex( IRGenFunction &IGF, ProtocolDecl *proto, llvm::Constant *reqtDescriptor); /// Given a type T and an associated type X of some protocol P to /// which T conforms, return the type metadata for T.X. /// /// \param parentMetadata - the type metadata for T /// \param wtable - the witness table witnessing the conformance of T to P /// \param associatedType - the declaration of X; a member of P MetadataResponse emitAssociatedTypeMetadataRef(IRGenFunction &IGF, llvm::Value *parentMetadata, llvm::Value *wtable, AssociatedType associatedType, DynamicMetadataRequest request); // Return the offset one should do on a witness table pointer to retrieve the // `index`th piece of private data. inline int privateWitnessTableIndexToTableOffset(unsigned index) { return -1 - (int)index; } /// Add the witness parameters necessary for calling a function with /// the given generics clause. void expandPolymorphicSignature(IRGenModule &IGM, CanSILFunctionType type, SmallVectorImpl &types); /// Return the number of trailing arguments necessary for calling a /// witness method. inline unsigned getTrailingWitnessSignatureLength(IRGenModule &IGM, CanSILFunctionType type) { return 2; } /// Add the trailing arguments necessary for calling a witness method. void expandTrailingWitnessSignature(IRGenModule &IGM, CanSILFunctionType type, SmallVectorImpl &types); struct WitnessMetadata { llvm::Value *SelfMetadata = nullptr; llvm::Value *SelfWitnessTable = nullptr; }; /// Collect any required metadata for a witness method from the end /// of the given parameter list. void collectTrailingWitnessMetadata(IRGenFunction &IGF, SILFunction &fn, Explosion ¶ms, WitnessMetadata &metadata); using GetParameterFn = llvm::function_ref; /// In the prelude of a generic function, perform the bindings for a /// generics clause. /// /// \param witnessMetadata - can be omitted if the function is /// definitely not a witness method void emitPolymorphicParameters(IRGenFunction &IGF, SILFunction &Fn, Explosion &args, WitnessMetadata *witnessMetadata, const GetParameterFn &getParameter); void emitPolymorphicParametersFromArray(IRGenFunction &IGF, NominalTypeDecl *typeDecl, Address array, MetadataState metadataState); /// When calling a polymorphic call, pass the arguments for the /// generics clause. void emitPolymorphicArguments(IRGenFunction &IGF, CanSILFunctionType origType, SubstitutionMap subs, WitnessMetadata *witnessMetadata, Explosion &args); /// Bind the polymorphic parameter inside of a partial apply forwarding thunk. void bindPolymorphicParameter(IRGenFunction &IGF, CanSILFunctionType &OrigFnType, CanSILFunctionType &SubstFnType, Explosion &nativeParam, unsigned paramIndex); /// Load a reference to the protocol descriptor for the given protocol. /// /// For Swift protocols, this is a constant reference to the protocol /// descriptor symbol. /// For ObjC protocols, descriptors are uniqued at runtime by the ObjC /// runtime. We need to load the unique reference from a global variable fixed up at /// startup. llvm::Value *emitProtocolDescriptorRef(IRGenFunction &IGF, ProtocolDecl *protocol); /// Emit a witness table reference. llvm::Value *emitWitnessTableRef(IRGenFunction &IGF, CanType srcType, llvm::Value **srcMetadataCache, ProtocolConformanceRef conformance); llvm::Value *emitWitnessTableRef(IRGenFunction &IGF, CanType srcType, ProtocolConformanceRef conformance); class MetadataSource { public: enum class Kind { /// Metadata is derived from a source class pointer. ClassPointer, /// Metadata is derived from a type metadata pointer. Metadata, /// Metadata is derived from the origin type parameter. GenericLValueMetadata, /// Metadata is obtained directly from the from a Self metadata /// parameter passed via the WitnessMethod convention. SelfMetadata, /// Metadata is derived from the Self witness table parameter /// passed via the WitnessMethod convention. SelfWitnessTable, }; static bool requiresSourceIndex(Kind kind) { return (kind == Kind::ClassPointer || kind == Kind::Metadata || kind == Kind::GenericLValueMetadata); } enum : unsigned { InvalidSourceIndex = ~0U }; private: /// The kind of source this is. Kind TheKind; /// The parameter index, for ClassPointer and Metadata sources. unsigned Index; public: CanType Type; MetadataSource(Kind kind, unsigned index, CanType type) : TheKind(kind), Index(index), Type(type) { assert(index != InvalidSourceIndex || !requiresSourceIndex(kind)); } Kind getKind() const { return TheKind; } unsigned getParamIndex() const { assert(requiresSourceIndex(getKind())); return Index; } }; using GenericParamFulfillmentCallback = llvm::function_ref; void enumerateGenericParamFulfillments(IRGenModule &IGM, CanSILFunctionType fnType, GenericParamFulfillmentCallback callback); } // end namespace irgen } // end namespace swift #endif