Add builtin function @handle() - #1297
Conversation
andrewrk
left a comment
There was a problem hiding this comment.
Thank you for starting this effort. I hope these comments help.
There was a problem hiding this comment.
in render functions in codegen.cpp it is too late - we need to put this semantic analysis and compile error in ir.cpp in the analyze_instruction_handle function. That's why that assert was there that you commented out :-)
There was a problem hiding this comment.
This is probably actually the best place to put the compile error for @handle() used outside an async function. Search for return expression outside function definition to see an example.
There was a problem hiding this comment.
Here, I think that @handle() should return a promise->T rather than just a promise, because we know the return type of the async function. If you look at the type of the variable that suspend blocks provide, it does this. You can see an example of this in ir_analyze_instruction_coro_begin.
|
Here are some more checklist items:
The self-hosted compiler does not have coroutine functionality yet, (but it does have a full parser) so you don't need to port this to stage2. |
There was a problem hiding this comment.
@andrewrk I am pretty sure that the coro_handle is stored in IrExecutable, but I am wondering how to expose it as an LLVMValueRef ? It seems to have no llvm_value.
There was a problem hiding this comment.
Solved it by LLVMBuildBitCasting executable->fn_entry->ir_executable.coro_handle->other
There was a problem hiding this comment.
Hmm. That might be ok. A more straightforward solution would probably be to use @llvm.coro.frame: http://llvm.org/docs/Coroutines.html#llvm-coro-frame-intrinsic
There was a problem hiding this comment.
To be clear, I think you can leave this as is, but if it causes problems, we'll know to try this other approach.
There was a problem hiding this comment.
Cool, I replaced it with the llvm.coro.frame which I think will give better separation between IR and codegen. I did look through the docs several times, and I am not sure why I didn't pickup on it. Thanks!
|
@andrewrk please review :-) Also, please let me know what you meant by "Remove old semantic analysis code" |
|
this code needs to be modified so that we're not putting a variable in scope: Buf *promise_symbol_name = node->data.suspend.promise_symbol->data.symbol_expr.symbol;
Scope *child_scope;
if (!buf_eql_str(promise_symbol_name, "_")) {
VariableTableEntry *promise_var = ir_create_var(irb, node, parent_scope, promise_symbol_name,
true, true, false, const_bool_false);
ir_build_var_decl(irb, parent_scope, node, promise_var, nullptr, nullptr, irb->exec->coro_handle);
child_scope = promise_var->child_scope;
} else {
child_scope = parent_scope;
}Once you update the parser you'll get a compile error for this. |
|
I think it looks good so far! Once you remove the old syntax, you'll probably have to update a few places in the standard library. If those tests still pass, that'll be a good test for this patch. |
|
Pretty sure I got everything -- running tests locally and then I will push. |
|
@andrewrk I am worried that This sometimes fails: This will always work: |
|
I'll have a look at the failure and see if I can figure out why it's happening |
This actually makes me think that my suggestion to use
It seems like a bug that LLVM would do this, and then not spill it and restore it correctly. But anyway we can work around it by having Zig store the handle in a variable secretly (which is what was happening with the old syntax). I'm happy to take this pull request from here and drive it to completion. Would you like me to do that, or would you like to keep working on it yourself? |
|
@andrewrk It looks like you reworked coroutines, so I will resolve this branch with the master and then test again. |
Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ; I removed/commented-out the assert checking for no errors since we now have some errors rendered.
Tracking Issue ziglang#1296 ; Thanks @andrewrk ;
Tracking Issue ziglang#1296 ; Thanks @andrewrk ;
Tracking Issue ziglang#1296 ; Thanks @andrewrk ;
Tracking Issue ziglang#1296 ; Thanks @andrewrk ;
Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
…ion; Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
…ndle(); Tracking Issue ziglang#1296 ;
(); Tracking Issue ziglang#1296 ;
…(); Tracking Issue ziglang#1296 ;
…); Tracking Issue ziglang#1296 ;
…); Tracking Issue ziglang#1296 ;
…ol is no in scope with suspend; Tracking Issue ziglang#1296 ;
…e promise symbol is no in scope with suspend; Tracking Issue ziglang#1296 ;
…mbol is no in scope with suspend; Tracking Issue ziglang#1296 ;
…d with @handle(); Tracking Issue ziglang#1296 ;
…ol is no in scope with suspend; Tracking Issue ziglang#1296 ;
…s no in scope with suspend; Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
|
@andrewrk I think that the |
closes #1296 ;
@handle();I am using
executable->fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsyncto check this condition.Using
@llvm.coro.frameremove
suspend |handle| {}@andrewrk Andrew, I took a crack at this because I want to learn more about zig's internals and based it off of
@frameAddress(). I learned a lot from this article.If you can help me understand the rest, I can start helping with more of the internals. :-)
Thanks