| ... | ... | @@ -419,6 +419,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSwitchVar *) { |
| 419 | 419 | return IrInstructionIdSwitchVar; |
| 420 | 420 | } |
| 421 | 421 | |
| 422 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSwitchElseVar *) { |
| 423 | return IrInstructionIdSwitchElseVar; |
| 424 | } |
| 425 | |
| 422 | 426 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSwitchTarget *) { |
| 423 | 427 | return IrInstructionIdSwitchTarget; |
| 424 | 428 | } |
| ... | ... | @@ -1791,7 +1795,7 @@ static IrInstruction *ir_build_pop_count(IrBuilder *irb, Scope *scope, AstNode * |
| 1791 | 1795 | return &instruction->base; |
| 1792 | 1796 | } |
| 1793 | 1797 | |
| 1794 | | static IrInstruction *ir_build_switch_br(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target_value, |
| 1798 | static IrInstructionSwitchBr *ir_build_switch_br(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target_value, |
| 1795 | 1799 | IrBasicBlock *else_block, size_t case_count, IrInstructionSwitchBrCase *cases, IrInstruction *is_comptime, |
| 1796 | 1800 | IrInstruction *switch_prongs_void) |
| 1797 | 1801 | { |
| ... | ... | @@ -1815,7 +1819,7 @@ static IrInstruction *ir_build_switch_br(IrBuilder *irb, Scope *scope, AstNode * |
| 1815 | 1819 | ir_ref_bb(cases[i].block); |
| 1816 | 1820 | } |
| 1817 | 1821 | |
| 1818 | | return &instruction->base; |
| 1822 | return instruction; |
| 1819 | 1823 | } |
| 1820 | 1824 | |
| 1821 | 1825 | static IrInstruction *ir_build_switch_target(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| ... | ... | @@ -1842,6 +1846,18 @@ static IrInstruction *ir_build_switch_var(IrBuilder *irb, Scope *scope, AstNode |
| 1842 | 1846 | return &instruction->base; |
| 1843 | 1847 | } |
| 1844 | 1848 | |
| 1849 | // For this instruction the switch_br must be set later. |
| 1850 | static IrInstructionSwitchElseVar *ir_build_switch_else_var(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1851 | IrInstruction *target_value_ptr) |
| 1852 | { |
| 1853 | IrInstructionSwitchElseVar *instruction = ir_build_instruction<IrInstructionSwitchElseVar>(irb, scope, source_node); |
| 1854 | instruction->target_value_ptr = target_value_ptr; |
| 1855 | |
| 1856 | ir_ref_instruction(target_value_ptr, irb->current_basic_block); |
| 1857 | |
| 1858 | return instruction; |
| 1859 | } |
| 1860 | |
| 1845 | 1861 | static IrInstruction *ir_build_union_tag(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { |
| 1846 | 1862 | IrInstructionUnionTag *instruction = ir_build_instruction<IrInstructionUnionTag>(irb, scope, source_node); |
| 1847 | 1863 | instruction->value = value; |
| ... | ... | @@ -6294,7 +6310,8 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 6294 | 6310 | static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node, |
| 6295 | 6311 | IrBasicBlock *end_block, IrInstruction *is_comptime, IrInstruction *var_is_comptime, |
| 6296 | 6312 | IrInstruction *target_value_ptr, IrInstruction *prong_value, |
| 6297 | | ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values) |
| 6313 | ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values, |
| 6314 | IrInstructionSwitchElseVar **out_switch_else_var) |
| 6298 | 6315 | { |
| 6299 | 6316 | assert(switch_node->type == NodeTypeSwitchExpr); |
| 6300 | 6317 | assert(prong_node->type == NodeTypeSwitchProng); |
| ... | ... | @@ -6312,13 +6329,17 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit |
| 6312 | 6329 | ZigVar *var = ir_create_var(irb, var_symbol_node, scope, |
| 6313 | 6330 | var_name, is_const, is_const, is_shadowable, var_is_comptime); |
| 6314 | 6331 | child_scope = var->child_scope; |
| 6315 | | IrInstruction *var_value; |
| 6316 | | if (prong_value) { |
| 6317 | | IrInstruction *var_ptr_value = ir_build_switch_var(irb, scope, var_symbol_node, target_value_ptr, prong_value); |
| 6318 | | var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, var_symbol_node, var_ptr_value); |
| 6332 | IrInstruction *var_ptr_value; |
| 6333 | if (prong_value != nullptr) { |
| 6334 | var_ptr_value = ir_build_switch_var(irb, scope, var_symbol_node, target_value_ptr, prong_value); |
| 6319 | 6335 | } else { |
| 6320 | | var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr); |
| 6336 | IrInstructionSwitchElseVar *switch_else_var = ir_build_switch_else_var(irb, scope, var_symbol_node, |
| 6337 | target_value_ptr); |
| 6338 | *out_switch_else_var = switch_else_var; |
| 6339 | var_ptr_value = &switch_else_var->base; |
| 6321 | 6340 | } |
| 6341 | IrInstruction *var_value = var_is_ptr ? |
| 6342 | var_ptr_value : ir_build_load_ptr(irb, scope, var_symbol_node, var_ptr_value); |
| 6322 | 6343 | IrInstruction *var_type = nullptr; // infer the type |
| 6323 | 6344 | ir_build_var_decl_src(irb, scope, var_symbol_node, var, var_type, nullptr, var_value); |
| 6324 | 6345 | } else { |
| ... | ... | @@ -6364,6 +6385,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 6364 | 6385 | ZigList<IrBasicBlock *> incoming_blocks = {0}; |
| 6365 | 6386 | ZigList<IrInstructionCheckSwitchProngsRange> check_ranges = {0}; |
| 6366 | 6387 | |
| 6388 | IrInstructionSwitchElseVar *switch_else_var = nullptr; |
| 6389 | |
| 6367 | 6390 | // First do the else and the ranges |
| 6368 | 6391 | Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); |
| 6369 | 6392 | Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); |
| ... | ... | @@ -6384,7 +6407,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 6384 | 6407 | IrBasicBlock *prev_block = irb->current_basic_block; |
| 6385 | 6408 | ir_set_cursor_at_end_and_append_block(irb, else_block); |
| 6386 | 6409 | if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, |
| 6387 | | is_comptime, var_is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values)) |
| 6410 | is_comptime, var_is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values, |
| 6411 | &switch_else_var)) |
| 6388 | 6412 | { |
| 6389 | 6413 | return irb->codegen->invalid_instruction; |
| 6390 | 6414 | } |
| ... | ... | @@ -6451,7 +6475,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 6451 | 6475 | |
| 6452 | 6476 | ir_set_cursor_at_end_and_append_block(irb, range_block_yes); |
| 6453 | 6477 | if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, |
| 6454 | | is_comptime, var_is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values)) |
| 6478 | is_comptime, var_is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values, nullptr)) |
| 6455 | 6479 | { |
| 6456 | 6480 | return irb->codegen->invalid_instruction; |
| 6457 | 6481 | } |
| ... | ... | @@ -6495,7 +6519,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 6495 | 6519 | IrBasicBlock *prev_block = irb->current_basic_block; |
| 6496 | 6520 | ir_set_cursor_at_end_and_append_block(irb, prong_block); |
| 6497 | 6521 | if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, |
| 6498 | | is_comptime, var_is_comptime, target_value_ptr, only_item_value, &incoming_blocks, &incoming_values)) |
| 6522 | is_comptime, var_is_comptime, target_value_ptr, only_item_value, &incoming_blocks, &incoming_values, |
| 6523 | nullptr)) |
| 6499 | 6524 | { |
| 6500 | 6525 | return irb->codegen->invalid_instruction; |
| 6501 | 6526 | } |
| ... | ... | @@ -6510,7 +6535,11 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 6510 | 6535 | if (cases.length == 0) { |
| 6511 | 6536 | ir_build_br(irb, scope, node, else_block, is_comptime); |
| 6512 | 6537 | } else { |
| 6513 | | ir_build_switch_br(irb, scope, node, target_value, else_block, cases.length, cases.items, is_comptime, switch_prongs_void); |
| 6538 | IrInstructionSwitchBr *switch_br = ir_build_switch_br(irb, scope, node, target_value, else_block, |
| 6539 | cases.length, cases.items, is_comptime, switch_prongs_void); |
| 6540 | if (switch_else_var != nullptr) { |
| 6541 | switch_else_var->switch_br = switch_br; |
| 6542 | } |
| 6514 | 6543 | } |
| 6515 | 6544 | |
| 6516 | 6545 | if (!else_prong) { |
| ... | ... | @@ -7474,8 +7503,9 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod |
| 7474 | 7503 | cases[0].block = resume_block; |
| 7475 | 7504 | cases[1].value = ir_mark_gen(ir_build_const_u8(irb, parent_scope, node, 1)); |
| 7476 | 7505 | cases[1].block = canceled_block; |
| 7477 | | ir_mark_gen(ir_build_switch_br(irb, parent_scope, node, suspend_code, irb->exec->coro_suspend_block, |
| 7478 | | 2, cases, const_bool_false, nullptr)); |
| 7506 | IrInstructionSwitchBr *switch_br = ir_build_switch_br(irb, parent_scope, node, suspend_code, |
| 7507 | irb->exec->coro_suspend_block, 2, cases, const_bool_false, nullptr); |
| 7508 | ir_mark_gen(&switch_br->base); |
| 7479 | 7509 | |
| 7480 | 7510 | ir_set_cursor_at_end_and_append_block(irb, cleanup_block); |
| 7481 | 7511 | IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2); |
| ... | ... | @@ -8972,6 +9002,15 @@ static bool slice_is_const(ZigType *type) { |
| 8972 | 9002 | return type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const; |
| 8973 | 9003 | } |
| 8974 | 9004 | |
| 9005 | static void populate_error_set_table(ErrorTableEntry **errors, ZigType *set) { |
| 9006 | assert(set->id == ZigTypeIdErrorSet); |
| 9007 | for (uint32_t i = 0; i < set->data.error_set.err_count; i += 1) { |
| 9008 | ErrorTableEntry *error_entry = set->data.error_set.errors[i]; |
| 9009 | assert(errors[error_entry->value] == nullptr); |
| 9010 | errors[error_entry->value] = error_entry; |
| 9011 | } |
| 9012 | } |
| 9013 | |
| 8975 | 9014 | static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigType *set2, |
| 8976 | 9015 | AstNode *source_node) |
| 8977 | 9016 | { |
| ... | ... | @@ -8991,11 +9030,7 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp |
| 8991 | 9030 | return set1; |
| 8992 | 9031 | } |
| 8993 | 9032 | ErrorTableEntry **errors = allocate<ErrorTableEntry *>(ira->codegen->errors_by_index.length); |
| 8994 | | for (uint32_t i = 0; i < set1->data.error_set.err_count; i += 1) { |
| 8995 | | ErrorTableEntry *error_entry = set1->data.error_set.errors[i]; |
| 8996 | | assert(errors[error_entry->value] == nullptr); |
| 8997 | | errors[error_entry->value] = error_entry; |
| 8998 | | } |
| 9033 | populate_error_set_table(errors, set1); |
| 8999 | 9034 | ZigList<ErrorTableEntry *> intersection_list = {}; |
| 9000 | 9035 | |
| 9001 | 9036 | ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet); |
| ... | ... | @@ -10410,6 +10445,24 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod |
| 10410 | 10445 | return ir_exec_const_result(codegen, analyzed_executable); |
| 10411 | 10446 | } |
| 10412 | 10447 | |
| 10448 | static ErrorTableEntry *ir_resolve_error(IrAnalyze *ira, IrInstruction *err_value) { |
| 10449 | if (type_is_invalid(err_value->value.type)) |
| 10450 | return nullptr; |
| 10451 | |
| 10452 | if (err_value->value.type->id != ZigTypeIdErrorSet) { |
| 10453 | ir_add_error(ira, err_value, |
| 10454 | buf_sprintf("expected error, found '%s'", buf_ptr(&err_value->value.type->name))); |
| 10455 | return nullptr; |
| 10456 | } |
| 10457 | |
| 10458 | ConstExprValue *const_val = ir_resolve_const(ira, err_value, UndefBad); |
| 10459 | if (!const_val) |
| 10460 | return nullptr; |
| 10461 | |
| 10462 | assert(const_val->data.x_err_set != nullptr); |
| 10463 | return const_val->data.x_err_set; |
| 10464 | } |
| 10465 | |
| 10413 | 10466 | static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { |
| 10414 | 10467 | if (type_is_invalid(type_value->value.type)) |
| 10415 | 10468 | return ira->codegen->builtin_types.entry_invalid; |
| ... | ... | @@ -17229,11 +17282,11 @@ static IrInstruction *ir_analyze_instruction_switch_br(IrAnalyze *ira, |
| 17229 | 17282 | } |
| 17230 | 17283 | |
| 17231 | 17284 | IrBasicBlock *new_else_block = ir_get_new_bb(ira, switch_br_instruction->else_block, &switch_br_instruction->base); |
| 17232 | | IrInstruction *result = ir_build_switch_br(&ira->new_irb, |
| 17285 | IrInstructionSwitchBr *switch_br = ir_build_switch_br(&ira->new_irb, |
| 17233 | 17286 | switch_br_instruction->base.scope, switch_br_instruction->base.source_node, |
| 17234 | 17287 | target_value, new_else_block, case_count, cases, nullptr, nullptr); |
| 17235 | | result->value.type = ira->codegen->builtin_types.entry_unreachable; |
| 17236 | | return ir_finish_anal(ira, result); |
| 17288 | switch_br->base.value.type = ira->codegen->builtin_types.entry_unreachable; |
| 17289 | return ir_finish_anal(ira, &switch_br->base); |
| 17237 | 17290 | } |
| 17238 | 17291 | |
| 17239 | 17292 | static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| ... | ... | @@ -17419,6 +17472,85 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru |
| 17419 | 17472 | } |
| 17420 | 17473 | } |
| 17421 | 17474 | |
| 17475 | static IrInstruction *ir_analyze_instruction_switch_else_var(IrAnalyze *ira, |
| 17476 | IrInstructionSwitchElseVar *instruction) |
| 17477 | { |
| 17478 | IrInstruction *target_value_ptr = instruction->target_value_ptr->child; |
| 17479 | if (type_is_invalid(target_value_ptr->value.type)) |
| 17480 | return ira->codegen->invalid_instruction; |
| 17481 | |
| 17482 | ZigType *ref_type = target_value_ptr->value.type; |
| 17483 | assert(ref_type->id == ZigTypeIdPointer); |
| 17484 | ZigType *target_type = target_value_ptr->value.type->data.pointer.child_type; |
| 17485 | if (target_type->id == ZigTypeIdErrorSet) { |
| 17486 | // make a new set that has the other cases removed |
| 17487 | if (!resolve_inferred_error_set(ira->codegen, target_type, instruction->base.source_node)) { |
| 17488 | return ira->codegen->invalid_instruction; |
| 17489 | } |
| 17490 | if (type_is_global_error_set(target_type)) { |
| 17491 | // the type of the else capture variable still has to be the global error set. |
| 17492 | // once the runtime hint system is more sophisticated, we could add some hint information here. |
| 17493 | return target_value_ptr; |
| 17494 | } |
| 17495 | // Make note of the errors handled by other cases |
| 17496 | ErrorTableEntry **errors = allocate<ErrorTableEntry *>(ira->codegen->errors_by_index.length); |
| 17497 | for (size_t case_i = 0; case_i < instruction->switch_br->case_count; case_i += 1) { |
| 17498 | IrInstructionSwitchBrCase *br_case = &instruction->switch_br->cases[case_i]; |
| 17499 | IrInstruction *case_expr = br_case->value->child; |
| 17500 | if (case_expr->value.type->id == ZigTypeIdErrorSet) { |
| 17501 | ErrorTableEntry *err = ir_resolve_error(ira, case_expr); |
| 17502 | if (err == nullptr) |
| 17503 | return ira->codegen->invalid_instruction; |
| 17504 | errors[err->value] = err; |
| 17505 | } else if (case_expr->value.type->id == ZigTypeIdMetaType) { |
| 17506 | ZigType *err_set_type = ir_resolve_type(ira, case_expr); |
| 17507 | if (type_is_invalid(err_set_type)) |
| 17508 | return ira->codegen->invalid_instruction; |
| 17509 | populate_error_set_table(errors, err_set_type); |
| 17510 | } else { |
| 17511 | zig_unreachable(); |
| 17512 | } |
| 17513 | } |
| 17514 | ZigList<ErrorTableEntry *> result_list = {}; |
| 17515 | |
| 17516 | ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet); |
| 17517 | buf_resize(&err_set_type->name, 0); |
| 17518 | buf_appendf(&err_set_type->name, "error{"); |
| 17519 | |
| 17520 | // Look at all the errors in the type switched on and add them to the result_list |
| 17521 | // if they are not handled by cases. |
| 17522 | for (uint32_t i = 0; i < target_type->data.error_set.err_count; i += 1) { |
| 17523 | ErrorTableEntry *error_entry = target_type->data.error_set.errors[i]; |
| 17524 | ErrorTableEntry *existing_entry = errors[error_entry->value]; |
| 17525 | if (existing_entry == nullptr) { |
| 17526 | result_list.append(error_entry); |
| 17527 | buf_appendf(&err_set_type->name, "%s,", buf_ptr(&error_entry->name)); |
| 17528 | } |
| 17529 | } |
| 17530 | free(errors); |
| 17531 | |
| 17532 | err_set_type->data.error_set.err_count = result_list.length; |
| 17533 | err_set_type->data.error_set.errors = result_list.items; |
| 17534 | err_set_type->size_in_bits = ira->codegen->builtin_types.entry_global_error_set->size_in_bits; |
| 17535 | err_set_type->abi_align = ira->codegen->builtin_types.entry_global_error_set->abi_align; |
| 17536 | err_set_type->abi_size = ira->codegen->builtin_types.entry_global_error_set->abi_size; |
| 17537 | |
| 17538 | buf_appendf(&err_set_type->name, "}"); |
| 17539 | |
| 17540 | ZigType *new_target_value_ptr_type = get_pointer_to_type_extra(ira->codegen, |
| 17541 | err_set_type, |
| 17542 | ref_type->data.pointer.is_const, ref_type->data.pointer.is_volatile, |
| 17543 | ref_type->data.pointer.ptr_len, |
| 17544 | ref_type->data.pointer.explicit_alignment, |
| 17545 | ref_type->data.pointer.bit_offset_in_host, ref_type->data.pointer.host_int_bytes, |
| 17546 | ref_type->data.pointer.allow_zero); |
| 17547 | return ir_analyze_ptr_cast(ira, &instruction->base, target_value_ptr, new_target_value_ptr_type, |
| 17548 | &instruction->base, false); |
| 17549 | } |
| 17550 | |
| 17551 | return target_value_ptr; |
| 17552 | } |
| 17553 | |
| 17422 | 17554 | static IrInstruction *ir_analyze_instruction_union_tag(IrAnalyze *ira, IrInstructionUnionTag *instruction) { |
| 17423 | 17555 | IrInstruction *value = instruction->value->child; |
| 17424 | 17556 | return ir_analyze_union_tag(ira, &instruction->base, value); |
| ... | ... | @@ -23094,6 +23226,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 23094 | 23226 | return ir_analyze_instruction_switch_target(ira, (IrInstructionSwitchTarget *)instruction); |
| 23095 | 23227 | case IrInstructionIdSwitchVar: |
| 23096 | 23228 | return ir_analyze_instruction_switch_var(ira, (IrInstructionSwitchVar *)instruction); |
| 23229 | case IrInstructionIdSwitchElseVar: |
| 23230 | return ir_analyze_instruction_switch_else_var(ira, (IrInstructionSwitchElseVar *)instruction); |
| 23097 | 23231 | case IrInstructionIdUnionTag: |
| 23098 | 23232 | return ir_analyze_instruction_union_tag(ira, (IrInstructionUnionTag *)instruction); |
| 23099 | 23233 | case IrInstructionIdImport: |
| ... | ... | @@ -23457,6 +23591,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 23457 | 23591 | case IrInstructionIdCtz: |
| 23458 | 23592 | case IrInstructionIdPopCount: |
| 23459 | 23593 | case IrInstructionIdSwitchVar: |
| 23594 | case IrInstructionIdSwitchElseVar: |
| 23460 | 23595 | case IrInstructionIdSwitchTarget: |
| 23461 | 23596 | case IrInstructionIdUnionTag: |
| 23462 | 23597 | case IrInstructionIdRef: |