authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-06 14:58:24-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-06 14:58:24-05:00
log04612d25d7d33e8c3f08301d668ab94fe7479c84
tree082688c8fa8d27618bea69995a57a50f8700314f
parentb66fb7ceae9029935e5cf3c3752d240a74b6cd7c
parent249cb2aa30bbdd0c30f24ef18097e3b1cd3e0da5

Merge branch 'master' into self-hosted


3 files changed, 166 insertions(+), 35 deletions(-)

src/ir.cpp+129-35
...@@ -7468,6 +7468,17 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,...@@ -7468,6 +7468,17 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
7468 }7468 }
7469 }7469 }
74707470
7471 // implicit union to its enum tag type
7472 if (expected_type->id == TypeTableEntryIdEnum && actual_type->id == TypeTableEntryIdUnion &&
7473 (actual_type->data.unionation.decl_node->data.container_decl.auto_enum ||
7474 actual_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
7475 {
7476 type_ensure_zero_bits_known(ira->codegen, actual_type);
7477 if (actual_type->data.unionation.tag_type == expected_type) {
7478 return ImplicitCastMatchResultYes;
7479 }
7480 }
7481
7471 // implicit enum to union which has the enum as the tag type7482 // implicit enum to union which has the enum as the tag type
7472 if (expected_type->id == TypeTableEntryIdUnion && actual_type->id == TypeTableEntryIdEnum &&7483 if (expected_type->id == TypeTableEntryIdUnion && actual_type->id == TypeTableEntryIdEnum &&
7473 (expected_type->data.unionation.decl_node->data.container_decl.auto_enum ||7484 (expected_type->data.unionation.decl_node->data.container_decl.auto_enum ||
...@@ -7508,33 +7519,53 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod...@@ -7508,33 +7519,53 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
7508 IrInstruction *cur_inst = instructions[i];7519 IrInstruction *cur_inst = instructions[i];
7509 TypeTableEntry *cur_type = cur_inst->value.type;7520 TypeTableEntry *cur_type = cur_inst->value.type;
7510 TypeTableEntry *prev_type = prev_inst->value.type;7521 TypeTableEntry *prev_type = prev_inst->value.type;
7522
7511 if (type_is_invalid(cur_type)) {7523 if (type_is_invalid(cur_type)) {
7512 return cur_type;7524 return cur_type;
7513 } else if (prev_type->id == TypeTableEntryIdUnreachable) {7525 }
7526
7527 if (prev_type->id == TypeTableEntryIdUnreachable) {
7514 prev_inst = cur_inst;7528 prev_inst = cur_inst;
7515 } else if (cur_type->id == TypeTableEntryIdUnreachable) {
7516 continue;7529 continue;
7517 } else if (prev_type->id == TypeTableEntryIdPureError) {7530 }
7531
7532 if (cur_type->id == TypeTableEntryIdUnreachable) {
7533 continue;
7534 }
7535
7536 if (prev_type->id == TypeTableEntryIdPureError) {
7518 prev_inst = cur_inst;7537 prev_inst = cur_inst;
7519 continue;7538 continue;
7520 } else if (prev_type->id == TypeTableEntryIdNullLit) {7539 }
7540
7541 if (prev_type->id == TypeTableEntryIdNullLit) {
7521 prev_inst = cur_inst;7542 prev_inst = cur_inst;
7522 continue;7543 continue;
7523 } else if (cur_type->id == TypeTableEntryIdPureError) {7544 }
7545
7546 if (cur_type->id == TypeTableEntryIdPureError) {
7524 if (prev_type->id == TypeTableEntryIdArray) {7547 if (prev_type->id == TypeTableEntryIdArray) {
7525 convert_to_const_slice = true;7548 convert_to_const_slice = true;
7526 }7549 }
7527 any_are_pure_error = true;7550 any_are_pure_error = true;
7528 continue;7551 continue;
7529 } else if (cur_type->id == TypeTableEntryIdNullLit) {7552 }
7553
7554 if (cur_type->id == TypeTableEntryIdNullLit) {
7530 any_are_null = true;7555 any_are_null = true;
7531 continue;7556 continue;
7532 } else if (types_match_const_cast_only(prev_type, cur_type)) {7557 }
7558
7559 if (types_match_const_cast_only(prev_type, cur_type)) {
7533 continue;7560 continue;
7534 } else if (types_match_const_cast_only(cur_type, prev_type)) {7561 }
7562
7563 if (types_match_const_cast_only(cur_type, prev_type)) {
7535 prev_inst = cur_inst;7564 prev_inst = cur_inst;
7536 continue;7565 continue;
7537 } else if (prev_type->id == TypeTableEntryIdInt &&7566 }
7567
7568 if (prev_type->id == TypeTableEntryIdInt &&
7538 cur_type->id == TypeTableEntryIdInt &&7569 cur_type->id == TypeTableEntryIdInt &&
7539 prev_type->data.integral.is_signed == cur_type->data.integral.is_signed)7570 prev_type->data.integral.is_signed == cur_type->data.integral.is_signed)
7540 {7571 {
...@@ -7542,36 +7573,51 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod...@@ -7542,36 +7573,51 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
7542 prev_inst = cur_inst;7573 prev_inst = cur_inst;
7543 }7574 }
7544 continue;7575 continue;
7545 } else if (prev_type->id == TypeTableEntryIdFloat &&7576 }
7546 cur_type->id == TypeTableEntryIdFloat)7577
7547 {7578 if (prev_type->id == TypeTableEntryIdFloat && cur_type->id == TypeTableEntryIdFloat) {
7548 if (cur_type->data.floating.bit_count > prev_type->data.floating.bit_count) {7579 if (cur_type->data.floating.bit_count > prev_type->data.floating.bit_count) {
7549 prev_inst = cur_inst;7580 prev_inst = cur_inst;
7550 }7581 }
7551 } else if (prev_type->id == TypeTableEntryIdErrorUnion &&7582 continue;
7583 }
7584
7585 if (prev_type->id == TypeTableEntryIdErrorUnion &&
7552 types_match_const_cast_only(prev_type->data.error.child_type, cur_type))7586 types_match_const_cast_only(prev_type->data.error.child_type, cur_type))
7553 {7587 {
7554 continue;7588 continue;
7555 } else if (cur_type->id == TypeTableEntryIdErrorUnion &&7589 }
7590
7591 if (cur_type->id == TypeTableEntryIdErrorUnion &&
7556 types_match_const_cast_only(cur_type->data.error.child_type, prev_type))7592 types_match_const_cast_only(cur_type->data.error.child_type, prev_type))
7557 {7593 {
7558 prev_inst = cur_inst;7594 prev_inst = cur_inst;
7559 continue;7595 continue;
7560 } else if (prev_type->id == TypeTableEntryIdMaybe &&7596 }
7597
7598 if (prev_type->id == TypeTableEntryIdMaybe &&
7561 types_match_const_cast_only(prev_type->data.maybe.child_type, cur_type))7599 types_match_const_cast_only(prev_type->data.maybe.child_type, cur_type))
7562 {7600 {
7563 continue;7601 continue;
7564 } else if (cur_type->id == TypeTableEntryIdMaybe &&7602 }
7603
7604 if (cur_type->id == TypeTableEntryIdMaybe &&
7565 types_match_const_cast_only(cur_type->data.maybe.child_type, prev_type))7605 types_match_const_cast_only(cur_type->data.maybe.child_type, prev_type))
7566 {7606 {
7567 prev_inst = cur_inst;7607 prev_inst = cur_inst;
7568 continue;7608 continue;
7569 } else if (cur_type->id == TypeTableEntryIdUndefLit) {7609 }
7610
7611 if (cur_type->id == TypeTableEntryIdUndefLit) {
7570 continue;7612 continue;
7571 } else if (prev_type->id == TypeTableEntryIdUndefLit) {7613 }
7614
7615 if (prev_type->id == TypeTableEntryIdUndefLit) {
7572 prev_inst = cur_inst;7616 prev_inst = cur_inst;
7573 continue;7617 continue;
7574 } else if (prev_type->id == TypeTableEntryIdNumLitInt ||7618 }
7619
7620 if (prev_type->id == TypeTableEntryIdNumLitInt ||
7575 prev_type->id == TypeTableEntryIdNumLitFloat)7621 prev_type->id == TypeTableEntryIdNumLitFloat)
7576 {7622 {
7577 if (ir_num_lit_fits_in_other_type(ira, prev_inst, cur_type, false)) {7623 if (ir_num_lit_fits_in_other_type(ira, prev_inst, cur_type, false)) {
...@@ -7580,7 +7626,9 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod...@@ -7580,7 +7626,9 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
7580 } else {7626 } else {
7581 return ira->codegen->builtin_types.entry_invalid;7627 return ira->codegen->builtin_types.entry_invalid;
7582 }7628 }
7583 } else if (cur_type->id == TypeTableEntryIdNumLitInt ||7629 }
7630
7631 if (cur_type->id == TypeTableEntryIdNumLitInt ||
7584 cur_type->id == TypeTableEntryIdNumLitFloat)7632 cur_type->id == TypeTableEntryIdNumLitFloat)
7585 {7633 {
7586 if (ir_num_lit_fits_in_other_type(ira, cur_inst, prev_type, false)) {7634 if (ir_num_lit_fits_in_other_type(ira, cur_inst, prev_type, false)) {
...@@ -7588,20 +7636,26 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod...@@ -7588,20 +7636,26 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
7588 } else {7636 } else {
7589 return ira->codegen->builtin_types.entry_invalid;7637 return ira->codegen->builtin_types.entry_invalid;
7590 }7638 }
7591 } else if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&7639 }
7640
7641 if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&
7592 cur_type->data.array.len != prev_type->data.array.len &&7642 cur_type->data.array.len != prev_type->data.array.len &&
7593 types_match_const_cast_only(cur_type->data.array.child_type, prev_type->data.array.child_type))7643 types_match_const_cast_only(cur_type->data.array.child_type, prev_type->data.array.child_type))
7594 {7644 {
7595 convert_to_const_slice = true;7645 convert_to_const_slice = true;
7596 prev_inst = cur_inst;7646 prev_inst = cur_inst;
7597 continue;7647 continue;
7598 } else if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&7648 }
7649
7650 if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&
7599 cur_type->data.array.len != prev_type->data.array.len &&7651 cur_type->data.array.len != prev_type->data.array.len &&
7600 types_match_const_cast_only(prev_type->data.array.child_type, cur_type->data.array.child_type))7652 types_match_const_cast_only(prev_type->data.array.child_type, cur_type->data.array.child_type))
7601 {7653 {
7602 convert_to_const_slice = true;7654 convert_to_const_slice = true;
7603 continue;7655 continue;
7604 } else if (cur_type->id == TypeTableEntryIdArray && is_slice(prev_type) &&7656 }
7657
7658 if (cur_type->id == TypeTableEntryIdArray && is_slice(prev_type) &&
7605 (prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||7659 (prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||
7606 cur_type->data.array.len == 0) &&7660 cur_type->data.array.len == 0) &&
7607 types_match_const_cast_only(prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,7661 types_match_const_cast_only(prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
...@@ -7609,7 +7663,9 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod...@@ -7609,7 +7663,9 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
7609 {7663 {
7610 convert_to_const_slice = false;7664 convert_to_const_slice = false;
7611 continue;7665 continue;
7612 } else if (prev_type->id == TypeTableEntryIdArray && is_slice(cur_type) &&7666 }
7667
7668 if (prev_type->id == TypeTableEntryIdArray && is_slice(cur_type) &&
7613 (cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||7669 (cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||
7614 prev_type->data.array.len == 0) &&7670 prev_type->data.array.len == 0) &&
7615 types_match_const_cast_only(cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,7671 types_match_const_cast_only(cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
...@@ -7618,17 +7674,40 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod...@@ -7618,17 +7674,40 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
7618 prev_inst = cur_inst;7674 prev_inst = cur_inst;
7619 convert_to_const_slice = false;7675 convert_to_const_slice = false;
7620 continue;7676 continue;
7621 } else {7677 }
7622 ErrorMsg *msg = ir_add_error_node(ira, source_node,
7623 buf_sprintf("incompatible types: '%s' and '%s'",
7624 buf_ptr(&prev_type->name), buf_ptr(&cur_type->name)));
7625 add_error_note(ira->codegen, msg, prev_inst->source_node,
7626 buf_sprintf("type '%s' here", buf_ptr(&prev_type->name)));
7627 add_error_note(ira->codegen, msg, cur_inst->source_node,
7628 buf_sprintf("type '%s' here", buf_ptr(&cur_type->name)));
76297678
7630 return ira->codegen->builtin_types.entry_invalid;7679 if (prev_type->id == TypeTableEntryIdEnum && cur_type->id == TypeTableEntryIdUnion &&
7680 (cur_type->data.unionation.decl_node->data.container_decl.auto_enum || cur_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
7681 {
7682 type_ensure_zero_bits_known(ira->codegen, cur_type);
7683 if (type_is_invalid(cur_type))
7684 return ira->codegen->builtin_types.entry_invalid;
7685 if (cur_type->data.unionation.tag_type == prev_type) {
7686 continue;
7687 }
7688 }
7689
7690 if (cur_type->id == TypeTableEntryIdEnum && prev_type->id == TypeTableEntryIdUnion &&
7691 (prev_type->data.unionation.decl_node->data.container_decl.auto_enum || prev_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
7692 {
7693 type_ensure_zero_bits_known(ira->codegen, prev_type);
7694 if (type_is_invalid(prev_type))
7695 return ira->codegen->builtin_types.entry_invalid;
7696 if (prev_type->data.unionation.tag_type == cur_type) {
7697 prev_inst = cur_inst;
7698 continue;
7699 }
7631 }7700 }
7701
7702 ErrorMsg *msg = ir_add_error_node(ira, source_node,
7703 buf_sprintf("incompatible types: '%s' and '%s'",
7704 buf_ptr(&prev_type->name), buf_ptr(&cur_type->name)));
7705 add_error_note(ira->codegen, msg, prev_inst->source_node,
7706 buf_sprintf("type '%s' here", buf_ptr(&prev_type->name)));
7707 add_error_note(ira->codegen, msg, cur_inst->source_node,
7708 buf_sprintf("type '%s' here", buf_ptr(&cur_type->name)));
7709
7710 return ira->codegen->builtin_types.entry_invalid;
7632 }7711 }
7633 if (convert_to_const_slice) {7712 if (convert_to_const_slice) {
7634 assert(prev_inst->value.type->id == TypeTableEntryIdArray);7713 assert(prev_inst->value.type->id == TypeTableEntryIdArray);
...@@ -9425,6 +9504,10 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -9425,6 +9504,10 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
9425 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, bin_op_instruction->base.source_node, instructions, 2);9504 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, bin_op_instruction->base.source_node, instructions, 2);
9426 if (type_is_invalid(resolved_type))9505 if (type_is_invalid(resolved_type))
9427 return resolved_type;9506 return resolved_type;
9507 type_ensure_zero_bits_known(ira->codegen, resolved_type);
9508 if (type_is_invalid(resolved_type))
9509 return resolved_type;
9510
94289511
9429 AstNode *source_node = bin_op_instruction->base.source_node;9512 AstNode *source_node = bin_op_instruction->base.source_node;
9430 switch (resolved_type->id) {9513 switch (resolved_type->id) {
...@@ -9489,7 +9572,8 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -9489,7 +9572,8 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
94899572
9490 ConstExprValue *op1_val = &casted_op1->value;9573 ConstExprValue *op1_val = &casted_op1->value;
9491 ConstExprValue *op2_val = &casted_op2->value;9574 ConstExprValue *op2_val = &casted_op2->value;
9492 if ((value_is_comptime(op1_val) && value_is_comptime(op2_val)) || resolved_type->id == TypeTableEntryIdVoid) {9575 bool one_possible_value = !type_requires_comptime(resolved_type) && !type_has_bits(resolved_type);
9576 if (one_possible_value || (value_is_comptime(op1_val) && value_is_comptime(op2_val))) {
9493 bool answer;9577 bool answer;
9494 if (resolved_type->id == TypeTableEntryIdNumLitFloat || resolved_type->id == TypeTableEntryIdFloat) {9578 if (resolved_type->id == TypeTableEntryIdNumLitFloat || resolved_type->id == TypeTableEntryIdFloat) {
9495 Cmp cmp_result = float_cmp(op1_val, op2_val);9579 Cmp cmp_result = float_cmp(op1_val, op2_val);
...@@ -9498,7 +9582,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -9498,7 +9582,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
9498 Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);9582 Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);
9499 answer = resolve_cmp_op_id(op_id, cmp_result);9583 answer = resolve_cmp_op_id(op_id, cmp_result);
9500 } else {9584 } else {
9501 bool are_equal = resolved_type->id == TypeTableEntryIdVoid || const_values_equal(op1_val, op2_val);9585 bool are_equal = one_possible_value || const_values_equal(op1_val, op2_val);
9502 if (op_id == IrBinOpCmpEq) {9586 if (op_id == IrBinOpCmpEq) {
9503 answer = are_equal;9587 answer = are_equal;
9504 } else if (op_id == IrBinOpCmpNotEq) {9588 } else if (op_id == IrBinOpCmpNotEq) {
...@@ -13090,6 +13174,16 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -13090,6 +13174,16 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
13090 return tag_type;13174 return tag_type;
13091 }13175 }
13092 case TypeTableEntryIdEnum: {13176 case TypeTableEntryIdEnum: {
13177 type_ensure_zero_bits_known(ira->codegen, target_type);
13178 if (type_is_invalid(target_type))
13179 return ira->codegen->builtin_types.entry_invalid;
13180 if (target_type->data.enumeration.src_field_count < 2) {
13181 TypeEnumField *only_field = &target_type->data.enumeration.fields[0];
13182 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
13183 bigint_init_bigint(&out_val->data.x_enum_tag, &only_field->value);
13184 return target_type;
13185 }
13186
13093 if (pointee_val) {13187 if (pointee_val) {
13094 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);13188 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
13095 bigint_init_bigint(&out_val->data.x_enum_tag, &pointee_val->data.x_enum_tag);13189 bigint_init_bigint(&out_val->data.x_enum_tag, &pointee_val->data.x_enum_tag);
test/cases/enum.zig+28
...@@ -349,3 +349,31 @@ test "cast integer literal to enum" {...@@ -349,3 +349,31 @@ test "cast integer literal to enum" {
349 assert(MultipleChoice2(0) == MultipleChoice2.Unspecified1);349 assert(MultipleChoice2(0) == MultipleChoice2.Unspecified1);
350 assert(MultipleChoice2(40) == MultipleChoice2.B);350 assert(MultipleChoice2(40) == MultipleChoice2.B);
351}351}
352
353const EnumWithOneMember = enum {
354 Eof,
355};
356
357fn doALoopThing(id: EnumWithOneMember) {
358 while (true) {
359 if (id == EnumWithOneMember.Eof) {
360 break;
361 }
362 @compileError("above if condition should be comptime");
363 }
364}
365
366test "comparison operator on enum with one member is comptime known" {
367 doALoopThing(EnumWithOneMember.Eof);
368}
369
370const State = enum {
371 Start,
372};
373test "switch on enum with one member is comptime known" {
374 var state = State.Start;
375 switch (state) {
376 State.Start => return,
377 }
378 @compileError("analysis should not reach here");
379}
test/cases/union.zig+9
...@@ -197,3 +197,12 @@ test "cast tag type of union to union" {...@@ -197,3 +197,12 @@ test "cast tag type of union to union" {
197}197}
198const Letter2 = enum { A, B, C };198const Letter2 = enum { A, B, C };
199const Value2 = union(Letter2) { A: i32, B, C, };199const Value2 = union(Letter2) { A: i32, B, C, };
200
201test "implicit cast union to its tag type" {
202 var x: Value2 = Letter2.B;
203 assert(x == Letter2.B);
204 giveMeLetterB(x);
205}
206fn giveMeLetterB(x: Letter2) {
207 assert(x == Value2.B);
208}