|
| 1 | +/** |
| 2 | + * The purpose of this file is to control which cached predicates belong to the same stage. |
| 3 | + * |
| 4 | + * Combining stages can improve performance as we are more likely to reuse shared, non-cached predicates. |
| 5 | + * |
| 6 | + * To make a predicate `p` belong to a stage `A`: |
| 7 | + * - make `p` depend on `A::ref()`, and |
| 8 | + * - make `A::backref()` depend on `p`. |
| 9 | + * |
| 10 | + * Since `A` is a cached module, `ref` and `backref` must be in the same stage, and the dependency |
| 11 | + * chain above thus forces `p` to be in that stage as well. |
| 12 | + * |
| 13 | + * With these two predicates in a `cached module` we ensure that all the cached predicates will be in a single stage at runtime. |
| 14 | + * |
| 15 | + * Grouping stages can cause unnecessary computation, as a concrete query might not depend on |
| 16 | + * all the cached predicates in a stage. |
| 17 | + * Care should therefore be taken not to combine two stages, if it is likely that a query only depend |
| 18 | + * on some but not all the cached predicates in the combined stage. |
| 19 | + */ |
| 20 | + |
| 21 | +import rust |
| 22 | + |
| 23 | +/** |
| 24 | + * Contains a `cached module` for each stage. |
| 25 | + * Each `cached module` ensures that predicates that are supposed to be in the same stage, are in the same stage. |
| 26 | + * |
| 27 | + * Each `cached module` contain two predicates: |
| 28 | + * The first, `ref`, always holds, and is referenced from `cached` predicates. |
| 29 | + * The second, `backref`, contains references to the same `cached` predicates. |
| 30 | + * The `backref` predicate starts with `1 = 1 or` to ensure that the predicate will be optimized down to a constant by the optimizer. |
| 31 | + */ |
| 32 | +module Stages { |
| 33 | + /** |
| 34 | + * The control flow graph (CFG) stage. |
| 35 | + */ |
| 36 | + cached |
| 37 | + module CfgStage { |
| 38 | + private import codeql.rust.controlflow.internal.Splitting |
| 39 | + private import codeql.rust.controlflow.internal.SuccessorType |
| 40 | + private import codeql.rust.controlflow.internal.ControlFlowGraphImpl |
| 41 | + |
| 42 | + /** |
| 43 | + * Always holds. |
| 44 | + * Ensures that a predicate is evaluated as part of the BasicBlocks stage. |
| 45 | + */ |
| 46 | + cached |
| 47 | + predicate ref() { 1 = 1 } |
| 48 | + |
| 49 | + /** |
| 50 | + * DO NOT USE! |
| 51 | + * |
| 52 | + * Contains references to each predicate that use the above `ref` predicate. |
| 53 | + */ |
| 54 | + cached |
| 55 | + predicate backref() { |
| 56 | + 1 = 1 |
| 57 | + or |
| 58 | + exists(TConditionalCompletionSplitKind()) |
| 59 | + or |
| 60 | + exists(TNormalSuccessor()) |
| 61 | + or |
| 62 | + exists(AstCfgNode n) |
| 63 | + } |
| 64 | + } |
| 65 | +} |
0 commit comments