text: //===---- FineGrainedDependencyFormat.h - swiftdeps format ---*- C++ -*-======//
  //
  // This source file is part of the Swift.org open source project
  //
  // Copyright (c) 2014 - 2020 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_FINEGRAINEDDEPENDENCYFORMAT_H
  #define SWIFT_AST_FINEGRAINEDDEPENDENCYFORMAT_H
  
  #include "llvm/Bitcode/BitcodeConvenience.h"
  #include "llvm/Bitstream/BitCodes.h"
  
  namespace llvm {
  class MemoryBuffer;
  }
  
  namespace swift {
  
  class DiagnosticEngine;
  
  namespace fine_grained_dependencies {
  
  class SourceFileDepGraph;
  
  using llvm::BCFixed;
  using llvm::BCVBR;
  using llvm::BCBlob;
  using llvm::BCRecordLayout;
  
  /// Every .swiftdeps file begins with these 4 bytes, for easy identification when
  /// debugging.
  const unsigned char FINE_GRAINED_DEPDENENCY_FORMAT_SIGNATURE[] = {'D', 'E', 'P', 'S'};
  
  const unsigned FINE_GRAINED_DEPENDENCY_FORMAT_VERSION_MAJOR = 1;
  
  /// Increment this on every change.
  const unsigned FINE_GRAINED_DEPENDENCY_FORMAT_VERSION_MINOR = 0;
  
  using IdentifierIDField = BCVBR<13>;
  
  using NodeKindField = BCFixed<3>;
  using DeclAspectField = BCFixed<1>;
  
  const unsigned RECORD_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID;
  const unsigned INCREMENTAL_INFORMATION_BLOCK_ID = 196;
  
  /// The swiftdeps file format consists of a METADATA record, followed by zero or more
  /// IDENTIFIER_NODE records.
  ///
  /// Then, there is one SOURCE_FILE_DEP_GRAPH_NODE for each serialized
  /// SourceFileDepGraphNode. These are followed by FINGERPRINT_NODE and
  /// DEPENDS_ON_DEFINITION_NODE, if the node has a fingerprint and depends-on
  /// definitions, respectively.
  namespace record_block {
    enum {
      METADATA = 1,
      SOURCE_FILE_DEP_GRAPH_NODE,
      FINGERPRINT_NODE,
      DEPENDS_ON_DEFINITION_NODE,
      IDENTIFIER_NODE,
    };
  
    // Always the first record in the file.
    using MetadataLayout = BCRecordLayout<
      METADATA, // ID
      BCFixed<16>, // Dependency graph format major version
      BCFixed<16>, // Dependency graph format minor version
      BCBlob // Compiler version string
    >;
  
    // After the metadata record, we have zero or more identifier records,
    // for each unique string that is referenced from a SourceFileDepGraphNode.
    //
    // Identifiers are referenced by their sequence number, starting from 1.
    // The identifier value 0 is special; it always represents the empty string.
    // There is no IDENTIFIER_NODE serialized that corresponds to it, instead
    // the first IDENTIFIER_NODE always has a sequence number of 1.
    using IdentifierNodeLayout = BCRecordLayout<
      IDENTIFIER_NODE,
      BCBlob
    >;
  
    using SourceFileDepGraphNodeLayout = BCRecordLayout<
      SOURCE_FILE_DEP_GRAPH_NODE, // ID
      // The next four fields correspond to the fields of the DependencyKey
      // structure.
      NodeKindField, // DependencyKey::kind
      DeclAspectField, // DependencyKey::aspect
      IdentifierIDField, // DependencyKey::context
      IdentifierIDField, // DependencyKey::name
      BCFixed<1> // Is this a "provides" node?
    >;
  
    // Follows DEPENDS_ON_DEFINITION_NODE when the SourceFileDepGraphNode has a
    // fingerprint set.
    using FingerprintNodeLayout = BCRecordLayout<
      FINGERPRINT_NODE,
      BCBlob
    >;
  
    // Follows SOURCE_FILE_DEP_GRAPH_NODE and FINGERPRINT_NODE when the
    // SourceFileDepGraphNode has one or more depends-on entries.
    using DependsOnDefNodeLayout = BCRecordLayout<
      DEPENDS_ON_DEFINITION_NODE,
      BCVBR<16> // The sequence number (starting from 0) of the referenced
                // SOURCE_FILE_DEP_GRAPH_NODE
    >;
  }
  
  /// Tries to read the dependency graph from the given buffer.
  /// Returns \c true if there was an error.
  bool readFineGrainedDependencyGraph(llvm::MemoryBuffer &buffer,
                                      SourceFileDepGraph &g);
  
  /// Tries to read the dependency graph from the given buffer, assuming that it
  /// is in the format of a swiftmodule file.
  /// Returns \c true if there was an error.
  bool readFineGrainedDependencyGraphFromSwiftModule(llvm::MemoryBuffer &buffer,
                                                     SourceFileDepGraph &g);
  
  /// Tries to read the dependency graph from the given path name.
  /// Returns true if there was an error.
  bool readFineGrainedDependencyGraph(llvm::StringRef path,
                                      SourceFileDepGraph &g);
  
  /// Tries to write the dependency graph to the given path name.
  /// Returns true if there was an error.
  bool writeFineGrainedDependencyGraphToPath(DiagnosticEngine &diags,
                                             llvm::StringRef path,
                                             const SourceFileDepGraph &g);
  
  /// Enumerates the supported set of purposes for writing out or reading in
  /// swift dependency information into a file. These can be used to influence
  /// the structure of the resulting data that is produced by the serialization
  /// machinery defined here.
  enum class Purpose : bool {
    /// Write out fine grained dependency metadata suitable for embedding in
    /// \c .swiftmodule file.
    ///
    /// The resulting metadata does not contain the usual block descriptor header
    /// nor does it contain a leading magic signature, which would otherwise
    /// disrupt clients and tools that do not expect them to be present such as
    /// llvm-bcanalyzer.
    ForSwiftModule = false,
    /// Write out fine grained dependency metadata suitable for a standalone
    /// \c .swiftdeps file.
    ///
    /// The resulting metadata will contain a leading magic signature and block
    /// descriptor header.
    ForSwiftDeps = true,
  };
  
  /// Tries to write out the given dependency graph with the given
  /// bitstream writer.
  void writeFineGrainedDependencyGraph(llvm::BitstreamWriter &Out,
                                       const SourceFileDepGraph &g,
                                       Purpose purpose);
  
  } // namespace fine_grained_dependencies
  } // namespace swift
  
  #endif
  