@@ -233,6 +233,125 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardConditionImpl
233
233
}
234
234
}
235
235
236
+ /**
237
+ * Holds if `ir` controls `block`, meaning that `block` is only
238
+ * entered if the value of this condition is `v`. This helper
239
+ * predicate does not necessarily hold for binary logical operations like
240
+ * `&&` and `||`. See the detailed explanation on predicate `controls`.
241
+ */
242
+ private predicate controlsBlock ( IRGuardCondition ir , BasicBlock controlled , AbstractValue v ) {
243
+ exists ( IRBlock irb |
244
+ ir .valueControls ( irb , v ) and
245
+ nonExcludedIRAndBasicBlock ( irb , controlled ) and
246
+ not isUnreachedBlock ( irb )
247
+ )
248
+ }
249
+
250
+ private class GuardConditionFromNotExpr extends GuardConditionImpl {
251
+ IRGuardCondition ir ;
252
+
253
+ GuardConditionFromNotExpr ( ) {
254
+ // When `!` is applied to an integer (such as `x`) the generated IR looks
255
+ // like:
256
+ // ```
257
+ // r1(glval<int>) = VariableAddress[myInt] :
258
+ // r2(int) = Load[x] : &:r1, m1_6
259
+ // r3(int) = Constant[0] :
260
+ // r4(bool) = CompareEQ : r2, r3
261
+ // ```
262
+ // And so the `IRGuardCondition` for an expression such as `if(!x)` is the
263
+ // `CompareEQ` instruction. However, users often expect the `x` to also
264
+ // be a guard condition. But from the perspective of the IR the `x` is just
265
+ // the left-hand side of a comparison against 0 so it's not included as a
266
+ // normal `IRGuardCondition`. So to align with user expectations we make
267
+ // that `x` a `GuardCondition`.
268
+ exists ( NotExpr notExpr , Type t |
269
+ this = notExpr .getOperand ( ) and
270
+ t = this .getUnspecifiedType ( ) and
271
+ not t instanceof BoolType and
272
+ ir .getUnconvertedResultExpression ( ) = notExpr
273
+ )
274
+ }
275
+
276
+ override predicate valueControls ( BasicBlock controlled , AbstractValue v ) {
277
+ // This condition must determine the flow of control; that is, this
278
+ // node must be a top-level condition.
279
+ controlsBlock ( ir , controlled , v .getDualValue ( ) )
280
+ }
281
+
282
+ pragma [ inline]
283
+ override predicate comparesLt ( Expr left , Expr right , int k , boolean isLessThan , boolean testIsTrue ) {
284
+ exists ( Instruction li , Instruction ri |
285
+ li .getUnconvertedResultExpression ( ) = left and
286
+ ri .getUnconvertedResultExpression ( ) = right and
287
+ ir .comparesLt ( li .getAUse ( ) , ri .getAUse ( ) , k , isLessThan , testIsTrue .booleanNot ( ) )
288
+ )
289
+ }
290
+
291
+ pragma [ inline]
292
+ override predicate comparesLt ( Expr e , int k , boolean isLessThan , AbstractValue value ) {
293
+ exists ( Instruction i |
294
+ i .getUnconvertedResultExpression ( ) = e and
295
+ ir .comparesLt ( i .getAUse ( ) , k , isLessThan , value .getDualValue ( ) )
296
+ )
297
+ }
298
+
299
+ pragma [ inline]
300
+ override predicate ensuresLt ( Expr left , Expr right , int k , BasicBlock block , boolean isLessThan ) {
301
+ exists ( Instruction li , Instruction ri , boolean testIsTrue |
302
+ li .getUnconvertedResultExpression ( ) = left and
303
+ ri .getUnconvertedResultExpression ( ) = right and
304
+ ir .comparesLt ( li .getAUse ( ) , ri .getAUse ( ) , k , isLessThan , testIsTrue .booleanNot ( ) ) and
305
+ this .controls ( block , testIsTrue )
306
+ )
307
+ }
308
+
309
+ pragma [ inline]
310
+ override predicate ensuresLt ( Expr e , int k , BasicBlock block , boolean isLessThan ) {
311
+ exists ( Instruction i , AbstractValue value |
312
+ i .getUnconvertedResultExpression ( ) = e and
313
+ ir .comparesLt ( i .getAUse ( ) , k , isLessThan , value .getDualValue ( ) ) and
314
+ this .valueControls ( block , value )
315
+ )
316
+ }
317
+
318
+ pragma [ inline]
319
+ override predicate comparesEq ( Expr left , Expr right , int k , boolean areEqual , boolean testIsTrue ) {
320
+ exists ( Instruction li , Instruction ri |
321
+ li .getUnconvertedResultExpression ( ) = left and
322
+ ri .getUnconvertedResultExpression ( ) = right and
323
+ ir .comparesEq ( li .getAUse ( ) , ri .getAUse ( ) , k , areEqual , testIsTrue .booleanNot ( ) )
324
+ )
325
+ }
326
+
327
+ pragma [ inline]
328
+ override predicate ensuresEq ( Expr left , Expr right , int k , BasicBlock block , boolean areEqual ) {
329
+ exists ( Instruction li , Instruction ri , boolean testIsTrue |
330
+ li .getUnconvertedResultExpression ( ) = left and
331
+ ri .getUnconvertedResultExpression ( ) = right and
332
+ ir .comparesEq ( li .getAUse ( ) , ri .getAUse ( ) , k , areEqual , testIsTrue .booleanNot ( ) ) and
333
+ this .controls ( block , testIsTrue )
334
+ )
335
+ }
336
+
337
+ pragma [ inline]
338
+ override predicate comparesEq ( Expr e , int k , boolean areEqual , AbstractValue value ) {
339
+ exists ( Instruction i |
340
+ i .getUnconvertedResultExpression ( ) = e and
341
+ ir .comparesEq ( i .getAUse ( ) , k , areEqual , value .getDualValue ( ) )
342
+ )
343
+ }
344
+
345
+ pragma [ inline]
346
+ override predicate ensuresEq ( Expr e , int k , BasicBlock block , boolean areEqual ) {
347
+ exists ( Instruction i , AbstractValue value |
348
+ i .getUnconvertedResultExpression ( ) = e and
349
+ ir .comparesEq ( i .getAUse ( ) , k , areEqual , value .getDualValue ( ) ) and
350
+ this .valueControls ( block , value )
351
+ )
352
+ }
353
+ }
354
+
236
355
/**
237
356
* A Boolean condition in the AST that guards one or more basic blocks and has a corresponding IR
238
357
* instruction.
@@ -245,7 +364,7 @@ private class GuardConditionFromIR extends GuardConditionImpl {
245
364
override predicate valueControls ( BasicBlock controlled , AbstractValue v ) {
246
365
// This condition must determine the flow of control; that is, this
247
366
// node must be a top-level condition.
248
- this . controlsBlock ( controlled , v )
367
+ controlsBlock ( ir , controlled , v )
249
368
}
250
369
251
370
pragma [ inline]
@@ -319,20 +438,6 @@ private class GuardConditionFromIR extends GuardConditionImpl {
319
438
this .valueControls ( block , value )
320
439
)
321
440
}
322
-
323
- /**
324
- * Holds if this condition controls `block`, meaning that `block` is only
325
- * entered if the value of this condition is `v`. This helper
326
- * predicate does not necessarily hold for binary logical operations like
327
- * `&&` and `||`. See the detailed explanation on predicate `controls`.
328
- */
329
- private predicate controlsBlock ( BasicBlock controlled , AbstractValue v ) {
330
- exists ( IRBlock irb |
331
- ir .valueControls ( irb , v ) and
332
- nonExcludedIRAndBasicBlock ( irb , controlled ) and
333
- not isUnreachedBlock ( irb )
334
- )
335
- }
336
441
}
337
442
338
443
private predicate excludeAsControlledInstruction ( Instruction instr ) {
0 commit comments