@@ -486,13 +486,23 @@ private extension Instruction {
486
486
if !atp. needsStackProtection {
487
487
return nil
488
488
}
489
+ var hasNoStores = NoStores ( )
490
+ if hasNoStores. walkDownUses ( ofValue: atp, path: SmallProjectionPath ( ) ) == . continueWalk {
491
+ return nil
492
+ }
493
+
489
494
// The result of an `address_to_pointer` may be used in any unsafe way, e.g.
490
495
// passed to a C function.
491
496
baseAddr = atp. operand
492
497
case let ia as IndexAddrInst :
493
498
if !ia. needsStackProtection {
494
499
return nil
495
500
}
501
+ var hasNoStores = NoStores ( )
502
+ if hasNoStores. walkDownUses ( ofAddress: ia, path: SmallProjectionPath ( ) ) == . continueWalk {
503
+ return nil
504
+ }
505
+
496
506
// `index_addr` is unsafe if not used for tail-allocated elements (e.g. in Array).
497
507
baseAddr = ia. base
498
508
default :
@@ -509,6 +519,29 @@ private extension Instruction {
509
519
}
510
520
}
511
521
522
+ /// Checks if there are no stores to an address or raw pointer.
523
+ private struct NoStores : ValueDefUseWalker , AddressDefUseWalker {
524
+ var walkDownCache = WalkerCache < SmallProjectionPath > ( )
525
+
526
+ mutating func leafUse( value: Operand , path: SmallProjectionPath ) -> WalkResult {
527
+ if let ptai = value. instruction as? PointerToAddressInst {
528
+ return walkDownUses ( ofAddress: ptai, path: path)
529
+ }
530
+ return . abortWalk
531
+ }
532
+
533
+ mutating func leafUse( address: Operand , path: SmallProjectionPath ) -> WalkResult {
534
+ switch address. instruction {
535
+ case is LoadInst :
536
+ return . continueWalk
537
+ case let cai as CopyAddrInst :
538
+ return address == cai. sourceOperand ? . continueWalk : . abortWalk
539
+ default :
540
+ return . abortWalk
541
+ }
542
+ }
543
+ }
544
+
512
545
private extension Function {
513
546
func setNeedsStackProtection( _ context: FunctionPassContext ) {
514
547
if !needsStackProtection {
0 commit comments