@@ -489,6 +489,49 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
489489 return false ;
490490 }
491491 }
492+ if (impact & RuntimeEffect::ExclusivityChecking) {
493+ switch (inst->getKind ()) {
494+ case SILInstructionKind::BeginUnpairedAccessInst:
495+ case SILInstructionKind::EndUnpairedAccessInst:
496+ // These instructions are quite unusual; they seem to only ever created
497+ // explicitly by calling functions from the Builtin module, see:
498+ // - emitBuiltinPerformInstantaneousReadAccess
499+ // - emitBuiltinEndUnpairedAccess
500+ break ;
501+ case SILInstructionKind::EndAccessInst:
502+ break ; // We'll already diagnose the begin access.
503+ case SILInstructionKind::BeginAccessInst: {
504+ auto bai = cast<BeginAccessInst>(inst);
505+ auto info = VariableNameInferrer::inferNameAndRoot (bai->getSource ());
506+
507+ if (!info) {
508+ LLVM_DEBUG (llvm::dbgs () << " exclusivity (no name?): " << *inst);
509+ diagnose (loc, diag::manualownership_exclusivity);
510+ return false ;
511+ }
512+ Identifier name = info->first ;
513+ SILValue root = info->second ;
514+ StringRef advice = " " ;
515+
516+ // Try to classify the root to give advice.
517+ if (isa<GlobalAddrInst>(root)) {
518+ advice = " , because it involves a global variable" ;
519+ } else if (root->getType ().isAnyClassReferenceType ()) {
520+ advice = " , because it's a member of a reference type" ;
521+ }
522+
523+ LLVM_DEBUG (llvm::dbgs () << " exclusivity: " << *inst);
524+ LLVM_DEBUG (llvm::dbgs () << " with root: " << root);
525+
526+ diagnose (loc, diag::manualownership_exclusivity_named, name, advice);
527+ break ;
528+ }
529+ default :
530+ LLVM_DEBUG (llvm::dbgs () << " UNKNOWN EXCLUSIVITY INST: " << *inst);
531+ diagnose (loc, diag::manualownership_exclusivity);
532+ return false ;
533+ }
534+ }
492535 return false ;
493536 }
494537
0 commit comments