15
15
#include " swift/AST/SemanticAttrs.h"
16
16
#include " swift/SIL/BasicBlockDatastructures.h"
17
17
#include " swift/SIL/InstructionUtils.h"
18
- #include " swift/SIL/PrettyStackTrace.h"
19
18
#include " swift/SIL/ApplySite.h"
20
19
#include " swift/SILOptimizer/Analysis/ArraySemantic.h"
21
20
#include " swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h"
@@ -27,6 +26,41 @@ using namespace swift;
27
26
28
27
namespace {
29
28
29
+ class PrettyStackTracePerformanceDiagnostics
30
+ : public llvm::PrettyStackTraceEntry {
31
+ const SILNode *node;
32
+ const char *action;
33
+
34
+ public:
35
+ PrettyStackTracePerformanceDiagnostics (const char *action, SILNodePointer node)
36
+ : node(node), action(action) {}
37
+
38
+ virtual void print (llvm::raw_ostream &OS) const override {
39
+ OS << " While " << action << " -- visiting node " ;
40
+ node->print (OS);
41
+
42
+ if (auto inst = dyn_cast<SILInstruction>(node)) {
43
+ OS << " While visiting instruction in function " ;
44
+ inst->getFunction ()->print (OS);
45
+ }
46
+ }
47
+ };
48
+
49
+ class PrettyStackTraceSILGlobal
50
+ : public llvm::PrettyStackTraceEntry {
51
+ const SILGlobalVariable *node;
52
+ const char *action;
53
+
54
+ public:
55
+ PrettyStackTraceSILGlobal (const char *action, SILGlobalVariable *node)
56
+ : node(node), action(action) {}
57
+
58
+ virtual void print (llvm::raw_ostream &OS) const override {
59
+ OS << " While " << action << " -- visiting node " ;
60
+ node->print (OS);
61
+ }
62
+ };
63
+
30
64
// / Issues performance diagnostics for functions which are annotated with
31
65
// / performance annotations, like @_noLocks, @_noAllocation.
32
66
// /
@@ -120,9 +154,6 @@ static bool isEffectFreeArraySemanticCall(SILInstruction *inst) {
120
154
bool PerformanceDiagnostics::visitFunction (SILFunction *function,
121
155
PerformanceConstraints perfConstr,
122
156
LocWithParent *parentLoc) {
123
- PrettyStackTraceSILFunction stackTrace (
124
- " Running performance diangostics on (visiting) " , function);
125
-
126
157
if (!function->isDefinition ())
127
158
return false ;
128
159
@@ -160,8 +191,9 @@ bool PerformanceDiagnostics::visitFunction(SILFunction *function,
160
191
if (visitCallee (&inst, bca->getCalleeList (as), perfConstr, parentLoc))
161
192
return true ;
162
193
} else if (auto *bi = dyn_cast<BuiltinInst>(&inst)) {
163
- PrettyStackTraceSILNode biStackTrace (
164
- " Validating built in (once, once with context)" , bi);
194
+ PrettyStackTracePerformanceDiagnostics stackTrace (
195
+ " visitFunction::BuiltinInst (once, once with context)" , &inst);
196
+
165
197
switch (bi->getBuiltinInfo ().ID ) {
166
198
case BuiltinValueKind::Once:
167
199
case BuiltinValueKind::OnceWithContext:
@@ -210,8 +242,6 @@ bool PerformanceDiagnostics::checkClosureValue(SILValue closure,
210
242
SILInstruction *callInst,
211
243
PerformanceConstraints perfConstr,
212
244
LocWithParent *parentLoc) {
213
- PrettyStackTraceSILNode closureStackTrace (" Validating closure" , closure);
214
-
215
245
// Walk through the definition of the closure until we find the "underlying"
216
246
// function_ref instruction.
217
247
while (!isa<FunctionRefInst>(closure)) {
@@ -234,6 +264,9 @@ bool PerformanceDiagnostics::checkClosureValue(SILValue closure,
234
264
// the call site.
235
265
return false ;
236
266
} else {
267
+ PrettyStackTracePerformanceDiagnostics stackTrace (
268
+ " validating closure (function ref, callee) - unkown callee" , callInst);
269
+
237
270
diagnose (LocWithParent (callInst->getLoc ().getSourceLoc (), parentLoc), diag::performance_unknown_callees);
238
271
return true ;
239
272
}
@@ -251,14 +284,14 @@ bool PerformanceDiagnostics::visitCallee(SILInstruction *callInst,
251
284
CalleeList callees,
252
285
PerformanceConstraints perfConstr,
253
286
LocWithParent *parentLoc) {
254
- PrettyStackTraceSILNode callStackTrace (" Validating callee" , callInst);
255
-
256
287
LocWithParent asLoc (callInst->getLoc ().getSourceLoc (), parentLoc);
257
288
LocWithParent *loc = &asLoc;
258
289
if (parentLoc && asLoc.loc == callInst->getFunction ()->getLocation ().getSourceLoc ())
259
290
loc = parentLoc;
260
291
261
292
if (callees.isIncomplete ()) {
293
+ PrettyStackTracePerformanceDiagnostics stackTrace (" incomplete" , callInst);
294
+
262
295
diagnose (*loc, diag::performance_unknown_callees);
263
296
return true ;
264
297
}
@@ -273,6 +306,8 @@ bool PerformanceDiagnostics::visitCallee(SILInstruction *callInst,
273
306
return false ;
274
307
275
308
if (!callee->isDefinition ()) {
309
+ PrettyStackTracePerformanceDiagnostics stackTrace (" incomplete" , callInst);
310
+
276
311
diagnose (*loc, diag::performance_callee_unavailable);
277
312
return true ;
278
313
}
@@ -291,8 +326,6 @@ bool PerformanceDiagnostics::visitCallee(SILInstruction *callInst,
291
326
}
292
327
293
328
static bool metatypeUsesAreNotRelevant (MetatypeInst *mt) {
294
- PrettyStackTraceSILNode mtStackTrace (" Validating metatype" , mt);
295
-
296
329
for (Operand *use : mt->getUses ()) {
297
330
if (auto *bi = dyn_cast<BuiltinInst>(use->getUser ())) {
298
331
switch (bi->getBuiltinInfo ().ID ) {
@@ -315,15 +348,15 @@ static bool metatypeUsesAreNotRelevant(MetatypeInst *mt) {
315
348
bool PerformanceDiagnostics::visitInst (SILInstruction *inst,
316
349
PerformanceConstraints perfConstr,
317
350
LocWithParent *parentLoc) {
318
- PrettyStackTraceSILNode stackTrace (" validating sil instruction (visiting)" , inst);
319
-
320
351
SILType impactType;
321
352
RuntimeEffect impact = getRuntimeEffect (inst, impactType);
322
353
LocWithParent loc (inst->getLoc ().getSourceLoc (), parentLoc);
323
354
324
355
if (impact & RuntimeEffect::Casting) {
325
356
// TODO: be more specific on casting.
326
357
// E.g. distinguish locking and allocating dynamic casts, etc.
358
+ PrettyStackTracePerformanceDiagnostics stackTrace (" bad cast" , inst);
359
+
327
360
diagnose (loc, diag::performance_dynamic_casting);
328
361
return true ;
329
362
}
@@ -333,21 +366,30 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
333
366
334
367
// Try to give a good error message by looking which type of code it is.
335
368
switch (inst->getKind ()) {
336
- case SILInstructionKind::KeyPathInst:
369
+ case SILInstructionKind::KeyPathInst: {
370
+ PrettyStackTracePerformanceDiagnostics stackTrace (" key path" , inst);
337
371
diagnose (loc, diag::performance_metadata, " using KeyPath" );
338
372
break ;
373
+ }
339
374
case SILInstructionKind::AllocGlobalInst:
340
- case SILInstructionKind::GlobalValueInst:
375
+ case SILInstructionKind::GlobalValueInst: {
376
+ PrettyStackTracePerformanceDiagnostics stackTrace (
377
+ " AllocGlobalInst | GlobalValueInst" , inst);
341
378
diagnose (loc, diag::performance_metadata, " global or static variables" );
342
379
break ;
380
+ }
343
381
case SILInstructionKind::PartialApplyInst: {
382
+ PrettyStackTracePerformanceDiagnostics stackTrace (
383
+ " PartialApplyInst" , inst);
344
384
diagnose (loc, diag::performance_metadata,
345
385
" generic closures or local functions" );
346
386
break ;
347
387
}
348
388
case SILInstructionKind::ApplyInst:
349
389
case SILInstructionKind::TryApplyInst:
350
390
case SILInstructionKind::BeginApplyInst: {
391
+ PrettyStackTracePerformanceDiagnostics stackTrace (
392
+ " ApplyInst | TryApplyInst | BeginApplyInst" , inst);
351
393
diagnose (loc, diag::performance_metadata, " generic function calls" );
352
394
break ;
353
395
}
@@ -359,16 +401,23 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
359
401
// We didn't recognize the instruction, so try to give an error message
360
402
// based on the involved type.
361
403
if (impactType) {
404
+ PrettyStackTracePerformanceDiagnostics stackTrace (
405
+ " impactType (unrecognized instruction)" , inst);
362
406
diagnose (loc, diag::performance_metadata_type, impactType.getASTType ());
363
407
break ;
364
408
}
365
409
// The default error message.
410
+ PrettyStackTracePerformanceDiagnostics stackTrace (
411
+ " default error (fallthrough, unkown inst)" , inst);
366
412
diagnose (loc, diag::performance_metadata, " this code pattern" );
367
413
break ;
368
414
}
369
415
return true ;
370
416
}
371
417
if (impact & RuntimeEffect::Allocating) {
418
+ PrettyStackTracePerformanceDiagnostics stackTrace (
419
+ " found allocation effect" , inst);
420
+
372
421
switch (inst->getKind ()) {
373
422
case SILInstructionKind::BeginApplyInst:
374
423
// Not all begin_applys necessarily allocate. But it's difficult to
@@ -389,6 +438,9 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
389
438
return true ;
390
439
}
391
440
if (impact & RuntimeEffect::Deallocating) {
441
+ PrettyStackTracePerformanceDiagnostics stackTrace (
442
+ " found deallocation effect" , inst);
443
+
392
444
if (impactType) {
393
445
switch (inst->getKind ()) {
394
446
case SILInstructionKind::StoreInst:
@@ -409,6 +461,9 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
409
461
return true ;
410
462
}
411
463
if (impact & RuntimeEffect::ObjectiveC) {
464
+ PrettyStackTracePerformanceDiagnostics stackTrace (
465
+ " found objc effect" , inst);
466
+
412
467
diagnose (loc, diag::performance_objectivec);
413
468
return true ;
414
469
}
@@ -417,6 +472,9 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
417
472
return false ;
418
473
419
474
// Handle locking-only effects.
475
+
476
+ PrettyStackTracePerformanceDiagnostics stackTrace (
477
+ " found locking or ref counting effect" , inst);
420
478
421
479
if (impact & RuntimeEffect::Locking) {
422
480
if (inst->getFunction ()->isGlobalInit ()) {
@@ -461,7 +519,7 @@ void PerformanceDiagnostics::checkNonAnnotatedFunction(SILFunction *function) {
461
519
}
462
520
}
463
521
464
- void PerformanceDiagnostics::diagnose (LocWithParent loc, Diagnostic &&D) {
522
+ void PerformanceDiagnostics::diagnose (LocWithParent loc, Diagnostic &&D) {
465
523
// Start with a valid location in the call tree.
466
524
LocWithParent *validLoc = &loc;
467
525
while (!validLoc->loc .isValid () && validLoc->parent ) {
@@ -498,6 +556,9 @@ class PerformanceDiagnosticsPass : public SILModuleTransform {
498
556
// Check that @_section, @_silgen_name is only on constant globals
499
557
for (SILGlobalVariable &g : module ->getSILGlobals ()) {
500
558
if (!g.getStaticInitializerValue () && g.mustBeInitializedStatically ()) {
559
+ PrettyStackTraceSILGlobal stackTrace (
560
+ " global inst" , &g);
561
+
501
562
auto *decl = g.getDecl ();
502
563
if (g.getSectionAttr ()) {
503
564
module ->getASTContext ().Diags .diagnose (
0 commit comments