@@ -1087,7 +1087,7 @@ fn analyzeBodyInner(
1087
1087
.elem_val_imm => try sema.zirElemValImm(block, inst),
1088
1088
.elem_type => try sema.zirElemType(block, inst),
1089
1089
.indexable_ptr_elem_type => try sema.zirIndexablePtrElemType(block, inst),
1090
- .vector_elem_type => try sema.zirVectorElemType (block, inst),
1090
+ .vec_arr_elem_type => try sema.zirVecArrElemType (block, inst),
1091
1091
.enum_literal => try sema.zirEnumLiteral(block, inst),
1092
1092
.decl_literal => try sema.zirDeclLiteral(block, inst, true),
1093
1093
.decl_literal_no_coerce => try sema.zirDeclLiteral(block, inst, false),
@@ -2046,7 +2046,7 @@ fn genericPoisonReason(sema: *Sema, block: *Block, ref: Zir.Inst.Ref) GenericPoi
2046
2046
const bin = sema.code.instructions.items(.data)[@intFromEnum(inst)].bin;
2047
2047
cur = bin.lhs;
2048
2048
},
2049
- .indexable_ptr_elem_type, .vector_elem_type => {
2049
+ .indexable_ptr_elem_type, .vec_arr_elem_type => {
2050
2050
const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
2051
2051
cur = un_node.operand;
2052
2052
},
@@ -8603,7 +8603,7 @@ fn zirIndexablePtrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
8603
8603
return Air.internedToRef(elem_ty.toIntern());
8604
8604
}
8605
8605
8606
- fn zirVectorElemType (sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
8606
+ fn zirVecArrElemType (sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
8607
8607
const pt = sema.pt;
8608
8608
const zcu = pt.zcu;
8609
8609
const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
@@ -8615,8 +8615,9 @@ fn zirVectorElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
8615
8615
error.GenericPoison => return .generic_poison_type,
8616
8616
else => |e| return e,
8617
8617
};
8618
- if (!vec_ty.isVector(zcu)) {
8619
- return sema.fail(block, block.nodeOffset(un_node.src_node), "expected vector type, found '{}'", .{vec_ty.fmt(pt)});
8618
+ switch (vec_ty.zigTypeTag(zcu)) {
8619
+ .array, .vector => {},
8620
+ else => return sema.fail(block, block.nodeOffset(un_node.src_node), "expected vector type, found '{}'", .{vec_ty.fmt(pt)}),
8620
8621
}
8621
8622
return Air.internedToRef(vec_ty.childType(zcu).toIntern());
8622
8623
}
@@ -24804,26 +24805,65 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
24804
24805
const scalar_src = block.builtinCallArgSrc(inst_data.src_node, 0);
24805
24806
const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@splat");
24806
24807
24807
- if (!dest_ty.isVector(zcu)) return sema.fail(block, src, "expected vector type, found '{}'", .{dest_ty.fmt(pt)});
24808
+ switch (dest_ty.zigTypeTag(zcu)) {
24809
+ .array, .vector => {},
24810
+ else => return sema.fail(block, src, "expected array or vector type, found '{}'", .{dest_ty.fmt(pt)}),
24811
+ }
24808
24812
24809
24813
if (!dest_ty.hasRuntimeBits(zcu)) {
24810
24814
const empty_aggregate = try pt.intern(.{ .aggregate = .{
24811
24815
.ty = dest_ty.toIntern(),
24812
- .storage = .{ .elems = &[_]InternPool.Index {} },
24816
+ .storage = .{ .elems = &. {} },
24813
24817
} });
24814
24818
return Air.internedToRef(empty_aggregate);
24815
24819
}
24816
24820
24821
+ const maybe_sentinel = dest_ty.sentinel(zcu);
24822
+
24817
24823
const operand = try sema.resolveInst(extra.rhs);
24818
24824
const scalar_ty = dest_ty.childType(zcu);
24819
24825
const scalar = try sema.coerce(block, scalar_ty, operand, scalar_src);
24820
24826
if (try sema.resolveValue(scalar)) |scalar_val| {
24821
- if (scalar_val.isUndef(zcu)) return pt.undefRef(dest_ty);
24822
- return Air.internedToRef((try sema.splat(dest_ty, scalar_val)).toIntern());
24827
+ if (scalar_val.isUndef(zcu) and maybe_sentinel == null) {
24828
+ return pt.undefRef(dest_ty);
24829
+ }
24830
+ // TODO: I didn't want to put `.aggregate` on a separate line here; `zig fmt` bugs have forced my hand
24831
+ return Air.internedToRef(try pt.intern(.{
24832
+ .aggregate = .{
24833
+ .ty = dest_ty.toIntern(),
24834
+ .storage = s: {
24835
+ full: {
24836
+ if (dest_ty.zigTypeTag(zcu) == .vector) break :full;
24837
+ const sentinel = maybe_sentinel orelse break :full;
24838
+ if (sentinel.toIntern() == scalar_val.toIntern()) break :full;
24839
+ const len = dest_ty.arrayLen(zcu);
24840
+ if (len == 0) break :full;
24841
+ // This is a array with non-zero length and a sentinel which does not match the element.
24842
+ // We have to use the full `elems` representation.
24843
+ const elems = try sema.arena.alloc(InternPool.Index, len + 1);
24844
+ @memset(elems[0..len], scalar_val.toIntern());
24845
+ elems[len] = sentinel.toIntern();
24846
+ break :s .{ .elems = elems };
24847
+ }
24848
+ break :s .{ .repeated_elem = scalar_val.toIntern() };
24849
+ },
24850
+ },
24851
+ }));
24823
24852
}
24824
24853
24825
24854
try sema.requireRuntimeBlock(block, src, scalar_src);
24826
- return block.addTyOp(.splat, dest_ty, scalar);
24855
+
24856
+ switch (dest_ty.zigTypeTag(zcu)) {
24857
+ .array => {
24858
+ const len = dest_ty.arrayLen(zcu);
24859
+ const elems = try sema.arena.alloc(Air.Inst.Ref, len + @intFromBool(maybe_sentinel != null));
24860
+ @memset(elems[0..len], scalar);
24861
+ if (maybe_sentinel) |s| elems[len] = Air.internedToRef(s.toIntern());
24862
+ return block.addAggregateInit(dest_ty, elems);
24863
+ },
24864
+ .vector => return block.addTyOp(.splat, dest_ty, scalar),
24865
+ else => unreachable,
24866
+ }
24827
24867
}
24828
24868
24829
24869
fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
0 commit comments