@@ -2788,13 +2788,13 @@ static IrInstruction *ir_build_coro_promise(IrBuilder *irb, Scope *scope, AstNod
2788
2788
}
2789
2789
2790
2790
static IrInstruction *ir_build_coro_alloc_helper(IrBuilder *irb, Scope *scope, AstNode *source_node,
2791
- IrInstruction *alloc_fn , IrInstruction *coro_size)
2791
+ IrInstruction *realloc_fn , IrInstruction *coro_size)
2792
2792
{
2793
2793
IrInstructionCoroAllocHelper *instruction = ir_build_instruction<IrInstructionCoroAllocHelper>(irb, scope, source_node);
2794
- instruction->alloc_fn = alloc_fn ;
2794
+ instruction->realloc_fn = realloc_fn ;
2795
2795
instruction->coro_size = coro_size;
2796
2796
2797
- ir_ref_instruction(alloc_fn , irb->current_basic_block);
2797
+ ir_ref_instruction(realloc_fn , irb->current_basic_block);
2798
2798
ir_ref_instruction(coro_size, irb->current_basic_block);
2799
2799
2800
2800
return &instruction->base;
@@ -3319,9 +3319,11 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
3319
3319
if (!skip_name_check) {
3320
3320
ZigVar *existing_var = find_variable(codegen, parent_scope, name, nullptr);
3321
3321
if (existing_var && !existing_var->shadowable) {
3322
- ErrorMsg *msg = add_node_error(codegen, node,
3323
- buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
3324
- add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
3322
+ if (existing_var->var_type == nullptr || !type_is_invalid(existing_var->var_type)) {
3323
+ ErrorMsg *msg = add_node_error(codegen, node,
3324
+ buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
3325
+ add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
3326
+ }
3325
3327
variable_entry->var_type = codegen->builtin_types.entry_invalid;
3326
3328
} else {
3327
3329
ZigType *type;
@@ -7506,10 +7508,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7506
7508
ImplicitAllocatorIdArg);
7507
7509
irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false);
7508
7510
ir_build_var_decl_src(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);
7509
- Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME );
7510
- IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, alloc_field_name );
7511
- IrInstruction *alloc_fn = ir_build_load_ptr(irb, coro_scope, node, alloc_fn_ptr );
7512
- IrInstruction *maybe_coro_mem_ptr = ir_build_coro_alloc_helper(irb, coro_scope, node, alloc_fn , coro_size);
7511
+ Buf *realloc_field_name = buf_create_from_str(ASYNC_REALLOC_FIELD_NAME );
7512
+ IrInstruction *realloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, realloc_field_name );
7513
+ IrInstruction *realloc_fn = ir_build_load_ptr(irb, coro_scope, node, realloc_fn_ptr );
7514
+ IrInstruction *maybe_coro_mem_ptr = ir_build_coro_alloc_helper(irb, coro_scope, node, realloc_fn , coro_size);
7513
7515
IrInstruction *alloc_result_is_ok = ir_build_test_nonnull(irb, coro_scope, node, maybe_coro_mem_ptr);
7514
7516
IrBasicBlock *alloc_err_block = ir_create_basic_block(irb, coro_scope, "AllocError");
7515
7517
IrBasicBlock *alloc_ok_block = ir_create_basic_block(irb, coro_scope, "AllocOk");
@@ -7643,11 +7645,11 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7643
7645
merge_incoming_values[1] = await_handle_in_block;
7644
7646
IrInstruction *awaiter_handle = ir_build_phi(irb, scope, node, 2, merge_incoming_blocks, merge_incoming_values);
7645
7647
7646
- Buf *free_field_name = buf_create_from_str(ASYNC_FREE_FIELD_NAME );
7648
+ Buf *shrink_field_name = buf_create_from_str(ASYNC_SHRINK_FIELD_NAME );
7647
7649
IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node,
7648
7650
ImplicitAllocatorIdLocalVar);
7649
- IrInstruction *free_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, free_field_name );
7650
- IrInstruction *free_fn = ir_build_load_ptr(irb, scope, node, free_fn_ptr );
7651
+ IrInstruction *shrink_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, shrink_field_name );
7652
+ IrInstruction *shrink_fn = ir_build_load_ptr(irb, scope, node, shrink_fn_ptr );
7651
7653
IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
7652
7654
IrInstruction *coro_mem_ptr_maybe = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle);
7653
7655
IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
@@ -7659,11 +7661,20 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7659
7661
IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
7660
7662
IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);
7661
7663
IrInstruction *mem_slice = ir_build_slice(irb, scope, node, coro_mem_ptr_ref, zero, coro_size, false);
7662
- size_t arg_count = 2 ;
7664
+ size_t arg_count = 5 ;
7663
7665
IrInstruction **args = allocate<IrInstruction *>(arg_count);
7664
7666
args[0] = implicit_allocator_ptr; // self
7665
7667
args[1] = mem_slice; // old_mem
7666
- ir_build_call(irb, scope, node, nullptr, free_fn, arg_count, args, false, FnInlineAuto, false, nullptr, nullptr);
7668
+ args[2] = ir_build_const_usize(irb, scope, node, 8); // old_align
7669
+ // TODO: intentional memory leak here. If this is set to 0 then there is an issue where a coroutine
7670
+ // calls the function and it frees its own stack frame, but then the return value is a slice, which
7671
+ // is implemented as an sret struct. writing to the return pointer causes invalid memory write.
7672
+ // We could work around it by having a global helper function which has a void return type
7673
+ // and calling that instead. But instead this hack will suffice until I rework coroutines to be
7674
+ // non-allocating. Basically coroutines are not supported right now until they are reworked.
7675
+ args[3] = ir_build_const_usize(irb, scope, node, 1); // new_size
7676
+ args[4] = ir_build_const_usize(irb, scope, node, 1); // new_align
7677
+ ir_build_call(irb, scope, node, nullptr, shrink_fn, arg_count, args, false, FnInlineAuto, false, nullptr, nullptr);
7667
7678
7668
7679
IrBasicBlock *resume_block = ir_create_basic_block(irb, scope, "Resume");
7669
7680
ir_build_cond_br(irb, scope, node, resume_awaiter, resume_block, irb->exec->coro_suspend_block, const_bool_false);
@@ -13574,32 +13585,31 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i
13574
13585
static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, ZigFn *fn_entry, ZigType *fn_type,
13575
13586
IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count, IrInstruction *async_allocator_inst)
13576
13587
{
13577
- Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
13578
- //Buf *free_field_name = buf_create_from_str("freeFn");
13588
+ Buf *realloc_field_name = buf_create_from_str(ASYNC_REALLOC_FIELD_NAME);
13579
13589
assert(async_allocator_inst->value.type->id == ZigTypeIdPointer);
13580
13590
ZigType *container_type = async_allocator_inst->value.type->data.pointer.child_type;
13581
- IrInstruction *field_ptr_inst = ir_analyze_container_field_ptr(ira, alloc_field_name , &call_instruction->base,
13591
+ IrInstruction *field_ptr_inst = ir_analyze_container_field_ptr(ira, realloc_field_name , &call_instruction->base,
13582
13592
async_allocator_inst, container_type);
13583
13593
if (type_is_invalid(field_ptr_inst->value.type)) {
13584
13594
return ira->codegen->invalid_instruction;
13585
13595
}
13586
- ZigType *ptr_to_alloc_fn_type = field_ptr_inst->value.type;
13587
- assert(ptr_to_alloc_fn_type ->id == ZigTypeIdPointer);
13596
+ ZigType *ptr_to_realloc_fn_type = field_ptr_inst->value.type;
13597
+ assert(ptr_to_realloc_fn_type ->id == ZigTypeIdPointer);
13588
13598
13589
- ZigType *alloc_fn_type = ptr_to_alloc_fn_type ->data.pointer.child_type;
13590
- if (alloc_fn_type ->id != ZigTypeIdFn) {
13599
+ ZigType *realloc_fn_type = ptr_to_realloc_fn_type ->data.pointer.child_type;
13600
+ if (realloc_fn_type ->id != ZigTypeIdFn) {
13591
13601
ir_add_error(ira, &call_instruction->base,
13592
- buf_sprintf("expected allocation function, found '%s'", buf_ptr(&alloc_fn_type ->name)));
13602
+ buf_sprintf("expected reallocation function, found '%s'", buf_ptr(&realloc_fn_type ->name)));
13593
13603
return ira->codegen->invalid_instruction;
13594
13604
}
13595
13605
13596
- ZigType *alloc_fn_return_type = alloc_fn_type ->data.fn.fn_type_id.return_type;
13597
- if (alloc_fn_return_type ->id != ZigTypeIdErrorUnion) {
13606
+ ZigType *realloc_fn_return_type = realloc_fn_type ->data.fn.fn_type_id.return_type;
13607
+ if (realloc_fn_return_type ->id != ZigTypeIdErrorUnion) {
13598
13608
ir_add_error(ira, fn_ref,
13599
- buf_sprintf("expected allocation function to return error union, but it returns '%s'", buf_ptr(&alloc_fn_return_type ->name)));
13609
+ buf_sprintf("expected allocation function to return error union, but it returns '%s'", buf_ptr(&realloc_fn_return_type ->name)));
13600
13610
return ira->codegen->invalid_instruction;
13601
13611
}
13602
- ZigType *alloc_fn_error_set_type = alloc_fn_return_type ->data.error_union.err_set_type;
13612
+ ZigType *alloc_fn_error_set_type = realloc_fn_return_type ->data.error_union.err_set_type;
13603
13613
ZigType *return_type = fn_type->data.fn.fn_type_id.return_type;
13604
13614
ZigType *promise_type = get_promise_type(ira->codegen, return_type);
13605
13615
ZigType *async_return_type = get_error_union_type(ira->codegen, alloc_fn_error_set_type, promise_type);
@@ -22033,16 +22043,16 @@ static IrInstruction *ir_analyze_instruction_coro_promise(IrAnalyze *ira, IrInst
22033
22043
}
22034
22044
22035
22045
static IrInstruction *ir_analyze_instruction_coro_alloc_helper(IrAnalyze *ira, IrInstructionCoroAllocHelper *instruction) {
22036
- IrInstruction *alloc_fn = instruction->alloc_fn ->child;
22037
- if (type_is_invalid(alloc_fn ->value.type))
22046
+ IrInstruction *realloc_fn = instruction->realloc_fn ->child;
22047
+ if (type_is_invalid(realloc_fn ->value.type))
22038
22048
return ira->codegen->invalid_instruction;
22039
22049
22040
22050
IrInstruction *coro_size = instruction->coro_size->child;
22041
22051
if (type_is_invalid(coro_size->value.type))
22042
22052
return ira->codegen->invalid_instruction;
22043
22053
22044
22054
IrInstruction *result = ir_build_coro_alloc_helper(&ira->new_irb, instruction->base.scope,
22045
- instruction->base.source_node, alloc_fn , coro_size);
22055
+ instruction->base.source_node, realloc_fn , coro_size);
22046
22056
ZigType *u8_ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, false);
22047
22057
result->value.type = get_optional_type(ira->codegen, u8_ptr_type);
22048
22058
return result;
0 commit comments