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 {
932932 assert(decl.has_tv);
933933 return switch (decl.val.tag()) {
934934 .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,
936936 else => false,
937937 };
938938 }
......@@ -4849,6 +4849,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
48494849 var is_extern = false;
48504850 switch (decl_tv.val.ip_index) {
48514851 .generic_poison => unreachable,
4852 .unreachable_value => unreachable,
4853
48524854 .none => switch (decl_tv.val.tag()) {
48534855 .variable => {
48544856 const variable = decl_tv.val.castTag(.variable).?.data;
......@@ -4869,8 +4871,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
48694871 }
48704872 },
48714873
4872 .unreachable_value => unreachable,
4873
48744874 .function => {},
48754875
48764876 else => {
......@@ -6592,7 +6592,7 @@ pub fn populateTestFunctions(
65926592 .len = try Value.Tag.int_u64.create(arena, test_name_slice.len),
65936593 }), // name
65946594 try Value.Tag.decl_ref.create(arena, test_decl_index), // func
6595 Value.initTag(.null_value), // async_frame_size
6595 Value.null, // async_frame_size
65966596 };
65976597 test_fn_vals[i] = try Value.Tag.aggregate.create(arena, field_vals);
65986598 }
src/Sema.zig+572-530
......@@ -1877,8 +1877,8 @@ fn resolveConstValue(
18771877 if (try sema.resolveMaybeUndefValAllowVariables(air_ref)) |val| {
18781878 switch (val.ip_index) {
18791879 .generic_poison => return error.GenericPoison,
1880 .undef => return sema.failWithUseOfUndef(block, src),
18801881 .none => switch (val.tag()) {
1881 .undef => return sema.failWithUseOfUndef(block, src),
18821882 .variable => return sema.failWithNeededComptime(block, src, reason),
18831883 else => return val,
18841884 },
......@@ -4409,7 +4409,7 @@ fn validateStructInit(
44094409 if (field_ptr != 0) continue;
44104410
44114411 const default_val = struct_ty.structFieldDefaultValue(i);
4412 if (default_val.tag() == .unreachable_value) {
4412 if (default_val.ip_index == .unreachable_value) {
44134413 if (struct_ty.isTuple()) {
44144414 const template = "missing tuple field with index {d}";
44154415 if (root_msg) |msg| {
......@@ -4554,7 +4554,7 @@ fn validateStructInit(
45544554 }
45554555
45564556 const default_val = struct_ty.structFieldDefaultValue(i);
4557 if (default_val.tag() == .unreachable_value) {
4557 if (default_val.ip_index == .unreachable_value) {
45584558 if (struct_ty.isTuple()) {
45594559 const template = "missing tuple field with index {d}";
45604560 if (root_msg) |msg| {
......@@ -4644,7 +4644,7 @@ fn zirValidateArrayInit(
46444644 var i = instrs.len;
46454645 while (i < array_len) : (i += 1) {
46464646 const default_val = array_ty.structFieldDefaultValue(i);
4647 if (default_val.tag() == .unreachable_value) {
4647 if (default_val.ip_index == .unreachable_value) {
46484648 const template = "missing tuple field with index {d}";
46494649 if (root_msg) |msg| {
46504650 try sema.errNote(block, init_src, msg, template, .{i});
......@@ -7885,7 +7885,7 @@ fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type)
78857885 const tuple = ty.tupleFields();
78867886 for (tuple.values, 0..) |field_val, i| {
78877887 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;
78897889 try sema.resolveLazyValue(field_val);
78907890 }
78917891}
......@@ -12641,7 +12641,7 @@ fn analyzeTupleCat(
1264112641 const default_val = lhs_ty.structFieldDefaultValue(i);
1264212642 values[i] = default_val;
1264312643 const operand_src = lhs_src; // TODO better source location
12644 if (default_val.tag() == .unreachable_value) {
12644 if (default_val.ip_index == .unreachable_value) {
1264512645 runtime_src = operand_src;
1264612646 }
1264712647 }
......@@ -12651,7 +12651,7 @@ fn analyzeTupleCat(
1265112651 const default_val = rhs_ty.structFieldDefaultValue(i);
1265212652 values[i + lhs_len] = default_val;
1265312653 const operand_src = rhs_src; // TODO better source location
12654 if (default_val.tag() == .unreachable_value) {
12654 if (default_val.ip_index == .unreachable_value) {
1265512655 runtime_src = operand_src;
1265612656 }
1265712657 }
......@@ -12809,8 +12809,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1280912809 while (elem_i < lhs_len) : (elem_i += 1) {
1281012810 const lhs_elem_i = elem_i;
1281112811 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);
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;
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.ip_index == .unreachable_value) try lhs_sub_val.elemValue(sema.mod, sema.arena, lhs_elem_i) else elem_default_val;
1281412814 const elem_val_inst = try sema.addConstant(elem_ty, elem_val);
1281512815 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded);
1281612816 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
1281912819 while (elem_i < result_len) : (elem_i += 1) {
1282012820 const rhs_elem_i = elem_i - lhs_len;
1282112821 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);
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;
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.ip_index == .unreachable_value) try rhs_sub_val.elemValue(sema.mod, sema.arena, rhs_elem_i) else elem_default_val;
1282412824 const elem_val_inst = try sema.addConstant(elem_ty, elem_val);
1282512825 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded);
1282612826 const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, "");
......@@ -12962,7 +12962,7 @@ fn analyzeTupleMul(
1296212962 types[i] = operand_ty.structFieldType(i);
1296312963 values[i] = operand_ty.structFieldDefaultValue(i);
1296412964 const operand_src = lhs_src; // TODO better source location
12965 if (values[i].tag() == .unreachable_value) {
12965 if (values[i].ip_index == .unreachable_value) {
1296612966 runtime_src = operand_src;
1296712967 }
1296812968 }
......@@ -14332,7 +14332,7 @@ fn zirOverflowArithmetic(
1433214332
1433314333 var result: struct {
1433414334 inst: Air.Inst.Ref = .none,
14335 wrapped: Value = Value.initTag(.unreachable_value),
14335 wrapped: Value = Value.@"unreachable",
1433614336 overflow_bit: Value,
1433714337 } = result: {
1433814338 switch (zir_tag) {
......@@ -14508,8 +14508,8 @@ fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type {
1450814508
1450914509 types[0] = ty;
1451014510 types[1] = ov_ty;
14511 values[0] = Value.initTag(.unreachable_value);
14512 values[1] = Value.initTag(.unreachable_value);
14511 values[0] = Value.@"unreachable";
14512 values[1] = Value.@"unreachable";
1451314513
1451414514 return tuple_ty;
1451514515}
......@@ -15647,7 +15647,7 @@ fn zirClosureCapture(
1564715647 // value only. In such case we preserve the type and use a dummy runtime value.
1564815648 const operand = try sema.resolveInst(inst_data.operand);
1564915649 const val = (try sema.resolveMaybeUndefValAllowVariables(operand)) orelse
15650 Value.initTag(.unreachable_value);
15650 Value.@"unreachable";
1565115651
1565215652 try block.wip_capture_scope.captures.putNoClobber(sema.gpa, inst, .{
1565315653 .ty = try sema.typeOf(operand).copy(sema.perm_arena),
......@@ -15684,7 +15684,7 @@ fn zirClosureGet(
1568415684 scope = scope.parent.?;
1568515685 };
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) {
1568815688 const msg = msg: {
1568915689 const name = name: {
1569015690 const file = sema.owner_decl.getFileScope();
......@@ -15712,7 +15712,7 @@ fn zirClosureGet(
1571215712 return sema.failWithOwnedErrorMsg(msg);
1571315713 }
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) {
1571615716 const msg = msg: {
1571715717 const name = name: {
1571815718 const file = sema.owner_decl.getFileScope();
......@@ -15742,7 +15742,7 @@ fn zirClosureGet(
1574215742 return sema.failWithOwnedErrorMsg(msg);
1574315743 }
1574415744
15745 if (tv.val.tag() == .unreachable_value) {
15745 if (tv.val.ip_index == .unreachable_value) {
1574615746 assert(block.is_typeof);
1574715747 // We need a dummy runtime instruction with the correct type.
1574815748 return block.addTy(.alloc, tv.ty);
......@@ -16477,7 +16477,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1647716477
1647816478 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
1647916479 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;
1648116481 const opt_default_val = if (is_comptime) field_val else null;
1648216482 const default_val_ptr = try sema.optRefValue(block, field_ty, opt_default_val);
1648316483 struct_field_fields.* = .{
......@@ -16518,7 +16518,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1651816518 };
1651916519
1652016520 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)
1652216522 null
1652316523 else
1652416524 field.default_val;
......@@ -16570,7 +16570,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1657016570 const backing_int_ty_val = try Value.Tag.ty.create(sema.arena, struct_obj.backing_int_ty);
1657116571 break :blk try Value.Tag.opt_payload.create(sema.arena, backing_int_ty_val);
1657216572 } else {
16573 break :blk Value.initTag(.null_value);
16573 break :blk Value.null;
1657416574 }
1657516575 };
1657616576
......@@ -17974,7 +17974,7 @@ fn finishStructInit(
1797417974 for (struct_obj.values, 0..) |default_val, i| {
1797517975 if (field_inits[i] != .none) continue;
1797617976
17977 if (default_val.tag() == .unreachable_value) {
17977 if (default_val.ip_index == .unreachable_value) {
1797817978 const field_name = struct_obj.names[i];
1797917979 const template = "missing struct field: {s}";
1798017980 const args = .{field_name};
......@@ -17994,7 +17994,7 @@ fn finishStructInit(
1799417994 if (field_inits[i] != .none) continue;
1799517995
1799617996 const default_val = struct_ty.structFieldDefaultValue(i);
17997 if (default_val.tag() == .unreachable_value) {
17997 if (default_val.ip_index == .unreachable_value) {
1799817998 const template = "missing tuple field with index {d}";
1799917999 if (root_msg) |msg| {
1800018000 try sema.errNote(block, init_src, msg, template, .{i});
......@@ -18010,7 +18010,7 @@ fn finishStructInit(
1801018010 for (struct_obj.fields.values(), 0..) |field, i| {
1801118011 if (field_inits[i] != .none) continue;
1801218012
18013 if (field.default_val.tag() == .unreachable_value) {
18013 if (field.default_val.ip_index == .unreachable_value) {
1801418014 const field_name = struct_obj.fields.keys()[i];
1801518015 const template = "missing struct field: {s}";
1801618016 const args = .{field_name};
......@@ -18145,7 +18145,7 @@ fn zirStructInitAnon(
1814518145 if (try sema.resolveMaybeUndefVal(init)) |init_val| {
1814618146 values[i] = init_val;
1814718147 } else {
18148 values[i] = Value.initTag(.unreachable_value);
18148 values[i] = Value.@"unreachable";
1814918149 runtime_index = i;
1815018150 }
1815118151 }
......@@ -18191,7 +18191,7 @@ fn zirStructInitAnon(
1819118191 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
1819218192 .pointee_type = field_ty,
1819318193 });
18194 if (values[i].tag() == .unreachable_value) {
18194 if (values[i].ip_index == .unreachable_value) {
1819518195 const init = try sema.resolveInst(item.data.init);
1819618196 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);
1819718197 _ = try block.addBinOp(.store, field_ptr, init);
......@@ -18357,7 +18357,7 @@ fn zirArrayInitAnon(
1835718357 if (try sema.resolveMaybeUndefVal(elem)) |val| {
1835818358 values[i] = val;
1835918359 } else {
18360 values[i] = Value.initTag(.unreachable_value);
18360 values[i] = Value.@"unreachable";
1836118361 runtime_src = operand_src;
1836218362 }
1836318363 }
......@@ -18390,7 +18390,7 @@ fn zirArrayInitAnon(
1839018390 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
1839118391 .pointee_type = types[i],
1839218392 });
18393 if (values[i].tag() == .unreachable_value) {
18393 if (values[i].ip_index == .unreachable_value) {
1839418394 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);
1839518395 _ = try block.addBinOp(.store, field_ptr, try sema.resolveInst(operand));
1839618396 }
......@@ -19545,8 +19545,8 @@ fn reifyStruct(
1954519545 else
1954619546 opt_val;
1954719547 break :blk try payload_val.copy(new_decl_arena_allocator);
19548 } else Value.initTag(.unreachable_value);
19549 if (is_comptime_val.toBool(mod) and default_val.tag() == .unreachable_value) {
19548 } else Value.@"unreachable";
19549 if (is_comptime_val.toBool(mod) and default_val.ip_index == .unreachable_value) {
1955019550 return sema.fail(block, src, "comptime field without default initialization value", .{});
1955119551 }
1955219552
......@@ -22579,7 +22579,7 @@ fn zirVarExtended(
2257922579
2258022580 break :blk (try sema.resolveMaybeUndefVal(init)) orelse
2258122581 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
2258422584 try sema.validateVarType(block, ty_src, var_ty, small.is_extern);
2258522585
......@@ -23080,7 +23080,7 @@ fn zirBuiltinExtern(
2308023080 const new_var = try new_decl_arena_allocator.create(Module.Var);
2308123081 new_var.* = .{
2308223082 .owner_decl = sema.owner_decl_index,
23083 .init = Value.initTag(.unreachable_value),
23083 .init = Value.@"unreachable",
2308423084 .is_extern = true,
2308523085 .is_mutable = false,
2308623086 .is_threadlocal = options.is_thread_local,
......@@ -25736,7 +25736,7 @@ fn coerceExtra(
2573625736 }
2573725737 } else {
2573825738 in_memory_result = .{ .ptr_sentinel = .{
25739 .actual = Value.initTag(.unreachable_value),
25739 .actual = Value.@"unreachable",
2574025740 .wanted = dest_sent,
2574125741 .ty = dst_elem_type,
2574225742 } };
......@@ -26116,26 +26116,28 @@ fn coerceExtra(
2611626116 .ErrorUnion => switch (inst_ty.zigTypeTag(mod)) {
2611726117 .ErrorUnion => eu: {
2611826118 if (maybe_inst_val) |inst_val| {
26119 switch (inst_val.tag()) {
26119 switch (inst_val.ip_index) {
2612026120 .undef => return sema.addConstUndef(dest_ty),
26121 .eu_payload => {
26122 const payload = try sema.addConstant(
26123 inst_ty.errorUnionPayload(),
26124 inst_val.castTag(.eu_payload).?.data,
26125 );
26126 return sema.wrapErrorUnionPayload(block, dest_ty, payload, inst_src) catch |err| switch (err) {
26127 error.NotCoercible => break :eu,
26128 else => |e| return e,
26129 };
26130 },
26131 else => {
26132 const error_set = try sema.addConstant(
26133 inst_ty.errorUnionSet(),
26134 inst_val,
26135 );
26136 return sema.wrapErrorUnionSet(block, dest_ty, error_set, inst_src);
26121 .none => switch (inst_val.tag()) {
26122 .eu_payload => {
26123 const payload = try sema.addConstant(
26124 inst_ty.errorUnionPayload(),
26125 inst_val.castTag(.eu_payload).?.data,
26126 );
26127 return sema.wrapErrorUnionPayload(block, dest_ty, payload, inst_src) catch |err| switch (err) {
26128 error.NotCoercible => break :eu,
26129 else => |e| return e,
26130 };
26131 },
26132 else => {},
2613726133 },
26134 else => {},
2613826135 }
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);
2613926141 }
2614026142 },
2614126143 .ErrorSet => {
......@@ -26413,7 +26415,7 @@ const InMemoryCoercionResult = union(enum) {
2641326415 break;
2641426416 },
2641526417 .array_sentinel => |sentinel| {
26416 if (sentinel.actual.tag() != .unreachable_value) {
26418 if (sentinel.actual.ip_index != .unreachable_value) {
2641726419 try sema.errNote(block, src, msg, "array sentinel '{}' cannot cast into array sentinel '{}'", .{
2641826420 sentinel.actual.fmtValue(sentinel.ty, sema.mod), sentinel.wanted.fmtValue(sentinel.ty, sema.mod),
2641926421 });
......@@ -26539,7 +26541,7 @@ const InMemoryCoercionResult = union(enum) {
2653926541 break;
2654026542 },
2654126543 .ptr_sentinel => |sentinel| {
26542 if (sentinel.actual.tag() != .unreachable_value) {
26544 if (sentinel.actual.ip_index != .unreachable_value) {
2654326545 try sema.errNote(block, src, msg, "pointer sentinel '{}' cannot cast into pointer sentinel '{}'", .{
2654426546 sentinel.actual.fmtValue(sentinel.ty, sema.mod), sentinel.wanted.fmtValue(sentinel.ty, sema.mod),
2654526547 });
......@@ -26747,8 +26749,8 @@ fn coerceInMemoryAllowed(
2674726749 dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.elem_type, mod));
2674826750 if (!ok_sent) {
2674926751 return InMemoryCoercionResult{ .array_sentinel = .{
26750 .actual = src_info.sentinel orelse Value.initTag(.unreachable_value),
26751 .wanted = dest_info.sentinel orelse Value.initTag(.unreachable_value),
26752 .actual = src_info.sentinel orelse Value.@"unreachable",
26753 .wanted = dest_info.sentinel orelse Value.@"unreachable",
2675226754 .ty = dest_info.elem_type,
2675326755 } };
2675426756 }
......@@ -27129,8 +27131,8 @@ fn coerceInMemoryAllowedPtrs(
2712927131 dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.pointee_type, sema.mod));
2713027132 if (!ok_sent) {
2713127133 return InMemoryCoercionResult{ .ptr_sentinel = .{
27132 .actual = src_info.sentinel orelse Value.initTag(.unreachable_value),
27133 .wanted = dest_info.sentinel orelse Value.initTag(.unreachable_value),
27134 .actual = src_info.sentinel orelse Value.@"unreachable",
27135 .wanted = dest_info.sentinel orelse Value.@"unreachable",
2713427136 .ty = dest_info.pointee_type,
2713527137 } };
2713627138 }
......@@ -27540,7 +27542,7 @@ fn beginComptimePtrMutation(
2754027542 };
2754127543 }
2754227544
27543 switch (val_ptr.tag()) {
27545 switch (val_ptr.ip_index) {
2754427546 .undef => {
2754527547 // An array has been initialized to undefined at comptime and now we
2754627548 // are for the first time setting an element. We must change the representation
......@@ -27565,127 +27567,130 @@ fn beginComptimePtrMutation(
2756527567 parent.decl_ref_mut,
2756627568 );
2756727569 },
27568 .bytes => {
27569 // An array is memory-optimized to store a slice of bytes, but we are about
27570 // to modify an individual field and the representation has to change.
27571 // If we wanted to avoid this, there would need to be special detection
27572 // elsewhere to identify when writing a value to an array element that is stored
27573 // using the `bytes` tag, and handle it without making a call to this function.
27574 const arena = parent.beginArena(sema.mod);
27575 defer parent.finishArena(sema.mod);
27576
27577 const bytes = val_ptr.castTag(.bytes).?.data;
27578 const dest_len = parent.ty.arrayLenIncludingSentinel(mod);
27579 // bytes.len may be one greater than dest_len because of the case when
27580 // assigning `[N:S]T` to `[N]T`. This is allowed; the sentinel is omitted.
27581 assert(bytes.len >= dest_len);
27582 const elems = try arena.alloc(Value, @intCast(usize, dest_len));
27583 for (elems, 0..) |*elem, i| {
27584 elem.* = try Value.Tag.int_u64.create(arena, bytes[i]);
27585 }
27586
27587 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
27570 .none => switch (val_ptr.tag()) {
27571 .bytes => {
27572 // An array is memory-optimized to store a slice of bytes, but we are about
27573 // to modify an individual field and the representation has to change.
27574 // If we wanted to avoid this, there would need to be special detection
27575 // elsewhere to identify when writing a value to an array element that is stored
27576 // using the `bytes` tag, and handle it without making a call to this function.
27577 const arena = parent.beginArena(sema.mod);
27578 defer parent.finishArena(sema.mod);
27579
27580 const bytes = val_ptr.castTag(.bytes).?.data;
27581 const dest_len = parent.ty.arrayLenIncludingSentinel(mod);
27582 // bytes.len may be one greater than dest_len because of the case when
27583 // assigning `[N:S]T` to `[N]T`. This is allowed; the sentinel is omitted.
27584 assert(bytes.len >= dest_len);
27585 const elems = try arena.alloc(Value, @intCast(usize, dest_len));
27586 for (elems, 0..) |*elem, i| {
27587 elem.* = try Value.Tag.int_u64.create(arena, bytes[i]);
27588 }
2758827589
27589 return beginComptimePtrMutationInner(
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);
27590 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
2760727591
27608 const str_lit = val_ptr.castTag(.str_lit).?.data;
27609 const dest_len = parent.ty.arrayLenIncludingSentinel(mod);
27610 const bytes = sema.mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
27611 const elems = try arena.alloc(Value, @intCast(usize, dest_len));
27612 for (bytes, 0..) |byte, i| {
27613 elems[i] = try Value.Tag.int_u64.create(arena, byte);
27614 }
27615 if (parent.ty.sentinel(mod)) |sent_val| {
27616 assert(elems.len == bytes.len + 1);
27617 elems[bytes.len] = sent_val;
27618 }
27592 return beginComptimePtrMutationInner(
27593 sema,
27594 block,
27595 src,
27596 elem_ty,
27597 &elems[elem_ptr.index],
27598 ptr_elem_ty,
27599 parent.decl_ref_mut,
27600 );
27601 },
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(
27623 sema,
27624 block,
27625 src,
27626 elem_ty,
27627 &elems[elem_ptr.index],
27628 ptr_elem_ty,
27629 parent.decl_ref_mut,
27630 );
27631 },
27632 .repeated => {
27633 // 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.
27635 // However, now we want to modify an individual field and so the
27636 // representation has to change. If we wanted to avoid this, there would
27637 // need to be special detection elsewhere to identify when writing a value to an
27638 // array element that is stored using the `repeated` tag, and handle it
27639 // without making a call to this function.
27640 const arena = parent.beginArena(sema.mod);
27641 defer parent.finishArena(sema.mod);
27625 return beginComptimePtrMutationInner(
27626 sema,
27627 block,
27628 src,
27629 elem_ty,
27630 &elems[elem_ptr.index],
27631 ptr_elem_ty,
27632 parent.decl_ref_mut,
27633 );
27634 },
27635 .repeated => {
27636 // An array is memory-optimized to store only a single element value, and
27637 // that value is understood to be the same for the entire length of the array.
27638 // However, now we want to modify an individual field and so the
27639 // representation has to change. If we wanted to avoid this, there would
27640 // need to be special detection elsewhere to identify when writing a value to an
27641 // array element that is stored using the `repeated` tag, and handle it
27642 // without making a call to this function.
27643 const arena = parent.beginArena(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);
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 }
27655 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
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(
2765527669 sema,
2765627670 block,
2765727671 src,
2765827672 elem_ty,
27659 &elems[elem_ptr.index],
27673 &val_ptr.castTag(.aggregate).?.data[elem_ptr.index],
2766027674 ptr_elem_ty,
2766127675 parent.decl_ref_mut,
27662 );
27663 },
27676 ),
2766427677
27665 .aggregate => return beginComptimePtrMutationInner(
27666 sema,
27667 block,
27668 src,
27669 elem_ty,
27670 &val_ptr.castTag(.aggregate).?.data[elem_ptr.index],
27671 ptr_elem_ty,
27672 parent.decl_ref_mut,
27673 ),
27678 .the_only_possible_value => {
27679 const duped = try sema.arena.create(Value);
27680 duped.* = Value.initTag(.the_only_possible_value);
27681 return beginComptimePtrMutationInner(
27682 sema,
27683 block,
27684 src,
27685 elem_ty,
27686 duped,
27687 ptr_elem_ty,
27688 parent.decl_ref_mut,
27689 );
27690 },
2767427691
27675 .the_only_possible_value => {
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 );
27692 else => unreachable,
2768727693 },
27688
2768927694 else => unreachable,
2769027695 }
2769127696 },
......@@ -27738,7 +27743,7 @@ fn beginComptimePtrMutation(
2773827743
2773927744 var parent = try sema.beginComptimePtrMutation(block, src, field_ptr.container_ptr, field_ptr.container_ty);
2774027745 switch (parent.pointee) {
27741 .direct => |val_ptr| switch (val_ptr.tag()) {
27746 .direct => |val_ptr| switch (val_ptr.ip_index) {
2774227747 .undef => {
2774327748 // A struct or union has been initialized to undefined at comptime and now we
2774427749 // are for the first time setting a field. We must change the representation
......@@ -27815,72 +27820,75 @@ fn beginComptimePtrMutation(
2781527820 else => unreachable,
2781627821 }
2781727822 },
27818 .aggregate => return beginComptimePtrMutationInner(
27819 sema,
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(
27823 .none => switch (val_ptr.tag()) {
27824 .aggregate => return beginComptimePtrMutationInner(
2783727825 sema,
2783827826 block,
2783927827 src,
2784027828 parent.ty.structFieldType(field_index),
27841 &payload.val,
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,
27829 &val_ptr.castTag(.aggregate).?.data[field_index],
2785327830 ptr_elem_ty,
2785427831 parent.decl_ref_mut,
2785527832 ),
2785627833
27857 Value.Payload.Slice.len_index => return beginComptimePtrMutationInner(
27858 sema,
27859 block,
27860 src,
27861 Type.usize,
27862 &val_ptr.castTag(.slice).?.data.len,
27863 ptr_elem_ty,
27864 parent.decl_ref_mut,
27865 ),
27834 .@"union" => {
27835 // We need to set the active field of the union.
27836 const arena = parent.beginArena(sema.mod);
27837 defer parent.finishArena(sema.mod);
2786627838
27867 else => unreachable,
27868 },
27839 const payload = &val_ptr.castTag(.@"union").?.data;
27840 payload.tag = try Value.Tag.enum_field_index.create(arena, field_index);
2786927841
27870 .empty_struct_value => {
27871 const duped = try sema.arena.create(Value);
27872 duped.* = Value.initTag(.the_only_possible_value);
27873 return beginComptimePtrMutationInner(
27874 sema,
27875 block,
27876 src,
27877 parent.ty.structFieldType(field_index),
27878 duped,
27879 ptr_elem_ty,
27880 parent.decl_ref_mut,
27881 );
27882 },
27842 return beginComptimePtrMutationInner(
27843 sema,
27844 block,
27845 src,
27846 parent.ty.structFieldType(field_index),
27847 &payload.val,
27848 ptr_elem_ty,
27849 parent.decl_ref_mut,
27850 );
27851 },
27852 .slice => switch (field_index) {
27853 Value.Payload.Slice.ptr_index => return beginComptimePtrMutationInner(
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 },
2788427892 else => unreachable,
2788527893 },
2788627894 .reinterpret => |reinterpret| {
......@@ -27951,7 +27959,7 @@ fn beginComptimePtrMutation(
2795127959 switch (parent.pointee) {
2795227960 .direct => |val_ptr| {
2795327961 const payload_ty = parent.ty.optionalChild(mod);
27954 switch (val_ptr.tag()) {
27962 switch (val_ptr.ip_index) {
2795527963 .undef, .null_value => {
2795627964 // An optional has been initialized to undefined at comptime and now we
2795727965 // are for the first time setting the payload. We must change the
......@@ -27973,12 +27981,19 @@ fn beginComptimePtrMutation(
2797327981 .ty = payload_ty,
2797427982 };
2797527983 },
27976 .opt_payload => return ComptimePtrMutationKit{
27977 .decl_ref_mut = parent.decl_ref_mut,
27978 .pointee = .{ .direct = &val_ptr.castTag(.opt_payload).?.data },
27979 .ty = payload_ty,
27980 },
27984 .none => switch (val_ptr.tag()) {
27985 .opt_payload => return ComptimePtrMutationKit{
27986 .decl_ref_mut = parent.decl_ref_mut,
27987 .pointee = .{ .direct = &val_ptr.castTag(.opt_payload).?.data },
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 },
2798227997 else => return ComptimePtrMutationKit{
2798327998 .decl_ref_mut = parent.decl_ref_mut,
2798427999 .pointee = .{ .direct = val_ptr },
......@@ -28092,231 +28107,236 @@ fn beginComptimePtrLoad(
2809228107) ComptimePtrLoadError!ComptimePtrLoadKit {
2809328108 const mod = sema.mod;
2809428109 const target = sema.mod.getTarget();
28095 var deref: ComptimePtrLoadKit = switch (ptr_val.tag()) {
28096 .decl_ref,
28097 .decl_ref_mut,
28098 => blk: {
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 };
28110
28111 var deref: ComptimePtrLoadKit = switch (ptr_val.ip_index) {
28112 .null_value => {
28113 return sema.fail(block, src, "attempt to use null value", .{});
2811628114 },
2811728115
28118 .elem_ptr => blk: {
28119 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
28120 const elem_ty = elem_ptr.elem_ty;
28121 var deref = try sema.beginComptimePtrLoad(block, src, elem_ptr.array_ptr, null);
28116 .none => switch (ptr_val.tag()) {
28117 .decl_ref,
28118 .decl_ref_mut,
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 dereference
28124 // to succeed, meaning that elem ptrs of the same elem_ty are coalesced. Here we check that
28125 // our parent is not an elem_ptr with the same elem_ty, since that would be "unflattened"
28126 if (elem_ptr.array_ptr.castTag(.elem_ptr)) |parent_elem_ptr| {
28127 assert(!(parent_elem_ptr.data.elem_ty.eql(elem_ty, sema.mod)));
28128 }
28139 .elem_ptr => blk: {
28140 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
28141 const elem_ty = elem_ptr.elem_ty;
28142 var deref = try sema.beginComptimePtrLoad(block, src, elem_ptr.array_ptr, null);
28143
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) {
28131 if (elem_ty.hasWellDefinedLayout(mod)) {
28132 if (deref.parent) |*parent| {
28212 .slice => blk: {
28213 const slice = ptr_val.castTag(.slice).?.data;
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| {
2813328228 // Update the byte offset (in-place)
28134 const elem_size = try sema.typeAbiSize(elem_ty);
28135 const offset = parent.byte_offset + elem_size * elem_ptr.index;
28136 parent.byte_offset = try sema.usizeCast(block, src, offset);
28229 try sema.resolveTypeLayout(field_ptr.container_ty);
28230 const field_offset = field_ptr.container_ty.structFieldOffset(field_index, mod);
28231 parent.byte_offset = try sema.usizeCast(block, src, parent.byte_offset + field_offset);
2813728232 }
2813828233 } else {
2813928234 deref.parent = null;
28140 deref.ty_without_well_defined_layout = elem_ty;
28235 deref.ty_without_well_defined_layout = field_ptr.container_ty;
2814128236 }
28142 }
2814328237
28144 // If we're loading an elem_ptr that was derived from a different type
28145 // than the true type of the underlying decl, we cannot deref directly
28146 const ty_matches = if (deref.pointee != null and deref.pointee.?.ty.isArrayOrVector(mod)) x: {
28147 const deref_elem_ty = deref.pointee.?.ty.childType(mod);
28148 break :x (try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok or
28149 (try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok;
28150 } else false;
28151 if (!ty_matches) {
28152 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;
28238 const tv = deref.pointee orelse {
28239 deref.pointee = null;
28240 break :blk deref;
28241 };
28242 const coerce_in_mem_ok =
28243 (try sema.coerceInMemoryAllowed(block, field_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or
28244 (try sema.coerceInMemoryAllowed(block, tv.ty, field_ptr.container_ty, false, target, src, src)) == .ok;
28245 if (!coerce_in_mem_ok) {
28246 deref.pointee = null;
2816728247 break :blk deref;
2816828248 }
28169 }
2817028249
28171 if (elem_ptr.index >= check_len) {
28172 deref.pointee = null;
28173 break :blk deref;
28174 }
28175 if (elem_ptr.index == check_len - 1) {
28176 if (array_tv.ty.sentinel(mod)) |sent| {
28250 if (field_ptr.container_ty.isSlice(mod)) {
28251 const slice_val = tv.val.castTag(.slice).?.data;
28252 deref.pointee = switch (field_index) {
28253 Value.Payload.Slice.ptr_index => TypedValue{
28254 .ty = field_ptr.container_ty.slicePtrFieldType(try sema.arena.create(Type.SlicePtrFieldTypeBuffer)),
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);
2817728265 deref.pointee = TypedValue{
28178 .ty = elem_ty,
28179 .val = sent,
28266 .ty = field_ty,
28267 .val = tv.val.fieldValue(tv.ty, mod, field_index),
2818028268 };
28181 break :blk deref;
2818228269 }
28183 }
28184 deref.pointee = TypedValue{
28185 .ty = elem_ty,
28186 .val = try array_tv.val.elemValue(sema.mod, sema.arena, elem_ptr.index),
28187 };
28188 break :blk deref;
28189 },
28270 break :blk deref;
28271 },
2819028272
28191 .slice => blk: {
28192 const slice = ptr_val.castTag(.slice).?.data;
28193 break :blk try sema.beginComptimePtrLoad(block, src, slice.ptr, null);
28194 },
28273 .comptime_field_ptr => blk: {
28274 const comptime_field_ptr = ptr_val.castTag(.comptime_field_ptr).?.data;
28275 break :blk ComptimePtrLoadKit{
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: {
28197 const field_ptr = ptr_val.castTag(.field_ptr).?.data;
28198 const field_index = @intCast(u32, field_ptr.field_index);
28199 var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.container_ptr, field_ptr.container_ty);
28283 .opt_payload_ptr,
28284 .eu_payload_ptr,
28285 => blk: {
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)) {
28202 const struct_ty = field_ptr.container_ty.castTag(.@"struct");
28203 if (struct_ty != null and struct_ty.?.data.layout == .Packed) {
28204 // packed structs are not byte addressable
28294 // eu_payload_ptr and opt_payload_ptr never have a well-defined layout
28295 if (deref.parent != null) {
2820528296 deref.parent = null;
28206 } else if (deref.parent) |*parent| {
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);
28297 deref.ty_without_well_defined_layout = payload_ptr.container_ty;
2821128298 }
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 {
28218 deref.pointee = null;
28219 break :blk deref;
28220 };
28221 const coerce_in_mem_ok =
28222 (try sema.coerceInMemoryAllowed(block, field_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or
28223 (try sema.coerceInMemoryAllowed(block, tv.ty, field_ptr.container_ty, false, target, src, src)) == .ok;
28224 if (!coerce_in_mem_ok) {
28300 if (deref.pointee) |*tv| {
28301 const coerce_in_mem_ok =
28302 (try sema.coerceInMemoryAllowed(block, payload_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or
28303 (try sema.coerceInMemoryAllowed(block, tv.ty, payload_ptr.container_ty, false, target, src, src)) == .ok;
28304 if (coerce_in_mem_ok) {
28305 const payload_val = switch (ptr_val.tag()) {
28306 .eu_payload_ptr => if (tv.val.castTag(.eu_payload)) |some| some.data else {
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 }
2822528319 deref.pointee = null;
2822628320 break :blk deref;
28227 }
28228
28229 if (field_ptr.container_ty.isSlice(mod)) {
28230 const slice_val = tv.val.castTag(.slice).?.data;
28231 deref.pointee = switch (field_index) {
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);
28321 },
28322 .opt_payload => blk: {
28323 const opt_payload = ptr_val.castTag(.opt_payload).?.data;
28324 break :blk try sema.beginComptimePtrLoad(block, src, opt_payload, null);
28325 },
2827228326
28273 // eu_payload_ptr and opt_payload_ptr never have a well-defined layout
28274 if (deref.parent != null) {
28275 deref.parent = null;
28276 deref.ty_without_well_defined_layout = payload_ptr.container_ty;
28277 }
28327 .zero,
28328 .one,
28329 .int_u64,
28330 .int_i64,
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| {
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);
28338 else => unreachable,
2830728339 },
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
2832028340 else => unreachable,
2832128341 };
2832228342
......@@ -28953,7 +28973,7 @@ fn coerceTupleToStruct(
2895328973 const field_name = fields.keys()[i];
2895428974 const field = fields.values()[i];
2895528975 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) {
2895728977 const template = "missing struct field: {s}";
2895828978 const args = .{field_name};
2895928979 if (root_msg) |msg| {
......@@ -29023,7 +29043,7 @@ fn coerceTupleToTuple(
2902329043 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);
2902429044 const coerced = try sema.coerce(block, field_ty, elem_ref, field_src);
2902529045 field_refs[field_index] = coerced;
29026 if (default_val.tag() != .unreachable_value) {
29046 if (default_val.ip_index != .unreachable_value) {
2902729047 const init_val = (try sema.resolveMaybeUndefVal(coerced)) orelse {
2902829048 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");
2902929049 };
......@@ -29052,7 +29072,7 @@ fn coerceTupleToTuple(
2905229072 const field_ty = tuple_ty.structFieldType(i);
2905329073
2905429074 const field_src = inst_src; // TODO better source location
29055 if (default_val.tag() == .unreachable_value) {
29075 if (default_val.ip_index == .unreachable_value) {
2905629076 if (tuple_ty.isTuple()) {
2905729077 const template = "missing tuple field: {d}";
2905829078 if (root_msg) |msg| {
......@@ -31557,7 +31577,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3155731577 .tuple, .anon_struct => {
3155831578 const tuple = ty.tupleFields();
3155931579 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;
3156131581 if (!have_comptime_val and try sema.resolveTypeRequiresComptime(field_ty)) {
3156231582 return true;
3156331583 }
......@@ -32141,7 +32161,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3214132161 gop.value_ptr.* = .{
3214232162 .ty = Type.noreturn,
3214332163 .abi_align = 0,
32144 .default_val = Value.initTag(.unreachable_value),
32164 .default_val = Value.@"unreachable",
3214532165 .is_comptime = is_comptime,
3214632166 .offset = undefined,
3214732167 };
......@@ -32965,7 +32985,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3296532985 => return null,
3296632986
3296732987 .void => return Value.void,
32968 .noreturn => return Value.initTag(.unreachable_value),
32988 .noreturn => return Value.@"unreachable",
3296932989 .null => return Value.null,
3297032990 .undefined => return Value.undef,
3297132991
......@@ -33027,7 +33047,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3302733047 .tuple, .anon_struct => {
3302833048 const tuple = ty.tupleFields();
3302933049 for (tuple.values, 0..) |val, i| {
33030 const is_comptime = val.tag() != .unreachable_value;
33050 const is_comptime = val.ip_index != .unreachable_value;
3303133051 if (is_comptime) continue;
3303233052 if ((try sema.typeHasOnePossibleValue(tuple.types[i])) != null) continue;
3303333053 return null;
......@@ -33059,7 +33079,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3305933079 return null;
3306033080 }
3306133081 switch (enum_obj.fields.count()) {
33062 0 => return Value.initTag(.unreachable_value),
33082 0 => return Value.@"unreachable",
3306333083 1 => if (enum_obj.values.count() == 0) {
3306433084 return Value.zero; // auto-numbered
3306533085 } else {
......@@ -33072,7 +33092,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3307233092 const resolved_ty = try sema.resolveTypeFields(ty);
3307333093 const enum_simple = resolved_ty.castTag(.enum_simple).?.data;
3307433094 switch (enum_simple.fields.count()) {
33075 0 => return Value.initTag(.unreachable_value),
33095 0 => return Value.@"unreachable",
3307633096 1 => return Value.zero,
3307733097 else => return null,
3307833098 }
......@@ -33091,7 +33111,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3309133111 const tag_val = (try sema.typeHasOnePossibleValue(union_obj.tag_ty)) orelse
3309233112 return null;
3309333113 const fields = union_obj.fields.values();
33094 if (fields.len == 0) return Value.initTag(.unreachable_value);
33114 if (fields.len == 0) return Value.@"unreachable";
3309533115 const only_field = fields[0];
3309633116 if (only_field.ty.eql(resolved_ty, sema.mod)) {
3309733117 const msg = try Module.ErrorMsg.create(
......@@ -33600,7 +33620,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3360033620 .tuple, .anon_struct => {
3360133621 const tuple = ty.tupleFields();
3360233622 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;
3360433624 if (!have_comptime_val and try sema.typeRequiresComptime(field_ty)) {
3360533625 return true;
3360633626 }
......@@ -33814,7 +33834,7 @@ fn numberAddWrapScalar(
3381433834 rhs: Value,
3381533835 ty: Type,
3381633836) !Value {
33817 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
33837 if (lhs.isUndef() or rhs.isUndef()) return Value.undef;
3381833838
3381933839 const mod = sema.mod;
3382033840 if (ty.zigTypeTag(mod) == .ComptimeInt) {
......@@ -33874,7 +33894,7 @@ fn numberSubWrapScalar(
3387433894 rhs: Value,
3387533895 ty: Type,
3387633896) !Value {
33877 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
33897 if (lhs.isUndef() or rhs.isUndef()) return Value.undef;
3387833898
3387933899 const mod = sema.mod;
3388033900 if (ty.zigTypeTag(mod) == .ComptimeInt) {
......@@ -34156,12 +34176,16 @@ fn intFitsInType(
3415634176) CompileError!bool {
3415734177 const mod = sema.mod;
3415834178 const target = mod.getTarget();
34159 switch (val.tag()) {
34160 .zero,
34179 switch (val.ip_index) {
3416134180 .undef,
34181 .zero,
34182 .zero_usize,
34183 .zero_u8,
3416234184 => return true,
3416334185
34164 .one => switch (ty.zigTypeTag(mod)) {
34186 .one,
34187 .one_usize,
34188 => switch (ty.zigTypeTag(mod)) {
3416534189 .Int => {
3416634190 const info = ty.intInfo(mod);
3416734191 return switch (info.signedness) {
......@@ -34173,111 +34197,129 @@ fn intFitsInType(
3417334197 else => unreachable,
3417434198 },
3417534199
34176 .lazy_align => switch (ty.zigTypeTag(mod)) {
34177 .Int => {
34178 const info = ty.intInfo(mod);
34179 const max_needed_bits = @as(u16, 16) + @boolToInt(info.signedness == .signed);
34180 // If it is u16 or bigger we know the alignment fits without resolving it.
34181 if (info.bits >= max_needed_bits) return true;
34182 const x = try sema.typeAbiAlignment(val.castTag(.lazy_align).?.data);
34183 if (x == 0) return true;
34184 const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
34185 return info.bits >= actual_needed_bits;
34200 .none => switch (val.tag()) {
34201 .zero => return true,
34202
34203 .one => switch (ty.zigTypeTag(mod)) {
34204 .Int => {
34205 const info = ty.intInfo(mod);
34206 return switch (info.signedness) {
34207 .signed => info.bits >= 2,
34208 .unsigned => info.bits >= 1,
34209 };
34210 },
34211 .ComptimeInt => return true,
34212 else => unreachable,
3418634213 },
34187 .ComptimeInt => return true,
34188 else => unreachable,
34189 },
34190 .lazy_size => switch (ty.zigTypeTag(mod)) {
34191 .Int => {
34192 const info = ty.intInfo(mod);
34193 const max_needed_bits = @as(u16, 64) + @boolToInt(info.signedness == .signed);
34194 // If it is u64 or bigger we know the size fits without resolving it.
34195 if (info.bits >= max_needed_bits) return true;
34196 const x = try sema.typeAbiSize(val.castTag(.lazy_size).?.data);
34197 if (x == 0) return true;
34198 const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
34199 return info.bits >= actual_needed_bits;
34214
34215 .lazy_align => switch (ty.zigTypeTag(mod)) {
34216 .Int => {
34217 const info = ty.intInfo(mod);
34218 const max_needed_bits = @as(u16, 16) + @boolToInt(info.signedness == .signed);
34219 // If it is u16 or bigger we know the alignment fits without resolving it.
34220 if (info.bits >= max_needed_bits) return true;
34221 const x = try sema.typeAbiAlignment(val.castTag(.lazy_align).?.data);
34222 if (x == 0) return true;
34223 const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
34224 return info.bits >= actual_needed_bits;
34225 },
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,
3420034242 },
34201 .ComptimeInt => return true,
34202 else => unreachable,
34203 },
3420434243
34205 .int_u64 => switch (ty.zigTypeTag(mod)) {
34206 .Int => {
34207 const x = val.castTag(.int_u64).?.data;
34208 if (x == 0) return true;
34209 const info = ty.intInfo(mod);
34210 const needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
34211 return info.bits >= needed_bits;
34244 .int_u64 => switch (ty.zigTypeTag(mod)) {
34245 .Int => {
34246 const x = val.castTag(.int_u64).?.data;
34247 if (x == 0) return true;
34248 const info = ty.intInfo(mod);
34249 const needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
34250 return info.bits >= needed_bits;
34251 },
34252 .ComptimeInt => return true,
34253 else => unreachable,
3421234254 },
34213 .ComptimeInt => return true,
34214 else => unreachable,
34215 },
34216 .int_i64 => switch (ty.zigTypeTag(mod)) {
34217 .Int => {
34218 const x = val.castTag(.int_i64).?.data;
34219 if (x == 0) return true;
34220 const info = ty.intInfo(mod);
34221 if (info.signedness == .unsigned and x < 0)
34222 return false;
34223 var buffer: Value.BigIntSpace = undefined;
34224 return (try val.toBigIntAdvanced(&buffer, mod, sema)).fitsInTwosComp(info.signedness, info.bits);
34255 .int_i64 => switch (ty.zigTypeTag(mod)) {
34256 .Int => {
34257 const x = val.castTag(.int_i64).?.data;
34258 if (x == 0) return true;
34259 const info = ty.intInfo(mod);
34260 if (info.signedness == .unsigned and x < 0)
34261 return false;
34262 var buffer: Value.BigIntSpace = undefined;
34263 return (try val.toBigIntAdvanced(&buffer, mod, sema)).fitsInTwosComp(info.signedness, info.bits);
34264 },
34265 .ComptimeInt => return true,
34266 else => unreachable,
3422534267 },
34226 .ComptimeInt => return true,
34227 else => unreachable,
34228 },
34229 .int_big_positive => switch (ty.zigTypeTag(mod)) {
34230 .Int => {
34231 const info = ty.intInfo(mod);
34232 return val.castTag(.int_big_positive).?.asBigInt().fitsInTwosComp(info.signedness, info.bits);
34268 .int_big_positive => switch (ty.zigTypeTag(mod)) {
34269 .Int => {
34270 const info = ty.intInfo(mod);
34271 return val.castTag(.int_big_positive).?.asBigInt().fitsInTwosComp(info.signedness, info.bits);
34272 },
34273 .ComptimeInt => return true,
34274 else => unreachable,
3423334275 },
34234 .ComptimeInt => return true,
34235 else => unreachable,
34236 },
34237 .int_big_negative => switch (ty.zigTypeTag(mod)) {
34238 .Int => {
34239 const info = ty.intInfo(mod);
34240 return val.castTag(.int_big_negative).?.asBigInt().fitsInTwosComp(info.signedness, info.bits);
34276 .int_big_negative => switch (ty.zigTypeTag(mod)) {
34277 .Int => {
34278 const info = ty.intInfo(mod);
34279 return val.castTag(.int_big_negative).?.asBigInt().fitsInTwosComp(info.signedness, info.bits);
34280 },
34281 .ComptimeInt => return true,
34282 else => unreachable,
3424134283 },
34242 .ComptimeInt => return true,
34243 else => unreachable,
34244 },
3424534284
34246 .the_only_possible_value => {
34247 assert(ty.intInfo(mod).bits == 0);
34248 return true;
34249 },
34285 .the_only_possible_value => {
34286 assert(ty.intInfo(mod).bits == 0);
34287 return true;
34288 },
3425034289
34251 .decl_ref_mut,
34252 .extern_fn,
34253 .decl_ref,
34254 .function,
34255 .variable,
34256 => switch (ty.zigTypeTag(mod)) {
34257 .Int => {
34258 const info = ty.intInfo(mod);
34259 const ptr_bits = target.ptrBitWidth();
34260 return switch (info.signedness) {
34261 .signed => info.bits > ptr_bits,
34262 .unsigned => info.bits >= ptr_bits,
34263 };
34290 .decl_ref_mut,
34291 .extern_fn,
34292 .decl_ref,
34293 .function,
34294 .variable,
34295 => switch (ty.zigTypeTag(mod)) {
34296 .Int => {
34297 const info = ty.intInfo(mod);
34298 const ptr_bits = target.ptrBitWidth();
34299 return switch (info.signedness) {
34300 .signed => info.bits > ptr_bits,
34301 .unsigned => info.bits >= ptr_bits,
34302 };
34303 },
34304 .ComptimeInt => return true,
34305 else => unreachable,
3426434306 },
34265 .ComptimeInt => return true,
34266 else => unreachable,
34267 },
3426834307
34269 .aggregate => {
34270 assert(ty.zigTypeTag(mod) == .Vector);
34271 for (val.castTag(.aggregate).?.data, 0..) |elem, i| {
34272 if (!(try sema.intFitsInType(elem, ty.scalarType(mod), null))) {
34273 if (vector_index) |some| some.* = i;
34274 return false;
34308 .aggregate => {
34309 assert(ty.zigTypeTag(mod) == .Vector);
34310 for (val.castTag(.aggregate).?.data, 0..) |elem, i| {
34311 if (!(try sema.intFitsInType(elem, ty.scalarType(mod), null))) {
34312 if (vector_index) |some| some.* = i;
34313 return false;
34314 }
3427534315 }
34276 }
34277 return true;
34316 return true;
34317 },
34318
34319 else => unreachable,
3427834320 },
3427934321
34280 else => unreachable,
34322 else => @panic("TODO"),
3428134323 }
3428234324}
3428334325
src/TypedValue.zig+289-286
......@@ -76,34 +76,236 @@ pub fn print(
7676 if (val.isVariable(mod))
7777 return writer.writeAll("(variable)");
7878
79 while (true) switch (val.tag()) {
80 .empty_struct_value, .aggregate => {
81 if (level == 0) {
82 return writer.writeAll(".{ ... }");
83 }
84 if (ty.zigTypeTag(mod) == .Struct) {
85 try writer.writeAll(".{");
86 const max_len = std.math.min(ty.structFieldCount(), max_aggregate_items);
79 while (true) switch (val.ip_index) {
80 .none => switch (val.tag()) {
81 .empty_struct_value, .aggregate => {
82 if (level == 0) {
83 return writer.writeAll(".{ ... }");
84 }
85 if (ty.zigTypeTag(mod) == .Struct) {
86 try writer.writeAll(".{");
87 const max_len = std.math.min(ty.structFieldCount(), max_aggregate_items);
8788
88 var i: u32 = 0;
89 while (i < max_len) : (i += 1) {
90 if (i != 0) try writer.writeAll(", ");
91 switch (ty.tag()) {
92 .anon_struct, .@"struct" => try writer.print(".{s} = ", .{ty.structFieldName(i)}),
93 else => {},
89 var i: u32 = 0;
90 while (i < max_len) : (i += 1) {
91 if (i != 0) try writer.writeAll(", ");
92 switch (ty.tag()) {
93 .anon_struct, .@"struct" => try writer.print(".{s} = ", .{ty.structFieldName(i)}),
94 else => {},
95 }
96 try print(.{
97 .ty = ty.structFieldType(i),
98 .val = val.fieldValue(ty, mod, i),
99 }, writer, level - 1, mod);
94100 }
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 {
95221 try print(.{
96 .ty = ty.structFieldType(i),
97 .val = val.fieldValue(ty, mod, i),
222 .ty = elem_ptr.elem_ty,
223 .val = elem_ptr.array_ptr,
98224 }, writer, level - 1, mod);
99225 }
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) {
101287 try writer.writeAll(", ...");
102288 }
103 return writer.writeAll("}");
104 } else {
289 return writer.writeAll(" }");
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;
105307 const elem_ty = ty.elemType2(mod);
106 const len = ty.arrayLen(mod);
308 const len = payload.len.toUnsignedInt(mod);
107309
108310 if (elem_ty.eql(Type.u8, mod)) str: {
109311 const max_len = @intCast(usize, std.math.min(len, max_string_len));
......@@ -111,11 +313,13 @@ pub fn print(
111313
112314 var i: u32 = 0;
113315 while (i < max_len) : (i += 1) {
114 const elem = val.fieldValue(ty, mod, i);
115 if (elem.isUndef()) break :str;
116 buf[i] = std.math.cast(u8, elem.toUnsignedInt(mod)) orelse break :str;
316 var elem_buf: Value.ElemValueBuffer = undefined;
317 const elem_val = payload.ptr.elemValueBuffer(mod, i, &elem_buf);
318 if (elem_val.isUndef()) break :str;
319 buf[i] = std.math.cast(u8, elem_val.toUnsignedInt(mod)) orelse break :str;
117320 }
118321
322 // TODO would be nice if this had a bit of unicode awareness.
119323 const truncated = if (len > max_string_len) " (truncated)" else "";
120324 return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
121325 }
......@@ -126,292 +330,91 @@ pub fn print(
126330 var i: u32 = 0;
127331 while (i < max_len) : (i += 1) {
128332 if (i != 0) try writer.writeAll(", ");
333 var buf: Value.ElemValueBuffer = undefined;
129334 try print(.{
130335 .ty = elem_ty,
131 .val = val.fieldValue(ty, mod, i),
336 .val = payload.ptr.elemValueBuffer(mod, i, &buf),
132337 }, writer, level - 1, mod);
133338 }
134339 if (len > max_aggregate_items) {
135340 try writer.writeAll(", ...");
136341 }
137342 return writer.writeAll(" }");
138 }
139 },
140 .@"union" => {
141 if (level == 0) {
142 return writer.writeAll(".{ ... }");
143 }
144 const union_val = val.castTag(.@"union").?.data;
145 try writer.writeAll(".{ ");
146
147 try print(.{
148 .ty = ty.cast(Type.Payload.Union).?.data.tag_ty,
149 .val = union_val.tag,
150 }, writer, level - 1, mod);
151 try writer.writeAll(" = ");
152 try print(.{
153 .ty = ty.unionFieldType(union_val.tag, mod),
154 .val = union_val.val,
155 }, writer, level - 1, mod);
156
157 return writer.writeAll(" }");
158 },
159 .null_value => return writer.writeAll("null"),
160 .undef => return writer.writeAll("undefined"),
161 .zero => return writer.writeAll("0"),
162 .one => return writer.writeAll("1"),
163 .unreachable_value => return writer.writeAll("unreachable"),
164 .the_only_possible_value => return writer.writeAll("0"),
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 {
343 },
344 .float_16 => return writer.print("{d}", .{val.castTag(.float_16).?.data}),
345 .float_32 => return writer.print("{d}", .{val.castTag(.float_32).?.data}),
346 .float_64 => return writer.print("{d}", .{val.castTag(.float_64).?.data}),
347 .float_80 => return writer.print("{d}", .{@floatCast(f64, val.castTag(.float_80).?.data)}),
348 .float_128 => return writer.print("{d}", .{@floatCast(f64, val.castTag(.float_128).?.data)}),
349 .@"error" => return writer.print("error.{s}", .{val.castTag(.@"error").?.data.name}),
350 .eu_payload => {
351 val = val.castTag(.eu_payload).?.data;
352 ty = ty.errorUnionPayload();
353 },
354 .opt_payload => {
355 val = val.castTag(.opt_payload).?.data;
356 ty = ty.optionalChild(mod);
357 return print(.{ .ty = ty, .val = val }, writer, level, mod);
358 },
359 .eu_payload_ptr => {
360 try writer.writeAll("&");
361
362 const data = val.castTag(.eu_payload_ptr).?.data;
363
364 var ty_val: Value.Payload.Ty = .{
365 .base = .{ .tag = .ty },
366 .data = ty,
367 };
368
369 try writer.writeAll("@as(");
223370 try print(.{
224 .ty = elem_ptr.elem_ty,
225 .val = elem_ptr.array_ptr,
371 .ty = Type.type,
372 .val = Value.initPayload(&ty_val.base),
226373 }, writer, level - 1, mod);
227 }
228 return writer.print("[{}]", .{elem_ptr.index});
229 },
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 {
374
375 try writer.writeAll(", &(payload of ");
376
236377 try print(.{
237 .ty = field_ptr.container_ty,
238 .val = field_ptr.container_ptr,
378 .ty = mod.singleMutPtrType(data.container_ty) catch @panic("OOM"),
379 .val = data.container_ptr,
239380 }, 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;
317 while (i < max_len) : (i += 1) {
318 var elem_buf: Value.ElemValueBuffer = undefined;
319 const elem_val = payload.ptr.elemValueBuffer(mod, i, &elem_buf);
320 if (elem_val.isUndef()) break :str;
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 }
382 try writer.writeAll("))");
383 return;
384 },
385 .opt_payload_ptr => {
386 const data = val.castTag(.opt_payload_ptr).?.data;
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);
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;
393 try writer.writeAll("@as(");
336394 try print(.{
337 .ty = elem_ty,
338 .val = payload.ptr.elemValueBuffer(mod, i, &buf),
395 .ty = Type.type,
396 .val = Value.initPayload(&ty_val.base),
339397 }, 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 = .{
367 .base = .{ .tag = .ty },
368 .data = ty,
369 };
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 ");
401 try print(.{
402 .ty = mod.singleMutPtrType(data.container_ty) catch @panic("OOM"),
403 .val = data.container_ptr,
404 }, writer, level - 1, mod);
378405
379 try print(.{
380 .ty = mod.singleMutPtrType(data.container_ty) catch @panic("OOM"),
381 .val = data.container_ptr,
382 }, writer, level - 1, mod);
406 try writer.writeAll("))");
407 return;
408 },
383409
384 try writer.writeAll("))");
385 return;
410 // TODO these should not appear in this function
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]"),
386414 },
387 .opt_payload_ptr => {
388 const data = val.castTag(.opt_payload_ptr).?.data;
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("))");
415 else => {
416 try writer.print("(interned: {})", .{val.ip_index});
409417 return;
410418 },
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]"),
416419 };
417420}
src/arch/wasm/CodeGen.zig+9-5
......@@ -3088,11 +3088,15 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
30883088 64 => return WValue{ .float64 = val.toFloat(f64) },
30893089 else => unreachable,
30903090 },
3091 .Pointer => switch (val.tag()) {
3092 .field_ptr, .elem_ptr, .opt_payload_ptr => return func.lowerParentPtr(val, 0),
3093 .int_u64, .one => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt(mod)) },
3094 .zero, .null_value => return WValue{ .imm32 = 0 },
3095 else => return func.fail("Wasm TODO: lowerConstant for other const pointer tag {}", .{val.tag()}),
3091 .Pointer => switch (val.ip_index) {
3092 .null_value => return WValue{ .imm32 = 0 },
3093 .none => switch (val.tag()) {
3094 .field_ptr, .elem_ptr, .opt_payload_ptr => return func.lowerParentPtr(val, 0),
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,
30963100 },
30973101 .Enum => {
30983102 if (val.castTag(.enum_field_index)) |field_index| {
src/codegen.zig+77-73
......@@ -312,7 +312,7 @@ pub fn generateSymbol(
312312 ),
313313 },
314314 },
315 .Pointer => switch (typed_value.val.tag()) {
315 .Pointer => switch (typed_value.val.ip_index) {
316316 .null_value => {
317317 switch (target.ptrBitWidth()) {
318318 32 => {
......@@ -327,76 +327,79 @@ pub fn generateSymbol(
327327 }
328328 return Result.ok;
329329 },
330 .zero, .one, .int_u64, .int_big_positive => {
331 switch (target.ptrBitWidth()) {
332 32 => {
333 const x = typed_value.val.toUnsignedInt(mod);
334 mem.writeInt(u32, try code.addManyAsArray(4), @intCast(u32, x), endian);
335 },
336 64 => {
337 const x = typed_value.val.toUnsignedInt(mod);
338 mem.writeInt(u64, try code.addManyAsArray(8), x, endian);
339 },
340 else => unreachable,
341 }
342 return Result.ok;
343 },
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,
330 .none => switch (typed_value.val.tag()) {
331 .zero, .one, .int_u64, .int_big_positive => {
332 switch (target.ptrBitWidth()) {
333 32 => {
334 const x = typed_value.val.toUnsignedInt(mod);
335 mem.writeInt(u32, try code.addManyAsArray(4), @intCast(u32, x), endian);
336 },
337 64 => {
338 const x = typed_value.val.toUnsignedInt(mod);
339 mem.writeInt(u64, try code.addManyAsArray(8), x, endian);
340 },
341 else => unreachable,
342 }
343 return Result.ok;
353344 },
354 code,
355 debug_output,
356 reloc_info,
357 ),
358 .slice => {
359 const slice = typed_value.val.castTag(.slice).?.data;
345 .variable, .decl_ref, .decl_ref_mut => |tag| return lowerDeclRef(
346 bin_file,
347 src_loc,
348 typed_value,
349 switch (tag) {
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 ptr
362 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
363 const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf);
364 switch (try generateSymbol(bin_file, src_loc, .{
365 .ty = slice_ptr_field_type,
366 .val = slice.ptr,
367 }, code, debug_output, reloc_info)) {
368 .ok => {},
369 .fail => |em| return Result{ .fail = em },
370 }
362 // generate ptr
363 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
364 const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf);
365 switch (try generateSymbol(bin_file, src_loc, .{
366 .ty = slice_ptr_field_type,
367 .val = slice.ptr,
368 }, code, debug_output, reloc_info)) {
369 .ok => {},
370 .fail => |em| return Result{ .fail = em },
371 }
371372
372 // generate length
373 switch (try generateSymbol(bin_file, src_loc, .{
374 .ty = Type.usize,
375 .val = slice.len,
376 }, code, debug_output, reloc_info)) {
377 .ok => {},
378 .fail => |em| return Result{ .fail = em },
379 }
373 // generate length
374 switch (try generateSymbol(bin_file, src_loc, .{
375 .ty = Type.usize,
376 .val = slice.len,
377 }, code, debug_output, reloc_info)) {
378 .ok => {},
379 .fail => |em| return Result{ .fail = em },
380 }
380381
381 return Result.ok;
382 },
383 .field_ptr, .elem_ptr, .opt_payload_ptr => return lowerParentPtr(
384 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,
382 return Result.ok;
383 },
384 .field_ptr, .elem_ptr, .opt_payload_ptr => return lowerParentPtr(
385 bin_file,
395386 src_loc,
396 "TODO implement generateSymbol for pointer type value: '{s}'",
397 .{@tagName(typed_value.val.tag())},
387 typed_value,
388 typed_value.val,
389 code,
390 debug_output,
391 reloc_info,
398392 ),
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 },
399401 },
402 else => unreachable,
400403 },
401404 .Int => {
402405 const info = typed_value.ty.intInfo(mod);
......@@ -652,7 +655,7 @@ pub fn generateSymbol(
652655 }
653656
654657 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;
656659 switch (try generateSymbol(bin_file, src_loc, .{
657660 .ty = payload_type,
658661 .val = value,
......@@ -696,7 +699,7 @@ pub fn generateSymbol(
696699 // emit payload part of the error union
697700 {
698701 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;
700703 switch (try generateSymbol(bin_file, src_loc, .{
701704 .ty = payload_ty,
702705 .val = payload_val,
......@@ -1189,16 +1192,17 @@ pub fn genTypedValue(
11891192 .Void => return GenResult.mcv(.none),
11901193 .Pointer => switch (typed_value.ty.ptrSize(mod)) {
11911194 .Slice => {},
1192 else => {
1193 switch (typed_value.val.tag()) {
1194 .null_value => {
1195 return GenResult.mcv(.{ .immediate = 0 });
1196 },
1195 else => switch (typed_value.val.ip_index) {
1196 .null_value => {
1197 return GenResult.mcv(.{ .immediate = 0 });
1198 },
1199 .none => switch (typed_value.val.tag()) {
11971200 .int_u64 => {
11981201 return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(mod) });
11991202 },
12001203 else => {},
1201 }
1204 },
1205 else => {},
12021206 },
12031207 },
12041208 .Int => {
......@@ -1216,7 +1220,7 @@ pub fn genTypedValue(
12161220 },
12171221 .Optional => {
12181222 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
12211225 return genTypedValue(bin_file, src_loc, .{
12221226 .ty = typed_value.ty.optionalChild(mod),
src/codegen/c.zig+137-105
......@@ -1045,8 +1045,8 @@ pub const DeclGen = struct {
10451045 if (!empty) try writer.writeByte(')');
10461046 return;
10471047 },
1048 .Pointer => switch (val.tag()) {
1049 .null_value, .zero => if (ty.isSlice(mod)) {
1048 .Pointer => switch (val.ip_index) {
1049 .null_value => if (ty.isSlice(mod)) {
10501050 var slice_pl = Value.Payload.Slice{
10511051 .base = .{ .tag = .slice },
10521052 .data = .{ .ptr = val, .len = Value.undef },
......@@ -1059,46 +1059,63 @@ pub const DeclGen = struct {
10591059 try dg.renderType(writer, ty);
10601060 try writer.writeAll(")NULL)");
10611061 },
1062 .variable => {
1063 const decl = val.castTag(.variable).?.data.owner_decl;
1064 return dg.renderDeclValue(writer, ty, val, decl, location);
1065 },
1066 .slice => {
1067 if (!location.isInitializer()) {
1068 try writer.writeByte('(');
1062 .none => switch (val.tag()) {
1063 .zero => if (ty.isSlice(mod)) {
1064 var slice_pl = Value.Payload.Slice{
1065 .base = .{ .tag = .slice },
1066 .data = .{ .ptr = val, .len = Value.undef },
1067 };
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("((");
10691073 try dg.renderType(writer, ty);
1070 try writer.writeByte(')');
1071 }
1074 try writer.writeAll(")NULL)");
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;
1074 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
1087 const slice = val.castTag(.slice).?.data;
1088 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
10751089
1076 try writer.writeByte('{');
1077 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr, initializer_type);
1078 try writer.writeAll(", ");
1079 try dg.renderValue(writer, Type.usize, slice.len, initializer_type);
1080 try writer.writeByte('}');
1081 },
1082 .function => {
1083 const func = val.castTag(.function).?.data;
1084 try dg.renderDeclName(writer, func.owner_decl, 0);
1085 },
1086 .extern_fn => {
1087 const extern_fn = val.castTag(.extern_fn).?.data;
1088 try dg.renderDeclName(writer, extern_fn.owner_decl, 0);
1089 },
1090 .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => {
1091 try writer.writeAll("((");
1092 try dg.renderType(writer, ty);
1093 return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
1090 try writer.writeByte('{');
1091 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr, initializer_type);
1092 try writer.writeAll(", ");
1093 try dg.renderValue(writer, Type.usize, slice.len, initializer_type);
1094 try writer.writeByte('}');
1095 },
1096 .function => {
1097 const func = val.castTag(.function).?.data;
1098 try dg.renderDeclName(writer, func.owner_decl, 0);
1099 },
1100 .extern_fn => {
1101 const extern_fn = val.castTag(.extern_fn).?.data;
1102 try dg.renderDeclName(writer, extern_fn.owner_decl, 0);
1103 },
1104 .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => {
1105 try writer.writeAll("((");
1106 try dg.renderType(writer, ty);
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,
10941118 },
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),
11021119 else => unreachable,
11031120 },
11041121 .Array, .Vector => {
......@@ -1109,8 +1126,8 @@ pub const DeclGen = struct {
11091126 }
11101127
11111128 // First try specific tag representations for more efficiency.
1112 switch (val.tag()) {
1113 .undef, .empty_struct_value, .empty_array => {
1129 switch (val.ip_index) {
1130 .undef => {
11141131 const ai = ty.arrayInfo(mod);
11151132 try writer.writeByte('{');
11161133 if (ai.sentinel) |s| {
......@@ -1119,76 +1136,91 @@ pub const DeclGen = struct {
11191136 try writer.writeByte('0');
11201137 }
11211138 try writer.writeByte('}');
1139 return;
11221140 },
1123 .bytes, .str_lit => |t| {
1124 const bytes = switch (t) {
1125 .bytes => val.castTag(.bytes).?.data,
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 {
1141 .none => switch (val.tag()) {
1142 .empty_struct_value, .empty_array => {
1143 const ai = ty.arrayInfo(mod);
11781144 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 }
11851145 if (ai.sentinel) |s| {
1186 if (index != 0) try writer.writeByte(',');
11871146 try dg.renderValue(writer, ai.elem_type, s, initializer_type);
1147 } else {
1148 try writer.writeByte('0');
11881149 }
11891150 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 => {},
11911169 },
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('}');
11921224 }
11931225 },
11941226 .Bool => {
......@@ -1201,7 +1233,7 @@ pub const DeclGen = struct {
12011233 .Optional => {
12021234 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);
12051237 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))
12061238 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
77657797 if (lowersToArray(ret_ty, mod)) {
77667798 buffer.names = [1][]const u8{"array"};
77677799 buffer.types = [1]Type{ret_ty};
7768 buffer.values = [1]Value{Value.initTag(.unreachable_value)};
7800 buffer.values = [1]Value{Value.@"unreachable"};
77697801 buffer.payload = .{ .data = .{
77707802 .names = &buffer.names,
77717803 .types = &buffer.types,
src/codegen/llvm.zig+63-56
......@@ -2028,7 +2028,7 @@ pub const Object = struct {
20282028
20292029 for (tuple.types, 0..) |field_ty, i| {
20302030 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
20332033 const field_size = field_ty.abiSize(mod);
20342034 const field_align = field_ty.abiAlignment(mod);
......@@ -2498,7 +2498,7 @@ pub const DeclGen = struct {
24982498 global.setGlobalConstant(.True);
24992499 break :init_val decl.val;
25002500 };
2501 if (init_val.tag() != .unreachable_value) {
2501 if (init_val.ip_index != .unreachable_value) {
25022502 const llvm_init = try dg.lowerValue(.{ .ty = decl.ty, .val = init_val });
25032503 if (global.globalGetValueType() == llvm_init.typeOf()) {
25042504 global.setInitializer(llvm_init);
......@@ -2954,7 +2954,7 @@ pub const DeclGen = struct {
29542954
29552955 for (tuple.types, 0..) |field_ty, i| {
29562956 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
29592959 const field_align = field_ty.abiAlignment(mod);
29602960 big_align = @max(big_align, field_align);
......@@ -3359,58 +3359,65 @@ pub const DeclGen = struct {
33593359 else => unreachable,
33603360 }
33613361 },
3362 .Pointer => switch (tv.val.tag()) {
3363 .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl_index),
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 => {
3362 .Pointer => switch (tv.val.ip_index) {
3363 .null_value => {
34043364 const llvm_type = try dg.lowerType(tv.ty);
34053365 return llvm_type.constNull();
34063366 },
3407 .opt_payload => {
3408 const payload = tv.val.castTag(.opt_payload).?.data;
3409 return dg.lowerParentPtr(payload, tv.ty.ptrInfo(mod).bit_offset % 8 == 0);
3367 .none => switch (tv.val.tag()) {
3368 .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl_index),
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 }),
34103419 },
3411 else => |tag| return dg.todo("implement const of pointer type '{}' ({})", .{
3412 tv.ty.fmtDebug(), tag,
3413 }),
3420 else => unreachable,
34143421 },
34153422 .Array => switch (tv.val.tag()) {
34163423 .bytes => {
......@@ -3555,7 +3562,7 @@ pub const DeclGen = struct {
35553562 var fields_buf: [3]*llvm.Value = undefined;
35563563 fields_buf[0] = try dg.lowerValue(.{
35573564 .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,
35593566 });
35603567 fields_buf[1] = non_null_bit;
35613568 if (llvm_field_count > 2) {
......@@ -3606,7 +3613,7 @@ pub const DeclGen = struct {
36063613 });
36073614 const llvm_payload_value = try dg.lowerValue(.{
36083615 .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,
36103617 });
36113618 var fields_buf: [3]*llvm.Value = undefined;
36123619
......@@ -3645,7 +3652,7 @@ pub const DeclGen = struct {
36453652 var need_unnamed = false;
36463653
36473654 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;
36493656 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
36503657
36513658 const field_align = field_ty.abiAlignment(mod);
......@@ -10501,7 +10508,7 @@ fn llvmFieldIndex(
1050110508 const tuple = ty.tupleFields();
1050210509 var llvm_field_index: c_uint = 0;
1050310510 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
1050610513 const field_align = field_ty.abiAlignment(mod);
1050710514 big_align = @max(big_align, field_align);
......@@ -11117,7 +11124,7 @@ fn isByRef(ty: Type, mod: *const Module) bool {
1111711124 const tuple = ty.tupleFields();
1111811125 var count: usize = 0;
1111911126 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
1112211129 count += 1;
1112311130 if (count > max_fields_byval) return true;
src/codegen/spirv.zig+6-5
......@@ -674,7 +674,7 @@ pub const DeclGen = struct {
674674 try self.lower(ptr_ty, slice.ptr);
675675 try self.addInt(Type.usize, slice.len);
676676 },
677 .null_value, .zero => try self.addNullPtr(try dg.resolveType(ty, .indirect)),
677 .zero => try self.addNullPtr(try dg.resolveType(ty, .indirect)),
678678 .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => {
679679 try self.addInt(Type.usize, val);
680680 },
......@@ -813,7 +813,8 @@ pub const DeclGen = struct {
813813 const error_size = Type.anyerror.abiAlignment(mod);
814814 const ty_size = ty.abiSize(mod);
815815 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
818819 if (eu_layout.error_first) {
819820 try self.lower(Type.anyerror, error_val);
......@@ -1021,7 +1022,7 @@ pub const DeclGen = struct {
10211022 return try self.constant(Type.anyerror, error_val, repr);
10221023 }
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
10261027 var members: [2]IdRef = undefined;
10271028 if (eu_layout.error_first) {
......@@ -1292,7 +1293,7 @@ pub const DeclGen = struct {
12921293 var member_index: usize = 0;
12931294 for (tuple.types, 0..) |field_ty, i| {
12941295 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
12971298 member_types[member_index] = try self.resolveType(field_ty, .indirect);
12981299 member_index += 1;
......@@ -1596,7 +1597,7 @@ pub const DeclGen = struct {
15961597 else
15971598 decl.val;
15981599
1599 if (init_val.tag() == .unreachable_value) {
1600 if (init_val.ip_index == .unreachable_value) {
16001601 return self.todo("importing extern variables", .{});
16011602 }
16021603
src/type.zig+29-29
......@@ -533,14 +533,14 @@ pub const Type = struct {
533533 for (a_tuple.values, 0..) |a_val, i| {
534534 const ty = a_tuple.types[i];
535535 const b_val = b_tuple.values[i];
536 if (a_val.tag() == .unreachable_value) {
537 if (b_val.tag() == .unreachable_value) {
536 if (a_val.ip_index == .unreachable_value) {
537 if (b_val.ip_index == .unreachable_value) {
538538 continue;
539539 } else {
540540 return false;
541541 }
542542 } else {
543 if (b_val.tag() == .unreachable_value) {
543 if (b_val.ip_index == .unreachable_value) {
544544 return false;
545545 } else {
546546 if (!Value.eql(a_val, b_val, ty, mod)) return false;
......@@ -569,14 +569,14 @@ pub const Type = struct {
569569 for (a_struct_obj.values, 0..) |a_val, i| {
570570 const ty = a_struct_obj.types[i];
571571 const b_val = b_struct_obj.values[i];
572 if (a_val.tag() == .unreachable_value) {
573 if (b_val.tag() == .unreachable_value) {
572 if (a_val.ip_index == .unreachable_value) {
573 if (b_val.ip_index == .unreachable_value) {
574574 continue;
575575 } else {
576576 return false;
577577 }
578578 } else {
579 if (b_val.tag() == .unreachable_value) {
579 if (b_val.ip_index == .unreachable_value) {
580580 return false;
581581 } else {
582582 if (!Value.eql(a_val, b_val, ty, mod)) return false;
......@@ -750,7 +750,7 @@ pub const Type = struct {
750750 for (tuple.types, 0..) |field_ty, i| {
751751 hashWithHasher(field_ty, hasher, mod);
752752 const field_val = tuple.values[i];
753 if (field_val.tag() == .unreachable_value) continue;
753 if (field_val.ip_index == .unreachable_value) continue;
754754 field_val.hash(field_ty, hasher, mod);
755755 }
756756 },
......@@ -764,7 +764,7 @@ pub const Type = struct {
764764 const field_val = struct_obj.values[i];
765765 hasher.update(field_name);
766766 hashWithHasher(field_ty, hasher, mod);
767 if (field_val.tag() == .unreachable_value) continue;
767 if (field_val.ip_index == .unreachable_value) continue;
768768 field_val.hash(field_ty, hasher, mod);
769769 }
770770 },
......@@ -1139,11 +1139,11 @@ pub const Type = struct {
11391139 for (tuple.types, 0..) |field_ty, i| {
11401140 if (i != 0) try writer.writeAll(", ");
11411141 const val = tuple.values[i];
1142 if (val.tag() != .unreachable_value) {
1142 if (val.ip_index != .unreachable_value) {
11431143 try writer.writeAll("comptime ");
11441144 }
11451145 try field_ty.dump("", .{}, writer);
1146 if (val.tag() != .unreachable_value) {
1146 if (val.ip_index != .unreachable_value) {
11471147 try writer.print(" = {}", .{val.fmtDebug()});
11481148 }
11491149 }
......@@ -1156,13 +1156,13 @@ pub const Type = struct {
11561156 for (anon_struct.types, 0..) |field_ty, i| {
11571157 if (i != 0) try writer.writeAll(", ");
11581158 const val = anon_struct.values[i];
1159 if (val.tag() != .unreachable_value) {
1159 if (val.ip_index != .unreachable_value) {
11601160 try writer.writeAll("comptime ");
11611161 }
11621162 try writer.writeAll(anon_struct.names[i]);
11631163 try writer.writeAll(": ");
11641164 try field_ty.dump("", .{}, writer);
1165 if (val.tag() != .unreachable_value) {
1165 if (val.ip_index != .unreachable_value) {
11661166 try writer.print(" = {}", .{val.fmtDebug()});
11671167 }
11681168 }
......@@ -1408,11 +1408,11 @@ pub const Type = struct {
14081408 for (tuple.types, 0..) |field_ty, i| {
14091409 if (i != 0) try writer.writeAll(", ");
14101410 const val = tuple.values[i];
1411 if (val.tag() != .unreachable_value) {
1411 if (val.ip_index != .unreachable_value) {
14121412 try writer.writeAll("comptime ");
14131413 }
14141414 try print(field_ty, writer, mod);
1415 if (val.tag() != .unreachable_value) {
1415 if (val.ip_index != .unreachable_value) {
14161416 try writer.print(" = {}", .{val.fmtValue(field_ty, mod)});
14171417 }
14181418 }
......@@ -1425,7 +1425,7 @@ pub const Type = struct {
14251425 for (anon_struct.types, 0..) |field_ty, i| {
14261426 if (i != 0) try writer.writeAll(", ");
14271427 const val = anon_struct.values[i];
1428 if (val.tag() != .unreachable_value) {
1428 if (val.ip_index != .unreachable_value) {
14291429 try writer.writeAll("comptime ");
14301430 }
14311431 try writer.writeAll(anon_struct.names[i]);
......@@ -1433,7 +1433,7 @@ pub const Type = struct {
14331433
14341434 try print(field_ty, writer, mod);
14351435
1436 if (val.tag() != .unreachable_value) {
1436 if (val.ip_index != .unreachable_value) {
14371437 try writer.print(" = {}", .{val.fmtValue(field_ty, mod)});
14381438 }
14391439 }
......@@ -1770,7 +1770,7 @@ pub const Type = struct {
17701770 const tuple = ty.tupleFields();
17711771 for (tuple.types, 0..) |field_ty, i| {
17721772 const val = tuple.values[i];
1773 if (val.tag() != .unreachable_value) continue; // comptime field
1773 if (val.ip_index != .unreachable_value) continue; // comptime field
17741774 if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true;
17751775 }
17761776 return false;
......@@ -2283,7 +2283,7 @@ pub const Type = struct {
22832283 var big_align: u32 = 0;
22842284 for (tuple.types, 0..) |field_ty, i| {
22852285 const val = tuple.values[i];
2286 if (val.tag() != .unreachable_value) continue; // comptime field
2286 if (val.ip_index != .unreachable_value) continue; // comptime field
22872287 if (!(field_ty.hasRuntimeBits(mod))) continue;
22882288
22892289 switch (try field_ty.abiAlignmentAdvanced(mod, strat)) {
......@@ -3845,7 +3845,7 @@ pub const Type = struct {
38453845 => return null,
38463846
38473847 .void => return Value.void,
3848 .noreturn => return Value.initTag(.unreachable_value),
3848 .noreturn => return Value.@"unreachable",
38493849 .null => return Value.null,
38503850 .undefined => return Value.undef,
38513851
......@@ -3896,7 +3896,7 @@ pub const Type = struct {
38963896 .tuple, .anon_struct => {
38973897 const tuple = ty.tupleFields();
38983898 for (tuple.values, 0..) |val, i| {
3899 const is_comptime = val.tag() != .unreachable_value;
3899 const is_comptime = val.ip_index != .unreachable_value;
39003900 if (is_comptime) continue;
39013901 if (tuple.types[i].onePossibleValue(mod) != null) continue;
39023902 return null;
......@@ -3919,7 +3919,7 @@ pub const Type = struct {
39193919 return null;
39203920 }
39213921 switch (enum_full.fields.count()) {
3922 0 => return Value.initTag(.unreachable_value),
3922 0 => return Value.@"unreachable",
39233923 1 => if (enum_full.values.count() == 0) {
39243924 return Value.zero; // auto-numbered
39253925 } else {
......@@ -3931,7 +3931,7 @@ pub const Type = struct {
39313931 .enum_simple => {
39323932 const enum_simple = ty.castTag(.enum_simple).?.data;
39333933 switch (enum_simple.fields.count()) {
3934 0 => return Value.initTag(.unreachable_value),
3934 0 => return Value.@"unreachable",
39353935 1 => return Value.zero,
39363936 else => return null,
39373937 }
......@@ -3947,7 +3947,7 @@ pub const Type = struct {
39473947 .@"union", .union_safety_tagged, .union_tagged => {
39483948 const union_obj = ty.cast(Payload.Union).?.data;
39493949 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";
39513951 const only_field = union_obj.fields.values()[0];
39523952 const val_val = only_field.ty.onePossibleValue(mod) orelse return null;
39533953 _ = tag_val;
......@@ -4075,7 +4075,7 @@ pub const Type = struct {
40754075 .tuple, .anon_struct => {
40764076 const tuple = ty.tupleFields();
40774077 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;
40794079 if (!have_comptime_val and field_ty.comptimeOnly(mod)) return true;
40804080 }
40814081 return false;
......@@ -4514,7 +4514,7 @@ pub const Type = struct {
45144514 .tuple => {
45154515 const tuple = ty.castTag(.tuple).?.data;
45164516 const val = tuple.values[index];
4517 if (val.tag() == .unreachable_value) {
4517 if (val.ip_index == .unreachable_value) {
45184518 return tuple.types[index].onePossibleValue(mod);
45194519 } else {
45204520 return val;
......@@ -4523,7 +4523,7 @@ pub const Type = struct {
45234523 .anon_struct => {
45244524 const anon_struct = ty.castTag(.anon_struct).?.data;
45254525 const val = anon_struct.values[index];
4526 if (val.tag() == .unreachable_value) {
4526 if (val.ip_index == .unreachable_value) {
45274527 return anon_struct.types[index].onePossibleValue(mod);
45284528 } else {
45294529 return val;
......@@ -4544,12 +4544,12 @@ pub const Type = struct {
45444544 .tuple => {
45454545 const tuple = ty.castTag(.tuple).?.data;
45464546 const val = tuple.values[index];
4547 return val.tag() != .unreachable_value;
4547 return val.ip_index != .unreachable_value;
45484548 },
45494549 .anon_struct => {
45504550 const anon_struct = ty.castTag(.anon_struct).?.data;
45514551 const val = anon_struct.values[index];
4552 return val.tag() != .unreachable_value;
4552 return val.ip_index != .unreachable_value;
45534553 },
45544554 else => unreachable,
45554555 }
......@@ -4647,7 +4647,7 @@ pub const Type = struct {
46474647
46484648 for (tuple.types, 0..) |field_ty, i| {
46494649 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)) {
46514651 // comptime field
46524652 if (i == index) return offset;
46534653 continue;
src/value.zig+254-240
......@@ -33,13 +33,10 @@ pub const Value = struct {
3333 // Keep in sync with tools/stage2_pretty_printers_common.py
3434 pub const Tag = enum(usize) {
3535 // The first section of this enum are tags that require no payload.
36 undef,
3736 zero,
3837 one,
39 unreachable_value,
4038 /// The only possible value for a particular type, which is stored externally.
4139 the_only_possible_value,
42 null_value,
4340
4441 empty_struct_value,
4542 empty_array, // See last_no_payload_tag below.
......@@ -132,14 +129,11 @@ pub const Value = struct {
132129
133130 pub fn Type(comptime t: Tag) type {
134131 return switch (t) {
135 .undef,
136132 .zero,
137133 .one,
138 .unreachable_value,
139134 .the_only_possible_value,
140135 .empty_struct_value,
141136 .empty_array,
142 .null_value,
143137 => @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"),
144138
145139 .int_big_positive,
......@@ -287,13 +281,10 @@ pub const Value = struct {
287281 .legacy = .{ .tag_if_small_enough = self.legacy.tag_if_small_enough },
288282 };
289283 } else switch (self.legacy.ptr_otherwise.tag) {
290 .undef,
291284 .zero,
292285 .one,
293 .unreachable_value,
294286 .the_only_possible_value,
295287 .empty_array,
296 .null_value,
297288 .empty_struct_value,
298289 => unreachable,
299290
......@@ -522,7 +513,7 @@ pub const Value = struct {
522513 ) !void {
523514 comptime assert(fmt.len == 0);
524515 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});
526517 return;
527518 }
528519 var val = start_val;
......@@ -534,11 +525,8 @@ pub const Value = struct {
534525 .@"union" => {
535526 return out_stream.writeAll("(union value)");
536527 },
537 .null_value => return out_stream.writeAll("null"),
538 .undef => return out_stream.writeAll("undefined"),
539528 .zero => return out_stream.writeAll("0"),
540529 .one => return out_stream.writeAll("1"),
541 .unreachable_value => return out_stream.writeAll("unreachable"),
542530 .the_only_possible_value => return out_stream.writeAll("(the only possible value)"),
543531 .ty => return val.castTag(.ty).?.data.dump("", options, out_stream),
544532 .lazy_align => {
......@@ -811,8 +799,9 @@ pub const Value = struct {
811799 switch (val.ip_index) {
812800 .bool_false => return BigIntMutable.init(&space.limbs, 0).toConst(),
813801 .bool_true => return BigIntMutable.init(&space.limbs, 1).toConst(),
802 .undef => unreachable,
803 .null_value => return BigIntMutable.init(&space.limbs, 0).toConst(),
814804 .none => switch (val.tag()) {
815 .null_value,
816805 .zero,
817806 .the_only_possible_value, // i0, u0
818807 => return BigIntMutable.init(&space.limbs, 0).toConst(),
......@@ -832,8 +821,6 @@ pub const Value = struct {
832821 .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt(),
833822 .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt(),
834823
835 .undef => unreachable,
836
837824 .lazy_align => {
838825 const ty = val.castTag(.lazy_align).?.data;
839826 if (opt_sema) |sema| {
......@@ -880,6 +867,7 @@ pub const Value = struct {
880867 switch (val.ip_index) {
881868 .bool_false => return 0,
882869 .bool_true => return 1,
870 .undef => unreachable,
883871 .none => switch (val.tag()) {
884872 .zero,
885873 .the_only_possible_value, // i0, u0
......@@ -892,8 +880,6 @@ pub const Value = struct {
892880 .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt().to(u64) catch null,
893881 .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt().to(u64) catch null,
894882
895 .undef => unreachable,
896
897883 .lazy_align => {
898884 const ty = val.castTag(.lazy_align).?.data;
899885 if (opt_sema) |sema| {
......@@ -913,9 +899,9 @@ pub const Value = struct {
913899
914900 else => return null,
915901 },
916 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
917 .int => |int| return int.big_int.to(u64) catch null,
918 else => unreachable,
902 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
903 .int => |int| int.big_int.to(u64) catch null,
904 else => null,
919905 },
920906 }
921907 }
......@@ -930,6 +916,7 @@ pub const Value = struct {
930916 switch (val.ip_index) {
931917 .bool_false => return 0,
932918 .bool_true => return 1,
919 .undef => unreachable,
933920 .none => switch (val.tag()) {
934921 .zero,
935922 .the_only_possible_value, // i0, u0
......@@ -951,7 +938,6 @@ pub const Value = struct {
951938 return @intCast(i64, ty.abiSize(mod));
952939 },
953940
954 .undef => unreachable,
955941 else => unreachable,
956942 },
957943 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
......@@ -2032,8 +2018,7 @@ pub const Value = struct {
20322018 const a_tag = a.tag();
20332019 const b_tag = b.tag();
20342020 if (a_tag == b_tag) switch (a_tag) {
2035 .undef => return true,
2036 .null_value, .the_only_possible_value, .empty_struct_value => return true,
2021 .the_only_possible_value, .empty_struct_value => return true,
20372022 .enum_literal => {
20382023 const a_name = a.castTag(.enum_literal).?.data;
20392024 const b_name = b.castTag(.enum_literal).?.data;
......@@ -2162,9 +2147,7 @@ pub const Value = struct {
21622147 return eqlAdvanced(a_union.val, active_field_ty, b_union.val, active_field_ty, mod, opt_sema);
21632148 },
21642149 else => {},
2165 } else if (b_tag == .null_value or b_tag == .@"error") {
2166 return false;
2167 } else if (a_tag == .undef or b_tag == .undef) {
2150 } else if (b_tag == .@"error") {
21682151 return false;
21692152 }
21702153
......@@ -2283,7 +2266,7 @@ pub const Value = struct {
22832266 if (a_nan) return true;
22842267 return a_float == b_float;
22852268 },
2286 .Optional => if (a_tag != .null_value and b_tag == .opt_payload) {
2269 .Optional => if (b_tag == .opt_payload) {
22872270 var sub_pl: Payload.SubValue = .{
22882271 .base = .{ .tag = b.tag() },
22892272 .data = a,
......@@ -2301,7 +2284,7 @@ pub const Value = struct {
23012284 },
23022285 else => {},
23032286 }
2304 if (a_tag == .null_value or a_tag == .@"error") return false;
2287 if (a_tag == .@"error") return false;
23052288 return (try orderAdvanced(a, b, mod, opt_sema)).compare(.eq);
23062289 }
23072290
......@@ -2642,7 +2625,6 @@ pub const Value = struct {
26422625
26432626 .zero,
26442627 .one,
2645 .null_value,
26462628 .int_u64,
26472629 .int_i64,
26482630 .int_big_positive,
......@@ -2717,102 +2699,108 @@ pub const Value = struct {
27172699 arena: ?Allocator,
27182700 buffer: *ElemValueBuffer,
27192701 ) error{OutOfMemory}!Value {
2720 switch (val.tag()) {
2721 // This is the case of accessing an element of an undef array.
2702 switch (val.ip_index) {
27222703 .undef => return Value.undef,
2723 .empty_array => unreachable, // out of bounds array index
2724 .empty_struct_value => unreachable, // out of bounds array index
2704 .none => switch (val.tag()) {
2705 // This is the case of accessing an element of an undef array.
2706 .empty_array => unreachable, // out of bounds array index
2707 .empty_struct_value => unreachable, // out of bounds array index
27252708
2726 .empty_array_sentinel => {
2727 assert(index == 0); // The only valid index for an empty array with sentinel.
2728 return val.castTag(.empty_array_sentinel).?.data;
2729 },
2709 .empty_array_sentinel => {
2710 assert(index == 0); // The only valid index for an empty array with sentinel.
2711 return val.castTag(.empty_array_sentinel).?.data;
2712 },
27302713
2731 .bytes => {
2732 const byte = val.castTag(.bytes).?.data[index];
2733 if (arena) |a| {
2734 return Tag.int_u64.create(a, byte);
2735 } else {
2736 buffer.* = .{
2737 .base = .{ .tag = .int_u64 },
2738 .data = byte,
2739 };
2740 return initPayload(&buffer.base);
2741 }
2742 },
2743 .str_lit => {
2744 const str_lit = val.castTag(.str_lit).?.data;
2745 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
2746 const byte = bytes[index];
2747 if (arena) |a| {
2748 return Tag.int_u64.create(a, byte);
2749 } else {
2750 buffer.* = .{
2751 .base = .{ .tag = .int_u64 },
2752 .data = byte,
2753 };
2754 return initPayload(&buffer.base);
2755 }
2756 },
2714 .bytes => {
2715 const byte = val.castTag(.bytes).?.data[index];
2716 if (arena) |a| {
2717 return Tag.int_u64.create(a, byte);
2718 } else {
2719 buffer.* = .{
2720 .base = .{ .tag = .int_u64 },
2721 .data = byte,
2722 };
2723 return initPayload(&buffer.base);
2724 }
2725 },
2726 .str_lit => {
2727 const str_lit = val.castTag(.str_lit).?.data;
2728 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
2729 const byte = bytes[index];
2730 if (arena) |a| {
2731 return Tag.int_u64.create(a, byte);
2732 } else {
2733 buffer.* = .{
2734 .base = .{ .tag = .int_u64 },
2735 .data = byte,
2736 };
2737 return initPayload(&buffer.base);
2738 }
2739 },
27572740
2758 // No matter the index; all the elements are the same!
2759 .repeated => return val.castTag(.repeated).?.data,
2741 // No matter the index; all the elements are the same!
2742 .repeated => return val.castTag(.repeated).?.data,
27602743
2761 .aggregate => return val.castTag(.aggregate).?.data[index],
2762 .slice => return val.castTag(.slice).?.data.ptr.elemValueAdvanced(mod, index, arena, buffer),
2744 .aggregate => return val.castTag(.aggregate).?.data[index],
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),
2765 .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),
2767 .elem_ptr => {
2768 const data = val.castTag(.elem_ptr).?.data;
2769 return data.array_ptr.elemValueAdvanced(mod, index + data.index, arena, buffer);
2770 },
2771 .field_ptr => {
2772 const data = val.castTag(.field_ptr).?.data;
2773 if (data.container_ptr.pointerDecl()) |decl_index| {
2774 const container_decl = mod.declPtr(decl_index);
2775 const field_type = data.container_ty.structFieldType(data.field_index);
2776 const field_val = container_decl.val.fieldValue(field_type, mod, data.field_index);
2777 return field_val.elemValueAdvanced(mod, index, arena, buffer);
2778 } else unreachable;
2779 },
2747 .decl_ref => return mod.declPtr(val.castTag(.decl_ref).?.data).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),
2749 .comptime_field_ptr => return val.castTag(.comptime_field_ptr).?.data.field_val.elemValueAdvanced(mod, index, arena, buffer),
2750 .elem_ptr => {
2751 const data = val.castTag(.elem_ptr).?.data;
2752 return data.array_ptr.elemValueAdvanced(mod, index + data.index, arena, buffer);
2753 },
2754 .field_ptr => {
2755 const data = val.castTag(.field_ptr).?.data;
2756 if (data.container_ptr.pointerDecl()) |decl_index| {
2757 const container_decl = mod.declPtr(decl_index);
2758 const field_type = data.container_ty.structFieldType(data.field_index);
2759 const field_val = container_decl.val.fieldValue(field_type, mod, data.field_index);
2760 return field_val.elemValueAdvanced(mod, index, arena, buffer);
2761 } else unreachable;
2762 },
27802763
2781 // The child type of arrays which have only one possible value need
2782 // to have only one possible value itself.
2783 .the_only_possible_value => return val,
2764 // The child type of arrays which have only one possible value need
2765 // to have only one possible value itself.
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),
2786 .eu_payload_ptr => return val.castTag(.eu_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),
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),
2789 .eu_payload => return val.castTag(.eu_payload).?.data.elemValueAdvanced(mod, index, arena, buffer),
2771 .opt_payload => return val.castTag(.opt_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 },
27912776 else => unreachable,
27922777 }
27932778 }
27942779
27952780 /// Returns true if a Value is backed by a variable
27962781 pub fn isVariable(val: Value, mod: *Module) bool {
2797 return switch (val.tag()) {
2798 .slice => val.castTag(.slice).?.data.ptr.isVariable(mod),
2799 .comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isVariable(mod),
2800 .elem_ptr => val.castTag(.elem_ptr).?.data.array_ptr.isVariable(mod),
2801 .field_ptr => val.castTag(.field_ptr).?.data.container_ptr.isVariable(mod),
2802 .eu_payload_ptr => val.castTag(.eu_payload_ptr).?.data.container_ptr.isVariable(mod),
2803 .opt_payload_ptr => val.castTag(.opt_payload_ptr).?.data.container_ptr.isVariable(mod),
2804 .decl_ref => {
2805 const decl = mod.declPtr(val.castTag(.decl_ref).?.data);
2806 assert(decl.has_tv);
2807 return decl.val.isVariable(mod);
2808 },
2809 .decl_ref_mut => {
2810 const decl = mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index);
2811 assert(decl.has_tv);
2812 return decl.val.isVariable(mod);
2813 },
2782 return switch (val.ip_index) {
2783 .none => switch (val.tag()) {
2784 .slice => val.castTag(.slice).?.data.ptr.isVariable(mod),
2785 .comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isVariable(mod),
2786 .elem_ptr => val.castTag(.elem_ptr).?.data.array_ptr.isVariable(mod),
2787 .field_ptr => val.castTag(.field_ptr).?.data.container_ptr.isVariable(mod),
2788 .eu_payload_ptr => val.castTag(.eu_payload_ptr).?.data.container_ptr.isVariable(mod),
2789 .opt_payload_ptr => val.castTag(.opt_payload_ptr).?.data.container_ptr.isVariable(mod),
2790 .decl_ref => {
2791 const decl = mod.declPtr(val.castTag(.decl_ref).?.data);
2792 assert(decl.has_tv);
2793 return decl.val.isVariable(mod);
2794 },
2795 .decl_ref_mut => {
2796 const decl = mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index);
2797 assert(decl.has_tv);
2798 return decl.val.isVariable(mod);
2799 },
28142800
2815 .variable => true,
2801 .variable => true,
2802 else => false,
2803 },
28162804 else => false,
28172805 };
28182806 }
......@@ -2878,39 +2866,46 @@ pub const Value = struct {
28782866 }
28792867
28802868 pub fn fieldValue(val: Value, ty: Type, mod: *const Module, index: usize) Value {
2881 switch (val.tag()) {
2882 .aggregate => {
2883 const field_values = val.castTag(.aggregate).?.data;
2884 return field_values[index];
2885 },
2886 .@"union" => {
2887 const payload = val.castTag(.@"union").?.data;
2888 // TODO assert the tag is correct
2889 return payload.val;
2890 },
2869 switch (val.ip_index) {
2870 .undef => return Value.undef,
2871 .none => switch (val.tag()) {
2872 .aggregate => {
2873 const field_values = val.castTag(.aggregate).?.data;
2874 return field_values[index];
2875 },
2876 .@"union" => {
2877 const payload = val.castTag(.@"union").?.data;
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 => {
2895 if (ty.isSimpleTupleOrAnonStruct()) {
2896 const tuple = ty.tupleFields();
2897 return tuple.values[index];
2898 }
2899 if (ty.structFieldValueComptime(mod, index)) |some| {
2900 return some;
2901 }
2902 unreachable;
2903 },
2904 .undef => return Value.undef,
2884 .empty_struct_value => {
2885 if (ty.isSimpleTupleOrAnonStruct()) {
2886 const tuple = ty.tupleFields();
2887 return tuple.values[index];
2888 }
2889 if (ty.structFieldValueComptime(mod, index)) |some| {
2890 return some;
2891 }
2892 unreachable;
2893 },
29052894
2895 else => unreachable,
2896 },
29062897 else => unreachable,
29072898 }
29082899 }
29092900
29102901 pub fn unionTag(val: Value) Value {
2911 switch (val.tag()) {
2912 .undef, .enum_field_index => return val,
2913 .@"union" => return val.castTag(.@"union").?.data.tag,
2902 switch (val.ip_index) {
2903 .undef => return val,
2904 .none => switch (val.tag()) {
2905 .enum_field_index => return val,
2906 .@"union" => return val.castTag(.@"union").?.data.tag,
2907 else => unreachable,
2908 },
29142909 else => unreachable,
29152910 }
29162911 }
......@@ -2946,15 +2941,15 @@ pub const Value = struct {
29462941 });
29472942 }
29482943
2949 pub fn isUndef(self: Value) bool {
2950 return self.tag() == .undef;
2944 pub fn isUndef(val: Value) bool {
2945 return val.ip_index == .undef;
29512946 }
29522947
29532948 /// TODO: check for cases such as array that is not marked undef but all the element
29542949 /// values are marked undef, or struct that is not marked undef but all fields are marked
29552950 /// undef, etc.
2956 pub fn isUndefDeep(self: Value) bool {
2957 return self.isUndef();
2951 pub fn isUndefDeep(val: Value) bool {
2952 return val.isUndef();
29582953 }
29592954
29602955 /// Returns true if any value contained in `self` is undefined.
......@@ -2962,27 +2957,29 @@ pub const Value = struct {
29622957 /// values are marked undef, or struct that is not marked undef but all fields are marked
29632958 /// undef, etc.
29642959 pub fn anyUndef(self: Value, mod: *Module) bool {
2965 switch (self.tag()) {
2966 .slice => {
2967 const payload = self.castTag(.slice).?;
2968 const len = payload.data.len.toUnsignedInt(mod);
2969
2970 var elem_value_buf: ElemValueBuffer = undefined;
2971 var i: usize = 0;
2972 while (i < len) : (i += 1) {
2973 const elem_val = payload.data.ptr.elemValueBuffer(mod, i, &elem_value_buf);
2974 if (elem_val.anyUndef(mod)) return true;
2975 }
2976 },
2960 switch (self.ip_index) {
2961 .undef => return true,
2962 .none => switch (self.tag()) {
2963 .slice => {
2964 const payload = self.castTag(.slice).?;
2965 const len = payload.data.len.toUnsignedInt(mod);
2966
2967 var elem_value_buf: ElemValueBuffer = undefined;
2968 var i: usize = 0;
2969 while (i < len) : (i += 1) {
2970 const elem_val = payload.data.ptr.elemValueBuffer(mod, i, &elem_value_buf);
2971 if (elem_val.anyUndef(mod)) return true;
2972 }
2973 },
29772974
2978 .aggregate => {
2979 const payload = self.castTag(.aggregate).?;
2980 for (payload.data) |val| {
2981 if (val.anyUndef(mod)) return true;
2982 }
2975 .aggregate => {
2976 const payload = self.castTag(.aggregate).?;
2977 for (payload.data) |val| {
2978 if (val.anyUndef(mod)) return true;
2979 }
2980 },
2981 else => {},
29832982 },
2984
2985 .undef => return true,
29862983 else => {},
29872984 }
29882985
......@@ -2992,30 +2989,33 @@ pub const Value = struct {
29922989 /// Asserts the value is not undefined and not unreachable.
29932990 /// Integer value 0 is considered null because of C pointers.
29942991 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,
29962995 .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,
3000 // in which case the value 0 is null and other values are non-null.
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.
30013001
3002 .zero,
3003 .the_only_possible_value,
3004 => true,
3002 .zero,
3003 .the_only_possible_value,
3004 => true,
30053005
3006 .one => false,
3006 .one => false,
30073007
3008 .int_u64,
3009 .int_i64,
3010 .int_big_positive,
3011 .int_big_negative,
3012 => self.orderAgainstZero(mod).compare(.eq),
3008 .int_u64,
3009 .int_i64,
3010 .int_big_positive,
3011 .int_big_negative,
3012 => self.orderAgainstZero(mod).compare(.eq),
30133013
3014 .undef => unreachable,
3015 .unreachable_value => unreachable,
3016 .inferred_alloc => unreachable,
3017 .inferred_alloc_comptime => unreachable,
3014 .inferred_alloc => unreachable,
3015 .inferred_alloc_comptime => unreachable,
30183016
3017 else => false,
3018 },
30193019 else => false,
30203020 };
30213021 }
......@@ -3025,18 +3025,21 @@ pub const Value = struct {
30253025 /// something is an error or not because it works without having to figure out the
30263026 /// string.
30273027 pub fn getError(self: Value) ?[]const u8 {
3028 return switch (self.tag()) {
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"),
3028 return switch (self.ip_index) {
30353029 .undef => unreachable,
30363030 .unreachable_value => unreachable,
3037 .inferred_alloc => unreachable,
3038 .inferred_alloc_comptime => unreachable,
3031 .none => switch (self.tag()) {
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 },
30403043 else => null,
30413044 };
30423045 }
......@@ -3044,13 +3047,16 @@ pub const Value = struct {
30443047 /// Assumes the type is an error union. Returns true if and only if the value is
30453048 /// the error union payload, not an error.
30463049 pub fn errorUnionIsPayload(val: Value) bool {
3047 return switch (val.tag()) {
3048 .eu_payload => true,
3049 else => false,
3050
3050 return switch (val.ip_index) {
30513051 .undef => unreachable,
3052 .inferred_alloc => unreachable,
3053 .inferred_alloc_comptime => unreachable,
3052 .none => switch (val.tag()) {
3053 .eu_payload => true,
3054 else => false,
3055
3056 .inferred_alloc => unreachable,
3057 .inferred_alloc_comptime => unreachable,
3058 },
3059 else => false,
30543060 };
30553061 }
30563062
......@@ -3065,17 +3071,20 @@ pub const Value = struct {
30653071
30663072 /// Valid for all types. Asserts the value is not undefined.
30673073 pub fn isFloat(self: Value) bool {
3068 return switch (self.tag()) {
3074 return switch (self.ip_index) {
30693075 .undef => unreachable,
3070 .inferred_alloc => unreachable,
3071 .inferred_alloc_comptime => unreachable,
3076 .none => switch (self.tag()) {
3077 .inferred_alloc => unreachable,
3078 .inferred_alloc_comptime => unreachable,
30723079
3073 .float_16,
3074 .float_32,
3075 .float_64,
3076 .float_80,
3077 .float_128,
3078 => true,
3080 .float_16,
3081 .float_32,
3082 .float_64,
3083 .float_80,
3084 .float_128,
3085 => true,
3086 else => false,
3087 },
30793088 else => false,
30803089 };
30813090 }
......@@ -3102,40 +3111,44 @@ pub const Value = struct {
31023111
31033112 pub fn intToFloatScalar(val: Value, arena: Allocator, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value {
31043113 const target = mod.getTarget();
3105 switch (val.tag()) {
3106 .undef, .zero, .one => return val,
3107 .the_only_possible_value => return Value.initTag(.zero), // for i0, u0
3108 .int_u64 => {
3109 return intToFloatInner(val.castTag(.int_u64).?.data, arena, float_ty, target);
3110 },
3111 .int_i64 => {
3112 return intToFloatInner(val.castTag(.int_i64).?.data, arena, float_ty, target);
3113 },
3114 .int_big_positive => {
3115 const limbs = val.castTag(.int_big_positive).?.data;
3116 const float = bigIntToFloat(limbs, true);
3117 return floatToValue(float, arena, float_ty, target);
3118 },
3119 .int_big_negative => {
3120 const limbs = val.castTag(.int_big_negative).?.data;
3121 const float = bigIntToFloat(limbs, false);
3122 return floatToValue(float, arena, float_ty, target);
3123 },
3124 .lazy_align => {
3125 const ty = val.castTag(.lazy_align).?.data;
3126 if (opt_sema) |sema| {
3127 return intToFloatInner((try ty.abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar, arena, float_ty, target);
3128 } else {
3129 return intToFloatInner(ty.abiAlignment(mod), arena, float_ty, target);
3130 }
3131 },
3132 .lazy_size => {
3133 const ty = val.castTag(.lazy_size).?.data;
3134 if (opt_sema) |sema| {
3135 return intToFloatInner((try ty.abiSizeAdvanced(mod, .{ .sema = sema })).scalar, arena, float_ty, target);
3136 } else {
3137 return intToFloatInner(ty.abiSize(mod), arena, float_ty, target);
3138 }
3114 switch (val.ip_index) {
3115 .undef => return val,
3116 .none => switch (val.tag()) {
3117 .zero, .one => return val,
3118 .the_only_possible_value => return Value.initTag(.zero), // for i0, u0
3119 .int_u64 => {
3120 return intToFloatInner(val.castTag(.int_u64).?.data, arena, float_ty, target);
3121 },
3122 .int_i64 => {
3123 return intToFloatInner(val.castTag(.int_i64).?.data, arena, float_ty, target);
3124 },
3125 .int_big_positive => {
3126 const limbs = val.castTag(.int_big_positive).?.data;
3127 const float = bigIntToFloat(limbs, true);
3128 return floatToValue(float, arena, float_ty, target);
3129 },
3130 .int_big_negative => {
3131 const limbs = val.castTag(.int_big_negative).?.data;
3132 const float = bigIntToFloat(limbs, false);
3133 return floatToValue(float, arena, float_ty, target);
3134 },
3135 .lazy_align => {
3136 const ty = val.castTag(.lazy_align).?.data;
3137 if (opt_sema) |sema| {
3138 return intToFloatInner((try ty.abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar, arena, float_ty, target);
3139 } else {
3140 return intToFloatInner(ty.abiAlignment(mod), arena, float_ty, target);
3141 }
3142 },
3143 .lazy_size => {
3144 const ty = val.castTag(.lazy_size).?.data;
3145 if (opt_sema) |sema| {
3146 return intToFloatInner((try ty.abiSizeAdvanced(mod, .{ .sema = sema })).scalar, arena, float_ty, target);
3147 } else {
3148 return intToFloatInner(ty.abiSize(mod), arena, float_ty, target);
3149 }
3150 },
3151 else => unreachable,
31393152 },
31403153 else => unreachable,
31413154 }
......@@ -3381,7 +3394,7 @@ pub const Value = struct {
33813394 arena: Allocator,
33823395 mod: *Module,
33833396 ) !Value {
3384 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
3397 if (lhs.isUndef() or rhs.isUndef()) return Value.undef;
33853398
33863399 if (ty.zigTypeTag(mod) == .ComptimeInt) {
33873400 return intMul(lhs, rhs, ty, arena, mod);
......@@ -3492,7 +3505,7 @@ pub const Value = struct {
34923505
34933506 /// operands must be integers; handles undefined.
34943507 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
34973510 const info = ty.intInfo(mod);
34983511
......@@ -3532,7 +3545,7 @@ pub const Value = struct {
35323545
35333546 /// operands must be integers; handles undefined.
35343547 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
35373550 // TODO is this a performance issue? maybe we should try the operation without
35383551 // resorting to BigInt first.
......@@ -3568,7 +3581,7 @@ pub const Value = struct {
35683581
35693582 /// operands must be integers; handles undefined.
35703583 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
35733586 const anded = try bitwiseAnd(lhs, rhs, ty, arena, mod);
35743587
......@@ -3598,7 +3611,7 @@ pub const Value = struct {
35983611
35993612 /// operands must be integers; handles undefined.
36003613 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
36033616 // TODO is this a performance issue? maybe we should try the operation without
36043617 // resorting to BigInt first.
......@@ -3633,7 +3646,7 @@ pub const Value = struct {
36333646
36343647 /// operands must be integers; handles undefined.
36353648 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
36383651 // TODO is this a performance issue? maybe we should try the operation without
36393652 // resorting to BigInt first.
......@@ -5393,11 +5406,12 @@ pub const Value = struct {
53935406 .ip_index = .none,
53945407 .legacy = .{ .ptr_otherwise = &negative_one_payload.base },
53955408 };
5396 pub const undef = initTag(.undef);
5409 pub const undef: Value = .{ .ip_index = .undef, .legacy = undefined };
53975410 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 };
53995412 pub const @"false": Value = .{ .ip_index = .bool_false, .legacy = undefined };
54005413 pub const @"true": Value = .{ .ip_index = .bool_true, .legacy = undefined };
5414 pub const @"unreachable": Value = .{ .ip_index = .unreachable_value, .legacy = undefined };
54015415
54025416 pub const generic_poison: Value = .{ .ip_index = .generic_poison, .legacy = undefined };
54035417 pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type, .legacy = undefined };