| ... | ... | @@ -853,14 +853,24 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void { |
| 853 | 853 | .@"union" => unreachable, |
| 854 | 854 | .@"struct" => switch (agg_ty.containerLayout(zcu)) { |
| 855 | 855 | .auto, .@"extern" => {}, |
| 856 | | .@"packed" => switch (agg_ty.structFieldCount(zcu)) { |
| 857 | | 0 => unreachable, |
| 858 | | // An `aggregate_init` of a packed struct with 1 field is just a fancy bitcast. |
| 859 | | 1 => continue :inst l.replaceInst(inst, .bitcast, .{ .ty_op = .{ |
| 860 | | .ty = .fromType(agg_ty), |
| 861 | | .operand = @enumFromInt(l.air_extra.items[ty_pl.payload]), |
| 862 | | } }), |
| 863 | | else => continue :inst l.replaceInst(inst, .block, try l.packedAggregateInitBlockPayload(inst)), |
| 856 | .@"packed" => { |
| 857 | // If any field accounts for the full bit size of the struct, this init |
| 858 | // is just equivalent to a bitcast of that field. This usually means the |
| 859 | // field count is 1, but not always, as there could be zero-bit fields. |
| 860 | const struct_bits = agg_ty.bitSize(zcu); |
| 861 | for (0..agg_ty.structFieldCount(zcu)) |field_index| { |
| 862 | const field_bits = agg_ty.fieldType(field_index, zcu).bitSize(zcu); |
| 863 | if (field_bits == struct_bits) { |
| 864 | // Just bitcast this field. |
| 865 | continue :inst l.replaceInst(inst, .bitcast, .{ .ty_op = .{ |
| 866 | .ty = .fromType(agg_ty), |
| 867 | .operand = @enumFromInt(l.air_extra.items[ty_pl.payload + field_index]), |
| 868 | } }); |
| 869 | } |
| 870 | } |
| 871 | // Otherwise, we will need to use a sequence of bitcasts and shifts to |
| 872 | // combine multiple values' bits. |
| 873 | continue :inst l.replaceInst(inst, .block, try l.packedAggregateInitBlockPayload(inst)); |
| 864 | 874 | }, |
| 865 | 875 | }, |
| 866 | 876 | } |
| ... | ... | @@ -2513,8 +2523,10 @@ fn packedAggregateInitBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Erro |
| 2513 | 2523 | while (field_idx > 0) { |
| 2514 | 2524 | field_idx -= 1; |
| 2515 | 2525 | const field_ty = agg_ty.fieldType(field_idx, zcu); |
| 2516 | | const field_uint_ty = try pt.intType(.unsigned, @intCast(field_ty.bitSize(zcu))); |
| 2517 | | const field_bit_size_ref: Air.Inst.Ref = .fromValue(try pt.intValue(shift_ty, field_ty.bitSize(zcu))); |
| 2526 | const field_bits: u16 = @intCast(field_ty.bitSize(zcu)); |
| 2527 | assert(field_bits < num_bits); |
| 2528 | const field_uint_ty = try pt.intType(.unsigned, field_bits); |
| 2529 | const field_bit_size_ref: Air.Inst.Ref = .fromValue(try pt.intValue(shift_ty, field_bits)); |
| 2518 | 2530 | const field_val: Air.Inst.Ref = @enumFromInt(l.air_extra.items[orig_ty_pl.payload + field_idx]); |
| 2519 | 2531 | |
| 2520 | 2532 | const shifted = main_block.addBinOp(l, .shl_exact, cur_uint, field_bit_size_ref).toRef(); |