| author | |
| committer | |
| log | 538c0cd2250e08aad07784355b402cfae6145507 |
| tree | a7d3de300e1580addd4e457d9a51e364355ff083 |
| parent | 70bced5dcffccc2f8029d8c3d7f2d18b48d993f5 |
| signature | Commit is signed but in an unrecognized format. |
6 files changed, 142 insertions(+), 4 deletions(-)
BRANCH_TODO+1| ... | ... | @@ -2,3 +2,4 @@ |
| 2 | 2 | * await of a non async function |
| 3 | 3 | * async call on a non async function |
| 4 | 4 | * safety for resuming when it is awaiting |
| 5 | * implicit cast of normal function to async function should be allowed when it is inferred to be async |
src/all_types.hpp+16| ... | ... | @@ -1508,6 +1508,7 @@ enum BuiltinFnId { |
| 1508 | 1508 | BuiltinFnIdFrameAddress, |
| 1509 | 1509 | BuiltinFnIdFrameType, |
| 1510 | 1510 | BuiltinFnIdFrameHandle, |
| 1511 | BuiltinFnIdFrameSize, | |
| 1511 | 1512 | }; |
| 1512 | 1513 | |
| 1513 | 1514 | struct BuiltinFnEntry { |
| ... | ... | @@ -2255,6 +2256,8 @@ enum IrInstructionId { |
| 2255 | 2256 | IrInstructionIdFrameAddress, |
| 2256 | 2257 | IrInstructionIdFrameHandle, |
| 2257 | 2258 | IrInstructionIdFrameType, |
| 2259 | IrInstructionIdFrameSizeSrc, | |
| 2260 | IrInstructionIdFrameSizeGen, | |
| 2258 | 2261 | IrInstructionIdAlignOf, |
| 2259 | 2262 | IrInstructionIdOverflowOp, |
| 2260 | 2263 | IrInstructionIdTestErrSrc, |
| ... | ... | @@ -3050,6 +3053,19 @@ struct IrInstructionFrameType { |
| 3050 | 3053 | IrInstruction *fn; |
| 3051 | 3054 | }; |
| 3052 | 3055 | |
| 3056 | struct IrInstructionFrameSizeSrc { | |
| 3057 | IrInstruction base; | |
| 3058 | ||
| 3059 | IrInstruction *fn; | |
| 3060 | }; | |
| 3061 | ||
| 3062 | struct IrInstructionFrameSizeGen { | |
| 3063 | IrInstruction base; | |
| 3064 | ||
| 3065 | IrInstruction *fn; | |
| 3066 | IrInstruction *frame_ptr; | |
| 3067 | }; | |
| 3068 | ||
| 3053 | 3069 | enum IrOverflowOp { |
| 3054 | 3070 | IrOverflowOpAdd, |
| 3055 | 3071 | IrOverflowOpSub, |
src/codegen.cpp+13| ... | ... | @@ -4914,6 +4914,15 @@ static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, |
| 4914 | 4914 | return nullptr; |
| 4915 | 4915 | } |
| 4916 | 4916 | |
| 4917 | static LLVMValueRef ir_render_frame_size(CodeGen *g, IrExecutable *executable, IrInstructionFrameSizeGen *instruction) { | |
| 4918 | LLVMValueRef fn_val = ir_llvm_value(g, instruction->fn); | |
| 4919 | LLVMValueRef frame_ptr = ir_llvm_value(g, instruction->frame_ptr); | |
| 4920 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, frame_ptr, coro_resume_index_index, ""); | |
| 4921 | LLVMValueRef one = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 1, false); | |
| 4922 | LLVMBuildStore(g->builder, one, resume_index_ptr); | |
| 4923 | return ZigLLVMBuildCall(g->builder, fn_val, &frame_ptr, 1, LLVMFastCallConv, ZigLLVM_FnInlineAuto, ""); | |
| 4924 | } | |
| 4925 | ||
| 4917 | 4926 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { |
| 4918 | 4927 | AstNode *source_node = instruction->source_node; |
| 4919 | 4928 | Scope *scope = instruction->scope; |
| ... | ... | @@ -5007,6 +5016,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5007 | 5016 | case IrInstructionIdTestErrSrc: |
| 5008 | 5017 | case IrInstructionIdUnionInitNamedField: |
| 5009 | 5018 | case IrInstructionIdFrameType: |
| 5019 | case IrInstructionIdFrameSizeSrc: | |
| 5010 | 5020 | zig_unreachable(); |
| 5011 | 5021 | |
| 5012 | 5022 | case IrInstructionIdDeclVarGen: |
| ... | ... | @@ -5161,6 +5171,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5161 | 5171 | return ir_render_suspend_br(g, executable, (IrInstructionSuspendBr *)instruction); |
| 5162 | 5172 | case IrInstructionIdCoroResume: |
| 5163 | 5173 | return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction); |
| 5174 | case IrInstructionIdFrameSizeGen: | |
| 5175 | return ir_render_frame_size(g, executable, (IrInstructionFrameSizeGen *)instruction); | |
| 5164 | 5176 | } |
| 5165 | 5177 | zig_unreachable(); |
| 5166 | 5178 | } |
| ... | ... | @@ -6856,6 +6868,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 6856 | 6868 | create_builtin_fn(g, BuiltinFnIdFrameHandle, "frame", 0); |
| 6857 | 6869 | create_builtin_fn(g, BuiltinFnIdFrameType, "Frame", 1); |
| 6858 | 6870 | create_builtin_fn(g, BuiltinFnIdFrameAddress, "frameAddress", 0); |
| 6871 | create_builtin_fn(g, BuiltinFnIdFrameSize, "frameSize", 1); | |
| 6859 | 6872 | } |
| 6860 | 6873 | |
| 6861 | 6874 | static const char *bool_to_str(bool b) { |
src/ir.cpp+66-4| ... | ... | @@ -763,6 +763,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameType *) { |
| 763 | 763 | return IrInstructionIdFrameType; |
| 764 | 764 | } |
| 765 | 765 | |
| 766 | static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameSizeSrc *) { | |
| 767 | return IrInstructionIdFrameSizeSrc; | |
| 768 | } | |
| 769 | ||
| 770 | static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameSizeGen *) { | |
| 771 | return IrInstructionIdFrameSizeGen; | |
| 772 | } | |
| 773 | ||
| 766 | 774 | static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignOf *) { |
| 767 | 775 | return IrInstructionIdAlignOf; |
| 768 | 776 | } |
| ... | ... | @@ -2379,6 +2387,28 @@ static IrInstruction *ir_build_frame_type(IrBuilder *irb, Scope *scope, AstNode |
| 2379 | 2387 | return &instruction->base; |
| 2380 | 2388 | } |
| 2381 | 2389 | |
| 2390 | static IrInstruction *ir_build_frame_size_src(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *fn) { | |
| 2391 | IrInstructionFrameSizeSrc *instruction = ir_build_instruction<IrInstructionFrameSizeSrc>(irb, scope, source_node); | |
| 2392 | instruction->fn = fn; | |
| 2393 | ||
| 2394 | ir_ref_instruction(fn, irb->current_basic_block); | |
| 2395 | ||
| 2396 | return &instruction->base; | |
| 2397 | } | |
| 2398 | ||
| 2399 | static IrInstruction *ir_build_frame_size_gen(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *fn, | |
| 2400 | IrInstruction *frame_ptr) | |
| 2401 | { | |
| 2402 | IrInstructionFrameSizeGen *instruction = ir_build_instruction<IrInstructionFrameSizeGen>(irb, scope, source_node); | |
| 2403 | instruction->fn = fn; | |
| 2404 | instruction->frame_ptr = frame_ptr; | |
| 2405 | ||
| 2406 | ir_ref_instruction(fn, irb->current_basic_block); | |
| 2407 | ir_ref_instruction(frame_ptr, irb->current_basic_block); | |
| 2408 | ||
| 2409 | return &instruction->base; | |
| 2410 | } | |
| 2411 | ||
| 2382 | 2412 | static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2383 | 2413 | IrOverflowOp op, IrInstruction *type_value, IrInstruction *op1, IrInstruction *op2, |
| 2384 | 2414 | IrInstruction *result_ptr, ZigType *result_ptr_type) |
| ... | ... | @@ -4923,6 +4953,15 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4923 | 4953 | IrInstruction *frame_type = ir_build_frame_type(irb, scope, node, arg0_value); |
| 4924 | 4954 | return ir_lval_wrap(irb, scope, frame_type, lval, result_loc); |
| 4925 | 4955 | } |
| 4956 | case BuiltinFnIdFrameSize: { | |
| 4957 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | |
| 4958 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | |
| 4959 | if (arg0_value == irb->codegen->invalid_instruction) | |
| 4960 | return arg0_value; | |
| 4961 | ||
| 4962 | IrInstruction *frame_size = ir_build_frame_size_src(irb, scope, node, arg0_value); | |
| 4963 | return ir_lval_wrap(irb, scope, frame_size, lval, result_loc); | |
| 4964 | } | |
| 4926 | 4965 | case BuiltinFnIdAlignOf: |
| 4927 | 4966 | { |
| 4928 | 4967 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| ... | ... | @@ -21758,6 +21797,28 @@ static IrInstruction *ir_analyze_instruction_frame_type(IrAnalyze *ira, IrInstru |
| 21758 | 21797 | return ir_const_type(ira, &instruction->base, ty); |
| 21759 | 21798 | } |
| 21760 | 21799 | |
| 21800 | static IrInstruction *ir_analyze_instruction_frame_size(IrAnalyze *ira, IrInstructionFrameSizeSrc *instruction) { | |
| 21801 | IrInstruction *fn = instruction->fn->child; | |
| 21802 | if (type_is_invalid(fn->value.type)) | |
| 21803 | return ira->codegen->invalid_instruction; | |
| 21804 | ||
| 21805 | if (fn->value.type->id != ZigTypeIdFn) { | |
| 21806 | ir_add_error(ira, fn, | |
| 21807 | buf_sprintf("expected function, found '%s'", buf_ptr(&fn->value.type->name))); | |
| 21808 | return ira->codegen->invalid_instruction; | |
| 21809 | } | |
| 21810 | ||
| 21811 | IrInstruction *frame_ptr = ir_resolve_result(ira, &instruction->base, no_result_loc(), | |
| 21812 | ira->codegen->builtin_types.entry_frame_header, nullptr, true, false); | |
| 21813 | if (frame_ptr != nullptr && (type_is_invalid(frame_ptr->value.type) || instr_is_unreachable(frame_ptr))) | |
| 21814 | return frame_ptr; | |
| 21815 | ||
| 21816 | IrInstruction *result = ir_build_frame_size_gen(&ira->new_irb, instruction->base.scope, | |
| 21817 | instruction->base.source_node, fn, frame_ptr); | |
| 21818 | result->value.type = ira->codegen->builtin_types.entry_usize; | |
| 21819 | return result; | |
| 21820 | } | |
| 21821 | ||
| 21761 | 21822 | static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) { |
| 21762 | 21823 | Error err; |
| 21763 | 21824 | IrInstruction *type_value = instruction->type_value->child; |
| ... | ... | @@ -22348,10 +22409,6 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct |
| 22348 | 22409 | return ira->codegen->invalid_instruction; |
| 22349 | 22410 | } |
| 22350 | 22411 | |
| 22351 | if (fn_type_id.cc == CallingConventionAsync) { | |
| 22352 | zig_panic("TODO"); | |
| 22353 | } | |
| 22354 | ||
| 22355 | 22412 | return ir_const_type(ira, &instruction->base, get_fn_type(ira->codegen, &fn_type_id)); |
| 22356 | 22413 | } |
| 22357 | 22414 | |
| ... | ... | @@ -24237,6 +24294,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction |
| 24237 | 24294 | case IrInstructionIdSliceGen: |
| 24238 | 24295 | case IrInstructionIdRefGen: |
| 24239 | 24296 | case IrInstructionIdTestErrGen: |
| 24297 | case IrInstructionIdFrameSizeGen: | |
| 24240 | 24298 | zig_unreachable(); |
| 24241 | 24299 | |
| 24242 | 24300 | case IrInstructionIdReturn: |
| ... | ... | @@ -24387,6 +24445,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction |
| 24387 | 24445 | return ir_analyze_instruction_frame_handle(ira, (IrInstructionFrameHandle *)instruction); |
| 24388 | 24446 | case IrInstructionIdFrameType: |
| 24389 | 24447 | return ir_analyze_instruction_frame_type(ira, (IrInstructionFrameType *)instruction); |
| 24448 | case IrInstructionIdFrameSizeSrc: | |
| 24449 | return ir_analyze_instruction_frame_size(ira, (IrInstructionFrameSizeSrc *)instruction); | |
| 24390 | 24450 | case IrInstructionIdAlignOf: |
| 24391 | 24451 | return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction); |
| 24392 | 24452 | case IrInstructionIdOverflowOp: |
| ... | ... | @@ -24682,6 +24742,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 24682 | 24742 | case IrInstructionIdFrameAddress: |
| 24683 | 24743 | case IrInstructionIdFrameHandle: |
| 24684 | 24744 | case IrInstructionIdFrameType: |
| 24745 | case IrInstructionIdFrameSizeSrc: | |
| 24746 | case IrInstructionIdFrameSizeGen: | |
| 24685 | 24747 | case IrInstructionIdTestErrSrc: |
| 24686 | 24748 | case IrInstructionIdTestErrGen: |
| 24687 | 24749 | case IrInstructionIdFnProto: |
src/ir_print.cpp+20| ... | ... | @@ -916,6 +916,20 @@ static void ir_print_frame_type(IrPrint *irp, IrInstructionFrameType *instructio |
| 916 | 916 | fprintf(irp->f, ")"); |
| 917 | 917 | } |
| 918 | 918 | |
| 919 | static void ir_print_frame_size_src(IrPrint *irp, IrInstructionFrameSizeSrc *instruction) { | |
| 920 | fprintf(irp->f, "@frameSize("); | |
| 921 | ir_print_other_instruction(irp, instruction->fn); | |
| 922 | fprintf(irp->f, ")"); | |
| 923 | } | |
| 924 | ||
| 925 | static void ir_print_frame_size_gen(IrPrint *irp, IrInstructionFrameSizeGen *instruction) { | |
| 926 | fprintf(irp->f, "@frameSize("); | |
| 927 | ir_print_other_instruction(irp, instruction->fn); | |
| 928 | fprintf(irp->f, ","); | |
| 929 | ir_print_other_instruction(irp, instruction->frame_ptr); | |
| 930 | fprintf(irp->f, ")"); | |
| 931 | } | |
| 932 | ||
| 919 | 933 | static void ir_print_return_address(IrPrint *irp, IrInstructionReturnAddress *instruction) { |
| 920 | 934 | fprintf(irp->f, "@returnAddress()"); |
| 921 | 935 | } |
| ... | ... | @@ -1776,6 +1790,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1776 | 1790 | case IrInstructionIdFrameType: |
| 1777 | 1791 | ir_print_frame_type(irp, (IrInstructionFrameType *)instruction); |
| 1778 | 1792 | break; |
| 1793 | case IrInstructionIdFrameSizeSrc: | |
| 1794 | ir_print_frame_size_src(irp, (IrInstructionFrameSizeSrc *)instruction); | |
| 1795 | break; | |
| 1796 | case IrInstructionIdFrameSizeGen: | |
| 1797 | ir_print_frame_size_gen(irp, (IrInstructionFrameSizeGen *)instruction); | |
| 1798 | break; | |
| 1779 | 1799 | case IrInstructionIdAlignOf: |
| 1780 | 1800 | ir_print_align_of(irp, (IrInstructionAlignOf *)instruction); |
| 1781 | 1801 | break; |
test/stage1/behavior/coroutines.zig+26| ... | ... | @@ -101,6 +101,32 @@ test "calling an inferred async function" { |
| 101 | 101 | S.doTheTest(); |
| 102 | 102 | } |
| 103 | 103 | |
| 104 | test "@frameSize" { | |
| 105 | const S = struct { | |
| 106 | fn doTheTest() void { | |
| 107 | { | |
| 108 | var ptr = @ptrCast(async fn(i32) void, other); | |
| 109 | const size = @frameSize(ptr); | |
| 110 | expect(size == @sizeOf(@Frame(other))); | |
| 111 | } | |
| 112 | { | |
| 113 | var ptr = @ptrCast(async fn() void, first); | |
| 114 | const size = @frameSize(ptr); | |
| 115 | expect(size == @sizeOf(@Frame(first))); | |
| 116 | } | |
| 117 | } | |
| 118 | ||
| 119 | fn first() void { | |
| 120 | other(1); | |
| 121 | } | |
| 122 | fn other(param: i32) void { | |
| 123 | var local: i32 = undefined; | |
| 124 | suspend; | |
| 125 | } | |
| 126 | }; | |
| 127 | S.doTheTest(); | |
| 128 | } | |
| 129 | ||
| 104 | 130 | //test "coroutine suspend, resume" { |
| 105 | 131 | // seq('a'); |
| 106 | 132 | // const p = try async<allocator> testAsyncSeq(); |