-
-
Notifications
You must be signed in to change notification settings - Fork 2.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
Add builtin function @handle() #1297
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.
Thank you for starting this effort. I hope these comments help.
src/codegen.cpp
Outdated
executable->fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; | ||
|
||
if (!is_async || !executable->coro_handle) { | ||
add_node_error(g, instruction->base.source_node, buf_sprintf("@handle() in non-async function")); |
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.
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 :-)
src/ir.cpp
Outdated
@@ -4448,6 +4463,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | |||
return ir_lval_wrap(irb, scope, ir_build_return_address(irb, scope, node), lval); | |||
case BuiltinFnIdFrameAddress: | |||
return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval); | |||
case BuiltinFnIdHandle: | |||
return ir_lval_wrap(irb, scope, ir_build_handle(irb, scope, node), lval); |
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.
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.
src/ir.cpp
Outdated
static TypeTableEntry *ir_analyze_instruction_handle(IrAnalyze *ira, IrInstructionHandle *instruction) { | ||
ir_build_handle_from(&ira->new_irb, &instruction->base); | ||
|
||
TypeTableEntry *promise_type = get_promise_type(ira->codegen, nullptr); |
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.
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. |
src/codegen.cpp
Outdated
@@ -4146,6 +4146,12 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutable *executable | |||
return LLVMBuildCall(g->builder, get_frame_address_fn_val(g), &zero, 1, ""); | |||
} | |||
|
|||
static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutable *executable, |
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.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solved it by LLVMBuildBitCast
ing executable->fn_entry->ir_executable.coro_handle->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.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 ;
d7123d2
to
ff4a03f
Compare
Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
Tracking Issue ziglang#1296 ;
closes #1296 ;
@handle();
I am using
executable->fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync
to check this condition.Using
@llvm.coro.frame
remove
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