152 lines
5.2 KiB
C
152 lines
5.2 KiB
C
|
//===- Debugify.h - Attach synthetic debug info to everything -------------===//
|
||
|
//
|
||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
///
|
||
|
/// \file Interface to the `debugify` synthetic debug info testing utility.
|
||
|
///
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#ifndef LLVM_TRANSFORM_UTILS_DEBUGIFY_H
|
||
|
#define LLVM_TRANSFORM_UTILS_DEBUGIFY_H
|
||
|
|
||
|
#include "llvm/ADT/MapVector.h"
|
||
|
#include "llvm/ADT/StringRef.h"
|
||
|
#include "llvm/Bitcode/BitcodeWriterPass.h"
|
||
|
#include "llvm/IR/IRPrintingPasses.h"
|
||
|
#include "llvm/IR/LegacyPassManager.h"
|
||
|
#include "llvm/IR/PassManager.h"
|
||
|
|
||
|
namespace llvm {
|
||
|
class DIBuilder;
|
||
|
|
||
|
/// Add synthesized debug information to a module.
|
||
|
///
|
||
|
/// \param M The module to add debug information to.
|
||
|
/// \param Functions A range of functions to add debug information to.
|
||
|
/// \param Banner A prefix string to add to debug/error messages.
|
||
|
/// \param ApplyToMF A call back that will add debug information to the
|
||
|
/// MachineFunction for a Function. If nullptr, then the
|
||
|
/// MachineFunction (if any) will not be modified.
|
||
|
bool applyDebugifyMetadata(
|
||
|
Module &M, iterator_range<Module::iterator> Functions, StringRef Banner,
|
||
|
std::function<bool(DIBuilder &, Function &)> ApplyToMF);
|
||
|
|
||
|
/// Strip out all of the metadata and debug info inserted by debugify. If no
|
||
|
/// llvm.debugify module-level named metadata is present, this is a no-op.
|
||
|
/// Returns true if any change was made.
|
||
|
bool stripDebugifyMetadata(Module &M);
|
||
|
|
||
|
llvm::ModulePass *createDebugifyModulePass();
|
||
|
llvm::FunctionPass *createDebugifyFunctionPass();
|
||
|
|
||
|
struct NewPMDebugifyPass : public llvm::PassInfoMixin<NewPMDebugifyPass> {
|
||
|
llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
|
||
|
};
|
||
|
|
||
|
/// Track how much `debugify` information has been lost.
|
||
|
struct DebugifyStatistics {
|
||
|
/// Number of missing dbg.values.
|
||
|
unsigned NumDbgValuesMissing = 0;
|
||
|
|
||
|
/// Number of dbg.values expected.
|
||
|
unsigned NumDbgValuesExpected = 0;
|
||
|
|
||
|
/// Number of instructions with empty debug locations.
|
||
|
unsigned NumDbgLocsMissing = 0;
|
||
|
|
||
|
/// Number of instructions expected to have debug locations.
|
||
|
unsigned NumDbgLocsExpected = 0;
|
||
|
|
||
|
/// Get the ratio of missing/expected dbg.values.
|
||
|
float getMissingValueRatio() const {
|
||
|
return float(NumDbgValuesMissing) / float(NumDbgLocsExpected);
|
||
|
}
|
||
|
|
||
|
/// Get the ratio of missing/expected instructions with locations.
|
||
|
float getEmptyLocationRatio() const {
|
||
|
return float(NumDbgLocsMissing) / float(NumDbgLocsExpected);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/// Map pass names to a per-pass DebugifyStatistics instance.
|
||
|
using DebugifyStatsMap = llvm::MapVector<llvm::StringRef, DebugifyStatistics>;
|
||
|
|
||
|
void exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map);
|
||
|
|
||
|
llvm::ModulePass *
|
||
|
createCheckDebugifyModulePass(bool Strip = false,
|
||
|
llvm::StringRef NameOfWrappedPass = "",
|
||
|
DebugifyStatsMap *StatsMap = nullptr);
|
||
|
|
||
|
llvm::FunctionPass *
|
||
|
createCheckDebugifyFunctionPass(bool Strip = false,
|
||
|
llvm::StringRef NameOfWrappedPass = "",
|
||
|
DebugifyStatsMap *StatsMap = nullptr);
|
||
|
|
||
|
struct NewPMCheckDebugifyPass
|
||
|
: public llvm::PassInfoMixin<NewPMCheckDebugifyPass> {
|
||
|
llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
|
||
|
};
|
||
|
|
||
|
struct DebugifyEachInstrumentation {
|
||
|
DebugifyStatsMap StatsMap;
|
||
|
|
||
|
void registerCallbacks(PassInstrumentationCallbacks &PIC);
|
||
|
};
|
||
|
|
||
|
/// DebugifyCustomPassManager wraps each pass with the debugify passes if
|
||
|
/// needed.
|
||
|
/// NOTE: We support legacy custom pass manager only.
|
||
|
/// TODO: Add New PM support for custom pass manager.
|
||
|
class DebugifyCustomPassManager : public legacy::PassManager {
|
||
|
DebugifyStatsMap DIStatsMap;
|
||
|
bool EnableDebugifyEach = false;
|
||
|
|
||
|
public:
|
||
|
using super = legacy::PassManager;
|
||
|
|
||
|
void add(Pass *P) override {
|
||
|
// Wrap each pass with (-check)-debugify passes if requested, making
|
||
|
// exceptions for passes which shouldn't see -debugify instrumentation.
|
||
|
bool WrapWithDebugify = EnableDebugifyEach && !P->getAsImmutablePass() &&
|
||
|
!isIRPrintingPass(P) && !isBitcodeWriterPass(P);
|
||
|
if (!WrapWithDebugify) {
|
||
|
super::add(P);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Apply -debugify/-check-debugify before/after each pass and collect
|
||
|
// debug info loss statistics.
|
||
|
PassKind Kind = P->getPassKind();
|
||
|
StringRef Name = P->getPassName();
|
||
|
|
||
|
// TODO: Implement Debugify for LoopPass.
|
||
|
switch (Kind) {
|
||
|
case PT_Function:
|
||
|
super::add(createDebugifyFunctionPass());
|
||
|
super::add(P);
|
||
|
super::add(createCheckDebugifyFunctionPass(true, Name, &DIStatsMap));
|
||
|
break;
|
||
|
case PT_Module:
|
||
|
super::add(createDebugifyModulePass());
|
||
|
super::add(P);
|
||
|
super::add(createCheckDebugifyModulePass(true, Name, &DIStatsMap));
|
||
|
break;
|
||
|
default:
|
||
|
super::add(P);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void enableDebugifyEach() { EnableDebugifyEach = true; }
|
||
|
|
||
|
const DebugifyStatsMap &getDebugifyStatsMap() const { return DIStatsMap; }
|
||
|
};
|
||
|
} // namespace llvm
|
||
|
|
||
|
#endif // LLVM_TRANSFORM_UTILS_DEBUGIFY_H
|