-
Notifications
You must be signed in to change notification settings - Fork 1.8k
C++: Placeholder CFG for coroutines #16187
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
Conversation
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.
Two questions about this.
// TODO: Use a new opcode to represent "awaiting the value" | ||
expr instanceof CoAwaitExpr and result instanceof Opcode::CopyValue | ||
or | ||
// TODO: Use a new opcode to represent "awaiting the value" |
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.
Shouldn't this be:
// TODO: Use a new opcode to represent "awaiting the value" | |
// TODO: Use a new opcode to represent "yielding a value" |
?
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.
Actually no. co_yield
is just syntactic sugar for:
co_await promise.yield_value(expr)
(see here) and the "yielding" is done by the call to yield_value
.
So whatever instruction we come up with to use the above TODO should also be used here since a co_yield
ultimately does something equivalent to a special kind of co_await
.
#-----| m0_9(promise_type) = Chi : total:m87_14, partial:m0_8 | ||
# 88| v88_1(void) = NoOp : | ||
#-----| v0_10(void) = NoOp : | ||
#-----| Goto (back edge) -> Block 1 |
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.
I'm somewhat confused by this. Why are there two blocks here and why is this Goto marked as a back edge?
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.
Oh, I didn't spot this either. I'm also confused by this. Will investigate!
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.
I should've checked the raw IR before opening this PR >.< The IR is still very messed up! I'll fix that
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! I've found the problem:
private predicate foo(UnaryOperation uo) {
not exists(uo.getOperand())
}
has 4 results in the co_return_void
function 🤔 So I think there's some extractor issue going on here.
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.
I've created an issue for this now.
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 (I'm out of my depth this deep in the IR).
@@ -1501,3 +1501,41 @@ class TranslatedVlaDeclarationStmt extends TranslatedStmt { | |||
|
|||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() } | |||
} | |||
|
|||
class TranslatedCoReturnStmt extends TranslatedStmt { | |||
override CoReturnStmt stmt; |
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.
I did not know you can do this (override the type of a member variable in QL).
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.
It's extremely useful! We do it a lot in both C/C++ IR construction and in the Swift CFG construction code
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.
LGTM.
This PR adds CFG support for C++20 coroutines. It's basically complete, except for the fact that we don't yet have an instruction to represent "awaiting a value". So instead we're simply emitting a
NoOp
instruction for now.Eventually, that
NoOp
instruction should be replaced with a new instruction, and subsequent analyses should decide what to do with it. (For example, dataflow should use field flow to ensure that yielded values propagate to the caller.)Commit-by-commit review recommended.