[opt-remark] Teach opt-remark how to emit notes that point to the value being retained/released.

This is just an initial implementation and doesn't handle all cases. This works
by grabbing the rc-identity root of a retain/release operation and then seeing:

1. If it is an argument, we use the ValueDecl of the argument.
2. If it is an instruction result, we try to infer the ValueDecl by looking for debug_value uses.
3. In the future, we should add support for globals and looking at addresses.

I may do 3 since it is important to have support for that due to inout objects.
This commit is contained in:
Michael Gottesman
2020-07-20 19:35:48 -07:00
parent aea6d7df80
commit 2c9a34fa01
5 changed files with 173 additions and 45 deletions

View File

@@ -20,6 +20,9 @@
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsSIL.h"
#include "swift/Demangling/Demangler.h"
#include "swift/SIL/DebugUtils.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILRemarkStreamer.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
@@ -72,6 +75,28 @@ Argument::Argument(StringRef key, CanType ty)
ty.print(stream);
}
bool Argument::inferArgumentsForValue(
ArgumentKeyKind keyKind, StringRef msg, SILValue value,
function_ref<bool(Argument)> funcPassedInferedArgs) {
// If we have an argument, just use that.
if (auto *arg = dyn_cast<SILArgument>(value))
if (auto *decl = arg->getDecl())
return funcPassedInferedArgs(
Argument({keyKind, "InferredValue"}, msg, decl));
// TODO: Look for loads from globals and addresses.
// Otherwise, look for debug_values.
for (auto *use : getDebugUses(value))
if (auto *dvi = dyn_cast<DebugValueInst>(use->getUser()))
if (auto *decl = dvi->getDecl())
if (!funcPassedInferedArgs(
Argument({keyKind, "InferredValue"}, msg, decl)))
return false;
return true;
}
template <typename DerivedT>
std::string Remark<DerivedT>::getMsg() const {
std::string str;