@@ -10789,23 +10789,24 @@ const SwitchProngAnalysis = struct {
10789
10789
const first_field_index: u32 = mod.unionTagFieldIndex(union_obj, first_item_val).?;
10790
10790
const first_field_ty = union_obj.field_types.get(ip)[first_field_index].toType();
10791
10791
10792
- const field_tys = try sema.arena.alloc(Type , case_vals.len);
10793
- for (case_vals, field_tys ) |item, *field_ty | {
10792
+ const field_indices = try sema.arena.alloc(u32 , case_vals.len);
10793
+ for (case_vals, field_indices ) |item, *field_idx | {
10794
10794
const item_val = sema.resolveConstDefinedValue(block, .unneeded, item, undefined) catch unreachable;
10795
- const field_idx = mod.unionTagFieldIndex(union_obj, item_val).?;
10796
- field_ty.* = union_obj.field_types.get(ip)[field_idx].toType();
10795
+ field_idx.* = mod.unionTagFieldIndex(union_obj, item_val).?;
10797
10796
}
10798
10797
10799
10798
// Fast path: if all the operands are the same type already, we don't need to hit
10800
10799
// PTR! This will also allow us to emit simpler code.
10801
- const same_types = for (field_tys[1..]) |field_ty| {
10802
- if (!field_ty.eql(field_tys[0], sema.mod)) break false;
10800
+ const same_types = for (field_indices[1..]) |field_idx| {
10801
+ const field_ty = union_obj.field_types.get(ip)[field_idx].toType();
10802
+ if (!field_ty.eql(first_field_ty, sema.mod)) break false;
10803
10803
} else true;
10804
10804
10805
- const capture_ty = if (same_types) field_tys[0] else capture_ty: {
10805
+ const capture_ty = if (same_types) first_field_ty else capture_ty: {
10806
10806
// We need values to run PTR on, so make a bunch of undef constants.
10807
10807
const dummy_captures = try sema.arena.alloc(Air.Inst.Ref, case_vals.len);
10808
- for (dummy_captures, field_tys) |*dummy, field_ty| {
10808
+ for (dummy_captures, field_indices) |*dummy, field_idx| {
10809
+ const field_ty = union_obj.field_types.get(ip)[field_idx].toType();
10809
10810
dummy.* = try mod.undefRef(field_ty);
10810
10811
}
10811
10812
@@ -10852,7 +10853,8 @@ const SwitchProngAnalysis = struct {
10852
10853
// By-ref captures of hetereogeneous types are only allowed if each field
10853
10854
// pointer type is in-memory coercible to the capture pointer type.
10854
10855
if (!same_types) {
10855
- for (field_tys, 0..) |field_ty, i| {
10856
+ for (field_indices, 0..) |field_idx, i| {
10857
+ const field_ty = union_obj.field_types.get(ip)[field_idx].toType();
10856
10858
const field_ptr_ty = try sema.ptrType(.{
10857
10859
.child = field_ty.toIntern(),
10858
10860
.flags = .{
@@ -10915,7 +10917,8 @@ const SwitchProngAnalysis = struct {
10915
10917
// We may have to emit a switch block which coerces the operand to the capture type.
10916
10918
// If we can, try to avoid that using in-memory coercions.
10917
10919
const first_non_imc = in_mem: {
10918
- for (field_tys, 0..) |field_ty, i| {
10920
+ for (field_indices, 0..) |field_idx, i| {
10921
+ const field_ty = union_obj.field_types.get(ip)[field_idx].toType();
10919
10922
if (.ok != try sema.coerceInMemoryAllowed(block, capture_ty, field_ty, false, sema.mod.getTarget(), .unneeded, .unneeded)) {
10920
10923
break :in_mem i;
10921
10924
}
@@ -10933,11 +10936,12 @@ const SwitchProngAnalysis = struct {
10933
10936
// be several, and we can squash all of these cases into the same switch prong using
10934
10937
// a simple bitcast. We'll make this the 'else' prong.
10935
10938
10936
- var in_mem_coercible = try std.DynamicBitSet.initFull(sema.arena, field_tys .len);
10939
+ var in_mem_coercible = try std.DynamicBitSet.initFull(sema.arena, field_indices .len);
10937
10940
in_mem_coercible.unset(first_non_imc);
10938
10941
{
10939
10942
const next = first_non_imc + 1;
10940
- for (field_tys[next..], next..) |field_ty, i| {
10943
+ for (field_indices[next..], next..) |field_idx, i| {
10944
+ const field_ty = union_obj.field_types.get(ip)[field_idx].toType();
10941
10945
if (.ok != try sema.coerceInMemoryAllowed(block, capture_ty, field_ty, false, sema.mod.getTarget(), .unneeded, .unneeded)) {
10942
10946
in_mem_coercible.unset(i);
10943
10947
}
@@ -10954,7 +10958,7 @@ const SwitchProngAnalysis = struct {
10954
10958
},
10955
10959
});
10956
10960
10957
- const prong_count = field_tys .len - in_mem_coercible.count();
10961
+ const prong_count = field_indices .len - in_mem_coercible.count();
10958
10962
10959
10963
const estimated_extra = prong_count * 6; // 2 for Case, 1 item, probably 3 insts
10960
10964
var cases_extra = try std.ArrayList(u32).initCapacity(sema.gpa, estimated_extra);
@@ -10967,7 +10971,9 @@ const SwitchProngAnalysis = struct {
10967
10971
var coerce_block = block.makeSubBlock();
10968
10972
defer coerce_block.instructions.deinit(sema.gpa);
10969
10973
10970
- const uncoerced = try coerce_block.addStructFieldVal(spa.operand, @intCast(idx), field_tys[idx]);
10974
+ const field_idx = field_indices[idx];
10975
+ const field_ty = union_obj.field_types.get(ip)[field_idx].toType();
10976
+ const uncoerced = try coerce_block.addStructFieldVal(spa.operand, field_idx, field_ty);
10971
10977
const coerced = sema.coerce(&coerce_block, capture_ty, uncoerced, .unneeded) catch |err| switch (err) {
10972
10978
error.NeededSourceLocation => {
10973
10979
const multi_idx = raw_capture_src.multi_capture;
@@ -10993,8 +10999,10 @@ const SwitchProngAnalysis = struct {
10993
10999
var coerce_block = block.makeSubBlock();
10994
11000
defer coerce_block.instructions.deinit(sema.gpa);
10995
11001
10996
- const first_imc = in_mem_coercible.findFirstSet().?;
10997
- const uncoerced = try coerce_block.addStructFieldVal(spa.operand, @intCast(first_imc), field_tys[first_imc]);
11002
+ const first_imc_item_idx = in_mem_coercible.findFirstSet().?;
11003
+ const first_imc_field_idx = field_indices[first_imc_item_idx];
11004
+ const first_imc_field_ty = union_obj.field_types.get(ip)[first_imc_field_idx].toType();
11005
+ const uncoerced = try coerce_block.addStructFieldVal(spa.operand, first_imc_field_idx, first_imc_field_ty);
10998
11006
const coerced = try coerce_block.addBitCast(capture_ty, uncoerced);
10999
11007
_ = try coerce_block.addBr(capture_block_inst, coerced);
11000
11008
0 commit comments