From 5f65ea60d12dd6b69e1979c269ad52e2873114d3 Mon Sep 17 00:00:00 2001 From: Kasper Svendsen Date: Tue, 27 May 2025 10:16:47 +0200 Subject: [PATCH 1/3] QL AST: Add overlay annotations --- ql/ql/src/codeql_ql/ast/Ast.qll | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/ql/ql/src/codeql_ql/ast/Ast.qll b/ql/ql/src/codeql_ql/ast/Ast.qll index 937c7bc61010..b3bbf41aaefe 100644 --- a/ql/ql/src/codeql_ql/ast/Ast.qll +++ b/ql/ql/src/codeql_ql/ast/Ast.qll @@ -2538,6 +2538,18 @@ private class NoOptArg extends AnnotationArg { NoOptArg() { this.getValue() = "noopt" } } +private class CallerArg extends AnnotationArg { + CallerArg() { this.getValue() = "caller" } +} + +private class LocalArg extends AnnotationArg { + LocalArg() { this.getValue() = "local" } +} + +private class LocalQArg extends AnnotationArg { + LocalQArg() { this.getValue() = "local?" } +} + private class MonotonicAggregatesArg extends AnnotationArg { MonotonicAggregatesArg() { this.getValue() = "monotonicAggregates" } } @@ -2597,6 +2609,27 @@ class NoOpt extends Annotation { override string toString() { result = "noopt" } } +/** An `overlay[caller]` annotation. */ +class OverlayCaller extends Annotation { + OverlayCaller() { this.getName() = "overlay" and this.getArgs(0) instanceof CallerArg } + + override string toString() { result = "caller" } +} + +/** An `overlay[local]` annotation. */ +class OverlayLocal extends Annotation { + OverlayLocal() { this.getName() = "overlay" and this.getArgs(0) instanceof LocalArg } + + override string toString() { result = "local" } +} + +/** An `overlay[local?]` annotation. */ +class OverlayLocalQ extends Annotation { + OverlayLocalQ() { this.getName() = "overlay" and this.getArgs(0) instanceof LocalQArg } + + override string toString() { result = "local?" } +} + /** A `language[monotonicAggregates]` annotation. */ class MonotonicAggregates extends Annotation { MonotonicAggregates() { this.getArgs(0) instanceof MonotonicAggregatesArg } From b291b0637e9691371e4c9ffe1ca88835023df2a1 Mon Sep 17 00:00:00 2001 From: Kasper Svendsen Date: Tue, 27 May 2025 10:17:46 +0200 Subject: [PATCH 2/3] Warn about possible non-inlining across overlay frontier --- .../queries/overlay/InlineOverlayCaller.ql | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 ql/ql/src/queries/overlay/InlineOverlayCaller.ql diff --git a/ql/ql/src/queries/overlay/InlineOverlayCaller.ql b/ql/ql/src/queries/overlay/InlineOverlayCaller.ql new file mode 100644 index 000000000000..d27a0ade9bbf --- /dev/null +++ b/ql/ql/src/queries/overlay/InlineOverlayCaller.ql @@ -0,0 +1,41 @@ +/** + * @name Cannot inline predicate across overlay frontier + * @description Local inline predicates that are not annotated with `overlay[caller]` are + * not inlined across the overlay frontier. This may negatively affect performance. + * @kind problem + * @problem.severity warning + * @id ql/inline-overlay-caller + * @tags performance + * @precision high + */ + +import ql + +predicate mayBeLocal(AstNode n) { + n.getAnAnnotation() instanceof OverlayLocal + or + n.getAnAnnotation() instanceof OverlayLocalQ + or + // The tree-sitter-ql grammar doesn't handle annotations on file-level + // module declarations correctly. To work around that, we consider any + // node in a file that contains an overlay[local] or overlay[local?] + // annotation to be potentially local. + exists(AstNode m | + n.getLocation().getFile() = m.getLocation().getFile() and + mayBeLocal(m) + ) +} + +from Predicate p +where + mayBeLocal(p) and + p.getAnAnnotation() instanceof Inline and + not p.getAnAnnotation() instanceof OverlayCaller and + not p.isPrivate() +select p, + "This possibly local non-private inline predicate will not " + + "be inlined across the overlay frontier. This may negatively " + + "affect evaluation performance. Consider adding an " + + "`overlay[caller]` annotation to allow inlining across the " + + "overlay frontier. Note that adding an `overlay[caller]` " + + "annotation affects semantics under overlay evaluation." From 23e789b421d5ceca2149cd66ed7ca2cd784b8d64 Mon Sep 17 00:00:00 2001 From: Kasper Svendsen Date: Tue, 10 Jun 2025 14:18:05 +0200 Subject: [PATCH 3/3] QL: Improve toString for overlay annotations --- ql/ql/src/codeql_ql/ast/Ast.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ql/ql/src/codeql_ql/ast/Ast.qll b/ql/ql/src/codeql_ql/ast/Ast.qll index b3bbf41aaefe..1e3ac4e8c827 100644 --- a/ql/ql/src/codeql_ql/ast/Ast.qll +++ b/ql/ql/src/codeql_ql/ast/Ast.qll @@ -2613,21 +2613,21 @@ class NoOpt extends Annotation { class OverlayCaller extends Annotation { OverlayCaller() { this.getName() = "overlay" and this.getArgs(0) instanceof CallerArg } - override string toString() { result = "caller" } + override string toString() { result = "overlay[caller]" } } /** An `overlay[local]` annotation. */ class OverlayLocal extends Annotation { OverlayLocal() { this.getName() = "overlay" and this.getArgs(0) instanceof LocalArg } - override string toString() { result = "local" } + override string toString() { result = "overlay[local]" } } /** An `overlay[local?]` annotation. */ class OverlayLocalQ extends Annotation { OverlayLocalQ() { this.getName() = "overlay" and this.getArgs(0) instanceof LocalQArg } - override string toString() { result = "local?" } + override string toString() { result = "overlay[local?]" } } /** A `language[monotonicAggregates]` annotation. */