authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-02 13:07:44-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-02 13:07:44-04:00
logd291d3c8c00450e31b7cce15eae43db265361186
treed9d14cfba1083a7fbea4bfb204b1c44fb2629199
parent0fe28855c5a32b16dc092ab1d70efde38ef89a7b
signaturelock-open Commit is signed but in an unrecognized format.

fix using @typeOf on a generic function call


2 files changed, 58 insertions(+), 25 deletions(-)

src/ir.cpp+33-25
...@@ -15648,6 +15648,31 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -15648,6 +15648,31 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
15648 return &store_ptr->base;15648 return &store_ptr->base;
15649}15649}
1565015650
15651static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,
15652 ZigFn *fn_entry)
15653{
15654 if (call_instruction->new_stack == nullptr)
15655 return nullptr;
15656
15657 IrInstruction *new_stack = call_instruction->new_stack->child;
15658 if (type_is_invalid(new_stack->value.type))
15659 return ira->codegen->invalid_instruction;
15660
15661 if (call_instruction->is_async_call_builtin &&
15662 fn_entry != nullptr && new_stack->value.type->id == ZigTypeIdPointer &&
15663 new_stack->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame)
15664 {
15665 ZigType *needed_frame_type = get_pointer_to_type(ira->codegen,
15666 get_fn_frame_type(ira->codegen, fn_entry), false);
15667 return ir_implicit_cast(ira, new_stack, needed_frame_type);
15668 } else {
15669 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
15670 false, false, PtrLenUnknown, target_fn_align(ira->codegen->zig_target), 0, 0, false);
15671 ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
15672 return ir_implicit_cast(ira, new_stack, u8_slice);
15673 }
15674}
15675
15651static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,15676static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,
15652 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,15677 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
15653 IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)15678 IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)
...@@ -15826,31 +15851,6 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -15826,31 +15851,6 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
15826 return ir_finish_anal(ira, new_instruction);15851 return ir_finish_anal(ira, new_instruction);
15827 }15852 }
1582815853
15829 IrInstruction *casted_new_stack = nullptr;
15830 if (call_instruction->new_stack != nullptr) {
15831 IrInstruction *new_stack = call_instruction->new_stack->child;
15832 if (type_is_invalid(new_stack->value.type))
15833 return ira->codegen->invalid_instruction;
15834
15835 if (call_instruction->is_async_call_builtin &&
15836 fn_entry != nullptr && new_stack->value.type->id == ZigTypeIdPointer &&
15837 new_stack->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame)
15838 {
15839 ZigType *needed_frame_type = get_pointer_to_type(ira->codegen,
15840 get_fn_frame_type(ira->codegen, fn_entry), false);
15841 casted_new_stack = ir_implicit_cast(ira, new_stack, needed_frame_type);
15842 if (type_is_invalid(casted_new_stack->value.type))
15843 return ira->codegen->invalid_instruction;
15844 } else {
15845 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
15846 false, false, PtrLenUnknown, target_fn_align(ira->codegen->zig_target), 0, 0, false);
15847 ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
15848 casted_new_stack = ir_implicit_cast(ira, new_stack, u8_slice);
15849 if (type_is_invalid(casted_new_stack->value.type))
15850 return ira->codegen->invalid_instruction;
15851 }
15852 }
15853
15854 if (fn_type->data.fn.is_generic) {15854 if (fn_type->data.fn.is_generic) {
15855 if (!fn_entry) {15855 if (!fn_entry) {
15856 ir_add_error(ira, call_instruction->fn_ref,15856 ir_add_error(ira, call_instruction->fn_ref,
...@@ -16063,6 +16063,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -16063,6 +16063,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
16063 parent_fn_entry->calls_or_awaits_errorable_fn = true;16063 parent_fn_entry->calls_or_awaits_errorable_fn = true;
16064 }16064 }
1606516065
16066 IrInstruction *casted_new_stack = analyze_casted_new_stack(ira, call_instruction, impl_fn);
16067 if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value.type))
16068 return ira->codegen->invalid_instruction;
16069
16066 size_t impl_param_count = impl_fn_type_id->param_count;16070 size_t impl_param_count = impl_fn_type_id->param_count;
16067 if (call_instruction->is_async) {16071 if (call_instruction->is_async) {
16068 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,16072 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,
...@@ -16211,6 +16215,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -16211,6 +16215,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
16211 return ira->codegen->invalid_instruction;16215 return ira->codegen->invalid_instruction;
16212 }16216 }
1621316217
16218 IrInstruction *casted_new_stack = analyze_casted_new_stack(ira, call_instruction, fn_entry);
16219 if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value.type))
16220 return ira->codegen->invalid_instruction;
16221
16214 if (call_instruction->is_async) {16222 if (call_instruction->is_async) {
16215 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref,16223 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref,
16216 casted_args, call_param_count, casted_new_stack);16224 casted_args, call_param_count, casted_new_stack);
test/stage1/behavior/async_fn.zig+25
...@@ -1031,3 +1031,28 @@ test "@typeOf an async function call of generic fn with error union type" {...@@ -1031,3 +1031,28 @@ test "@typeOf an async function call of generic fn with error union type" {
1031 };1031 };
1032 _ = async S.func(i32);1032 _ = async S.func(i32);
1033}1033}
1034
1035test "using @typeOf on a generic function call" {
1036 const S = struct {
1037 var global_frame: anyframe = undefined;
1038 var global_ok = false;
1039
1040 var buf: [100]u8 align(16) = undefined;
1041
1042 fn amain(x: var) void {
1043 if (x == 0) {
1044 global_ok = true;
1045 return;
1046 }
1047 suspend {
1048 global_frame = @frame();
1049 }
1050 const F = @typeOf(async amain(x - 1));
1051 const frame = @intToPtr(*F, @ptrToInt(&buf));
1052 return await @asyncCall(frame, {}, amain, x - 1);
1053 }
1054 };
1055 _ = async S.amain(u32(1));
1056 resume S.global_frame;
1057 expect(S.global_ok);
1058}