-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
C#: Move implicit entry definitions inside method bodies in SSA construction #16875
Conversation
|
||
bindingset[l1, l2] | ||
pragma[inline_late] | ||
private predicate inSameFile0(Location l1, Location l2) { l1.getFile() = l2.getFile() } |
Check warning
Code scanning / CodeQL
Candidate predicate not marked as `nomagic` Warning
inSameFile
f765570
to
f9324d1
Compare
f9324d1
to
c5c97ac
Compare
@@ -50,6 +50,27 @@ class Location extends @location { | |||
|
|||
/** Gets the 1-based column number (inclusive) where this location ends. */ | |||
final int getEndColumn() { this.hasLocationInfo(_, _, _, _, result) } | |||
|
|||
/** Holds if this location starts strictly before the specified location. */ | |||
bindingset[this, other] |
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.
Aha, so it is possible to declare bindingsets for member predicates?
Or is the bindingset just declared because you want to use the inline_late
pragma?
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.
Yes, it's needed for inline_late
.
assignableDefinitionLocalScopeVariable(result, v, c) and | ||
localScopeSourceVariable(this, v, c, _) |
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.
Did you need to force the join order for performance reasons?
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.
Yes.
predicate implicitEntryDefinition(ControlFlow::ControlFlow::BasicBlock bb, Ssa::SourceVariable v) { | ||
exists(ControlFlow::ControlFlow::BasicBlocks::EntryBlock entry, Callable c | | ||
c = entry.getCallable() and | ||
// In case `c` has multiple bodies, we want each body to gets its own implicit |
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.
nit: get its own
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.
Thanks, I'll fix follow-up on another PR to avoid having to wait for CI.
} | ||
|
||
override Location getLocation() { | ||
not NearestLocation<NearestLocationInput>::nearestLocation(this, _, _) and |
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.
Why doesn't this give us the exact location whe the is only a single implementation?
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.
Because the
not def.getBasicBlock() instanceof ControlFlow::BasicBlocks::EntryBlock
constraint in NearestLocationInput::relevantLocations/3
restricts the logic to multi-bodied methods.
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.
Looks plausible to me!
Methods with multiple implementations such as
give rise to a single CFG, where flow splits immediately following the special entry node:
Before this PR, implicit entry SSA definitions (such as for parameters) were placed at the
enter M
node, meaning that all implementation bodies would share those definitions. However, in #16817 we would like to be able to differentiate between the method bodies, and this PR consequently moves the implicit entry definitions into the basic blocks that start each method body (i.e., theaccess to parameter x
nodes above).Note that single-bodied methods (which is the far most common case) will still have the implicit entry SSA definitions at the entry nodes, since the basic block for the method body entry is the same as the basic block for the special entry node.