20
20
#include " swift/AST/DiagnosticEngine.h"
21
21
#include " swift/AST/DiagnosticsSIL.h"
22
22
#include " swift/Demangling/Demangler.h"
23
+ #include " swift/SIL/DebugUtils.h"
24
+ #include " swift/SIL/SILArgument.h"
25
+ #include " swift/SIL/SILInstruction.h"
23
26
#include " swift/SIL/SILRemarkStreamer.h"
24
27
#include " llvm/ADT/StringExtras.h"
25
28
#include " llvm/Support/CommandLine.h"
28
31
using namespace swift ;
29
32
using namespace OptRemark ;
30
33
31
- Argument::Argument (StringRef key, int n) : key(key), val(llvm::itostr(n)) {}
34
+ Argument::Argument (StringRef key, int n)
35
+ : key(ArgumentKeyKind::Default, key), val(llvm::itostr(n)) {}
32
36
33
- Argument::Argument (StringRef key, long n) : key(key), val(llvm::itostr(n)) {}
37
+ Argument::Argument (StringRef key, long n)
38
+ : key(ArgumentKeyKind::Default, key), val(llvm::itostr(n)) {}
34
39
35
40
Argument::Argument (StringRef key, long long n)
36
- : key(key), val(llvm::itostr(n)) {}
41
+ : key(ArgumentKeyKind::Default, key), val(llvm::itostr(n)) {}
37
42
38
43
Argument::Argument (StringRef key, unsigned n)
39
- : key(key), val(llvm::utostr(n)) {}
44
+ : key(ArgumentKeyKind::Default, key), val(llvm::utostr(n)) {}
40
45
41
46
Argument::Argument (StringRef key, unsigned long n)
42
- : key(key), val(llvm::utostr(n)) {}
47
+ : key(ArgumentKeyKind::Default, key), val(llvm::utostr(n)) {}
43
48
44
49
Argument::Argument (StringRef key, unsigned long long n)
45
- : key(key), val(llvm::utostr(n)) {}
50
+ : key(ArgumentKeyKind::Default, key), val(llvm::utostr(n)) {}
46
51
47
- Argument::Argument (StringRef key, SILFunction *f) : key(key) {
52
+ Argument::Argument (ArgumentKey key, SILFunction *f) : key(key) {
48
53
auto options = Demangle::DemangleOptions::SimplifiedUIDemangleOptions ();
49
54
// Enable module names so that we have a way of filtering out
50
55
// stdlib-related remarks.
@@ -58,22 +63,53 @@ Argument::Argument(StringRef key, SILFunction *f) : key(key) {
58
63
loc = f->getLocation ().getSourceLoc ();
59
64
}
60
65
61
- Argument::Argument (StringRef key, SILType ty) : key(key) {
66
+ Argument::Argument (StringRef key, SILType ty)
67
+ : key(ArgumentKeyKind::Default, key) {
62
68
llvm::raw_string_ostream stream (val);
63
69
ty.print (stream);
64
70
}
65
71
66
- Argument::Argument (StringRef key, CanType ty) : key(key) {
72
+ Argument::Argument (StringRef key, CanType ty)
73
+ : key(ArgumentKeyKind::Default, key) {
67
74
llvm::raw_string_ostream stream (val);
68
75
ty.print (stream);
69
76
}
70
77
78
+ bool Argument::inferArgumentsForValue (
79
+ ArgumentKeyKind keyKind, StringRef msg, SILValue value,
80
+ function_ref<bool (Argument)> funcPassedInferedArgs) {
81
+ // If we have an argument, just use that.
82
+ if (auto *arg = dyn_cast<SILArgument>(value))
83
+ if (auto *decl = arg->getDecl ())
84
+ return funcPassedInferedArgs (
85
+ Argument ({keyKind, " InferredValue" }, msg, decl));
86
+
87
+ // TODO: Look for loads from globals and addresses.
88
+
89
+ // Otherwise, look for debug_values.
90
+ for (auto *use : getDebugUses (value))
91
+ if (auto *dvi = dyn_cast<DebugValueInst>(use->getUser ()))
92
+ if (auto *decl = dvi->getDecl ())
93
+ if (!funcPassedInferedArgs (
94
+ Argument ({keyKind, " InferredValue" }, msg, decl)))
95
+ return false ;
96
+
97
+ return true ;
98
+ }
99
+
71
100
template <typename DerivedT>
72
101
std::string Remark<DerivedT>::getMsg() const {
73
102
std::string str;
74
103
llvm::raw_string_ostream stream (str);
75
- for (const Argument &arg : args)
104
+ // Go through our args and if we are not emitting for diagnostics *OR* we are
105
+ // emitting for diagnostics and this argument is not intended to be emitted as
106
+ // a diagnostic separate from our main remark, emit the arg value here.
107
+ for (const Argument &arg : args) {
108
+ if (arg.key .kind .isSeparateDiagnostic ())
109
+ continue ;
76
110
stream << arg.val ;
111
+ }
112
+
77
113
return stream.str ();
78
114
}
79
115
@@ -194,9 +230,30 @@ static void emitRemark(SILModule &module, const Remark<RemarkT> &remark,
194
230
return ;
195
231
if (auto *remarkStreamer = module .getSILRemarkStreamer ())
196
232
remarkStreamer->emit (remark);
197
- if (diagEnabled)
198
- module .getASTContext ().Diags .diagnose (remark.getLocation (), id,
199
- remark.getMsg ());
233
+
234
+ // If diagnostics are enabled, first emit the main diagnostic and then loop
235
+ // through our arguments and allow the arguments to add additional diagnostics
236
+ // if they want.
237
+ if (!diagEnabled)
238
+ return ;
239
+
240
+ auto &de = module .getASTContext ().Diags ;
241
+ de.diagnoseWithNotes (
242
+ de.diagnose (remark.getLocation (), id, remark.getMsg ()), [&]() {
243
+ for (auto &arg : remark.getArgs ()) {
244
+ switch (arg.key .kind ) {
245
+ case ArgumentKeyKind::Default:
246
+ continue ;
247
+ case ArgumentKeyKind::Note:
248
+ de.diagnose (arg.loc , diag::opt_remark_note, arg.val );
249
+ continue ;
250
+ case ArgumentKeyKind::ParentLocNote:
251
+ de.diagnose (remark.getLocation (), diag::opt_remark_note, arg.val );
252
+ continue ;
253
+ }
254
+ llvm_unreachable (" Unhandled case?!" );
255
+ }
256
+ });
200
257
}
201
258
202
259
void Emitter::emit (const RemarkPassed &remark) {
0 commit comments