authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-25 15:05:55-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-25 15:05:55-04:00
log538c0cd2250e08aad07784355b402cfae6145507
treea7d3de300e1580addd4e457d9a51e364355ff083
parent70bced5dcffccc2f8029d8c3d7f2d18b48d993f5
signature Commit is signed but in an unrecognized format.

implement `@frameSize`


6 files changed, 142 insertions(+), 4 deletions(-)

BRANCH_TODO+1
...@@ -2,3 +2,4 @@...@@ -2,3 +2,4 @@
2 * await of a non async function2 * await of a non async function
3 * async call on a non async function3 * async call on a non async function
4 * safety for resuming when it is awaiting4 * 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,6 +1508,7 @@ enum BuiltinFnId {
1508 BuiltinFnIdFrameAddress,1508 BuiltinFnIdFrameAddress,
1509 BuiltinFnIdFrameType,1509 BuiltinFnIdFrameType,
1510 BuiltinFnIdFrameHandle,1510 BuiltinFnIdFrameHandle,
1511 BuiltinFnIdFrameSize,
1511};1512};
15121513
1513struct BuiltinFnEntry {1514struct BuiltinFnEntry {
...@@ -2255,6 +2256,8 @@ enum IrInstructionId {...@@ -2255,6 +2256,8 @@ enum IrInstructionId {
2255 IrInstructionIdFrameAddress,2256 IrInstructionIdFrameAddress,
2256 IrInstructionIdFrameHandle,2257 IrInstructionIdFrameHandle,
2257 IrInstructionIdFrameType,2258 IrInstructionIdFrameType,
2259 IrInstructionIdFrameSizeSrc,
2260 IrInstructionIdFrameSizeGen,
2258 IrInstructionIdAlignOf,2261 IrInstructionIdAlignOf,
2259 IrInstructionIdOverflowOp,2262 IrInstructionIdOverflowOp,
2260 IrInstructionIdTestErrSrc,2263 IrInstructionIdTestErrSrc,
...@@ -3050,6 +3053,19 @@ struct IrInstructionFrameType {...@@ -3050,6 +3053,19 @@ struct IrInstructionFrameType {
3050 IrInstruction *fn;3053 IrInstruction *fn;
3051};3054};
30523055
3056struct IrInstructionFrameSizeSrc {
3057 IrInstruction base;
3058
3059 IrInstruction *fn;
3060};
3061
3062struct IrInstructionFrameSizeGen {
3063 IrInstruction base;
3064
3065 IrInstruction *fn;
3066 IrInstruction *frame_ptr;
3067};
3068
3053enum IrOverflowOp {3069enum IrOverflowOp {
3054 IrOverflowOpAdd,3070 IrOverflowOpAdd,
3055 IrOverflowOpSub,3071 IrOverflowOpSub,
src/codegen.cpp+13
...@@ -4914,6 +4914,15 @@ static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable,...@@ -4914,6 +4914,15 @@ static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable,
4914 return nullptr;4914 return nullptr;
4915}4915}
49164916
4917static 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
4917static void set_debug_location(CodeGen *g, IrInstruction *instruction) {4926static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
4918 AstNode *source_node = instruction->source_node;4927 AstNode *source_node = instruction->source_node;
4919 Scope *scope = instruction->scope;4928 Scope *scope = instruction->scope;
...@@ -5007,6 +5016,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5007,6 +5016,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5007 case IrInstructionIdTestErrSrc:5016 case IrInstructionIdTestErrSrc:
5008 case IrInstructionIdUnionInitNamedField:5017 case IrInstructionIdUnionInitNamedField:
5009 case IrInstructionIdFrameType:5018 case IrInstructionIdFrameType:
5019 case IrInstructionIdFrameSizeSrc:
5010 zig_unreachable();5020 zig_unreachable();
50115021
5012 case IrInstructionIdDeclVarGen:5022 case IrInstructionIdDeclVarGen:
...@@ -5161,6 +5171,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5161,6 +5171,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5161 return ir_render_suspend_br(g, executable, (IrInstructionSuspendBr *)instruction);5171 return ir_render_suspend_br(g, executable, (IrInstructionSuspendBr *)instruction);
5162 case IrInstructionIdCoroResume:5172 case IrInstructionIdCoroResume:
5163 return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction);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 zig_unreachable();5177 zig_unreachable();
5166}5178}
...@@ -6856,6 +6868,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -6856,6 +6868,7 @@ static void define_builtin_fns(CodeGen *g) {
6856 create_builtin_fn(g, BuiltinFnIdFrameHandle, "frame", 0);6868 create_builtin_fn(g, BuiltinFnIdFrameHandle, "frame", 0);
6857 create_builtin_fn(g, BuiltinFnIdFrameType, "Frame", 1);6869 create_builtin_fn(g, BuiltinFnIdFrameType, "Frame", 1);
6858 create_builtin_fn(g, BuiltinFnIdFrameAddress, "frameAddress", 0);6870 create_builtin_fn(g, BuiltinFnIdFrameAddress, "frameAddress", 0);
6871 create_builtin_fn(g, BuiltinFnIdFrameSize, "frameSize", 1);
6859}6872}
68606873
6861static const char *bool_to_str(bool b) {6874static const char *bool_to_str(bool b) {
src/ir.cpp+66-4
...@@ -763,6 +763,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameType *) {...@@ -763,6 +763,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameType *) {
763 return IrInstructionIdFrameType;763 return IrInstructionIdFrameType;
764}764}
765765
766static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameSizeSrc *) {
767 return IrInstructionIdFrameSizeSrc;
768}
769
770static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameSizeGen *) {
771 return IrInstructionIdFrameSizeGen;
772}
773
766static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignOf *) {774static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignOf *) {
767 return IrInstructionIdAlignOf;775 return IrInstructionIdAlignOf;
768}776}
...@@ -2379,6 +2387,28 @@ static IrInstruction *ir_build_frame_type(IrBuilder *irb, Scope *scope, AstNode...@@ -2379,6 +2387,28 @@ static IrInstruction *ir_build_frame_type(IrBuilder *irb, Scope *scope, AstNode
2379 return &instruction->base;2387 return &instruction->base;
2380}2388}
23812389
2390static 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
2399static 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
2382static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode *source_node,2412static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode *source_node,
2383 IrOverflowOp op, IrInstruction *type_value, IrInstruction *op1, IrInstruction *op2,2413 IrOverflowOp op, IrInstruction *type_value, IrInstruction *op1, IrInstruction *op2,
2384 IrInstruction *result_ptr, ZigType *result_ptr_type)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,6 +4953,15 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4923 IrInstruction *frame_type = ir_build_frame_type(irb, scope, node, arg0_value);4953 IrInstruction *frame_type = ir_build_frame_type(irb, scope, node, arg0_value);
4924 return ir_lval_wrap(irb, scope, frame_type, lval, result_loc);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 case BuiltinFnIdAlignOf:4965 case BuiltinFnIdAlignOf:
4927 {4966 {
4928 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);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,6 +21797,28 @@ static IrInstruction *ir_analyze_instruction_frame_type(IrAnalyze *ira, IrInstru
21758 return ir_const_type(ira, &instruction->base, ty);21797 return ir_const_type(ira, &instruction->base, ty);
21759}21798}
2176021799
21800static 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
21761static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) {21822static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) {
21762 Error err;21823 Error err;
21763 IrInstruction *type_value = instruction->type_value->child;21824 IrInstruction *type_value = instruction->type_value->child;
...@@ -22348,10 +22409,6 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct...@@ -22348,10 +22409,6 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct
22348 return ira->codegen->invalid_instruction;22409 return ira->codegen->invalid_instruction;
22349 }22410 }
2235022411
22351 if (fn_type_id.cc == CallingConventionAsync) {
22352 zig_panic("TODO");
22353 }
22354
22355 return ir_const_type(ira, &instruction->base, get_fn_type(ira->codegen, &fn_type_id));22412 return ir_const_type(ira, &instruction->base, get_fn_type(ira->codegen, &fn_type_id));
22356}22413}
2235722414
...@@ -24237,6 +24294,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -24237,6 +24294,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
24237 case IrInstructionIdSliceGen:24294 case IrInstructionIdSliceGen:
24238 case IrInstructionIdRefGen:24295 case IrInstructionIdRefGen:
24239 case IrInstructionIdTestErrGen:24296 case IrInstructionIdTestErrGen:
24297 case IrInstructionIdFrameSizeGen:
24240 zig_unreachable();24298 zig_unreachable();
2424124299
24242 case IrInstructionIdReturn:24300 case IrInstructionIdReturn:
...@@ -24387,6 +24445,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -24387,6 +24445,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
24387 return ir_analyze_instruction_frame_handle(ira, (IrInstructionFrameHandle *)instruction);24445 return ir_analyze_instruction_frame_handle(ira, (IrInstructionFrameHandle *)instruction);
24388 case IrInstructionIdFrameType:24446 case IrInstructionIdFrameType:
24389 return ir_analyze_instruction_frame_type(ira, (IrInstructionFrameType *)instruction);24447 return ir_analyze_instruction_frame_type(ira, (IrInstructionFrameType *)instruction);
24448 case IrInstructionIdFrameSizeSrc:
24449 return ir_analyze_instruction_frame_size(ira, (IrInstructionFrameSizeSrc *)instruction);
24390 case IrInstructionIdAlignOf:24450 case IrInstructionIdAlignOf:
24391 return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction);24451 return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction);
24392 case IrInstructionIdOverflowOp:24452 case IrInstructionIdOverflowOp:
...@@ -24682,6 +24742,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -24682,6 +24742,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
24682 case IrInstructionIdFrameAddress:24742 case IrInstructionIdFrameAddress:
24683 case IrInstructionIdFrameHandle:24743 case IrInstructionIdFrameHandle:
24684 case IrInstructionIdFrameType:24744 case IrInstructionIdFrameType:
24745 case IrInstructionIdFrameSizeSrc:
24746 case IrInstructionIdFrameSizeGen:
24685 case IrInstructionIdTestErrSrc:24747 case IrInstructionIdTestErrSrc:
24686 case IrInstructionIdTestErrGen:24748 case IrInstructionIdTestErrGen:
24687 case IrInstructionIdFnProto:24749 case IrInstructionIdFnProto:
src/ir_print.cpp+20
...@@ -916,6 +916,20 @@ static void ir_print_frame_type(IrPrint *irp, IrInstructionFrameType *instructio...@@ -916,6 +916,20 @@ static void ir_print_frame_type(IrPrint *irp, IrInstructionFrameType *instructio
916 fprintf(irp->f, ")");916 fprintf(irp->f, ")");
917}917}
918918
919static 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
925static 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
919static void ir_print_return_address(IrPrint *irp, IrInstructionReturnAddress *instruction) {933static void ir_print_return_address(IrPrint *irp, IrInstructionReturnAddress *instruction) {
920 fprintf(irp->f, "@returnAddress()");934 fprintf(irp->f, "@returnAddress()");
921}935}
...@@ -1776,6 +1790,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1776,6 +1790,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1776 case IrInstructionIdFrameType:1790 case IrInstructionIdFrameType:
1777 ir_print_frame_type(irp, (IrInstructionFrameType *)instruction);1791 ir_print_frame_type(irp, (IrInstructionFrameType *)instruction);
1778 break;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 case IrInstructionIdAlignOf:1799 case IrInstructionIdAlignOf:
1780 ir_print_align_of(irp, (IrInstructionAlignOf *)instruction);1800 ir_print_align_of(irp, (IrInstructionAlignOf *)instruction);
1781 break;1801 break;
test/stage1/behavior/coroutines.zig+26
...@@ -101,6 +101,32 @@ test "calling an inferred async function" {...@@ -101,6 +101,32 @@ test "calling an inferred async function" {
101 S.doTheTest();101 S.doTheTest();
102}102}
103103
104test "@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//test "coroutine suspend, resume" {130//test "coroutine suspend, resume" {
105// seq('a');131// seq('a');
106// const p = try async<allocator> testAsyncSeq();132// const p = try async<allocator> testAsyncSeq();