From 9c13e9b7ed9806d0f9774433d5e24359aff1b238 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 15 Mar 2019 17:47:47 -0400 Subject: breaking changes to std.mem.Allocator interface API Before, allocator implementations had to provide `allocFn`, `reallocFn`, and `freeFn`. Now, they must provide only `reallocFn` and `shrinkFn`. Reallocating from a zero length slice is allocation, and shrinking to a zero length slice is freeing. When the new memory size is less than or equal to the previous allocation size, `reallocFn` now has the option to return `error.OutOfMemory` to indicate that the allocator would not be able to take advantage of the new size. For more details see #1306. This commit closes #1306. This commit paves the way to solving #2009. This commit also introduces a memory leak to all coroutines. There is an issue where a coroutine calls the function and it frees its own stack frame, but then the return value of `shrinkFn` is a slice, which is implemented as an sret struct. Writing to the return pointer causes invalid memory write. We could work around it by having a global helper function which has a void return type and calling that instead. But instead this hack will suffice until I rework coroutines to be non-allocating. Basically coroutines are not supported right now until they are reworked as in #1194. --- src/codegen.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src/codegen.cpp') diff --git a/src/codegen.cpp b/src/codegen.cpp index df907915bb..2de1243a66 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5177,7 +5177,7 @@ static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_f LLVMValueRef sret_ptr = LLVMBuildAlloca(g->builder, LLVMGetElementType(alloc_fn_arg_types[0]), ""); size_t next_arg = 0; - LLVMValueRef alloc_fn_val = LLVMGetParam(fn_val, next_arg); + LLVMValueRef realloc_fn_val = LLVMGetParam(fn_val, next_arg); next_arg += 1; LLVMValueRef stack_trace_val; @@ -5195,15 +5195,22 @@ static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_f LLVMValueRef alignment_val = LLVMConstInt(g->builtin_types.entry_u29->type_ref, get_coro_frame_align_bytes(g), false); + ConstExprValue *zero_array = create_const_str_lit(g, buf_create_from_str("")); + ConstExprValue *undef_slice_zero = create_const_slice(g, zero_array, 0, 0, false); + render_const_val(g, undef_slice_zero, ""); + render_const_val_global(g, undef_slice_zero, ""); + ZigList args = {}; args.append(sret_ptr); if (g->have_err_ret_tracing) { args.append(stack_trace_val); } args.append(allocator_val); + args.append(undef_slice_zero->global_refs->llvm_global); + args.append(LLVMGetUndef(g->builtin_types.entry_u29->type_ref)); args.append(coro_size); args.append(alignment_val); - LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, alloc_fn_val, args.items, args.length, + LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, realloc_fn_val, args.items, args.length, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, ""); set_call_instr_sret(g, call_instruction); LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, sret_ptr, err_union_err_index, ""); @@ -5239,14 +5246,14 @@ static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_f static LLVMValueRef ir_render_coro_alloc_helper(CodeGen *g, IrExecutable *executable, IrInstructionCoroAllocHelper *instruction) { - LLVMValueRef alloc_fn = ir_llvm_value(g, instruction->alloc_fn); + LLVMValueRef realloc_fn = ir_llvm_value(g, instruction->realloc_fn); LLVMValueRef coro_size = ir_llvm_value(g, instruction->coro_size); - LLVMValueRef fn_val = get_coro_alloc_helper_fn_val(g, LLVMTypeOf(alloc_fn), instruction->alloc_fn->value.type); + LLVMValueRef fn_val = get_coro_alloc_helper_fn_val(g, LLVMTypeOf(realloc_fn), instruction->realloc_fn->value.type); size_t err_code_ptr_arg_index = get_async_err_code_arg_index(g, &g->cur_fn->type_entry->data.fn.fn_type_id); size_t allocator_arg_index = get_async_allocator_arg_index(g, &g->cur_fn->type_entry->data.fn.fn_type_id); ZigList params = {}; - params.append(alloc_fn); + params.append(realloc_fn); uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, g->cur_fn); if (err_ret_trace_arg_index != UINT32_MAX) { params.append(LLVMGetParam(g->cur_fn_val, err_ret_trace_arg_index)); -- cgit v1.2.3