@@ -244,17 +244,6 @@ Instruction getDestinationAddress(Instruction instr) {
244
244
]
245
245
}
246
246
247
- class ReferenceToInstruction extends CopyValueInstruction {
248
- ReferenceToInstruction ( ) {
249
- this .getResultType ( ) instanceof Cpp:: ReferenceType and
250
- not this .getUnary ( ) .getResultType ( ) instanceof Cpp:: ReferenceType
251
- }
252
-
253
- Instruction getSourceAddress ( ) { result = getSourceAddressOperand ( ) .getDef ( ) }
254
-
255
- Operand getSourceAddressOperand ( ) { result = this .getUnaryOperand ( ) }
256
- }
257
-
258
247
/** Gets the source address of `instr` if it is an instruction that behaves like a `LoadInstruction`. */
259
248
Instruction getSourceAddress ( Instruction instr ) { result = getSourceAddressOperand ( instr ) .getDef ( ) }
260
249
@@ -266,11 +255,7 @@ Operand getSourceAddressOperand(Instruction instr) {
266
255
result =
267
256
[
268
257
instr .( LoadInstruction ) .getSourceAddressOperand ( ) ,
269
- instr .( ReadSideEffectInstruction ) .getArgumentOperand ( ) ,
270
- // `ReferenceToInstruction` is really more of an address-of operation,
271
- // but by including it in this list we break out of `flowOutOfAddressStep` at an
272
- // instruction that, at the source level, looks like a use of a variable.
273
- instr .( ReferenceToInstruction ) .getSourceAddressOperand ( )
258
+ instr .( ReadSideEffectInstruction ) .getArgumentOperand ( )
274
259
]
275
260
}
276
261
@@ -295,10 +280,6 @@ Operand getSourceValueOperand(Instruction instr) {
295
280
result = instr .( LoadInstruction ) .getSourceValueOperand ( )
296
281
or
297
282
result = instr .( ReadSideEffectInstruction ) .getSideEffectOperand ( )
298
- or
299
- // See the comment on the `ReferenceToInstruction` disjunct in `getSourceAddressOperand` for why
300
- // this case is included.
301
- result = instr .( ReferenceToInstruction ) .getSourceValueOperand ( )
302
283
}
303
284
304
285
/**
@@ -513,6 +494,64 @@ private module Cached {
513
494
explicitWrite ( false , storeNode .getStoreInstruction ( ) , def )
514
495
)
515
496
or
497
+ // The destination of a store operation has undergone lvalue-to-rvalue conversion and is now a
498
+ // right-hand-side of a store operation.
499
+ // Find the next use of the variable in that store operation, and recursively find the load of that
500
+ // pointer. For example, consider this case:
501
+ //
502
+ // ```cpp
503
+ // int x = source();
504
+ // int* p = &x;
505
+ // sink(*p);
506
+ // ```
507
+ //
508
+ // if we want to find the load of the address of `x`, we see that the pointer is stored into `p`,
509
+ // and we then need to recursively look for the load of `p`.
510
+ exists (
511
+ Def def , StoreInstruction store , IRBlock block1 , int rnk1 , Use use , IRBlock block2 , int rnk2
512
+ |
513
+ store = def .getInstruction ( ) and
514
+ store .getSourceValueOperand ( ) = operand and
515
+ def .hasRankInBlock ( block1 , rnk1 ) and
516
+ use .hasRankInBlock ( block2 , rnk2 ) and
517
+ adjacentDefRead ( _, block1 , rnk1 , block2 , rnk2 )
518
+ |
519
+ // The shared SSA library has determined that `use` is the next use of the operand
520
+ // so we find the next load of that use (but only if there is no `PostUpdateNode`) we
521
+ // need to flow into first.
522
+ not StoreNodeFlow:: flowInto ( store , _) and
523
+ flowOutOfAddressStep ( use .getOperand ( ) , nodeTo )
524
+ or
525
+ // It may also be the case that `store` gives rise to another store step. So let's make sure that
526
+ // we also take those into account.
527
+ StoreNodeFlow:: flowInto ( store , nodeTo )
528
+ )
529
+ or
530
+ // As we find the next load of an address, we might come across another use of the same variable.
531
+ // In that case, we recursively find the next use of _that_ operand, and continue searching for
532
+ // the next load of that operand. For example, consider this case:
533
+ //
534
+ // ```cpp
535
+ // int x = source();
536
+ // use(&x);
537
+ // int* p = &x;
538
+ // sink(*p);
539
+ // ```
540
+ //
541
+ // The next use of `x` after its definition is `use(&x)`, but there is a later load of the address
542
+ // of `x` that we want to flow to. So we use the shared SSA library to find the next load.
543
+ not operand = getSourceAddressOperand ( _) and
544
+ exists ( Use use1 , Use use2 , IRBlock block1 , int rnk1 , IRBlock block2 , int rnk2 |
545
+ use1 .getOperand ( ) = operand and
546
+ use1 .hasRankInBlock ( block1 , rnk1 ) and
547
+ // Don't flow to the next use if this use is part of a store operation that totally
548
+ // overrides a variable.
549
+ not explicitWrite ( true , _, use1 .getOperand ( ) .getDef ( ) ) and
550
+ adjacentDefRead ( _, block1 , rnk1 , block2 , rnk2 ) and
551
+ use2 .hasRankInBlock ( block2 , rnk2 ) and
552
+ flowOutOfAddressStep ( use2 .getOperand ( ) , nodeTo )
553
+ )
554
+ or
516
555
operand = getSourceAddressOperand ( nodeTo .asInstruction ( ) )
517
556
or
518
557
exists ( ReturnIndirectionInstruction ret |
0 commit comments