authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-26 21:14:15-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-26 21:14:15-05:00
log4ac6c4d6bfb8f7ada2799ddb5ce3a9797be0518d
tree4ab97ddfa6d660de755eec346162df5125919d23
parent3e86fb500dc918618a2ccaa5d942de98bd5fea47

workaround llvm coro transformations

by making alloc and free functions be parameters to async functions instead of using getelementptr in the DynAlloc block See #727

6 files changed, 179 insertions(+), 69 deletions(-)

src/all_types.hpp+11
...@@ -2208,7 +2208,10 @@ struct IrInstructionCall {...@@ -2208,7 +2208,10 @@ struct IrInstructionCall {
2208 LLVMValueRef tmp_ptr;2208 LLVMValueRef tmp_ptr;
2209 FnInline fn_inline;2209 FnInline fn_inline;
2210 bool is_async;2210 bool is_async;
2211
2211 IrInstruction *async_allocator;2212 IrInstruction *async_allocator;
2213 IrInstruction *alloc_fn;
2214 IrInstruction *free_fn;
2212};2215};
22132216
2214struct IrInstructionConst {2217struct IrInstructionConst {
...@@ -2849,8 +2852,16 @@ struct IrInstructionCancel {...@@ -2849,8 +2852,16 @@ struct IrInstructionCancel {
2849 IrInstruction *target;2852 IrInstruction *target;
2850};2853};
28512854
2855enum ImplicitAllocatorId {
2856 ImplicitAllocatorIdContext,
2857 ImplicitAllocatorIdAlloc,
2858 ImplicitAllocatorIdFree,
2859};
2860
2852struct IrInstructionGetImplicitAllocator {2861struct IrInstructionGetImplicitAllocator {
2853 IrInstruction base;2862 IrInstruction base;
2863
2864 ImplicitAllocatorId id;
2854};2865};
28552866
2856struct IrInstructionCoroId {2867struct IrInstructionCoroId {
src/analyze.cpp+30-4
...@@ -1006,13 +1006,13 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {...@@ -1006,13 +1006,13 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
1006 fn_type_id->return_type->id == TypeTableEntryIdErrorSet);1006 fn_type_id->return_type->id == TypeTableEntryIdErrorSet);
1007 // +1 for maybe making the first argument the return value1007 // +1 for maybe making the first argument the return value
1008 // +1 for maybe first argument the error return trace1008 // +1 for maybe first argument the error return trace
1009 // +2 for maybe arguments async allocator and error code pointer1009 // +4 for maybe arguments async allocator and error code pointer
1010 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(4 + fn_type_id->param_count);1010 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(6 + fn_type_id->param_count);
1011 // +1 because 0 is the return type and1011 // +1 because 0 is the return type and
1012 // +1 for maybe making first arg ret val and1012 // +1 for maybe making first arg ret val and
1013 // +1 for maybe first argument the error return trace1013 // +1 for maybe first argument the error return trace
1014 // +2 for maybe arguments async allocator and error code pointer1014 // +4 for maybe arguments async allocator and error code pointer
1015 ZigLLVMDIType **param_di_types = allocate<ZigLLVMDIType*>(5 + fn_type_id->param_count);1015 ZigLLVMDIType **param_di_types = allocate<ZigLLVMDIType*>(7 + fn_type_id->param_count);
1016 param_di_types[0] = fn_type_id->return_type->di_type;1016 param_di_types[0] = fn_type_id->return_type->di_type;
1017 size_t gen_param_index = 0;1017 size_t gen_param_index = 0;
1018 TypeTableEntry *gen_return_type;1018 TypeTableEntry *gen_return_type;
...@@ -1049,6 +1049,32 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {...@@ -1049,6 +1049,32 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
1049 param_di_types[gen_param_index] = gen_type->di_type;1049 param_di_types[gen_param_index] = gen_type->di_type;
1050 }1050 }
10511051
1052 {
1053 // async alloc fn param
1054 assert(fn_type_id->async_allocator_type->id == TypeTableEntryIdPointer);
1055 TypeTableEntry *struct_type = fn_type_id->async_allocator_type->data.pointer.child_type;
1056 TypeStructField *alloc_fn_field = find_struct_type_field(struct_type, buf_create_from_str("allocFn"));
1057 assert(alloc_fn_field->type_entry->id == TypeTableEntryIdFn);
1058 TypeTableEntry *gen_type = alloc_fn_field->type_entry;
1059 gen_param_types[gen_param_index] = gen_type->type_ref;
1060 gen_param_index += 1;
1061 // after the gen_param_index += 1 because 0 is the return type
1062 param_di_types[gen_param_index] = gen_type->di_type;
1063 }
1064
1065 {
1066 // async free fn param
1067 assert(fn_type_id->async_allocator_type->id == TypeTableEntryIdPointer);
1068 TypeTableEntry *struct_type = fn_type_id->async_allocator_type->data.pointer.child_type;
1069 TypeStructField *free_fn_field = find_struct_type_field(struct_type, buf_create_from_str("freeFn"));
1070 assert(free_fn_field->type_entry->id == TypeTableEntryIdFn);
1071 TypeTableEntry *gen_type = free_fn_field->type_entry;
1072 gen_param_types[gen_param_index] = gen_type->type_ref;
1073 gen_param_index += 1;
1074 // after the gen_param_index += 1 because 0 is the return type
1075 param_di_types[gen_param_index] = gen_type->di_type;
1076 }
1077
1052 {1078 {
1053 // error code pointer1079 // error code pointer
1054 TypeTableEntry *gen_type = get_pointer_to_type(g, g->builtin_types.entry_global_error_set, false);1080 TypeTableEntry *gen_type = get_pointer_to_type(g, g->builtin_types.entry_global_error_set, false);
src/codegen.cpp+31-6
...@@ -2667,6 +2667,18 @@ static bool get_prefix_arg_err_ret_stack(CodeGen *g, TypeTableEntry *src_return_...@@ -2667,6 +2667,18 @@ static bool get_prefix_arg_err_ret_stack(CodeGen *g, TypeTableEntry *src_return_
2667 (src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdErrorSet);2667 (src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdErrorSet);
2668}2668}
26692669
2670static size_t get_async_allocator_arg_index(CodeGen *g, TypeTableEntry *src_return_type) {
2671 // 0 1 2 3 4 5
2672 // err_ret_stack allocator_ptr alloc free err_code other_args...
2673 return get_prefix_arg_err_ret_stack(g, src_return_type) ? 1 : 0;
2674}
2675
2676static size_t get_async_err_code_arg_index(CodeGen *g, TypeTableEntry *src_return_type) {
2677 // 0 1 2 3 4 5
2678 // err_ret_stack allocator_ptr alloc free err_code other_args...
2679 return 3 + get_async_allocator_arg_index(g, src_return_type);
2680}
2681
2670static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) {2682static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) {
2671 LLVMValueRef fn_val;2683 LLVMValueRef fn_val;
2672 TypeTableEntry *fn_type;2684 TypeTableEntry *fn_type;
...@@ -2687,7 +2699,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -2687,7 +2699,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
2687 bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type) &&2699 bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type) &&
2688 calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc);2700 calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc);
2689 bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack(g, src_return_type);2701 bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack(g, src_return_type);
2690 size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0);2702 // +4 for the async args
2703 size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0) + 4;
2691 bool is_var_args = fn_type_id->is_var_args;2704 bool is_var_args = fn_type_id->is_var_args;
2692 LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count);2705 LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count);
2693 size_t gen_param_index = 0;2706 size_t gen_param_index = 0;
...@@ -2703,6 +2716,12 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -2703,6 +2716,12 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
2703 gen_param_values[gen_param_index] = ir_llvm_value(g, instruction->async_allocator);2716 gen_param_values[gen_param_index] = ir_llvm_value(g, instruction->async_allocator);
2704 gen_param_index += 1;2717 gen_param_index += 1;
27052718
2719 gen_param_values[gen_param_index] = ir_llvm_value(g, instruction->alloc_fn);
2720 gen_param_index += 1;
2721
2722 gen_param_values[gen_param_index] = ir_llvm_value(g, instruction->free_fn);
2723 gen_param_index += 1;
2724
2706 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");2725 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");
2707 LLVMBuildStore(g->builder, LLVMConstNull(g->builtin_types.entry_global_error_set->type_ref), err_val_ptr);2726 LLVMBuildStore(g->builder, LLVMConstNull(g->builtin_types.entry_global_error_set->type_ref), err_val_ptr);
2708 gen_param_values[gen_param_index] = err_val_ptr;2727 gen_param_values[gen_param_index] = err_val_ptr;
...@@ -3281,9 +3300,16 @@ static LLVMValueRef ir_render_get_implicit_allocator(CodeGen *g, IrExecutable *e...@@ -3281,9 +3300,16 @@ static LLVMValueRef ir_render_get_implicit_allocator(CodeGen *g, IrExecutable *e
3281 IrInstructionGetImplicitAllocator *instruction)3300 IrInstructionGetImplicitAllocator *instruction)
3282{3301{
3283 TypeTableEntry *src_return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;3302 TypeTableEntry *src_return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
3284 bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack(g, src_return_type);3303 size_t allocator_arg_index = get_async_allocator_arg_index(g, src_return_type);
3285 size_t allocator_arg_index = prefix_arg_err_ret_stack ? 1 : 0;3304 switch (instruction->id) {
3286 return LLVMGetParam(g->cur_fn_val, allocator_arg_index);3305 case ImplicitAllocatorIdContext:
3306 return LLVMGetParam(g->cur_fn_val, allocator_arg_index + 0);
3307 case ImplicitAllocatorIdAlloc:
3308 return LLVMGetParam(g->cur_fn_val, allocator_arg_index + 1);
3309 case ImplicitAllocatorIdFree:
3310 return LLVMGetParam(g->cur_fn_val, allocator_arg_index + 2);
3311 }
3312 zig_unreachable();
3287}3313}
32883314
3289static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) {3315static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) {
...@@ -3915,8 +3941,7 @@ static LLVMValueRef ir_render_coro_alloc_fail(CodeGen *g, IrExecutable *executab...@@ -3915,8 +3941,7 @@ static LLVMValueRef ir_render_coro_alloc_fail(CodeGen *g, IrExecutable *executab
3915 IrInstructionCoroAllocFail *instruction)3941 IrInstructionCoroAllocFail *instruction)
3916{3942{
3917 TypeTableEntry *src_return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;3943 TypeTableEntry *src_return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
3918 bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack(g, src_return_type);3944 size_t err_code_ptr_arg_index = get_async_err_code_arg_index(g, src_return_type);
3919 size_t err_code_ptr_arg_index = prefix_arg_err_ret_stack ? 2 : 1;
3920 LLVMValueRef err_code_ptr_val = LLVMGetParam(g->cur_fn_val, err_code_ptr_arg_index);3945 LLVMValueRef err_code_ptr_val = LLVMGetParam(g->cur_fn_val, err_code_ptr_arg_index);
3921 LLVMValueRef err_code = ir_llvm_value(g, instruction->err_val);3946 LLVMValueRef err_code = ir_llvm_value(g, instruction->err_val);
3922 LLVMBuildStore(g->builder, err_code, err_code_ptr_val);3947 LLVMBuildStore(g->builder, err_code, err_code_ptr_val);
src/ir.cpp+94-42
...@@ -1066,7 +1066,7 @@ static IrInstruction *ir_build_union_field_ptr_from(IrBuilder *irb, IrInstructio...@@ -1066,7 +1066,7 @@ static IrInstruction *ir_build_union_field_ptr_from(IrBuilder *irb, IrInstructio
10661066
1067static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *source_node,1067static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *source_node,
1068 FnTableEntry *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,1068 FnTableEntry *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
1069 bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator)1069 bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator, IrInstruction *alloc_fn, IrInstruction *free_fn)
1070{1070{
1071 IrInstructionCall *call_instruction = ir_build_instruction<IrInstructionCall>(irb, scope, source_node);1071 IrInstructionCall *call_instruction = ir_build_instruction<IrInstructionCall>(irb, scope, source_node);
1072 call_instruction->fn_entry = fn_entry;1072 call_instruction->fn_entry = fn_entry;
...@@ -1077,6 +1077,8 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc...@@ -1077,6 +1077,8 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc
1077 call_instruction->arg_count = arg_count;1077 call_instruction->arg_count = arg_count;
1078 call_instruction->is_async = is_async;1078 call_instruction->is_async = is_async;
1079 call_instruction->async_allocator = async_allocator;1079 call_instruction->async_allocator = async_allocator;
1080 call_instruction->alloc_fn = alloc_fn;
1081 call_instruction->free_fn = free_fn;
10801082
1081 if (fn_ref)1083 if (fn_ref)
1082 ir_ref_instruction(fn_ref, irb->current_basic_block);1084 ir_ref_instruction(fn_ref, irb->current_basic_block);
...@@ -1084,16 +1086,20 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc...@@ -1084,16 +1086,20 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc
1084 ir_ref_instruction(args[i], irb->current_basic_block);1086 ir_ref_instruction(args[i], irb->current_basic_block);
1085 if (async_allocator)1087 if (async_allocator)
1086 ir_ref_instruction(async_allocator, irb->current_basic_block);1088 ir_ref_instruction(async_allocator, irb->current_basic_block);
1089 if (alloc_fn)
1090 ir_ref_instruction(alloc_fn, irb->current_basic_block);
1091 if (free_fn)
1092 ir_ref_instruction(free_fn, irb->current_basic_block);
10871093
1088 return &call_instruction->base;1094 return &call_instruction->base;
1089}1095}
10901096
1091static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_instruction,1097static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_instruction,
1092 FnTableEntry *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,1098 FnTableEntry *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
1093 bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator)1099 bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator, IrInstruction *alloc_fn, IrInstruction *free_fn)
1094{1100{
1095 IrInstruction *new_instruction = ir_build_call(irb, old_instruction->scope,1101 IrInstruction *new_instruction = ir_build_call(irb, old_instruction->scope,
1096 old_instruction->source_node, fn_entry, fn_ref, arg_count, args, is_comptime, fn_inline, is_async, async_allocator);1102 old_instruction->source_node, fn_entry, fn_ref, arg_count, args, is_comptime, fn_inline, is_async, async_allocator, alloc_fn, free_fn);
1097 ir_link_new_instruction(new_instruction, old_instruction);1103 ir_link_new_instruction(new_instruction, old_instruction);
1098 return new_instruction;1104 return new_instruction;
1099}1105}
...@@ -2495,8 +2501,9 @@ static IrInstruction *ir_build_cancel(IrBuilder *irb, Scope *scope, AstNode *sou...@@ -2495,8 +2501,9 @@ static IrInstruction *ir_build_cancel(IrBuilder *irb, Scope *scope, AstNode *sou
2495 return &instruction->base;2501 return &instruction->base;
2496}2502}
24972503
2498static IrInstruction *ir_build_get_implicit_allocator(IrBuilder *irb, Scope *scope, AstNode *source_node) {2504static IrInstruction *ir_build_get_implicit_allocator(IrBuilder *irb, Scope *scope, AstNode *source_node, ImplicitAllocatorId id) {
2499 IrInstructionGetImplicitAllocator *instruction = ir_build_instruction<IrInstructionGetImplicitAllocator>(irb, scope, source_node);2505 IrInstructionGetImplicitAllocator *instruction = ir_build_instruction<IrInstructionGetImplicitAllocator>(irb, scope, source_node);
2506 instruction->id = id;
25002507
2501 return &instruction->base;2508 return &instruction->base;
2502}2509}
...@@ -3970,7 +3977,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -3970,7 +3977,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
3970 }3977 }
3971 FnInline fn_inline = (builtin_fn->id == BuiltinFnIdInlineCall) ? FnInlineAlways : FnInlineNever;3978 FnInline fn_inline = (builtin_fn->id == BuiltinFnIdInlineCall) ? FnInlineAlways : FnInlineNever;
39723979
3973 return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, fn_inline, false, nullptr);3980 return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, fn_inline, false, nullptr, nullptr, nullptr);
3974 }3981 }
3975 case BuiltinFnIdTypeId:3982 case BuiltinFnIdTypeId:
3976 {3983 {
...@@ -4106,15 +4113,25 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node...@@ -4106,15 +4113,25 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
41064113
4107 bool is_async = node->data.fn_call_expr.is_async;4114 bool is_async = node->data.fn_call_expr.is_async;
4108 IrInstruction *async_allocator = nullptr;4115 IrInstruction *async_allocator = nullptr;
4116 IrInstruction *alloc_fn = nullptr;
4117 IrInstruction *free_fn = nullptr;
4109 if (is_async) {4118 if (is_async) {
4110 if (node->data.fn_call_expr.async_allocator) {4119 if (node->data.fn_call_expr.async_allocator) {
4111 async_allocator = ir_gen_node(irb, node->data.fn_call_expr.async_allocator, scope);4120 async_allocator = ir_gen_node(irb, node->data.fn_call_expr.async_allocator, scope);
4112 if (async_allocator == irb->codegen->invalid_instruction)4121 if (async_allocator == irb->codegen->invalid_instruction)
4113 return async_allocator;4122 return async_allocator;
4123
4124 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
4125 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, async_allocator, alloc_field_name);
4126 alloc_fn = ir_build_load_ptr(irb, scope, node, alloc_fn_ptr);
4127
4128 Buf *free_field_name = buf_create_from_str(ASYNC_FREE_FIELD_NAME);
4129 IrInstruction *free_fn_ptr = ir_build_field_ptr(irb, scope, node, async_allocator, free_field_name);
4130 free_fn = ir_build_load_ptr(irb, scope, node, free_fn_ptr);
4114 }4131 }
4115 }4132 }
41164133
4117 return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, is_async, async_allocator);4134 return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, is_async, async_allocator, alloc_fn, free_fn);
4118}4135}
41194136
4120static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node) {4137static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
...@@ -6106,20 +6123,16 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -6106,20 +6123,16 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
61066123
6107 ir_set_cursor_at_end_and_append_block(irb, dyn_alloc_block);6124 ir_set_cursor_at_end_and_append_block(irb, dyn_alloc_block);
6108 IrInstruction *coro_size = ir_build_coro_size(irb, scope, node);6125 IrInstruction *coro_size = ir_build_coro_size(irb, scope, node);
6109 irb->exec->implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node);6126 irb->exec->implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node, ImplicitAllocatorIdContext);
6110 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);6127 IrInstruction *alloc_fn = ir_build_get_implicit_allocator(irb, scope, node, ImplicitAllocatorIdAlloc);
6111 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, irb->exec->implicit_allocator_ptr,6128 IrInstruction *alignment = ir_build_const_u29(irb, scope, node, get_coro_frame_align_bytes(irb->codegen));
6112 alloc_field_name);
6113 IrInstruction *alloc_fn = ir_build_load_ptr(irb, scope, node, alloc_fn_ptr);
6114 IrInstruction *alignment = ir_build_const_u29(irb, scope, node,
6115 get_coro_frame_align_bytes(irb->codegen));
6116 size_t arg_count = 3;6129 size_t arg_count = 3;
6117 IrInstruction **args = allocate<IrInstruction *>(arg_count);6130 IrInstruction **args = allocate<IrInstruction *>(arg_count);
6118 args[0] = irb->exec->implicit_allocator_ptr; // self6131 args[0] = irb->exec->implicit_allocator_ptr; // self
6119 args[1] = coro_size; // byte_count6132 args[1] = coro_size; // byte_count
6120 args[2] = alignment; // alignment6133 args[2] = alignment; // alignment
6121 IrInstruction *alloc_result = ir_build_call(irb, scope, node, nullptr, alloc_fn, arg_count, args, false,6134 IrInstruction *alloc_result = ir_build_call(irb, scope, node, nullptr, alloc_fn, arg_count, args, false,
6122 FnInlineAuto, false, nullptr);6135 FnInlineAuto, false, nullptr, nullptr, nullptr);
6123 IrInstruction *alloc_result_ptr = ir_build_ref(irb, scope, node, alloc_result, true, false);6136 IrInstruction *alloc_result_ptr = ir_build_ref(irb, scope, node, alloc_result, true, false);
6124 IrInstruction *alloc_result_is_err = ir_build_test_err(irb, scope, node, alloc_result);6137 IrInstruction *alloc_result_is_err = ir_build_test_err(irb, scope, node, alloc_result);
6125 IrBasicBlock *alloc_err_block = ir_create_basic_block(irb, scope, "AllocError");6138 IrBasicBlock *alloc_err_block = ir_create_basic_block(irb, scope, "AllocError");
...@@ -6237,15 +6250,12 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -6237,15 +6250,12 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
6237 ir_build_cond_br(irb, scope, node, coro_need_dyn_alloc, dyn_free_block, end_free_block, const_bool_false);6250 ir_build_cond_br(irb, scope, node, coro_need_dyn_alloc, dyn_free_block, end_free_block, const_bool_false);
62386251
6239 ir_set_cursor_at_end_and_append_block(irb, dyn_free_block);6252 ir_set_cursor_at_end_and_append_block(irb, dyn_free_block);
6240 Buf *free_field_name = buf_create_from_str(ASYNC_FREE_FIELD_NAME);6253 IrInstruction *free_fn = ir_build_get_implicit_allocator(irb, scope, node, ImplicitAllocatorIdFree);
6241 IrInstruction *free_fn_ptr = ir_build_field_ptr(irb, scope, node, irb->exec->implicit_allocator_ptr,
6242 free_field_name);
6243 IrInstruction *free_fn = ir_build_load_ptr(irb, scope, node, free_fn_ptr);
6244 size_t arg_count = 2;6254 size_t arg_count = 2;
6245 IrInstruction **args = allocate<IrInstruction *>(arg_count);6255 IrInstruction **args = allocate<IrInstruction *>(arg_count);
6246 args[0] = irb->exec->implicit_allocator_ptr; // self6256 args[0] = irb->exec->implicit_allocator_ptr; // self
6247 args[1] = ir_build_load_ptr(irb, scope, node, coro_unwrapped_mem_ptr); // old_mem6257 args[1] = ir_build_load_ptr(irb, scope, node, coro_unwrapped_mem_ptr); // old_mem
6248 ir_build_call(irb, scope, node, nullptr, free_fn, arg_count, args, false, FnInlineAuto, false, nullptr);6258 ir_build_call(irb, scope, node, nullptr, free_fn, arg_count, args, false, FnInlineAuto, false, nullptr, nullptr, nullptr);
6249 ir_build_br(irb, scope, node, end_free_block, const_bool_false);6259 ir_build_br(irb, scope, node, end_free_block, const_bool_false);
62506260
6251 ir_set_cursor_at_end_and_append_block(irb, end_free_block);6261 ir_set_cursor_at_end_and_append_block(irb, end_free_block);
...@@ -11266,7 +11276,7 @@ static TypeTableEntry *ir_analyze_instruction_error_union(IrAnalyze *ira,...@@ -11266,7 +11276,7 @@ static TypeTableEntry *ir_analyze_instruction_error_union(IrAnalyze *ira,
11266 return ira->codegen->builtin_types.entry_type;11276 return ira->codegen->builtin_types.entry_type;
11267}11277}
1126811278
11269IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_instr) {11279IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_instr, ImplicitAllocatorId id) {
11270 FnTableEntry *parent_fn_entry = exec_fn_entry(ira->new_irb.exec);11280 FnTableEntry *parent_fn_entry = exec_fn_entry(ira->new_irb.exec);
11271 if (parent_fn_entry == nullptr) {11281 if (parent_fn_entry == nullptr) {
11272 ir_add_error(ira, source_instr, buf_sprintf("no implicit allocator available"));11282 ir_add_error(ira, source_instr, buf_sprintf("no implicit allocator available"));
...@@ -11280,27 +11290,39 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i...@@ -11280,27 +11290,39 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i
11280 }11290 }
1128111291
11282 assert(parent_fn_type->async_allocator_type != nullptr);11292 assert(parent_fn_type->async_allocator_type != nullptr);
11283 IrInstruction *result = ir_build_get_implicit_allocator(&ira->new_irb, source_instr->scope, source_instr->source_node);11293 IrInstruction *result = ir_build_get_implicit_allocator(&ira->new_irb, source_instr->scope, source_instr->source_node, id);
11284 result->value.type = parent_fn_type->async_allocator_type;11294 switch (id) {
11295 case ImplicitAllocatorIdContext:
11296 result->value.type = parent_fn_type->async_allocator_type;
11297 break;
11298 case ImplicitAllocatorIdAlloc:
11299 {
11300 assert(parent_fn_type->async_allocator_type->id == TypeTableEntryIdPointer);
11301 TypeTableEntry *struct_type = parent_fn_type->async_allocator_type->data.pointer.child_type;
11302 TypeStructField *alloc_fn_field = find_struct_type_field(struct_type, buf_create_from_str(ASYNC_ALLOC_FIELD_NAME));
11303 assert(alloc_fn_field->type_entry->id == TypeTableEntryIdFn);
11304 result->value.type = alloc_fn_field->type_entry;
11305 break;
11306 }
11307 case ImplicitAllocatorIdFree:
11308 {
11309 assert(parent_fn_type->async_allocator_type->id == TypeTableEntryIdPointer);
11310 TypeTableEntry *struct_type = parent_fn_type->async_allocator_type->data.pointer.child_type;
11311 TypeStructField *free_fn_field = find_struct_type_field(struct_type, buf_create_from_str(ASYNC_FREE_FIELD_NAME));
11312 assert(free_fn_field->type_entry->id == TypeTableEntryIdFn);
11313 result->value.type = free_fn_field->type_entry;
11314 break;
11315 }
11316 }
11285 return result;11317 return result;
11286}11318}
1128711319
11288static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, FnTableEntry *fn_entry, TypeTableEntry *fn_type,11320static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, FnTableEntry *fn_entry, TypeTableEntry *fn_type,
11289 IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count, IrInstruction *async_allocator_inst)11321 IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count, IrInstruction *async_allocator_inst, IrInstruction *alloc_fn, IrInstruction *free_fn)
11290{11322{
11291 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
11292 //Buf *free_field_name = buf_create_from_str("freeFn");
11293 assert(async_allocator_inst->value.type->id == TypeTableEntryIdPointer);11323 assert(async_allocator_inst->value.type->id == TypeTableEntryIdPointer);
11294 TypeTableEntry *container_type = async_allocator_inst->value.type->data.pointer.child_type;
11295 IrInstruction *field_ptr_inst = ir_analyze_container_field_ptr(ira, alloc_field_name, &call_instruction->base,
11296 async_allocator_inst, container_type);
11297 if (type_is_invalid(field_ptr_inst->value.type)) {
11298 return ira->codegen->invalid_instruction;
11299 }
11300 TypeTableEntry *ptr_to_alloc_fn_type = field_ptr_inst->value.type;
11301 assert(ptr_to_alloc_fn_type->id == TypeTableEntryIdPointer);
1130211324
11303 TypeTableEntry *alloc_fn_type = ptr_to_alloc_fn_type->data.pointer.child_type;11325 TypeTableEntry *alloc_fn_type = alloc_fn->value.type;
11304 if (alloc_fn_type->id != TypeTableEntryIdFn) {11326 if (alloc_fn_type->id != TypeTableEntryIdFn) {
11305 ir_add_error(ira, &call_instruction->base,11327 ir_add_error(ira, &call_instruction->base,
11306 buf_sprintf("expected allocation function, found '%s'", buf_ptr(&alloc_fn_type->name)));11328 buf_sprintf("expected allocation function, found '%s'", buf_ptr(&alloc_fn_type->name)));
...@@ -11319,7 +11341,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *c...@@ -11319,7 +11341,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *c
11319 TypeTableEntry *async_return_type = get_error_union_type(ira->codegen, alloc_fn_error_set_type, promise_type);11341 TypeTableEntry *async_return_type = get_error_union_type(ira->codegen, alloc_fn_error_set_type, promise_type);
1132011342
11321 IrInstruction *result = ir_build_call(&ira->new_irb, call_instruction->base.scope, call_instruction->base.source_node,11343 IrInstruction *result = ir_build_call(&ira->new_irb, call_instruction->base.scope, call_instruction->base.source_node,
11322 fn_entry, fn_ref, arg_count, casted_args, false, FnInlineAuto, true, async_allocator_inst);11344 fn_entry, fn_ref, arg_count, casted_args, false, FnInlineAuto, true, async_allocator_inst, alloc_fn, free_fn);
11323 result->value.type = async_return_type;11345 result->value.type = async_return_type;
11324 return result;11346 return result;
11325}11347}
...@@ -11842,7 +11864,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -11842,7 +11864,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
11842 }11864 }
11843 IrInstruction *uncasted_async_allocator_inst;11865 IrInstruction *uncasted_async_allocator_inst;
11844 if (call_instruction->async_allocator == nullptr) {11866 if (call_instruction->async_allocator == nullptr) {
11845 uncasted_async_allocator_inst = ir_get_implicit_allocator(ira, &call_instruction->base);11867 uncasted_async_allocator_inst = ir_get_implicit_allocator(ira, &call_instruction->base, ImplicitAllocatorIdContext);
11846 if (type_is_invalid(uncasted_async_allocator_inst->value.type))11868 if (type_is_invalid(uncasted_async_allocator_inst->value.type))
11847 return ira->codegen->builtin_types.entry_invalid;11869 return ira->codegen->builtin_types.entry_invalid;
11848 } else {11870 } else {
...@@ -11886,15 +11908,25 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -11886,15 +11908,25 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1188611908
11887 size_t impl_param_count = impl_fn->type_entry->data.fn.fn_type_id.param_count;11909 size_t impl_param_count = impl_fn->type_entry->data.fn.fn_type_id.param_count;
11888 if (call_instruction->is_async) {11910 if (call_instruction->is_async) {
11889 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry, fn_ref, casted_args, impl_param_count, async_allocator_inst);11911 IrInstruction *alloc_fn = call_instruction->alloc_fn->other;
11912 if (type_is_invalid(alloc_fn->value.type))
11913 return ira->codegen->builtin_types.entry_invalid;
11914
11915 IrInstruction *free_fn = call_instruction->free_fn->other;
11916 if (type_is_invalid(free_fn->value.type))
11917 return ira->codegen->builtin_types.entry_invalid;
11918
11919 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry, fn_ref, casted_args, impl_param_count,
11920 async_allocator_inst, alloc_fn, free_fn);
11890 ir_link_new_instruction(result, &call_instruction->base);11921 ir_link_new_instruction(result, &call_instruction->base);
11891 ir_add_alloca(ira, result, result->value.type);11922 ir_add_alloca(ira, result, result->value.type);
11892 return ir_finish_anal(ira, result->value.type);11923 return ir_finish_anal(ira, result->value.type);
11893 }11924 }
1189411925
11926 assert(async_allocator_inst == nullptr);
11895 IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base,11927 IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base,
11896 impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline,11928 impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline,
11897 call_instruction->is_async, async_allocator_inst);11929 call_instruction->is_async, nullptr, nullptr, nullptr);
1189811930
11899 ir_add_alloca(ira, new_call_instruction, return_type);11931 ir_add_alloca(ira, new_call_instruction, return_type);
1190011932
...@@ -11961,20 +11993,40 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -11961,20 +11993,40 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1196111993
11962 if (call_instruction->is_async) {11994 if (call_instruction->is_async) {
11963 IrInstruction *uncasted_async_allocator_inst;11995 IrInstruction *uncasted_async_allocator_inst;
11996 IrInstruction *uncasted_alloc_fn_inst;
11997 IrInstruction *uncasted_free_fn_inst;
11964 if (call_instruction->async_allocator == nullptr) {11998 if (call_instruction->async_allocator == nullptr) {
11965 uncasted_async_allocator_inst = ir_get_implicit_allocator(ira, &call_instruction->base);11999 uncasted_async_allocator_inst = ir_get_implicit_allocator(ira, &call_instruction->base, ImplicitAllocatorIdContext);
11966 if (type_is_invalid(uncasted_async_allocator_inst->value.type))12000 if (type_is_invalid(uncasted_async_allocator_inst->value.type))
11967 return ira->codegen->builtin_types.entry_invalid;12001 return ira->codegen->builtin_types.entry_invalid;
12002
12003 uncasted_alloc_fn_inst = ir_get_implicit_allocator(ira, &call_instruction->base, ImplicitAllocatorIdAlloc);
12004 if (type_is_invalid(uncasted_alloc_fn_inst->value.type))
12005 return ira->codegen->builtin_types.entry_invalid;
12006
12007 uncasted_free_fn_inst = ir_get_implicit_allocator(ira, &call_instruction->base, ImplicitAllocatorIdFree);
12008 if (type_is_invalid(uncasted_free_fn_inst->value.type))
12009 return ira->codegen->builtin_types.entry_invalid;
11968 } else {12010 } else {
11969 uncasted_async_allocator_inst = call_instruction->async_allocator->other;12011 uncasted_async_allocator_inst = call_instruction->async_allocator->other;
11970 if (type_is_invalid(uncasted_async_allocator_inst->value.type))12012 if (type_is_invalid(uncasted_async_allocator_inst->value.type))
11971 return ira->codegen->builtin_types.entry_invalid;12013 return ira->codegen->builtin_types.entry_invalid;
12014
12015 uncasted_alloc_fn_inst = call_instruction->alloc_fn->other;
12016 if (type_is_invalid(uncasted_alloc_fn_inst->value.type))
12017 return ira->codegen->builtin_types.entry_invalid;
12018
12019 uncasted_free_fn_inst = call_instruction->free_fn->other;
12020 if (type_is_invalid(uncasted_free_fn_inst->value.type))
12021 return ira->codegen->builtin_types.entry_invalid;
12022
11972 }12023 }
11973 IrInstruction *async_allocator_inst = ir_implicit_cast(ira, uncasted_async_allocator_inst, fn_type_id->async_allocator_type);12024 IrInstruction *async_allocator_inst = ir_implicit_cast(ira, uncasted_async_allocator_inst, fn_type_id->async_allocator_type);
11974 if (type_is_invalid(async_allocator_inst->value.type))12025 if (type_is_invalid(async_allocator_inst->value.type))
11975 return ira->codegen->builtin_types.entry_invalid;12026 return ira->codegen->builtin_types.entry_invalid;
1197612027
11977 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref, casted_args, call_param_count, async_allocator_inst);12028 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref, casted_args, call_param_count,
12029 async_allocator_inst, uncasted_alloc_fn_inst, uncasted_free_fn_inst);
11978 ir_link_new_instruction(result, &call_instruction->base);12030 ir_link_new_instruction(result, &call_instruction->base);
11979 ir_add_alloca(ira, result, result->value.type);12031 ir_add_alloca(ira, result, result->value.type);
11980 return ir_finish_anal(ira, result->value.type);12032 return ir_finish_anal(ira, result->value.type);
...@@ -11982,7 +12034,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -11982,7 +12034,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1198212034
1198312035
11984 IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base,12036 IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base,
11985 fn_entry, fn_ref, call_param_count, casted_args, false, fn_inline, false, nullptr);12037 fn_entry, fn_ref, call_param_count, casted_args, false, fn_inline, false, nullptr, nullptr, nullptr);
1198612038
11987 ir_add_alloca(ira, new_call_instruction, return_type);12039 ir_add_alloca(ira, new_call_instruction, return_type);
11988 return ir_finish_anal(ira, return_type);12040 return ir_finish_anal(ira, return_type);
...@@ -17222,7 +17274,7 @@ static TypeTableEntry *ir_analyze_instruction_coro_begin(IrAnalyze *ira, IrInstr...@@ -17222,7 +17274,7 @@ static TypeTableEntry *ir_analyze_instruction_coro_begin(IrAnalyze *ira, IrInstr
17222}17274}
1722317275
17224static TypeTableEntry *ir_analyze_instruction_get_implicit_allocator(IrAnalyze *ira, IrInstructionGetImplicitAllocator *instruction) {17276static TypeTableEntry *ir_analyze_instruction_get_implicit_allocator(IrAnalyze *ira, IrInstructionGetImplicitAllocator *instruction) {
17225 IrInstruction *result = ir_get_implicit_allocator(ira, &instruction->base);17277 IrInstruction *result = ir_get_implicit_allocator(ira, &instruction->base, instruction->id);
17226 ir_link_new_instruction(result, &instruction->base);17278 ir_link_new_instruction(result, &instruction->base);
17227 return result->value.type;17279 return result->value.type;
17228}17280}
src/ir_print.cpp+13-1
...@@ -1027,7 +1027,19 @@ static void ir_print_cancel(IrPrint *irp, IrInstructionCancel *instruction) {...@@ -1027,7 +1027,19 @@ static void ir_print_cancel(IrPrint *irp, IrInstructionCancel *instruction) {
1027}1027}
10281028
1029static void ir_print_get_implicit_allocator(IrPrint *irp, IrInstructionGetImplicitAllocator *instruction) {1029static void ir_print_get_implicit_allocator(IrPrint *irp, IrInstructionGetImplicitAllocator *instruction) {
1030 fprintf(irp->f, "@getImplicitAllocator()");1030 fprintf(irp->f, "@getImplicitAllocator(");
1031 switch (instruction->id) {
1032 case ImplicitAllocatorIdContext:
1033 fprintf(irp->f, "Context");
1034 break;
1035 case ImplicitAllocatorIdAlloc:
1036 fprintf(irp->f, "Alloc");
1037 break;
1038 case ImplicitAllocatorIdFree:
1039 fprintf(irp->f, "Free");
1040 break;
1041 }
1042 fprintf(irp->f, ")");
1031}1043}
10321044
1033static void ir_print_coro_id(IrPrint *irp, IrInstructionCoroId *instruction) {1045static void ir_print_coro_id(IrPrint *irp, IrInstructionCoroId *instruction) {
std/mem.zig-16
...@@ -116,22 +116,6 @@ pub const Allocator = struct {...@@ -116,22 +116,6 @@ pub const Allocator = struct {
116 const non_const_ptr = @intToPtr(&u8, @ptrToInt(bytes.ptr));116 const non_const_ptr = @intToPtr(&u8, @ptrToInt(bytes.ptr));
117 self.freeFn(self, non_const_ptr[0..bytes.len]);117 self.freeFn(self, non_const_ptr[0..bytes.len]);
118 }118 }
119
120 pub const AsyncAllocator = struct {
121 allocator: &Allocator,
122
123 fn alloc(self: &const AsyncAllocator, byte_count: usize, alignment: u29) Error![]u8 {
124 return self.allocator.allocFn(self.allocator, byte_count, alignment);
125 }
126
127 fn free(self: &const AsyncAllocator, old_mem: []u8) void {
128 return self.allocator.freeFn(self.allocator, old_mem);
129 }
130 };
131
132 fn toAsync(self: &Allocator) AsyncAllocator {
133 return AsyncAllocator { .allocator = self };
134 }
135};119};
136120
137/// Copy all of source into dest at position 0.121/// Copy all of source into dest at position 0.