예제 #1
0
  /// Build a map from generic parameter -> source of its metadata at runtime.
  ///
  /// If the callee that we are partially applying to create a box/closure
  /// isn't generic, then the map is empty.
  MetadataSourceMap getMetadataSourceMap() {
    MetadataSourceMap SourceMap;

    if (!OrigCalleeType->isPolymorphic())
      return SourceMap;

    // Any generic parameters that are not fulfilled are passed in via the
    // bindings. Structural types are decomposed, so emit the contents of
    // the bindings structure directly.
    auto &Bindings = Layout.getBindings();
    for (unsigned i = 0; i < Bindings.size(); ++i) {
      // Skip protocol requirements (FIXME: for now?)
      if (Bindings[i].Protocol != nullptr)
        continue;

      auto Source = SourceBuilder.createClosureBinding(i);
      auto BindingType = Caller.mapTypeOutOfContext(Bindings[i].TypeParameter);
      SourceMap.push_back({BindingType->getCanonicalType(), Source});
    }

    PolymorphicConvention Convention(IGM, OrigCalleeType);

    using SourceKind = PolymorphicConvention::SourceKind;

    // Check if any requirements were fulfilled by metadata stored inside a
    // captured value.
    auto GenericSig = OrigCalleeType->getGenericSignature();
    auto SubstMap = GenericSig->getSubstitutionMap(Subs);
    auto Generics = GenericSig->getGenericParams();

    for (auto GenericParam : Generics) {
      auto GenericParamType = GenericParam->getCanonicalType();

      auto Fulfillment
        = Convention.getFulfillmentForTypeMetadata(GenericParamType);

      if (Fulfillment != nullptr) {
        auto ConventionSource = Convention.getSource(Fulfillment->SourceIndex);

        if (ConventionSource.getKind() == SourceKind::SelfMetadata ||
            ConventionSource.getKind() == SourceKind::SelfWitnessTable) {
          // Handled as part of bindings
          continue;
        }

        // The metadata might be reached via a non-trivial path (eg,
        // dereferencing an isa pointer or a generic argument). Record
        // the path. We assume captured values map 1-1 with function
        // parameters.
        auto Root = ConventionSource.getMetadataSource(SourceBuilder);
        auto Src = Fulfillment->Path.getMetadataSource(SourceBuilder, Root);

        auto SubstType = Caller.mapTypeOutOfContext(SubstMap[GenericParam]);
        SourceMap.push_back({SubstType->getCanonicalType(), Src});
      }
    }

    return SourceMap;
  }
예제 #2
0
  /// Build a map from generic parameter -> source of its metadata at runtime.
  ///
  /// If the callee that we are partially applying to create a box/closure
  /// isn't generic, then the map is empty.
  MetadataSourceMap getMetadataSourceMap() {
    MetadataSourceMap SourceMap;

    // Generic parameters of pseudogeneric functions do not have
    // runtime metadata.
    if (!OrigCalleeType->isPolymorphic() ||
        OrigCalleeType->isPseudogeneric())
      return SourceMap;

    // Any generic parameters that are not fulfilled are passed in via the
    // bindings. Structural types are decomposed, so emit the contents of
    // the bindings structure directly.
    auto &Bindings = Layout.getBindings();
    for (unsigned i = 0; i < Bindings.size(); ++i) {
      // Skip protocol requirements (FIXME: for now?)
      if (Bindings[i].Protocol != nullptr)
        continue;

      auto Source = SourceBuilder.createClosureBinding(i);
      auto BindingType = Bindings[i].TypeParameter;
      auto InterfaceType = BindingType->mapTypeOutOfContext();
      SourceMap.push_back({InterfaceType->getCanonicalType(), Source});
    }

    // Check if any requirements were fulfilled by metadata stored inside a
    // captured value.

    enumerateGenericParamFulfillments(IGM, OrigCalleeType,
        [&](CanType GenericParam,
            const irgen::MetadataSource &Source,
            const MetadataPath &Path) {

      const reflection::MetadataSource *Root;
      switch (Source.getKind()) {
      case irgen::MetadataSource::Kind::SelfMetadata:
      case irgen::MetadataSource::Kind::SelfWitnessTable:
        // Handled as part of bindings
        return;

      case irgen::MetadataSource::Kind::GenericLValueMetadata:
        // FIXME?
        return;

      case irgen::MetadataSource::Kind::ClassPointer:
        Root = SourceBuilder.createReferenceCapture(Source.getParamIndex());
        break;

      case irgen::MetadataSource::Kind::Metadata:
        Root = SourceBuilder.createMetadataCapture(Source.getParamIndex());
        break;
      }

      // The metadata might be reached via a non-trivial path (eg,
      // dereferencing an isa pointer or a generic argument). Record
      // the path. We assume captured values map 1-1 with function
      // parameters.
      auto Src = Path.getMetadataSource(SourceBuilder, Root);

      auto SubstType = GenericParam.subst(Subs);
      auto InterfaceType = SubstType->mapTypeOutOfContext();
      SourceMap.push_back({InterfaceType->getCanonicalType(), Src});
    });

    return SourceMap;
  }