1515#include " swift/AST/SemanticAttrs.h"
1616#include " swift/SIL/BasicBlockDatastructures.h"
1717#include " swift/SIL/InstructionUtils.h"
18- #include " swift/SIL/PrettyStackTrace.h"
1918#include " swift/SIL/ApplySite.h"
2019#include " swift/SILOptimizer/Analysis/ArraySemantic.h"
2120#include " swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h"
@@ -27,6 +26,41 @@ using namespace swift;
2726
2827namespace {
2928
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+
3064// / Issues performance diagnostics for functions which are annotated with
3165// / performance annotations, like @_noLocks, @_noAllocation.
3266// /
@@ -120,9 +154,6 @@ static bool isEffectFreeArraySemanticCall(SILInstruction *inst) {
120154bool PerformanceDiagnostics::visitFunction (SILFunction *function,
121155 PerformanceConstraints perfConstr,
122156 LocWithParent *parentLoc) {
123- PrettyStackTraceSILFunction stackTrace (
124- " Running performance diangostics on (visiting) " , function);
125-
126157 if (!function->isDefinition ())
127158 return false ;
128159
@@ -160,8 +191,9 @@ bool PerformanceDiagnostics::visitFunction(SILFunction *function,
160191 if (visitCallee (&inst, bca->getCalleeList (as), perfConstr, parentLoc))
161192 return true ;
162193 } 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+
165197 switch (bi->getBuiltinInfo ().ID ) {
166198 case BuiltinValueKind::Once:
167199 case BuiltinValueKind::OnceWithContext:
@@ -210,8 +242,6 @@ bool PerformanceDiagnostics::checkClosureValue(SILValue closure,
210242 SILInstruction *callInst,
211243 PerformanceConstraints perfConstr,
212244 LocWithParent *parentLoc) {
213- PrettyStackTraceSILNode closureStackTrace (" Validating closure" , closure);
214-
215245 // Walk through the definition of the closure until we find the "underlying"
216246 // function_ref instruction.
217247 while (!isa<FunctionRefInst>(closure)) {
@@ -234,6 +264,9 @@ bool PerformanceDiagnostics::checkClosureValue(SILValue closure,
234264 // the call site.
235265 return false ;
236266 } else {
267+ PrettyStackTracePerformanceDiagnostics stackTrace (
268+ " validating closure (function ref, callee) - unkown callee" , callInst);
269+
237270 diagnose (LocWithParent (callInst->getLoc ().getSourceLoc (), parentLoc), diag::performance_unknown_callees);
238271 return true ;
239272 }
@@ -251,14 +284,14 @@ bool PerformanceDiagnostics::visitCallee(SILInstruction *callInst,
251284 CalleeList callees,
252285 PerformanceConstraints perfConstr,
253286 LocWithParent *parentLoc) {
254- PrettyStackTraceSILNode callStackTrace (" Validating callee" , callInst);
255-
256287 LocWithParent asLoc (callInst->getLoc ().getSourceLoc (), parentLoc);
257288 LocWithParent *loc = &asLoc;
258289 if (parentLoc && asLoc.loc == callInst->getFunction ()->getLocation ().getSourceLoc ())
259290 loc = parentLoc;
260291
261292 if (callees.isIncomplete ()) {
293+ PrettyStackTracePerformanceDiagnostics stackTrace (" incomplete" , callInst);
294+
262295 diagnose (*loc, diag::performance_unknown_callees);
263296 return true ;
264297 }
@@ -273,6 +306,8 @@ bool PerformanceDiagnostics::visitCallee(SILInstruction *callInst,
273306 return false ;
274307
275308 if (!callee->isDefinition ()) {
309+ PrettyStackTracePerformanceDiagnostics stackTrace (" incomplete" , callInst);
310+
276311 diagnose (*loc, diag::performance_callee_unavailable);
277312 return true ;
278313 }
@@ -291,8 +326,6 @@ bool PerformanceDiagnostics::visitCallee(SILInstruction *callInst,
291326}
292327
293328static bool metatypeUsesAreNotRelevant (MetatypeInst *mt) {
294- PrettyStackTraceSILNode mtStackTrace (" Validating metatype" , mt);
295-
296329 for (Operand *use : mt->getUses ()) {
297330 if (auto *bi = dyn_cast<BuiltinInst>(use->getUser ())) {
298331 switch (bi->getBuiltinInfo ().ID ) {
@@ -315,15 +348,15 @@ static bool metatypeUsesAreNotRelevant(MetatypeInst *mt) {
315348bool PerformanceDiagnostics::visitInst (SILInstruction *inst,
316349 PerformanceConstraints perfConstr,
317350 LocWithParent *parentLoc) {
318- PrettyStackTraceSILNode stackTrace (" validating sil instruction (visiting)" , inst);
319-
320351 SILType impactType;
321352 RuntimeEffect impact = getRuntimeEffect (inst, impactType);
322353 LocWithParent loc (inst->getLoc ().getSourceLoc (), parentLoc);
323354
324355 if (impact & RuntimeEffect::Casting) {
325356 // TODO: be more specific on casting.
326357 // E.g. distinguish locking and allocating dynamic casts, etc.
358+ PrettyStackTracePerformanceDiagnostics stackTrace (" bad cast" , inst);
359+
327360 diagnose (loc, diag::performance_dynamic_casting);
328361 return true ;
329362 }
@@ -333,21 +366,30 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
333366
334367 // Try to give a good error message by looking which type of code it is.
335368 switch (inst->getKind ()) {
336- case SILInstructionKind::KeyPathInst:
369+ case SILInstructionKind::KeyPathInst: {
370+ PrettyStackTracePerformanceDiagnostics stackTrace (" key path" , inst);
337371 diagnose (loc, diag::performance_metadata, " using KeyPath" );
338372 break ;
373+ }
339374 case SILInstructionKind::AllocGlobalInst:
340- case SILInstructionKind::GlobalValueInst:
375+ case SILInstructionKind::GlobalValueInst: {
376+ PrettyStackTracePerformanceDiagnostics stackTrace (
377+ " AllocGlobalInst | GlobalValueInst" , inst);
341378 diagnose (loc, diag::performance_metadata, " global or static variables" );
342379 break ;
380+ }
343381 case SILInstructionKind::PartialApplyInst: {
382+ PrettyStackTracePerformanceDiagnostics stackTrace (
383+ " PartialApplyInst" , inst);
344384 diagnose (loc, diag::performance_metadata,
345385 " generic closures or local functions" );
346386 break ;
347387 }
348388 case SILInstructionKind::ApplyInst:
349389 case SILInstructionKind::TryApplyInst:
350390 case SILInstructionKind::BeginApplyInst: {
391+ PrettyStackTracePerformanceDiagnostics stackTrace (
392+ " ApplyInst | TryApplyInst | BeginApplyInst" , inst);
351393 diagnose (loc, diag::performance_metadata, " generic function calls" );
352394 break ;
353395 }
@@ -359,16 +401,23 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
359401 // We didn't recognize the instruction, so try to give an error message
360402 // based on the involved type.
361403 if (impactType) {
404+ PrettyStackTracePerformanceDiagnostics stackTrace (
405+ " impactType (unrecognized instruction)" , inst);
362406 diagnose (loc, diag::performance_metadata_type, impactType.getASTType ());
363407 break ;
364408 }
365409 // The default error message.
410+ PrettyStackTracePerformanceDiagnostics stackTrace (
411+ " default error (fallthrough, unkown inst)" , inst);
366412 diagnose (loc, diag::performance_metadata, " this code pattern" );
367413 break ;
368414 }
369415 return true ;
370416 }
371417 if (impact & RuntimeEffect::Allocating) {
418+ PrettyStackTracePerformanceDiagnostics stackTrace (
419+ " found allocation effect" , inst);
420+
372421 switch (inst->getKind ()) {
373422 case SILInstructionKind::BeginApplyInst:
374423 // Not all begin_applys necessarily allocate. But it's difficult to
@@ -389,6 +438,9 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
389438 return true ;
390439 }
391440 if (impact & RuntimeEffect::Deallocating) {
441+ PrettyStackTracePerformanceDiagnostics stackTrace (
442+ " found deallocation effect" , inst);
443+
392444 if (impactType) {
393445 switch (inst->getKind ()) {
394446 case SILInstructionKind::StoreInst:
@@ -409,6 +461,9 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
409461 return true ;
410462 }
411463 if (impact & RuntimeEffect::ObjectiveC) {
464+ PrettyStackTracePerformanceDiagnostics stackTrace (
465+ " found objc effect" , inst);
466+
412467 diagnose (loc, diag::performance_objectivec);
413468 return true ;
414469 }
@@ -417,6 +472,9 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
417472 return false ;
418473
419474 // Handle locking-only effects.
475+
476+ PrettyStackTracePerformanceDiagnostics stackTrace (
477+ " found locking or ref counting effect" , inst);
420478
421479 if (impact & RuntimeEffect::Locking) {
422480 if (inst->getFunction ()->isGlobalInit ()) {
@@ -461,7 +519,7 @@ void PerformanceDiagnostics::checkNonAnnotatedFunction(SILFunction *function) {
461519 }
462520}
463521
464- void PerformanceDiagnostics::diagnose (LocWithParent loc, Diagnostic &&D) {
522+ void PerformanceDiagnostics::diagnose (LocWithParent loc, Diagnostic &&D) {
465523 // Start with a valid location in the call tree.
466524 LocWithParent *validLoc = &loc;
467525 while (!validLoc->loc .isValid () && validLoc->parent ) {
@@ -498,6 +556,9 @@ class PerformanceDiagnosticsPass : public SILModuleTransform {
498556 // Check that @_section, @_silgen_name is only on constant globals
499557 for (SILGlobalVariable &g : module ->getSILGlobals ()) {
500558 if (!g.getStaticInitializerValue () && g.mustBeInitializedStatically ()) {
559+ PrettyStackTraceSILGlobal stackTrace (
560+ " global inst" , &g);
561+
501562 auto *decl = g.getDecl ();
502563 if (g.getSectionAttr ()) {
503564 module ->getASTContext ().Diags .diagnose (
0 commit comments