From ca1b77b2d51408589659f652b1b1dbe2a25e149f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 22 Feb 2018 11:54:27 -0500 Subject: [PATCH] IR analysis for coro.begin See #727 --- src/all_types.hpp | 8 ++++++ src/codegen.cpp | 6 +++++ src/ir.cpp | 68 ++++++++++++++++++++++++++++++++++++++++++----- src/ir_print.cpp | 9 +++++++ 4 files changed, 84 insertions(+), 7 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index b2d073f698..9575f6cdad 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1490,6 +1490,7 @@ struct CodeGen { TypeTableEntry *entry_u8; TypeTableEntry *entry_u16; TypeTableEntry *entry_u32; + TypeTableEntry *entry_u29; TypeTableEntry *entry_u64; TypeTableEntry *entry_u128; TypeTableEntry *entry_i8; @@ -1966,6 +1967,7 @@ enum IrInstructionId { IrInstructionIdCoroAlloc, IrInstructionIdCoroSize, IrInstructionIdCoroBegin, + IrInstructionIdCoroAllocFail, }; struct IrInstruction { @@ -2836,6 +2838,12 @@ struct IrInstructionCoroBegin { IrInstruction *coro_mem_ptr; }; +struct IrInstructionCoroAllocFail { + IrInstruction base; + + IrInstruction *err_val; +}; + static const size_t slice_ptr_index = 0; static const size_t slice_len_index = 1; diff --git a/src/codegen.cpp b/src/codegen.cpp index e304d3cc24..cb3a98bb88 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3712,6 +3712,9 @@ static LLVMValueRef ir_render_coro_begin(CodeGen *g, IrExecutable *executable, I zig_panic("TODO ir_render_coro_begin"); } +static LLVMValueRef ir_render_coro_alloc_fail(CodeGen *g, IrExecutable *executable, IrInstructionCoroAllocFail *instruction) { + zig_panic("TODO ir_render_coro_alloc_fail"); +} static void set_debug_location(CodeGen *g, IrInstruction *instruction) { AstNode *source_node = instruction->source_node; @@ -3906,6 +3909,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, return ir_render_coro_size(g, executable, (IrInstructionCoroSize *)instruction); case IrInstructionIdCoroBegin: return ir_render_coro_begin(g, executable, (IrInstructionCoroBegin *)instruction); + case IrInstructionIdCoroAllocFail: + return ir_render_coro_alloc_fail(g, executable, (IrInstructionCoroAllocFail *)instruction); } zig_unreachable(); } @@ -5282,6 +5287,7 @@ static void define_builtin_types(CodeGen *g) { g->builtin_types.entry_u8 = get_int_type(g, false, 8); g->builtin_types.entry_u16 = get_int_type(g, false, 16); + g->builtin_types.entry_u29 = get_int_type(g, false, 29); g->builtin_types.entry_u32 = get_int_type(g, false, 32); g->builtin_types.entry_u64 = get_int_type(g, false, 64); g->builtin_types.entry_u128 = get_int_type(g, false, 128); diff --git a/src/ir.cpp b/src/ir.cpp index 7235ad72f2..68d31a7712 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -668,6 +668,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroBegin *) { return IrInstructionIdCoroBegin; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroAllocFail *) { + return IrInstructionIdCoroAllocFail; +} + template static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { T *special_instruction = allocate(1); @@ -810,6 +814,14 @@ static IrInstruction *ir_build_const_usize(IrBuilder *irb, Scope *scope, AstNode return &const_instruction->base; } +static IrInstruction *ir_build_const_u29(IrBuilder *irb, Scope *scope, AstNode *source_node, uint32_t value) { + IrInstructionConst *const_instruction = ir_build_instruction(irb, scope, source_node); + const_instruction->base.value.type = irb->codegen->builtin_types.entry_u29; + const_instruction->base.value.special = ConstValSpecialStatic; + bigint_init_unsigned(&const_instruction->base.value.data.x_bigint, value); + return &const_instruction->base; +} + static IrInstruction *ir_create_const_type(IrBuilder *irb, Scope *scope, AstNode *source_node, TypeTableEntry *type_entry) { @@ -2471,6 +2483,17 @@ static IrInstruction *ir_build_coro_begin(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } +static IrInstruction *ir_build_coro_alloc_fail(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *err_val) { + IrInstructionCoroAllocFail *instruction = ir_build_instruction(irb, scope, source_node); + instruction->base.value.type = irb->codegen->builtin_types.entry_unreachable; + instruction->base.value.special = ConstValSpecialStatic; + instruction->err_val = err_val; + + ir_ref_instruction(err_val, irb->current_basic_block); + + return &instruction->base; +} + static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { results[ReturnKindUnconditional] = 0; results[ReturnKindError] = 0; @@ -5854,23 +5877,22 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME); IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, alloc_field_name); IrInstruction *alloc_fn = ir_build_load_ptr(irb, scope, node, alloc_fn_ptr); - IrInstruction *implicit_allocator = ir_build_load_ptr(irb, scope, node, implicit_allocator_ptr); - IrInstruction *alignment = ir_build_const_usize(irb, scope, node, irb->codegen->pointer_size_bytes * 2); + IrInstruction *alignment = ir_build_const_u29(irb, scope, node, irb->codegen->pointer_size_bytes * 2); size_t arg_count = 3; IrInstruction **args = allocate(arg_count); - args[0] = implicit_allocator; // self + args[0] = implicit_allocator_ptr; // self args[1] = coro_size; // byte_count args[2] = alignment; // alignment IrInstruction *alloc_result = ir_build_call(irb, scope, node, nullptr, alloc_fn, arg_count, args, false, FnInlineAuto, false, nullptr); IrInstruction *alloc_result_ptr = ir_build_ref(irb, scope, node, alloc_result, true, false); - IrInstruction *alloc_result_is_err = ir_build_test_err(irb, scope, node, alloc_result_ptr); + IrInstruction *alloc_result_is_err = ir_build_test_err(irb, scope, node, alloc_result); IrBasicBlock *alloc_err_block = ir_create_basic_block(irb, scope, "AllocError"); IrBasicBlock *alloc_ok_block = ir_create_basic_block(irb, scope, "AllocOk"); ir_build_cond_br(irb, scope, node, alloc_result_is_err, alloc_err_block, alloc_ok_block, is_comptime_false); ir_set_cursor_at_end_and_append_block(irb, alloc_err_block); IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, alloc_result_ptr); - ir_build_return(irb, scope, node, err_val); + ir_build_coro_alloc_fail(irb, scope, node, err_val); ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block); IrInstruction *unwrapped_mem_ptr = ir_build_unwrap_err_payload(irb, scope, node, alloc_result_ptr, false); @@ -16826,18 +16848,47 @@ static TypeTableEntry *ir_analyze_instruction_coro_alloc(IrAnalyze *ira, IrInstr } static TypeTableEntry *ir_analyze_instruction_coro_size(IrAnalyze *ira, IrInstructionCoroSize *instruction) { - zig_panic("TODO ir_analyze_instruction_coro_size"); + IrInstruction *result = ir_build_coro_size(&ira->new_irb, instruction->base.scope, instruction->base.source_node); + ir_link_new_instruction(result, &instruction->base); + result->value.type = ira->codegen->builtin_types.entry_usize; + return result->value.type; } static TypeTableEntry *ir_analyze_instruction_coro_begin(IrAnalyze *ira, IrInstructionCoroBegin *instruction) { - zig_panic("TODO ir_analyze_instruction_coro_begin"); + IrInstruction *coro_id = instruction->coro_id->other; + if (type_is_invalid(coro_id->value.type)) + return ira->codegen->builtin_types.entry_invalid; + + IrInstruction *coro_mem_ptr = instruction->coro_mem_ptr->other; + if (type_is_invalid(coro_mem_ptr->value.type)) + return ira->codegen->builtin_types.entry_invalid; + + FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); + assert(fn_entry != nullptr); + IrInstruction *result = ir_build_coro_begin(&ira->new_irb, instruction->base.scope, instruction->base.source_node, + coro_id, coro_mem_ptr); + ir_link_new_instruction(result, &instruction->base); + result->value.type = get_promise_type(ira->codegen, fn_entry->type_entry->data.fn.fn_type_id.return_type); + return result->value.type; } static TypeTableEntry *ir_analyze_instruction_get_implicit_allocator(IrAnalyze *ira, IrInstructionGetImplicitAllocator *instruction) { IrInstruction *result = ir_get_implicit_allocator(ira, &instruction->base); + ir_link_new_instruction(result, &instruction->base); return result->value.type; } +static TypeTableEntry *ir_analyze_instruction_coro_alloc_fail(IrAnalyze *ira, IrInstructionCoroAllocFail *instruction) { + IrInstruction *err_val = instruction->err_val->other; + if (type_is_invalid(err_val->value.type)) + return ir_unreach_error(ira); + + IrInstruction *result = ir_build_coro_alloc_fail(&ira->new_irb, instruction->base.scope, instruction->base.source_node, err_val); + ir_link_new_instruction(result, &instruction->base); + result->value.type = ira->codegen->builtin_types.entry_unreachable; + return ir_finish_anal(ira, result->value.type); +} + static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { switch (instruction->id) { case IrInstructionIdInvalid: @@ -17052,6 +17103,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi return ir_analyze_instruction_coro_begin(ira, (IrInstructionCoroBegin *)instruction); case IrInstructionIdGetImplicitAllocator: return ir_analyze_instruction_get_implicit_allocator(ira, (IrInstructionGetImplicitAllocator *)instruction); + case IrInstructionIdCoroAllocFail: + return ir_analyze_instruction_coro_alloc_fail(ira, (IrInstructionCoroAllocFail *)instruction); } zig_unreachable(); } @@ -17168,6 +17221,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdCancel: case IrInstructionIdCoroId: case IrInstructionIdCoroBegin: + case IrInstructionIdCoroAllocFail: return true; case IrInstructionIdPhi: diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 186e2711a4..bb49273d5c 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -1052,6 +1052,12 @@ static void ir_print_coro_begin(IrPrint *irp, IrInstructionCoroBegin *instructio fprintf(irp->f, ")"); } +static void ir_print_coro_alloc_fail(IrPrint *irp, IrInstructionCoroAllocFail *instruction) { + fprintf(irp->f, "@coroAllocFail("); + ir_print_other_instruction(irp, instruction->err_val); + fprintf(irp->f, ")"); +} + static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { ir_print_prefix(irp, instruction); switch (instruction->id) { @@ -1390,6 +1396,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { case IrInstructionIdCoroBegin: ir_print_coro_begin(irp, (IrInstructionCoroBegin *)instruction); break; + case IrInstructionIdCoroAllocFail: + ir_print_coro_alloc_fail(irp, (IrInstructionCoroAllocFail *)instruction); + break; } fprintf(irp->f, "\n"); }