| author | |
| committer | |
| log | 6ab8b6f8b273356ce248a075b6a0657bfea33c79 |
| tree | cf0ea8802bc77376a38a4cfa25c6e9413d5b3fc0 |
| parent | 773fabf3610629c8974b59ed6fbd27050b7e505b |
10 files changed, 1440 insertions(+), 1333 deletions(-)
src/Module.zig+4-4| ... | @@ -932,7 +932,7 @@ pub const Decl = struct { | ... | @@ -932,7 +932,7 @@ pub const Decl = struct { |
| 932 | assert(decl.has_tv); | 932 | assert(decl.has_tv); |
| 933 | return switch (decl.val.tag()) { | 933 | return switch (decl.val.tag()) { |
| 934 | .extern_fn => true, | 934 | .extern_fn => true, |
| 935 | .variable => decl.val.castTag(.variable).?.data.init.tag() == .unreachable_value, | 935 | .variable => decl.val.castTag(.variable).?.data.init.ip_index == .unreachable_value, |
| 936 | else => false, | 936 | else => false, |
| 937 | }; | 937 | }; |
| 938 | } | 938 | } |
| ... | @@ -4849,6 +4849,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -4849,6 +4849,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4849 | var is_extern = false; | 4849 | var is_extern = false; |
| 4850 | switch (decl_tv.val.ip_index) { | 4850 | switch (decl_tv.val.ip_index) { |
| 4851 | .generic_poison => unreachable, | 4851 | .generic_poison => unreachable, |
| 4852 | .unreachable_value => unreachable, | ||
| 4853 | |||
| 4852 | .none => switch (decl_tv.val.tag()) { | 4854 | .none => switch (decl_tv.val.tag()) { |
| 4853 | .variable => { | 4855 | .variable => { |
| 4854 | const variable = decl_tv.val.castTag(.variable).?.data; | 4856 | const variable = decl_tv.val.castTag(.variable).?.data; |
| ... | @@ -4869,8 +4871,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -4869,8 +4871,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4869 | } | 4871 | } |
| 4870 | }, | 4872 | }, |
| 4871 | 4873 | ||
| 4872 | .unreachable_value => unreachable, | ||
| 4873 | |||
| 4874 | .function => {}, | 4874 | .function => {}, |
| 4875 | 4875 | ||
| 4876 | else => { | 4876 | else => { |
| ... | @@ -6592,7 +6592,7 @@ pub fn populateTestFunctions( | ... | @@ -6592,7 +6592,7 @@ pub fn populateTestFunctions( |
| 6592 | .len = try Value.Tag.int_u64.create(arena, test_name_slice.len), | 6592 | .len = try Value.Tag.int_u64.create(arena, test_name_slice.len), |
| 6593 | }), // name | 6593 | }), // name |
| 6594 | try Value.Tag.decl_ref.create(arena, test_decl_index), // func | 6594 | try Value.Tag.decl_ref.create(arena, test_decl_index), // func |
| 6595 | Value.initTag(.null_value), // async_frame_size | 6595 | Value.null, // async_frame_size |
| 6596 | }; | 6596 | }; |
| 6597 | test_fn_vals[i] = try Value.Tag.aggregate.create(arena, field_vals); | 6597 | test_fn_vals[i] = try Value.Tag.aggregate.create(arena, field_vals); |
| 6598 | } | 6598 | } |
src/Sema.zig+572-530| ... | @@ -1877,8 +1877,8 @@ fn resolveConstValue( | ... | @@ -1877,8 +1877,8 @@ fn resolveConstValue( |
| 1877 | if (try sema.resolveMaybeUndefValAllowVariables(air_ref)) |val| { | 1877 | if (try sema.resolveMaybeUndefValAllowVariables(air_ref)) |val| { |
| 1878 | switch (val.ip_index) { | 1878 | switch (val.ip_index) { |
| 1879 | .generic_poison => return error.GenericPoison, | 1879 | .generic_poison => return error.GenericPoison, |
| 1880 | .undef => return sema.failWithUseOfUndef(block, src), | ||
| 1880 | .none => switch (val.tag()) { | 1881 | .none => switch (val.tag()) { |
| 1881 | .undef => return sema.failWithUseOfUndef(block, src), | ||
| 1882 | .variable => return sema.failWithNeededComptime(block, src, reason), | 1882 | .variable => return sema.failWithNeededComptime(block, src, reason), |
| 1883 | else => return val, | 1883 | else => return val, |
| 1884 | }, | 1884 | }, |
| ... | @@ -4409,7 +4409,7 @@ fn validateStructInit( | ... | @@ -4409,7 +4409,7 @@ fn validateStructInit( |
| 4409 | if (field_ptr != 0) continue; | 4409 | if (field_ptr != 0) continue; |
| 4410 | 4410 | ||
| 4411 | const default_val = struct_ty.structFieldDefaultValue(i); | 4411 | const default_val = struct_ty.structFieldDefaultValue(i); |
| 4412 | if (default_val.tag() == .unreachable_value) { | 4412 | if (default_val.ip_index == .unreachable_value) { |
| 4413 | if (struct_ty.isTuple()) { | 4413 | if (struct_ty.isTuple()) { |
| 4414 | const template = "missing tuple field with index {d}"; | 4414 | const template = "missing tuple field with index {d}"; |
| 4415 | if (root_msg) |msg| { | 4415 | if (root_msg) |msg| { |
| ... | @@ -4554,7 +4554,7 @@ fn validateStructInit( | ... | @@ -4554,7 +4554,7 @@ fn validateStructInit( |
| 4554 | } | 4554 | } |
| 4555 | 4555 | ||
| 4556 | const default_val = struct_ty.structFieldDefaultValue(i); | 4556 | const default_val = struct_ty.structFieldDefaultValue(i); |
| 4557 | if (default_val.tag() == .unreachable_value) { | 4557 | if (default_val.ip_index == .unreachable_value) { |
| 4558 | if (struct_ty.isTuple()) { | 4558 | if (struct_ty.isTuple()) { |
| 4559 | const template = "missing tuple field with index {d}"; | 4559 | const template = "missing tuple field with index {d}"; |
| 4560 | if (root_msg) |msg| { | 4560 | if (root_msg) |msg| { |
| ... | @@ -4644,7 +4644,7 @@ fn zirValidateArrayInit( | ... | @@ -4644,7 +4644,7 @@ fn zirValidateArrayInit( |
| 4644 | var i = instrs.len; | 4644 | var i = instrs.len; |
| 4645 | while (i < array_len) : (i += 1) { | 4645 | while (i < array_len) : (i += 1) { |
| 4646 | const default_val = array_ty.structFieldDefaultValue(i); | 4646 | const default_val = array_ty.structFieldDefaultValue(i); |
| 4647 | if (default_val.tag() == .unreachable_value) { | 4647 | if (default_val.ip_index == .unreachable_value) { |
| 4648 | const template = "missing tuple field with index {d}"; | 4648 | const template = "missing tuple field with index {d}"; |
| 4649 | if (root_msg) |msg| { | 4649 | if (root_msg) |msg| { |
| 4650 | try sema.errNote(block, init_src, msg, template, .{i}); | 4650 | try sema.errNote(block, init_src, msg, template, .{i}); |
| ... | @@ -7885,7 +7885,7 @@ fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) | ... | @@ -7885,7 +7885,7 @@ fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) |
| 7885 | const tuple = ty.tupleFields(); | 7885 | const tuple = ty.tupleFields(); |
| 7886 | for (tuple.values, 0..) |field_val, i| { | 7886 | for (tuple.values, 0..) |field_val, i| { |
| 7887 | try sema.resolveTupleLazyValues(block, src, tuple.types[i]); | 7887 | try sema.resolveTupleLazyValues(block, src, tuple.types[i]); |
| 7888 | if (field_val.tag() == .unreachable_value) continue; | 7888 | if (field_val.ip_index == .unreachable_value) continue; |
| 7889 | try sema.resolveLazyValue(field_val); | 7889 | try sema.resolveLazyValue(field_val); |
| 7890 | } | 7890 | } |
| 7891 | } | 7891 | } |
| ... | @@ -12641,7 +12641,7 @@ fn analyzeTupleCat( | ... | @@ -12641,7 +12641,7 @@ fn analyzeTupleCat( |
| 12641 | const default_val = lhs_ty.structFieldDefaultValue(i); | 12641 | const default_val = lhs_ty.structFieldDefaultValue(i); |
| 12642 | values[i] = default_val; | 12642 | values[i] = default_val; |
| 12643 | const operand_src = lhs_src; // TODO better source location | 12643 | const operand_src = lhs_src; // TODO better source location |
| 12644 | if (default_val.tag() == .unreachable_value) { | 12644 | if (default_val.ip_index == .unreachable_value) { |
| 12645 | runtime_src = operand_src; | 12645 | runtime_src = operand_src; |
| 12646 | } | 12646 | } |
| 12647 | } | 12647 | } |
| ... | @@ -12651,7 +12651,7 @@ fn analyzeTupleCat( | ... | @@ -12651,7 +12651,7 @@ fn analyzeTupleCat( |
| 12651 | const default_val = rhs_ty.structFieldDefaultValue(i); | 12651 | const default_val = rhs_ty.structFieldDefaultValue(i); |
| 12652 | values[i + lhs_len] = default_val; | 12652 | values[i + lhs_len] = default_val; |
| 12653 | const operand_src = rhs_src; // TODO better source location | 12653 | const operand_src = rhs_src; // TODO better source location |
| 12654 | if (default_val.tag() == .unreachable_value) { | 12654 | if (default_val.ip_index == .unreachable_value) { |
| 12655 | runtime_src = operand_src; | 12655 | runtime_src = operand_src; |
| 12656 | } | 12656 | } |
| 12657 | } | 12657 | } |
| ... | @@ -12809,8 +12809,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12809,8 +12809,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12809 | while (elem_i < lhs_len) : (elem_i += 1) { | 12809 | while (elem_i < lhs_len) : (elem_i += 1) { |
| 12810 | const lhs_elem_i = elem_i; | 12810 | const lhs_elem_i = elem_i; |
| 12811 | const elem_ty = if (lhs_is_tuple) lhs_ty.structFieldType(lhs_elem_i) else lhs_info.elem_type; | 12811 | const elem_ty = if (lhs_is_tuple) lhs_ty.structFieldType(lhs_elem_i) else lhs_info.elem_type; |
| 12812 | const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i) else Value.initTag(.unreachable_value); | 12812 | const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i) else Value.@"unreachable"; |
| 12813 | const elem_val = if (elem_default_val.tag() == .unreachable_value) try lhs_sub_val.elemValue(sema.mod, sema.arena, lhs_elem_i) else elem_default_val; | 12813 | const elem_val = if (elem_default_val.ip_index == .unreachable_value) try lhs_sub_val.elemValue(sema.mod, sema.arena, lhs_elem_i) else elem_default_val; |
| 12814 | const elem_val_inst = try sema.addConstant(elem_ty, elem_val); | 12814 | const elem_val_inst = try sema.addConstant(elem_ty, elem_val); |
| 12815 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded); | 12815 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded); |
| 12816 | const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, ""); | 12816 | const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, ""); |
| ... | @@ -12819,8 +12819,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12819,8 +12819,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12819 | while (elem_i < result_len) : (elem_i += 1) { | 12819 | while (elem_i < result_len) : (elem_i += 1) { |
| 12820 | const rhs_elem_i = elem_i - lhs_len; | 12820 | const rhs_elem_i = elem_i - lhs_len; |
| 12821 | const elem_ty = if (rhs_is_tuple) rhs_ty.structFieldType(rhs_elem_i) else rhs_info.elem_type; | 12821 | const elem_ty = if (rhs_is_tuple) rhs_ty.structFieldType(rhs_elem_i) else rhs_info.elem_type; |
| 12822 | const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i) else Value.initTag(.unreachable_value); | 12822 | const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i) else Value.@"unreachable"; |
| 12823 | const elem_val = if (elem_default_val.tag() == .unreachable_value) try rhs_sub_val.elemValue(sema.mod, sema.arena, rhs_elem_i) else elem_default_val; | 12823 | const elem_val = if (elem_default_val.ip_index == .unreachable_value) try rhs_sub_val.elemValue(sema.mod, sema.arena, rhs_elem_i) else elem_default_val; |
| 12824 | const elem_val_inst = try sema.addConstant(elem_ty, elem_val); | 12824 | const elem_val_inst = try sema.addConstant(elem_ty, elem_val); |
| 12825 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded); | 12825 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded); |
| 12826 | const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, ""); | 12826 | const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, ""); |
| ... | @@ -12962,7 +12962,7 @@ fn analyzeTupleMul( | ... | @@ -12962,7 +12962,7 @@ fn analyzeTupleMul( |
| 12962 | types[i] = operand_ty.structFieldType(i); | 12962 | types[i] = operand_ty.structFieldType(i); |
| 12963 | values[i] = operand_ty.structFieldDefaultValue(i); | 12963 | values[i] = operand_ty.structFieldDefaultValue(i); |
| 12964 | const operand_src = lhs_src; // TODO better source location | 12964 | const operand_src = lhs_src; // TODO better source location |
| 12965 | if (values[i].tag() == .unreachable_value) { | 12965 | if (values[i].ip_index == .unreachable_value) { |
| 12966 | runtime_src = operand_src; | 12966 | runtime_src = operand_src; |
| 12967 | } | 12967 | } |
| 12968 | } | 12968 | } |
| ... | @@ -14332,7 +14332,7 @@ fn zirOverflowArithmetic( | ... | @@ -14332,7 +14332,7 @@ fn zirOverflowArithmetic( |
| 14332 | 14332 | ||
| 14333 | var result: struct { | 14333 | var result: struct { |
| 14334 | inst: Air.Inst.Ref = .none, | 14334 | inst: Air.Inst.Ref = .none, |
| 14335 | wrapped: Value = Value.initTag(.unreachable_value), | 14335 | wrapped: Value = Value.@"unreachable", |
| 14336 | overflow_bit: Value, | 14336 | overflow_bit: Value, |
| 14337 | } = result: { | 14337 | } = result: { |
| 14338 | switch (zir_tag) { | 14338 | switch (zir_tag) { |
| ... | @@ -14508,8 +14508,8 @@ fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type { | ... | @@ -14508,8 +14508,8 @@ fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type { |
| 14508 | 14508 | ||
| 14509 | types[0] = ty; | 14509 | types[0] = ty; |
| 14510 | types[1] = ov_ty; | 14510 | types[1] = ov_ty; |
| 14511 | values[0] = Value.initTag(.unreachable_value); | 14511 | values[0] = Value.@"unreachable"; |
| 14512 | values[1] = Value.initTag(.unreachable_value); | 14512 | values[1] = Value.@"unreachable"; |
| 14513 | 14513 | ||
| 14514 | return tuple_ty; | 14514 | return tuple_ty; |
| 14515 | } | 14515 | } |
| ... | @@ -15647,7 +15647,7 @@ fn zirClosureCapture( | ... | @@ -15647,7 +15647,7 @@ fn zirClosureCapture( |
| 15647 | // value only. In such case we preserve the type and use a dummy runtime value. | 15647 | // value only. In such case we preserve the type and use a dummy runtime value. |
| 15648 | const operand = try sema.resolveInst(inst_data.operand); | 15648 | const operand = try sema.resolveInst(inst_data.operand); |
| 15649 | const val = (try sema.resolveMaybeUndefValAllowVariables(operand)) orelse | 15649 | const val = (try sema.resolveMaybeUndefValAllowVariables(operand)) orelse |
| 15650 | Value.initTag(.unreachable_value); | 15650 | Value.@"unreachable"; |
| 15651 | 15651 | ||
| 15652 | try block.wip_capture_scope.captures.putNoClobber(sema.gpa, inst, .{ | 15652 | try block.wip_capture_scope.captures.putNoClobber(sema.gpa, inst, .{ |
| 15653 | .ty = try sema.typeOf(operand).copy(sema.perm_arena), | 15653 | .ty = try sema.typeOf(operand).copy(sema.perm_arena), |
| ... | @@ -15684,7 +15684,7 @@ fn zirClosureGet( | ... | @@ -15684,7 +15684,7 @@ fn zirClosureGet( |
| 15684 | scope = scope.parent.?; | 15684 | scope = scope.parent.?; |
| 15685 | }; | 15685 | }; |
| 15686 | 15686 | ||
| 15687 | if (tv.val.tag() == .unreachable_value and !block.is_typeof and sema.func == null) { | 15687 | if (tv.val.ip_index == .unreachable_value and !block.is_typeof and sema.func == null) { |
| 15688 | const msg = msg: { | 15688 | const msg = msg: { |
| 15689 | const name = name: { | 15689 | const name = name: { |
| 15690 | const file = sema.owner_decl.getFileScope(); | 15690 | const file = sema.owner_decl.getFileScope(); |
| ... | @@ -15712,7 +15712,7 @@ fn zirClosureGet( | ... | @@ -15712,7 +15712,7 @@ fn zirClosureGet( |
| 15712 | return sema.failWithOwnedErrorMsg(msg); | 15712 | return sema.failWithOwnedErrorMsg(msg); |
| 15713 | } | 15713 | } |
| 15714 | 15714 | ||
| 15715 | if (tv.val.tag() == .unreachable_value and !block.is_typeof and !block.is_comptime and sema.func != null) { | 15715 | if (tv.val.ip_index == .unreachable_value and !block.is_typeof and !block.is_comptime and sema.func != null) { |
| 15716 | const msg = msg: { | 15716 | const msg = msg: { |
| 15717 | const name = name: { | 15717 | const name = name: { |
| 15718 | const file = sema.owner_decl.getFileScope(); | 15718 | const file = sema.owner_decl.getFileScope(); |
| ... | @@ -15742,7 +15742,7 @@ fn zirClosureGet( | ... | @@ -15742,7 +15742,7 @@ fn zirClosureGet( |
| 15742 | return sema.failWithOwnedErrorMsg(msg); | 15742 | return sema.failWithOwnedErrorMsg(msg); |
| 15743 | } | 15743 | } |
| 15744 | 15744 | ||
| 15745 | if (tv.val.tag() == .unreachable_value) { | 15745 | if (tv.val.ip_index == .unreachable_value) { |
| 15746 | assert(block.is_typeof); | 15746 | assert(block.is_typeof); |
| 15747 | // We need a dummy runtime instruction with the correct type. | 15747 | // We need a dummy runtime instruction with the correct type. |
| 15748 | return block.addTy(.alloc, tv.ty); | 15748 | return block.addTy(.alloc, tv.ty); |
| ... | @@ -16477,7 +16477,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16477,7 +16477,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16477 | 16477 | ||
| 16478 | const struct_field_fields = try fields_anon_decl.arena().create([5]Value); | 16478 | const struct_field_fields = try fields_anon_decl.arena().create([5]Value); |
| 16479 | const field_val = tuple.values[i]; | 16479 | const field_val = tuple.values[i]; |
| 16480 | const is_comptime = field_val.tag() != .unreachable_value; | 16480 | const is_comptime = field_val.ip_index != .unreachable_value; |
| 16481 | const opt_default_val = if (is_comptime) field_val else null; | 16481 | const opt_default_val = if (is_comptime) field_val else null; |
| 16482 | const default_val_ptr = try sema.optRefValue(block, field_ty, opt_default_val); | 16482 | const default_val_ptr = try sema.optRefValue(block, field_ty, opt_default_val); |
| 16483 | struct_field_fields.* = .{ | 16483 | struct_field_fields.* = .{ |
| ... | @@ -16518,7 +16518,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16518,7 +16518,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16518 | }; | 16518 | }; |
| 16519 | 16519 | ||
| 16520 | const struct_field_fields = try fields_anon_decl.arena().create([5]Value); | 16520 | const struct_field_fields = try fields_anon_decl.arena().create([5]Value); |
| 16521 | const opt_default_val = if (field.default_val.tag() == .unreachable_value) | 16521 | const opt_default_val = if (field.default_val.ip_index == .unreachable_value) |
| 16522 | null | 16522 | null |
| 16523 | else | 16523 | else |
| 16524 | field.default_val; | 16524 | field.default_val; |
| ... | @@ -16570,7 +16570,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16570,7 +16570,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16570 | const backing_int_ty_val = try Value.Tag.ty.create(sema.arena, struct_obj.backing_int_ty); | 16570 | const backing_int_ty_val = try Value.Tag.ty.create(sema.arena, struct_obj.backing_int_ty); |
| 16571 | break :blk try Value.Tag.opt_payload.create(sema.arena, backing_int_ty_val); | 16571 | break :blk try Value.Tag.opt_payload.create(sema.arena, backing_int_ty_val); |
| 16572 | } else { | 16572 | } else { |
| 16573 | break :blk Value.initTag(.null_value); | 16573 | break :blk Value.null; |
| 16574 | } | 16574 | } |
| 16575 | }; | 16575 | }; |
| 16576 | 16576 | ||
| ... | @@ -17974,7 +17974,7 @@ fn finishStructInit( | ... | @@ -17974,7 +17974,7 @@ fn finishStructInit( |
| 17974 | for (struct_obj.values, 0..) |default_val, i| { | 17974 | for (struct_obj.values, 0..) |default_val, i| { |
| 17975 | if (field_inits[i] != .none) continue; | 17975 | if (field_inits[i] != .none) continue; |
| 17976 | 17976 | ||
| 17977 | if (default_val.tag() == .unreachable_value) { | 17977 | if (default_val.ip_index == .unreachable_value) { |
| 17978 | const field_name = struct_obj.names[i]; | 17978 | const field_name = struct_obj.names[i]; |
| 17979 | const template = "missing struct field: {s}"; | 17979 | const template = "missing struct field: {s}"; |
| 17980 | const args = .{field_name}; | 17980 | const args = .{field_name}; |
| ... | @@ -17994,7 +17994,7 @@ fn finishStructInit( | ... | @@ -17994,7 +17994,7 @@ fn finishStructInit( |
| 17994 | if (field_inits[i] != .none) continue; | 17994 | if (field_inits[i] != .none) continue; |
| 17995 | 17995 | ||
| 17996 | const default_val = struct_ty.structFieldDefaultValue(i); | 17996 | const default_val = struct_ty.structFieldDefaultValue(i); |
| 17997 | if (default_val.tag() == .unreachable_value) { | 17997 | if (default_val.ip_index == .unreachable_value) { |
| 17998 | const template = "missing tuple field with index {d}"; | 17998 | const template = "missing tuple field with index {d}"; |
| 17999 | if (root_msg) |msg| { | 17999 | if (root_msg) |msg| { |
| 18000 | try sema.errNote(block, init_src, msg, template, .{i}); | 18000 | try sema.errNote(block, init_src, msg, template, .{i}); |
| ... | @@ -18010,7 +18010,7 @@ fn finishStructInit( | ... | @@ -18010,7 +18010,7 @@ fn finishStructInit( |
| 18010 | for (struct_obj.fields.values(), 0..) |field, i| { | 18010 | for (struct_obj.fields.values(), 0..) |field, i| { |
| 18011 | if (field_inits[i] != .none) continue; | 18011 | if (field_inits[i] != .none) continue; |
| 18012 | 18012 | ||
| 18013 | if (field.default_val.tag() == .unreachable_value) { | 18013 | if (field.default_val.ip_index == .unreachable_value) { |
| 18014 | const field_name = struct_obj.fields.keys()[i]; | 18014 | const field_name = struct_obj.fields.keys()[i]; |
| 18015 | const template = "missing struct field: {s}"; | 18015 | const template = "missing struct field: {s}"; |
| 18016 | const args = .{field_name}; | 18016 | const args = .{field_name}; |
| ... | @@ -18145,7 +18145,7 @@ fn zirStructInitAnon( | ... | @@ -18145,7 +18145,7 @@ fn zirStructInitAnon( |
| 18145 | if (try sema.resolveMaybeUndefVal(init)) |init_val| { | 18145 | if (try sema.resolveMaybeUndefVal(init)) |init_val| { |
| 18146 | values[i] = init_val; | 18146 | values[i] = init_val; |
| 18147 | } else { | 18147 | } else { |
| 18148 | values[i] = Value.initTag(.unreachable_value); | 18148 | values[i] = Value.@"unreachable"; |
| 18149 | runtime_index = i; | 18149 | runtime_index = i; |
| 18150 | } | 18150 | } |
| 18151 | } | 18151 | } |
| ... | @@ -18191,7 +18191,7 @@ fn zirStructInitAnon( | ... | @@ -18191,7 +18191,7 @@ fn zirStructInitAnon( |
| 18191 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), | 18191 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 18192 | .pointee_type = field_ty, | 18192 | .pointee_type = field_ty, |
| 18193 | }); | 18193 | }); |
| 18194 | if (values[i].tag() == .unreachable_value) { | 18194 | if (values[i].ip_index == .unreachable_value) { |
| 18195 | const init = try sema.resolveInst(item.data.init); | 18195 | const init = try sema.resolveInst(item.data.init); |
| 18196 | const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty); | 18196 | const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty); |
| 18197 | _ = try block.addBinOp(.store, field_ptr, init); | 18197 | _ = try block.addBinOp(.store, field_ptr, init); |
| ... | @@ -18357,7 +18357,7 @@ fn zirArrayInitAnon( | ... | @@ -18357,7 +18357,7 @@ fn zirArrayInitAnon( |
| 18357 | if (try sema.resolveMaybeUndefVal(elem)) |val| { | 18357 | if (try sema.resolveMaybeUndefVal(elem)) |val| { |
| 18358 | values[i] = val; | 18358 | values[i] = val; |
| 18359 | } else { | 18359 | } else { |
| 18360 | values[i] = Value.initTag(.unreachable_value); | 18360 | values[i] = Value.@"unreachable"; |
| 18361 | runtime_src = operand_src; | 18361 | runtime_src = operand_src; |
| 18362 | } | 18362 | } |
| 18363 | } | 18363 | } |
| ... | @@ -18390,7 +18390,7 @@ fn zirArrayInitAnon( | ... | @@ -18390,7 +18390,7 @@ fn zirArrayInitAnon( |
| 18390 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), | 18390 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 18391 | .pointee_type = types[i], | 18391 | .pointee_type = types[i], |
| 18392 | }); | 18392 | }); |
| 18393 | if (values[i].tag() == .unreachable_value) { | 18393 | if (values[i].ip_index == .unreachable_value) { |
| 18394 | const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty); | 18394 | const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty); |
| 18395 | _ = try block.addBinOp(.store, field_ptr, try sema.resolveInst(operand)); | 18395 | _ = try block.addBinOp(.store, field_ptr, try sema.resolveInst(operand)); |
| 18396 | } | 18396 | } |
| ... | @@ -19545,8 +19545,8 @@ fn reifyStruct( | ... | @@ -19545,8 +19545,8 @@ fn reifyStruct( |
| 19545 | else | 19545 | else |
| 19546 | opt_val; | 19546 | opt_val; |
| 19547 | break :blk try payload_val.copy(new_decl_arena_allocator); | 19547 | break :blk try payload_val.copy(new_decl_arena_allocator); |
| 19548 | } else Value.initTag(.unreachable_value); | 19548 | } else Value.@"unreachable"; |
| 19549 | if (is_comptime_val.toBool(mod) and default_val.tag() == .unreachable_value) { | 19549 | if (is_comptime_val.toBool(mod) and default_val.ip_index == .unreachable_value) { |
| 19550 | return sema.fail(block, src, "comptime field without default initialization value", .{}); | 19550 | return sema.fail(block, src, "comptime field without default initialization value", .{}); |
| 19551 | } | 19551 | } |
| 19552 | 19552 | ||
| ... | @@ -22579,7 +22579,7 @@ fn zirVarExtended( | ... | @@ -22579,7 +22579,7 @@ fn zirVarExtended( |
| 22579 | 22579 | ||
| 22580 | break :blk (try sema.resolveMaybeUndefVal(init)) orelse | 22580 | break :blk (try sema.resolveMaybeUndefVal(init)) orelse |
| 22581 | return sema.failWithNeededComptime(block, init_src, "container level variable initializers must be comptime-known"); | 22581 | return sema.failWithNeededComptime(block, init_src, "container level variable initializers must be comptime-known"); |
| 22582 | } else Value.initTag(.unreachable_value); | 22582 | } else Value.@"unreachable"; |
| 22583 | 22583 | ||
| 22584 | try sema.validateVarType(block, ty_src, var_ty, small.is_extern); | 22584 | try sema.validateVarType(block, ty_src, var_ty, small.is_extern); |
| 22585 | 22585 | ||
| ... | @@ -23080,7 +23080,7 @@ fn zirBuiltinExtern( | ... | @@ -23080,7 +23080,7 @@ fn zirBuiltinExtern( |
| 23080 | const new_var = try new_decl_arena_allocator.create(Module.Var); | 23080 | const new_var = try new_decl_arena_allocator.create(Module.Var); |
| 23081 | new_var.* = .{ | 23081 | new_var.* = .{ |
| 23082 | .owner_decl = sema.owner_decl_index, | 23082 | .owner_decl = sema.owner_decl_index, |
| 23083 | .init = Value.initTag(.unreachable_value), | 23083 | .init = Value.@"unreachable", |
| 23084 | .is_extern = true, | 23084 | .is_extern = true, |
| 23085 | .is_mutable = false, | 23085 | .is_mutable = false, |
| 23086 | .is_threadlocal = options.is_thread_local, | 23086 | .is_threadlocal = options.is_thread_local, |
| ... | @@ -25736,7 +25736,7 @@ fn coerceExtra( | ... | @@ -25736,7 +25736,7 @@ fn coerceExtra( |
| 25736 | } | 25736 | } |
| 25737 | } else { | 25737 | } else { |
| 25738 | in_memory_result = .{ .ptr_sentinel = .{ | 25738 | in_memory_result = .{ .ptr_sentinel = .{ |
| 25739 | .actual = Value.initTag(.unreachable_value), | 25739 | .actual = Value.@"unreachable", |
| 25740 | .wanted = dest_sent, | 25740 | .wanted = dest_sent, |
| 25741 | .ty = dst_elem_type, | 25741 | .ty = dst_elem_type, |
| 25742 | } }; | 25742 | } }; |
| ... | @@ -26116,26 +26116,28 @@ fn coerceExtra( | ... | @@ -26116,26 +26116,28 @@ fn coerceExtra( |
| 26116 | .ErrorUnion => switch (inst_ty.zigTypeTag(mod)) { | 26116 | .ErrorUnion => switch (inst_ty.zigTypeTag(mod)) { |
| 26117 | .ErrorUnion => eu: { | 26117 | .ErrorUnion => eu: { |
| 26118 | if (maybe_inst_val) |inst_val| { | 26118 | if (maybe_inst_val) |inst_val| { |
| 26119 | switch (inst_val.tag()) { | 26119 | switch (inst_val.ip_index) { |
| 26120 | .undef => return sema.addConstUndef(dest_ty), | 26120 | .undef => return sema.addConstUndef(dest_ty), |
| 26121 | .eu_payload => { | 26121 | .none => switch (inst_val.tag()) { |
| 26122 | const payload = try sema.addConstant( | 26122 | .eu_payload => { |
| 26123 | inst_ty.errorUnionPayload(), | 26123 | const payload = try sema.addConstant( |
| 26124 | inst_val.castTag(.eu_payload).?.data, | 26124 | inst_ty.errorUnionPayload(), |
| 26125 | ); | 26125 | inst_val.castTag(.eu_payload).?.data, |
| 26126 | return sema.wrapErrorUnionPayload(block, dest_ty, payload, inst_src) catch |err| switch (err) { | 26126 | ); |
| 26127 | error.NotCoercible => break :eu, | 26127 | return sema.wrapErrorUnionPayload(block, dest_ty, payload, inst_src) catch |err| switch (err) { |
| 26128 | else => |e| return e, | 26128 | error.NotCoercible => break :eu, |
| 26129 | }; | 26129 | else => |e| return e, |
| 26130 | }, | 26130 | }; |
| 26131 | else => { | 26131 | }, |
| 26132 | const error_set = try sema.addConstant( | 26132 | else => {}, |
| 26133 | inst_ty.errorUnionSet(), | ||
| 26134 | inst_val, | ||
| 26135 | ); | ||
| 26136 | return sema.wrapErrorUnionSet(block, dest_ty, error_set, inst_src); | ||
| 26137 | }, | 26133 | }, |
| 26134 | else => {}, | ||
| 26138 | } | 26135 | } |
| 26136 | const error_set = try sema.addConstant( | ||
| 26137 | inst_ty.errorUnionSet(), | ||
| 26138 | inst_val, | ||
| 26139 | ); | ||
| 26140 | return sema.wrapErrorUnionSet(block, dest_ty, error_set, inst_src); | ||
| 26139 | } | 26141 | } |
| 26140 | }, | 26142 | }, |
| 26141 | .ErrorSet => { | 26143 | .ErrorSet => { |
| ... | @@ -26413,7 +26415,7 @@ const InMemoryCoercionResult = union(enum) { | ... | @@ -26413,7 +26415,7 @@ const InMemoryCoercionResult = union(enum) { |
| 26413 | break; | 26415 | break; |
| 26414 | }, | 26416 | }, |
| 26415 | .array_sentinel => |sentinel| { | 26417 | .array_sentinel => |sentinel| { |
| 26416 | if (sentinel.actual.tag() != .unreachable_value) { | 26418 | if (sentinel.actual.ip_index != .unreachable_value) { |
| 26417 | try sema.errNote(block, src, msg, "array sentinel '{}' cannot cast into array sentinel '{}'", .{ | 26419 | try sema.errNote(block, src, msg, "array sentinel '{}' cannot cast into array sentinel '{}'", .{ |
| 26418 | sentinel.actual.fmtValue(sentinel.ty, sema.mod), sentinel.wanted.fmtValue(sentinel.ty, sema.mod), | 26420 | sentinel.actual.fmtValue(sentinel.ty, sema.mod), sentinel.wanted.fmtValue(sentinel.ty, sema.mod), |
| 26419 | }); | 26421 | }); |
| ... | @@ -26539,7 +26541,7 @@ const InMemoryCoercionResult = union(enum) { | ... | @@ -26539,7 +26541,7 @@ const InMemoryCoercionResult = union(enum) { |
| 26539 | break; | 26541 | break; |
| 26540 | }, | 26542 | }, |
| 26541 | .ptr_sentinel => |sentinel| { | 26543 | .ptr_sentinel => |sentinel| { |
| 26542 | if (sentinel.actual.tag() != .unreachable_value) { | 26544 | if (sentinel.actual.ip_index != .unreachable_value) { |
| 26543 | try sema.errNote(block, src, msg, "pointer sentinel '{}' cannot cast into pointer sentinel '{}'", .{ | 26545 | try sema.errNote(block, src, msg, "pointer sentinel '{}' cannot cast into pointer sentinel '{}'", .{ |
| 26544 | sentinel.actual.fmtValue(sentinel.ty, sema.mod), sentinel.wanted.fmtValue(sentinel.ty, sema.mod), | 26546 | sentinel.actual.fmtValue(sentinel.ty, sema.mod), sentinel.wanted.fmtValue(sentinel.ty, sema.mod), |
| 26545 | }); | 26547 | }); |
| ... | @@ -26747,8 +26749,8 @@ fn coerceInMemoryAllowed( | ... | @@ -26747,8 +26749,8 @@ fn coerceInMemoryAllowed( |
| 26747 | dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.elem_type, mod)); | 26749 | dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.elem_type, mod)); |
| 26748 | if (!ok_sent) { | 26750 | if (!ok_sent) { |
| 26749 | return InMemoryCoercionResult{ .array_sentinel = .{ | 26751 | return InMemoryCoercionResult{ .array_sentinel = .{ |
| 26750 | .actual = src_info.sentinel orelse Value.initTag(.unreachable_value), | 26752 | .actual = src_info.sentinel orelse Value.@"unreachable", |
| 26751 | .wanted = dest_info.sentinel orelse Value.initTag(.unreachable_value), | 26753 | .wanted = dest_info.sentinel orelse Value.@"unreachable", |
| 26752 | .ty = dest_info.elem_type, | 26754 | .ty = dest_info.elem_type, |
| 26753 | } }; | 26755 | } }; |
| 26754 | } | 26756 | } |
| ... | @@ -27129,8 +27131,8 @@ fn coerceInMemoryAllowedPtrs( | ... | @@ -27129,8 +27131,8 @@ fn coerceInMemoryAllowedPtrs( |
| 27129 | dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.pointee_type, sema.mod)); | 27131 | dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.pointee_type, sema.mod)); |
| 27130 | if (!ok_sent) { | 27132 | if (!ok_sent) { |
| 27131 | return InMemoryCoercionResult{ .ptr_sentinel = .{ | 27133 | return InMemoryCoercionResult{ .ptr_sentinel = .{ |
| 27132 | .actual = src_info.sentinel orelse Value.initTag(.unreachable_value), | 27134 | .actual = src_info.sentinel orelse Value.@"unreachable", |
| 27133 | .wanted = dest_info.sentinel orelse Value.initTag(.unreachable_value), | 27135 | .wanted = dest_info.sentinel orelse Value.@"unreachable", |
| 27134 | .ty = dest_info.pointee_type, | 27136 | .ty = dest_info.pointee_type, |
| 27135 | } }; | 27137 | } }; |
| 27136 | } | 27138 | } |
| ... | @@ -27540,7 +27542,7 @@ fn beginComptimePtrMutation( | ... | @@ -27540,7 +27542,7 @@ fn beginComptimePtrMutation( |
| 27540 | }; | 27542 | }; |
| 27541 | } | 27543 | } |
| 27542 | 27544 | ||
| 27543 | switch (val_ptr.tag()) { | 27545 | switch (val_ptr.ip_index) { |
| 27544 | .undef => { | 27546 | .undef => { |
| 27545 | // An array has been initialized to undefined at comptime and now we | 27547 | // An array has been initialized to undefined at comptime and now we |
| 27546 | // are for the first time setting an element. We must change the representation | 27548 | // are for the first time setting an element. We must change the representation |
| ... | @@ -27565,127 +27567,130 @@ fn beginComptimePtrMutation( | ... | @@ -27565,127 +27567,130 @@ fn beginComptimePtrMutation( |
| 27565 | parent.decl_ref_mut, | 27567 | parent.decl_ref_mut, |
| 27566 | ); | 27568 | ); |
| 27567 | }, | 27569 | }, |
| 27568 | .bytes => { | 27570 | .none => switch (val_ptr.tag()) { |
| 27569 | // An array is memory-optimized to store a slice of bytes, but we are about | 27571 | .bytes => { |
| 27570 | // to modify an individual field and the representation has to change. | 27572 | // An array is memory-optimized to store a slice of bytes, but we are about |
| 27571 | // If we wanted to avoid this, there would need to be special detection | 27573 | // to modify an individual field and the representation has to change. |
| 27572 | // elsewhere to identify when writing a value to an array element that is stored | 27574 | // If we wanted to avoid this, there would need to be special detection |
| 27573 | // using the `bytes` tag, and handle it without making a call to this function. | 27575 | // elsewhere to identify when writing a value to an array element that is stored |
| 27574 | const arena = parent.beginArena(sema.mod); | 27576 | // using the `bytes` tag, and handle it without making a call to this function. |
| 27575 | defer parent.finishArena(sema.mod); | 27577 | const arena = parent.beginArena(sema.mod); |
| 27576 | 27578 | defer parent.finishArena(sema.mod); | |
| 27577 | const bytes = val_ptr.castTag(.bytes).?.data; | 27579 | |
| 27578 | const dest_len = parent.ty.arrayLenIncludingSentinel(mod); | 27580 | const bytes = val_ptr.castTag(.bytes).?.data; |
| 27579 | // bytes.len may be one greater than dest_len because of the case when | 27581 | const dest_len = parent.ty.arrayLenIncludingSentinel(mod); |
| 27580 | // assigning `[N:S]T` to `[N]T`. This is allowed; the sentinel is omitted. | 27582 | // bytes.len may be one greater than dest_len because of the case when |
| 27581 | assert(bytes.len >= dest_len); | 27583 | // assigning `[N:S]T` to `[N]T`. This is allowed; the sentinel is omitted. |
| 27582 | const elems = try arena.alloc(Value, @intCast(usize, dest_len)); | 27584 | assert(bytes.len >= dest_len); |
| 27583 | for (elems, 0..) |*elem, i| { | 27585 | const elems = try arena.alloc(Value, @intCast(usize, dest_len)); |
| 27584 | elem.* = try Value.Tag.int_u64.create(arena, bytes[i]); | 27586 | for (elems, 0..) |*elem, i| { |
| 27585 | } | 27587 | elem.* = try Value.Tag.int_u64.create(arena, bytes[i]); |
| 27586 | 27588 | } | |
| 27587 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); | ||
| 27588 | 27589 | ||
| 27589 | return beginComptimePtrMutationInner( | 27590 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); |
| 27590 | sema, | ||
| 27591 | block, | ||
| 27592 | src, | ||
| 27593 | elem_ty, | ||
| 27594 | &elems[elem_ptr.index], | ||
| 27595 | ptr_elem_ty, | ||
| 27596 | parent.decl_ref_mut, | ||
| 27597 | ); | ||
| 27598 | }, | ||
| 27599 | .str_lit => { | ||
| 27600 | // An array is memory-optimized to store a slice of bytes, but we are about | ||
| 27601 | // to modify an individual field and the representation has to change. | ||
| 27602 | // If we wanted to avoid this, there would need to be special detection | ||
| 27603 | // elsewhere to identify when writing a value to an array element that is stored | ||
| 27604 | // using the `str_lit` tag, and handle it without making a call to this function. | ||
| 27605 | const arena = parent.beginArena(sema.mod); | ||
| 27606 | defer parent.finishArena(sema.mod); | ||
| 27607 | 27591 | ||
| 27608 | const str_lit = val_ptr.castTag(.str_lit).?.data; | 27592 | return beginComptimePtrMutationInner( |
| 27609 | const dest_len = parent.ty.arrayLenIncludingSentinel(mod); | 27593 | sema, |
| 27610 | const bytes = sema.mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; | 27594 | block, |
| 27611 | const elems = try arena.alloc(Value, @intCast(usize, dest_len)); | 27595 | src, |
| 27612 | for (bytes, 0..) |byte, i| { | 27596 | elem_ty, |
| 27613 | elems[i] = try Value.Tag.int_u64.create(arena, byte); | 27597 | &elems[elem_ptr.index], |
| 27614 | } | 27598 | ptr_elem_ty, |
| 27615 | if (parent.ty.sentinel(mod)) |sent_val| { | 27599 | parent.decl_ref_mut, |
| 27616 | assert(elems.len == bytes.len + 1); | 27600 | ); |
| 27617 | elems[bytes.len] = sent_val; | 27601 | }, |
| 27618 | } | 27602 | .str_lit => { |
| 27603 | // An array is memory-optimized to store a slice of bytes, but we are about | ||
| 27604 | // to modify an individual field and the representation has to change. | ||
| 27605 | // If we wanted to avoid this, there would need to be special detection | ||
| 27606 | // elsewhere to identify when writing a value to an array element that is stored | ||
| 27607 | // using the `str_lit` tag, and handle it without making a call to this function. | ||
| 27608 | const arena = parent.beginArena(sema.mod); | ||
| 27609 | defer parent.finishArena(sema.mod); | ||
| 27610 | |||
| 27611 | const str_lit = val_ptr.castTag(.str_lit).?.data; | ||
| 27612 | const dest_len = parent.ty.arrayLenIncludingSentinel(mod); | ||
| 27613 | const bytes = sema.mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; | ||
| 27614 | const elems = try arena.alloc(Value, @intCast(usize, dest_len)); | ||
| 27615 | for (bytes, 0..) |byte, i| { | ||
| 27616 | elems[i] = try Value.Tag.int_u64.create(arena, byte); | ||
| 27617 | } | ||
| 27618 | if (parent.ty.sentinel(mod)) |sent_val| { | ||
| 27619 | assert(elems.len == bytes.len + 1); | ||
| 27620 | elems[bytes.len] = sent_val; | ||
| 27621 | } | ||
| 27619 | 27622 | ||
| 27620 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); | 27623 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); |
| 27621 | 27624 | ||
| 27622 | return beginComptimePtrMutationInner( | 27625 | return beginComptimePtrMutationInner( |
| 27623 | sema, | 27626 | sema, |
| 27624 | block, | 27627 | block, |
| 27625 | src, | 27628 | src, |
| 27626 | elem_ty, | 27629 | elem_ty, |
| 27627 | &elems[elem_ptr.index], | 27630 | &elems[elem_ptr.index], |
| 27628 | ptr_elem_ty, | 27631 | ptr_elem_ty, |
| 27629 | parent.decl_ref_mut, | 27632 | parent.decl_ref_mut, |
| 27630 | ); | 27633 | ); |
| 27631 | }, | 27634 | }, |
| 27632 | .repeated => { | 27635 | .repeated => { |
| 27633 | // An array is memory-optimized to store only a single element value, and | 27636 | // An array is memory-optimized to store only a single element value, and |
| 27634 | // that value is understood to be the same for the entire length of the array. | 27637 | // that value is understood to be the same for the entire length of the array. |
| 27635 | // However, now we want to modify an individual field and so the | 27638 | // However, now we want to modify an individual field and so the |
| 27636 | // representation has to change. If we wanted to avoid this, there would | 27639 | // representation has to change. If we wanted to avoid this, there would |
| 27637 | // need to be special detection elsewhere to identify when writing a value to an | 27640 | // need to be special detection elsewhere to identify when writing a value to an |
| 27638 | // array element that is stored using the `repeated` tag, and handle it | 27641 | // array element that is stored using the `repeated` tag, and handle it |
| 27639 | // without making a call to this function. | 27642 | // without making a call to this function. |
| 27640 | const arena = parent.beginArena(sema.mod); | 27643 | const arena = parent.beginArena(sema.mod); |
| 27641 | defer parent.finishArena(sema.mod); | 27644 | defer parent.finishArena(sema.mod); |
| 27645 | |||
| 27646 | const repeated_val = try val_ptr.castTag(.repeated).?.data.copy(arena); | ||
| 27647 | const array_len_including_sentinel = | ||
| 27648 | try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel(mod)); | ||
| 27649 | const elems = try arena.alloc(Value, array_len_including_sentinel); | ||
| 27650 | if (elems.len > 0) elems[0] = repeated_val; | ||
| 27651 | for (elems[1..]) |*elem| { | ||
| 27652 | elem.* = try repeated_val.copy(arena); | ||
| 27653 | } | ||
| 27642 | 27654 | ||
| 27643 | const repeated_val = try val_ptr.castTag(.repeated).?.data.copy(arena); | 27655 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); |
| 27644 | const array_len_including_sentinel = | ||
| 27645 | try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel(mod)); | ||
| 27646 | const elems = try arena.alloc(Value, array_len_including_sentinel); | ||
| 27647 | if (elems.len > 0) elems[0] = repeated_val; | ||
| 27648 | for (elems[1..]) |*elem| { | ||
| 27649 | elem.* = try repeated_val.copy(arena); | ||
| 27650 | } | ||
| 27651 | 27656 | ||
| 27652 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); | 27657 | return beginComptimePtrMutationInner( |
| 27658 | sema, | ||
| 27659 | block, | ||
| 27660 | src, | ||
| 27661 | elem_ty, | ||
| 27662 | &elems[elem_ptr.index], | ||
| 27663 | ptr_elem_ty, | ||
| 27664 | parent.decl_ref_mut, | ||
| 27665 | ); | ||
| 27666 | }, | ||
| 27653 | 27667 | ||
| 27654 | return beginComptimePtrMutationInner( | 27668 | .aggregate => return beginComptimePtrMutationInner( |
| 27655 | sema, | 27669 | sema, |
| 27656 | block, | 27670 | block, |
| 27657 | src, | 27671 | src, |
| 27658 | elem_ty, | 27672 | elem_ty, |
| 27659 | &elems[elem_ptr.index], | 27673 | &val_ptr.castTag(.aggregate).?.data[elem_ptr.index], |
| 27660 | ptr_elem_ty, | 27674 | ptr_elem_ty, |
| 27661 | parent.decl_ref_mut, | 27675 | parent.decl_ref_mut, |
| 27662 | ); | 27676 | ), |
| 27663 | }, | ||
| 27664 | 27677 | ||
| 27665 | .aggregate => return beginComptimePtrMutationInner( | 27678 | .the_only_possible_value => { |
| 27666 | sema, | 27679 | const duped = try sema.arena.create(Value); |
| 27667 | block, | 27680 | duped.* = Value.initTag(.the_only_possible_value); |
| 27668 | src, | 27681 | return beginComptimePtrMutationInner( |
| 27669 | elem_ty, | 27682 | sema, |
| 27670 | &val_ptr.castTag(.aggregate).?.data[elem_ptr.index], | 27683 | block, |
| 27671 | ptr_elem_ty, | 27684 | src, |
| 27672 | parent.decl_ref_mut, | 27685 | elem_ty, |
| 27673 | ), | 27686 | duped, |
| 27687 | ptr_elem_ty, | ||
| 27688 | parent.decl_ref_mut, | ||
| 27689 | ); | ||
| 27690 | }, | ||
| 27674 | 27691 | ||
| 27675 | .the_only_possible_value => { | 27692 | else => unreachable, |
| 27676 | const duped = try sema.arena.create(Value); | ||
| 27677 | duped.* = Value.initTag(.the_only_possible_value); | ||
| 27678 | return beginComptimePtrMutationInner( | ||
| 27679 | sema, | ||
| 27680 | block, | ||
| 27681 | src, | ||
| 27682 | elem_ty, | ||
| 27683 | duped, | ||
| 27684 | ptr_elem_ty, | ||
| 27685 | parent.decl_ref_mut, | ||
| 27686 | ); | ||
| 27687 | }, | 27693 | }, |
| 27688 | |||
| 27689 | else => unreachable, | 27694 | else => unreachable, |
| 27690 | } | 27695 | } |
| 27691 | }, | 27696 | }, |
| ... | @@ -27738,7 +27743,7 @@ fn beginComptimePtrMutation( | ... | @@ -27738,7 +27743,7 @@ fn beginComptimePtrMutation( |
| 27738 | 27743 | ||
| 27739 | var parent = try sema.beginComptimePtrMutation(block, src, field_ptr.container_ptr, field_ptr.container_ty); | 27744 | var parent = try sema.beginComptimePtrMutation(block, src, field_ptr.container_ptr, field_ptr.container_ty); |
| 27740 | switch (parent.pointee) { | 27745 | switch (parent.pointee) { |
| 27741 | .direct => |val_ptr| switch (val_ptr.tag()) { | 27746 | .direct => |val_ptr| switch (val_ptr.ip_index) { |
| 27742 | .undef => { | 27747 | .undef => { |
| 27743 | // A struct or union has been initialized to undefined at comptime and now we | 27748 | // A struct or union has been initialized to undefined at comptime and now we |
| 27744 | // are for the first time setting a field. We must change the representation | 27749 | // are for the first time setting a field. We must change the representation |
| ... | @@ -27815,72 +27820,75 @@ fn beginComptimePtrMutation( | ... | @@ -27815,72 +27820,75 @@ fn beginComptimePtrMutation( |
| 27815 | else => unreachable, | 27820 | else => unreachable, |
| 27816 | } | 27821 | } |
| 27817 | }, | 27822 | }, |
| 27818 | .aggregate => return beginComptimePtrMutationInner( | 27823 | .none => switch (val_ptr.tag()) { |
| 27819 | sema, | 27824 | .aggregate => return beginComptimePtrMutationInner( |
| 27820 | block, | ||
| 27821 | src, | ||
| 27822 | parent.ty.structFieldType(field_index), | ||
| 27823 | &val_ptr.castTag(.aggregate).?.data[field_index], | ||
| 27824 | ptr_elem_ty, | ||
| 27825 | parent.decl_ref_mut, | ||
| 27826 | ), | ||
| 27827 | |||
| 27828 | .@"union" => { | ||
| 27829 | // We need to set the active field of the union. | ||
| 27830 | const arena = parent.beginArena(sema.mod); | ||
| 27831 | defer parent.finishArena(sema.mod); | ||
| 27832 | |||
| 27833 | const payload = &val_ptr.castTag(.@"union").?.data; | ||
| 27834 | payload.tag = try Value.Tag.enum_field_index.create(arena, field_index); | ||
| 27835 | |||
| 27836 | return beginComptimePtrMutationInner( | ||
| 27837 | sema, | 27825 | sema, |
| 27838 | block, | 27826 | block, |
| 27839 | src, | 27827 | src, |
| 27840 | parent.ty.structFieldType(field_index), | 27828 | parent.ty.structFieldType(field_index), |
| 27841 | &payload.val, | 27829 | &val_ptr.castTag(.aggregate).?.data[field_index], |
| 27842 | ptr_elem_ty, | ||
| 27843 | parent.decl_ref_mut, | ||
| 27844 | ); | ||
| 27845 | }, | ||
| 27846 | .slice => switch (field_index) { | ||
| 27847 | Value.Payload.Slice.ptr_index => return beginComptimePtrMutationInner( | ||
| 27848 | sema, | ||
| 27849 | block, | ||
| 27850 | src, | ||
| 27851 | parent.ty.slicePtrFieldType(try sema.arena.create(Type.SlicePtrFieldTypeBuffer)), | ||
| 27852 | &val_ptr.castTag(.slice).?.data.ptr, | ||
| 27853 | ptr_elem_ty, | 27830 | ptr_elem_ty, |
| 27854 | parent.decl_ref_mut, | 27831 | parent.decl_ref_mut, |
| 27855 | ), | 27832 | ), |
| 27856 | 27833 | ||
| 27857 | Value.Payload.Slice.len_index => return beginComptimePtrMutationInner( | 27834 | .@"union" => { |
| 27858 | sema, | 27835 | // We need to set the active field of the union. |
| 27859 | block, | 27836 | const arena = parent.beginArena(sema.mod); |
| 27860 | src, | 27837 | defer parent.finishArena(sema.mod); |
| 27861 | Type.usize, | ||
| 27862 | &val_ptr.castTag(.slice).?.data.len, | ||
| 27863 | ptr_elem_ty, | ||
| 27864 | parent.decl_ref_mut, | ||
| 27865 | ), | ||
| 27866 | 27838 | ||
| 27867 | else => unreachable, | 27839 | const payload = &val_ptr.castTag(.@"union").?.data; |
| 27868 | }, | 27840 | payload.tag = try Value.Tag.enum_field_index.create(arena, field_index); |
| 27869 | 27841 | ||
| 27870 | .empty_struct_value => { | 27842 | return beginComptimePtrMutationInner( |
| 27871 | const duped = try sema.arena.create(Value); | 27843 | sema, |
| 27872 | duped.* = Value.initTag(.the_only_possible_value); | 27844 | block, |
| 27873 | return beginComptimePtrMutationInner( | 27845 | src, |
| 27874 | sema, | 27846 | parent.ty.structFieldType(field_index), |
| 27875 | block, | 27847 | &payload.val, |
| 27876 | src, | 27848 | ptr_elem_ty, |
| 27877 | parent.ty.structFieldType(field_index), | 27849 | parent.decl_ref_mut, |
| 27878 | duped, | 27850 | ); |
| 27879 | ptr_elem_ty, | 27851 | }, |
| 27880 | parent.decl_ref_mut, | 27852 | .slice => switch (field_index) { |
| 27881 | ); | 27853 | Value.Payload.Slice.ptr_index => return beginComptimePtrMutationInner( |
| 27882 | }, | 27854 | sema, |
| 27855 | block, | ||
| 27856 | src, | ||
| 27857 | parent.ty.slicePtrFieldType(try sema.arena.create(Type.SlicePtrFieldTypeBuffer)), | ||
| 27858 | &val_ptr.castTag(.slice).?.data.ptr, | ||
| 27859 | ptr_elem_ty, | ||
| 27860 | parent.decl_ref_mut, | ||
| 27861 | ), | ||
| 27862 | |||
| 27863 | Value.Payload.Slice.len_index => return beginComptimePtrMutationInner( | ||
| 27864 | sema, | ||
| 27865 | block, | ||
| 27866 | src, | ||
| 27867 | Type.usize, | ||
| 27868 | &val_ptr.castTag(.slice).?.data.len, | ||
| 27869 | ptr_elem_ty, | ||
| 27870 | parent.decl_ref_mut, | ||
| 27871 | ), | ||
| 27872 | |||
| 27873 | else => unreachable, | ||
| 27874 | }, | ||
| 27875 | |||
| 27876 | .empty_struct_value => { | ||
| 27877 | const duped = try sema.arena.create(Value); | ||
| 27878 | duped.* = Value.initTag(.the_only_possible_value); | ||
| 27879 | return beginComptimePtrMutationInner( | ||
| 27880 | sema, | ||
| 27881 | block, | ||
| 27882 | src, | ||
| 27883 | parent.ty.structFieldType(field_index), | ||
| 27884 | duped, | ||
| 27885 | ptr_elem_ty, | ||
| 27886 | parent.decl_ref_mut, | ||
| 27887 | ); | ||
| 27888 | }, | ||
| 27883 | 27889 | ||
| 27890 | else => unreachable, | ||
| 27891 | }, | ||
| 27884 | else => unreachable, | 27892 | else => unreachable, |
| 27885 | }, | 27893 | }, |
| 27886 | .reinterpret => |reinterpret| { | 27894 | .reinterpret => |reinterpret| { |
| ... | @@ -27951,7 +27959,7 @@ fn beginComptimePtrMutation( | ... | @@ -27951,7 +27959,7 @@ fn beginComptimePtrMutation( |
| 27951 | switch (parent.pointee) { | 27959 | switch (parent.pointee) { |
| 27952 | .direct => |val_ptr| { | 27960 | .direct => |val_ptr| { |
| 27953 | const payload_ty = parent.ty.optionalChild(mod); | 27961 | const payload_ty = parent.ty.optionalChild(mod); |
| 27954 | switch (val_ptr.tag()) { | 27962 | switch (val_ptr.ip_index) { |
| 27955 | .undef, .null_value => { | 27963 | .undef, .null_value => { |
| 27956 | // An optional has been initialized to undefined at comptime and now we | 27964 | // An optional has been initialized to undefined at comptime and now we |
| 27957 | // are for the first time setting the payload. We must change the | 27965 | // are for the first time setting the payload. We must change the |
| ... | @@ -27973,12 +27981,19 @@ fn beginComptimePtrMutation( | ... | @@ -27973,12 +27981,19 @@ fn beginComptimePtrMutation( |
| 27973 | .ty = payload_ty, | 27981 | .ty = payload_ty, |
| 27974 | }; | 27982 | }; |
| 27975 | }, | 27983 | }, |
| 27976 | .opt_payload => return ComptimePtrMutationKit{ | 27984 | .none => switch (val_ptr.tag()) { |
| 27977 | .decl_ref_mut = parent.decl_ref_mut, | 27985 | .opt_payload => return ComptimePtrMutationKit{ |
| 27978 | .pointee = .{ .direct = &val_ptr.castTag(.opt_payload).?.data }, | 27986 | .decl_ref_mut = parent.decl_ref_mut, |
| 27979 | .ty = payload_ty, | 27987 | .pointee = .{ .direct = &val_ptr.castTag(.opt_payload).?.data }, |
| 27980 | }, | 27988 | .ty = payload_ty, |
| 27989 | }, | ||
| 27981 | 27990 | ||
| 27991 | else => return ComptimePtrMutationKit{ | ||
| 27992 | .decl_ref_mut = parent.decl_ref_mut, | ||
| 27993 | .pointee = .{ .direct = val_ptr }, | ||
| 27994 | .ty = payload_ty, | ||
| 27995 | }, | ||
| 27996 | }, | ||
| 27982 | else => return ComptimePtrMutationKit{ | 27997 | else => return ComptimePtrMutationKit{ |
| 27983 | .decl_ref_mut = parent.decl_ref_mut, | 27998 | .decl_ref_mut = parent.decl_ref_mut, |
| 27984 | .pointee = .{ .direct = val_ptr }, | 27999 | .pointee = .{ .direct = val_ptr }, |
| ... | @@ -28092,231 +28107,236 @@ fn beginComptimePtrLoad( | ... | @@ -28092,231 +28107,236 @@ fn beginComptimePtrLoad( |
| 28092 | ) ComptimePtrLoadError!ComptimePtrLoadKit { | 28107 | ) ComptimePtrLoadError!ComptimePtrLoadKit { |
| 28093 | const mod = sema.mod; | 28108 | const mod = sema.mod; |
| 28094 | const target = sema.mod.getTarget(); | 28109 | const target = sema.mod.getTarget(); |
| 28095 | var deref: ComptimePtrLoadKit = switch (ptr_val.tag()) { | 28110 | |
| 28096 | .decl_ref, | 28111 | var deref: ComptimePtrLoadKit = switch (ptr_val.ip_index) { |
| 28097 | .decl_ref_mut, | 28112 | .null_value => { |
| 28098 | => blk: { | 28113 | return sema.fail(block, src, "attempt to use null value", .{}); |
| 28099 | const decl_index = switch (ptr_val.tag()) { | ||
| 28100 | .decl_ref => ptr_val.castTag(.decl_ref).?.data, | ||
| 28101 | .decl_ref_mut => ptr_val.castTag(.decl_ref_mut).?.data.decl_index, | ||
| 28102 | else => unreachable, | ||
| 28103 | }; | ||
| 28104 | const is_mutable = ptr_val.tag() == .decl_ref_mut; | ||
| 28105 | const decl = sema.mod.declPtr(decl_index); | ||
| 28106 | const decl_tv = try decl.typedValue(); | ||
| 28107 | if (decl_tv.val.tag() == .variable) return error.RuntimeLoad; | ||
| 28108 | |||
| 28109 | const layout_defined = decl.ty.hasWellDefinedLayout(mod); | ||
| 28110 | break :blk ComptimePtrLoadKit{ | ||
| 28111 | .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null, | ||
| 28112 | .pointee = decl_tv, | ||
| 28113 | .is_mutable = is_mutable, | ||
| 28114 | .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null, | ||
| 28115 | }; | ||
| 28116 | }, | 28114 | }, |
| 28117 | 28115 | ||
| 28118 | .elem_ptr => blk: { | 28116 | .none => switch (ptr_val.tag()) { |
| 28119 | const elem_ptr = ptr_val.castTag(.elem_ptr).?.data; | 28117 | .decl_ref, |
| 28120 | const elem_ty = elem_ptr.elem_ty; | 28118 | .decl_ref_mut, |
| 28121 | var deref = try sema.beginComptimePtrLoad(block, src, elem_ptr.array_ptr, null); | 28119 | => blk: { |
| 28120 | const decl_index = switch (ptr_val.tag()) { | ||
| 28121 | .decl_ref => ptr_val.castTag(.decl_ref).?.data, | ||
| 28122 | .decl_ref_mut => ptr_val.castTag(.decl_ref_mut).?.data.decl_index, | ||
| 28123 | else => unreachable, | ||
| 28124 | }; | ||
| 28125 | const is_mutable = ptr_val.tag() == .decl_ref_mut; | ||
| 28126 | const decl = sema.mod.declPtr(decl_index); | ||
| 28127 | const decl_tv = try decl.typedValue(); | ||
| 28128 | if (decl_tv.val.tag() == .variable) return error.RuntimeLoad; | ||
| 28129 | |||
| 28130 | const layout_defined = decl.ty.hasWellDefinedLayout(mod); | ||
| 28131 | break :blk ComptimePtrLoadKit{ | ||
| 28132 | .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null, | ||
| 28133 | .pointee = decl_tv, | ||
| 28134 | .is_mutable = is_mutable, | ||
| 28135 | .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null, | ||
| 28136 | }; | ||
| 28137 | }, | ||
| 28122 | 28138 | ||
| 28123 | // This code assumes that elem_ptrs have been "flattened" in order for direct dereference | 28139 | .elem_ptr => blk: { |
| 28124 | // to succeed, meaning that elem ptrs of the same elem_ty are coalesced. Here we check that | 28140 | const elem_ptr = ptr_val.castTag(.elem_ptr).?.data; |
| 28125 | // our parent is not an elem_ptr with the same elem_ty, since that would be "unflattened" | 28141 | const elem_ty = elem_ptr.elem_ty; |
| 28126 | if (elem_ptr.array_ptr.castTag(.elem_ptr)) |parent_elem_ptr| { | 28142 | var deref = try sema.beginComptimePtrLoad(block, src, elem_ptr.array_ptr, null); |
| 28127 | assert(!(parent_elem_ptr.data.elem_ty.eql(elem_ty, sema.mod))); | 28143 | |
| 28128 | } | 28144 | // This code assumes that elem_ptrs have been "flattened" in order for direct dereference |
| 28145 | // to succeed, meaning that elem ptrs of the same elem_ty are coalesced. Here we check that | ||
| 28146 | // our parent is not an elem_ptr with the same elem_ty, since that would be "unflattened" | ||
| 28147 | if (elem_ptr.array_ptr.castTag(.elem_ptr)) |parent_elem_ptr| { | ||
| 28148 | assert(!(parent_elem_ptr.data.elem_ty.eql(elem_ty, sema.mod))); | ||
| 28149 | } | ||
| 28150 | |||
| 28151 | if (elem_ptr.index != 0) { | ||
| 28152 | if (elem_ty.hasWellDefinedLayout(mod)) { | ||
| 28153 | if (deref.parent) |*parent| { | ||
| 28154 | // Update the byte offset (in-place) | ||
| 28155 | const elem_size = try sema.typeAbiSize(elem_ty); | ||
| 28156 | const offset = parent.byte_offset + elem_size * elem_ptr.index; | ||
| 28157 | parent.byte_offset = try sema.usizeCast(block, src, offset); | ||
| 28158 | } | ||
| 28159 | } else { | ||
| 28160 | deref.parent = null; | ||
| 28161 | deref.ty_without_well_defined_layout = elem_ty; | ||
| 28162 | } | ||
| 28163 | } | ||
| 28164 | |||
| 28165 | // If we're loading an elem_ptr that was derived from a different type | ||
| 28166 | // than the true type of the underlying decl, we cannot deref directly | ||
| 28167 | const ty_matches = if (deref.pointee != null and deref.pointee.?.ty.isArrayOrVector(mod)) x: { | ||
| 28168 | const deref_elem_ty = deref.pointee.?.ty.childType(mod); | ||
| 28169 | break :x (try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok or | ||
| 28170 | (try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok; | ||
| 28171 | } else false; | ||
| 28172 | if (!ty_matches) { | ||
| 28173 | deref.pointee = null; | ||
| 28174 | break :blk deref; | ||
| 28175 | } | ||
| 28176 | |||
| 28177 | var array_tv = deref.pointee.?; | ||
| 28178 | const check_len = array_tv.ty.arrayLenIncludingSentinel(mod); | ||
| 28179 | if (maybe_array_ty) |load_ty| { | ||
| 28180 | // It's possible that we're loading a [N]T, in which case we'd like to slice | ||
| 28181 | // the pointee array directly from our parent array. | ||
| 28182 | if (load_ty.isArrayOrVector(mod) and load_ty.childType(mod).eql(elem_ty, sema.mod)) { | ||
| 28183 | const N = try sema.usizeCast(block, src, load_ty.arrayLenIncludingSentinel(mod)); | ||
| 28184 | deref.pointee = if (elem_ptr.index + N <= check_len) TypedValue{ | ||
| 28185 | .ty = try Type.array(sema.arena, N, null, elem_ty, sema.mod), | ||
| 28186 | .val = try array_tv.val.sliceArray(sema.mod, sema.arena, elem_ptr.index, elem_ptr.index + N), | ||
| 28187 | } else null; | ||
| 28188 | break :blk deref; | ||
| 28189 | } | ||
| 28190 | } | ||
| 28191 | |||
| 28192 | if (elem_ptr.index >= check_len) { | ||
| 28193 | deref.pointee = null; | ||
| 28194 | break :blk deref; | ||
| 28195 | } | ||
| 28196 | if (elem_ptr.index == check_len - 1) { | ||
| 28197 | if (array_tv.ty.sentinel(mod)) |sent| { | ||
| 28198 | deref.pointee = TypedValue{ | ||
| 28199 | .ty = elem_ty, | ||
| 28200 | .val = sent, | ||
| 28201 | }; | ||
| 28202 | break :blk deref; | ||
| 28203 | } | ||
| 28204 | } | ||
| 28205 | deref.pointee = TypedValue{ | ||
| 28206 | .ty = elem_ty, | ||
| 28207 | .val = try array_tv.val.elemValue(sema.mod, sema.arena, elem_ptr.index), | ||
| 28208 | }; | ||
| 28209 | break :blk deref; | ||
| 28210 | }, | ||
| 28129 | 28211 | ||
| 28130 | if (elem_ptr.index != 0) { | 28212 | .slice => blk: { |
| 28131 | if (elem_ty.hasWellDefinedLayout(mod)) { | 28213 | const slice = ptr_val.castTag(.slice).?.data; |
| 28132 | if (deref.parent) |*parent| { | 28214 | break :blk try sema.beginComptimePtrLoad(block, src, slice.ptr, null); |
| 28215 | }, | ||
| 28216 | |||
| 28217 | .field_ptr => blk: { | ||
| 28218 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; | ||
| 28219 | const field_index = @intCast(u32, field_ptr.field_index); | ||
| 28220 | var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.container_ptr, field_ptr.container_ty); | ||
| 28221 | |||
| 28222 | if (field_ptr.container_ty.hasWellDefinedLayout(mod)) { | ||
| 28223 | const struct_ty = field_ptr.container_ty.castTag(.@"struct"); | ||
| 28224 | if (struct_ty != null and struct_ty.?.data.layout == .Packed) { | ||
| 28225 | // packed structs are not byte addressable | ||
| 28226 | deref.parent = null; | ||
| 28227 | } else if (deref.parent) |*parent| { | ||
| 28133 | // Update the byte offset (in-place) | 28228 | // Update the byte offset (in-place) |
| 28134 | const elem_size = try sema.typeAbiSize(elem_ty); | 28229 | try sema.resolveTypeLayout(field_ptr.container_ty); |
| 28135 | const offset = parent.byte_offset + elem_size * elem_ptr.index; | 28230 | const field_offset = field_ptr.container_ty.structFieldOffset(field_index, mod); |
| 28136 | parent.byte_offset = try sema.usizeCast(block, src, offset); | 28231 | parent.byte_offset = try sema.usizeCast(block, src, parent.byte_offset + field_offset); |
| 28137 | } | 28232 | } |
| 28138 | } else { | 28233 | } else { |
| 28139 | deref.parent = null; | 28234 | deref.parent = null; |
| 28140 | deref.ty_without_well_defined_layout = elem_ty; | 28235 | deref.ty_without_well_defined_layout = field_ptr.container_ty; |
| 28141 | } | 28236 | } |
| 28142 | } | ||
| 28143 | 28237 | ||
| 28144 | // If we're loading an elem_ptr that was derived from a different type | 28238 | const tv = deref.pointee orelse { |
| 28145 | // than the true type of the underlying decl, we cannot deref directly | 28239 | deref.pointee = null; |
| 28146 | const ty_matches = if (deref.pointee != null and deref.pointee.?.ty.isArrayOrVector(mod)) x: { | 28240 | break :blk deref; |
| 28147 | const deref_elem_ty = deref.pointee.?.ty.childType(mod); | 28241 | }; |
| 28148 | break :x (try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok or | 28242 | const coerce_in_mem_ok = |
| 28149 | (try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok; | 28243 | (try sema.coerceInMemoryAllowed(block, field_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or |
| 28150 | } else false; | 28244 | (try sema.coerceInMemoryAllowed(block, tv.ty, field_ptr.container_ty, false, target, src, src)) == .ok; |
| 28151 | if (!ty_matches) { | 28245 | if (!coerce_in_mem_ok) { |
| 28152 | deref.pointee = null; | 28246 | deref.pointee = null; |
| 28153 | break :blk deref; | ||
| 28154 | } | ||
| 28155 | |||
| 28156 | var array_tv = deref.pointee.?; | ||
| 28157 | const check_len = array_tv.ty.arrayLenIncludingSentinel(mod); | ||
| 28158 | if (maybe_array_ty) |load_ty| { | ||
| 28159 | // It's possible that we're loading a [N]T, in which case we'd like to slice | ||
| 28160 | // the pointee array directly from our parent array. | ||
| 28161 | if (load_ty.isArrayOrVector(mod) and load_ty.childType(mod).eql(elem_ty, sema.mod)) { | ||
| 28162 | const N = try sema.usizeCast(block, src, load_ty.arrayLenIncludingSentinel(mod)); | ||
| 28163 | deref.pointee = if (elem_ptr.index + N <= check_len) TypedValue{ | ||
| 28164 | .ty = try Type.array(sema.arena, N, null, elem_ty, sema.mod), | ||
| 28165 | .val = try array_tv.val.sliceArray(sema.mod, sema.arena, elem_ptr.index, elem_ptr.index + N), | ||
| 28166 | } else null; | ||
| 28167 | break :blk deref; | 28247 | break :blk deref; |
| 28168 | } | 28248 | } |
| 28169 | } | ||
| 28170 | 28249 | ||
| 28171 | if (elem_ptr.index >= check_len) { | 28250 | if (field_ptr.container_ty.isSlice(mod)) { |
| 28172 | deref.pointee = null; | 28251 | const slice_val = tv.val.castTag(.slice).?.data; |
| 28173 | break :blk deref; | 28252 | deref.pointee = switch (field_index) { |
| 28174 | } | 28253 | Value.Payload.Slice.ptr_index => TypedValue{ |
| 28175 | if (elem_ptr.index == check_len - 1) { | 28254 | .ty = field_ptr.container_ty.slicePtrFieldType(try sema.arena.create(Type.SlicePtrFieldTypeBuffer)), |
| 28176 | if (array_tv.ty.sentinel(mod)) |sent| { | 28255 | .val = slice_val.ptr, |
| 28256 | }, | ||
| 28257 | Value.Payload.Slice.len_index => TypedValue{ | ||
| 28258 | .ty = Type.usize, | ||
| 28259 | .val = slice_val.len, | ||
| 28260 | }, | ||
| 28261 | else => unreachable, | ||
| 28262 | }; | ||
| 28263 | } else { | ||
| 28264 | const field_ty = field_ptr.container_ty.structFieldType(field_index); | ||
| 28177 | deref.pointee = TypedValue{ | 28265 | deref.pointee = TypedValue{ |
| 28178 | .ty = elem_ty, | 28266 | .ty = field_ty, |
| 28179 | .val = sent, | 28267 | .val = tv.val.fieldValue(tv.ty, mod, field_index), |
| 28180 | }; | 28268 | }; |
| 28181 | break :blk deref; | ||
| 28182 | } | 28269 | } |
| 28183 | } | 28270 | break :blk deref; |
| 28184 | deref.pointee = TypedValue{ | 28271 | }, |
| 28185 | .ty = elem_ty, | ||
| 28186 | .val = try array_tv.val.elemValue(sema.mod, sema.arena, elem_ptr.index), | ||
| 28187 | }; | ||
| 28188 | break :blk deref; | ||
| 28189 | }, | ||
| 28190 | 28272 | ||
| 28191 | .slice => blk: { | 28273 | .comptime_field_ptr => blk: { |
| 28192 | const slice = ptr_val.castTag(.slice).?.data; | 28274 | const comptime_field_ptr = ptr_val.castTag(.comptime_field_ptr).?.data; |
| 28193 | break :blk try sema.beginComptimePtrLoad(block, src, slice.ptr, null); | 28275 | break :blk ComptimePtrLoadKit{ |
| 28194 | }, | 28276 | .parent = null, |
| 28277 | .pointee = .{ .ty = comptime_field_ptr.field_ty, .val = comptime_field_ptr.field_val }, | ||
| 28278 | .is_mutable = false, | ||
| 28279 | .ty_without_well_defined_layout = comptime_field_ptr.field_ty, | ||
| 28280 | }; | ||
| 28281 | }, | ||
| 28195 | 28282 | ||
| 28196 | .field_ptr => blk: { | 28283 | .opt_payload_ptr, |
| 28197 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; | 28284 | .eu_payload_ptr, |
| 28198 | const field_index = @intCast(u32, field_ptr.field_index); | 28285 | => blk: { |
| 28199 | var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.container_ptr, field_ptr.container_ty); | 28286 | const payload_ptr = ptr_val.cast(Value.Payload.PayloadPtr).?.data; |
| 28287 | const payload_ty = switch (ptr_val.tag()) { | ||
| 28288 | .eu_payload_ptr => payload_ptr.container_ty.errorUnionPayload(), | ||
| 28289 | .opt_payload_ptr => payload_ptr.container_ty.optionalChild(mod), | ||
| 28290 | else => unreachable, | ||
| 28291 | }; | ||
| 28292 | var deref = try sema.beginComptimePtrLoad(block, src, payload_ptr.container_ptr, payload_ptr.container_ty); | ||
| 28200 | 28293 | ||
| 28201 | if (field_ptr.container_ty.hasWellDefinedLayout(mod)) { | 28294 | // eu_payload_ptr and opt_payload_ptr never have a well-defined layout |
| 28202 | const struct_ty = field_ptr.container_ty.castTag(.@"struct"); | 28295 | if (deref.parent != null) { |
| 28203 | if (struct_ty != null and struct_ty.?.data.layout == .Packed) { | ||
| 28204 | // packed structs are not byte addressable | ||
| 28205 | deref.parent = null; | 28296 | deref.parent = null; |
| 28206 | } else if (deref.parent) |*parent| { | 28297 | deref.ty_without_well_defined_layout = payload_ptr.container_ty; |
| 28207 | // Update the byte offset (in-place) | ||
| 28208 | try sema.resolveTypeLayout(field_ptr.container_ty); | ||
| 28209 | const field_offset = field_ptr.container_ty.structFieldOffset(field_index, mod); | ||
| 28210 | parent.byte_offset = try sema.usizeCast(block, src, parent.byte_offset + field_offset); | ||
| 28211 | } | 28298 | } |
| 28212 | } else { | ||
| 28213 | deref.parent = null; | ||
| 28214 | deref.ty_without_well_defined_layout = field_ptr.container_ty; | ||
| 28215 | } | ||
| 28216 | 28299 | ||
| 28217 | const tv = deref.pointee orelse { | 28300 | if (deref.pointee) |*tv| { |
| 28218 | deref.pointee = null; | 28301 | const coerce_in_mem_ok = |
| 28219 | break :blk deref; | 28302 | (try sema.coerceInMemoryAllowed(block, payload_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or |
| 28220 | }; | 28303 | (try sema.coerceInMemoryAllowed(block, tv.ty, payload_ptr.container_ty, false, target, src, src)) == .ok; |
| 28221 | const coerce_in_mem_ok = | 28304 | if (coerce_in_mem_ok) { |
| 28222 | (try sema.coerceInMemoryAllowed(block, field_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or | 28305 | const payload_val = switch (ptr_val.tag()) { |
| 28223 | (try sema.coerceInMemoryAllowed(block, tv.ty, field_ptr.container_ty, false, target, src, src)) == .ok; | 28306 | .eu_payload_ptr => if (tv.val.castTag(.eu_payload)) |some| some.data else { |
| 28224 | if (!coerce_in_mem_ok) { | 28307 | return sema.fail(block, src, "attempt to unwrap error: {s}", .{tv.val.castTag(.@"error").?.data.name}); |
| 28308 | }, | ||
| 28309 | .opt_payload_ptr => if (tv.val.castTag(.opt_payload)) |some| some.data else opt: { | ||
| 28310 | if (tv.val.isNull(mod)) return sema.fail(block, src, "attempt to use null value", .{}); | ||
| 28311 | break :opt tv.val; | ||
| 28312 | }, | ||
| 28313 | else => unreachable, | ||
| 28314 | }; | ||
| 28315 | tv.* = TypedValue{ .ty = payload_ty, .val = payload_val }; | ||
| 28316 | break :blk deref; | ||
| 28317 | } | ||
| 28318 | } | ||
| 28225 | deref.pointee = null; | 28319 | deref.pointee = null; |
| 28226 | break :blk deref; | 28320 | break :blk deref; |
| 28227 | } | 28321 | }, |
| 28228 | 28322 | .opt_payload => blk: { | |
| 28229 | if (field_ptr.container_ty.isSlice(mod)) { | 28323 | const opt_payload = ptr_val.castTag(.opt_payload).?.data; |
| 28230 | const slice_val = tv.val.castTag(.slice).?.data; | 28324 | break :blk try sema.beginComptimePtrLoad(block, src, opt_payload, null); |
| 28231 | deref.pointee = switch (field_index) { | 28325 | }, |
| 28232 | Value.Payload.Slice.ptr_index => TypedValue{ | ||
| 28233 | .ty = field_ptr.container_ty.slicePtrFieldType(try sema.arena.create(Type.SlicePtrFieldTypeBuffer)), | ||
| 28234 | .val = slice_val.ptr, | ||
| 28235 | }, | ||
| 28236 | Value.Payload.Slice.len_index => TypedValue{ | ||
| 28237 | .ty = Type.usize, | ||
| 28238 | .val = slice_val.len, | ||
| 28239 | }, | ||
| 28240 | else => unreachable, | ||
| 28241 | }; | ||
| 28242 | } else { | ||
| 28243 | const field_ty = field_ptr.container_ty.structFieldType(field_index); | ||
| 28244 | deref.pointee = TypedValue{ | ||
| 28245 | .ty = field_ty, | ||
| 28246 | .val = tv.val.fieldValue(tv.ty, mod, field_index), | ||
| 28247 | }; | ||
| 28248 | } | ||
| 28249 | break :blk deref; | ||
| 28250 | }, | ||
| 28251 | |||
| 28252 | .comptime_field_ptr => blk: { | ||
| 28253 | const comptime_field_ptr = ptr_val.castTag(.comptime_field_ptr).?.data; | ||
| 28254 | break :blk ComptimePtrLoadKit{ | ||
| 28255 | .parent = null, | ||
| 28256 | .pointee = .{ .ty = comptime_field_ptr.field_ty, .val = comptime_field_ptr.field_val }, | ||
| 28257 | .is_mutable = false, | ||
| 28258 | .ty_without_well_defined_layout = comptime_field_ptr.field_ty, | ||
| 28259 | }; | ||
| 28260 | }, | ||
| 28261 | |||
| 28262 | .opt_payload_ptr, | ||
| 28263 | .eu_payload_ptr, | ||
| 28264 | => blk: { | ||
| 28265 | const payload_ptr = ptr_val.cast(Value.Payload.PayloadPtr).?.data; | ||
| 28266 | const payload_ty = switch (ptr_val.tag()) { | ||
| 28267 | .eu_payload_ptr => payload_ptr.container_ty.errorUnionPayload(), | ||
| 28268 | .opt_payload_ptr => payload_ptr.container_ty.optionalChild(mod), | ||
| 28269 | else => unreachable, | ||
| 28270 | }; | ||
| 28271 | var deref = try sema.beginComptimePtrLoad(block, src, payload_ptr.container_ptr, payload_ptr.container_ty); | ||
| 28272 | 28326 | ||
| 28273 | // eu_payload_ptr and opt_payload_ptr never have a well-defined layout | 28327 | .zero, |
| 28274 | if (deref.parent != null) { | 28328 | .one, |
| 28275 | deref.parent = null; | 28329 | .int_u64, |
| 28276 | deref.ty_without_well_defined_layout = payload_ptr.container_ty; | 28330 | .int_i64, |
| 28277 | } | 28331 | .int_big_positive, |
| 28332 | .int_big_negative, | ||
| 28333 | .variable, | ||
| 28334 | .extern_fn, | ||
| 28335 | .function, | ||
| 28336 | => return error.RuntimeLoad, | ||
| 28278 | 28337 | ||
| 28279 | if (deref.pointee) |*tv| { | 28338 | else => unreachable, |
| 28280 | const coerce_in_mem_ok = | ||
| 28281 | (try sema.coerceInMemoryAllowed(block, payload_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or | ||
| 28282 | (try sema.coerceInMemoryAllowed(block, tv.ty, payload_ptr.container_ty, false, target, src, src)) == .ok; | ||
| 28283 | if (coerce_in_mem_ok) { | ||
| 28284 | const payload_val = switch (ptr_val.tag()) { | ||
| 28285 | .eu_payload_ptr => if (tv.val.castTag(.eu_payload)) |some| some.data else { | ||
| 28286 | return sema.fail(block, src, "attempt to unwrap error: {s}", .{tv.val.castTag(.@"error").?.data.name}); | ||
| 28287 | }, | ||
| 28288 | .opt_payload_ptr => if (tv.val.castTag(.opt_payload)) |some| some.data else opt: { | ||
| 28289 | if (tv.val.isNull(mod)) return sema.fail(block, src, "attempt to use null value", .{}); | ||
| 28290 | break :opt tv.val; | ||
| 28291 | }, | ||
| 28292 | else => unreachable, | ||
| 28293 | }; | ||
| 28294 | tv.* = TypedValue{ .ty = payload_ty, .val = payload_val }; | ||
| 28295 | break :blk deref; | ||
| 28296 | } | ||
| 28297 | } | ||
| 28298 | deref.pointee = null; | ||
| 28299 | break :blk deref; | ||
| 28300 | }, | ||
| 28301 | .null_value => { | ||
| 28302 | return sema.fail(block, src, "attempt to use null value", .{}); | ||
| 28303 | }, | ||
| 28304 | .opt_payload => blk: { | ||
| 28305 | const opt_payload = ptr_val.castTag(.opt_payload).?.data; | ||
| 28306 | break :blk try sema.beginComptimePtrLoad(block, src, opt_payload, null); | ||
| 28307 | }, | 28339 | }, |
| 28308 | |||
| 28309 | .zero, | ||
| 28310 | .one, | ||
| 28311 | .int_u64, | ||
| 28312 | .int_i64, | ||
| 28313 | .int_big_positive, | ||
| 28314 | .int_big_negative, | ||
| 28315 | .variable, | ||
| 28316 | .extern_fn, | ||
| 28317 | .function, | ||
| 28318 | => return error.RuntimeLoad, | ||
| 28319 | |||
| 28320 | else => unreachable, | 28340 | else => unreachable, |
| 28321 | }; | 28341 | }; |
| 28322 | 28342 | ||
| ... | @@ -28953,7 +28973,7 @@ fn coerceTupleToStruct( | ... | @@ -28953,7 +28973,7 @@ fn coerceTupleToStruct( |
| 28953 | const field_name = fields.keys()[i]; | 28973 | const field_name = fields.keys()[i]; |
| 28954 | const field = fields.values()[i]; | 28974 | const field = fields.values()[i]; |
| 28955 | const field_src = inst_src; // TODO better source location | 28975 | const field_src = inst_src; // TODO better source location |
| 28956 | if (field.default_val.tag() == .unreachable_value) { | 28976 | if (field.default_val.ip_index == .unreachable_value) { |
| 28957 | const template = "missing struct field: {s}"; | 28977 | const template = "missing struct field: {s}"; |
| 28958 | const args = .{field_name}; | 28978 | const args = .{field_name}; |
| 28959 | if (root_msg) |msg| { | 28979 | if (root_msg) |msg| { |
| ... | @@ -29023,7 +29043,7 @@ fn coerceTupleToTuple( | ... | @@ -29023,7 +29043,7 @@ fn coerceTupleToTuple( |
| 29023 | const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i); | 29043 | const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i); |
| 29024 | const coerced = try sema.coerce(block, field_ty, elem_ref, field_src); | 29044 | const coerced = try sema.coerce(block, field_ty, elem_ref, field_src); |
| 29025 | field_refs[field_index] = coerced; | 29045 | field_refs[field_index] = coerced; |
| 29026 | if (default_val.tag() != .unreachable_value) { | 29046 | if (default_val.ip_index != .unreachable_value) { |
| 29027 | const init_val = (try sema.resolveMaybeUndefVal(coerced)) orelse { | 29047 | const init_val = (try sema.resolveMaybeUndefVal(coerced)) orelse { |
| 29028 | return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known"); | 29048 | return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known"); |
| 29029 | }; | 29049 | }; |
| ... | @@ -29052,7 +29072,7 @@ fn coerceTupleToTuple( | ... | @@ -29052,7 +29072,7 @@ fn coerceTupleToTuple( |
| 29052 | const field_ty = tuple_ty.structFieldType(i); | 29072 | const field_ty = tuple_ty.structFieldType(i); |
| 29053 | 29073 | ||
| 29054 | const field_src = inst_src; // TODO better source location | 29074 | const field_src = inst_src; // TODO better source location |
| 29055 | if (default_val.tag() == .unreachable_value) { | 29075 | if (default_val.ip_index == .unreachable_value) { |
| 29056 | if (tuple_ty.isTuple()) { | 29076 | if (tuple_ty.isTuple()) { |
| 29057 | const template = "missing tuple field: {d}"; | 29077 | const template = "missing tuple field: {d}"; |
| 29058 | if (root_msg) |msg| { | 29078 | if (root_msg) |msg| { |
| ... | @@ -31557,7 +31577,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -31557,7 +31577,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 31557 | .tuple, .anon_struct => { | 31577 | .tuple, .anon_struct => { |
| 31558 | const tuple = ty.tupleFields(); | 31578 | const tuple = ty.tupleFields(); |
| 31559 | for (tuple.types, 0..) |field_ty, i| { | 31579 | for (tuple.types, 0..) |field_ty, i| { |
| 31560 | const have_comptime_val = tuple.values[i].tag() != .unreachable_value; | 31580 | const have_comptime_val = tuple.values[i].ip_index != .unreachable_value; |
| 31561 | if (!have_comptime_val and try sema.resolveTypeRequiresComptime(field_ty)) { | 31581 | if (!have_comptime_val and try sema.resolveTypeRequiresComptime(field_ty)) { |
| 31562 | return true; | 31582 | return true; |
| 31563 | } | 31583 | } |
| ... | @@ -32141,7 +32161,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void | ... | @@ -32141,7 +32161,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 32141 | gop.value_ptr.* = .{ | 32161 | gop.value_ptr.* = .{ |
| 32142 | .ty = Type.noreturn, | 32162 | .ty = Type.noreturn, |
| 32143 | .abi_align = 0, | 32163 | .abi_align = 0, |
| 32144 | .default_val = Value.initTag(.unreachable_value), | 32164 | .default_val = Value.@"unreachable", |
| 32145 | .is_comptime = is_comptime, | 32165 | .is_comptime = is_comptime, |
| 32146 | .offset = undefined, | 32166 | .offset = undefined, |
| 32147 | }; | 32167 | }; |
| ... | @@ -32965,7 +32985,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -32965,7 +32985,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 32965 | => return null, | 32985 | => return null, |
| 32966 | 32986 | ||
| 32967 | .void => return Value.void, | 32987 | .void => return Value.void, |
| 32968 | .noreturn => return Value.initTag(.unreachable_value), | 32988 | .noreturn => return Value.@"unreachable", |
| 32969 | .null => return Value.null, | 32989 | .null => return Value.null, |
| 32970 | .undefined => return Value.undef, | 32990 | .undefined => return Value.undef, |
| 32971 | 32991 | ||
| ... | @@ -33027,7 +33047,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -33027,7 +33047,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 33027 | .tuple, .anon_struct => { | 33047 | .tuple, .anon_struct => { |
| 33028 | const tuple = ty.tupleFields(); | 33048 | const tuple = ty.tupleFields(); |
| 33029 | for (tuple.values, 0..) |val, i| { | 33049 | for (tuple.values, 0..) |val, i| { |
| 33030 | const is_comptime = val.tag() != .unreachable_value; | 33050 | const is_comptime = val.ip_index != .unreachable_value; |
| 33031 | if (is_comptime) continue; | 33051 | if (is_comptime) continue; |
| 33032 | if ((try sema.typeHasOnePossibleValue(tuple.types[i])) != null) continue; | 33052 | if ((try sema.typeHasOnePossibleValue(tuple.types[i])) != null) continue; |
| 33033 | return null; | 33053 | return null; |
| ... | @@ -33059,7 +33079,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -33059,7 +33079,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 33059 | return null; | 33079 | return null; |
| 33060 | } | 33080 | } |
| 33061 | switch (enum_obj.fields.count()) { | 33081 | switch (enum_obj.fields.count()) { |
| 33062 | 0 => return Value.initTag(.unreachable_value), | 33082 | 0 => return Value.@"unreachable", |
| 33063 | 1 => if (enum_obj.values.count() == 0) { | 33083 | 1 => if (enum_obj.values.count() == 0) { |
| 33064 | return Value.zero; // auto-numbered | 33084 | return Value.zero; // auto-numbered |
| 33065 | } else { | 33085 | } else { |
| ... | @@ -33072,7 +33092,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -33072,7 +33092,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 33072 | const resolved_ty = try sema.resolveTypeFields(ty); | 33092 | const resolved_ty = try sema.resolveTypeFields(ty); |
| 33073 | const enum_simple = resolved_ty.castTag(.enum_simple).?.data; | 33093 | const enum_simple = resolved_ty.castTag(.enum_simple).?.data; |
| 33074 | switch (enum_simple.fields.count()) { | 33094 | switch (enum_simple.fields.count()) { |
| 33075 | 0 => return Value.initTag(.unreachable_value), | 33095 | 0 => return Value.@"unreachable", |
| 33076 | 1 => return Value.zero, | 33096 | 1 => return Value.zero, |
| 33077 | else => return null, | 33097 | else => return null, |
| 33078 | } | 33098 | } |
| ... | @@ -33091,7 +33111,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -33091,7 +33111,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 33091 | const tag_val = (try sema.typeHasOnePossibleValue(union_obj.tag_ty)) orelse | 33111 | const tag_val = (try sema.typeHasOnePossibleValue(union_obj.tag_ty)) orelse |
| 33092 | return null; | 33112 | return null; |
| 33093 | const fields = union_obj.fields.values(); | 33113 | const fields = union_obj.fields.values(); |
| 33094 | if (fields.len == 0) return Value.initTag(.unreachable_value); | 33114 | if (fields.len == 0) return Value.@"unreachable"; |
| 33095 | const only_field = fields[0]; | 33115 | const only_field = fields[0]; |
| 33096 | if (only_field.ty.eql(resolved_ty, sema.mod)) { | 33116 | if (only_field.ty.eql(resolved_ty, sema.mod)) { |
| 33097 | const msg = try Module.ErrorMsg.create( | 33117 | const msg = try Module.ErrorMsg.create( |
| ... | @@ -33600,7 +33620,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -33600,7 +33620,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 33600 | .tuple, .anon_struct => { | 33620 | .tuple, .anon_struct => { |
| 33601 | const tuple = ty.tupleFields(); | 33621 | const tuple = ty.tupleFields(); |
| 33602 | for (tuple.types, 0..) |field_ty, i| { | 33622 | for (tuple.types, 0..) |field_ty, i| { |
| 33603 | const have_comptime_val = tuple.values[i].tag() != .unreachable_value; | 33623 | const have_comptime_val = tuple.values[i].ip_index != .unreachable_value; |
| 33604 | if (!have_comptime_val and try sema.typeRequiresComptime(field_ty)) { | 33624 | if (!have_comptime_val and try sema.typeRequiresComptime(field_ty)) { |
| 33605 | return true; | 33625 | return true; |
| 33606 | } | 33626 | } |
| ... | @@ -33814,7 +33834,7 @@ fn numberAddWrapScalar( | ... | @@ -33814,7 +33834,7 @@ fn numberAddWrapScalar( |
| 33814 | rhs: Value, | 33834 | rhs: Value, |
| 33815 | ty: Type, | 33835 | ty: Type, |
| 33816 | ) !Value { | 33836 | ) !Value { |
| 33817 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); | 33837 | if (lhs.isUndef() or rhs.isUndef()) return Value.undef; |
| 33818 | 33838 | ||
| 33819 | const mod = sema.mod; | 33839 | const mod = sema.mod; |
| 33820 | if (ty.zigTypeTag(mod) == .ComptimeInt) { | 33840 | if (ty.zigTypeTag(mod) == .ComptimeInt) { |
| ... | @@ -33874,7 +33894,7 @@ fn numberSubWrapScalar( | ... | @@ -33874,7 +33894,7 @@ fn numberSubWrapScalar( |
| 33874 | rhs: Value, | 33894 | rhs: Value, |
| 33875 | ty: Type, | 33895 | ty: Type, |
| 33876 | ) !Value { | 33896 | ) !Value { |
| 33877 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); | 33897 | if (lhs.isUndef() or rhs.isUndef()) return Value.undef; |
| 33878 | 33898 | ||
| 33879 | const mod = sema.mod; | 33899 | const mod = sema.mod; |
| 33880 | if (ty.zigTypeTag(mod) == .ComptimeInt) { | 33900 | if (ty.zigTypeTag(mod) == .ComptimeInt) { |
| ... | @@ -34156,12 +34176,16 @@ fn intFitsInType( | ... | @@ -34156,12 +34176,16 @@ fn intFitsInType( |
| 34156 | ) CompileError!bool { | 34176 | ) CompileError!bool { |
| 34157 | const mod = sema.mod; | 34177 | const mod = sema.mod; |
| 34158 | const target = mod.getTarget(); | 34178 | const target = mod.getTarget(); |
| 34159 | switch (val.tag()) { | 34179 | switch (val.ip_index) { |
| 34160 | .zero, | ||
| 34161 | .undef, | 34180 | .undef, |
| 34181 | .zero, | ||
| 34182 | .zero_usize, | ||
| 34183 | .zero_u8, | ||
| 34162 | => return true, | 34184 | => return true, |
| 34163 | 34185 | ||
| 34164 | .one => switch (ty.zigTypeTag(mod)) { | 34186 | .one, |
| 34187 | .one_usize, | ||
| 34188 | => switch (ty.zigTypeTag(mod)) { | ||
| 34165 | .Int => { | 34189 | .Int => { |
| 34166 | const info = ty.intInfo(mod); | 34190 | const info = ty.intInfo(mod); |
| 34167 | return switch (info.signedness) { | 34191 | return switch (info.signedness) { |
| ... | @@ -34173,111 +34197,129 @@ fn intFitsInType( | ... | @@ -34173,111 +34197,129 @@ fn intFitsInType( |
| 34173 | else => unreachable, | 34197 | else => unreachable, |
| 34174 | }, | 34198 | }, |
| 34175 | 34199 | ||
| 34176 | .lazy_align => switch (ty.zigTypeTag(mod)) { | 34200 | .none => switch (val.tag()) { |
| 34177 | .Int => { | 34201 | .zero => return true, |
| 34178 | const info = ty.intInfo(mod); | 34202 | |
| 34179 | const max_needed_bits = @as(u16, 16) + @boolToInt(info.signedness == .signed); | 34203 | .one => switch (ty.zigTypeTag(mod)) { |
| 34180 | // If it is u16 or bigger we know the alignment fits without resolving it. | 34204 | .Int => { |
| 34181 | if (info.bits >= max_needed_bits) return true; | 34205 | const info = ty.intInfo(mod); |
| 34182 | const x = try sema.typeAbiAlignment(val.castTag(.lazy_align).?.data); | 34206 | return switch (info.signedness) { |
| 34183 | if (x == 0) return true; | 34207 | .signed => info.bits >= 2, |
| 34184 | const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed); | 34208 | .unsigned => info.bits >= 1, |
| 34185 | return info.bits >= actual_needed_bits; | 34209 | }; |
| 34210 | }, | ||
| 34211 | .ComptimeInt => return true, | ||
| 34212 | else => unreachable, | ||
| 34186 | }, | 34213 | }, |
| 34187 | .ComptimeInt => return true, | 34214 | |
| 34188 | else => unreachable, | 34215 | .lazy_align => switch (ty.zigTypeTag(mod)) { |
| 34189 | }, | 34216 | .Int => { |
| 34190 | .lazy_size => switch (ty.zigTypeTag(mod)) { | 34217 | const info = ty.intInfo(mod); |
| 34191 | .Int => { | 34218 | const max_needed_bits = @as(u16, 16) + @boolToInt(info.signedness == .signed); |
| 34192 | const info = ty.intInfo(mod); | 34219 | // If it is u16 or bigger we know the alignment fits without resolving it. |
| 34193 | const max_needed_bits = @as(u16, 64) + @boolToInt(info.signedness == .signed); | 34220 | if (info.bits >= max_needed_bits) return true; |
| 34194 | // If it is u64 or bigger we know the size fits without resolving it. | 34221 | const x = try sema.typeAbiAlignment(val.castTag(.lazy_align).?.data); |
| 34195 | if (info.bits >= max_needed_bits) return true; | 34222 | if (x == 0) return true; |
| 34196 | const x = try sema.typeAbiSize(val.castTag(.lazy_size).?.data); | 34223 | const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed); |
| 34197 | if (x == 0) return true; | 34224 | return info.bits >= actual_needed_bits; |
| 34198 | const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed); | 34225 | }, |
| 34199 | return info.bits >= actual_needed_bits; | 34226 | .ComptimeInt => return true, |
| 34227 | else => unreachable, | ||
| 34228 | }, | ||
| 34229 | .lazy_size => switch (ty.zigTypeTag(mod)) { | ||
| 34230 | .Int => { | ||
| 34231 | const info = ty.intInfo(mod); | ||
| 34232 | const max_needed_bits = @as(u16, 64) + @boolToInt(info.signedness == .signed); | ||
| 34233 | // If it is u64 or bigger we know the size fits without resolving it. | ||
| 34234 | if (info.bits >= max_needed_bits) return true; | ||
| 34235 | const x = try sema.typeAbiSize(val.castTag(.lazy_size).?.data); | ||
| 34236 | if (x == 0) return true; | ||
| 34237 | const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed); | ||
| 34238 | return info.bits >= actual_needed_bits; | ||
| 34239 | }, | ||
| 34240 | .ComptimeInt => return true, | ||
| 34241 | else => unreachable, | ||
| 34200 | }, | 34242 | }, |
| 34201 | .ComptimeInt => return true, | ||
| 34202 | else => unreachable, | ||
| 34203 | }, | ||
| 34204 | 34243 | ||
| 34205 | .int_u64 => switch (ty.zigTypeTag(mod)) { | 34244 | .int_u64 => switch (ty.zigTypeTag(mod)) { |
| 34206 | .Int => { | 34245 | .Int => { |
| 34207 | const x = val.castTag(.int_u64).?.data; | 34246 | const x = val.castTag(.int_u64).?.data; |
| 34208 | if (x == 0) return true; | 34247 | if (x == 0) return true; |
| 34209 | const info = ty.intInfo(mod); | 34248 | const info = ty.intInfo(mod); |
| 34210 | const needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed); | 34249 | const needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed); |
| 34211 | return info.bits >= needed_bits; | 34250 | return info.bits >= needed_bits; |
| 34251 | }, | ||
| 34252 | .ComptimeInt => return true, | ||
| 34253 | else => unreachable, | ||
| 34212 | }, | 34254 | }, |
| 34213 | .ComptimeInt => return true, | 34255 | .int_i64 => switch (ty.zigTypeTag(mod)) { |
| 34214 | else => unreachable, | 34256 | .Int => { |
| 34215 | }, | 34257 | const x = val.castTag(.int_i64).?.data; |
| 34216 | .int_i64 => switch (ty.zigTypeTag(mod)) { | 34258 | if (x == 0) return true; |
| 34217 | .Int => { | 34259 | const info = ty.intInfo(mod); |
| 34218 | const x = val.castTag(.int_i64).?.data; | 34260 | if (info.signedness == .unsigned and x < 0) |
| 34219 | if (x == 0) return true; | 34261 | return false; |
| 34220 | const info = ty.intInfo(mod); | 34262 | var buffer: Value.BigIntSpace = undefined; |
| 34221 | if (info.signedness == .unsigned and x < 0) | 34263 | return (try val.toBigIntAdvanced(&buffer, mod, sema)).fitsInTwosComp(info.signedness, info.bits); |
| 34222 | return false; | 34264 | }, |
| 34223 | var buffer: Value.BigIntSpace = undefined; | 34265 | .ComptimeInt => return true, |
| 34224 | return (try val.toBigIntAdvanced(&buffer, mod, sema)).fitsInTwosComp(info.signedness, info.bits); | 34266 | else => unreachable, |
| 34225 | }, | 34267 | }, |
| 34226 | .ComptimeInt => return true, | 34268 | .int_big_positive => switch (ty.zigTypeTag(mod)) { |
| 34227 | else => unreachable, | 34269 | .Int => { |
| 34228 | }, | 34270 | const info = ty.intInfo(mod); |
| 34229 | .int_big_positive => switch (ty.zigTypeTag(mod)) { | 34271 | return val.castTag(.int_big_positive).?.asBigInt().fitsInTwosComp(info.signedness, info.bits); |
| 34230 | .Int => { | 34272 | }, |
| 34231 | const info = ty.intInfo(mod); | 34273 | .ComptimeInt => return true, |
| 34232 | return val.castTag(.int_big_positive).?.asBigInt().fitsInTwosComp(info.signedness, info.bits); | 34274 | else => unreachable, |
| 34233 | }, | 34275 | }, |
| 34234 | .ComptimeInt => return true, | 34276 | .int_big_negative => switch (ty.zigTypeTag(mod)) { |
| 34235 | else => unreachable, | 34277 | .Int => { |
| 34236 | }, | 34278 | const info = ty.intInfo(mod); |
| 34237 | .int_big_negative => switch (ty.zigTypeTag(mod)) { | 34279 | return val.castTag(.int_big_negative).?.asBigInt().fitsInTwosComp(info.signedness, info.bits); |
| 34238 | .Int => { | 34280 | }, |
| 34239 | const info = ty.intInfo(mod); | 34281 | .ComptimeInt => return true, |
| 34240 | return val.castTag(.int_big_negative).?.asBigInt().fitsInTwosComp(info.signedness, info.bits); | 34282 | else => unreachable, |
| 34241 | }, | 34283 | }, |
| 34242 | .ComptimeInt => return true, | ||
| 34243 | else => unreachable, | ||
| 34244 | }, | ||
| 34245 | 34284 | ||
| 34246 | .the_only_possible_value => { | 34285 | .the_only_possible_value => { |
| 34247 | assert(ty.intInfo(mod).bits == 0); | 34286 | assert(ty.intInfo(mod).bits == 0); |
| 34248 | return true; | 34287 | return true; |
| 34249 | }, | 34288 | }, |
| 34250 | 34289 | ||
| 34251 | .decl_ref_mut, | 34290 | .decl_ref_mut, |
| 34252 | .extern_fn, | 34291 | .extern_fn, |
| 34253 | .decl_ref, | 34292 | .decl_ref, |
| 34254 | .function, | 34293 | .function, |
| 34255 | .variable, | 34294 | .variable, |
| 34256 | => switch (ty.zigTypeTag(mod)) { | 34295 | => switch (ty.zigTypeTag(mod)) { |
| 34257 | .Int => { | 34296 | .Int => { |
| 34258 | const info = ty.intInfo(mod); | 34297 | const info = ty.intInfo(mod); |
| 34259 | const ptr_bits = target.ptrBitWidth(); | 34298 | const ptr_bits = target.ptrBitWidth(); |
| 34260 | return switch (info.signedness) { | 34299 | return switch (info.signedness) { |
| 34261 | .signed => info.bits > ptr_bits, | 34300 | .signed => info.bits > ptr_bits, |
| 34262 | .unsigned => info.bits >= ptr_bits, | 34301 | .unsigned => info.bits >= ptr_bits, |
| 34263 | }; | 34302 | }; |
| 34303 | }, | ||
| 34304 | .ComptimeInt => return true, | ||
| 34305 | else => unreachable, | ||
| 34264 | }, | 34306 | }, |
| 34265 | .ComptimeInt => return true, | ||
| 34266 | else => unreachable, | ||
| 34267 | }, | ||
| 34268 | 34307 | ||
| 34269 | .aggregate => { | 34308 | .aggregate => { |
| 34270 | assert(ty.zigTypeTag(mod) == .Vector); | 34309 | assert(ty.zigTypeTag(mod) == .Vector); |
| 34271 | for (val.castTag(.aggregate).?.data, 0..) |elem, i| { | 34310 | for (val.castTag(.aggregate).?.data, 0..) |elem, i| { |
| 34272 | if (!(try sema.intFitsInType(elem, ty.scalarType(mod), null))) { | 34311 | if (!(try sema.intFitsInType(elem, ty.scalarType(mod), null))) { |
| 34273 | if (vector_index) |some| some.* = i; | 34312 | if (vector_index) |some| some.* = i; |
| 34274 | return false; | 34313 | return false; |
| 34314 | } | ||
| 34275 | } | 34315 | } |
| 34276 | } | 34316 | return true; |
| 34277 | return true; | 34317 | }, |
| 34318 | |||
| 34319 | else => unreachable, | ||
| 34278 | }, | 34320 | }, |
| 34279 | 34321 | ||
| 34280 | else => unreachable, | 34322 | else => @panic("TODO"), |
| 34281 | } | 34323 | } |
| 34282 | } | 34324 | } |
| 34283 | 34325 |
src/TypedValue.zig+289-286| ... | @@ -76,34 +76,236 @@ pub fn print( | ... | @@ -76,34 +76,236 @@ pub fn print( |
| 76 | if (val.isVariable(mod)) | 76 | if (val.isVariable(mod)) |
| 77 | return writer.writeAll("(variable)"); | 77 | return writer.writeAll("(variable)"); |
| 78 | 78 | ||
| 79 | while (true) switch (val.tag()) { | 79 | while (true) switch (val.ip_index) { |
| 80 | .empty_struct_value, .aggregate => { | 80 | .none => switch (val.tag()) { |
| 81 | if (level == 0) { | 81 | .empty_struct_value, .aggregate => { |
| 82 | return writer.writeAll(".{ ... }"); | 82 | if (level == 0) { |
| 83 | } | 83 | return writer.writeAll(".{ ... }"); |
| 84 | if (ty.zigTypeTag(mod) == .Struct) { | 84 | } |
| 85 | try writer.writeAll(".{"); | 85 | if (ty.zigTypeTag(mod) == .Struct) { |
| 86 | const max_len = std.math.min(ty.structFieldCount(), max_aggregate_items); | 86 | try writer.writeAll(".{"); |
| 87 | const max_len = std.math.min(ty.structFieldCount(), max_aggregate_items); | ||
| 87 | 88 | ||
| 88 | var i: u32 = 0; | 89 | var i: u32 = 0; |
| 89 | while (i < max_len) : (i += 1) { | 90 | while (i < max_len) : (i += 1) { |
| 90 | if (i != 0) try writer.writeAll(", "); | 91 | if (i != 0) try writer.writeAll(", "); |
| 91 | switch (ty.tag()) { | 92 | switch (ty.tag()) { |
| 92 | .anon_struct, .@"struct" => try writer.print(".{s} = ", .{ty.structFieldName(i)}), | 93 | .anon_struct, .@"struct" => try writer.print(".{s} = ", .{ty.structFieldName(i)}), |
| 93 | else => {}, | 94 | else => {}, |
| 95 | } | ||
| 96 | try print(.{ | ||
| 97 | .ty = ty.structFieldType(i), | ||
| 98 | .val = val.fieldValue(ty, mod, i), | ||
| 99 | }, writer, level - 1, mod); | ||
| 94 | } | 100 | } |
| 101 | if (ty.structFieldCount() > max_aggregate_items) { | ||
| 102 | try writer.writeAll(", ..."); | ||
| 103 | } | ||
| 104 | return writer.writeAll("}"); | ||
| 105 | } else { | ||
| 106 | const elem_ty = ty.elemType2(mod); | ||
| 107 | const len = ty.arrayLen(mod); | ||
| 108 | |||
| 109 | if (elem_ty.eql(Type.u8, mod)) str: { | ||
| 110 | const max_len = @intCast(usize, std.math.min(len, max_string_len)); | ||
| 111 | var buf: [max_string_len]u8 = undefined; | ||
| 112 | |||
| 113 | var i: u32 = 0; | ||
| 114 | while (i < max_len) : (i += 1) { | ||
| 115 | const elem = val.fieldValue(ty, mod, i); | ||
| 116 | if (elem.isUndef()) break :str; | ||
| 117 | buf[i] = std.math.cast(u8, elem.toUnsignedInt(mod)) orelse break :str; | ||
| 118 | } | ||
| 119 | |||
| 120 | const truncated = if (len > max_string_len) " (truncated)" else ""; | ||
| 121 | return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated }); | ||
| 122 | } | ||
| 123 | |||
| 124 | try writer.writeAll(".{ "); | ||
| 125 | |||
| 126 | const max_len = std.math.min(len, max_aggregate_items); | ||
| 127 | var i: u32 = 0; | ||
| 128 | while (i < max_len) : (i += 1) { | ||
| 129 | if (i != 0) try writer.writeAll(", "); | ||
| 130 | try print(.{ | ||
| 131 | .ty = elem_ty, | ||
| 132 | .val = val.fieldValue(ty, mod, i), | ||
| 133 | }, writer, level - 1, mod); | ||
| 134 | } | ||
| 135 | if (len > max_aggregate_items) { | ||
| 136 | try writer.writeAll(", ..."); | ||
| 137 | } | ||
| 138 | return writer.writeAll(" }"); | ||
| 139 | } | ||
| 140 | }, | ||
| 141 | .@"union" => { | ||
| 142 | if (level == 0) { | ||
| 143 | return writer.writeAll(".{ ... }"); | ||
| 144 | } | ||
| 145 | const union_val = val.castTag(.@"union").?.data; | ||
| 146 | try writer.writeAll(".{ "); | ||
| 147 | |||
| 148 | try print(.{ | ||
| 149 | .ty = ty.cast(Type.Payload.Union).?.data.tag_ty, | ||
| 150 | .val = union_val.tag, | ||
| 151 | }, writer, level - 1, mod); | ||
| 152 | try writer.writeAll(" = "); | ||
| 153 | try print(.{ | ||
| 154 | .ty = ty.unionFieldType(union_val.tag, mod), | ||
| 155 | .val = union_val.val, | ||
| 156 | }, writer, level - 1, mod); | ||
| 157 | |||
| 158 | return writer.writeAll(" }"); | ||
| 159 | }, | ||
| 160 | .zero => return writer.writeAll("0"), | ||
| 161 | .one => return writer.writeAll("1"), | ||
| 162 | .the_only_possible_value => return writer.writeAll("0"), | ||
| 163 | .ty => return val.castTag(.ty).?.data.print(writer, mod), | ||
| 164 | .int_u64 => return std.fmt.formatIntValue(val.castTag(.int_u64).?.data, "", .{}, writer), | ||
| 165 | .int_i64 => return std.fmt.formatIntValue(val.castTag(.int_i64).?.data, "", .{}, writer), | ||
| 166 | .int_big_positive => return writer.print("{}", .{val.castTag(.int_big_positive).?.asBigInt()}), | ||
| 167 | .int_big_negative => return writer.print("{}", .{val.castTag(.int_big_negative).?.asBigInt()}), | ||
| 168 | .lazy_align => { | ||
| 169 | const sub_ty = val.castTag(.lazy_align).?.data; | ||
| 170 | const x = sub_ty.abiAlignment(mod); | ||
| 171 | return writer.print("{d}", .{x}); | ||
| 172 | }, | ||
| 173 | .lazy_size => { | ||
| 174 | const sub_ty = val.castTag(.lazy_size).?.data; | ||
| 175 | const x = sub_ty.abiSize(mod); | ||
| 176 | return writer.print("{d}", .{x}); | ||
| 177 | }, | ||
| 178 | .function => return writer.print("(function '{s}')", .{ | ||
| 179 | mod.declPtr(val.castTag(.function).?.data.owner_decl).name, | ||
| 180 | }), | ||
| 181 | .extern_fn => return writer.writeAll("(extern function)"), | ||
| 182 | .variable => unreachable, | ||
| 183 | .decl_ref_mut => { | ||
| 184 | const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index; | ||
| 185 | const decl = mod.declPtr(decl_index); | ||
| 186 | if (level == 0) { | ||
| 187 | return writer.print("(decl ref mut '{s}')", .{decl.name}); | ||
| 188 | } | ||
| 189 | return print(.{ | ||
| 190 | .ty = decl.ty, | ||
| 191 | .val = decl.val, | ||
| 192 | }, writer, level - 1, mod); | ||
| 193 | }, | ||
| 194 | .decl_ref => { | ||
| 195 | const decl_index = val.castTag(.decl_ref).?.data; | ||
| 196 | const decl = mod.declPtr(decl_index); | ||
| 197 | if (level == 0) { | ||
| 198 | return writer.print("(decl ref '{s}')", .{decl.name}); | ||
| 199 | } | ||
| 200 | return print(.{ | ||
| 201 | .ty = decl.ty, | ||
| 202 | .val = decl.val, | ||
| 203 | }, writer, level - 1, mod); | ||
| 204 | }, | ||
| 205 | .comptime_field_ptr => { | ||
| 206 | const payload = val.castTag(.comptime_field_ptr).?.data; | ||
| 207 | if (level == 0) { | ||
| 208 | return writer.writeAll("(comptime field ptr)"); | ||
| 209 | } | ||
| 210 | return print(.{ | ||
| 211 | .ty = payload.field_ty, | ||
| 212 | .val = payload.field_val, | ||
| 213 | }, writer, level - 1, mod); | ||
| 214 | }, | ||
| 215 | .elem_ptr => { | ||
| 216 | const elem_ptr = val.castTag(.elem_ptr).?.data; | ||
| 217 | try writer.writeAll("&"); | ||
| 218 | if (level == 0) { | ||
| 219 | try writer.writeAll("(ptr)"); | ||
| 220 | } else { | ||
| 95 | try print(.{ | 221 | try print(.{ |
| 96 | .ty = ty.structFieldType(i), | 222 | .ty = elem_ptr.elem_ty, |
| 97 | .val = val.fieldValue(ty, mod, i), | 223 | .val = elem_ptr.array_ptr, |
| 98 | }, writer, level - 1, mod); | 224 | }, writer, level - 1, mod); |
| 99 | } | 225 | } |
| 100 | if (ty.structFieldCount() > max_aggregate_items) { | 226 | return writer.print("[{}]", .{elem_ptr.index}); |
| 227 | }, | ||
| 228 | .field_ptr => { | ||
| 229 | const field_ptr = val.castTag(.field_ptr).?.data; | ||
| 230 | try writer.writeAll("&"); | ||
| 231 | if (level == 0) { | ||
| 232 | try writer.writeAll("(ptr)"); | ||
| 233 | } else { | ||
| 234 | try print(.{ | ||
| 235 | .ty = field_ptr.container_ty, | ||
| 236 | .val = field_ptr.container_ptr, | ||
| 237 | }, writer, level - 1, mod); | ||
| 238 | } | ||
| 239 | |||
| 240 | if (field_ptr.container_ty.zigTypeTag(mod) == .Struct) { | ||
| 241 | switch (field_ptr.container_ty.tag()) { | ||
| 242 | .tuple => return writer.print(".@\"{d}\"", .{field_ptr.field_index}), | ||
| 243 | else => { | ||
| 244 | const field_name = field_ptr.container_ty.structFieldName(field_ptr.field_index); | ||
| 245 | return writer.print(".{s}", .{field_name}); | ||
| 246 | }, | ||
| 247 | } | ||
| 248 | } else if (field_ptr.container_ty.zigTypeTag(mod) == .Union) { | ||
| 249 | const field_name = field_ptr.container_ty.unionFields().keys()[field_ptr.field_index]; | ||
| 250 | return writer.print(".{s}", .{field_name}); | ||
| 251 | } else if (field_ptr.container_ty.isSlice(mod)) { | ||
| 252 | switch (field_ptr.field_index) { | ||
| 253 | Value.Payload.Slice.ptr_index => return writer.writeAll(".ptr"), | ||
| 254 | Value.Payload.Slice.len_index => return writer.writeAll(".len"), | ||
| 255 | else => unreachable, | ||
| 256 | } | ||
| 257 | } | ||
| 258 | }, | ||
| 259 | .empty_array => return writer.writeAll(".{}"), | ||
| 260 | .enum_literal => return writer.print(".{}", .{std.zig.fmtId(val.castTag(.enum_literal).?.data)}), | ||
| 261 | .enum_field_index => { | ||
| 262 | return writer.print(".{s}", .{ty.enumFieldName(val.castTag(.enum_field_index).?.data)}); | ||
| 263 | }, | ||
| 264 | .bytes => return writer.print("\"{}\"", .{std.zig.fmtEscapes(val.castTag(.bytes).?.data)}), | ||
| 265 | .str_lit => { | ||
| 266 | const str_lit = val.castTag(.str_lit).?.data; | ||
| 267 | const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; | ||
| 268 | return writer.print("\"{}\"", .{std.zig.fmtEscapes(bytes)}); | ||
| 269 | }, | ||
| 270 | .repeated => { | ||
| 271 | if (level == 0) { | ||
| 272 | return writer.writeAll(".{ ... }"); | ||
| 273 | } | ||
| 274 | var i: u32 = 0; | ||
| 275 | try writer.writeAll(".{ "); | ||
| 276 | const elem_tv = TypedValue{ | ||
| 277 | .ty = ty.elemType2(mod), | ||
| 278 | .val = val.castTag(.repeated).?.data, | ||
| 279 | }; | ||
| 280 | const len = ty.arrayLen(mod); | ||
| 281 | const max_len = std.math.min(len, max_aggregate_items); | ||
| 282 | while (i < max_len) : (i += 1) { | ||
| 283 | if (i != 0) try writer.writeAll(", "); | ||
| 284 | try print(elem_tv, writer, level - 1, mod); | ||
| 285 | } | ||
| 286 | if (len > max_aggregate_items) { | ||
| 101 | try writer.writeAll(", ..."); | 287 | try writer.writeAll(", ..."); |
| 102 | } | 288 | } |
| 103 | return writer.writeAll("}"); | 289 | return writer.writeAll(" }"); |
| 104 | } else { | 290 | }, |
| 291 | .empty_array_sentinel => { | ||
| 292 | if (level == 0) { | ||
| 293 | return writer.writeAll(".{ (sentinel) }"); | ||
| 294 | } | ||
| 295 | try writer.writeAll(".{ "); | ||
| 296 | try print(.{ | ||
| 297 | .ty = ty.elemType2(mod), | ||
| 298 | .val = ty.sentinel(mod).?, | ||
| 299 | }, writer, level - 1, mod); | ||
| 300 | return writer.writeAll(" }"); | ||
| 301 | }, | ||
| 302 | .slice => { | ||
| 303 | if (level == 0) { | ||
| 304 | return writer.writeAll(".{ ... }"); | ||
| 305 | } | ||
| 306 | const payload = val.castTag(.slice).?.data; | ||
| 105 | const elem_ty = ty.elemType2(mod); | 307 | const elem_ty = ty.elemType2(mod); |
| 106 | const len = ty.arrayLen(mod); | 308 | const len = payload.len.toUnsignedInt(mod); |
| 107 | 309 | ||
| 108 | if (elem_ty.eql(Type.u8, mod)) str: { | 310 | if (elem_ty.eql(Type.u8, mod)) str: { |
| 109 | const max_len = @intCast(usize, std.math.min(len, max_string_len)); | 311 | const max_len = @intCast(usize, std.math.min(len, max_string_len)); |
| ... | @@ -111,11 +313,13 @@ pub fn print( | ... | @@ -111,11 +313,13 @@ pub fn print( |
| 111 | 313 | ||
| 112 | var i: u32 = 0; | 314 | var i: u32 = 0; |
| 113 | while (i < max_len) : (i += 1) { | 315 | while (i < max_len) : (i += 1) { |
| 114 | const elem = val.fieldValue(ty, mod, i); | 316 | var elem_buf: Value.ElemValueBuffer = undefined; |
| 115 | if (elem.isUndef()) break :str; | 317 | const elem_val = payload.ptr.elemValueBuffer(mod, i, &elem_buf); |
| 116 | buf[i] = std.math.cast(u8, elem.toUnsignedInt(mod)) orelse break :str; | 318 | if (elem_val.isUndef()) break :str; |
| 319 | buf[i] = std.math.cast(u8, elem_val.toUnsignedInt(mod)) orelse break :str; | ||
| 117 | } | 320 | } |
| 118 | 321 | ||
| 322 | // TODO would be nice if this had a bit of unicode awareness. | ||
| 119 | const truncated = if (len > max_string_len) " (truncated)" else ""; | 323 | const truncated = if (len > max_string_len) " (truncated)" else ""; |
| 120 | return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated }); | 324 | return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated }); |
| 121 | } | 325 | } |
| ... | @@ -126,292 +330,91 @@ pub fn print( | ... | @@ -126,292 +330,91 @@ pub fn print( |
| 126 | var i: u32 = 0; | 330 | var i: u32 = 0; |
| 127 | while (i < max_len) : (i += 1) { | 331 | while (i < max_len) : (i += 1) { |
| 128 | if (i != 0) try writer.writeAll(", "); | 332 | if (i != 0) try writer.writeAll(", "); |
| 333 | var buf: Value.ElemValueBuffer = undefined; | ||
| 129 | try print(.{ | 334 | try print(.{ |
| 130 | .ty = elem_ty, | 335 | .ty = elem_ty, |
| 131 | .val = val.fieldValue(ty, mod, i), | 336 | .val = payload.ptr.elemValueBuffer(mod, i, &buf), |
| 132 | }, writer, level - 1, mod); | 337 | }, writer, level - 1, mod); |
| 133 | } | 338 | } |
| 134 | if (len > max_aggregate_items) { | 339 | if (len > max_aggregate_items) { |
| 135 | try writer.writeAll(", ..."); | 340 | try writer.writeAll(", ..."); |
| 136 | } | 341 | } |
| 137 | return writer.writeAll(" }"); | 342 | return writer.writeAll(" }"); |
| 138 | } | 343 | }, |
| 139 | }, | 344 | .float_16 => return writer.print("{d}", .{val.castTag(.float_16).?.data}), |
| 140 | .@"union" => { | 345 | .float_32 => return writer.print("{d}", .{val.castTag(.float_32).?.data}), |
| 141 | if (level == 0) { | 346 | .float_64 => return writer.print("{d}", .{val.castTag(.float_64).?.data}), |
| 142 | return writer.writeAll(".{ ... }"); | 347 | .float_80 => return writer.print("{d}", .{@floatCast(f64, val.castTag(.float_80).?.data)}), |
| 143 | } | 348 | .float_128 => return writer.print("{d}", .{@floatCast(f64, val.castTag(.float_128).?.data)}), |
| 144 | const union_val = val.castTag(.@"union").?.data; | 349 | .@"error" => return writer.print("error.{s}", .{val.castTag(.@"error").?.data.name}), |
| 145 | try writer.writeAll(".{ "); | 350 | .eu_payload => { |
| 146 | 351 | val = val.castTag(.eu_payload).?.data; | |
| 147 | try print(.{ | 352 | ty = ty.errorUnionPayload(); |
| 148 | .ty = ty.cast(Type.Payload.Union).?.data.tag_ty, | 353 | }, |
| 149 | .val = union_val.tag, | 354 | .opt_payload => { |
| 150 | }, writer, level - 1, mod); | 355 | val = val.castTag(.opt_payload).?.data; |
| 151 | try writer.writeAll(" = "); | 356 | ty = ty.optionalChild(mod); |
| 152 | try print(.{ | 357 | return print(.{ .ty = ty, .val = val }, writer, level, mod); |
| 153 | .ty = ty.unionFieldType(union_val.tag, mod), | 358 | }, |
| 154 | .val = union_val.val, | 359 | .eu_payload_ptr => { |
| 155 | }, writer, level - 1, mod); | 360 | try writer.writeAll("&"); |
| 156 | 361 | ||
| 157 | return writer.writeAll(" }"); | 362 | const data = val.castTag(.eu_payload_ptr).?.data; |
| 158 | }, | 363 | |
| 159 | .null_value => return writer.writeAll("null"), | 364 | var ty_val: Value.Payload.Ty = .{ |
| 160 | .undef => return writer.writeAll("undefined"), | 365 | .base = .{ .tag = .ty }, |
| 161 | .zero => return writer.writeAll("0"), | 366 | .data = ty, |
| 162 | .one => return writer.writeAll("1"), | 367 | }; |
| 163 | .unreachable_value => return writer.writeAll("unreachable"), | 368 | |
| 164 | .the_only_possible_value => return writer.writeAll("0"), | 369 | try writer.writeAll("@as("); |
| 165 | .ty => return val.castTag(.ty).?.data.print(writer, mod), | ||
| 166 | .int_u64 => return std.fmt.formatIntValue(val.castTag(.int_u64).?.data, "", .{}, writer), | ||
| 167 | .int_i64 => return std.fmt.formatIntValue(val.castTag(.int_i64).?.data, "", .{}, writer), | ||
| 168 | .int_big_positive => return writer.print("{}", .{val.castTag(.int_big_positive).?.asBigInt()}), | ||
| 169 | .int_big_negative => return writer.print("{}", .{val.castTag(.int_big_negative).?.asBigInt()}), | ||
| 170 | .lazy_align => { | ||
| 171 | const sub_ty = val.castTag(.lazy_align).?.data; | ||
| 172 | const x = sub_ty.abiAlignment(mod); | ||
| 173 | return writer.print("{d}", .{x}); | ||
| 174 | }, | ||
| 175 | .lazy_size => { | ||
| 176 | const sub_ty = val.castTag(.lazy_size).?.data; | ||
| 177 | const x = sub_ty.abiSize(mod); | ||
| 178 | return writer.print("{d}", .{x}); | ||
| 179 | }, | ||
| 180 | .function => return writer.print("(function '{s}')", .{ | ||
| 181 | mod.declPtr(val.castTag(.function).?.data.owner_decl).name, | ||
| 182 | }), | ||
| 183 | .extern_fn => return writer.writeAll("(extern function)"), | ||
| 184 | .variable => unreachable, | ||
| 185 | .decl_ref_mut => { | ||
| 186 | const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index; | ||
| 187 | const decl = mod.declPtr(decl_index); | ||
| 188 | if (level == 0) { | ||
| 189 | return writer.print("(decl ref mut '{s}')", .{decl.name}); | ||
| 190 | } | ||
| 191 | return print(.{ | ||
| 192 | .ty = decl.ty, | ||
| 193 | .val = decl.val, | ||
| 194 | }, writer, level - 1, mod); | ||
| 195 | }, | ||
| 196 | .decl_ref => { | ||
| 197 | const decl_index = val.castTag(.decl_ref).?.data; | ||
| 198 | const decl = mod.declPtr(decl_index); | ||
| 199 | if (level == 0) { | ||
| 200 | return writer.print("(decl ref '{s}')", .{decl.name}); | ||
| 201 | } | ||
| 202 | return print(.{ | ||
| 203 | .ty = decl.ty, | ||
| 204 | .val = decl.val, | ||
| 205 | }, writer, level - 1, mod); | ||
| 206 | }, | ||
| 207 | .comptime_field_ptr => { | ||
| 208 | const payload = val.castTag(.comptime_field_ptr).?.data; | ||
| 209 | if (level == 0) { | ||
| 210 | return writer.writeAll("(comptime field ptr)"); | ||
| 211 | } | ||
| 212 | return print(.{ | ||
| 213 | .ty = payload.field_ty, | ||
| 214 | .val = payload.field_val, | ||
| 215 | }, writer, level - 1, mod); | ||
| 216 | }, | ||
| 217 | .elem_ptr => { | ||
| 218 | const elem_ptr = val.castTag(.elem_ptr).?.data; | ||
| 219 | try writer.writeAll("&"); | ||
| 220 | if (level == 0) { | ||
| 221 | try writer.writeAll("(ptr)"); | ||
| 222 | } else { | ||
| 223 | try print(.{ | 370 | try print(.{ |
| 224 | .ty = elem_ptr.elem_ty, | 371 | .ty = Type.type, |
| 225 | .val = elem_ptr.array_ptr, | 372 | .val = Value.initPayload(&ty_val.base), |
| 226 | }, writer, level - 1, mod); | 373 | }, writer, level - 1, mod); |
| 227 | } | 374 | |
| 228 | return writer.print("[{}]", .{elem_ptr.index}); | 375 | try writer.writeAll(", &(payload of "); |
| 229 | }, | 376 | |
| 230 | .field_ptr => { | ||
| 231 | const field_ptr = val.castTag(.field_ptr).?.data; | ||
| 232 | try writer.writeAll("&"); | ||
| 233 | if (level == 0) { | ||
| 234 | try writer.writeAll("(ptr)"); | ||
| 235 | } else { | ||
| 236 | try print(.{ | 377 | try print(.{ |
| 237 | .ty = field_ptr.container_ty, | 378 | .ty = mod.singleMutPtrType(data.container_ty) catch @panic("OOM"), |
| 238 | .val = field_ptr.container_ptr, | 379 | .val = data.container_ptr, |
| 239 | }, writer, level - 1, mod); | 380 | }, writer, level - 1, mod); |
| 240 | } | ||
| 241 | |||
| 242 | if (field_ptr.container_ty.zigTypeTag(mod) == .Struct) { | ||
| 243 | switch (field_ptr.container_ty.tag()) { | ||
| 244 | .tuple => return writer.print(".@\"{d}\"", .{field_ptr.field_index}), | ||
| 245 | else => { | ||
| 246 | const field_name = field_ptr.container_ty.structFieldName(field_ptr.field_index); | ||
| 247 | return writer.print(".{s}", .{field_name}); | ||
| 248 | }, | ||
| 249 | } | ||
| 250 | } else if (field_ptr.container_ty.zigTypeTag(mod) == .Union) { | ||
| 251 | const field_name = field_ptr.container_ty.unionFields().keys()[field_ptr.field_index]; | ||
| 252 | return writer.print(".{s}", .{field_name}); | ||
| 253 | } else if (field_ptr.container_ty.isSlice(mod)) { | ||
| 254 | switch (field_ptr.field_index) { | ||
| 255 | Value.Payload.Slice.ptr_index => return writer.writeAll(".ptr"), | ||
| 256 | Value.Payload.Slice.len_index => return writer.writeAll(".len"), | ||
| 257 | else => unreachable, | ||
| 258 | } | ||
| 259 | } | ||
| 260 | }, | ||
| 261 | .empty_array => return writer.writeAll(".{}"), | ||
| 262 | .enum_literal => return writer.print(".{}", .{std.zig.fmtId(val.castTag(.enum_literal).?.data)}), | ||
| 263 | .enum_field_index => { | ||
| 264 | return writer.print(".{s}", .{ty.enumFieldName(val.castTag(.enum_field_index).?.data)}); | ||
| 265 | }, | ||
| 266 | .bytes => return writer.print("\"{}\"", .{std.zig.fmtEscapes(val.castTag(.bytes).?.data)}), | ||
| 267 | .str_lit => { | ||
| 268 | const str_lit = val.castTag(.str_lit).?.data; | ||
| 269 | const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; | ||
| 270 | return writer.print("\"{}\"", .{std.zig.fmtEscapes(bytes)}); | ||
| 271 | }, | ||
| 272 | .repeated => { | ||
| 273 | if (level == 0) { | ||
| 274 | return writer.writeAll(".{ ... }"); | ||
| 275 | } | ||
| 276 | var i: u32 = 0; | ||
| 277 | try writer.writeAll(".{ "); | ||
| 278 | const elem_tv = TypedValue{ | ||
| 279 | .ty = ty.elemType2(mod), | ||
| 280 | .val = val.castTag(.repeated).?.data, | ||
| 281 | }; | ||
| 282 | const len = ty.arrayLen(mod); | ||
| 283 | const max_len = std.math.min(len, max_aggregate_items); | ||
| 284 | while (i < max_len) : (i += 1) { | ||
| 285 | if (i != 0) try writer.writeAll(", "); | ||
| 286 | try print(elem_tv, writer, level - 1, mod); | ||
| 287 | } | ||
| 288 | if (len > max_aggregate_items) { | ||
| 289 | try writer.writeAll(", ..."); | ||
| 290 | } | ||
| 291 | return writer.writeAll(" }"); | ||
| 292 | }, | ||
| 293 | .empty_array_sentinel => { | ||
| 294 | if (level == 0) { | ||
| 295 | return writer.writeAll(".{ (sentinel) }"); | ||
| 296 | } | ||
| 297 | try writer.writeAll(".{ "); | ||
| 298 | try print(.{ | ||
| 299 | .ty = ty.elemType2(mod), | ||
| 300 | .val = ty.sentinel(mod).?, | ||
| 301 | }, writer, level - 1, mod); | ||
| 302 | return writer.writeAll(" }"); | ||
| 303 | }, | ||
| 304 | .slice => { | ||
| 305 | if (level == 0) { | ||
| 306 | return writer.writeAll(".{ ... }"); | ||
| 307 | } | ||
| 308 | const payload = val.castTag(.slice).?.data; | ||
| 309 | const elem_ty = ty.elemType2(mod); | ||
| 310 | const len = payload.len.toUnsignedInt(mod); | ||
| 311 | |||
| 312 | if (elem_ty.eql(Type.u8, mod)) str: { | ||
| 313 | const max_len = @intCast(usize, std.math.min(len, max_string_len)); | ||
| 314 | var buf: [max_string_len]u8 = undefined; | ||
| 315 | 381 | ||
| 316 | var i: u32 = 0; | 382 | try writer.writeAll("))"); |
| 317 | while (i < max_len) : (i += 1) { | 383 | return; |
| 318 | var elem_buf: Value.ElemValueBuffer = undefined; | 384 | }, |
| 319 | const elem_val = payload.ptr.elemValueBuffer(mod, i, &elem_buf); | 385 | .opt_payload_ptr => { |
| 320 | if (elem_val.isUndef()) break :str; | 386 | const data = val.castTag(.opt_payload_ptr).?.data; |
| 321 | buf[i] = std.math.cast(u8, elem_val.toUnsignedInt(mod)) orelse break :str; | ||
| 322 | } | ||
| 323 | |||
| 324 | // TODO would be nice if this had a bit of unicode awareness. | ||
| 325 | const truncated = if (len > max_string_len) " (truncated)" else ""; | ||
| 326 | return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated }); | ||
| 327 | } | ||
| 328 | 387 | ||
| 329 | try writer.writeAll(".{ "); | 388 | var ty_val: Value.Payload.Ty = .{ |
| 389 | .base = .{ .tag = .ty }, | ||
| 390 | .data = ty, | ||
| 391 | }; | ||
| 330 | 392 | ||
| 331 | const max_len = std.math.min(len, max_aggregate_items); | 393 | try writer.writeAll("@as("); |
| 332 | var i: u32 = 0; | ||
| 333 | while (i < max_len) : (i += 1) { | ||
| 334 | if (i != 0) try writer.writeAll(", "); | ||
| 335 | var buf: Value.ElemValueBuffer = undefined; | ||
| 336 | try print(.{ | 394 | try print(.{ |
| 337 | .ty = elem_ty, | 395 | .ty = Type.type, |
| 338 | .val = payload.ptr.elemValueBuffer(mod, i, &buf), | 396 | .val = Value.initPayload(&ty_val.base), |
| 339 | }, writer, level - 1, mod); | 397 | }, writer, level - 1, mod); |
| 340 | } | ||
| 341 | if (len > max_aggregate_items) { | ||
| 342 | try writer.writeAll(", ..."); | ||
| 343 | } | ||
| 344 | return writer.writeAll(" }"); | ||
| 345 | }, | ||
| 346 | .float_16 => return writer.print("{d}", .{val.castTag(.float_16).?.data}), | ||
| 347 | .float_32 => return writer.print("{d}", .{val.castTag(.float_32).?.data}), | ||
| 348 | .float_64 => return writer.print("{d}", .{val.castTag(.float_64).?.data}), | ||
| 349 | .float_80 => return writer.print("{d}", .{@floatCast(f64, val.castTag(.float_80).?.data)}), | ||
| 350 | .float_128 => return writer.print("{d}", .{@floatCast(f64, val.castTag(.float_128).?.data)}), | ||
| 351 | .@"error" => return writer.print("error.{s}", .{val.castTag(.@"error").?.data.name}), | ||
| 352 | .eu_payload => { | ||
| 353 | val = val.castTag(.eu_payload).?.data; | ||
| 354 | ty = ty.errorUnionPayload(); | ||
| 355 | }, | ||
| 356 | .opt_payload => { | ||
| 357 | val = val.castTag(.opt_payload).?.data; | ||
| 358 | ty = ty.optionalChild(mod); | ||
| 359 | return print(.{ .ty = ty, .val = val }, writer, level, mod); | ||
| 360 | }, | ||
| 361 | .eu_payload_ptr => { | ||
| 362 | try writer.writeAll("&"); | ||
| 363 | 398 | ||
| 364 | const data = val.castTag(.eu_payload_ptr).?.data; | 399 | try writer.writeAll(", &(payload of "); |
| 365 | 400 | ||
| 366 | var ty_val: Value.Payload.Ty = .{ | 401 | try print(.{ |
| 367 | .base = .{ .tag = .ty }, | 402 | .ty = mod.singleMutPtrType(data.container_ty) catch @panic("OOM"), |
| 368 | .data = ty, | 403 | .val = data.container_ptr, |
| 369 | }; | 404 | }, writer, level - 1, mod); |
| 370 | |||
| 371 | try writer.writeAll("@as("); | ||
| 372 | try print(.{ | ||
| 373 | .ty = Type.type, | ||
| 374 | .val = Value.initPayload(&ty_val.base), | ||
| 375 | }, writer, level - 1, mod); | ||
| 376 | |||
| 377 | try writer.writeAll(", &(payload of "); | ||
| 378 | 405 | ||
| 379 | try print(.{ | 406 | try writer.writeAll("))"); |
| 380 | .ty = mod.singleMutPtrType(data.container_ty) catch @panic("OOM"), | 407 | return; |
| 381 | .val = data.container_ptr, | 408 | }, |
| 382 | }, writer, level - 1, mod); | ||
| 383 | 409 | ||
| 384 | try writer.writeAll("))"); | 410 | // TODO these should not appear in this function |
| 385 | return; | 411 | .inferred_alloc => return writer.writeAll("(inferred allocation value)"), |
| 412 | .inferred_alloc_comptime => return writer.writeAll("(inferred comptime allocation value)"), | ||
| 413 | .runtime_value => return writer.writeAll("[runtime value]"), | ||
| 386 | }, | 414 | }, |
| 387 | .opt_payload_ptr => { | 415 | else => { |
| 388 | const data = val.castTag(.opt_payload_ptr).?.data; | 416 | try writer.print("(interned: {})", .{val.ip_index}); |
| 389 | |||
| 390 | var ty_val: Value.Payload.Ty = .{ | ||
| 391 | .base = .{ .tag = .ty }, | ||
| 392 | .data = ty, | ||
| 393 | }; | ||
| 394 | |||
| 395 | try writer.writeAll("@as("); | ||
| 396 | try print(.{ | ||
| 397 | .ty = Type.type, | ||
| 398 | .val = Value.initPayload(&ty_val.base), | ||
| 399 | }, writer, level - 1, mod); | ||
| 400 | |||
| 401 | try writer.writeAll(", &(payload of "); | ||
| 402 | |||
| 403 | try print(.{ | ||
| 404 | .ty = mod.singleMutPtrType(data.container_ty) catch @panic("OOM"), | ||
| 405 | .val = data.container_ptr, | ||
| 406 | }, writer, level - 1, mod); | ||
| 407 | |||
| 408 | try writer.writeAll("))"); | ||
| 409 | return; | 417 | return; |
| 410 | }, | 418 | }, |
| 411 | |||
| 412 | // TODO these should not appear in this function | ||
| 413 | .inferred_alloc => return writer.writeAll("(inferred allocation value)"), | ||
| 414 | .inferred_alloc_comptime => return writer.writeAll("(inferred comptime allocation value)"), | ||
| 415 | .runtime_value => return writer.writeAll("[runtime value]"), | ||
| 416 | }; | 419 | }; |
| 417 | } | 420 | } |
src/arch/wasm/CodeGen.zig+9-5| ... | @@ -3088,11 +3088,15 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { | ... | @@ -3088,11 +3088,15 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { |
| 3088 | 64 => return WValue{ .float64 = val.toFloat(f64) }, | 3088 | 64 => return WValue{ .float64 = val.toFloat(f64) }, |
| 3089 | else => unreachable, | 3089 | else => unreachable, |
| 3090 | }, | 3090 | }, |
| 3091 | .Pointer => switch (val.tag()) { | 3091 | .Pointer => switch (val.ip_index) { |
| 3092 | .field_ptr, .elem_ptr, .opt_payload_ptr => return func.lowerParentPtr(val, 0), | 3092 | .null_value => return WValue{ .imm32 = 0 }, |
| 3093 | .int_u64, .one => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt(mod)) }, | 3093 | .none => switch (val.tag()) { |
| 3094 | .zero, .null_value => return WValue{ .imm32 = 0 }, | 3094 | .field_ptr, .elem_ptr, .opt_payload_ptr => return func.lowerParentPtr(val, 0), |
| 3095 | else => return func.fail("Wasm TODO: lowerConstant for other const pointer tag {}", .{val.tag()}), | 3095 | .int_u64, .one => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt(mod)) }, |
| 3096 | .zero => return WValue{ .imm32 = 0 }, | ||
| 3097 | else => return func.fail("Wasm TODO: lowerConstant for other const pointer tag {}", .{val.tag()}), | ||
| 3098 | }, | ||
| 3099 | else => unreachable, | ||
| 3096 | }, | 3100 | }, |
| 3097 | .Enum => { | 3101 | .Enum => { |
| 3098 | if (val.castTag(.enum_field_index)) |field_index| { | 3102 | if (val.castTag(.enum_field_index)) |field_index| { |
src/codegen.zig+77-73| ... | @@ -312,7 +312,7 @@ pub fn generateSymbol( | ... | @@ -312,7 +312,7 @@ pub fn generateSymbol( |
| 312 | ), | 312 | ), |
| 313 | }, | 313 | }, |
| 314 | }, | 314 | }, |
| 315 | .Pointer => switch (typed_value.val.tag()) { | 315 | .Pointer => switch (typed_value.val.ip_index) { |
| 316 | .null_value => { | 316 | .null_value => { |
| 317 | switch (target.ptrBitWidth()) { | 317 | switch (target.ptrBitWidth()) { |
| 318 | 32 => { | 318 | 32 => { |
| ... | @@ -327,76 +327,79 @@ pub fn generateSymbol( | ... | @@ -327,76 +327,79 @@ pub fn generateSymbol( |
| 327 | } | 327 | } |
| 328 | return Result.ok; | 328 | return Result.ok; |
| 329 | }, | 329 | }, |
| 330 | .zero, .one, .int_u64, .int_big_positive => { | 330 | .none => switch (typed_value.val.tag()) { |
| 331 | switch (target.ptrBitWidth()) { | 331 | .zero, .one, .int_u64, .int_big_positive => { |
| 332 | 32 => { | 332 | switch (target.ptrBitWidth()) { |
| 333 | const x = typed_value.val.toUnsignedInt(mod); | 333 | 32 => { |
| 334 | mem.writeInt(u32, try code.addManyAsArray(4), @intCast(u32, x), endian); | 334 | const x = typed_value.val.toUnsignedInt(mod); |
| 335 | }, | 335 | mem.writeInt(u32, try code.addManyAsArray(4), @intCast(u32, x), endian); |
| 336 | 64 => { | 336 | }, |
| 337 | const x = typed_value.val.toUnsignedInt(mod); | 337 | 64 => { |
| 338 | mem.writeInt(u64, try code.addManyAsArray(8), x, endian); | 338 | const x = typed_value.val.toUnsignedInt(mod); |
| 339 | }, | 339 | mem.writeInt(u64, try code.addManyAsArray(8), x, endian); |
| 340 | else => unreachable, | 340 | }, |
| 341 | } | 341 | else => unreachable, |
| 342 | return Result.ok; | 342 | } |
| 343 | }, | 343 | return Result.ok; |
| 344 | .variable, .decl_ref, .decl_ref_mut => |tag| return lowerDeclRef( | ||
| 345 | bin_file, | ||
| 346 | src_loc, | ||
| 347 | typed_value, | ||
| 348 | switch (tag) { | ||
| 349 | .variable => typed_value.val.castTag(.variable).?.data.owner_decl, | ||
| 350 | .decl_ref => typed_value.val.castTag(.decl_ref).?.data, | ||
| 351 | .decl_ref_mut => typed_value.val.castTag(.decl_ref_mut).?.data.decl_index, | ||
| 352 | else => unreachable, | ||
| 353 | }, | 344 | }, |
| 354 | code, | 345 | .variable, .decl_ref, .decl_ref_mut => |tag| return lowerDeclRef( |
| 355 | debug_output, | 346 | bin_file, |
| 356 | reloc_info, | 347 | src_loc, |
| 357 | ), | 348 | typed_value, |
| 358 | .slice => { | 349 | switch (tag) { |
| 359 | const slice = typed_value.val.castTag(.slice).?.data; | 350 | .variable => typed_value.val.castTag(.variable).?.data.owner_decl, |
| 351 | .decl_ref => typed_value.val.castTag(.decl_ref).?.data, | ||
| 352 | .decl_ref_mut => typed_value.val.castTag(.decl_ref_mut).?.data.decl_index, | ||
| 353 | else => unreachable, | ||
| 354 | }, | ||
| 355 | code, | ||
| 356 | debug_output, | ||
| 357 | reloc_info, | ||
| 358 | ), | ||
| 359 | .slice => { | ||
| 360 | const slice = typed_value.val.castTag(.slice).?.data; | ||
| 360 | 361 | ||
| 361 | // generate ptr | 362 | // generate ptr |
| 362 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | 363 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 363 | const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf); | 364 | const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf); |
| 364 | switch (try generateSymbol(bin_file, src_loc, .{ | 365 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 365 | .ty = slice_ptr_field_type, | 366 | .ty = slice_ptr_field_type, |
| 366 | .val = slice.ptr, | 367 | .val = slice.ptr, |
| 367 | }, code, debug_output, reloc_info)) { | 368 | }, code, debug_output, reloc_info)) { |
| 368 | .ok => {}, | 369 | .ok => {}, |
| 369 | .fail => |em| return Result{ .fail = em }, | 370 | .fail => |em| return Result{ .fail = em }, |
| 370 | } | 371 | } |
| 371 | 372 | ||
| 372 | // generate length | 373 | // generate length |
| 373 | switch (try generateSymbol(bin_file, src_loc, .{ | 374 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 374 | .ty = Type.usize, | 375 | .ty = Type.usize, |
| 375 | .val = slice.len, | 376 | .val = slice.len, |
| 376 | }, code, debug_output, reloc_info)) { | 377 | }, code, debug_output, reloc_info)) { |
| 377 | .ok => {}, | 378 | .ok => {}, |
| 378 | .fail => |em| return Result{ .fail = em }, | 379 | .fail => |em| return Result{ .fail = em }, |
| 379 | } | 380 | } |
| 380 | 381 | ||
| 381 | return Result.ok; | 382 | return Result.ok; |
| 382 | }, | 383 | }, |
| 383 | .field_ptr, .elem_ptr, .opt_payload_ptr => return lowerParentPtr( | 384 | .field_ptr, .elem_ptr, .opt_payload_ptr => return lowerParentPtr( |
| 384 | bin_file, | 385 | bin_file, |
| 385 | src_loc, | ||
| 386 | typed_value, | ||
| 387 | typed_value.val, | ||
| 388 | code, | ||
| 389 | debug_output, | ||
| 390 | reloc_info, | ||
| 391 | ), | ||
| 392 | else => return Result{ | ||
| 393 | .fail = try ErrorMsg.create( | ||
| 394 | bin_file.allocator, | ||
| 395 | src_loc, | 386 | src_loc, |
| 396 | "TODO implement generateSymbol for pointer type value: '{s}'", | 387 | typed_value, |
| 397 | .{@tagName(typed_value.val.tag())}, | 388 | typed_value.val, |
| 389 | code, | ||
| 390 | debug_output, | ||
| 391 | reloc_info, | ||
| 398 | ), | 392 | ), |
| 393 | else => return Result{ | ||
| 394 | .fail = try ErrorMsg.create( | ||
| 395 | bin_file.allocator, | ||
| 396 | src_loc, | ||
| 397 | "TODO implement generateSymbol for pointer type value: '{s}'", | ||
| 398 | .{@tagName(typed_value.val.tag())}, | ||
| 399 | ), | ||
| 400 | }, | ||
| 399 | }, | 401 | }, |
| 402 | else => unreachable, | ||
| 400 | }, | 403 | }, |
| 401 | .Int => { | 404 | .Int => { |
| 402 | const info = typed_value.ty.intInfo(mod); | 405 | const info = typed_value.ty.intInfo(mod); |
| ... | @@ -652,7 +655,7 @@ pub fn generateSymbol( | ... | @@ -652,7 +655,7 @@ pub fn generateSymbol( |
| 652 | } | 655 | } |
| 653 | 656 | ||
| 654 | const padding = abi_size - (math.cast(usize, payload_type.abiSize(mod)) orelse return error.Overflow) - 1; | 657 | const padding = abi_size - (math.cast(usize, payload_type.abiSize(mod)) orelse return error.Overflow) - 1; |
| 655 | const value = if (typed_value.val.castTag(.opt_payload)) |payload| payload.data else Value.initTag(.undef); | 658 | const value = if (typed_value.val.castTag(.opt_payload)) |payload| payload.data else Value.undef; |
| 656 | switch (try generateSymbol(bin_file, src_loc, .{ | 659 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 657 | .ty = payload_type, | 660 | .ty = payload_type, |
| 658 | .val = value, | 661 | .val = value, |
| ... | @@ -696,7 +699,7 @@ pub fn generateSymbol( | ... | @@ -696,7 +699,7 @@ pub fn generateSymbol( |
| 696 | // emit payload part of the error union | 699 | // emit payload part of the error union |
| 697 | { | 700 | { |
| 698 | const begin = code.items.len; | 701 | const begin = code.items.len; |
| 699 | const payload_val = if (typed_value.val.castTag(.eu_payload)) |val| val.data else Value.initTag(.undef); | 702 | const payload_val = if (typed_value.val.castTag(.eu_payload)) |val| val.data else Value.undef; |
| 700 | switch (try generateSymbol(bin_file, src_loc, .{ | 703 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 701 | .ty = payload_ty, | 704 | .ty = payload_ty, |
| 702 | .val = payload_val, | 705 | .val = payload_val, |
| ... | @@ -1189,16 +1192,17 @@ pub fn genTypedValue( | ... | @@ -1189,16 +1192,17 @@ pub fn genTypedValue( |
| 1189 | .Void => return GenResult.mcv(.none), | 1192 | .Void => return GenResult.mcv(.none), |
| 1190 | .Pointer => switch (typed_value.ty.ptrSize(mod)) { | 1193 | .Pointer => switch (typed_value.ty.ptrSize(mod)) { |
| 1191 | .Slice => {}, | 1194 | .Slice => {}, |
| 1192 | else => { | 1195 | else => switch (typed_value.val.ip_index) { |
| 1193 | switch (typed_value.val.tag()) { | 1196 | .null_value => { |
| 1194 | .null_value => { | 1197 | return GenResult.mcv(.{ .immediate = 0 }); |
| 1195 | return GenResult.mcv(.{ .immediate = 0 }); | 1198 | }, |
| 1196 | }, | 1199 | .none => switch (typed_value.val.tag()) { |
| 1197 | .int_u64 => { | 1200 | .int_u64 => { |
| 1198 | return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(mod) }); | 1201 | return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(mod) }); |
| 1199 | }, | 1202 | }, |
| 1200 | else => {}, | 1203 | else => {}, |
| 1201 | } | 1204 | }, |
| 1205 | else => {}, | ||
| 1202 | }, | 1206 | }, |
| 1203 | }, | 1207 | }, |
| 1204 | .Int => { | 1208 | .Int => { |
| ... | @@ -1216,7 +1220,7 @@ pub fn genTypedValue( | ... | @@ -1216,7 +1220,7 @@ pub fn genTypedValue( |
| 1216 | }, | 1220 | }, |
| 1217 | .Optional => { | 1221 | .Optional => { |
| 1218 | if (typed_value.ty.isPtrLikeOptional(mod)) { | 1222 | if (typed_value.ty.isPtrLikeOptional(mod)) { |
| 1219 | if (typed_value.val.tag() == .null_value) return GenResult.mcv(.{ .immediate = 0 }); | 1223 | if (typed_value.val.ip_index == .null_value) return GenResult.mcv(.{ .immediate = 0 }); |
| 1220 | 1224 | ||
| 1221 | return genTypedValue(bin_file, src_loc, .{ | 1225 | return genTypedValue(bin_file, src_loc, .{ |
| 1222 | .ty = typed_value.ty.optionalChild(mod), | 1226 | .ty = typed_value.ty.optionalChild(mod), |
src/codegen/c.zig+137-105| ... | @@ -1045,8 +1045,8 @@ pub const DeclGen = struct { | ... | @@ -1045,8 +1045,8 @@ pub const DeclGen = struct { |
| 1045 | if (!empty) try writer.writeByte(')'); | 1045 | if (!empty) try writer.writeByte(')'); |
| 1046 | return; | 1046 | return; |
| 1047 | }, | 1047 | }, |
| 1048 | .Pointer => switch (val.tag()) { | 1048 | .Pointer => switch (val.ip_index) { |
| 1049 | .null_value, .zero => if (ty.isSlice(mod)) { | 1049 | .null_value => if (ty.isSlice(mod)) { |
| 1050 | var slice_pl = Value.Payload.Slice{ | 1050 | var slice_pl = Value.Payload.Slice{ |
| 1051 | .base = .{ .tag = .slice }, | 1051 | .base = .{ .tag = .slice }, |
| 1052 | .data = .{ .ptr = val, .len = Value.undef }, | 1052 | .data = .{ .ptr = val, .len = Value.undef }, |
| ... | @@ -1059,46 +1059,63 @@ pub const DeclGen = struct { | ... | @@ -1059,46 +1059,63 @@ pub const DeclGen = struct { |
| 1059 | try dg.renderType(writer, ty); | 1059 | try dg.renderType(writer, ty); |
| 1060 | try writer.writeAll(")NULL)"); | 1060 | try writer.writeAll(")NULL)"); |
| 1061 | }, | 1061 | }, |
| 1062 | .variable => { | 1062 | .none => switch (val.tag()) { |
| 1063 | const decl = val.castTag(.variable).?.data.owner_decl; | 1063 | .zero => if (ty.isSlice(mod)) { |
| 1064 | return dg.renderDeclValue(writer, ty, val, decl, location); | 1064 | var slice_pl = Value.Payload.Slice{ |
| 1065 | }, | 1065 | .base = .{ .tag = .slice }, |
| 1066 | .slice => { | 1066 | .data = .{ .ptr = val, .len = Value.undef }, |
| 1067 | if (!location.isInitializer()) { | 1067 | }; |
| 1068 | try writer.writeByte('('); | 1068 | const slice_val = Value.initPayload(&slice_pl.base); |
| 1069 | |||
| 1070 | return dg.renderValue(writer, ty, slice_val, location); | ||
| 1071 | } else { | ||
| 1072 | try writer.writeAll("(("); | ||
| 1069 | try dg.renderType(writer, ty); | 1073 | try dg.renderType(writer, ty); |
| 1070 | try writer.writeByte(')'); | 1074 | try writer.writeAll(")NULL)"); |
| 1071 | } | 1075 | }, |
| 1076 | .variable => { | ||
| 1077 | const decl = val.castTag(.variable).?.data.owner_decl; | ||
| 1078 | return dg.renderDeclValue(writer, ty, val, decl, location); | ||
| 1079 | }, | ||
| 1080 | .slice => { | ||
| 1081 | if (!location.isInitializer()) { | ||
| 1082 | try writer.writeByte('('); | ||
| 1083 | try dg.renderType(writer, ty); | ||
| 1084 | try writer.writeByte(')'); | ||
| 1085 | } | ||
| 1072 | 1086 | ||
| 1073 | const slice = val.castTag(.slice).?.data; | 1087 | const slice = val.castTag(.slice).?.data; |
| 1074 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | 1088 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 1075 | 1089 | ||
| 1076 | try writer.writeByte('{'); | 1090 | try writer.writeByte('{'); |
| 1077 | try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr, initializer_type); | 1091 | try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr, initializer_type); |
| 1078 | try writer.writeAll(", "); | 1092 | try writer.writeAll(", "); |
| 1079 | try dg.renderValue(writer, Type.usize, slice.len, initializer_type); | 1093 | try dg.renderValue(writer, Type.usize, slice.len, initializer_type); |
| 1080 | try writer.writeByte('}'); | 1094 | try writer.writeByte('}'); |
| 1081 | }, | 1095 | }, |
| 1082 | .function => { | 1096 | .function => { |
| 1083 | const func = val.castTag(.function).?.data; | 1097 | const func = val.castTag(.function).?.data; |
| 1084 | try dg.renderDeclName(writer, func.owner_decl, 0); | 1098 | try dg.renderDeclName(writer, func.owner_decl, 0); |
| 1085 | }, | 1099 | }, |
| 1086 | .extern_fn => { | 1100 | .extern_fn => { |
| 1087 | const extern_fn = val.castTag(.extern_fn).?.data; | 1101 | const extern_fn = val.castTag(.extern_fn).?.data; |
| 1088 | try dg.renderDeclName(writer, extern_fn.owner_decl, 0); | 1102 | try dg.renderDeclName(writer, extern_fn.owner_decl, 0); |
| 1089 | }, | 1103 | }, |
| 1090 | .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => { | 1104 | .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => { |
| 1091 | try writer.writeAll("(("); | 1105 | try writer.writeAll("(("); |
| 1092 | try dg.renderType(writer, ty); | 1106 | try dg.renderType(writer, ty); |
| 1093 | return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)}); | 1107 | return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)}); |
| 1108 | }, | ||
| 1109 | .field_ptr, | ||
| 1110 | .elem_ptr, | ||
| 1111 | .opt_payload_ptr, | ||
| 1112 | .eu_payload_ptr, | ||
| 1113 | .decl_ref_mut, | ||
| 1114 | .decl_ref, | ||
| 1115 | => try dg.renderParentPtr(writer, val, ty, location), | ||
| 1116 | |||
| 1117 | else => unreachable, | ||
| 1094 | }, | 1118 | }, |
| 1095 | .field_ptr, | ||
| 1096 | .elem_ptr, | ||
| 1097 | .opt_payload_ptr, | ||
| 1098 | .eu_payload_ptr, | ||
| 1099 | .decl_ref_mut, | ||
| 1100 | .decl_ref, | ||
| 1101 | => try dg.renderParentPtr(writer, val, ty, location), | ||
| 1102 | else => unreachable, | 1119 | else => unreachable, |
| 1103 | }, | 1120 | }, |
| 1104 | .Array, .Vector => { | 1121 | .Array, .Vector => { |
| ... | @@ -1109,8 +1126,8 @@ pub const DeclGen = struct { | ... | @@ -1109,8 +1126,8 @@ pub const DeclGen = struct { |
| 1109 | } | 1126 | } |
| 1110 | 1127 | ||
| 1111 | // First try specific tag representations for more efficiency. | 1128 | // First try specific tag representations for more efficiency. |
| 1112 | switch (val.tag()) { | 1129 | switch (val.ip_index) { |
| 1113 | .undef, .empty_struct_value, .empty_array => { | 1130 | .undef => { |
| 1114 | const ai = ty.arrayInfo(mod); | 1131 | const ai = ty.arrayInfo(mod); |
| 1115 | try writer.writeByte('{'); | 1132 | try writer.writeByte('{'); |
| 1116 | if (ai.sentinel) |s| { | 1133 | if (ai.sentinel) |s| { |
| ... | @@ -1119,76 +1136,91 @@ pub const DeclGen = struct { | ... | @@ -1119,76 +1136,91 @@ pub const DeclGen = struct { |
| 1119 | try writer.writeByte('0'); | 1136 | try writer.writeByte('0'); |
| 1120 | } | 1137 | } |
| 1121 | try writer.writeByte('}'); | 1138 | try writer.writeByte('}'); |
| 1139 | return; | ||
| 1122 | }, | 1140 | }, |
| 1123 | .bytes, .str_lit => |t| { | 1141 | .none => switch (val.tag()) { |
| 1124 | const bytes = switch (t) { | 1142 | .empty_struct_value, .empty_array => { |
| 1125 | .bytes => val.castTag(.bytes).?.data, | 1143 | const ai = ty.arrayInfo(mod); |
| 1126 | .str_lit => bytes: { | ||
| 1127 | const str_lit = val.castTag(.str_lit).?.data; | ||
| 1128 | break :bytes dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; | ||
| 1129 | }, | ||
| 1130 | else => unreachable, | ||
| 1131 | }; | ||
| 1132 | const sentinel = if (ty.sentinel(mod)) |sentinel| @intCast(u8, sentinel.toUnsignedInt(mod)) else null; | ||
| 1133 | try writer.print("{s}", .{ | ||
| 1134 | fmtStringLiteral(bytes[0..@intCast(usize, ty.arrayLen(mod))], sentinel), | ||
| 1135 | }); | ||
| 1136 | }, | ||
| 1137 | else => { | ||
| 1138 | // Fall back to generic implementation. | ||
| 1139 | var arena = std.heap.ArenaAllocator.init(dg.gpa); | ||
| 1140 | defer arena.deinit(); | ||
| 1141 | const arena_allocator = arena.allocator(); | ||
| 1142 | |||
| 1143 | // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal | ||
| 1144 | const max_string_initializer_len = 65535; | ||
| 1145 | |||
| 1146 | const ai = ty.arrayInfo(mod); | ||
| 1147 | if (ai.elem_type.eql(Type.u8, dg.module)) { | ||
| 1148 | if (ai.len <= max_string_initializer_len) { | ||
| 1149 | var literal = stringLiteral(writer); | ||
| 1150 | try literal.start(); | ||
| 1151 | var index: usize = 0; | ||
| 1152 | while (index < ai.len) : (index += 1) { | ||
| 1153 | const elem_val = try val.elemValue(dg.module, arena_allocator, index); | ||
| 1154 | const elem_val_u8 = if (elem_val.isUndef()) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(mod)); | ||
| 1155 | try literal.writeChar(elem_val_u8); | ||
| 1156 | } | ||
| 1157 | if (ai.sentinel) |s| { | ||
| 1158 | const s_u8 = @intCast(u8, s.toUnsignedInt(mod)); | ||
| 1159 | if (s_u8 != 0) try literal.writeChar(s_u8); | ||
| 1160 | } | ||
| 1161 | try literal.end(); | ||
| 1162 | } else { | ||
| 1163 | try writer.writeByte('{'); | ||
| 1164 | var index: usize = 0; | ||
| 1165 | while (index < ai.len) : (index += 1) { | ||
| 1166 | if (index != 0) try writer.writeByte(','); | ||
| 1167 | const elem_val = try val.elemValue(dg.module, arena_allocator, index); | ||
| 1168 | const elem_val_u8 = if (elem_val.isUndef()) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(mod)); | ||
| 1169 | try writer.print("'\\x{x}'", .{elem_val_u8}); | ||
| 1170 | } | ||
| 1171 | if (ai.sentinel) |s| { | ||
| 1172 | if (index != 0) try writer.writeByte(','); | ||
| 1173 | try dg.renderValue(writer, ai.elem_type, s, initializer_type); | ||
| 1174 | } | ||
| 1175 | try writer.writeByte('}'); | ||
| 1176 | } | ||
| 1177 | } else { | ||
| 1178 | try writer.writeByte('{'); | 1144 | try writer.writeByte('{'); |
| 1179 | var index: usize = 0; | ||
| 1180 | while (index < ai.len) : (index += 1) { | ||
| 1181 | if (index != 0) try writer.writeByte(','); | ||
| 1182 | const elem_val = try val.elemValue(dg.module, arena_allocator, index); | ||
| 1183 | try dg.renderValue(writer, ai.elem_type, elem_val, initializer_type); | ||
| 1184 | } | ||
| 1185 | if (ai.sentinel) |s| { | 1145 | if (ai.sentinel) |s| { |
| 1186 | if (index != 0) try writer.writeByte(','); | ||
| 1187 | try dg.renderValue(writer, ai.elem_type, s, initializer_type); | 1146 | try dg.renderValue(writer, ai.elem_type, s, initializer_type); |
| 1147 | } else { | ||
| 1148 | try writer.writeByte('0'); | ||
| 1188 | } | 1149 | } |
| 1189 | try writer.writeByte('}'); | 1150 | try writer.writeByte('}'); |
| 1190 | } | 1151 | return; |
| 1152 | }, | ||
| 1153 | .bytes, .str_lit => |t| { | ||
| 1154 | const bytes = switch (t) { | ||
| 1155 | .bytes => val.castTag(.bytes).?.data, | ||
| 1156 | .str_lit => bytes: { | ||
| 1157 | const str_lit = val.castTag(.str_lit).?.data; | ||
| 1158 | break :bytes dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; | ||
| 1159 | }, | ||
| 1160 | else => unreachable, | ||
| 1161 | }; | ||
| 1162 | const sentinel = if (ty.sentinel(mod)) |sentinel| @intCast(u8, sentinel.toUnsignedInt(mod)) else null; | ||
| 1163 | try writer.print("{s}", .{ | ||
| 1164 | fmtStringLiteral(bytes[0..@intCast(usize, ty.arrayLen(mod))], sentinel), | ||
| 1165 | }); | ||
| 1166 | return; | ||
| 1167 | }, | ||
| 1168 | else => {}, | ||
| 1191 | }, | 1169 | }, |
| 1170 | else => {}, | ||
| 1171 | } | ||
| 1172 | // Fall back to generic implementation. | ||
| 1173 | var arena = std.heap.ArenaAllocator.init(dg.gpa); | ||
| 1174 | defer arena.deinit(); | ||
| 1175 | const arena_allocator = arena.allocator(); | ||
| 1176 | |||
| 1177 | // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal | ||
| 1178 | const max_string_initializer_len = 65535; | ||
| 1179 | |||
| 1180 | const ai = ty.arrayInfo(mod); | ||
| 1181 | if (ai.elem_type.eql(Type.u8, dg.module)) { | ||
| 1182 | if (ai.len <= max_string_initializer_len) { | ||
| 1183 | var literal = stringLiteral(writer); | ||
| 1184 | try literal.start(); | ||
| 1185 | var index: usize = 0; | ||
| 1186 | while (index < ai.len) : (index += 1) { | ||
| 1187 | const elem_val = try val.elemValue(dg.module, arena_allocator, index); | ||
| 1188 | const elem_val_u8 = if (elem_val.isUndef()) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(mod)); | ||
| 1189 | try literal.writeChar(elem_val_u8); | ||
| 1190 | } | ||
| 1191 | if (ai.sentinel) |s| { | ||
| 1192 | const s_u8 = @intCast(u8, s.toUnsignedInt(mod)); | ||
| 1193 | if (s_u8 != 0) try literal.writeChar(s_u8); | ||
| 1194 | } | ||
| 1195 | try literal.end(); | ||
| 1196 | } else { | ||
| 1197 | try writer.writeByte('{'); | ||
| 1198 | var index: usize = 0; | ||
| 1199 | while (index < ai.len) : (index += 1) { | ||
| 1200 | if (index != 0) try writer.writeByte(','); | ||
| 1201 | const elem_val = try val.elemValue(dg.module, arena_allocator, index); | ||
| 1202 | const elem_val_u8 = if (elem_val.isUndef()) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(mod)); | ||
| 1203 | try writer.print("'\\x{x}'", .{elem_val_u8}); | ||
| 1204 | } | ||
| 1205 | if (ai.sentinel) |s| { | ||
| 1206 | if (index != 0) try writer.writeByte(','); | ||
| 1207 | try dg.renderValue(writer, ai.elem_type, s, initializer_type); | ||
| 1208 | } | ||
| 1209 | try writer.writeByte('}'); | ||
| 1210 | } | ||
| 1211 | } else { | ||
| 1212 | try writer.writeByte('{'); | ||
| 1213 | var index: usize = 0; | ||
| 1214 | while (index < ai.len) : (index += 1) { | ||
| 1215 | if (index != 0) try writer.writeByte(','); | ||
| 1216 | const elem_val = try val.elemValue(dg.module, arena_allocator, index); | ||
| 1217 | try dg.renderValue(writer, ai.elem_type, elem_val, initializer_type); | ||
| 1218 | } | ||
| 1219 | if (ai.sentinel) |s| { | ||
| 1220 | if (index != 0) try writer.writeByte(','); | ||
| 1221 | try dg.renderValue(writer, ai.elem_type, s, initializer_type); | ||
| 1222 | } | ||
| 1223 | try writer.writeByte('}'); | ||
| 1192 | } | 1224 | } |
| 1193 | }, | 1225 | }, |
| 1194 | .Bool => { | 1226 | .Bool => { |
| ... | @@ -1201,7 +1233,7 @@ pub const DeclGen = struct { | ... | @@ -1201,7 +1233,7 @@ pub const DeclGen = struct { |
| 1201 | .Optional => { | 1233 | .Optional => { |
| 1202 | const payload_ty = ty.optionalChild(mod); | 1234 | const payload_ty = ty.optionalChild(mod); |
| 1203 | 1235 | ||
| 1204 | const is_null_val = Value.makeBool(val.tag() == .null_value); | 1236 | const is_null_val = Value.makeBool(val.ip_index == .null_value); |
| 1205 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) | 1237 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) |
| 1206 | return dg.renderValue(writer, Type.bool, is_null_val, location); | 1238 | return dg.renderValue(writer, Type.bool, is_null_val, location); |
| 1207 | 1239 | ||
| ... | @@ -7765,7 +7797,7 @@ fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, mod: *const Module) T | ... | @@ -7765,7 +7797,7 @@ fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, mod: *const Module) T |
| 7765 | if (lowersToArray(ret_ty, mod)) { | 7797 | if (lowersToArray(ret_ty, mod)) { |
| 7766 | buffer.names = [1][]const u8{"array"}; | 7798 | buffer.names = [1][]const u8{"array"}; |
| 7767 | buffer.types = [1]Type{ret_ty}; | 7799 | buffer.types = [1]Type{ret_ty}; |
| 7768 | buffer.values = [1]Value{Value.initTag(.unreachable_value)}; | 7800 | buffer.values = [1]Value{Value.@"unreachable"}; |
| 7769 | buffer.payload = .{ .data = .{ | 7801 | buffer.payload = .{ .data = .{ |
| 7770 | .names = &buffer.names, | 7802 | .names = &buffer.names, |
| 7771 | .types = &buffer.types, | 7803 | .types = &buffer.types, |
src/codegen/llvm.zig+63-56| ... | @@ -2028,7 +2028,7 @@ pub const Object = struct { | ... | @@ -2028,7 +2028,7 @@ pub const Object = struct { |
| 2028 | 2028 | ||
| 2029 | for (tuple.types, 0..) |field_ty, i| { | 2029 | for (tuple.types, 0..) |field_ty, i| { |
| 2030 | const field_val = tuple.values[i]; | 2030 | const field_val = tuple.values[i]; |
| 2031 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; | 2031 | if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; |
| 2032 | 2032 | ||
| 2033 | const field_size = field_ty.abiSize(mod); | 2033 | const field_size = field_ty.abiSize(mod); |
| 2034 | const field_align = field_ty.abiAlignment(mod); | 2034 | const field_align = field_ty.abiAlignment(mod); |
| ... | @@ -2498,7 +2498,7 @@ pub const DeclGen = struct { | ... | @@ -2498,7 +2498,7 @@ pub const DeclGen = struct { |
| 2498 | global.setGlobalConstant(.True); | 2498 | global.setGlobalConstant(.True); |
| 2499 | break :init_val decl.val; | 2499 | break :init_val decl.val; |
| 2500 | }; | 2500 | }; |
| 2501 | if (init_val.tag() != .unreachable_value) { | 2501 | if (init_val.ip_index != .unreachable_value) { |
| 2502 | const llvm_init = try dg.lowerValue(.{ .ty = decl.ty, .val = init_val }); | 2502 | const llvm_init = try dg.lowerValue(.{ .ty = decl.ty, .val = init_val }); |
| 2503 | if (global.globalGetValueType() == llvm_init.typeOf()) { | 2503 | if (global.globalGetValueType() == llvm_init.typeOf()) { |
| 2504 | global.setInitializer(llvm_init); | 2504 | global.setInitializer(llvm_init); |
| ... | @@ -2954,7 +2954,7 @@ pub const DeclGen = struct { | ... | @@ -2954,7 +2954,7 @@ pub const DeclGen = struct { |
| 2954 | 2954 | ||
| 2955 | for (tuple.types, 0..) |field_ty, i| { | 2955 | for (tuple.types, 0..) |field_ty, i| { |
| 2956 | const field_val = tuple.values[i]; | 2956 | const field_val = tuple.values[i]; |
| 2957 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; | 2957 | if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; |
| 2958 | 2958 | ||
| 2959 | const field_align = field_ty.abiAlignment(mod); | 2959 | const field_align = field_ty.abiAlignment(mod); |
| 2960 | big_align = @max(big_align, field_align); | 2960 | big_align = @max(big_align, field_align); |
| ... | @@ -3359,58 +3359,65 @@ pub const DeclGen = struct { | ... | @@ -3359,58 +3359,65 @@ pub const DeclGen = struct { |
| 3359 | else => unreachable, | 3359 | else => unreachable, |
| 3360 | } | 3360 | } |
| 3361 | }, | 3361 | }, |
| 3362 | .Pointer => switch (tv.val.tag()) { | 3362 | .Pointer => switch (tv.val.ip_index) { |
| 3363 | .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl_index), | 3363 | .null_value => { |
| 3364 | .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data), | ||
| 3365 | .variable => { | ||
| 3366 | const decl_index = tv.val.castTag(.variable).?.data.owner_decl; | ||
| 3367 | const decl = dg.module.declPtr(decl_index); | ||
| 3368 | dg.module.markDeclAlive(decl); | ||
| 3369 | |||
| 3370 | const llvm_wanted_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); | ||
| 3371 | const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target); | ||
| 3372 | |||
| 3373 | const val = try dg.resolveGlobalDecl(decl_index); | ||
| 3374 | const addrspace_casted_ptr = if (llvm_actual_addrspace != llvm_wanted_addrspace) | ||
| 3375 | val.constAddrSpaceCast(dg.context.pointerType(llvm_wanted_addrspace)) | ||
| 3376 | else | ||
| 3377 | val; | ||
| 3378 | return addrspace_casted_ptr; | ||
| 3379 | }, | ||
| 3380 | .slice => { | ||
| 3381 | const slice = tv.val.castTag(.slice).?.data; | ||
| 3382 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | ||
| 3383 | const fields: [2]*llvm.Value = .{ | ||
| 3384 | try dg.lowerValue(.{ | ||
| 3385 | .ty = tv.ty.slicePtrFieldType(&buf), | ||
| 3386 | .val = slice.ptr, | ||
| 3387 | }), | ||
| 3388 | try dg.lowerValue(.{ | ||
| 3389 | .ty = Type.usize, | ||
| 3390 | .val = slice.len, | ||
| 3391 | }), | ||
| 3392 | }; | ||
| 3393 | return dg.context.constStruct(&fields, fields.len, .False); | ||
| 3394 | }, | ||
| 3395 | .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => { | ||
| 3396 | const llvm_usize = try dg.lowerType(Type.usize); | ||
| 3397 | const llvm_int = llvm_usize.constInt(tv.val.toUnsignedInt(mod), .False); | ||
| 3398 | return llvm_int.constIntToPtr(try dg.lowerType(tv.ty)); | ||
| 3399 | }, | ||
| 3400 | .field_ptr, .opt_payload_ptr, .eu_payload_ptr, .elem_ptr => { | ||
| 3401 | return dg.lowerParentPtr(tv.val, tv.ty.ptrInfo(mod).bit_offset % 8 == 0); | ||
| 3402 | }, | ||
| 3403 | .null_value, .zero => { | ||
| 3404 | const llvm_type = try dg.lowerType(tv.ty); | 3364 | const llvm_type = try dg.lowerType(tv.ty); |
| 3405 | return llvm_type.constNull(); | 3365 | return llvm_type.constNull(); |
| 3406 | }, | 3366 | }, |
| 3407 | .opt_payload => { | 3367 | .none => switch (tv.val.tag()) { |
| 3408 | const payload = tv.val.castTag(.opt_payload).?.data; | 3368 | .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl_index), |
| 3409 | return dg.lowerParentPtr(payload, tv.ty.ptrInfo(mod).bit_offset % 8 == 0); | 3369 | .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data), |
| 3370 | .variable => { | ||
| 3371 | const decl_index = tv.val.castTag(.variable).?.data.owner_decl; | ||
| 3372 | const decl = dg.module.declPtr(decl_index); | ||
| 3373 | dg.module.markDeclAlive(decl); | ||
| 3374 | |||
| 3375 | const llvm_wanted_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); | ||
| 3376 | const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target); | ||
| 3377 | |||
| 3378 | const val = try dg.resolveGlobalDecl(decl_index); | ||
| 3379 | const addrspace_casted_ptr = if (llvm_actual_addrspace != llvm_wanted_addrspace) | ||
| 3380 | val.constAddrSpaceCast(dg.context.pointerType(llvm_wanted_addrspace)) | ||
| 3381 | else | ||
| 3382 | val; | ||
| 3383 | return addrspace_casted_ptr; | ||
| 3384 | }, | ||
| 3385 | .slice => { | ||
| 3386 | const slice = tv.val.castTag(.slice).?.data; | ||
| 3387 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | ||
| 3388 | const fields: [2]*llvm.Value = .{ | ||
| 3389 | try dg.lowerValue(.{ | ||
| 3390 | .ty = tv.ty.slicePtrFieldType(&buf), | ||
| 3391 | .val = slice.ptr, | ||
| 3392 | }), | ||
| 3393 | try dg.lowerValue(.{ | ||
| 3394 | .ty = Type.usize, | ||
| 3395 | .val = slice.len, | ||
| 3396 | }), | ||
| 3397 | }; | ||
| 3398 | return dg.context.constStruct(&fields, fields.len, .False); | ||
| 3399 | }, | ||
| 3400 | .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => { | ||
| 3401 | const llvm_usize = try dg.lowerType(Type.usize); | ||
| 3402 | const llvm_int = llvm_usize.constInt(tv.val.toUnsignedInt(mod), .False); | ||
| 3403 | return llvm_int.constIntToPtr(try dg.lowerType(tv.ty)); | ||
| 3404 | }, | ||
| 3405 | .field_ptr, .opt_payload_ptr, .eu_payload_ptr, .elem_ptr => { | ||
| 3406 | return dg.lowerParentPtr(tv.val, tv.ty.ptrInfo(mod).bit_offset % 8 == 0); | ||
| 3407 | }, | ||
| 3408 | .zero => { | ||
| 3409 | const llvm_type = try dg.lowerType(tv.ty); | ||
| 3410 | return llvm_type.constNull(); | ||
| 3411 | }, | ||
| 3412 | .opt_payload => { | ||
| 3413 | const payload = tv.val.castTag(.opt_payload).?.data; | ||
| 3414 | return dg.lowerParentPtr(payload, tv.ty.ptrInfo(mod).bit_offset % 8 == 0); | ||
| 3415 | }, | ||
| 3416 | else => |tag| return dg.todo("implement const of pointer type '{}' ({})", .{ | ||
| 3417 | tv.ty.fmtDebug(), tag, | ||
| 3418 | }), | ||
| 3410 | }, | 3419 | }, |
| 3411 | else => |tag| return dg.todo("implement const of pointer type '{}' ({})", .{ | 3420 | else => unreachable, |
| 3412 | tv.ty.fmtDebug(), tag, | ||
| 3413 | }), | ||
| 3414 | }, | 3421 | }, |
| 3415 | .Array => switch (tv.val.tag()) { | 3422 | .Array => switch (tv.val.tag()) { |
| 3416 | .bytes => { | 3423 | .bytes => { |
| ... | @@ -3555,7 +3562,7 @@ pub const DeclGen = struct { | ... | @@ -3555,7 +3562,7 @@ pub const DeclGen = struct { |
| 3555 | var fields_buf: [3]*llvm.Value = undefined; | 3562 | var fields_buf: [3]*llvm.Value = undefined; |
| 3556 | fields_buf[0] = try dg.lowerValue(.{ | 3563 | fields_buf[0] = try dg.lowerValue(.{ |
| 3557 | .ty = payload_ty, | 3564 | .ty = payload_ty, |
| 3558 | .val = if (tv.val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef), | 3565 | .val = if (tv.val.castTag(.opt_payload)) |pl| pl.data else Value.undef, |
| 3559 | }); | 3566 | }); |
| 3560 | fields_buf[1] = non_null_bit; | 3567 | fields_buf[1] = non_null_bit; |
| 3561 | if (llvm_field_count > 2) { | 3568 | if (llvm_field_count > 2) { |
| ... | @@ -3606,7 +3613,7 @@ pub const DeclGen = struct { | ... | @@ -3606,7 +3613,7 @@ pub const DeclGen = struct { |
| 3606 | }); | 3613 | }); |
| 3607 | const llvm_payload_value = try dg.lowerValue(.{ | 3614 | const llvm_payload_value = try dg.lowerValue(.{ |
| 3608 | .ty = payload_type, | 3615 | .ty = payload_type, |
| 3609 | .val = if (tv.val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef), | 3616 | .val = if (tv.val.castTag(.eu_payload)) |pl| pl.data else Value.undef, |
| 3610 | }); | 3617 | }); |
| 3611 | var fields_buf: [3]*llvm.Value = undefined; | 3618 | var fields_buf: [3]*llvm.Value = undefined; |
| 3612 | 3619 | ||
| ... | @@ -3645,7 +3652,7 @@ pub const DeclGen = struct { | ... | @@ -3645,7 +3652,7 @@ pub const DeclGen = struct { |
| 3645 | var need_unnamed = false; | 3652 | var need_unnamed = false; |
| 3646 | 3653 | ||
| 3647 | for (tuple.types, 0..) |field_ty, i| { | 3654 | for (tuple.types, 0..) |field_ty, i| { |
| 3648 | if (tuple.values[i].tag() != .unreachable_value) continue; | 3655 | if (tuple.values[i].ip_index != .unreachable_value) continue; |
| 3649 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 3656 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 3650 | 3657 | ||
| 3651 | const field_align = field_ty.abiAlignment(mod); | 3658 | const field_align = field_ty.abiAlignment(mod); |
| ... | @@ -10501,7 +10508,7 @@ fn llvmFieldIndex( | ... | @@ -10501,7 +10508,7 @@ fn llvmFieldIndex( |
| 10501 | const tuple = ty.tupleFields(); | 10508 | const tuple = ty.tupleFields(); |
| 10502 | var llvm_field_index: c_uint = 0; | 10509 | var llvm_field_index: c_uint = 0; |
| 10503 | for (tuple.types, 0..) |field_ty, i| { | 10510 | for (tuple.types, 0..) |field_ty, i| { |
| 10504 | if (tuple.values[i].tag() != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; | 10511 | if (tuple.values[i].ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; |
| 10505 | 10512 | ||
| 10506 | const field_align = field_ty.abiAlignment(mod); | 10513 | const field_align = field_ty.abiAlignment(mod); |
| 10507 | big_align = @max(big_align, field_align); | 10514 | big_align = @max(big_align, field_align); |
| ... | @@ -11117,7 +11124,7 @@ fn isByRef(ty: Type, mod: *const Module) bool { | ... | @@ -11117,7 +11124,7 @@ fn isByRef(ty: Type, mod: *const Module) bool { |
| 11117 | const tuple = ty.tupleFields(); | 11124 | const tuple = ty.tupleFields(); |
| 11118 | var count: usize = 0; | 11125 | var count: usize = 0; |
| 11119 | for (tuple.values, 0..) |field_val, i| { | 11126 | for (tuple.values, 0..) |field_val, i| { |
| 11120 | if (field_val.tag() != .unreachable_value or !tuple.types[i].hasRuntimeBits(mod)) continue; | 11127 | if (field_val.ip_index != .unreachable_value or !tuple.types[i].hasRuntimeBits(mod)) continue; |
| 11121 | 11128 | ||
| 11122 | count += 1; | 11129 | count += 1; |
| 11123 | if (count > max_fields_byval) return true; | 11130 | if (count > max_fields_byval) return true; |
src/codegen/spirv.zig+6-5| ... | @@ -674,7 +674,7 @@ pub const DeclGen = struct { | ... | @@ -674,7 +674,7 @@ pub const DeclGen = struct { |
| 674 | try self.lower(ptr_ty, slice.ptr); | 674 | try self.lower(ptr_ty, slice.ptr); |
| 675 | try self.addInt(Type.usize, slice.len); | 675 | try self.addInt(Type.usize, slice.len); |
| 676 | }, | 676 | }, |
| 677 | .null_value, .zero => try self.addNullPtr(try dg.resolveType(ty, .indirect)), | 677 | .zero => try self.addNullPtr(try dg.resolveType(ty, .indirect)), |
| 678 | .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => { | 678 | .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => { |
| 679 | try self.addInt(Type.usize, val); | 679 | try self.addInt(Type.usize, val); |
| 680 | }, | 680 | }, |
| ... | @@ -813,7 +813,8 @@ pub const DeclGen = struct { | ... | @@ -813,7 +813,8 @@ pub const DeclGen = struct { |
| 813 | const error_size = Type.anyerror.abiAlignment(mod); | 813 | const error_size = Type.anyerror.abiAlignment(mod); |
| 814 | const ty_size = ty.abiSize(mod); | 814 | const ty_size = ty.abiSize(mod); |
| 815 | const padding = ty_size - payload_size - error_size; | 815 | const padding = ty_size - payload_size - error_size; |
| 816 | const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef); | 816 | |
| 817 | const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.undef; | ||
| 817 | 818 | ||
| 818 | if (eu_layout.error_first) { | 819 | if (eu_layout.error_first) { |
| 819 | try self.lower(Type.anyerror, error_val); | 820 | try self.lower(Type.anyerror, error_val); |
| ... | @@ -1021,7 +1022,7 @@ pub const DeclGen = struct { | ... | @@ -1021,7 +1022,7 @@ pub const DeclGen = struct { |
| 1021 | return try self.constant(Type.anyerror, error_val, repr); | 1022 | return try self.constant(Type.anyerror, error_val, repr); |
| 1022 | } | 1023 | } |
| 1023 | 1024 | ||
| 1024 | const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef); | 1025 | const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.undef; |
| 1025 | 1026 | ||
| 1026 | var members: [2]IdRef = undefined; | 1027 | var members: [2]IdRef = undefined; |
| 1027 | if (eu_layout.error_first) { | 1028 | if (eu_layout.error_first) { |
| ... | @@ -1292,7 +1293,7 @@ pub const DeclGen = struct { | ... | @@ -1292,7 +1293,7 @@ pub const DeclGen = struct { |
| 1292 | var member_index: usize = 0; | 1293 | var member_index: usize = 0; |
| 1293 | for (tuple.types, 0..) |field_ty, i| { | 1294 | for (tuple.types, 0..) |field_ty, i| { |
| 1294 | const field_val = tuple.values[i]; | 1295 | const field_val = tuple.values[i]; |
| 1295 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; | 1296 | if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; |
| 1296 | 1297 | ||
| 1297 | member_types[member_index] = try self.resolveType(field_ty, .indirect); | 1298 | member_types[member_index] = try self.resolveType(field_ty, .indirect); |
| 1298 | member_index += 1; | 1299 | member_index += 1; |
| ... | @@ -1596,7 +1597,7 @@ pub const DeclGen = struct { | ... | @@ -1596,7 +1597,7 @@ pub const DeclGen = struct { |
| 1596 | else | 1597 | else |
| 1597 | decl.val; | 1598 | decl.val; |
| 1598 | 1599 | ||
| 1599 | if (init_val.tag() == .unreachable_value) { | 1600 | if (init_val.ip_index == .unreachable_value) { |
| 1600 | return self.todo("importing extern variables", .{}); | 1601 | return self.todo("importing extern variables", .{}); |
| 1601 | } | 1602 | } |
| 1602 | 1603 |
src/type.zig+29-29| ... | @@ -533,14 +533,14 @@ pub const Type = struct { | ... | @@ -533,14 +533,14 @@ pub const Type = struct { |
| 533 | for (a_tuple.values, 0..) |a_val, i| { | 533 | for (a_tuple.values, 0..) |a_val, i| { |
| 534 | const ty = a_tuple.types[i]; | 534 | const ty = a_tuple.types[i]; |
| 535 | const b_val = b_tuple.values[i]; | 535 | const b_val = b_tuple.values[i]; |
| 536 | if (a_val.tag() == .unreachable_value) { | 536 | if (a_val.ip_index == .unreachable_value) { |
| 537 | if (b_val.tag() == .unreachable_value) { | 537 | if (b_val.ip_index == .unreachable_value) { |
| 538 | continue; | 538 | continue; |
| 539 | } else { | 539 | } else { |
| 540 | return false; | 540 | return false; |
| 541 | } | 541 | } |
| 542 | } else { | 542 | } else { |
| 543 | if (b_val.tag() == .unreachable_value) { | 543 | if (b_val.ip_index == .unreachable_value) { |
| 544 | return false; | 544 | return false; |
| 545 | } else { | 545 | } else { |
| 546 | if (!Value.eql(a_val, b_val, ty, mod)) return false; | 546 | if (!Value.eql(a_val, b_val, ty, mod)) return false; |
| ... | @@ -569,14 +569,14 @@ pub const Type = struct { | ... | @@ -569,14 +569,14 @@ pub const Type = struct { |
| 569 | for (a_struct_obj.values, 0..) |a_val, i| { | 569 | for (a_struct_obj.values, 0..) |a_val, i| { |
| 570 | const ty = a_struct_obj.types[i]; | 570 | const ty = a_struct_obj.types[i]; |
| 571 | const b_val = b_struct_obj.values[i]; | 571 | const b_val = b_struct_obj.values[i]; |
| 572 | if (a_val.tag() == .unreachable_value) { | 572 | if (a_val.ip_index == .unreachable_value) { |
| 573 | if (b_val.tag() == .unreachable_value) { | 573 | if (b_val.ip_index == .unreachable_value) { |
| 574 | continue; | 574 | continue; |
| 575 | } else { | 575 | } else { |
| 576 | return false; | 576 | return false; |
| 577 | } | 577 | } |
| 578 | } else { | 578 | } else { |
| 579 | if (b_val.tag() == .unreachable_value) { | 579 | if (b_val.ip_index == .unreachable_value) { |
| 580 | return false; | 580 | return false; |
| 581 | } else { | 581 | } else { |
| 582 | if (!Value.eql(a_val, b_val, ty, mod)) return false; | 582 | if (!Value.eql(a_val, b_val, ty, mod)) return false; |
| ... | @@ -750,7 +750,7 @@ pub const Type = struct { | ... | @@ -750,7 +750,7 @@ pub const Type = struct { |
| 750 | for (tuple.types, 0..) |field_ty, i| { | 750 | for (tuple.types, 0..) |field_ty, i| { |
| 751 | hashWithHasher(field_ty, hasher, mod); | 751 | hashWithHasher(field_ty, hasher, mod); |
| 752 | const field_val = tuple.values[i]; | 752 | const field_val = tuple.values[i]; |
| 753 | if (field_val.tag() == .unreachable_value) continue; | 753 | if (field_val.ip_index == .unreachable_value) continue; |
| 754 | field_val.hash(field_ty, hasher, mod); | 754 | field_val.hash(field_ty, hasher, mod); |
| 755 | } | 755 | } |
| 756 | }, | 756 | }, |
| ... | @@ -764,7 +764,7 @@ pub const Type = struct { | ... | @@ -764,7 +764,7 @@ pub const Type = struct { |
| 764 | const field_val = struct_obj.values[i]; | 764 | const field_val = struct_obj.values[i]; |
| 765 | hasher.update(field_name); | 765 | hasher.update(field_name); |
| 766 | hashWithHasher(field_ty, hasher, mod); | 766 | hashWithHasher(field_ty, hasher, mod); |
| 767 | if (field_val.tag() == .unreachable_value) continue; | 767 | if (field_val.ip_index == .unreachable_value) continue; |
| 768 | field_val.hash(field_ty, hasher, mod); | 768 | field_val.hash(field_ty, hasher, mod); |
| 769 | } | 769 | } |
| 770 | }, | 770 | }, |
| ... | @@ -1139,11 +1139,11 @@ pub const Type = struct { | ... | @@ -1139,11 +1139,11 @@ pub const Type = struct { |
| 1139 | for (tuple.types, 0..) |field_ty, i| { | 1139 | for (tuple.types, 0..) |field_ty, i| { |
| 1140 | if (i != 0) try writer.writeAll(", "); | 1140 | if (i != 0) try writer.writeAll(", "); |
| 1141 | const val = tuple.values[i]; | 1141 | const val = tuple.values[i]; |
| 1142 | if (val.tag() != .unreachable_value) { | 1142 | if (val.ip_index != .unreachable_value) { |
| 1143 | try writer.writeAll("comptime "); | 1143 | try writer.writeAll("comptime "); |
| 1144 | } | 1144 | } |
| 1145 | try field_ty.dump("", .{}, writer); | 1145 | try field_ty.dump("", .{}, writer); |
| 1146 | if (val.tag() != .unreachable_value) { | 1146 | if (val.ip_index != .unreachable_value) { |
| 1147 | try writer.print(" = {}", .{val.fmtDebug()}); | 1147 | try writer.print(" = {}", .{val.fmtDebug()}); |
| 1148 | } | 1148 | } |
| 1149 | } | 1149 | } |
| ... | @@ -1156,13 +1156,13 @@ pub const Type = struct { | ... | @@ -1156,13 +1156,13 @@ pub const Type = struct { |
| 1156 | for (anon_struct.types, 0..) |field_ty, i| { | 1156 | for (anon_struct.types, 0..) |field_ty, i| { |
| 1157 | if (i != 0) try writer.writeAll(", "); | 1157 | if (i != 0) try writer.writeAll(", "); |
| 1158 | const val = anon_struct.values[i]; | 1158 | const val = anon_struct.values[i]; |
| 1159 | if (val.tag() != .unreachable_value) { | 1159 | if (val.ip_index != .unreachable_value) { |
| 1160 | try writer.writeAll("comptime "); | 1160 | try writer.writeAll("comptime "); |
| 1161 | } | 1161 | } |
| 1162 | try writer.writeAll(anon_struct.names[i]); | 1162 | try writer.writeAll(anon_struct.names[i]); |
| 1163 | try writer.writeAll(": "); | 1163 | try writer.writeAll(": "); |
| 1164 | try field_ty.dump("", .{}, writer); | 1164 | try field_ty.dump("", .{}, writer); |
| 1165 | if (val.tag() != .unreachable_value) { | 1165 | if (val.ip_index != .unreachable_value) { |
| 1166 | try writer.print(" = {}", .{val.fmtDebug()}); | 1166 | try writer.print(" = {}", .{val.fmtDebug()}); |
| 1167 | } | 1167 | } |
| 1168 | } | 1168 | } |
| ... | @@ -1408,11 +1408,11 @@ pub const Type = struct { | ... | @@ -1408,11 +1408,11 @@ pub const Type = struct { |
| 1408 | for (tuple.types, 0..) |field_ty, i| { | 1408 | for (tuple.types, 0..) |field_ty, i| { |
| 1409 | if (i != 0) try writer.writeAll(", "); | 1409 | if (i != 0) try writer.writeAll(", "); |
| 1410 | const val = tuple.values[i]; | 1410 | const val = tuple.values[i]; |
| 1411 | if (val.tag() != .unreachable_value) { | 1411 | if (val.ip_index != .unreachable_value) { |
| 1412 | try writer.writeAll("comptime "); | 1412 | try writer.writeAll("comptime "); |
| 1413 | } | 1413 | } |
| 1414 | try print(field_ty, writer, mod); | 1414 | try print(field_ty, writer, mod); |
| 1415 | if (val.tag() != .unreachable_value) { | 1415 | if (val.ip_index != .unreachable_value) { |
| 1416 | try writer.print(" = {}", .{val.fmtValue(field_ty, mod)}); | 1416 | try writer.print(" = {}", .{val.fmtValue(field_ty, mod)}); |
| 1417 | } | 1417 | } |
| 1418 | } | 1418 | } |
| ... | @@ -1425,7 +1425,7 @@ pub const Type = struct { | ... | @@ -1425,7 +1425,7 @@ pub const Type = struct { |
| 1425 | for (anon_struct.types, 0..) |field_ty, i| { | 1425 | for (anon_struct.types, 0..) |field_ty, i| { |
| 1426 | if (i != 0) try writer.writeAll(", "); | 1426 | if (i != 0) try writer.writeAll(", "); |
| 1427 | const val = anon_struct.values[i]; | 1427 | const val = anon_struct.values[i]; |
| 1428 | if (val.tag() != .unreachable_value) { | 1428 | if (val.ip_index != .unreachable_value) { |
| 1429 | try writer.writeAll("comptime "); | 1429 | try writer.writeAll("comptime "); |
| 1430 | } | 1430 | } |
| 1431 | try writer.writeAll(anon_struct.names[i]); | 1431 | try writer.writeAll(anon_struct.names[i]); |
| ... | @@ -1433,7 +1433,7 @@ pub const Type = struct { | ... | @@ -1433,7 +1433,7 @@ pub const Type = struct { |
| 1433 | 1433 | ||
| 1434 | try print(field_ty, writer, mod); | 1434 | try print(field_ty, writer, mod); |
| 1435 | 1435 | ||
| 1436 | if (val.tag() != .unreachable_value) { | 1436 | if (val.ip_index != .unreachable_value) { |
| 1437 | try writer.print(" = {}", .{val.fmtValue(field_ty, mod)}); | 1437 | try writer.print(" = {}", .{val.fmtValue(field_ty, mod)}); |
| 1438 | } | 1438 | } |
| 1439 | } | 1439 | } |
| ... | @@ -1770,7 +1770,7 @@ pub const Type = struct { | ... | @@ -1770,7 +1770,7 @@ pub const Type = struct { |
| 1770 | const tuple = ty.tupleFields(); | 1770 | const tuple = ty.tupleFields(); |
| 1771 | for (tuple.types, 0..) |field_ty, i| { | 1771 | for (tuple.types, 0..) |field_ty, i| { |
| 1772 | const val = tuple.values[i]; | 1772 | const val = tuple.values[i]; |
| 1773 | if (val.tag() != .unreachable_value) continue; // comptime field | 1773 | if (val.ip_index != .unreachable_value) continue; // comptime field |
| 1774 | if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true; | 1774 | if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true; |
| 1775 | } | 1775 | } |
| 1776 | return false; | 1776 | return false; |
| ... | @@ -2283,7 +2283,7 @@ pub const Type = struct { | ... | @@ -2283,7 +2283,7 @@ pub const Type = struct { |
| 2283 | var big_align: u32 = 0; | 2283 | var big_align: u32 = 0; |
| 2284 | for (tuple.types, 0..) |field_ty, i| { | 2284 | for (tuple.types, 0..) |field_ty, i| { |
| 2285 | const val = tuple.values[i]; | 2285 | const val = tuple.values[i]; |
| 2286 | if (val.tag() != .unreachable_value) continue; // comptime field | 2286 | if (val.ip_index != .unreachable_value) continue; // comptime field |
| 2287 | if (!(field_ty.hasRuntimeBits(mod))) continue; | 2287 | if (!(field_ty.hasRuntimeBits(mod))) continue; |
| 2288 | 2288 | ||
| 2289 | switch (try field_ty.abiAlignmentAdvanced(mod, strat)) { | 2289 | switch (try field_ty.abiAlignmentAdvanced(mod, strat)) { |
| ... | @@ -3845,7 +3845,7 @@ pub const Type = struct { | ... | @@ -3845,7 +3845,7 @@ pub const Type = struct { |
| 3845 | => return null, | 3845 | => return null, |
| 3846 | 3846 | ||
| 3847 | .void => return Value.void, | 3847 | .void => return Value.void, |
| 3848 | .noreturn => return Value.initTag(.unreachable_value), | 3848 | .noreturn => return Value.@"unreachable", |
| 3849 | .null => return Value.null, | 3849 | .null => return Value.null, |
| 3850 | .undefined => return Value.undef, | 3850 | .undefined => return Value.undef, |
| 3851 | 3851 | ||
| ... | @@ -3896,7 +3896,7 @@ pub const Type = struct { | ... | @@ -3896,7 +3896,7 @@ pub const Type = struct { |
| 3896 | .tuple, .anon_struct => { | 3896 | .tuple, .anon_struct => { |
| 3897 | const tuple = ty.tupleFields(); | 3897 | const tuple = ty.tupleFields(); |
| 3898 | for (tuple.values, 0..) |val, i| { | 3898 | for (tuple.values, 0..) |val, i| { |
| 3899 | const is_comptime = val.tag() != .unreachable_value; | 3899 | const is_comptime = val.ip_index != .unreachable_value; |
| 3900 | if (is_comptime) continue; | 3900 | if (is_comptime) continue; |
| 3901 | if (tuple.types[i].onePossibleValue(mod) != null) continue; | 3901 | if (tuple.types[i].onePossibleValue(mod) != null) continue; |
| 3902 | return null; | 3902 | return null; |
| ... | @@ -3919,7 +3919,7 @@ pub const Type = struct { | ... | @@ -3919,7 +3919,7 @@ pub const Type = struct { |
| 3919 | return null; | 3919 | return null; |
| 3920 | } | 3920 | } |
| 3921 | switch (enum_full.fields.count()) { | 3921 | switch (enum_full.fields.count()) { |
| 3922 | 0 => return Value.initTag(.unreachable_value), | 3922 | 0 => return Value.@"unreachable", |
| 3923 | 1 => if (enum_full.values.count() == 0) { | 3923 | 1 => if (enum_full.values.count() == 0) { |
| 3924 | return Value.zero; // auto-numbered | 3924 | return Value.zero; // auto-numbered |
| 3925 | } else { | 3925 | } else { |
| ... | @@ -3931,7 +3931,7 @@ pub const Type = struct { | ... | @@ -3931,7 +3931,7 @@ pub const Type = struct { |
| 3931 | .enum_simple => { | 3931 | .enum_simple => { |
| 3932 | const enum_simple = ty.castTag(.enum_simple).?.data; | 3932 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| 3933 | switch (enum_simple.fields.count()) { | 3933 | switch (enum_simple.fields.count()) { |
| 3934 | 0 => return Value.initTag(.unreachable_value), | 3934 | 0 => return Value.@"unreachable", |
| 3935 | 1 => return Value.zero, | 3935 | 1 => return Value.zero, |
| 3936 | else => return null, | 3936 | else => return null, |
| 3937 | } | 3937 | } |
| ... | @@ -3947,7 +3947,7 @@ pub const Type = struct { | ... | @@ -3947,7 +3947,7 @@ pub const Type = struct { |
| 3947 | .@"union", .union_safety_tagged, .union_tagged => { | 3947 | .@"union", .union_safety_tagged, .union_tagged => { |
| 3948 | const union_obj = ty.cast(Payload.Union).?.data; | 3948 | const union_obj = ty.cast(Payload.Union).?.data; |
| 3949 | const tag_val = union_obj.tag_ty.onePossibleValue(mod) orelse return null; | 3949 | const tag_val = union_obj.tag_ty.onePossibleValue(mod) orelse return null; |
| 3950 | if (union_obj.fields.count() == 0) return Value.initTag(.unreachable_value); | 3950 | if (union_obj.fields.count() == 0) return Value.@"unreachable"; |
| 3951 | const only_field = union_obj.fields.values()[0]; | 3951 | const only_field = union_obj.fields.values()[0]; |
| 3952 | const val_val = only_field.ty.onePossibleValue(mod) orelse return null; | 3952 | const val_val = only_field.ty.onePossibleValue(mod) orelse return null; |
| 3953 | _ = tag_val; | 3953 | _ = tag_val; |
| ... | @@ -4075,7 +4075,7 @@ pub const Type = struct { | ... | @@ -4075,7 +4075,7 @@ pub const Type = struct { |
| 4075 | .tuple, .anon_struct => { | 4075 | .tuple, .anon_struct => { |
| 4076 | const tuple = ty.tupleFields(); | 4076 | const tuple = ty.tupleFields(); |
| 4077 | for (tuple.types, 0..) |field_ty, i| { | 4077 | for (tuple.types, 0..) |field_ty, i| { |
| 4078 | const have_comptime_val = tuple.values[i].tag() != .unreachable_value; | 4078 | const have_comptime_val = tuple.values[i].ip_index != .unreachable_value; |
| 4079 | if (!have_comptime_val and field_ty.comptimeOnly(mod)) return true; | 4079 | if (!have_comptime_val and field_ty.comptimeOnly(mod)) return true; |
| 4080 | } | 4080 | } |
| 4081 | return false; | 4081 | return false; |
| ... | @@ -4514,7 +4514,7 @@ pub const Type = struct { | ... | @@ -4514,7 +4514,7 @@ pub const Type = struct { |
| 4514 | .tuple => { | 4514 | .tuple => { |
| 4515 | const tuple = ty.castTag(.tuple).?.data; | 4515 | const tuple = ty.castTag(.tuple).?.data; |
| 4516 | const val = tuple.values[index]; | 4516 | const val = tuple.values[index]; |
| 4517 | if (val.tag() == .unreachable_value) { | 4517 | if (val.ip_index == .unreachable_value) { |
| 4518 | return tuple.types[index].onePossibleValue(mod); | 4518 | return tuple.types[index].onePossibleValue(mod); |
| 4519 | } else { | 4519 | } else { |
| 4520 | return val; | 4520 | return val; |
| ... | @@ -4523,7 +4523,7 @@ pub const Type = struct { | ... | @@ -4523,7 +4523,7 @@ pub const Type = struct { |
| 4523 | .anon_struct => { | 4523 | .anon_struct => { |
| 4524 | const anon_struct = ty.castTag(.anon_struct).?.data; | 4524 | const anon_struct = ty.castTag(.anon_struct).?.data; |
| 4525 | const val = anon_struct.values[index]; | 4525 | const val = anon_struct.values[index]; |
| 4526 | if (val.tag() == .unreachable_value) { | 4526 | if (val.ip_index == .unreachable_value) { |
| 4527 | return anon_struct.types[index].onePossibleValue(mod); | 4527 | return anon_struct.types[index].onePossibleValue(mod); |
| 4528 | } else { | 4528 | } else { |
| 4529 | return val; | 4529 | return val; |
| ... | @@ -4544,12 +4544,12 @@ pub const Type = struct { | ... | @@ -4544,12 +4544,12 @@ pub const Type = struct { |
| 4544 | .tuple => { | 4544 | .tuple => { |
| 4545 | const tuple = ty.castTag(.tuple).?.data; | 4545 | const tuple = ty.castTag(.tuple).?.data; |
| 4546 | const val = tuple.values[index]; | 4546 | const val = tuple.values[index]; |
| 4547 | return val.tag() != .unreachable_value; | 4547 | return val.ip_index != .unreachable_value; |
| 4548 | }, | 4548 | }, |
| 4549 | .anon_struct => { | 4549 | .anon_struct => { |
| 4550 | const anon_struct = ty.castTag(.anon_struct).?.data; | 4550 | const anon_struct = ty.castTag(.anon_struct).?.data; |
| 4551 | const val = anon_struct.values[index]; | 4551 | const val = anon_struct.values[index]; |
| 4552 | return val.tag() != .unreachable_value; | 4552 | return val.ip_index != .unreachable_value; |
| 4553 | }, | 4553 | }, |
| 4554 | else => unreachable, | 4554 | else => unreachable, |
| 4555 | } | 4555 | } |
| ... | @@ -4647,7 +4647,7 @@ pub const Type = struct { | ... | @@ -4647,7 +4647,7 @@ pub const Type = struct { |
| 4647 | 4647 | ||
| 4648 | for (tuple.types, 0..) |field_ty, i| { | 4648 | for (tuple.types, 0..) |field_ty, i| { |
| 4649 | const field_val = tuple.values[i]; | 4649 | const field_val = tuple.values[i]; |
| 4650 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits(mod)) { | 4650 | if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) { |
| 4651 | // comptime field | 4651 | // comptime field |
| 4652 | if (i == index) return offset; | 4652 | if (i == index) return offset; |
| 4653 | continue; | 4653 | continue; |
src/value.zig+254-240| ... | @@ -33,13 +33,10 @@ pub const Value = struct { | ... | @@ -33,13 +33,10 @@ pub const Value = struct { |
| 33 | // Keep in sync with tools/stage2_pretty_printers_common.py | 33 | // Keep in sync with tools/stage2_pretty_printers_common.py |
| 34 | pub const Tag = enum(usize) { | 34 | pub const Tag = enum(usize) { |
| 35 | // The first section of this enum are tags that require no payload. | 35 | // The first section of this enum are tags that require no payload. |
| 36 | undef, | ||
| 37 | zero, | 36 | zero, |
| 38 | one, | 37 | one, |
| 39 | unreachable_value, | ||
| 40 | /// The only possible value for a particular type, which is stored externally. | 38 | /// The only possible value for a particular type, which is stored externally. |
| 41 | the_only_possible_value, | 39 | the_only_possible_value, |
| 42 | null_value, | ||
| 43 | 40 | ||
| 44 | empty_struct_value, | 41 | empty_struct_value, |
| 45 | empty_array, // See last_no_payload_tag below. | 42 | empty_array, // See last_no_payload_tag below. |
| ... | @@ -132,14 +129,11 @@ pub const Value = struct { | ... | @@ -132,14 +129,11 @@ pub const Value = struct { |
| 132 | 129 | ||
| 133 | pub fn Type(comptime t: Tag) type { | 130 | pub fn Type(comptime t: Tag) type { |
| 134 | return switch (t) { | 131 | return switch (t) { |
| 135 | .undef, | ||
| 136 | .zero, | 132 | .zero, |
| 137 | .one, | 133 | .one, |
| 138 | .unreachable_value, | ||
| 139 | .the_only_possible_value, | 134 | .the_only_possible_value, |
| 140 | .empty_struct_value, | 135 | .empty_struct_value, |
| 141 | .empty_array, | 136 | .empty_array, |
| 142 | .null_value, | ||
| 143 | => @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"), | 137 | => @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"), |
| 144 | 138 | ||
| 145 | .int_big_positive, | 139 | .int_big_positive, |
| ... | @@ -287,13 +281,10 @@ pub const Value = struct { | ... | @@ -287,13 +281,10 @@ pub const Value = struct { |
| 287 | .legacy = .{ .tag_if_small_enough = self.legacy.tag_if_small_enough }, | 281 | .legacy = .{ .tag_if_small_enough = self.legacy.tag_if_small_enough }, |
| 288 | }; | 282 | }; |
| 289 | } else switch (self.legacy.ptr_otherwise.tag) { | 283 | } else switch (self.legacy.ptr_otherwise.tag) { |
| 290 | .undef, | ||
| 291 | .zero, | 284 | .zero, |
| 292 | .one, | 285 | .one, |
| 293 | .unreachable_value, | ||
| 294 | .the_only_possible_value, | 286 | .the_only_possible_value, |
| 295 | .empty_array, | 287 | .empty_array, |
| 296 | .null_value, | ||
| 297 | .empty_struct_value, | 288 | .empty_struct_value, |
| 298 | => unreachable, | 289 | => unreachable, |
| 299 | 290 | ||
| ... | @@ -522,7 +513,7 @@ pub const Value = struct { | ... | @@ -522,7 +513,7 @@ pub const Value = struct { |
| 522 | ) !void { | 513 | ) !void { |
| 523 | comptime assert(fmt.len == 0); | 514 | comptime assert(fmt.len == 0); |
| 524 | if (start_val.ip_index != .none) { | 515 | if (start_val.ip_index != .none) { |
| 525 | try out_stream.print("(interned {d})", .{@enumToInt(start_val.ip_index)}); | 516 | try out_stream.print("(interned: {})", .{start_val.ip_index}); |
| 526 | return; | 517 | return; |
| 527 | } | 518 | } |
| 528 | var val = start_val; | 519 | var val = start_val; |
| ... | @@ -534,11 +525,8 @@ pub const Value = struct { | ... | @@ -534,11 +525,8 @@ pub const Value = struct { |
| 534 | .@"union" => { | 525 | .@"union" => { |
| 535 | return out_stream.writeAll("(union value)"); | 526 | return out_stream.writeAll("(union value)"); |
| 536 | }, | 527 | }, |
| 537 | .null_value => return out_stream.writeAll("null"), | ||
| 538 | .undef => return out_stream.writeAll("undefined"), | ||
| 539 | .zero => return out_stream.writeAll("0"), | 528 | .zero => return out_stream.writeAll("0"), |
| 540 | .one => return out_stream.writeAll("1"), | 529 | .one => return out_stream.writeAll("1"), |
| 541 | .unreachable_value => return out_stream.writeAll("unreachable"), | ||
| 542 | .the_only_possible_value => return out_stream.writeAll("(the only possible value)"), | 530 | .the_only_possible_value => return out_stream.writeAll("(the only possible value)"), |
| 543 | .ty => return val.castTag(.ty).?.data.dump("", options, out_stream), | 531 | .ty => return val.castTag(.ty).?.data.dump("", options, out_stream), |
| 544 | .lazy_align => { | 532 | .lazy_align => { |
| ... | @@ -811,8 +799,9 @@ pub const Value = struct { | ... | @@ -811,8 +799,9 @@ pub const Value = struct { |
| 811 | switch (val.ip_index) { | 799 | switch (val.ip_index) { |
| 812 | .bool_false => return BigIntMutable.init(&space.limbs, 0).toConst(), | 800 | .bool_false => return BigIntMutable.init(&space.limbs, 0).toConst(), |
| 813 | .bool_true => return BigIntMutable.init(&space.limbs, 1).toConst(), | 801 | .bool_true => return BigIntMutable.init(&space.limbs, 1).toConst(), |
| 802 | .undef => unreachable, | ||
| 803 | .null_value => return BigIntMutable.init(&space.limbs, 0).toConst(), | ||
| 814 | .none => switch (val.tag()) { | 804 | .none => switch (val.tag()) { |
| 815 | .null_value, | ||
| 816 | .zero, | 805 | .zero, |
| 817 | .the_only_possible_value, // i0, u0 | 806 | .the_only_possible_value, // i0, u0 |
| 818 | => return BigIntMutable.init(&space.limbs, 0).toConst(), | 807 | => return BigIntMutable.init(&space.limbs, 0).toConst(), |
| ... | @@ -832,8 +821,6 @@ pub const Value = struct { | ... | @@ -832,8 +821,6 @@ pub const Value = struct { |
| 832 | .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt(), | 821 | .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt(), |
| 833 | .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt(), | 822 | .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt(), |
| 834 | 823 | ||
| 835 | .undef => unreachable, | ||
| 836 | |||
| 837 | .lazy_align => { | 824 | .lazy_align => { |
| 838 | const ty = val.castTag(.lazy_align).?.data; | 825 | const ty = val.castTag(.lazy_align).?.data; |
| 839 | if (opt_sema) |sema| { | 826 | if (opt_sema) |sema| { |
| ... | @@ -880,6 +867,7 @@ pub const Value = struct { | ... | @@ -880,6 +867,7 @@ pub const Value = struct { |
| 880 | switch (val.ip_index) { | 867 | switch (val.ip_index) { |
| 881 | .bool_false => return 0, | 868 | .bool_false => return 0, |
| 882 | .bool_true => return 1, | 869 | .bool_true => return 1, |
| 870 | .undef => unreachable, | ||
| 883 | .none => switch (val.tag()) { | 871 | .none => switch (val.tag()) { |
| 884 | .zero, | 872 | .zero, |
| 885 | .the_only_possible_value, // i0, u0 | 873 | .the_only_possible_value, // i0, u0 |
| ... | @@ -892,8 +880,6 @@ pub const Value = struct { | ... | @@ -892,8 +880,6 @@ pub const Value = struct { |
| 892 | .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt().to(u64) catch null, | 880 | .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt().to(u64) catch null, |
| 893 | .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt().to(u64) catch null, | 881 | .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt().to(u64) catch null, |
| 894 | 882 | ||
| 895 | .undef => unreachable, | ||
| 896 | |||
| 897 | .lazy_align => { | 883 | .lazy_align => { |
| 898 | const ty = val.castTag(.lazy_align).?.data; | 884 | const ty = val.castTag(.lazy_align).?.data; |
| 899 | if (opt_sema) |sema| { | 885 | if (opt_sema) |sema| { |
| ... | @@ -913,9 +899,9 @@ pub const Value = struct { | ... | @@ -913,9 +899,9 @@ pub const Value = struct { |
| 913 | 899 | ||
| 914 | else => return null, | 900 | else => return null, |
| 915 | }, | 901 | }, |
| 916 | else => switch (mod.intern_pool.indexToKey(val.ip_index)) { | 902 | else => return switch (mod.intern_pool.indexToKey(val.ip_index)) { |
| 917 | .int => |int| return int.big_int.to(u64) catch null, | 903 | .int => |int| int.big_int.to(u64) catch null, |
| 918 | else => unreachable, | 904 | else => null, |
| 919 | }, | 905 | }, |
| 920 | } | 906 | } |
| 921 | } | 907 | } |
| ... | @@ -930,6 +916,7 @@ pub const Value = struct { | ... | @@ -930,6 +916,7 @@ pub const Value = struct { |
| 930 | switch (val.ip_index) { | 916 | switch (val.ip_index) { |
| 931 | .bool_false => return 0, | 917 | .bool_false => return 0, |
| 932 | .bool_true => return 1, | 918 | .bool_true => return 1, |
| 919 | .undef => unreachable, | ||
| 933 | .none => switch (val.tag()) { | 920 | .none => switch (val.tag()) { |
| 934 | .zero, | 921 | .zero, |
| 935 | .the_only_possible_value, // i0, u0 | 922 | .the_only_possible_value, // i0, u0 |
| ... | @@ -951,7 +938,6 @@ pub const Value = struct { | ... | @@ -951,7 +938,6 @@ pub const Value = struct { |
| 951 | return @intCast(i64, ty.abiSize(mod)); | 938 | return @intCast(i64, ty.abiSize(mod)); |
| 952 | }, | 939 | }, |
| 953 | 940 | ||
| 954 | .undef => unreachable, | ||
| 955 | else => unreachable, | 941 | else => unreachable, |
| 956 | }, | 942 | }, |
| 957 | else => switch (mod.intern_pool.indexToKey(val.ip_index)) { | 943 | else => switch (mod.intern_pool.indexToKey(val.ip_index)) { |
| ... | @@ -2032,8 +2018,7 @@ pub const Value = struct { | ... | @@ -2032,8 +2018,7 @@ pub const Value = struct { |
| 2032 | const a_tag = a.tag(); | 2018 | const a_tag = a.tag(); |
| 2033 | const b_tag = b.tag(); | 2019 | const b_tag = b.tag(); |
| 2034 | if (a_tag == b_tag) switch (a_tag) { | 2020 | if (a_tag == b_tag) switch (a_tag) { |
| 2035 | .undef => return true, | 2021 | .the_only_possible_value, .empty_struct_value => return true, |
| 2036 | .null_value, .the_only_possible_value, .empty_struct_value => return true, | ||
| 2037 | .enum_literal => { | 2022 | .enum_literal => { |
| 2038 | const a_name = a.castTag(.enum_literal).?.data; | 2023 | const a_name = a.castTag(.enum_literal).?.data; |
| 2039 | const b_name = b.castTag(.enum_literal).?.data; | 2024 | const b_name = b.castTag(.enum_literal).?.data; |
| ... | @@ -2162,9 +2147,7 @@ pub const Value = struct { | ... | @@ -2162,9 +2147,7 @@ pub const Value = struct { |
| 2162 | return eqlAdvanced(a_union.val, active_field_ty, b_union.val, active_field_ty, mod, opt_sema); | 2147 | return eqlAdvanced(a_union.val, active_field_ty, b_union.val, active_field_ty, mod, opt_sema); |
| 2163 | }, | 2148 | }, |
| 2164 | else => {}, | 2149 | else => {}, |
| 2165 | } else if (b_tag == .null_value or b_tag == .@"error") { | 2150 | } else if (b_tag == .@"error") { |
| 2166 | return false; | ||
| 2167 | } else if (a_tag == .undef or b_tag == .undef) { | ||
| 2168 | return false; | 2151 | return false; |
| 2169 | } | 2152 | } |
| 2170 | 2153 | ||
| ... | @@ -2283,7 +2266,7 @@ pub const Value = struct { | ... | @@ -2283,7 +2266,7 @@ pub const Value = struct { |
| 2283 | if (a_nan) return true; | 2266 | if (a_nan) return true; |
| 2284 | return a_float == b_float; | 2267 | return a_float == b_float; |
| 2285 | }, | 2268 | }, |
| 2286 | .Optional => if (a_tag != .null_value and b_tag == .opt_payload) { | 2269 | .Optional => if (b_tag == .opt_payload) { |
| 2287 | var sub_pl: Payload.SubValue = .{ | 2270 | var sub_pl: Payload.SubValue = .{ |
| 2288 | .base = .{ .tag = b.tag() }, | 2271 | .base = .{ .tag = b.tag() }, |
| 2289 | .data = a, | 2272 | .data = a, |
| ... | @@ -2301,7 +2284,7 @@ pub const Value = struct { | ... | @@ -2301,7 +2284,7 @@ pub const Value = struct { |
| 2301 | }, | 2284 | }, |
| 2302 | else => {}, | 2285 | else => {}, |
| 2303 | } | 2286 | } |
| 2304 | if (a_tag == .null_value or a_tag == .@"error") return false; | 2287 | if (a_tag == .@"error") return false; |
| 2305 | return (try orderAdvanced(a, b, mod, opt_sema)).compare(.eq); | 2288 | return (try orderAdvanced(a, b, mod, opt_sema)).compare(.eq); |
| 2306 | } | 2289 | } |
| 2307 | 2290 | ||
| ... | @@ -2642,7 +2625,6 @@ pub const Value = struct { | ... | @@ -2642,7 +2625,6 @@ pub const Value = struct { |
| 2642 | 2625 | ||
| 2643 | .zero, | 2626 | .zero, |
| 2644 | .one, | 2627 | .one, |
| 2645 | .null_value, | ||
| 2646 | .int_u64, | 2628 | .int_u64, |
| 2647 | .int_i64, | 2629 | .int_i64, |
| 2648 | .int_big_positive, | 2630 | .int_big_positive, |
| ... | @@ -2717,102 +2699,108 @@ pub const Value = struct { | ... | @@ -2717,102 +2699,108 @@ pub const Value = struct { |
| 2717 | arena: ?Allocator, | 2699 | arena: ?Allocator, |
| 2718 | buffer: *ElemValueBuffer, | 2700 | buffer: *ElemValueBuffer, |
| 2719 | ) error{OutOfMemory}!Value { | 2701 | ) error{OutOfMemory}!Value { |
| 2720 | switch (val.tag()) { | 2702 | switch (val.ip_index) { |
| 2721 | // This is the case of accessing an element of an undef array. | ||
| 2722 | .undef => return Value.undef, | 2703 | .undef => return Value.undef, |
| 2723 | .empty_array => unreachable, // out of bounds array index | 2704 | .none => switch (val.tag()) { |
| 2724 | .empty_struct_value => unreachable, // out of bounds array index | 2705 | // This is the case of accessing an element of an undef array. |
| 2706 | .empty_array => unreachable, // out of bounds array index | ||
| 2707 | .empty_struct_value => unreachable, // out of bounds array index | ||
| 2725 | 2708 | ||
| 2726 | .empty_array_sentinel => { | 2709 | .empty_array_sentinel => { |
| 2727 | assert(index == 0); // The only valid index for an empty array with sentinel. | 2710 | assert(index == 0); // The only valid index for an empty array with sentinel. |
| 2728 | return val.castTag(.empty_array_sentinel).?.data; | 2711 | return val.castTag(.empty_array_sentinel).?.data; |
| 2729 | }, | 2712 | }, |
| 2730 | 2713 | ||
| 2731 | .bytes => { | 2714 | .bytes => { |
| 2732 | const byte = val.castTag(.bytes).?.data[index]; | 2715 | const byte = val.castTag(.bytes).?.data[index]; |
| 2733 | if (arena) |a| { | 2716 | if (arena) |a| { |
| 2734 | return Tag.int_u64.create(a, byte); | 2717 | return Tag.int_u64.create(a, byte); |
| 2735 | } else { | 2718 | } else { |
| 2736 | buffer.* = .{ | 2719 | buffer.* = .{ |
| 2737 | .base = .{ .tag = .int_u64 }, | 2720 | .base = .{ .tag = .int_u64 }, |
| 2738 | .data = byte, | 2721 | .data = byte, |
| 2739 | }; | 2722 | }; |
| 2740 | return initPayload(&buffer.base); | 2723 | return initPayload(&buffer.base); |
| 2741 | } | 2724 | } |
| 2742 | }, | 2725 | }, |
| 2743 | .str_lit => { | 2726 | .str_lit => { |
| 2744 | const str_lit = val.castTag(.str_lit).?.data; | 2727 | const str_lit = val.castTag(.str_lit).?.data; |
| 2745 | const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; | 2728 | const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; |
| 2746 | const byte = bytes[index]; | 2729 | const byte = bytes[index]; |
| 2747 | if (arena) |a| { | 2730 | if (arena) |a| { |
| 2748 | return Tag.int_u64.create(a, byte); | 2731 | return Tag.int_u64.create(a, byte); |
| 2749 | } else { | 2732 | } else { |
| 2750 | buffer.* = .{ | 2733 | buffer.* = .{ |
| 2751 | .base = .{ .tag = .int_u64 }, | 2734 | .base = .{ .tag = .int_u64 }, |
| 2752 | .data = byte, | 2735 | .data = byte, |
| 2753 | }; | 2736 | }; |
| 2754 | return initPayload(&buffer.base); | 2737 | return initPayload(&buffer.base); |
| 2755 | } | 2738 | } |
| 2756 | }, | 2739 | }, |
| 2757 | 2740 | ||
| 2758 | // No matter the index; all the elements are the same! | 2741 | // No matter the index; all the elements are the same! |
| 2759 | .repeated => return val.castTag(.repeated).?.data, | 2742 | .repeated => return val.castTag(.repeated).?.data, |
| 2760 | 2743 | ||
| 2761 | .aggregate => return val.castTag(.aggregate).?.data[index], | 2744 | .aggregate => return val.castTag(.aggregate).?.data[index], |
| 2762 | .slice => return val.castTag(.slice).?.data.ptr.elemValueAdvanced(mod, index, arena, buffer), | 2745 | .slice => return val.castTag(.slice).?.data.ptr.elemValueAdvanced(mod, index, arena, buffer), |
| 2763 | 2746 | ||
| 2764 | .decl_ref => return mod.declPtr(val.castTag(.decl_ref).?.data).val.elemValueAdvanced(mod, index, arena, buffer), | 2747 | .decl_ref => return mod.declPtr(val.castTag(.decl_ref).?.data).val.elemValueAdvanced(mod, index, arena, buffer), |
| 2765 | .decl_ref_mut => return mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val.elemValueAdvanced(mod, index, arena, buffer), | 2748 | .decl_ref_mut => return mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val.elemValueAdvanced(mod, index, arena, buffer), |
| 2766 | .comptime_field_ptr => return val.castTag(.comptime_field_ptr).?.data.field_val.elemValueAdvanced(mod, index, arena, buffer), | 2749 | .comptime_field_ptr => return val.castTag(.comptime_field_ptr).?.data.field_val.elemValueAdvanced(mod, index, arena, buffer), |
| 2767 | .elem_ptr => { | 2750 | .elem_ptr => { |
| 2768 | const data = val.castTag(.elem_ptr).?.data; | 2751 | const data = val.castTag(.elem_ptr).?.data; |
| 2769 | return data.array_ptr.elemValueAdvanced(mod, index + data.index, arena, buffer); | 2752 | return data.array_ptr.elemValueAdvanced(mod, index + data.index, arena, buffer); |
| 2770 | }, | 2753 | }, |
| 2771 | .field_ptr => { | 2754 | .field_ptr => { |
| 2772 | const data = val.castTag(.field_ptr).?.data; | 2755 | const data = val.castTag(.field_ptr).?.data; |
| 2773 | if (data.container_ptr.pointerDecl()) |decl_index| { | 2756 | if (data.container_ptr.pointerDecl()) |decl_index| { |
| 2774 | const container_decl = mod.declPtr(decl_index); | 2757 | const container_decl = mod.declPtr(decl_index); |
| 2775 | const field_type = data.container_ty.structFieldType(data.field_index); | 2758 | const field_type = data.container_ty.structFieldType(data.field_index); |
| 2776 | const field_val = container_decl.val.fieldValue(field_type, mod, data.field_index); | 2759 | const field_val = container_decl.val.fieldValue(field_type, mod, data.field_index); |
| 2777 | return field_val.elemValueAdvanced(mod, index, arena, buffer); | 2760 | return field_val.elemValueAdvanced(mod, index, arena, buffer); |
| 2778 | } else unreachable; | 2761 | } else unreachable; |
| 2779 | }, | 2762 | }, |
| 2780 | 2763 | ||
| 2781 | // The child type of arrays which have only one possible value need | 2764 | // The child type of arrays which have only one possible value need |
| 2782 | // to have only one possible value itself. | 2765 | // to have only one possible value itself. |
| 2783 | .the_only_possible_value => return val, | 2766 | .the_only_possible_value => return val, |
| 2784 | 2767 | ||
| 2785 | .opt_payload_ptr => return val.castTag(.opt_payload_ptr).?.data.container_ptr.elemValueAdvanced(mod, index, arena, buffer), | 2768 | .opt_payload_ptr => return val.castTag(.opt_payload_ptr).?.data.container_ptr.elemValueAdvanced(mod, index, arena, buffer), |
| 2786 | .eu_payload_ptr => return val.castTag(.eu_payload_ptr).?.data.container_ptr.elemValueAdvanced(mod, index, arena, buffer), | 2769 | .eu_payload_ptr => return val.castTag(.eu_payload_ptr).?.data.container_ptr.elemValueAdvanced(mod, index, arena, buffer), |
| 2787 | 2770 | ||
| 2788 | .opt_payload => return val.castTag(.opt_payload).?.data.elemValueAdvanced(mod, index, arena, buffer), | 2771 | .opt_payload => return val.castTag(.opt_payload).?.data.elemValueAdvanced(mod, index, arena, buffer), |
| 2789 | .eu_payload => return val.castTag(.eu_payload).?.data.elemValueAdvanced(mod, index, arena, buffer), | 2772 | .eu_payload => return val.castTag(.eu_payload).?.data.elemValueAdvanced(mod, index, arena, buffer), |
| 2790 | 2773 | ||
| 2774 | else => unreachable, | ||
| 2775 | }, | ||
| 2791 | else => unreachable, | 2776 | else => unreachable, |
| 2792 | } | 2777 | } |
| 2793 | } | 2778 | } |
| 2794 | 2779 | ||
| 2795 | /// Returns true if a Value is backed by a variable | 2780 | /// Returns true if a Value is backed by a variable |
| 2796 | pub fn isVariable(val: Value, mod: *Module) bool { | 2781 | pub fn isVariable(val: Value, mod: *Module) bool { |
| 2797 | return switch (val.tag()) { | 2782 | return switch (val.ip_index) { |
| 2798 | .slice => val.castTag(.slice).?.data.ptr.isVariable(mod), | 2783 | .none => switch (val.tag()) { |
| 2799 | .comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isVariable(mod), | 2784 | .slice => val.castTag(.slice).?.data.ptr.isVariable(mod), |
| 2800 | .elem_ptr => val.castTag(.elem_ptr).?.data.array_ptr.isVariable(mod), | 2785 | .comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isVariable(mod), |
| 2801 | .field_ptr => val.castTag(.field_ptr).?.data.container_ptr.isVariable(mod), | 2786 | .elem_ptr => val.castTag(.elem_ptr).?.data.array_ptr.isVariable(mod), |
| 2802 | .eu_payload_ptr => val.castTag(.eu_payload_ptr).?.data.container_ptr.isVariable(mod), | 2787 | .field_ptr => val.castTag(.field_ptr).?.data.container_ptr.isVariable(mod), |
| 2803 | .opt_payload_ptr => val.castTag(.opt_payload_ptr).?.data.container_ptr.isVariable(mod), | 2788 | .eu_payload_ptr => val.castTag(.eu_payload_ptr).?.data.container_ptr.isVariable(mod), |
| 2804 | .decl_ref => { | 2789 | .opt_payload_ptr => val.castTag(.opt_payload_ptr).?.data.container_ptr.isVariable(mod), |
| 2805 | const decl = mod.declPtr(val.castTag(.decl_ref).?.data); | 2790 | .decl_ref => { |
| 2806 | assert(decl.has_tv); | 2791 | const decl = mod.declPtr(val.castTag(.decl_ref).?.data); |
| 2807 | return decl.val.isVariable(mod); | 2792 | assert(decl.has_tv); |
| 2808 | }, | 2793 | return decl.val.isVariable(mod); |
| 2809 | .decl_ref_mut => { | 2794 | }, |
| 2810 | const decl = mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index); | 2795 | .decl_ref_mut => { |
| 2811 | assert(decl.has_tv); | 2796 | const decl = mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index); |
| 2812 | return decl.val.isVariable(mod); | 2797 | assert(decl.has_tv); |
| 2813 | }, | 2798 | return decl.val.isVariable(mod); |
| 2799 | }, | ||
| 2814 | 2800 | ||
| 2815 | .variable => true, | 2801 | .variable => true, |
| 2802 | else => false, | ||
| 2803 | }, | ||
| 2816 | else => false, | 2804 | else => false, |
| 2817 | }; | 2805 | }; |
| 2818 | } | 2806 | } |
| ... | @@ -2878,39 +2866,46 @@ pub const Value = struct { | ... | @@ -2878,39 +2866,46 @@ pub const Value = struct { |
| 2878 | } | 2866 | } |
| 2879 | 2867 | ||
| 2880 | pub fn fieldValue(val: Value, ty: Type, mod: *const Module, index: usize) Value { | 2868 | pub fn fieldValue(val: Value, ty: Type, mod: *const Module, index: usize) Value { |
| 2881 | switch (val.tag()) { | 2869 | switch (val.ip_index) { |
| 2882 | .aggregate => { | 2870 | .undef => return Value.undef, |
| 2883 | const field_values = val.castTag(.aggregate).?.data; | 2871 | .none => switch (val.tag()) { |
| 2884 | return field_values[index]; | 2872 | .aggregate => { |
| 2885 | }, | 2873 | const field_values = val.castTag(.aggregate).?.data; |
| 2886 | .@"union" => { | 2874 | return field_values[index]; |
| 2887 | const payload = val.castTag(.@"union").?.data; | 2875 | }, |
| 2888 | // TODO assert the tag is correct | 2876 | .@"union" => { |
| 2889 | return payload.val; | 2877 | const payload = val.castTag(.@"union").?.data; |
| 2890 | }, | 2878 | // TODO assert the tag is correct |
| 2879 | return payload.val; | ||
| 2880 | }, | ||
| 2891 | 2881 | ||
| 2892 | .the_only_possible_value => return ty.onePossibleValue(mod).?, | 2882 | .the_only_possible_value => return ty.onePossibleValue(mod).?, |
| 2893 | 2883 | ||
| 2894 | .empty_struct_value => { | 2884 | .empty_struct_value => { |
| 2895 | if (ty.isSimpleTupleOrAnonStruct()) { | 2885 | if (ty.isSimpleTupleOrAnonStruct()) { |
| 2896 | const tuple = ty.tupleFields(); | 2886 | const tuple = ty.tupleFields(); |
| 2897 | return tuple.values[index]; | 2887 | return tuple.values[index]; |
| 2898 | } | 2888 | } |
| 2899 | if (ty.structFieldValueComptime(mod, index)) |some| { | 2889 | if (ty.structFieldValueComptime(mod, index)) |some| { |
| 2900 | return some; | 2890 | return some; |
| 2901 | } | 2891 | } |
| 2902 | unreachable; | 2892 | unreachable; |
| 2903 | }, | 2893 | }, |
| 2904 | .undef => return Value.undef, | ||
| 2905 | 2894 | ||
| 2895 | else => unreachable, | ||
| 2896 | }, | ||
| 2906 | else => unreachable, | 2897 | else => unreachable, |
| 2907 | } | 2898 | } |
| 2908 | } | 2899 | } |
| 2909 | 2900 | ||
| 2910 | pub fn unionTag(val: Value) Value { | 2901 | pub fn unionTag(val: Value) Value { |
| 2911 | switch (val.tag()) { | 2902 | switch (val.ip_index) { |
| 2912 | .undef, .enum_field_index => return val, | 2903 | .undef => return val, |
| 2913 | .@"union" => return val.castTag(.@"union").?.data.tag, | 2904 | .none => switch (val.tag()) { |
| 2905 | .enum_field_index => return val, | ||
| 2906 | .@"union" => return val.castTag(.@"union").?.data.tag, | ||
| 2907 | else => unreachable, | ||
| 2908 | }, | ||
| 2914 | else => unreachable, | 2909 | else => unreachable, |
| 2915 | } | 2910 | } |
| 2916 | } | 2911 | } |
| ... | @@ -2946,15 +2941,15 @@ pub const Value = struct { | ... | @@ -2946,15 +2941,15 @@ pub const Value = struct { |
| 2946 | }); | 2941 | }); |
| 2947 | } | 2942 | } |
| 2948 | 2943 | ||
| 2949 | pub fn isUndef(self: Value) bool { | 2944 | pub fn isUndef(val: Value) bool { |
| 2950 | return self.tag() == .undef; | 2945 | return val.ip_index == .undef; |
| 2951 | } | 2946 | } |
| 2952 | 2947 | ||
| 2953 | /// TODO: check for cases such as array that is not marked undef but all the element | 2948 | /// TODO: check for cases such as array that is not marked undef but all the element |
| 2954 | /// values are marked undef, or struct that is not marked undef but all fields are marked | 2949 | /// values are marked undef, or struct that is not marked undef but all fields are marked |
| 2955 | /// undef, etc. | 2950 | /// undef, etc. |
| 2956 | pub fn isUndefDeep(self: Value) bool { | 2951 | pub fn isUndefDeep(val: Value) bool { |
| 2957 | return self.isUndef(); | 2952 | return val.isUndef(); |
| 2958 | } | 2953 | } |
| 2959 | 2954 | ||
| 2960 | /// Returns true if any value contained in `self` is undefined. | 2955 | /// Returns true if any value contained in `self` is undefined. |
| ... | @@ -2962,27 +2957,29 @@ pub const Value = struct { | ... | @@ -2962,27 +2957,29 @@ pub const Value = struct { |
| 2962 | /// values are marked undef, or struct that is not marked undef but all fields are marked | 2957 | /// values are marked undef, or struct that is not marked undef but all fields are marked |
| 2963 | /// undef, etc. | 2958 | /// undef, etc. |
| 2964 | pub fn anyUndef(self: Value, mod: *Module) bool { | 2959 | pub fn anyUndef(self: Value, mod: *Module) bool { |
| 2965 | switch (self.tag()) { | 2960 | switch (self.ip_index) { |
| 2966 | .slice => { | 2961 | .undef => return true, |
| 2967 | const payload = self.castTag(.slice).?; | 2962 | .none => switch (self.tag()) { |
| 2968 | const len = payload.data.len.toUnsignedInt(mod); | 2963 | .slice => { |
| 2969 | 2964 | const payload = self.castTag(.slice).?; | |
| 2970 | var elem_value_buf: ElemValueBuffer = undefined; | 2965 | const len = payload.data.len.toUnsignedInt(mod); |
| 2971 | var i: usize = 0; | 2966 | |
| 2972 | while (i < len) : (i += 1) { | 2967 | var elem_value_buf: ElemValueBuffer = undefined; |
| 2973 | const elem_val = payload.data.ptr.elemValueBuffer(mod, i, &elem_value_buf); | 2968 | var i: usize = 0; |
| 2974 | if (elem_val.anyUndef(mod)) return true; | 2969 | while (i < len) : (i += 1) { |
| 2975 | } | 2970 | const elem_val = payload.data.ptr.elemValueBuffer(mod, i, &elem_value_buf); |
| 2976 | }, | 2971 | if (elem_val.anyUndef(mod)) return true; |
| 2972 | } | ||
| 2973 | }, | ||
| 2977 | 2974 | ||
| 2978 | .aggregate => { | 2975 | .aggregate => { |
| 2979 | const payload = self.castTag(.aggregate).?; | 2976 | const payload = self.castTag(.aggregate).?; |
| 2980 | for (payload.data) |val| { | 2977 | for (payload.data) |val| { |
| 2981 | if (val.anyUndef(mod)) return true; | 2978 | if (val.anyUndef(mod)) return true; |
| 2982 | } | 2979 | } |
| 2980 | }, | ||
| 2981 | else => {}, | ||
| 2983 | }, | 2982 | }, |
| 2984 | |||
| 2985 | .undef => return true, | ||
| 2986 | else => {}, | 2983 | else => {}, |
| 2987 | } | 2984 | } |
| 2988 | 2985 | ||
| ... | @@ -2992,30 +2989,33 @@ pub const Value = struct { | ... | @@ -2992,30 +2989,33 @@ pub const Value = struct { |
| 2992 | /// Asserts the value is not undefined and not unreachable. | 2989 | /// Asserts the value is not undefined and not unreachable. |
| 2993 | /// Integer value 0 is considered null because of C pointers. | 2990 | /// Integer value 0 is considered null because of C pointers. |
| 2994 | pub fn isNull(self: Value, mod: *const Module) bool { | 2991 | pub fn isNull(self: Value, mod: *const Module) bool { |
| 2995 | return switch (self.tag()) { | 2992 | return switch (self.ip_index) { |
| 2993 | .undef => unreachable, | ||
| 2994 | .unreachable_value => unreachable, | ||
| 2996 | .null_value => true, | 2995 | .null_value => true, |
| 2997 | .opt_payload => false, | 2996 | .none => switch (self.tag()) { |
| 2997 | .opt_payload => false, | ||
| 2998 | 2998 | ||
| 2999 | // If it's not one of those two tags then it must be a C pointer value, | 2999 | // If it's not one of those two tags then it must be a C pointer value, |
| 3000 | // in which case the value 0 is null and other values are non-null. | 3000 | // in which case the value 0 is null and other values are non-null. |
| 3001 | 3001 | ||
| 3002 | .zero, | 3002 | .zero, |
| 3003 | .the_only_possible_value, | 3003 | .the_only_possible_value, |
| 3004 | => true, | 3004 | => true, |
| 3005 | 3005 | ||
| 3006 | .one => false, | 3006 | .one => false, |
| 3007 | 3007 | ||
| 3008 | .int_u64, | 3008 | .int_u64, |
| 3009 | .int_i64, | 3009 | .int_i64, |
| 3010 | .int_big_positive, | 3010 | .int_big_positive, |
| 3011 | .int_big_negative, | 3011 | .int_big_negative, |
| 3012 | => self.orderAgainstZero(mod).compare(.eq), | 3012 | => self.orderAgainstZero(mod).compare(.eq), |
| 3013 | 3013 | ||
| 3014 | .undef => unreachable, | 3014 | .inferred_alloc => unreachable, |
| 3015 | .unreachable_value => unreachable, | 3015 | .inferred_alloc_comptime => unreachable, |
| 3016 | .inferred_alloc => unreachable, | ||
| 3017 | .inferred_alloc_comptime => unreachable, | ||
| 3018 | 3016 | ||
| 3017 | else => false, | ||
| 3018 | }, | ||
| 3019 | else => false, | 3019 | else => false, |
| 3020 | }; | 3020 | }; |
| 3021 | } | 3021 | } |
| ... | @@ -3025,18 +3025,21 @@ pub const Value = struct { | ... | @@ -3025,18 +3025,21 @@ pub const Value = struct { |
| 3025 | /// something is an error or not because it works without having to figure out the | 3025 | /// something is an error or not because it works without having to figure out the |
| 3026 | /// string. | 3026 | /// string. |
| 3027 | pub fn getError(self: Value) ?[]const u8 { | 3027 | pub fn getError(self: Value) ?[]const u8 { |
| 3028 | return switch (self.tag()) { | 3028 | return switch (self.ip_index) { |
| 3029 | .@"error" => self.castTag(.@"error").?.data.name, | ||
| 3030 | .int_u64 => @panic("TODO"), | ||
| 3031 | .int_i64 => @panic("TODO"), | ||
| 3032 | .int_big_positive => @panic("TODO"), | ||
| 3033 | .int_big_negative => @panic("TODO"), | ||
| 3034 | .one => @panic("TODO"), | ||
| 3035 | .undef => unreachable, | 3029 | .undef => unreachable, |
| 3036 | .unreachable_value => unreachable, | 3030 | .unreachable_value => unreachable, |
| 3037 | .inferred_alloc => unreachable, | 3031 | .none => switch (self.tag()) { |
| 3038 | .inferred_alloc_comptime => unreachable, | 3032 | .@"error" => self.castTag(.@"error").?.data.name, |
| 3033 | .int_u64 => @panic("TODO"), | ||
| 3034 | .int_i64 => @panic("TODO"), | ||
| 3035 | .int_big_positive => @panic("TODO"), | ||
| 3036 | .int_big_negative => @panic("TODO"), | ||
| 3037 | .one => @panic("TODO"), | ||
| 3038 | .inferred_alloc => unreachable, | ||
| 3039 | .inferred_alloc_comptime => unreachable, | ||
| 3039 | 3040 | ||
| 3041 | else => null, | ||
| 3042 | }, | ||
| 3040 | else => null, | 3043 | else => null, |
| 3041 | }; | 3044 | }; |
| 3042 | } | 3045 | } |
| ... | @@ -3044,13 +3047,16 @@ pub const Value = struct { | ... | @@ -3044,13 +3047,16 @@ pub const Value = struct { |
| 3044 | /// Assumes the type is an error union. Returns true if and only if the value is | 3047 | /// Assumes the type is an error union. Returns true if and only if the value is |
| 3045 | /// the error union payload, not an error. | 3048 | /// the error union payload, not an error. |
| 3046 | pub fn errorUnionIsPayload(val: Value) bool { | 3049 | pub fn errorUnionIsPayload(val: Value) bool { |
| 3047 | return switch (val.tag()) { | 3050 | return switch (val.ip_index) { |
| 3048 | .eu_payload => true, | ||
| 3049 | else => false, | ||
| 3050 | |||
| 3051 | .undef => unreachable, | 3051 | .undef => unreachable, |
| 3052 | .inferred_alloc => unreachable, | 3052 | .none => switch (val.tag()) { |
| 3053 | .inferred_alloc_comptime => unreachable, | 3053 | .eu_payload => true, |
| 3054 | else => false, | ||
| 3055 | |||
| 3056 | .inferred_alloc => unreachable, | ||
| 3057 | .inferred_alloc_comptime => unreachable, | ||
| 3058 | }, | ||
| 3059 | else => false, | ||
| 3054 | }; | 3060 | }; |
| 3055 | } | 3061 | } |
| 3056 | 3062 | ||
| ... | @@ -3065,17 +3071,20 @@ pub const Value = struct { | ... | @@ -3065,17 +3071,20 @@ pub const Value = struct { |
| 3065 | 3071 | ||
| 3066 | /// Valid for all types. Asserts the value is not undefined. | 3072 | /// Valid for all types. Asserts the value is not undefined. |
| 3067 | pub fn isFloat(self: Value) bool { | 3073 | pub fn isFloat(self: Value) bool { |
| 3068 | return switch (self.tag()) { | 3074 | return switch (self.ip_index) { |
| 3069 | .undef => unreachable, | 3075 | .undef => unreachable, |
| 3070 | .inferred_alloc => unreachable, | 3076 | .none => switch (self.tag()) { |
| 3071 | .inferred_alloc_comptime => unreachable, | 3077 | .inferred_alloc => unreachable, |
| 3078 | .inferred_alloc_comptime => unreachable, | ||
| 3072 | 3079 | ||
| 3073 | .float_16, | 3080 | .float_16, |
| 3074 | .float_32, | 3081 | .float_32, |
| 3075 | .float_64, | 3082 | .float_64, |
| 3076 | .float_80, | 3083 | .float_80, |
| 3077 | .float_128, | 3084 | .float_128, |
| 3078 | => true, | 3085 | => true, |
| 3086 | else => false, | ||
| 3087 | }, | ||
| 3079 | else => false, | 3088 | else => false, |
| 3080 | }; | 3089 | }; |
| 3081 | } | 3090 | } |
| ... | @@ -3102,40 +3111,44 @@ pub const Value = struct { | ... | @@ -3102,40 +3111,44 @@ pub const Value = struct { |
| 3102 | 3111 | ||
| 3103 | pub fn intToFloatScalar(val: Value, arena: Allocator, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value { | 3112 | pub fn intToFloatScalar(val: Value, arena: Allocator, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value { |
| 3104 | const target = mod.getTarget(); | 3113 | const target = mod.getTarget(); |
| 3105 | switch (val.tag()) { | 3114 | switch (val.ip_index) { |
| 3106 | .undef, .zero, .one => return val, | 3115 | .undef => return val, |
| 3107 | .the_only_possible_value => return Value.initTag(.zero), // for i0, u0 | 3116 | .none => switch (val.tag()) { |
| 3108 | .int_u64 => { | 3117 | .zero, .one => return val, |
| 3109 | return intToFloatInner(val.castTag(.int_u64).?.data, arena, float_ty, target); | 3118 | .the_only_possible_value => return Value.initTag(.zero), // for i0, u0 |
| 3110 | }, | 3119 | .int_u64 => { |
| 3111 | .int_i64 => { | 3120 | return intToFloatInner(val.castTag(.int_u64).?.data, arena, float_ty, target); |
| 3112 | return intToFloatInner(val.castTag(.int_i64).?.data, arena, float_ty, target); | 3121 | }, |
| 3113 | }, | 3122 | .int_i64 => { |
| 3114 | .int_big_positive => { | 3123 | return intToFloatInner(val.castTag(.int_i64).?.data, arena, float_ty, target); |
| 3115 | const limbs = val.castTag(.int_big_positive).?.data; | 3124 | }, |
| 3116 | const float = bigIntToFloat(limbs, true); | 3125 | .int_big_positive => { |
| 3117 | return floatToValue(float, arena, float_ty, target); | 3126 | const limbs = val.castTag(.int_big_positive).?.data; |
| 3118 | }, | 3127 | const float = bigIntToFloat(limbs, true); |
| 3119 | .int_big_negative => { | 3128 | return floatToValue(float, arena, float_ty, target); |
| 3120 | const limbs = val.castTag(.int_big_negative).?.data; | 3129 | }, |
| 3121 | const float = bigIntToFloat(limbs, false); | 3130 | .int_big_negative => { |
| 3122 | return floatToValue(float, arena, float_ty, target); | 3131 | const limbs = val.castTag(.int_big_negative).?.data; |
| 3123 | }, | 3132 | const float = bigIntToFloat(limbs, false); |
| 3124 | .lazy_align => { | 3133 | return floatToValue(float, arena, float_ty, target); |
| 3125 | const ty = val.castTag(.lazy_align).?.data; | 3134 | }, |
| 3126 | if (opt_sema) |sema| { | 3135 | .lazy_align => { |
| 3127 | return intToFloatInner((try ty.abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar, arena, float_ty, target); | 3136 | const ty = val.castTag(.lazy_align).?.data; |
| 3128 | } else { | 3137 | if (opt_sema) |sema| { |
| 3129 | return intToFloatInner(ty.abiAlignment(mod), arena, float_ty, target); | 3138 | return intToFloatInner((try ty.abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar, arena, float_ty, target); |
| 3130 | } | 3139 | } else { |
| 3131 | }, | 3140 | return intToFloatInner(ty.abiAlignment(mod), arena, float_ty, target); |
| 3132 | .lazy_size => { | 3141 | } |
| 3133 | const ty = val.castTag(.lazy_size).?.data; | 3142 | }, |
| 3134 | if (opt_sema) |sema| { | 3143 | .lazy_size => { |
| 3135 | return intToFloatInner((try ty.abiSizeAdvanced(mod, .{ .sema = sema })).scalar, arena, float_ty, target); | 3144 | const ty = val.castTag(.lazy_size).?.data; |
| 3136 | } else { | 3145 | if (opt_sema) |sema| { |
| 3137 | return intToFloatInner(ty.abiSize(mod), arena, float_ty, target); | 3146 | return intToFloatInner((try ty.abiSizeAdvanced(mod, .{ .sema = sema })).scalar, arena, float_ty, target); |
| 3138 | } | 3147 | } else { |
| 3148 | return intToFloatInner(ty.abiSize(mod), arena, float_ty, target); | ||
| 3149 | } | ||
| 3150 | }, | ||
| 3151 | else => unreachable, | ||
| 3139 | }, | 3152 | }, |
| 3140 | else => unreachable, | 3153 | else => unreachable, |
| 3141 | } | 3154 | } |
| ... | @@ -3381,7 +3394,7 @@ pub const Value = struct { | ... | @@ -3381,7 +3394,7 @@ pub const Value = struct { |
| 3381 | arena: Allocator, | 3394 | arena: Allocator, |
| 3382 | mod: *Module, | 3395 | mod: *Module, |
| 3383 | ) !Value { | 3396 | ) !Value { |
| 3384 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); | 3397 | if (lhs.isUndef() or rhs.isUndef()) return Value.undef; |
| 3385 | 3398 | ||
| 3386 | if (ty.zigTypeTag(mod) == .ComptimeInt) { | 3399 | if (ty.zigTypeTag(mod) == .ComptimeInt) { |
| 3387 | return intMul(lhs, rhs, ty, arena, mod); | 3400 | return intMul(lhs, rhs, ty, arena, mod); |
| ... | @@ -3492,7 +3505,7 @@ pub const Value = struct { | ... | @@ -3492,7 +3505,7 @@ pub const Value = struct { |
| 3492 | 3505 | ||
| 3493 | /// operands must be integers; handles undefined. | 3506 | /// operands must be integers; handles undefined. |
| 3494 | pub fn bitwiseNotScalar(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value { | 3507 | pub fn bitwiseNotScalar(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value { |
| 3495 | if (val.isUndef()) return Value.initTag(.undef); | 3508 | if (val.isUndef()) return Value.undef; |
| 3496 | 3509 | ||
| 3497 | const info = ty.intInfo(mod); | 3510 | const info = ty.intInfo(mod); |
| 3498 | 3511 | ||
| ... | @@ -3532,7 +3545,7 @@ pub const Value = struct { | ... | @@ -3532,7 +3545,7 @@ pub const Value = struct { |
| 3532 | 3545 | ||
| 3533 | /// operands must be integers; handles undefined. | 3546 | /// operands must be integers; handles undefined. |
| 3534 | pub fn bitwiseAndScalar(lhs: Value, rhs: Value, arena: Allocator, mod: *Module) !Value { | 3547 | pub fn bitwiseAndScalar(lhs: Value, rhs: Value, arena: Allocator, mod: *Module) !Value { |
| 3535 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); | 3548 | if (lhs.isUndef() or rhs.isUndef()) return Value.undef; |
| 3536 | 3549 | ||
| 3537 | // TODO is this a performance issue? maybe we should try the operation without | 3550 | // TODO is this a performance issue? maybe we should try the operation without |
| 3538 | // resorting to BigInt first. | 3551 | // resorting to BigInt first. |
| ... | @@ -3568,7 +3581,7 @@ pub const Value = struct { | ... | @@ -3568,7 +3581,7 @@ pub const Value = struct { |
| 3568 | 3581 | ||
| 3569 | /// operands must be integers; handles undefined. | 3582 | /// operands must be integers; handles undefined. |
| 3570 | pub fn bitwiseNandScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value { | 3583 | pub fn bitwiseNandScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value { |
| 3571 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); | 3584 | if (lhs.isUndef() or rhs.isUndef()) return Value.undef; |
| 3572 | 3585 | ||
| 3573 | const anded = try bitwiseAnd(lhs, rhs, ty, arena, mod); | 3586 | const anded = try bitwiseAnd(lhs, rhs, ty, arena, mod); |
| 3574 | 3587 | ||
| ... | @@ -3598,7 +3611,7 @@ pub const Value = struct { | ... | @@ -3598,7 +3611,7 @@ pub const Value = struct { |
| 3598 | 3611 | ||
| 3599 | /// operands must be integers; handles undefined. | 3612 | /// operands must be integers; handles undefined. |
| 3600 | pub fn bitwiseOrScalar(lhs: Value, rhs: Value, arena: Allocator, mod: *Module) !Value { | 3613 | pub fn bitwiseOrScalar(lhs: Value, rhs: Value, arena: Allocator, mod: *Module) !Value { |
| 3601 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); | 3614 | if (lhs.isUndef() or rhs.isUndef()) return Value.undef; |
| 3602 | 3615 | ||
| 3603 | // TODO is this a performance issue? maybe we should try the operation without | 3616 | // TODO is this a performance issue? maybe we should try the operation without |
| 3604 | // resorting to BigInt first. | 3617 | // resorting to BigInt first. |
| ... | @@ -3633,7 +3646,7 @@ pub const Value = struct { | ... | @@ -3633,7 +3646,7 @@ pub const Value = struct { |
| 3633 | 3646 | ||
| 3634 | /// operands must be integers; handles undefined. | 3647 | /// operands must be integers; handles undefined. |
| 3635 | pub fn bitwiseXorScalar(lhs: Value, rhs: Value, arena: Allocator, mod: *Module) !Value { | 3648 | pub fn bitwiseXorScalar(lhs: Value, rhs: Value, arena: Allocator, mod: *Module) !Value { |
| 3636 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); | 3649 | if (lhs.isUndef() or rhs.isUndef()) return Value.undef; |
| 3637 | 3650 | ||
| 3638 | // TODO is this a performance issue? maybe we should try the operation without | 3651 | // TODO is this a performance issue? maybe we should try the operation without |
| 3639 | // resorting to BigInt first. | 3652 | // resorting to BigInt first. |
| ... | @@ -5393,11 +5406,12 @@ pub const Value = struct { | ... | @@ -5393,11 +5406,12 @@ pub const Value = struct { |
| 5393 | .ip_index = .none, | 5406 | .ip_index = .none, |
| 5394 | .legacy = .{ .ptr_otherwise = &negative_one_payload.base }, | 5407 | .legacy = .{ .ptr_otherwise = &negative_one_payload.base }, |
| 5395 | }; | 5408 | }; |
| 5396 | pub const undef = initTag(.undef); | 5409 | pub const undef: Value = .{ .ip_index = .undef, .legacy = undefined }; |
| 5397 | pub const @"void": Value = .{ .ip_index = .void_value, .legacy = undefined }; | 5410 | pub const @"void": Value = .{ .ip_index = .void_value, .legacy = undefined }; |
| 5398 | pub const @"null" = initTag(.null_value); | 5411 | pub const @"null": Value = .{ .ip_index = .null_value, .legacy = undefined }; |
| 5399 | pub const @"false": Value = .{ .ip_index = .bool_false, .legacy = undefined }; | 5412 | pub const @"false": Value = .{ .ip_index = .bool_false, .legacy = undefined }; |
| 5400 | pub const @"true": Value = .{ .ip_index = .bool_true, .legacy = undefined }; | 5413 | pub const @"true": Value = .{ .ip_index = .bool_true, .legacy = undefined }; |
| 5414 | pub const @"unreachable": Value = .{ .ip_index = .unreachable_value, .legacy = undefined }; | ||
| 5401 | 5415 | ||
| 5402 | pub const generic_poison: Value = .{ .ip_index = .generic_poison, .legacy = undefined }; | 5416 | pub const generic_poison: Value = .{ .ip_index = .generic_poison, .legacy = undefined }; |
| 5403 | pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type, .legacy = undefined }; | 5417 | pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type, .legacy = undefined }; |