-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rust: SSA additions #17786
Rust: SSA additions #17786
Changes from 1 commit
a1db359
577afc3
76e1885
85e59c9
75103f4
334602a
c5b01eb
b86a581
cab9164
8f8564d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -74,6 +74,8 @@ module SsaInput implements SsaImplCommon::InputSig<Location> { | |
capturedEntryWrite(bb, i, v) | ||
) and | ||
certain = true | ||
or | ||
capturedCallWrite(_, bb, i, v) and certain = false | ||
} | ||
|
||
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) { | ||
|
@@ -99,6 +101,8 @@ module SsaInput implements SsaImplCommon::InputSig<Location> { | |
certain = false | ||
) | ||
or | ||
capturedCallRead(_, bb, i, v) and certain = false | ||
or | ||
capturedExitRead(bb, i, v) and certain = false | ||
} | ||
} | ||
|
@@ -145,6 +149,35 @@ private predicate variableReadActual(BasicBlock bb, int i, Variable v) { | |
) | ||
} | ||
|
||
/** | ||
* Holds if captured variable `v` is written directly inside `scope`, | ||
* or inside a (transitively) nested scope of `scope`. | ||
*/ | ||
pragma[noinline] | ||
private predicate hasCapturedWrite(Variable v, Cfg::CfgScope scope) { | ||
any(VariableWriteAccess write | write.getVariable() = v and scope = write.getEnclosingCallable*()) | ||
.isCapture() | ||
} | ||
|
||
/** | ||
* Holds if `v` is read inside basic block `bb` at index `i`, which is in the | ||
* immediate outer scope of `scope`. | ||
*/ | ||
pragma[noinline] | ||
private predicate variableReadActualInOuterScope( | ||
BasicBlock bb, int i, Variable v, Cfg::CfgScope scope | ||
) { | ||
variableReadActual(bb, i, v) and bb.getScope() = scope.getEnclosingCallable() | ||
} | ||
|
||
pragma[noinline] | ||
private predicate hasVariableReadWithCapturedWrite( | ||
BasicBlock bb, int i, Variable v, Cfg::CfgScope scope | ||
) { | ||
hasCapturedWrite(v, scope) and | ||
variableReadActualInOuterScope(bb, i, v, scope) | ||
} | ||
|
||
private predicate adjacentDefReachesRead( | ||
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2 | ||
) { | ||
|
@@ -223,6 +256,40 @@ private predicate readsCapturedVariable(BasicBlock bb, Variable v) { | |
getCapturedVariableAccess(bb, v) instanceof VariableReadAccess | ||
} | ||
|
||
/** | ||
* Holds if captured variable `v` is read directly inside `scope`, | ||
* or inside a (transitively) nested scope of `scope`. | ||
*/ | ||
pragma[noinline] | ||
private predicate hasCapturedRead(Variable v, Cfg::CfgScope scope) { | ||
any(VariableReadAccess read | read.getVariable() = v and scope = read.getEnclosingCallable*()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same |
||
.isCapture() | ||
} | ||
|
||
/** | ||
* Holds if `v` is written inside basic block `bb` at index `i`, which is in | ||
* the immediate outer scope of `scope`. | ||
*/ | ||
pragma[noinline] | ||
private predicate variableWriteInOuterScope(BasicBlock bb, int i, Variable v, Cfg::CfgScope scope) { | ||
SsaInput::variableWrite(bb, i, v, _) and scope.getEnclosingCallable() = bb.getScope() | ||
} | ||
|
||
/** | ||
* Holds if the call `call` at index `i` in basic block `bb` may reach | ||
* a callable that reads captured variable `v`. | ||
*/ | ||
private predicate capturedCallRead(CallExprBase call, BasicBlock bb, int i, Variable v) { | ||
exists(Cfg::CfgScope scope | | ||
hasCapturedRead(v, scope) and | ||
( | ||
variableWriteInOuterScope(bb, any(int j | j < i), v, scope) or | ||
variableWriteInOuterScope(bb.getAPredecessor+(), _, v, scope) | ||
) and | ||
call = bb.getNode(i).getAstNode() | ||
) | ||
} | ||
|
||
/** | ||
* Holds if a pseudo read of captured variable `v` should be inserted | ||
* at index `i` in exit block `bb`. | ||
|
@@ -245,6 +312,20 @@ private module Cached { | |
i = -1 | ||
} | ||
|
||
/** | ||
* Holds if the call `call` at index `i` in basic block `bb` may reach a callable | ||
* that writes captured variable `v`. | ||
*/ | ||
cached | ||
predicate capturedCallWrite(CallExprBase call, BasicBlock bb, int i, Variable v) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There should be no need to cache this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should I just remove the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Ruby equivalent is also cached. Is there something different about that one that causes it to need caching? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It needs to be moved out, otherwise the compiler will complain (all public declarations in a The reason why it is cached in Ruby is that it is referenced in a user-visible class. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see, thanks. I've addressed the comments :) |
||
call = bb.getNode(i).getAstNode() and | ||
exists(Cfg::CfgScope scope | | ||
hasVariableReadWithCapturedWrite(bb, any(int j | j > i), v, scope) | ||
or | ||
hasVariableReadWithCapturedWrite(bb.getASuccessor+(), _, v, scope) | ||
) | ||
} | ||
|
||
/** | ||
* Holds if `v` is written at index `i` in basic block `bb`, and the corresponding | ||
* AST write access is `write`. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be
getEnclosingCallable+
.