authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-04 21:40:35-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:42:28-07:00
log6ab8b6f8b273356ce248a075b6a0657bfea33c79
treecf0ea8802bc77376a38a4cfa25c6e9413d5b3fc0
parent773fabf3610629c8974b59ed6fbd27050b7e505b

stage2: move undef, unreach, null values to InternPool


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 },
48714873
4872 .unreachable_value => unreachable,
4873
4874 .function => {},4874 .function => {},
48754875
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 }), // name6593 }), // name
6594 try Value.Tag.decl_ref.create(arena, test_decl_index), // func6594 try Value.Tag.decl_ref.create(arena, test_decl_index), // func
6595 Value.initTag(.null_value), // async_frame_size6595 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;
44104410
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 }
45554555
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 location12643 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 location12653 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 location12964 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(
1433214332
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 {
1450814508
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";
1451314513
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)) orelse15649 const val = (try sema.resolveMaybeUndefValAllowVariables(operand)) orelse
15650 Value.initTag(.unreachable_value);15650 Value.@"unreachable";
1565115651
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 };
1568615686
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 }
1571415714
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 }
1574415744
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
1647716477
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 };
1651916519
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 null16522 null
16523 else16523 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 };
1657616576
...@@ -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;
1797617976
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;
1799517995
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;
1801218012
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 else19545 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 }
1955219552
...@@ -22579,7 +22579,7 @@ fn zirVarExtended(...@@ -22579,7 +22579,7 @@ fn zirVarExtended(
2257922579
22580 break :blk (try sema.resolveMaybeUndefVal(init)) orelse22580 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";
2258322583
22584 try sema.validateVarType(block, ty_src, var_ty, small.is_extern);22584 try sema.validateVarType(block, ty_src, var_ty, small.is_extern);
2258522585
...@@ -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 }
2754227544
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 we27547 // 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 representation27548 // 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 about27571 .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 detection27573 // 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 stored27574 // 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);
2757627578 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 when27581 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]);
2758627588 }
27587 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
2758827589
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);
2760727591
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 }
2761927622
27620 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);27623 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
2762127624
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, and27636 // 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 the27638 // However, now we want to modify an individual field and so the
27636 // representation has to change. If we wanted to avoid this, there would27639 // 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 an27640 // 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 it27641 // 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 }
2764227654
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 }
2765127656
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 },
2765327667
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 },
2766427677
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 },
2767427691
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(
2773827743
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 we27748 // 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 representation27749 // 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 ),
2785627833
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 ),
2786627838
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);
2786927841
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 },
2788327889
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 we27964 // An optional has been initialized to undefined at comptime and now we
27957 // are for the first time setting the payload. We must change the27965 // 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 },
2798127990
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 },
2811728115
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 },
2812228138
28123 // This code assumes that elem_ptrs have been "flattened" in order for direct dereference28139 .elem_ptr => blk: {
28124 // to succeed, meaning that elem ptrs of the same elem_ty are coalesced. Here we check that28140 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 },
2812928211
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 }
2814328237
28144 // If we're loading an elem_ptr that was derived from a different type28238 const tv = deref.pointee orelse {
28145 // than the true type of the underlying decl, we cannot deref directly28239 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 or28242 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 }
2817028249
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 },
2819028272
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 },
2819528282
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);
2820028293
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 }
2821628299
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 or28305 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 },
2822828322 .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);
2827228326
28273 // eu_payload_ptr and opt_payload_ptr never have a well-defined layout28327 .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,
2827828337
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 };
2832228342
...@@ -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 location28975 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);
2905329073
29054 const field_src = inst_src; // TODO better source location29074 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,
3296632986
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,
3297132991
...@@ -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-numbered33084 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)) orelse33111 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;
3381833838
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;
3387833898
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,
3416334185
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 },
3417534199
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 },
3420434243
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 },
3424534284
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 },
3425034289
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 },
3426834307
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 },
3427934321
34280 else => unreachable,34322 else => @panic("TODO"),
34281 }34323 }
34282}34324}
3428334325
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)");
7878
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);
8788
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);
107309
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(
111313
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 }
118321
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 => {
146351 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("&");
156361
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;
315381
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 }
328387
329 try writer.writeAll(".{ ");388 var ty_val: Value.Payload.Ty = .{
389 .base = .{ .tag = .ty },
390 .data = ty,
391 };
330392
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("&");
363398
364 const data = val.castTag(.eu_payload_ptr).?.data;399 try writer.writeAll(", &(payload of ");
365400
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 ");
378405
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);
383409
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;
360361
361 // generate ptr362 // 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 }
371372
372 // generate length373 // 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 }
380381
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 }
653656
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 union699 // 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 });
12201224
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 }
10721086
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;
10751089
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 }
11101127
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);
12031235
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);
12071239
...@@ -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 {
20282028
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;
20322032
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 {
29542954
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;
29582958
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;
36123619
...@@ -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;
36463653
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;
36503657
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;
1050510512
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;
1112111128
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;
817818
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 }
10231024
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;
10251026
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;
12961297
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 else1597 else
1597 decl.val;1598 decl.val;
15981599
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 }
16021603
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 {
14331433
1434 try print(field_ty, writer, mod);1434 try print(field_ty, writer, mod);
14351435
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 field1773 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 field2286 if (val.ip_index != .unreachable_value) continue; // comptime field
2287 if (!(field_ty.hasRuntimeBits(mod))) continue;2287 if (!(field_ty.hasRuntimeBits(mod))) continue;
22882288
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,
38463846
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,
38513851
...@@ -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-numbered3924 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 {
46474647
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 field4651 // 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.py33 // 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,
4340
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 {
132129
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"),
144138
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,
299290
...@@ -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, u0806 .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(),
834823
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, u0873 .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,
894882
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 {
913899
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, u0922 .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 },
953940
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 }
21702153
...@@ -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 }
23072290
...@@ -2642,7 +2625,6 @@ pub const Value = struct {...@@ -2642,7 +2625,6 @@ pub const Value = struct {
26422625
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 index2704 .none => switch (val.tag()) {
2724 .empty_struct_value => unreachable, // out of bounds array index2705 // 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
27252708
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 },
27302713
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 },
27572740
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,
27602743
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),
27632746
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 },
27802763
2781 // The child type of arrays which have only one possible value need2764 // 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,
27842767
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),
27872770
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),
27902773
2774 else => unreachable,
2775 },
2791 else => unreachable,2776 else => unreachable,
2792 }2777 }
2793 }2778 }
27942779
2795 /// Returns true if a Value is backed by a variable2780 /// 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 },
28142800
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 }
28792867
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 correct2876 .@"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 },
28912881
2892 .the_only_possible_value => return ty.onePossibleValue(mod).?,2882 .the_only_possible_value => return ty.onePossibleValue(mod).?,
28932883
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,
29052894
2895 else => unreachable,
2896 },
2906 else => unreachable,2897 else => unreachable,
2907 }2898 }
2908 }2899 }
29092900
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 }
29482943
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 }
29522947
2953 /// TODO: check for cases such as array that is not marked undef but all the element2948 /// 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 marked2949 /// 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 }
29592954
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 marked2957 /// 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 => {
29692964 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 },
29772974
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 }
29882985
...@@ -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,
29982998
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.
30013001
3002 .zero,3002 .zero,
3003 .the_only_possible_value,3003 .the_only_possible_value,
3004 => true,3004 => true,
30053005
3006 .one => false,3006 .one => false,
30073007
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),
30133013
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,
30183016
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 the3025 /// 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,
30393040
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 is3047 /// 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 }
30563062
...@@ -3065,17 +3071,20 @@ pub const Value = struct {...@@ -3065,17 +3071,20 @@ pub const Value = struct {
30653071
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,
30723079
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 {
31023111
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, u03116 .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;
33853398
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 {
34923505
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;
34963509
3497 const info = ty.intInfo(mod);3510 const info = ty.intInfo(mod);
34983511
...@@ -3532,7 +3545,7 @@ pub const Value = struct {...@@ -3532,7 +3545,7 @@ pub const Value = struct {
35323545
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;
35363549
3537 // TODO is this a performance issue? maybe we should try the operation without3550 // 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 {
35683581
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;
35723585
3573 const anded = try bitwiseAnd(lhs, rhs, ty, arena, mod);3586 const anded = try bitwiseAnd(lhs, rhs, ty, arena, mod);
35743587
...@@ -3598,7 +3611,7 @@ pub const Value = struct {...@@ -3598,7 +3611,7 @@ pub const Value = struct {
35983611
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;
36023615
3603 // TODO is this a performance issue? maybe we should try the operation without3616 // 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 {
36333646
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;
36373650
3638 // TODO is this a performance issue? maybe we should try the operation without3651 // 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 };
54015415
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 };