Repository: rust-lang/rust
File: compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp (C++)

Code before:
      LLVMRustSetLastError(ErrMsg.c_str());
      return LLVMRustResult::Failure;
    }
  }

  if (NeedThinLTOBufferPasses) {
    MPM.addPass(CanonicalizeAliasesPass());
    MPM.addPass(NameAnonGlobalPass());
  }
  // For `-Copt-level=0`, ThinLTO, or LTO.
  if (ThinLTOBufferRef && *ThinLTOBufferRef == nullptr) {
    if (EmitThinLTO) {
      MPM.addPass(ThinLTOBitcodeWriterPass(
          ThinLTODataOS, EmitThinLTOSummary ? &ThinLinkDataOS : nullptr));
    } else {
      MPM.addPass(BitcodeWriterPass(ThinLTODataOS));
    }
    *ThinLTOBufferRef = ThinLTOBuffer.release();
  }

  // now load "-enzyme" pass:
  // With dlopen, ENZYME macro may not be defined, so check EnzymePtr directly
  if (EnzymePtr) {

    if (PrintBeforeEnzyme) {
      // Handle the Rust flag `-Zautodiff=PrintModBefore`.
      std::string Banner = "Module before EnzymeNewPM";
      MPM.addPass(PrintModulePass(outs(), Banner, true, false));
    }

    EnzymePtr(PB, false);
    if (auto Err = PB.parsePassPipeline(MPM, "enzyme")) {
      std::string ErrMsg = toString(std::move(Err));
      LLVMRustSetLastError(ErrMsg.c_str());
      return LLVMRustResult::Failure;
    }

    if (PrintAfterEnzyme) {
      // Handle the Rust flag `-Zautodiff=PrintModAfter`.
      std::string Banner = "Module after EnzymeNewPM";
      MPM.addPass(PrintModulePass(outs(), Banner, true, false));
    }
  }
  if (PrintPasses) {
    // Print all passes from the PM:
    std::string Pipeline;
    raw_string_ostream SOS(Pipeline);
    MPM.printPipeline(SOS, [&PIC](StringRef ClassName) {
      auto PassName = PIC.getPassNameForClassName(ClassName);
      return PassName.empty() ? ClassName : PassName;
    });

Review comment (suggestion):
I could have checked for fat-lto only, since that's what we require atm. But it seems to work atm. and every once in a while I experiment with lowering our requirements from fat to thin lto, so I think it's fine.

Code after:
      LLVMRustSetLastError(ErrMsg.c_str());
      return LLVMRustResult::Failure;
    }
  }

  if (NeedThinLTOBufferPasses) {
    MPM.addPass(CanonicalizeAliasesPass());
    MPM.addPass(NameAnonGlobalPass());
  }
  // For `-Copt-level=0`, ThinLTO, or LTO.
  if (ThinLTOBufferRef && *ThinLTOBufferRef == nullptr) {
    if (EmitThinLTO) {
      MPM.addPass(ThinLTOBitcodeWriterPass(
          ThinLTODataOS, EmitThinLTOSummary ? &ThinLinkDataOS : nullptr));
    } else {
      MPM.addPass(BitcodeWriterPass(ThinLTODataOS));
    }
    *ThinLTOBufferRef = ThinLTOBuffer.release();
  }

  // now load "-enzyme" pass:
  // With dlopen, ENZYME macro may not be defined, so check EnzymePtr directly
  // In the case of debug builds with multiple codegen units, we might not
  // have all function definitions available during the early compiler
  // invocations. We therefore wait for the final lto step to run Enzyme.
  if (EnzymePtr && IsLTO) {

    if (PrintBeforeEnzyme) {
      // Handle the Rust flag `-Zautodiff=PrintModBefore`.
      std::string Banner = "Module before EnzymeNewPM";
      MPM.addPass(PrintModulePass(outs(), Banner, true, false));
    }

    EnzymePtr(PB, false);
    if (auto Err = PB.parsePassPipeline(MPM, "enzyme")) {
      std::string ErrMsg = toString(std::move(Err));
      LLVMRustSetLastError(ErrMsg.c_str());
      return LLVMRustResult::Failure;
    }

    if (PrintAfterEnzyme) {
      // Handle the Rust flag `-Zautodiff=PrintModAfter`.
      std::string Banner = "Module after EnzymeNewPM";
      MPM.addPass(PrintModulePass(outs(), Banner, true, false));
    }
  }

  if (PrintPasses) {
    // Print all passes from the PM:
    std::string Pipeline;
    raw_string_ostream SOS(Pipeline);