authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-25 01:47:56-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-25 01:47:56-04:00
log70bced5dcffccc2f8029d8c3d7f2d18b48d993f5
tree17672a7a6787d9de275d6cad00b9854ea168e409
parentead2d32be871411685f846e604ec7e4253b9f25a
signature Commit is signed but in an unrecognized format.

implement `@frame` and `@Frame`


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,8 +1435,6 @@ enum BuiltinFnId {
1435 BuiltinFnIdErrName,1435 BuiltinFnIdErrName,
1436 BuiltinFnIdBreakpoint,1436 BuiltinFnIdBreakpoint,
1437 BuiltinFnIdReturnAddress,1437 BuiltinFnIdReturnAddress,
1438 BuiltinFnIdFrameAddress,
1439 BuiltinFnIdHandle,
1440 BuiltinFnIdEmbedFile,1438 BuiltinFnIdEmbedFile,
1441 BuiltinFnIdCmpxchgWeak,1439 BuiltinFnIdCmpxchgWeak,
1442 BuiltinFnIdCmpxchgStrong,1440 BuiltinFnIdCmpxchgStrong,
...@@ -1507,6 +1505,9 @@ enum BuiltinFnId {...@@ -1507,6 +1505,9 @@ enum BuiltinFnId {
1507 BuiltinFnIdAtomicLoad,1505 BuiltinFnIdAtomicLoad,
1508 BuiltinFnIdHasDecl,1506 BuiltinFnIdHasDecl,
1509 BuiltinFnIdUnionInit,1507 BuiltinFnIdUnionInit,
1508 BuiltinFnIdFrameAddress,
1509 BuiltinFnIdFrameType,
1510 BuiltinFnIdFrameHandle,
1510};1511};
15111512
1512struct BuiltinFnEntry {1513struct BuiltinFnEntry {
...@@ -2252,7 +2253,8 @@ enum IrInstructionId {...@@ -2252,7 +2253,8 @@ enum IrInstructionId {
2252 IrInstructionIdBreakpoint,2253 IrInstructionIdBreakpoint,
2253 IrInstructionIdReturnAddress,2254 IrInstructionIdReturnAddress,
2254 IrInstructionIdFrameAddress,2255 IrInstructionIdFrameAddress,
2255 IrInstructionIdHandle,2256 IrInstructionIdFrameHandle,
2257 IrInstructionIdFrameType,
2256 IrInstructionIdAlignOf,2258 IrInstructionIdAlignOf,
2257 IrInstructionIdOverflowOp,2259 IrInstructionIdOverflowOp,
2258 IrInstructionIdTestErrSrc,2260 IrInstructionIdTestErrSrc,
...@@ -3038,8 +3040,14 @@ struct IrInstructionFrameAddress {...@@ -3038,8 +3040,14 @@ struct IrInstructionFrameAddress {
3038 IrInstruction base;3040 IrInstruction base;
3039};3041};
30403042
3041struct IrInstructionHandle {3043struct IrInstructionFrameHandle {
3044 IrInstruction base;
3045};
3046
3047struct IrInstructionFrameType {
3042 IrInstruction base;3048 IrInstruction base;
3049
3050 IrInstruction *fn;
3043};3051};
30443052
3045enum IrOverflowOp {3053enum IrOverflowOp {
src/codegen.cpp+8-8
...@@ -4457,10 +4457,8 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutable *executable...@@ -4457,10 +4457,8 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutable *executable
4457 return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, "");4457 return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, "");
4458}4458}
44594459
4460static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutable *executable,4460static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutable *executable, IrInstructionFrameHandle *instruction) {
4461 IrInstructionHandle *instruction)4461 return g->cur_ret_ptr;
4462{
4463 zig_panic("TODO @handle() codegen");
4464}4462}
44654463
4466static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstructionOverflowOp *instruction) {4464static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstructionOverflowOp *instruction) {
...@@ -5008,6 +5006,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5008,6 +5006,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5008 case IrInstructionIdBitCastSrc:5006 case IrInstructionIdBitCastSrc:
5009 case IrInstructionIdTestErrSrc:5007 case IrInstructionIdTestErrSrc:
5010 case IrInstructionIdUnionInitNamedField:5008 case IrInstructionIdUnionInitNamedField:
5009 case IrInstructionIdFrameType:
5011 zig_unreachable();5010 zig_unreachable();
50125011
5013 case IrInstructionIdDeclVarGen:5012 case IrInstructionIdDeclVarGen:
...@@ -5086,8 +5085,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5086,8 +5085,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5086 return ir_render_return_address(g, executable, (IrInstructionReturnAddress *)instruction);5085 return ir_render_return_address(g, executable, (IrInstructionReturnAddress *)instruction);
5087 case IrInstructionIdFrameAddress:5086 case IrInstructionIdFrameAddress:
5088 return ir_render_frame_address(g, executable, (IrInstructionFrameAddress *)instruction);5087 return ir_render_frame_address(g, executable, (IrInstructionFrameAddress *)instruction);
5089 case IrInstructionIdHandle:5088 case IrInstructionIdFrameHandle:
5090 return ir_render_handle(g, executable, (IrInstructionHandle *)instruction);5089 return ir_render_handle(g, executable, (IrInstructionFrameHandle *)instruction);
5091 case IrInstructionIdOverflowOp:5090 case IrInstructionIdOverflowOp:
5092 return ir_render_overflow_op(g, executable, (IrInstructionOverflowOp *)instruction);5091 return ir_render_overflow_op(g, executable, (IrInstructionOverflowOp *)instruction);
5093 case IrInstructionIdTestErrGen:5092 case IrInstructionIdTestErrGen:
...@@ -6754,8 +6753,6 @@ static BuiltinFnEntry *create_builtin_fn(CodeGen *g, BuiltinFnId id, const char...@@ -6754,8 +6753,6 @@ static BuiltinFnEntry *create_builtin_fn(CodeGen *g, BuiltinFnId id, const char
6754static void define_builtin_fns(CodeGen *g) {6753static void define_builtin_fns(CodeGen *g) {
6755 create_builtin_fn(g, BuiltinFnIdBreakpoint, "breakpoint", 0);6754 create_builtin_fn(g, BuiltinFnIdBreakpoint, "breakpoint", 0);
6756 create_builtin_fn(g, BuiltinFnIdReturnAddress, "returnAddress", 0);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 create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy", 3);6756 create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy", 3);
6760 create_builtin_fn(g, BuiltinFnIdMemset, "memset", 3);6757 create_builtin_fn(g, BuiltinFnIdMemset, "memset", 3);
6761 create_builtin_fn(g, BuiltinFnIdSizeof, "sizeOf", 1);6758 create_builtin_fn(g, BuiltinFnIdSizeof, "sizeOf", 1);
...@@ -6856,6 +6853,9 @@ static void define_builtin_fns(CodeGen *g) {...@@ -6856,6 +6853,9 @@ static void define_builtin_fns(CodeGen *g) {
6856 create_builtin_fn(g, BuiltinFnIdThis, "This", 0);6853 create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
6857 create_builtin_fn(g, BuiltinFnIdHasDecl, "hasDecl", 2);6854 create_builtin_fn(g, BuiltinFnIdHasDecl, "hasDecl", 2);
6858 create_builtin_fn(g, BuiltinFnIdUnionInit, "unionInit", 3);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}
68606860
6861static const char *bool_to_str(bool b) {6861static const char *bool_to_str(bool b) {
src/ir.cpp+51-20
...@@ -755,8 +755,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameAddress *)...@@ -755,8 +755,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameAddress *)
755 return IrInstructionIdFrameAddress;755 return IrInstructionIdFrameAddress;
756}756}
757757
758static constexpr IrInstructionId ir_instruction_id(IrInstructionHandle *) {758static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameHandle *) {
759 return IrInstructionIdHandle;759 return IrInstructionIdFrameHandle;
760}
761
762static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameType *) {
763 return IrInstructionIdFrameType;
760}764}
761765
762static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignOf *) {766static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignOf *) {
...@@ -2362,7 +2366,16 @@ static IrInstruction *ir_build_frame_address(IrBuilder *irb, Scope *scope, AstNo...@@ -2362,7 +2366,16 @@ static IrInstruction *ir_build_frame_address(IrBuilder *irb, Scope *scope, AstNo
2362}2366}
23632367
2364static IrInstruction *ir_build_handle(IrBuilder *irb, Scope *scope, AstNode *source_node) {2368static 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
2373static 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 return &instruction->base;2379 return &instruction->base;
2367}2380}
23682381
...@@ -3358,11 +3371,6 @@ static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) {...@@ -3358,11 +3371,6 @@ static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) {
3358 return nullptr;3371 return nullptr;
3359}3372}
33603373
3361static 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
3366static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode *node, IrInstruction *return_value,3374static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode *node, IrInstruction *return_value,
3367 bool is_generated_code)3375 bool is_generated_code)
3368{3376{
...@@ -4278,8 +4286,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4278,8 +4286,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4278 return irb->codegen->invalid_instruction;4286 return irb->codegen->invalid_instruction;
4279 }4287 }
42804288
4281 bool is_async = exec_is_async(irb->exec);
4282
4283 switch (builtin_fn->id) {4289 switch (builtin_fn->id) {
4284 case BuiltinFnIdInvalid:4290 case BuiltinFnIdInvalid:
4285 zig_unreachable();4291 zig_unreachable();
...@@ -4902,16 +4908,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4902,16 +4908,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4902 return ir_lval_wrap(irb, scope, ir_build_return_address(irb, scope, node), lval, result_loc);4908 return ir_lval_wrap(irb, scope, ir_build_return_address(irb, scope, node), lval, result_loc);
4903 case BuiltinFnIdFrameAddress:4909 case BuiltinFnIdFrameAddress:
4904 return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval, result_loc);4910 return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval, result_loc);
4905 case BuiltinFnIdHandle:4911 case BuiltinFnIdFrameHandle:
4906 if (!irb->exec->fn_entry) {4912 if (!irb->exec->fn_entry) {
4907 add_node_error(irb->codegen, node, buf_sprintf("@handle() called outside of function definition"));4913 add_node_error(irb->codegen, node, buf_sprintf("@handle() called outside of function definition"));
4908 return irb->codegen->invalid_instruction;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 return ir_lval_wrap(irb, scope, ir_build_handle(irb, scope, node), lval, result_loc);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 case BuiltinFnIdAlignOf:4926 case BuiltinFnIdAlignOf:
4916 {4927 {
4917 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);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,8 +21737,25 @@ static IrInstruction *ir_analyze_instruction_frame_address(IrAnalyze *ira, IrIns
21726 return result;21737 return result;
21727}21738}
2172821739
21729static IrInstruction *ir_analyze_instruction_handle(IrAnalyze *ira, IrInstructionHandle *instruction) {21740static IrInstruction *ir_analyze_instruction_frame_handle(IrAnalyze *ira, IrInstructionFrameHandle *instruction) {
21730 zig_panic("TODO anlayze @handle()");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
21752static 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}
2173221760
21733static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) {21761static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) {
...@@ -24355,8 +24383,10 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -24355,8 +24383,10 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
24355 return ir_analyze_instruction_return_address(ira, (IrInstructionReturnAddress *)instruction);24383 return ir_analyze_instruction_return_address(ira, (IrInstructionReturnAddress *)instruction);
24356 case IrInstructionIdFrameAddress:24384 case IrInstructionIdFrameAddress:
24357 return ir_analyze_instruction_frame_address(ira, (IrInstructionFrameAddress *)instruction);24385 return ir_analyze_instruction_frame_address(ira, (IrInstructionFrameAddress *)instruction);
24358 case IrInstructionIdHandle:24386 case IrInstructionIdFrameHandle:
24359 return ir_analyze_instruction_handle(ira, (IrInstructionHandle *)instruction);24387 return ir_analyze_instruction_frame_handle(ira, (IrInstructionFrameHandle *)instruction);
24388 case IrInstructionIdFrameType:
24389 return ir_analyze_instruction_frame_type(ira, (IrInstructionFrameType *)instruction);
24360 case IrInstructionIdAlignOf:24390 case IrInstructionIdAlignOf:
24361 return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction);24391 return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction);
24362 case IrInstructionIdOverflowOp:24392 case IrInstructionIdOverflowOp:
...@@ -24650,7 +24680,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -24650,7 +24680,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
24650 case IrInstructionIdAlignOf:24680 case IrInstructionIdAlignOf:
24651 case IrInstructionIdReturnAddress:24681 case IrInstructionIdReturnAddress:
24652 case IrInstructionIdFrameAddress:24682 case IrInstructionIdFrameAddress:
24653 case IrInstructionIdHandle:24683 case IrInstructionIdFrameHandle:
24684 case IrInstructionIdFrameType:
24654 case IrInstructionIdTestErrSrc:24685 case IrInstructionIdTestErrSrc:
24655 case IrInstructionIdTestErrGen:24686 case IrInstructionIdTestErrGen:
24656 case IrInstructionIdFnProto:24687 case IrInstructionIdFnProto:
src/ir_print.cpp+13-4
...@@ -906,8 +906,14 @@ static void ir_print_frame_address(IrPrint *irp, IrInstructionFrameAddress *inst...@@ -906,8 +906,14 @@ static void ir_print_frame_address(IrPrint *irp, IrInstructionFrameAddress *inst
906 fprintf(irp->f, "@frameAddress()");906 fprintf(irp->f, "@frameAddress()");
907}907}
908908
909static void ir_print_handle(IrPrint *irp, IrInstructionHandle *instruction) {909static void ir_print_handle(IrPrint *irp, IrInstructionFrameHandle *instruction) {
910 fprintf(irp->f, "@handle()");910 fprintf(irp->f, "@frame()");
911}
912
913static 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}
912918
913static void ir_print_return_address(IrPrint *irp, IrInstructionReturnAddress *instruction) {919static void ir_print_return_address(IrPrint *irp, IrInstructionReturnAddress *instruction) {
...@@ -1764,8 +1770,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1764,8 +1770,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1764 case IrInstructionIdFrameAddress:1770 case IrInstructionIdFrameAddress:
1765 ir_print_frame_address(irp, (IrInstructionFrameAddress *)instruction);1771 ir_print_frame_address(irp, (IrInstructionFrameAddress *)instruction);
1766 break;1772 break;
1767 case IrInstructionIdHandle:1773 case IrInstructionIdFrameHandle:
1768 ir_print_handle(irp, (IrInstructionHandle *)instruction);1774 ir_print_handle(irp, (IrInstructionFrameHandle *)instruction);
1775 break;
1776 case IrInstructionIdFrameType:
1777 ir_print_frame_type(irp, (IrInstructionFrameType *)instruction);
1769 break;1778 break;
1770 case IrInstructionIdAlignOf:1779 case IrInstructionIdAlignOf:
1771 ir_print_align_of(irp, (IrInstructionAlignOf *)instruction);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,15 +79,23 @@ test "local variable in async function" {
7979
80test "calling an inferred async function" {80test "calling an inferred async function" {
81 const S = struct {81 const S = struct {
82 var x: i32 = 1;
83 var other_frame: *@Frame(other) = undefined;
84
82 fn doTheTest() void {85 fn doTheTest() void {
83 const p = async first();86 const p = async first();
87 expect(x == 1);
88 resume other_frame.*;
89 expect(x == 2);
84 }90 }
8591
86 fn first() void {92 fn first() void {
87 other();93 other();
88 }94 }
89 fn other() void {95 fn other() void {
96 other_frame = @frame();
90 suspend;97 suspend;
98 x += 1;
91 }99 }
92 };100 };
93 S.doTheTest();101 S.doTheTest();