@@ -233,6 +233,125 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardConditionImpl
233233 }
234234}
235235
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+
236355/**
237356 * A Boolean condition in the AST that guards one or more basic blocks and has a corresponding IR
238357 * instruction.
@@ -245,7 +364,7 @@ private class GuardConditionFromIR extends GuardConditionImpl {
245364 override predicate valueControls ( BasicBlock controlled , AbstractValue v ) {
246365 // This condition must determine the flow of control; that is, this
247366 // node must be a top-level condition.
248- this . controlsBlock ( controlled , v )
367+ controlsBlock ( ir , controlled , v )
249368 }
250369
251370 pragma [ inline]
@@ -319,20 +438,6 @@ private class GuardConditionFromIR extends GuardConditionImpl {
319438 this .valueControls ( block , value )
320439 )
321440 }
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- }
336441}
337442
338443private predicate excludeAsControlledInstruction ( Instruction instr ) {
0 commit comments