| author | |
| committer | |
| log | 70bced5dcffccc2f8029d8c3d7f2d18b48d993f5 |
| tree | 17672a7a6787d9de275d6cad00b9854ea168e409 |
| parent | ead2d32be871411685f846e604ec7e4253b9f25a |
| signature |
6 files changed, 96 insertions(+), 36 deletions(-)
BRANCH_TODO created+4| ... | ... | @@ -0,0 +1,4 @@ |
| 1 | * await | |
| 2 | * await of a non async function | |
| 3 | * async call on a non async function | |
| 4 | * safety for resuming when it is awaiting |
src/all_types.hpp+12-4| ... | ... | @@ -1435,8 +1435,6 @@ enum BuiltinFnId { |
| 1435 | 1435 | BuiltinFnIdErrName, |
| 1436 | 1436 | BuiltinFnIdBreakpoint, |
| 1437 | 1437 | BuiltinFnIdReturnAddress, |
| 1438 | BuiltinFnIdFrameAddress, | |
| 1439 | BuiltinFnIdHandle, | |
| 1440 | 1438 | BuiltinFnIdEmbedFile, |
| 1441 | 1439 | BuiltinFnIdCmpxchgWeak, |
| 1442 | 1440 | BuiltinFnIdCmpxchgStrong, |
| ... | ... | @@ -1507,6 +1505,9 @@ enum BuiltinFnId { |
| 1507 | 1505 | BuiltinFnIdAtomicLoad, |
| 1508 | 1506 | BuiltinFnIdHasDecl, |
| 1509 | 1507 | BuiltinFnIdUnionInit, |
| 1508 | BuiltinFnIdFrameAddress, | |
| 1509 | BuiltinFnIdFrameType, | |
| 1510 | BuiltinFnIdFrameHandle, | |
| 1510 | 1511 | }; |
| 1511 | 1512 | |
| 1512 | 1513 | struct BuiltinFnEntry { |
| ... | ... | @@ -2252,7 +2253,8 @@ enum IrInstructionId { |
| 2252 | 2253 | IrInstructionIdBreakpoint, |
| 2253 | 2254 | IrInstructionIdReturnAddress, |
| 2254 | 2255 | IrInstructionIdFrameAddress, |
| 2255 | IrInstructionIdHandle, | |
| 2256 | IrInstructionIdFrameHandle, | |
| 2257 | IrInstructionIdFrameType, | |
| 2256 | 2258 | IrInstructionIdAlignOf, |
| 2257 | 2259 | IrInstructionIdOverflowOp, |
| 2258 | 2260 | IrInstructionIdTestErrSrc, |
| ... | ... | @@ -3038,8 +3040,14 @@ struct IrInstructionFrameAddress { |
| 3038 | 3040 | IrInstruction base; |
| 3039 | 3041 | }; |
| 3040 | 3042 | |
| 3041 | struct IrInstructionHandle { | |
| 3043 | struct IrInstructionFrameHandle { | |
| 3044 | IrInstruction base; | |
| 3045 | }; | |
| 3046 | ||
| 3047 | struct IrInstructionFrameType { | |
| 3042 | 3048 | IrInstruction base; |
| 3049 | ||
| 3050 | IrInstruction *fn; | |
| 3043 | 3051 | }; |
| 3044 | 3052 | |
| 3045 | 3053 | enum IrOverflowOp { |
src/codegen.cpp+8-8| ... | ... | @@ -4457,10 +4457,8 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutable *executable |
| 4457 | 4457 | return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, ""); |
| 4458 | 4458 | } |
| 4459 | 4459 | |
| 4460 | static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutable *executable, | |
| 4461 | IrInstructionHandle *instruction) | |
| 4462 | { | |
| 4463 | zig_panic("TODO @handle() codegen"); | |
| 4460 | static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutable *executable, IrInstructionFrameHandle *instruction) { | |
| 4461 | return g->cur_ret_ptr; | |
| 4464 | 4462 | } |
| 4465 | 4463 | |
| 4466 | 4464 | static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstructionOverflowOp *instruction) { |
| ... | ... | @@ -5008,6 +5006,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5008 | 5006 | case IrInstructionIdBitCastSrc: |
| 5009 | 5007 | case IrInstructionIdTestErrSrc: |
| 5010 | 5008 | case IrInstructionIdUnionInitNamedField: |
| 5009 | case IrInstructionIdFrameType: | |
| 5011 | 5010 | zig_unreachable(); |
| 5012 | 5011 | |
| 5013 | 5012 | case IrInstructionIdDeclVarGen: |
| ... | ... | @@ -5086,8 +5085,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5086 | 5085 | return ir_render_return_address(g, executable, (IrInstructionReturnAddress *)instruction); |
| 5087 | 5086 | case IrInstructionIdFrameAddress: |
| 5088 | 5087 | return ir_render_frame_address(g, executable, (IrInstructionFrameAddress *)instruction); |
| 5089 | case IrInstructionIdHandle: | |
| 5090 | return ir_render_handle(g, executable, (IrInstructionHandle *)instruction); | |
| 5088 | case IrInstructionIdFrameHandle: | |
| 5089 | return ir_render_handle(g, executable, (IrInstructionFrameHandle *)instruction); | |
| 5091 | 5090 | case IrInstructionIdOverflowOp: |
| 5092 | 5091 | return ir_render_overflow_op(g, executable, (IrInstructionOverflowOp *)instruction); |
| 5093 | 5092 | case IrInstructionIdTestErrGen: |
| ... | ... | @@ -6754,8 +6753,6 @@ static BuiltinFnEntry *create_builtin_fn(CodeGen *g, BuiltinFnId id, const char |
| 6754 | 6753 | static void define_builtin_fns(CodeGen *g) { |
| 6755 | 6754 | create_builtin_fn(g, BuiltinFnIdBreakpoint, "breakpoint", 0); |
| 6756 | 6755 | create_builtin_fn(g, BuiltinFnIdReturnAddress, "returnAddress", 0); |
| 6757 | create_builtin_fn(g, BuiltinFnIdFrameAddress, "frameAddress", 0); | |
| 6758 | create_builtin_fn(g, BuiltinFnIdHandle, "handle", 0); | |
| 6759 | 6756 | create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy", 3); |
| 6760 | 6757 | create_builtin_fn(g, BuiltinFnIdMemset, "memset", 3); |
| 6761 | 6758 | create_builtin_fn(g, BuiltinFnIdSizeof, "sizeOf", 1); |
| ... | ... | @@ -6856,6 +6853,9 @@ static void define_builtin_fns(CodeGen *g) { |
| 6856 | 6853 | create_builtin_fn(g, BuiltinFnIdThis, "This", 0); |
| 6857 | 6854 | create_builtin_fn(g, BuiltinFnIdHasDecl, "hasDecl", 2); |
| 6858 | 6855 | create_builtin_fn(g, BuiltinFnIdUnionInit, "unionInit", 3); |
| 6856 | create_builtin_fn(g, BuiltinFnIdFrameHandle, "frame", 0); | |
| 6857 | create_builtin_fn(g, BuiltinFnIdFrameType, "Frame", 1); | |
| 6858 | create_builtin_fn(g, BuiltinFnIdFrameAddress, "frameAddress", 0); | |
| 6859 | 6859 | } |
| 6860 | 6860 | |
| 6861 | 6861 | static const char *bool_to_str(bool b) { |
src/ir.cpp+51-20| ... | ... | @@ -755,8 +755,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameAddress *) |
| 755 | 755 | return IrInstructionIdFrameAddress; |
| 756 | 756 | } |
| 757 | 757 | |
| 758 | static constexpr IrInstructionId ir_instruction_id(IrInstructionHandle *) { | |
| 759 | return IrInstructionIdHandle; | |
| 758 | static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameHandle *) { | |
| 759 | return IrInstructionIdFrameHandle; | |
| 760 | } | |
| 761 | ||
| 762 | static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameType *) { | |
| 763 | return IrInstructionIdFrameType; | |
| 760 | 764 | } |
| 761 | 765 | |
| 762 | 766 | static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignOf *) { |
| ... | ... | @@ -2362,7 +2366,16 @@ static IrInstruction *ir_build_frame_address(IrBuilder *irb, Scope *scope, AstNo |
| 2362 | 2366 | } |
| 2363 | 2367 | |
| 2364 | 2368 | static IrInstruction *ir_build_handle(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 2365 | IrInstructionHandle *instruction = ir_build_instruction<IrInstructionHandle>(irb, scope, source_node); | |
| 2369 | IrInstructionFrameHandle *instruction = ir_build_instruction<IrInstructionFrameHandle>(irb, scope, source_node); | |
| 2370 | return &instruction->base; | |
| 2371 | } | |
| 2372 | ||
| 2373 | static IrInstruction *ir_build_frame_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *fn) { | |
| 2374 | IrInstructionFrameType *instruction = ir_build_instruction<IrInstructionFrameType>(irb, scope, source_node); | |
| 2375 | instruction->fn = fn; | |
| 2376 | ||
| 2377 | ir_ref_instruction(fn, irb->current_basic_block); | |
| 2378 | ||
| 2366 | 2379 | return &instruction->base; |
| 2367 | 2380 | } |
| 2368 | 2381 | |
| ... | ... | @@ -3358,11 +3371,6 @@ static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) { |
| 3358 | 3371 | return nullptr; |
| 3359 | 3372 | } |
| 3360 | 3373 | |
| 3361 | static bool exec_is_async(IrExecutable *exec) { | |
| 3362 | ZigFn *fn_entry = exec_fn_entry(exec); | |
| 3363 | return fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; | |
| 3364 | } | |
| 3365 | ||
| 3366 | 3374 | static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode *node, IrInstruction *return_value, |
| 3367 | 3375 | bool is_generated_code) |
| 3368 | 3376 | { |
| ... | ... | @@ -4278,8 +4286,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4278 | 4286 | return irb->codegen->invalid_instruction; |
| 4279 | 4287 | } |
| 4280 | 4288 | |
| 4281 | bool is_async = exec_is_async(irb->exec); | |
| 4282 | ||
| 4283 | 4289 | switch (builtin_fn->id) { |
| 4284 | 4290 | case BuiltinFnIdInvalid: |
| 4285 | 4291 | zig_unreachable(); |
| ... | ... | @@ -4902,16 +4908,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4902 | 4908 | return ir_lval_wrap(irb, scope, ir_build_return_address(irb, scope, node), lval, result_loc); |
| 4903 | 4909 | case BuiltinFnIdFrameAddress: |
| 4904 | 4910 | return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval, result_loc); |
| 4905 | case BuiltinFnIdHandle: | |
| 4911 | case BuiltinFnIdFrameHandle: | |
| 4906 | 4912 | if (!irb->exec->fn_entry) { |
| 4907 | 4913 | add_node_error(irb->codegen, node, buf_sprintf("@handle() called outside of function definition")); |
| 4908 | 4914 | return irb->codegen->invalid_instruction; |
| 4909 | 4915 | } |
| 4910 | if (!is_async) { | |
| 4911 | add_node_error(irb->codegen, node, buf_sprintf("@handle() in non-async function")); | |
| 4912 | return irb->codegen->invalid_instruction; | |
| 4913 | } | |
| 4914 | 4916 | return ir_lval_wrap(irb, scope, ir_build_handle(irb, scope, node), lval, result_loc); |
| 4917 | case BuiltinFnIdFrameType: { | |
| 4918 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | |
| 4919 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | |
| 4920 | if (arg0_value == irb->codegen->invalid_instruction) | |
| 4921 | return arg0_value; | |
| 4922 | ||
| 4923 | IrInstruction *frame_type = ir_build_frame_type(irb, scope, node, arg0_value); | |
| 4924 | return ir_lval_wrap(irb, scope, frame_type, lval, result_loc); | |
| 4925 | } | |
| 4915 | 4926 | case BuiltinFnIdAlignOf: |
| 4916 | 4927 | { |
| 4917 | 4928 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| ... | ... | @@ -21726,8 +21737,25 @@ static IrInstruction *ir_analyze_instruction_frame_address(IrAnalyze *ira, IrIns |
| 21726 | 21737 | return result; |
| 21727 | 21738 | } |
| 21728 | 21739 | |
| 21729 | static IrInstruction *ir_analyze_instruction_handle(IrAnalyze *ira, IrInstructionHandle *instruction) { | |
| 21730 | zig_panic("TODO anlayze @handle()"); | |
| 21740 | static IrInstruction *ir_analyze_instruction_frame_handle(IrAnalyze *ira, IrInstructionFrameHandle *instruction) { | |
| 21741 | ZigFn *fn = exec_fn_entry(ira->new_irb.exec); | |
| 21742 | ir_assert(fn != nullptr, &instruction->base); | |
| 21743 | ||
| 21744 | ZigType *frame_type = get_coro_frame_type(ira->codegen, fn); | |
| 21745 | ZigType *ptr_frame_type = get_pointer_to_type(ira->codegen, frame_type, false); | |
| 21746 | ||
| 21747 | IrInstruction *result = ir_build_handle(&ira->new_irb, instruction->base.scope, instruction->base.source_node); | |
| 21748 | result->value.type = ptr_frame_type; | |
| 21749 | return result; | |
| 21750 | } | |
| 21751 | ||
| 21752 | static IrInstruction *ir_analyze_instruction_frame_type(IrAnalyze *ira, IrInstructionFrameType *instruction) { | |
| 21753 | ZigFn *fn = ir_resolve_fn(ira, instruction->fn->child); | |
| 21754 | if (fn == nullptr) | |
| 21755 | return ira->codegen->invalid_instruction; | |
| 21756 | ||
| 21757 | ZigType *ty = get_coro_frame_type(ira->codegen, fn); | |
| 21758 | return ir_const_type(ira, &instruction->base, ty); | |
| 21731 | 21759 | } |
| 21732 | 21760 | |
| 21733 | 21761 | static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) { |
| ... | ... | @@ -24355,8 +24383,10 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction |
| 24355 | 24383 | return ir_analyze_instruction_return_address(ira, (IrInstructionReturnAddress *)instruction); |
| 24356 | 24384 | case IrInstructionIdFrameAddress: |
| 24357 | 24385 | return ir_analyze_instruction_frame_address(ira, (IrInstructionFrameAddress *)instruction); |
| 24358 | case IrInstructionIdHandle: | |
| 24359 | return ir_analyze_instruction_handle(ira, (IrInstructionHandle *)instruction); | |
| 24386 | case IrInstructionIdFrameHandle: | |
| 24387 | return ir_analyze_instruction_frame_handle(ira, (IrInstructionFrameHandle *)instruction); | |
| 24388 | case IrInstructionIdFrameType: | |
| 24389 | return ir_analyze_instruction_frame_type(ira, (IrInstructionFrameType *)instruction); | |
| 24360 | 24390 | case IrInstructionIdAlignOf: |
| 24361 | 24391 | return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction); |
| 24362 | 24392 | case IrInstructionIdOverflowOp: |
| ... | ... | @@ -24650,7 +24680,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 24650 | 24680 | case IrInstructionIdAlignOf: |
| 24651 | 24681 | case IrInstructionIdReturnAddress: |
| 24652 | 24682 | case IrInstructionIdFrameAddress: |
| 24653 | case IrInstructionIdHandle: | |
| 24683 | case IrInstructionIdFrameHandle: | |
| 24684 | case IrInstructionIdFrameType: | |
| 24654 | 24685 | case IrInstructionIdTestErrSrc: |
| 24655 | 24686 | case IrInstructionIdTestErrGen: |
| 24656 | 24687 | case IrInstructionIdFnProto: |
src/ir_print.cpp+13-4| ... | ... | @@ -906,8 +906,14 @@ static void ir_print_frame_address(IrPrint *irp, IrInstructionFrameAddress *inst |
| 906 | 906 | fprintf(irp->f, "@frameAddress()"); |
| 907 | 907 | } |
| 908 | 908 | |
| 909 | static void ir_print_handle(IrPrint *irp, IrInstructionHandle *instruction) { | |
| 910 | fprintf(irp->f, "@handle()"); | |
| 909 | static void ir_print_handle(IrPrint *irp, IrInstructionFrameHandle *instruction) { | |
| 910 | fprintf(irp->f, "@frame()"); | |
| 911 | } | |
| 912 | ||
| 913 | static void ir_print_frame_type(IrPrint *irp, IrInstructionFrameType *instruction) { | |
| 914 | fprintf(irp->f, "@Frame("); | |
| 915 | ir_print_other_instruction(irp, instruction->fn); | |
| 916 | fprintf(irp->f, ")"); | |
| 911 | 917 | } |
| 912 | 918 | |
| 913 | 919 | static void ir_print_return_address(IrPrint *irp, IrInstructionReturnAddress *instruction) { |
| ... | ... | @@ -1764,8 +1770,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1764 | 1770 | case IrInstructionIdFrameAddress: |
| 1765 | 1771 | ir_print_frame_address(irp, (IrInstructionFrameAddress *)instruction); |
| 1766 | 1772 | break; |
| 1767 | case IrInstructionIdHandle: | |
| 1768 | ir_print_handle(irp, (IrInstructionHandle *)instruction); | |
| 1773 | case IrInstructionIdFrameHandle: | |
| 1774 | ir_print_handle(irp, (IrInstructionFrameHandle *)instruction); | |
| 1775 | break; | |
| 1776 | case IrInstructionIdFrameType: | |
| 1777 | ir_print_frame_type(irp, (IrInstructionFrameType *)instruction); | |
| 1769 | 1778 | break; |
| 1770 | 1779 | case IrInstructionIdAlignOf: |
| 1771 | 1780 | ir_print_align_of(irp, (IrInstructionAlignOf *)instruction); |
test/stage1/behavior/coroutines.zig+8| ... | ... | @@ -79,15 +79,23 @@ test "local variable in async function" { |
| 79 | 79 | |
| 80 | 80 | test "calling an inferred async function" { |
| 81 | 81 | const S = struct { |
| 82 | var x: i32 = 1; | |
| 83 | var other_frame: *@Frame(other) = undefined; | |
| 84 | ||
| 82 | 85 | fn doTheTest() void { |
| 83 | 86 | const p = async first(); |
| 87 | expect(x == 1); | |
| 88 | resume other_frame.*; | |
| 89 | expect(x == 2); | |
| 84 | 90 | } |
| 85 | 91 | |
| 86 | 92 | fn first() void { |
| 87 | 93 | other(); |
| 88 | 94 | } |
| 89 | 95 | fn other() void { |
| 96 | other_frame = @frame(); | |
| 90 | 97 | suspend; |
| 98 | x += 1; | |
| 91 | 99 | } |
| 92 | 100 | }; |
| 93 | 101 | S.doTheTest(); |