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 @@
22 * await of a non async function
33 * async call on a non async function
44 * 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 {
15081508 BuiltinFnIdFrameAddress,
15091509 BuiltinFnIdFrameType,
15101510 BuiltinFnIdFrameHandle,
1511 BuiltinFnIdFrameSize,
15111512};
15121513
15131514struct BuiltinFnEntry {
......@@ -2255,6 +2256,8 @@ enum IrInstructionId {
22552256 IrInstructionIdFrameAddress,
22562257 IrInstructionIdFrameHandle,
22572258 IrInstructionIdFrameType,
2259 IrInstructionIdFrameSizeSrc,
2260 IrInstructionIdFrameSizeGen,
22582261 IrInstructionIdAlignOf,
22592262 IrInstructionIdOverflowOp,
22602263 IrInstructionIdTestErrSrc,
......@@ -3050,6 +3053,19 @@ struct IrInstructionFrameType {
30503053 IrInstruction *fn;
30513054};
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
30533069enum IrOverflowOp {
30543070 IrOverflowOpAdd,
30553071 IrOverflowOpSub,
src/codegen.cpp+13
......@@ -4914,6 +4914,15 @@ static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable,
49144914 return nullptr;
49154915}
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
49174926static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
49184927 AstNode *source_node = instruction->source_node;
49194928 Scope *scope = instruction->scope;
......@@ -5007,6 +5016,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
50075016 case IrInstructionIdTestErrSrc:
50085017 case IrInstructionIdUnionInitNamedField:
50095018 case IrInstructionIdFrameType:
5019 case IrInstructionIdFrameSizeSrc:
50105020 zig_unreachable();
50115021
50125022 case IrInstructionIdDeclVarGen:
......@@ -5161,6 +5171,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
51615171 return ir_render_suspend_br(g, executable, (IrInstructionSuspendBr *)instruction);
51625172 case IrInstructionIdCoroResume:
51635173 return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction);
5174 case IrInstructionIdFrameSizeGen:
5175 return ir_render_frame_size(g, executable, (IrInstructionFrameSizeGen *)instruction);
51645176 }
51655177 zig_unreachable();
51665178}
......@@ -6856,6 +6868,7 @@ static void define_builtin_fns(CodeGen *g) {
68566868 create_builtin_fn(g, BuiltinFnIdFrameHandle, "frame", 0);
68576869 create_builtin_fn(g, BuiltinFnIdFrameType, "Frame", 1);
68586870 create_builtin_fn(g, BuiltinFnIdFrameAddress, "frameAddress", 0);
6871 create_builtin_fn(g, BuiltinFnIdFrameSize, "frameSize", 1);
68596872}
68606873
68616874static const char *bool_to_str(bool b) {
src/ir.cpp+66-4
......@@ -763,6 +763,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameType *) {
763763 return IrInstructionIdFrameType;
764764}
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
766774static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignOf *) {
767775 return IrInstructionIdAlignOf;
768776}
......@@ -2379,6 +2387,28 @@ static IrInstruction *ir_build_frame_type(IrBuilder *irb, Scope *scope, AstNode
23792387 return &instruction->base;
23802388}
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
23822412static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode *source_node,
23832413 IrOverflowOp op, IrInstruction *type_value, IrInstruction *op1, IrInstruction *op2,
23842414 IrInstruction *result_ptr, ZigType *result_ptr_type)
......@@ -4923,6 +4953,15 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
49234953 IrInstruction *frame_type = ir_build_frame_type(irb, scope, node, arg0_value);
49244954 return ir_lval_wrap(irb, scope, frame_type, lval, result_loc);
49254955 }
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 }
49264965 case BuiltinFnIdAlignOf:
49274966 {
49284967 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
2175821797 return ir_const_type(ira, &instruction->base, ty);
2175921798}
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
2176121822static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) {
2176221823 Error err;
2176321824 IrInstruction *type_value = instruction->type_value->child;
......@@ -22348,10 +22409,6 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct
2234822409 return ira->codegen->invalid_instruction;
2234922410 }
2235022411
22351 if (fn_type_id.cc == CallingConventionAsync) {
22352 zig_panic("TODO");
22353 }
22354
2235522412 return ir_const_type(ira, &instruction->base, get_fn_type(ira->codegen, &fn_type_id));
2235622413}
2235722414
......@@ -24237,6 +24294,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
2423724294 case IrInstructionIdSliceGen:
2423824295 case IrInstructionIdRefGen:
2423924296 case IrInstructionIdTestErrGen:
24297 case IrInstructionIdFrameSizeGen:
2424024298 zig_unreachable();
2424124299
2424224300 case IrInstructionIdReturn:
......@@ -24387,6 +24445,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
2438724445 return ir_analyze_instruction_frame_handle(ira, (IrInstructionFrameHandle *)instruction);
2438824446 case IrInstructionIdFrameType:
2438924447 return ir_analyze_instruction_frame_type(ira, (IrInstructionFrameType *)instruction);
24448 case IrInstructionIdFrameSizeSrc:
24449 return ir_analyze_instruction_frame_size(ira, (IrInstructionFrameSizeSrc *)instruction);
2439024450 case IrInstructionIdAlignOf:
2439124451 return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction);
2439224452 case IrInstructionIdOverflowOp:
......@@ -24682,6 +24742,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2468224742 case IrInstructionIdFrameAddress:
2468324743 case IrInstructionIdFrameHandle:
2468424744 case IrInstructionIdFrameType:
24745 case IrInstructionIdFrameSizeSrc:
24746 case IrInstructionIdFrameSizeGen:
2468524747 case IrInstructionIdTestErrSrc:
2468624748 case IrInstructionIdTestErrGen:
2468724749 case IrInstructionIdFnProto:
src/ir_print.cpp+20
......@@ -916,6 +916,20 @@ static void ir_print_frame_type(IrPrint *irp, IrInstructionFrameType *instructio
916916 fprintf(irp->f, ")");
917917}
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
919933static void ir_print_return_address(IrPrint *irp, IrInstructionReturnAddress *instruction) {
920934 fprintf(irp->f, "@returnAddress()");
921935}
......@@ -1776,6 +1790,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
17761790 case IrInstructionIdFrameType:
17771791 ir_print_frame_type(irp, (IrInstructionFrameType *)instruction);
17781792 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;
17791799 case IrInstructionIdAlignOf:
17801800 ir_print_align_of(irp, (IrInstructionAlignOf *)instruction);
17811801 break;
test/stage1/behavior/coroutines.zig+26
......@@ -101,6 +101,32 @@ test "calling an inferred async function" {
101101 S.doTheTest();
102102}
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
104130//test "coroutine suspend, resume" {
105131// seq('a');
106132// const p = try async<allocator> testAsyncSeq();