| ... | ... | @@ -114,6 +114,8 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 114 | 114 | static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg); |
| 115 | 115 | static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, |
| 116 | 116 | IrInstruction *source_instr, IrInstruction *container_ptr, TypeTableEntry *container_type); |
| 117 | static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 118 | VariableTableEntry *var, bool is_const_ptr, bool is_volatile_ptr); |
| 117 | 119 | |
| 118 | 120 | ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) { |
| 119 | 121 | assert(const_val->type->id == TypeTableEntryIdPointer); |
| ... | ... | @@ -2491,8 +2493,11 @@ static IrInstruction *ir_build_cancel(IrBuilder *irb, Scope *scope, AstNode *sou |
| 2491 | 2493 | return &instruction->base; |
| 2492 | 2494 | } |
| 2493 | 2495 | |
| 2494 | | static IrInstruction *ir_build_get_implicit_allocator(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 2496 | static IrInstruction *ir_build_get_implicit_allocator(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2497 | ImplicitAllocatorId id) |
| 2498 | { |
| 2495 | 2499 | IrInstructionGetImplicitAllocator *instruction = ir_build_instruction<IrInstructionGetImplicitAllocator>(irb, scope, source_node); |
| 2500 | instruction->id = id; |
| 2496 | 2501 | |
| 2497 | 2502 | return &instruction->base; |
| 2498 | 2503 | } |
| ... | ... | @@ -6081,15 +6086,13 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 6081 | 6086 | |
| 6082 | 6087 | FnTableEntry *fn_entry = exec_fn_entry(irb->exec); |
| 6083 | 6088 | bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; |
| 6089 | IrInstruction *coro_id; |
| 6084 | 6090 | IrInstruction *u8_ptr_type; |
| 6085 | 6091 | IrInstruction *const_bool_false; |
| 6086 | | IrInstruction *coro_size; |
| 6087 | | IrInstruction *coro_id; |
| 6088 | | IrInstruction *coro_promise_ptr; |
| 6089 | 6092 | IrInstruction *coro_result_field_ptr; |
| 6090 | | IrInstruction *coro_mem_ptr; |
| 6091 | 6093 | TypeTableEntry *return_type; |
| 6092 | 6094 | Buf *result_ptr_field_name; |
| 6095 | VariableTableEntry *coro_size_var; |
| 6093 | 6096 | if (is_async) { |
| 6094 | 6097 | // create the coro promise |
| 6095 | 6098 | const_bool_false = ir_build_const_bool(irb, scope, node, false); |
| ... | ... | @@ -6099,17 +6102,21 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 6099 | 6102 | return_type = fn_entry->type_entry->data.fn.fn_type_id.return_type; |
| 6100 | 6103 | IrInstruction *promise_init = ir_build_const_promise_init(irb, scope, node, return_type); |
| 6101 | 6104 | ir_build_var_decl(irb, scope, node, promise_var, nullptr, nullptr, promise_init); |
| 6102 | | coro_promise_ptr = ir_build_var_ptr(irb, scope, node, promise_var, false, false); |
| 6105 | IrInstruction *coro_promise_ptr = ir_build_var_ptr(irb, scope, node, promise_var, false, false); |
| 6103 | 6106 | |
| 6104 | 6107 | u8_ptr_type = ir_build_const_type(irb, scope, node, |
| 6105 | 6108 | get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false)); |
| 6106 | 6109 | IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_promise_ptr); |
| 6107 | 6110 | coro_id = ir_build_coro_id(irb, scope, node, promise_as_u8_ptr); |
| 6108 | | coro_size = ir_build_coro_size(irb, scope, node); |
| 6109 | | irb->exec->implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node); |
| 6111 | coro_size_var = ir_create_var(irb, node, scope, nullptr, false, false, true, const_bool_false); |
| 6112 | IrInstruction *coro_size = ir_build_coro_size(irb, scope, node); |
| 6113 | ir_build_var_decl(irb, scope, node, coro_size_var, nullptr, nullptr, coro_size); |
| 6114 | IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node, |
| 6115 | ImplicitAllocatorIdArg); |
| 6116 | irb->exec->coro_allocator_var = ir_create_var(irb, node, scope, nullptr, true, true, true, const_bool_false); |
| 6117 | ir_build_var_decl(irb, scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr); |
| 6110 | 6118 | Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME); |
| 6111 | | IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, irb->exec->implicit_allocator_ptr, |
| 6112 | | alloc_field_name); |
| 6119 | IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, alloc_field_name); |
| 6113 | 6120 | IrInstruction *alloc_fn = ir_build_load_ptr(irb, scope, node, alloc_fn_ptr); |
| 6114 | 6121 | IrInstruction *maybe_coro_mem_ptr = ir_build_coro_alloc_helper(irb, scope, node, alloc_fn, coro_size); |
| 6115 | 6122 | IrInstruction *alloc_result_is_ok = ir_build_test_nonnull(irb, scope, node, maybe_coro_mem_ptr); |
| ... | ... | @@ -6122,7 +6129,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 6122 | 6129 | ir_build_return(irb, scope, node, undef); |
| 6123 | 6130 | |
| 6124 | 6131 | ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block); |
| 6125 | | coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, maybe_coro_mem_ptr); |
| 6132 | IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, maybe_coro_mem_ptr); |
| 6126 | 6133 | irb->exec->coro_handle = ir_build_coro_begin(irb, scope, node, coro_id, coro_mem_ptr); |
| 6127 | 6134 | |
| 6128 | 6135 | Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME); |
| ... | ... | @@ -6200,15 +6207,20 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 6200 | 6207 | IrInstruction *resume_awaiter = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values); |
| 6201 | 6208 | |
| 6202 | 6209 | Buf *free_field_name = buf_create_from_str(ASYNC_FREE_FIELD_NAME); |
| 6203 | | IrInstruction *free_fn_ptr = ir_build_field_ptr(irb, scope, node, irb->exec->implicit_allocator_ptr, |
| 6204 | | free_field_name); |
| 6210 | IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node, |
| 6211 | ImplicitAllocatorIdLocalVar); |
| 6212 | IrInstruction *free_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, free_field_name); |
| 6205 | 6213 | IrInstruction *free_fn = ir_build_load_ptr(irb, scope, node, free_fn_ptr); |
| 6206 | 6214 | IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0); |
| 6215 | IrInstruction *coro_mem_ptr_maybe = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle); |
| 6216 | IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_mem_ptr_maybe); |
| 6207 | 6217 | IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false); |
| 6218 | IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var, true, false); |
| 6219 | IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr); |
| 6208 | 6220 | IrInstruction *mem_slice = ir_build_slice(irb, scope, node, coro_mem_ptr_ref, zero, coro_size, false); |
| 6209 | 6221 | size_t arg_count = 2; |
| 6210 | 6222 | IrInstruction **args = allocate<IrInstruction *>(arg_count); |
| 6211 | | args[0] = irb->exec->implicit_allocator_ptr; // self |
| 6223 | args[0] = implicit_allocator_ptr; // self |
| 6212 | 6224 | args[1] = mem_slice; // old_mem |
| 6213 | 6225 | ir_build_call(irb, scope, node, nullptr, free_fn, arg_count, args, false, FnInlineAuto, false, nullptr); |
| 6214 | 6226 | |
| ... | ... | @@ -11229,7 +11241,7 @@ static TypeTableEntry *ir_analyze_instruction_error_union(IrAnalyze *ira, |
| 11229 | 11241 | return ira->codegen->builtin_types.entry_type; |
| 11230 | 11242 | } |
| 11231 | 11243 | |
| 11232 | | IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_instr) { |
| 11244 | IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_instr, ImplicitAllocatorId id) { |
| 11233 | 11245 | FnTableEntry *parent_fn_entry = exec_fn_entry(ira->new_irb.exec); |
| 11234 | 11246 | if (parent_fn_entry == nullptr) { |
| 11235 | 11247 | ir_add_error(ira, source_instr, buf_sprintf("no implicit allocator available")); |
| ... | ... | @@ -11243,9 +11255,26 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i |
| 11243 | 11255 | } |
| 11244 | 11256 | |
| 11245 | 11257 | assert(parent_fn_type->async_allocator_type != nullptr); |
| 11246 | | IrInstruction *result = ir_build_get_implicit_allocator(&ira->new_irb, source_instr->scope, source_instr->source_node); |
| 11247 | | result->value.type = parent_fn_type->async_allocator_type; |
| 11248 | | return result; |
| 11258 | |
| 11259 | switch (id) { |
| 11260 | case ImplicitAllocatorIdArg: |
| 11261 | { |
| 11262 | IrInstruction *result = ir_build_get_implicit_allocator(&ira->new_irb, source_instr->scope, |
| 11263 | source_instr->source_node, ImplicitAllocatorIdArg); |
| 11264 | result->value.type = parent_fn_type->async_allocator_type; |
| 11265 | return result; |
| 11266 | } |
| 11267 | case ImplicitAllocatorIdLocalVar: |
| 11268 | { |
| 11269 | VariableTableEntry *coro_allocator_var = ira->old_irb.exec->coro_allocator_var; |
| 11270 | assert(coro_allocator_var != nullptr); |
| 11271 | IrInstruction *var_ptr_inst = ir_get_var_ptr(ira, source_instr, coro_allocator_var, true, false); |
| 11272 | IrInstruction *result = ir_get_deref(ira, source_instr, var_ptr_inst); |
| 11273 | assert(result->value.type != nullptr); |
| 11274 | return result; |
| 11275 | } |
| 11276 | } |
| 11277 | zig_unreachable(); |
| 11249 | 11278 | } |
| 11250 | 11279 | |
| 11251 | 11280 | static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, FnTableEntry *fn_entry, TypeTableEntry *fn_type, |
| ... | ... | @@ -11805,7 +11834,8 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 11805 | 11834 | } |
| 11806 | 11835 | IrInstruction *uncasted_async_allocator_inst; |
| 11807 | 11836 | if (call_instruction->async_allocator == nullptr) { |
| 11808 | | uncasted_async_allocator_inst = ir_get_implicit_allocator(ira, &call_instruction->base); |
| 11837 | uncasted_async_allocator_inst = ir_get_implicit_allocator(ira, &call_instruction->base, |
| 11838 | ImplicitAllocatorIdLocalVar); |
| 11809 | 11839 | if (type_is_invalid(uncasted_async_allocator_inst->value.type)) |
| 11810 | 11840 | return ira->codegen->builtin_types.entry_invalid; |
| 11811 | 11841 | } else { |
| ... | ... | @@ -11927,7 +11957,8 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 11927 | 11957 | if (call_instruction->is_async) { |
| 11928 | 11958 | IrInstruction *uncasted_async_allocator_inst; |
| 11929 | 11959 | if (call_instruction->async_allocator == nullptr) { |
| 11930 | | uncasted_async_allocator_inst = ir_get_implicit_allocator(ira, &call_instruction->base); |
| 11960 | uncasted_async_allocator_inst = ir_get_implicit_allocator(ira, &call_instruction->base, |
| 11961 | ImplicitAllocatorIdLocalVar); |
| 11931 | 11962 | if (type_is_invalid(uncasted_async_allocator_inst->value.type)) |
| 11932 | 11963 | return ira->codegen->builtin_types.entry_invalid; |
| 11933 | 11964 | } else { |
| ... | ... | @@ -17189,7 +17220,7 @@ static TypeTableEntry *ir_analyze_instruction_coro_begin(IrAnalyze *ira, IrInstr |
| 17189 | 17220 | } |
| 17190 | 17221 | |
| 17191 | 17222 | static TypeTableEntry *ir_analyze_instruction_get_implicit_allocator(IrAnalyze *ira, IrInstructionGetImplicitAllocator *instruction) { |
| 17192 | | IrInstruction *result = ir_get_implicit_allocator(ira, &instruction->base); |
| 17223 | IrInstruction *result = ir_get_implicit_allocator(ira, &instruction->base, instruction->id); |
| 17193 | 17224 | ir_link_new_instruction(result, &instruction->base); |
| 17194 | 17225 | return result->value.type; |
| 17195 | 17226 | } |