cb424d7448
verify-patch-sanity.py validates every active recipe .patch has internally- consistent hunk line counts — catching the 'malformed patch at line N' failure at commit/CI/preflight time instead of hours into a cook. This cycle hit that class three times (qtwaylandscanner, sddm, xwayland), each only discovered when cookbook tried to apply the patch. Running it across the repo found 29 latent malformed patches (validated against GNU patch: e.g. relibc/P3-sysv-ipc reproduces 'malformed patch at line 22'). They were harmless only because they sit in vendored recipes (baked, not re- applied) — but would fail on any version-bump re-derivation. --fix recounts the hunk headers (body untouched) and repaired all 29. Wired into build-preflight.sh (Phase 1.0D) and redbear-ci.yml, with a unit test (test-patch-sanity.sh). Skips archived/legacy trees and unvalidatable formats (empty placeholders, bare-@@ git hunks).
148 lines
5.5 KiB
C++
148 lines
5.5 KiB
C++
///===- DroppedVariableStats.cpp ----------------------------------------===//
|
|
///
|
|
/// 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
|
|
/// Dropped Variable Statistics for Debug Information. Reports any number
|
|
/// of #dbg_value that get dropped due to an optimization pass.
|
|
///
|
|
///===---------------------------------------------------------------------===//
|
|
|
|
#include "llvm/IR/DroppedVariableStats.h"
|
|
#include "llvm/IR/DebugInfoMetadata.h"
|
|
#include "llvm/IR/DiagnosticInfo.h"
|
|
#include "llvm/IR/Function.h"
|
|
|
|
using namespace llvm;
|
|
|
|
DroppedVariableStats::DroppedVariableStats(bool DroppedVarStatsEnabled)
|
|
: DroppedVariableStatsEnabled(DroppedVarStatsEnabled) {
|
|
if (DroppedVarStatsEnabled)
|
|
llvm::outs() << "Pass Level, Pass Name, Num of Dropped Variables, Func or "
|
|
"Module Name\n";
|
|
}
|
|
|
|
void DroppedVariableStats::setup() {
|
|
DebugVariablesStack.push_back({DenseMap<const Function *, DebugVariables>()});
|
|
InlinedAts.push_back({DenseMap<StringRef, DenseMap<VarID, DILocation *>>()});
|
|
}
|
|
|
|
void DroppedVariableStats::cleanup() {
|
|
assert(!DebugVariablesStack.empty() &&
|
|
"DebugVariablesStack shouldn't be empty!");
|
|
assert(!InlinedAts.empty() && "InlinedAts shouldn't be empty!");
|
|
DebugVariablesStack.pop_back();
|
|
InlinedAts.pop_back();
|
|
}
|
|
|
|
void DroppedVariableStats::calculateDroppedStatsAndPrint(
|
|
DebugVariables &DbgVariables, StringRef FuncName, StringRef PassID,
|
|
StringRef FuncOrModName, StringRef PassLevel, const Function *Func) {
|
|
unsigned DroppedCount = 0;
|
|
DenseSet<VarID> &DebugVariablesBeforeSet = DbgVariables.DebugVariablesBefore;
|
|
DenseSet<VarID> &DebugVariablesAfterSet = DbgVariables.DebugVariablesAfter;
|
|
auto It = InlinedAts.back().find(FuncName);
|
|
if (It == InlinedAts.back().end())
|
|
return;
|
|
DenseMap<VarID, DILocation *> &InlinedAtsMap = It->second;
|
|
// Find an Instruction that shares the same scope as the dropped #dbg_value
|
|
// or has a scope that is the child of the scope of the #dbg_value, and has
|
|
// an inlinedAt equal to the inlinedAt of the #dbg_value or it's inlinedAt
|
|
// chain contains the inlinedAt of the #dbg_value, if such an Instruction is
|
|
// found, debug information is dropped.
|
|
for (VarID Var : DebugVariablesBeforeSet) {
|
|
if (DebugVariablesAfterSet.contains(Var))
|
|
continue;
|
|
visitEveryInstruction(DroppedCount, InlinedAtsMap, Var);
|
|
removeVarFromAllSets(Var, Func);
|
|
}
|
|
if (DroppedCount > 0) {
|
|
llvm::outs() << PassLevel << ", " << PassID << ", " << DroppedCount << ", "
|
|
<< FuncOrModName << "\n";
|
|
PassDroppedVariables = true;
|
|
} else
|
|
PassDroppedVariables = false;
|
|
}
|
|
|
|
bool DroppedVariableStats::updateDroppedCount(
|
|
DILocation *DbgLoc, const DIScope *Scope, const DIScope *DbgValScope,
|
|
DenseMap<VarID, DILocation *> &InlinedAtsMap, VarID Var,
|
|
unsigned &DroppedCount) {
|
|
// If the Scope is a child of, or equal to the DbgValScope and is inlined at
|
|
// the Var's InlinedAt location, return true to signify that the Var has
|
|
// been dropped.
|
|
if (isScopeChildOfOrEqualTo(Scope, DbgValScope))
|
|
if (isInlinedAtChildOfOrEqualTo(DbgLoc->getInlinedAt(),
|
|
InlinedAtsMap[Var])) {
|
|
// Found another instruction in the variable's scope, so there exists a
|
|
// break point at which the variable could be observed. Count it as
|
|
// dropped.
|
|
DroppedCount++;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void DroppedVariableStats::run(DebugVariables &DbgVariables, StringRef FuncName,
|
|
bool Before) {
|
|
auto &VarIDSet = (Before ? DbgVariables.DebugVariablesBefore
|
|
: DbgVariables.DebugVariablesAfter);
|
|
auto &InlinedAtsMap = InlinedAts.back();
|
|
if (Before)
|
|
InlinedAtsMap.try_emplace(FuncName, DenseMap<VarID, DILocation *>());
|
|
VarIDSet = DenseSet<VarID>();
|
|
visitEveryDebugRecord(VarIDSet, InlinedAtsMap, FuncName, Before);
|
|
}
|
|
|
|
void DroppedVariableStats::populateVarIDSetAndInlinedMap(
|
|
const DILocalVariable *DbgVar, DebugLoc DbgLoc, DenseSet<VarID> &VarIDSet,
|
|
DenseMap<StringRef, DenseMap<VarID, DILocation *>> &InlinedAtsMap,
|
|
StringRef FuncName, bool Before) {
|
|
VarID Key{DbgVar->getScope(), DbgLoc->getInlinedAtScope(), DbgVar};
|
|
VarIDSet.insert(Key);
|
|
if (Before)
|
|
InlinedAtsMap[FuncName].try_emplace(Key, DbgLoc.getInlinedAt());
|
|
}
|
|
|
|
void DroppedVariableStats::removeVarFromAllSets(VarID Var, const Function *F) {
|
|
// Do not remove Var from the last element, it will be popped from the
|
|
// stack.
|
|
for (auto &DebugVariablesMap : llvm::drop_end(DebugVariablesStack))
|
|
DebugVariablesMap[F].DebugVariablesBefore.erase(Var);
|
|
}
|
|
|
|
bool DroppedVariableStats::isScopeChildOfOrEqualTo(const DIScope *Scope,
|
|
const DIScope *DbgValScope) {
|
|
while (Scope != nullptr) {
|
|
if (VisitedScope.insert(Scope).second) {
|
|
if (Scope == DbgValScope) {
|
|
VisitedScope.clear();
|
|
return true;
|
|
}
|
|
Scope = Scope->getScope();
|
|
} else {
|
|
VisitedScope.clear();
|
|
return false;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool DroppedVariableStats::isInlinedAtChildOfOrEqualTo(
|
|
const DILocation *InlinedAt, const DILocation *DbgValInlinedAt) {
|
|
if (DbgValInlinedAt == InlinedAt)
|
|
return true;
|
|
if (!DbgValInlinedAt)
|
|
return false;
|
|
auto *IA = InlinedAt;
|
|
while (IA) {
|
|
if (IA == DbgValInlinedAt)
|
|
return true;
|
|
IA = IA->getInlinedAt();
|
|
}
|
|
return false;
|
|
}
|