Skip to content

Commit 9a828bc

Browse files
committed
[opt-remark] Teach opt-remarks how to emit notes.
I did this by adding a kind to Arguments and making it so we have a kind that emits as a separate NOTE when we emit diagnostics, but is emitted as a normal argument when emitting to the bitstream.
1 parent 994edab commit 9a828bc

File tree

4 files changed

+97
-18
lines changed

4 files changed

+97
-18
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,7 @@ ERROR(non_borrowed_indirect_addressof,none,
536536

537537
REMARK(opt_remark_passed, none, "%0", (StringRef))
538538
REMARK(opt_remark_missed, none, "%0", (StringRef))
539+
NOTE(opt_remark_note, none, "%0", (StringRef))
539540

540541
// Float-point to integer conversions
541542
ERROR(float_to_int_overflow, none,

include/swift/SIL/OptimizationRemark.h

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,63 @@ class SILFunction;
3232

3333
namespace OptRemark {
3434

35+
struct ArgumentKeyKind {
36+
enum InnerTy {
37+
// Just assume this is a normal msg that we are emitting.
38+
Default,
39+
40+
// Assume this is a note that should be emitted as a separate
41+
// diagnostic when emitting diagnostics. Do nothing special
42+
// along the backend path.
43+
Note,
44+
};
45+
46+
InnerTy innerValue;
47+
48+
ArgumentKeyKind(InnerTy value) : innerValue(value) {}
49+
ArgumentKeyKind(const ArgumentKeyKind &kind) : innerValue(kind.innerValue) {}
50+
51+
operator InnerTy() const { return innerValue; }
52+
53+
/// Return true if this argument is meant to be a separate diagnostic when we
54+
/// emit diagnostics but when we emit to the remark streamer (due to not
55+
/// having support for this), we just emit the remark inline.
56+
///
57+
/// TODO: Unfortunate that this needs to be done.
58+
bool isSeparateDiagnostic() const {
59+
switch (innerValue) {
60+
case InnerTy::Default:
61+
return false;
62+
case InnerTy::Note:
63+
return true;
64+
}
65+
66+
llvm_unreachable("Covered switch isn't covered?!");
67+
}
68+
};
69+
70+
struct ArgumentKey {
71+
ArgumentKeyKind kind;
72+
std::string data;
73+
74+
ArgumentKey(ArgumentKeyKind kind, StringRef data) : kind(kind), data(data) {}
75+
ArgumentKey(ArgumentKeyKind::InnerTy kind, StringRef data)
76+
: kind(kind), data(data) {}
77+
ArgumentKey(ArgumentKey kind, StringRef data) : kind(kind.kind), data(data) {}
78+
};
79+
3580
/// Used in the streaming interface as the general argument type. It
3681
/// internally converts everything into a key-value pair.
3782
struct Argument {
38-
std::string key;
83+
ArgumentKey key;
3984
std::string val;
4085
/// If set, the debug location corresponding to the value.
4186
SourceLoc loc;
4287

43-
explicit Argument(StringRef Str = "") : key("String"), val(Str) {}
44-
Argument(StringRef key, StringRef val) : key(key), val(val) {}
88+
explicit Argument(StringRef Str = "")
89+
: key(ArgumentKeyKind::Default, "String"), val(Str) {}
90+
Argument(StringRef key, StringRef val)
91+
: key(ArgumentKeyKind::Default, key), val(val) {}
4592

4693
Argument(StringRef key, int n);
4794
Argument(StringRef key, long n);
@@ -50,7 +97,9 @@ struct Argument {
5097
Argument(StringRef key, unsigned long n);
5198
Argument(StringRef key, unsigned long long n);
5299

53-
Argument(StringRef key, SILFunction *f);
100+
Argument(StringRef key, SILFunction *f)
101+
: Argument(ArgumentKey(ArgumentKeyKind::Default, key), f) {}
102+
Argument(ArgumentKey key, SILFunction *f);
54103
Argument(StringRef key, SILType ty);
55104
Argument(StringRef key, CanType ty);
56105
};

include/swift/SIL/SILRemarkStreamer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ llvm::remarks::Remark SILRemarkStreamer::toLLVMRemark(
111111

112112
for (const OptRemark::Argument &arg : optRemark.getArgs()) {
113113
llvmRemark.Args.emplace_back();
114-
llvmRemark.Args.back().Key = arg.key;
114+
llvmRemark.Args.back().Key = arg.key.data;
115115
llvmRemark.Args.back().Val = arg.val;
116116
llvmRemark.Args.back().Loc =
117117
toRemarkLocation(arg.loc, getASTContext().SourceMgr);

lib/SIL/Utils/OptimizationRemark.cpp

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,25 @@
2828
using namespace swift;
2929
using namespace OptRemark;
3030

31-
Argument::Argument(StringRef key, int n) : key(key), val(llvm::itostr(n)) {}
31+
Argument::Argument(StringRef key, int n)
32+
: key(ArgumentKeyKind::Default, key), val(llvm::itostr(n)) {}
3233

33-
Argument::Argument(StringRef key, long n) : key(key), val(llvm::itostr(n)) {}
34+
Argument::Argument(StringRef key, long n)
35+
: key(ArgumentKeyKind::Default, key), val(llvm::itostr(n)) {}
3436

3537
Argument::Argument(StringRef key, long long n)
36-
: key(key), val(llvm::itostr(n)) {}
38+
: key(ArgumentKeyKind::Default, key), val(llvm::itostr(n)) {}
3739

3840
Argument::Argument(StringRef key, unsigned n)
39-
: key(key), val(llvm::utostr(n)) {}
41+
: key(ArgumentKeyKind::Default, key), val(llvm::utostr(n)) {}
4042

4143
Argument::Argument(StringRef key, unsigned long n)
42-
: key(key), val(llvm::utostr(n)) {}
44+
: key(ArgumentKeyKind::Default, key), val(llvm::utostr(n)) {}
4345

4446
Argument::Argument(StringRef key, unsigned long long n)
45-
: key(key), val(llvm::utostr(n)) {}
47+
: key(ArgumentKeyKind::Default, key), val(llvm::utostr(n)) {}
4648

47-
Argument::Argument(StringRef key, SILFunction *f) : key(key) {
49+
Argument::Argument(ArgumentKey key, SILFunction *f) : key(key) {
4850
auto options = Demangle::DemangleOptions::SimplifiedUIDemangleOptions();
4951
// Enable module names so that we have a way of filtering out
5052
// stdlib-related remarks.
@@ -58,12 +60,14 @@ Argument::Argument(StringRef key, SILFunction *f) : key(key) {
5860
loc = f->getLocation().getSourceLoc();
5961
}
6062

61-
Argument::Argument(StringRef key, SILType ty) : key(key) {
63+
Argument::Argument(StringRef key, SILType ty)
64+
: key(ArgumentKeyKind::Default, key) {
6265
llvm::raw_string_ostream stream(val);
6366
ty.print(stream);
6467
}
6568

66-
Argument::Argument(StringRef key, CanType ty) : key(key) {
69+
Argument::Argument(StringRef key, CanType ty)
70+
: key(ArgumentKeyKind::Default, key) {
6771
llvm::raw_string_ostream stream(val);
6872
ty.print(stream);
6973
}
@@ -72,8 +76,15 @@ template <typename DerivedT>
7276
std::string Remark<DerivedT>::getMsg() const {
7377
std::string str;
7478
llvm::raw_string_ostream stream(str);
75-
for (const Argument &arg : args)
79+
// Go through our args and if we are not emitting for diagnostics *OR* we are
80+
// emitting for diagnostics and this argument is not intended to be emitted as
81+
// a diagnostic separate from our main remark, emit the arg value here.
82+
for (const Argument &arg : args) {
83+
if (arg.key.kind.isSeparateDiagnostic())
84+
continue;
7685
stream << arg.val;
86+
}
87+
7788
return stream.str();
7889
}
7990

@@ -194,9 +205,27 @@ static void emitRemark(SILModule &module, const Remark<RemarkT> &remark,
194205
return;
195206
if (auto *remarkStreamer = module.getSILRemarkStreamer())
196207
remarkStreamer->emit(remark);
197-
if (diagEnabled)
198-
module.getASTContext().Diags.diagnose(remark.getLocation(), id,
199-
remark.getMsg());
208+
209+
// If diagnostics are enabled, first emit the main diagnostic and then loop
210+
// through our arguments and allow the arguments to add additional diagnostics
211+
// if they want.
212+
if (diagEnabled) {
213+
auto &Diags = module.getASTContext().Diags;
214+
Diags.diagnose(remark.getLocation(), id,
215+
remark.getMsg());
216+
for (auto &arg : remark.getArgs()) {
217+
switch (arg.key.kind) {
218+
case ArgumentKeyKind::Default:
219+
continue;
220+
case ArgumentKeyKind::Note:
221+
Diags.diagnose(arg.loc, diag::opt_remark_note,
222+
arg.key.data);
223+
continue;
224+
}
225+
226+
llvm_unreachable("Unhandled case?!");
227+
}
228+
}
200229
}
201230

202231
void Emitter::emit(const RemarkPassed &remark) {

0 commit comments

Comments
 (0)