| ... | ... | @@ -1834,14 +1834,17 @@ static IrInstruction *ir_build_switch_target(IrBuilder *irb, Scope *scope, AstNo |
| 1834 | 1834 | } |
| 1835 | 1835 | |
| 1836 | 1836 | static IrInstruction *ir_build_switch_var(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1837 | | IrInstruction *target_value_ptr, IrInstruction *prong_value) |
| 1837 | IrInstruction *target_value_ptr, IrInstruction **prongs_ptr, size_t prongs_len) |
| 1838 | 1838 | { |
| 1839 | 1839 | IrInstructionSwitchVar *instruction = ir_build_instruction<IrInstructionSwitchVar>(irb, scope, source_node); |
| 1840 | 1840 | instruction->target_value_ptr = target_value_ptr; |
| 1841 | | instruction->prong_value = prong_value; |
| 1841 | instruction->prongs_ptr = prongs_ptr; |
| 1842 | instruction->prongs_len = prongs_len; |
| 1842 | 1843 | |
| 1843 | 1844 | ir_ref_instruction(target_value_ptr, irb->current_basic_block); |
| 1844 | | ir_ref_instruction(prong_value, irb->current_basic_block); |
| 1845 | for (size_t i = 0; i < prongs_len; i += 1) { |
| 1846 | ir_ref_instruction(prongs_ptr[i], irb->current_basic_block); |
| 1847 | } |
| 1845 | 1848 | |
| 1846 | 1849 | return &instruction->base; |
| 1847 | 1850 | } |
| ... | ... | @@ -6309,7 +6312,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 6309 | 6312 | |
| 6310 | 6313 | static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node, |
| 6311 | 6314 | IrBasicBlock *end_block, IrInstruction *is_comptime, IrInstruction *var_is_comptime, |
| 6312 | | IrInstruction *target_value_ptr, IrInstruction *prong_value, |
| 6315 | IrInstruction *target_value_ptr, IrInstruction **prong_values, size_t prong_values_len, |
| 6313 | 6316 | ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values, |
| 6314 | 6317 | IrInstructionSwitchElseVar **out_switch_else_var) |
| 6315 | 6318 | { |
| ... | ... | @@ -6336,8 +6339,9 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit |
| 6336 | 6339 | *out_switch_else_var = switch_else_var; |
| 6337 | 6340 | IrInstruction *var_ptr_value = &switch_else_var->base; |
| 6338 | 6341 | var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, var_symbol_node, var_ptr_value); |
| 6339 | | } else if (prong_value != nullptr) { |
| 6340 | | IrInstruction *var_ptr_value = ir_build_switch_var(irb, scope, var_symbol_node, target_value_ptr, prong_value); |
| 6342 | } else if (prong_values != nullptr) { |
| 6343 | IrInstruction *var_ptr_value = ir_build_switch_var(irb, scope, var_symbol_node, target_value_ptr, |
| 6344 | prong_values, prong_values_len); |
| 6341 | 6345 | var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, var_symbol_node, var_ptr_value); |
| 6342 | 6346 | } else { |
| 6343 | 6347 | var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, |
| ... | ... | @@ -6410,7 +6414,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 6410 | 6414 | IrBasicBlock *prev_block = irb->current_basic_block; |
| 6411 | 6415 | ir_set_cursor_at_end_and_append_block(irb, else_block); |
| 6412 | 6416 | if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, |
| 6413 | | is_comptime, var_is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values, |
| 6417 | is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values, |
| 6414 | 6418 | &switch_else_var)) |
| 6415 | 6419 | { |
| 6416 | 6420 | return irb->codegen->invalid_instruction; |
| ... | ... | @@ -6478,7 +6482,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 6478 | 6482 | |
| 6479 | 6483 | ir_set_cursor_at_end_and_append_block(irb, range_block_yes); |
| 6480 | 6484 | if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, |
| 6481 | | is_comptime, var_is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values, nullptr)) |
| 6485 | is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, |
| 6486 | &incoming_blocks, &incoming_values, nullptr)) |
| 6482 | 6487 | { |
| 6483 | 6488 | return irb->codegen->invalid_instruction; |
| 6484 | 6489 | } |
| ... | ... | @@ -6497,7 +6502,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 6497 | 6502 | continue; |
| 6498 | 6503 | |
| 6499 | 6504 | IrBasicBlock *prong_block = ir_create_basic_block(irb, scope, "SwitchProng"); |
| 6500 | | IrInstruction *last_item_value = nullptr; |
| 6505 | IrInstruction **items = allocate<IrInstruction *>(prong_item_count); |
| 6501 | 6506 | |
| 6502 | 6507 | for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) { |
| 6503 | 6508 | AstNode *item_node = prong_node->data.switch_prong.items.at(item_i); |
| ... | ... | @@ -6515,15 +6520,14 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 6515 | 6520 | this_case->value = item_value; |
| 6516 | 6521 | this_case->block = prong_block; |
| 6517 | 6522 | |
| 6518 | | last_item_value = item_value; |
| 6523 | items[item_i] = item_value; |
| 6519 | 6524 | } |
| 6520 | | IrInstruction *only_item_value = (prong_item_count == 1) ? last_item_value : nullptr; |
| 6521 | 6525 | |
| 6522 | 6526 | IrBasicBlock *prev_block = irb->current_basic_block; |
| 6523 | 6527 | ir_set_cursor_at_end_and_append_block(irb, prong_block); |
| 6524 | 6528 | if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, |
| 6525 | | is_comptime, var_is_comptime, target_value_ptr, only_item_value, &incoming_blocks, &incoming_values, |
| 6526 | | nullptr)) |
| 6529 | is_comptime, var_is_comptime, target_value_ptr, items, prong_item_count, |
| 6530 | &incoming_blocks, &incoming_values, nullptr)) |
| 6527 | 6531 | { |
| 6528 | 6532 | return irb->codegen->invalid_instruction; |
| 6529 | 6533 | } |
| ... | ... | @@ -17423,17 +17427,22 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru |
| 17423 | 17427 | if (type_is_invalid(target_value_ptr->value.type)) |
| 17424 | 17428 | return ira->codegen->invalid_instruction; |
| 17425 | 17429 | |
| 17426 | | IrInstruction *prong_value = instruction->prong_value->child; |
| 17427 | | if (type_is_invalid(prong_value->value.type)) |
| 17428 | | return ira->codegen->invalid_instruction; |
| 17429 | | |
| 17430 | | assert(target_value_ptr->value.type->id == ZigTypeIdPointer); |
| 17430 | ZigType *ref_type = target_value_ptr->value.type; |
| 17431 | assert(ref_type->id == ZigTypeIdPointer); |
| 17431 | 17432 | ZigType *target_type = target_value_ptr->value.type->data.pointer.child_type; |
| 17432 | 17433 | if (target_type->id == ZigTypeIdUnion) { |
| 17433 | 17434 | ZigType *enum_type = target_type->data.unionation.tag_type; |
| 17434 | 17435 | assert(enum_type != nullptr); |
| 17435 | 17436 | assert(enum_type->id == ZigTypeIdEnum); |
| 17436 | 17437 | |
| 17438 | if (instruction->prongs_len != 1) { |
| 17439 | return target_value_ptr; |
| 17440 | } |
| 17441 | |
| 17442 | IrInstruction *prong_value = instruction->prongs_ptr[0]->child; |
| 17443 | if (type_is_invalid(prong_value->value.type)) |
| 17444 | return ira->codegen->invalid_instruction; |
| 17445 | |
| 17437 | 17446 | IrInstruction *casted_prong_value = ir_implicit_cast(ira, prong_value, enum_type); |
| 17438 | 17447 | if (type_is_invalid(casted_prong_value->value.type)) |
| 17439 | 17448 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -17468,6 +17477,36 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru |
| 17468 | 17477 | result->value.type = get_pointer_to_type(ira->codegen, field->type_entry, |
| 17469 | 17478 | target_value_ptr->value.type->data.pointer.is_const); |
| 17470 | 17479 | return result; |
| 17480 | } else if (target_type->id == ZigTypeIdErrorSet) { |
| 17481 | // construct an error set from the prong values |
| 17482 | ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet); |
| 17483 | err_set_type->size_in_bits = ira->codegen->builtin_types.entry_global_error_set->size_in_bits; |
| 17484 | err_set_type->abi_align = ira->codegen->builtin_types.entry_global_error_set->abi_align; |
| 17485 | err_set_type->abi_size = ira->codegen->builtin_types.entry_global_error_set->abi_size; |
| 17486 | ZigList<ErrorTableEntry *> error_list = {}; |
| 17487 | buf_resize(&err_set_type->name, 0); |
| 17488 | buf_appendf(&err_set_type->name, "error{"); |
| 17489 | for (size_t i = 0; i < instruction->prongs_len; i += 1) { |
| 17490 | ErrorTableEntry *err = ir_resolve_error(ira, instruction->prongs_ptr[i]->child); |
| 17491 | if (err == nullptr) |
| 17492 | return ira->codegen->invalid_instruction; |
| 17493 | error_list.append(err); |
| 17494 | buf_appendf(&err_set_type->name, "%s,", buf_ptr(&err->name)); |
| 17495 | } |
| 17496 | err_set_type->data.error_set.errors = error_list.items; |
| 17497 | err_set_type->data.error_set.err_count = error_list.length; |
| 17498 | buf_appendf(&err_set_type->name, "}"); |
| 17499 | |
| 17500 | |
| 17501 | ZigType *new_target_value_ptr_type = get_pointer_to_type_extra(ira->codegen, |
| 17502 | err_set_type, |
| 17503 | ref_type->data.pointer.is_const, ref_type->data.pointer.is_volatile, |
| 17504 | ref_type->data.pointer.ptr_len, |
| 17505 | ref_type->data.pointer.explicit_alignment, |
| 17506 | ref_type->data.pointer.bit_offset_in_host, ref_type->data.pointer.host_int_bytes, |
| 17507 | ref_type->data.pointer.allow_zero); |
| 17508 | return ir_analyze_ptr_cast(ira, &instruction->base, target_value_ptr, new_target_value_ptr_type, |
| 17509 | &instruction->base, false); |
| 17471 | 17510 | } else { |
| 17472 | 17511 | ir_add_error(ira, &instruction->base, |
| 17473 | 17512 | buf_sprintf("switch on type '%s' provides no expression parameter", buf_ptr(&target_type->name))); |