mutating func addCompileInputs()

in Sources/SwiftDriver/Jobs/CompileJob.swift [104:218]


  mutating func addCompileInputs(primaryInputs: [TypedVirtualPath],
                                 indexFilePath: TypedVirtualPath?,
                                 inputs: inout [TypedVirtualPath],
                                 inputOutputMap: inout [TypedVirtualPath: [TypedVirtualPath]],
                                 outputType: FileType?,
                                 commandLine: inout [Job.ArgTemplate])
  -> ([TypedVirtualPath], [TypedVirtualPath]) {
    let useInputFileList: Bool
    if let allSourcesFileList = allSourcesFileList {
      useInputFileList = true
      commandLine.appendFlag(.filelist)
      commandLine.appendPath(allSourcesFileList)
    } else {
      useInputFileList = false
    }

    let usePrimaryInputFileList = primaryInputs.count > fileListThreshold
    if usePrimaryInputFileList {
      // primary file list
      commandLine.appendFlag(.primaryFilelist)
      let fileList = VirtualPath.createUniqueFilelist(RelativePath("primaryInputs"),
                                                      .list(primaryInputs.map(\.file)))
      commandLine.appendPath(fileList)
    }

    let isTopLevel = isTopLevelOutput(type: outputType)

    // If we will be passing primary files via -primary-file, form a set of primary input files so
    // we can check more quickly.
    let usesPrimaryFileInputs: Bool
    // N.B. We use an array instead of a hashed collection like a set because
    // TypedVirtualPaths are quite expensive to hash. To the point where a
    // linear scan beats Set.contains by a factor of 4 for heavy workloads.
    let primaryInputFiles: [TypedVirtualPath]
    if compilerMode.usesPrimaryFileInputs {
      assert(!primaryInputs.isEmpty)
      usesPrimaryFileInputs = true
      primaryInputFiles = primaryInputs
    } else if let path = indexFilePath {
      // If -index-file is used, we perform a single compile but pass the
      // -index-file-path as a primary input file.
      usesPrimaryFileInputs = true
      primaryInputFiles = [path]
    } else {
      usesPrimaryFileInputs = false
      primaryInputFiles = []
    }

    let isMultithreaded = numThreads > 0

    // Add each of the input files.
    var primaryOutputs: [TypedVirtualPath] = []
    var primaryIndexUnitOutputs: [TypedVirtualPath] = []
    var indexUnitOutputDiffers = false
    let firstSwiftInput = inputs.count
    for input in self.inputFiles where input.type.isPartOfSwiftCompilation {
      inputs.append(input)

      let isPrimary = usesPrimaryFileInputs && primaryInputFiles.contains(input)
      if isPrimary {
        if !usePrimaryInputFileList {
          commandLine.appendFlag(.primaryFile)
          commandLine.appendPath(input.file)
        }
      } else {
        if !useInputFileList {
          commandLine.appendPath(input.file)
        }
      }

      // If there is a primary output or we are doing multithreaded compiles,
      // add an output for the input.
      if let outputType = outputType,
        isPrimary || (!usesPrimaryFileInputs && isMultithreaded && outputType.isAfterLLVM) {
        let output = computePrimaryOutput(for: input,
                                          outputType: outputType,
                                          isTopLevel: isTopLevel)
        primaryOutputs.append(output)
        inputOutputMap[input] = [output]

        if let indexUnitOut = computeIndexUnitOutput(for: input, outputType: outputType, topLevel: isTopLevel) {
          indexUnitOutputDiffers = true
          primaryIndexUnitOutputs.append(indexUnitOut)
        } else {
          primaryIndexUnitOutputs.append(output)
        }
      }
    }

    // When not using primary file inputs or multithreading, add a single output.
    if let outputType = outputType,
       !usesPrimaryFileInputs && !(isMultithreaded && outputType.isAfterLLVM) {
      let input = TypedVirtualPath(file: OutputFileMap.singleInputKey, type: inputs[firstSwiftInput].type)
      let output = computePrimaryOutput(for: input,
                                        outputType: outputType,
                                        isTopLevel: isTopLevel)
      primaryOutputs.append(output)
      inputOutputMap[input] = [output]

      if let indexUnitOut = computeIndexUnitOutput(for: input, outputType: outputType, topLevel: isTopLevel) {
        indexUnitOutputDiffers = true
        primaryIndexUnitOutputs.append(indexUnitOut)
      } else {
        primaryIndexUnitOutputs.append(output)
      }
    }

    if !indexUnitOutputDiffers {
      primaryIndexUnitOutputs.removeAll()
    } else {
      assert(primaryOutputs.count == primaryIndexUnitOutputs.count)
    }

    return (primaryOutputs, primaryIndexUnitOutputs)
  }