Commit d291d3c8c0
Changed files (2)
src
test
stage1
behavior
src/ir.cpp
@@ -15648,6 +15648,31 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
return &store_ptr->base;
}
+static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,
+ ZigFn *fn_entry)
+{
+ if (call_instruction->new_stack == nullptr)
+ return nullptr;
+
+ IrInstruction *new_stack = call_instruction->new_stack->child;
+ if (type_is_invalid(new_stack->value.type))
+ return ira->codegen->invalid_instruction;
+
+ if (call_instruction->is_async_call_builtin &&
+ fn_entry != nullptr && new_stack->value.type->id == ZigTypeIdPointer &&
+ new_stack->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame)
+ {
+ ZigType *needed_frame_type = get_pointer_to_type(ira->codegen,
+ get_fn_frame_type(ira->codegen, fn_entry), false);
+ return ir_implicit_cast(ira, new_stack, needed_frame_type);
+ } else {
+ ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
+ false, false, PtrLenUnknown, target_fn_align(ira->codegen->zig_target), 0, 0, false);
+ ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
+ return ir_implicit_cast(ira, new_stack, u8_slice);
+ }
+}
+
static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,
ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
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
return ir_finish_anal(ira, new_instruction);
}
- IrInstruction *casted_new_stack = nullptr;
- if (call_instruction->new_stack != nullptr) {
- IrInstruction *new_stack = call_instruction->new_stack->child;
- if (type_is_invalid(new_stack->value.type))
- return ira->codegen->invalid_instruction;
-
- if (call_instruction->is_async_call_builtin &&
- fn_entry != nullptr && new_stack->value.type->id == ZigTypeIdPointer &&
- new_stack->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame)
- {
- ZigType *needed_frame_type = get_pointer_to_type(ira->codegen,
- get_fn_frame_type(ira->codegen, fn_entry), false);
- casted_new_stack = ir_implicit_cast(ira, new_stack, needed_frame_type);
- if (type_is_invalid(casted_new_stack->value.type))
- return ira->codegen->invalid_instruction;
- } else {
- ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
- false, false, PtrLenUnknown, target_fn_align(ira->codegen->zig_target), 0, 0, false);
- ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
- casted_new_stack = ir_implicit_cast(ira, new_stack, u8_slice);
- if (type_is_invalid(casted_new_stack->value.type))
- return ira->codegen->invalid_instruction;
- }
- }
-
if (fn_type->data.fn.is_generic) {
if (!fn_entry) {
ir_add_error(ira, call_instruction->fn_ref,
@@ -16063,6 +16063,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
parent_fn_entry->calls_or_awaits_errorable_fn = true;
}
+ IrInstruction *casted_new_stack = analyze_casted_new_stack(ira, call_instruction, impl_fn);
+ if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value.type))
+ return ira->codegen->invalid_instruction;
+
size_t impl_param_count = impl_fn_type_id->param_count;
if (call_instruction->is_async) {
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
return ira->codegen->invalid_instruction;
}
+ IrInstruction *casted_new_stack = analyze_casted_new_stack(ira, call_instruction, fn_entry);
+ if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value.type))
+ return ira->codegen->invalid_instruction;
+
if (call_instruction->is_async) {
IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref,
casted_args, call_param_count, casted_new_stack);
test/stage1/behavior/async_fn.zig
@@ -1031,3 +1031,28 @@ test "@typeOf an async function call of generic fn with error union type" {
};
_ = async S.func(i32);
}
+
+test "using @typeOf on a generic function call" {
+ const S = struct {
+ var global_frame: anyframe = undefined;
+ var global_ok = false;
+
+ var buf: [100]u8 align(16) = undefined;
+
+ fn amain(x: var) void {
+ if (x == 0) {
+ global_ok = true;
+ return;
+ }
+ suspend {
+ global_frame = @frame();
+ }
+ const F = @typeOf(async amain(x - 1));
+ const frame = @intToPtr(*F, @ptrToInt(&buf));
+ return await @asyncCall(frame, {}, amain, x - 1);
+ }
+ };
+ _ = async S.amain(u32(1));
+ resume S.global_frame;
+ expect(S.global_ok);
+}