diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Transforms/Utils/Debugify.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/Transforms/Utils/Debugify.cpp | 540 | 
1 files changed, 494 insertions, 46 deletions
diff --git a/contrib/llvm-project/llvm/lib/Transforms/Utils/Debugify.cpp b/contrib/llvm-project/llvm/lib/Transforms/Utils/Debugify.cpp index 3e4d53c10dc9..30c3fa521d52 100644 --- a/contrib/llvm-project/llvm/lib/Transforms/Utils/Debugify.cpp +++ b/contrib/llvm-project/llvm/lib/Transforms/Utils/Debugify.cpp @@ -1,4 +1,4 @@ -//===- Debugify.cpp - Attach synthetic debug info to everything -----------===// +//===- Debugify.cpp - Check debug info preservation in optimizations ------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -6,8 +6,10 @@  //  //===----------------------------------------------------------------------===//  /// -/// \file This pass attaches synthetic debug info to everything. It can be used -/// to create targeted tests for debug info preservation. +/// \file In the `synthetic` mode, the `-debugify` attaches synthetic debug info +/// to everything. It can be used to create targeted tests for debug info +/// preservation. In addition, when using the `original` mode, it can check +/// original debug info preservation. The `synthetic` mode is default one.  ///  //===----------------------------------------------------------------------===// @@ -23,6 +25,10 @@  #include "llvm/IR/PassInstrumentation.h"  #include "llvm/Pass.h"  #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/JSON.h" + +#define DEBUG_TYPE "debugify"  using namespace llvm; @@ -35,6 +41,8 @@ enum class Level {    Locations,    LocationsAndVariables  }; + +// Used for the synthetic mode only.  cl::opt<Level> DebugifyLevel(      "debugify-level", cl::desc("Kind of debug info to add"),      cl::values(clEnumValN(Level::Locations, "locations", "Locations only"), @@ -199,16 +207,33 @@ bool llvm::applyDebugifyMetadata(    return true;  } -static bool applyDebugify(Function &F) { +static bool +applyDebugify(Function &F, +              enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo, +              DebugInfoPerPassMap *DIPreservationMap = nullptr, +              StringRef NameOfWrappedPass = "") {    Module &M = *F.getParent();    auto FuncIt = F.getIterator(); -  return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)), -                               "FunctionDebugify: ", /*ApplyToMF=*/nullptr); +  if (Mode == DebugifyMode::SyntheticDebugInfo) +    return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)), +                                 "FunctionDebugify: ", /*ApplyToMF*/ nullptr); +  assert(DIPreservationMap); +  return collectDebugInfoMetadata(M, M.functions(), *DIPreservationMap, +                                  "FunctionDebugify (original debuginfo)", +                                  NameOfWrappedPass);  } -static bool applyDebugify(Module &M) { -  return applyDebugifyMetadata(M, M.functions(), -                               "ModuleDebugify: ", /*ApplyToMF=*/nullptr); +static bool +applyDebugify(Module &M, +              enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo, +              DebugInfoPerPassMap *DIPreservationMap = nullptr, +              StringRef NameOfWrappedPass = "") { +  if (Mode == DebugifyMode::SyntheticDebugInfo) +    return applyDebugifyMetadata(M, M.functions(), +                                 "ModuleDebugify: ", /*ApplyToMF*/ nullptr); +  return collectDebugInfoMetadata(M, M.functions(), *DIPreservationMap, +                                  "ModuleDebugify (original debuginfo)", +                                  NameOfWrappedPass);  }  bool llvm::stripDebugifyMetadata(Module &M) { @@ -256,6 +281,355 @@ bool llvm::stripDebugifyMetadata(Module &M) {    return Changed;  } +bool llvm::collectDebugInfoMetadata(Module &M, +                                    iterator_range<Module::iterator> Functions, +                                    DebugInfoPerPassMap &DIPreservationMap, +                                    StringRef Banner, +                                    StringRef NameOfWrappedPass) { +  LLVM_DEBUG(dbgs() << Banner << ": (before) " << NameOfWrappedPass << '\n'); + +  // Clear the map with the debug info before every single pass. +  DIPreservationMap.clear(); + +  if (!M.getNamedMetadata("llvm.dbg.cu")) { +    dbg() << Banner << ": Skipping module without debug info\n"; +    return false; +  } + +  // Visit each instruction. +  for (Function &F : Functions) { +    if (isFunctionSkipped(F)) +      continue; + +    // Collect the DISubprogram. +    auto *SP = F.getSubprogram(); +    DIPreservationMap[NameOfWrappedPass].DIFunctions.insert({F.getName(), SP}); +    if (SP) { +      LLVM_DEBUG(dbgs() << "  Collecting subprogram: " << *SP << '\n'); +      for (const DINode *DN : SP->getRetainedNodes()) { +        if (const auto *DV = dyn_cast<DILocalVariable>(DN)) { +          DIPreservationMap[NameOfWrappedPass].DIVariables[DV] = 0; +        } +      } +    } + +    for (BasicBlock &BB : F) { +      // Collect debug locations (!dbg) and debug variable intrinsics. +      for (Instruction &I : BB) { +        // Skip PHIs. +        if (isa<PHINode>(I)) +          continue; + +        // Collect dbg.values and dbg.declares. +        if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I)) { +          if (!SP) +            continue; +          // Skip inlined variables. +          if (I.getDebugLoc().getInlinedAt()) +            continue; +          // Skip undef values. +          if (DVI->isUndef()) +            continue; + +          auto *Var = DVI->getVariable(); +          DIPreservationMap[NameOfWrappedPass].DIVariables[Var]++; +          continue; +        } + +        // Skip debug instructions other than dbg.value and dbg.declare. +        if (isa<DbgInfoIntrinsic>(&I)) +          continue; + +        LLVM_DEBUG(dbgs() << "  Collecting info for inst: " << I << '\n'); +        DIPreservationMap[NameOfWrappedPass].InstToDelete.insert({&I, &I}); + +        const DILocation *Loc = I.getDebugLoc().get(); +        bool HasLoc = Loc != nullptr; +        DIPreservationMap[NameOfWrappedPass].DILocations.insert({&I, HasLoc}); +      } +    } +  } + +  return true; +} + +// This checks the preservation of original debug info attached to functions. +static bool checkFunctions(const DebugFnMap &DIFunctionsBefore, +                           const DebugFnMap &DIFunctionsAfter, +                           StringRef NameOfWrappedPass, +                           StringRef FileNameFromCU, bool ShouldWriteIntoJSON, +                           llvm::json::Array &Bugs) { +  bool Preserved = true; +  for (const auto &F : DIFunctionsAfter) { +    if (F.second) +      continue; +    auto SPIt = DIFunctionsBefore.find(F.first); +    if (SPIt == DIFunctionsBefore.end()) { +      if (ShouldWriteIntoJSON) +        Bugs.push_back(llvm::json::Object({{"metadata", "DISubprogram"}, +                                           {"name", F.first}, +                                           {"action", "not-generate"}})); +      else +        dbg() << "ERROR: " << NameOfWrappedPass +              << " did not generate DISubprogram for " << F.first << " from " +              << FileNameFromCU << '\n'; +      Preserved = false; +    } else { +      auto SP = SPIt->second; +      if (!SP) +        continue; +      // If the function had the SP attached before the pass, consider it as +      // a debug info bug. +      if (ShouldWriteIntoJSON) +        Bugs.push_back(llvm::json::Object({{"metadata", "DISubprogram"}, +                                           {"name", F.first}, +                                           {"action", "drop"}})); +      else +        dbg() << "ERROR: " << NameOfWrappedPass << " dropped DISubprogram of " +              << F.first << " from " << FileNameFromCU << '\n'; +      Preserved = false; +    } +  } + +  return Preserved; +} + +// This checks the preservation of the original debug info attached to +// instructions. +static bool checkInstructions(const DebugInstMap &DILocsBefore, +                              const DebugInstMap &DILocsAfter, +                              const WeakInstValueMap &InstToDelete, +                              StringRef NameOfWrappedPass, +                              StringRef FileNameFromCU, +                              bool ShouldWriteIntoJSON, +                              llvm::json::Array &Bugs) { +  bool Preserved = true; +  for (const auto &L : DILocsAfter) { +    if (L.second) +      continue; +    auto Instr = L.first; + +    // In order to avoid pointer reuse/recycling, skip the values that might +    // have been deleted during a pass. +    auto WeakInstrPtr = InstToDelete.find(Instr); +    if (WeakInstrPtr != InstToDelete.end() && !WeakInstrPtr->second) +      continue; + +    auto FnName = Instr->getFunction()->getName(); +    auto BB = Instr->getParent(); +    auto BBName = BB->hasName() ? BB->getName() : "no-name"; +    auto InstName = Instruction::getOpcodeName(Instr->getOpcode()); + +    auto InstrIt = DILocsBefore.find(Instr); +    if (InstrIt == DILocsBefore.end()) { +      if (ShouldWriteIntoJSON) +        Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"}, +                                           {"fn-name", FnName.str()}, +                                           {"bb-name", BBName.str()}, +                                           {"instr", InstName}, +                                           {"action", "not-generate"}})); +      else +        dbg() << "WARNING: " << NameOfWrappedPass +              << " did not generate DILocation for " << *Instr +              << " (BB: " << BBName << ", Fn: " << FnName +              << ", File: " << FileNameFromCU << ")\n"; +      Preserved = false; +    } else { +      if (!InstrIt->second) +        continue; +      // If the instr had the !dbg attached before the pass, consider it as +      // a debug info issue. +      if (ShouldWriteIntoJSON) +        Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"}, +                                           {"fn-name", FnName.str()}, +                                           {"bb-name", BBName.str()}, +                                           {"instr", InstName}, +                                           {"action", "drop"}})); +      else +        dbg() << "WARNING: " << NameOfWrappedPass << " dropped DILocation of " +              << *Instr << " (BB: " << BBName << ", Fn: " << FnName +              << ", File: " << FileNameFromCU << ")\n"; +      Preserved = false; +    } +  } + +  return Preserved; +} + +// This checks the preservation of original debug variable intrinsics. +static bool checkVars(const DebugVarMap &DIFunctionsBefore, +                      const DebugVarMap &DIFunctionsAfter, +                      StringRef NameOfWrappedPass, StringRef FileNameFromCU, +                      bool ShouldWriteIntoJSON, llvm::json::Array &Bugs) { +  bool Preserved = true; +  for (const auto &V : DIFunctionsBefore) { +    auto VarIt = DIFunctionsAfter.find(V.first); +    if (VarIt == DIFunctionsAfter.end()) +      continue; + +    unsigned NumOfDbgValsAfter = VarIt->second; + +    if (V.second > NumOfDbgValsAfter) { +      if (ShouldWriteIntoJSON) +        Bugs.push_back(llvm::json::Object( +            {{"metadata", "dbg-var-intrinsic"}, +             {"name", V.first->getName()}, +             {"fn-name", V.first->getScope()->getSubprogram()->getName()}, +             {"action", "drop"}})); +      else +        dbg() << "WARNING: " << NameOfWrappedPass +              << " drops dbg.value()/dbg.declare() for " << V.first->getName() +              << " from " +              << "function " << V.first->getScope()->getSubprogram()->getName() +              << " (file " << FileNameFromCU << ")\n"; +      Preserved = false; +    } +  } + +  return Preserved; +} + +// Write the json data into the specifed file. +static void writeJSON(StringRef OrigDIVerifyBugsReportFilePath, +                      StringRef FileNameFromCU, StringRef NameOfWrappedPass, +                      llvm::json::Array &Bugs) { +  std::error_code EC; +  raw_fd_ostream OS_FILE{OrigDIVerifyBugsReportFilePath, EC, +                         sys::fs::OF_Append | sys::fs::OF_TextWithCRLF}; +  if (EC) { +    errs() << "Could not open file: " << EC.message() << ", " +           << OrigDIVerifyBugsReportFilePath << '\n'; +    return; +  } + +  OS_FILE << "{\"file\":\"" << FileNameFromCU << "\", "; + +  StringRef PassName = NameOfWrappedPass != "" ? NameOfWrappedPass : "no-name"; +  OS_FILE << "\"pass\":\"" << PassName << "\", "; + +  llvm::json::Value BugsToPrint{std::move(Bugs)}; +  OS_FILE << "\"bugs\": " << BugsToPrint; + +  OS_FILE << "}\n"; +} + +bool llvm::checkDebugInfoMetadata(Module &M, +                                  iterator_range<Module::iterator> Functions, +                                  DebugInfoPerPassMap &DIPreservationMap, +                                  StringRef Banner, StringRef NameOfWrappedPass, +                                  StringRef OrigDIVerifyBugsReportFilePath) { +  LLVM_DEBUG(dbgs() << Banner << ": (after) " << NameOfWrappedPass << '\n'); + +  if (!M.getNamedMetadata("llvm.dbg.cu")) { +    dbg() << Banner << ": Skipping module without debug info\n"; +    return false; +  } + +  // Map the debug info holding DIs after a pass. +  DebugInfoPerPassMap DIPreservationAfter; + +  // Visit each instruction. +  for (Function &F : Functions) { +    if (isFunctionSkipped(F)) +      continue; + +    // TODO: Collect metadata other than DISubprograms. +    // Collect the DISubprogram. +    auto *SP = F.getSubprogram(); +    DIPreservationAfter[NameOfWrappedPass].DIFunctions.insert( +        {F.getName(), SP}); + +    if (SP) { +      LLVM_DEBUG(dbgs() << "  Collecting subprogram: " << *SP << '\n'); +      for (const DINode *DN : SP->getRetainedNodes()) { +        if (const auto *DV = dyn_cast<DILocalVariable>(DN)) { +          DIPreservationAfter[NameOfWrappedPass].DIVariables[DV] = 0; +        } +      } +    } + +    for (BasicBlock &BB : F) { +      // Collect debug locations (!dbg) and debug variable intrinsics. +      for (Instruction &I : BB) { +        // Skip PHIs. +        if (isa<PHINode>(I)) +          continue; + +        // Collect dbg.values and dbg.declares. +        if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I)) { +          if (!SP) +            continue; +          // Skip inlined variables. +          if (I.getDebugLoc().getInlinedAt()) +            continue; +          // Skip undef values. +          if (DVI->isUndef()) +            continue; + +          auto *Var = DVI->getVariable(); +          DIPreservationAfter[NameOfWrappedPass].DIVariables[Var]++; +          continue; +        } + +        // Skip debug instructions other than dbg.value and dbg.declare. +        if (isa<DbgInfoIntrinsic>(&I)) +          continue; + +        LLVM_DEBUG(dbgs() << "  Collecting info for inst: " << I << '\n'); + +        const DILocation *Loc = I.getDebugLoc().get(); +        bool HasLoc = Loc != nullptr; + +        DIPreservationAfter[NameOfWrappedPass].DILocations.insert({&I, HasLoc}); +      } +    } +  } + +  // TODO: The name of the module could be read better? +  StringRef FileNameFromCU = +      (cast<DICompileUnit>(M.getNamedMetadata("llvm.dbg.cu")->getOperand(0))) +          ->getFilename(); + +  auto DIFunctionsBefore = DIPreservationMap[NameOfWrappedPass].DIFunctions; +  auto DIFunctionsAfter = DIPreservationAfter[NameOfWrappedPass].DIFunctions; + +  auto DILocsBefore = DIPreservationMap[NameOfWrappedPass].DILocations; +  auto DILocsAfter = DIPreservationAfter[NameOfWrappedPass].DILocations; + +  auto InstToDelete = DIPreservationAfter[NameOfWrappedPass].InstToDelete; + +  auto DIVarsBefore = DIPreservationMap[NameOfWrappedPass].DIVariables; +  auto DIVarsAfter = DIPreservationAfter[NameOfWrappedPass].DIVariables; + +  bool ShouldWriteIntoJSON = !OrigDIVerifyBugsReportFilePath.empty(); +  llvm::json::Array Bugs; + +  bool ResultForFunc = +      checkFunctions(DIFunctionsBefore, DIFunctionsAfter, NameOfWrappedPass, +                     FileNameFromCU, ShouldWriteIntoJSON, Bugs); +  bool ResultForInsts = checkInstructions( +      DILocsBefore, DILocsAfter, InstToDelete, NameOfWrappedPass, +      FileNameFromCU, ShouldWriteIntoJSON, Bugs); + +  bool ResultForVars = checkVars(DIVarsBefore, DIVarsAfter, NameOfWrappedPass, +                                 FileNameFromCU, ShouldWriteIntoJSON, Bugs); + +  bool Result = ResultForFunc && ResultForInsts && ResultForVars; + +  StringRef ResultBanner = NameOfWrappedPass != "" ? NameOfWrappedPass : Banner; +  if (ShouldWriteIntoJSON && !Bugs.empty()) +    writeJSON(OrigDIVerifyBugsReportFilePath, FileNameFromCU, NameOfWrappedPass, +              Bugs); + +  if (Result) +    dbg() << ResultBanner << ": PASS\n"; +  else +    dbg() << ResultBanner << ": FAIL\n"; + +  LLVM_DEBUG(dbgs() << "\n\n"); +  return Result; +} +  namespace {  /// Return true if a mis-sized diagnostic is issued for \p DVI.  bool diagnoseMisSizedDbgValue(Module &M, DbgValueInst *DVI) { @@ -264,15 +638,16 @@ bool diagnoseMisSizedDbgValue(Module &M, DbgValueInst *DVI) {    //    // TODO: This, along with a check for non-null value operands, should be    // promoted to verifier failures. -  Value *V = DVI->getValue(); -  if (!V) -    return false;    // For now, don't try to interpret anything more complicated than an empty    // DIExpression. Eventually we should try to handle OP_deref and fragments.    if (DVI->getExpression()->getNumElements())      return false; +  Value *V = DVI->getVariableLocationOp(0); +  if (!V) +    return false; +    Type *Ty = V->getType();    uint64_t ValueOperandSize = getAllocSizeInBits(M, Ty);    Optional<uint64_t> DbgVarSize = DVI->getFragmentSizeInBits(); @@ -331,7 +706,7 @@ bool checkDebugifyMetadata(Module &M,      // Find missing lines.      for (Instruction &I : instructions(F)) { -      if (isa<DbgValueInst>(&I) || isa<PHINode>(&I)) +      if (isa<DbgValueInst>(&I))          continue;        auto DL = I.getDebugLoc(); @@ -340,7 +715,7 @@ bool checkDebugifyMetadata(Module &M,          continue;        } -      if (!DL) { +      if (!isa<PHINode>(&I) && !DL) {          dbg() << "WARNING: Instruction with empty DebugLoc in function ";          dbg() << F.getName() << " --";          I.print(dbg()); @@ -394,43 +769,77 @@ bool checkDebugifyMetadata(Module &M,  /// ModulePass for attaching synthetic debug info to everything, used with the  /// legacy module pass manager.  struct DebugifyModulePass : public ModulePass { -  bool runOnModule(Module &M) override { return applyDebugify(M); } +  bool runOnModule(Module &M) override { +    return applyDebugify(M, Mode, DIPreservationMap, NameOfWrappedPass); +  } -  DebugifyModulePass() : ModulePass(ID) {} +  DebugifyModulePass(enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo, +                     StringRef NameOfWrappedPass = "", +                     DebugInfoPerPassMap *DIPreservationMap = nullptr) +      : ModulePass(ID), NameOfWrappedPass(NameOfWrappedPass), +        DIPreservationMap(DIPreservationMap), Mode(Mode) {}    void getAnalysisUsage(AnalysisUsage &AU) const override {      AU.setPreservesAll();    }    static char ID; // Pass identification. + +private: +  StringRef NameOfWrappedPass; +  DebugInfoPerPassMap *DIPreservationMap; +  enum DebugifyMode Mode;  };  /// FunctionPass for attaching synthetic debug info to instructions within a  /// single function, used with the legacy module pass manager.  struct DebugifyFunctionPass : public FunctionPass { -  bool runOnFunction(Function &F) override { return applyDebugify(F); } +  bool runOnFunction(Function &F) override { +    return applyDebugify(F, Mode, DIPreservationMap, NameOfWrappedPass); +  } -  DebugifyFunctionPass() : FunctionPass(ID) {} +  DebugifyFunctionPass( +      enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo, +      StringRef NameOfWrappedPass = "", +      DebugInfoPerPassMap *DIPreservationMap = nullptr) +      : FunctionPass(ID), NameOfWrappedPass(NameOfWrappedPass), +        DIPreservationMap(DIPreservationMap), Mode(Mode) {}    void getAnalysisUsage(AnalysisUsage &AU) const override {      AU.setPreservesAll();    }    static char ID; // Pass identification. + +private: +  StringRef NameOfWrappedPass; +  DebugInfoPerPassMap *DIPreservationMap; +  enum DebugifyMode Mode;  };  /// ModulePass for checking debug info inserted by -debugify, used with the  /// legacy module pass manager.  struct CheckDebugifyModulePass : public ModulePass {    bool runOnModule(Module &M) override { -    return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass, -                                 "CheckModuleDebugify", Strip, StatsMap); +    if (Mode == DebugifyMode::SyntheticDebugInfo) +      return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass, +                                   "CheckModuleDebugify", Strip, StatsMap); +    return checkDebugInfoMetadata( +        M, M.functions(), *DIPreservationMap, +        "CheckModuleDebugify (original debuginfo)", NameOfWrappedPass, +        OrigDIVerifyBugsReportFilePath);    } -  CheckDebugifyModulePass(bool Strip = false, StringRef NameOfWrappedPass = "", -                          DebugifyStatsMap *StatsMap = nullptr) -      : ModulePass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass), -        StatsMap(StatsMap) {} +  CheckDebugifyModulePass( +      bool Strip = false, StringRef NameOfWrappedPass = "", +      DebugifyStatsMap *StatsMap = nullptr, +      enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo, +      DebugInfoPerPassMap *DIPreservationMap = nullptr, +      StringRef OrigDIVerifyBugsReportFilePath = "") +      : ModulePass(ID), NameOfWrappedPass(NameOfWrappedPass), +        OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath), +        StatsMap(StatsMap), DIPreservationMap(DIPreservationMap), Mode(Mode), +        Strip(Strip) {}    void getAnalysisUsage(AnalysisUsage &AU) const override {      AU.setPreservesAll(); @@ -439,9 +848,12 @@ struct CheckDebugifyModulePass : public ModulePass {    static char ID; // Pass identification.  private: -  bool Strip;    StringRef NameOfWrappedPass; +  StringRef OrigDIVerifyBugsReportFilePath;    DebugifyStatsMap *StatsMap; +  DebugInfoPerPassMap *DIPreservationMap; +  enum DebugifyMode Mode; +  bool Strip;  };  /// FunctionPass for checking debug info inserted by -debugify-function, used @@ -450,16 +862,26 @@ struct CheckDebugifyFunctionPass : public FunctionPass {    bool runOnFunction(Function &F) override {      Module &M = *F.getParent();      auto FuncIt = F.getIterator(); -    return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)), -                                 NameOfWrappedPass, "CheckFunctionDebugify", -                                 Strip, StatsMap); +    if (Mode == DebugifyMode::SyntheticDebugInfo) +      return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)), +                                   NameOfWrappedPass, "CheckFunctionDebugify", +                                   Strip, StatsMap); +    return checkDebugInfoMetadata( +        M, make_range(FuncIt, std::next(FuncIt)), *DIPreservationMap, +        "CheckFunctionDebugify (original debuginfo)", NameOfWrappedPass, +        OrigDIVerifyBugsReportFilePath);    } -  CheckDebugifyFunctionPass(bool Strip = false, -                            StringRef NameOfWrappedPass = "", -                            DebugifyStatsMap *StatsMap = nullptr) -      : FunctionPass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass), -        StatsMap(StatsMap) {} +  CheckDebugifyFunctionPass( +      bool Strip = false, StringRef NameOfWrappedPass = "", +      DebugifyStatsMap *StatsMap = nullptr, +      enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo, +      DebugInfoPerPassMap *DIPreservationMap = nullptr, +      StringRef OrigDIVerifyBugsReportFilePath = "") +      : FunctionPass(ID), NameOfWrappedPass(NameOfWrappedPass), +        OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath), +        StatsMap(StatsMap), DIPreservationMap(DIPreservationMap), Mode(Mode), +        Strip(Strip) {}    void getAnalysisUsage(AnalysisUsage &AU) const override {      AU.setPreservesAll(); @@ -468,9 +890,12 @@ struct CheckDebugifyFunctionPass : public FunctionPass {    static char ID; // Pass identification.  private: -  bool Strip;    StringRef NameOfWrappedPass; +  StringRef OrigDIVerifyBugsReportFilePath;    DebugifyStatsMap *StatsMap; +  DebugInfoPerPassMap *DIPreservationMap; +  enum DebugifyMode Mode; +  bool Strip;  };  } // end anonymous namespace @@ -496,12 +921,23 @@ void llvm::exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map) {    }  } -ModulePass *llvm::createDebugifyModulePass() { -  return new DebugifyModulePass(); +ModulePass *createDebugifyModulePass(enum DebugifyMode Mode, +                                     llvm::StringRef NameOfWrappedPass, +                                     DebugInfoPerPassMap *DIPreservationMap) { +  if (Mode == DebugifyMode::SyntheticDebugInfo) +    return new DebugifyModulePass(); +  assert(Mode == DebugifyMode::OriginalDebugInfo && "Must be original mode"); +  return new DebugifyModulePass(Mode, NameOfWrappedPass, DIPreservationMap);  } -FunctionPass *llvm::createDebugifyFunctionPass() { -  return new DebugifyFunctionPass(); +FunctionPass * +createDebugifyFunctionPass(enum DebugifyMode Mode, +                           llvm::StringRef NameOfWrappedPass, +                           DebugInfoPerPassMap *DIPreservationMap) { +  if (Mode == DebugifyMode::SyntheticDebugInfo) +    return new DebugifyFunctionPass(); +  assert(Mode == DebugifyMode::OriginalDebugInfo && "Must be original mode"); +  return new DebugifyFunctionPass(Mode, NameOfWrappedPass, DIPreservationMap);  }  PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) { @@ -510,16 +946,28 @@ PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) {    return PreservedAnalyses::all();  } -ModulePass *llvm::createCheckDebugifyModulePass(bool Strip, -                                                StringRef NameOfWrappedPass, -                                                DebugifyStatsMap *StatsMap) { -  return new CheckDebugifyModulePass(Strip, NameOfWrappedPass, StatsMap); +ModulePass *createCheckDebugifyModulePass( +    bool Strip, StringRef NameOfWrappedPass, DebugifyStatsMap *StatsMap, +    enum DebugifyMode Mode, DebugInfoPerPassMap *DIPreservationMap, +    StringRef OrigDIVerifyBugsReportFilePath) { +  if (Mode == DebugifyMode::SyntheticDebugInfo) +    return new CheckDebugifyModulePass(Strip, NameOfWrappedPass, StatsMap); +  assert(Mode == DebugifyMode::OriginalDebugInfo && "Must be original mode"); +  return new CheckDebugifyModulePass(false, NameOfWrappedPass, nullptr, Mode, +                                     DIPreservationMap, +                                     OrigDIVerifyBugsReportFilePath);  } -FunctionPass * -llvm::createCheckDebugifyFunctionPass(bool Strip, StringRef NameOfWrappedPass, -                                      DebugifyStatsMap *StatsMap) { -  return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass, StatsMap); +FunctionPass *createCheckDebugifyFunctionPass( +    bool Strip, StringRef NameOfWrappedPass, DebugifyStatsMap *StatsMap, +    enum DebugifyMode Mode, DebugInfoPerPassMap *DIPreservationMap, +    StringRef OrigDIVerifyBugsReportFilePath) { +  if (Mode == DebugifyMode::SyntheticDebugInfo) +    return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass, StatsMap); +  assert(Mode == DebugifyMode::OriginalDebugInfo && "Must be original mode"); +  return new CheckDebugifyFunctionPass(false, NameOfWrappedPass, nullptr, Mode, +                                       DIPreservationMap, +                                       OrigDIVerifyBugsReportFilePath);  }  PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M,  | 
