Commit 76335bc7ba
Changed files (6)
test
behavior
src/AstGen.zig
@@ -1352,15 +1352,14 @@ fn arrayInitExprRlPtr(
defer gpa.free(elem_ptr_list);
for (elements) |elem_init, i| {
- const index_inst = try gz.addInt(i);
- const elem_ptr = try gz.addPlNode(.elem_ptr_node, elem_init, Zir.Inst.Bin{
- .lhs = result_ptr,
- .rhs = index_inst,
+ const elem_ptr = try gz.addPlNode(.elem_ptr_imm, elem_init, Zir.Inst.ElemPtrImm{
+ .ptr = result_ptr,
+ .index = @intCast(u32, i),
});
elem_ptr_list[i] = refToIndex(elem_ptr).?;
_ = try expr(gz, scope, .{ .ptr = elem_ptr }, elem_init);
}
- _ = try gz.addPlNode(.validate_array_init_ptr, node, Zir.Inst.Block{
+ _ = try gz.addPlNode(.validate_array_init, node, Zir.Inst.Block{
.body_len = @intCast(u32, elem_ptr_list.len),
});
try astgen.extra.appendSlice(gpa, elem_ptr_list);
@@ -1539,7 +1538,7 @@ fn structInitExprRlPtrInner(
field_ptr_list[i] = refToIndex(field_ptr).?;
_ = try expr(gz, scope, .{ .ptr = field_ptr }, field_init);
}
- _ = try gz.addPlNode(.validate_struct_init_ptr, node, Zir.Inst.Block{
+ _ = try gz.addPlNode(.validate_struct_init, node, Zir.Inst.Block{
.body_len = @intCast(u32, field_ptr_list.len),
});
try astgen.extra.appendSlice(gpa, field_ptr_list);
@@ -2040,6 +2039,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
.elem_ptr,
.elem_val,
.elem_ptr_node,
+ .elem_ptr_imm,
.elem_val_node,
.field_ptr,
.field_val,
@@ -2246,8 +2246,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
.store_to_block_ptr,
.store_to_inferred_ptr,
.resolve_inferred_alloc,
- .validate_struct_init_ptr,
- .validate_array_init_ptr,
+ .validate_struct_init,
+ .validate_array_init,
.set_align_stack,
.set_cold,
.set_float_mode,
src/print_zir.zig
@@ -355,6 +355,8 @@ const Writer = struct {
.elem_val_node,
=> try self.writePlNodeBin(stream, inst),
+ .elem_ptr_imm => try self.writeElemPtrImm(stream, inst),
+
.@"export" => try self.writePlNodeExport(stream, inst),
.export_value => try self.writePlNodeExportValue(stream, inst),
@@ -364,8 +366,8 @@ const Writer = struct {
.block_inline,
.suspend_block,
.loop,
- .validate_struct_init_ptr,
- .validate_array_init_ptr,
+ .validate_struct_init,
+ .validate_array_init,
.c_import,
=> try self.writePlNodeBlock(stream, inst),
@@ -809,6 +811,15 @@ const Writer = struct {
try self.writeSrc(stream, inst_data.src());
}
+ fn writeElemPtrImm(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
+ const inst_data = self.code.instructions.items(.data)[inst].pl_node;
+ const extra = self.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;
+
+ try self.writeInstRef(stream, extra.ptr);
+ try stream.print(", {d}) ", .{extra.index});
+ try self.writeSrc(stream, inst_data.src());
+ }
+
fn writePlNodeExport(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
const extra = self.code.extraData(Zir.Inst.Export, inst_data.payload_index).data;
src/Sema.zig
@@ -479,6 +479,7 @@ pub fn analyzeBody(
.load => try sema.zirLoad(block, inst),
.elem_ptr => try sema.zirElemPtr(block, inst),
.elem_ptr_node => try sema.zirElemPtrNode(block, inst),
+ .elem_ptr_imm => try sema.zirElemPtrImm(block, inst),
.elem_val => try sema.zirElemVal(block, inst),
.elem_val_node => try sema.zirElemValNode(block, inst),
.elem_type => try sema.zirElemType(block, inst),
@@ -741,13 +742,13 @@ pub fn analyzeBody(
i += 1;
continue;
},
- .validate_struct_init_ptr => {
- try sema.zirValidateStructInitPtr(block, inst);
+ .validate_struct_init => {
+ try sema.zirValidateStructInit(block, inst);
i += 1;
continue;
},
- .validate_array_init_ptr => {
- try sema.zirValidateArrayInitPtr(block, inst);
+ .validate_array_init => {
+ try sema.zirValidateArrayInit(block, inst);
i += 1;
continue;
},
@@ -2106,7 +2107,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
}
}
-fn zirValidateStructInitPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
+fn zirValidateStructInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
const tracy = trace(@src());
defer tracy.end();
@@ -2117,15 +2118,15 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Co
const field_ptr_data = sema.code.instructions.items(.data)[instrs[0]].pl_node;
const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;
const object_ptr = sema.resolveInst(field_ptr_extra.lhs);
- const agg_ty = sema.typeOf(object_ptr).elemType();
+ const agg_ty = sema.typeOf(object_ptr).childType();
switch (agg_ty.zigTypeTag()) {
- .Struct => return sema.validateStructInitPtr(
+ .Struct => return sema.validateStructInit(
block,
agg_ty.castTag(.@"struct").?.data,
init_src,
instrs,
),
- .Union => return sema.validateUnionInitPtr(
+ .Union => return sema.validateUnionInit(
block,
agg_ty.cast(Type.Payload.Union).?.data,
init_src,
@@ -2136,7 +2137,7 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Co
}
}
-fn validateUnionInitPtr(
+fn validateUnionInit(
sema: *Sema,
block: *Block,
union_obj: *Module.Union,
@@ -2175,7 +2176,7 @@ fn validateUnionInitPtr(
_ = try block.addBinOp(.set_union_tag, union_ptr, new_tag);
}
-fn validateStructInitPtr(
+fn validateStructInit(
sema: *Sema,
block: *Block,
struct_obj: *Module.Struct,
@@ -2239,10 +2240,22 @@ fn validateStructInitPtr(
}
}
-fn zirValidateArrayInitPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
- const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
- const src = inst_data.src();
- return sema.fail(block, src, "TODO implement Sema.zirValidateArrayInitPtr", .{});
+fn zirValidateArrayInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
+ const validate_inst = sema.code.instructions.items(.data)[inst].pl_node;
+ const init_src = validate_inst.src();
+ const validate_extra = sema.code.extraData(Zir.Inst.Block, validate_inst.payload_index);
+ const instrs = sema.code.extra[validate_extra.end..][0..validate_extra.data.body_len];
+ const elem_ptr_data = sema.code.instructions.items(.data)[instrs[0]].pl_node;
+ const elem_ptr_extra = sema.code.extraData(Zir.Inst.ElemPtrImm, elem_ptr_data.payload_index).data;
+ const array_ptr = sema.resolveInst(elem_ptr_extra.ptr);
+ const array_ty = sema.typeOf(array_ptr).childType();
+ const array_len = array_ty.arrayLen();
+
+ if (instrs.len != array_len) {
+ return sema.fail(block, init_src, "expected {d} array elements; found {d}", .{
+ array_len, instrs.len,
+ });
+ }
}
fn failWithBadFieldAccess(
@@ -5169,6 +5182,18 @@ fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
return sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src);
}
+fn zirElemPtrImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
+ const tracy = trace(@src());
+ defer tracy.end();
+
+ const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
+ const src = inst_data.src();
+ const extra = sema.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;
+ const array_ptr = sema.resolveInst(extra.ptr);
+ const elem_index = try sema.addIntUnsigned(Type.usize, extra.index);
+ return sema.elemPtr(block, src, array_ptr, elem_index, src);
+}
+
fn zirSliceStart(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const tracy = trace(@src());
defer tracy.end();
src/Zir.zig
@@ -344,6 +344,11 @@ pub const Inst = struct {
/// Same as `elem_ptr` except also stores a source location node.
/// Uses the `pl_node` union field. AST node is a[b] syntax. Payload is `Bin`.
elem_ptr_node,
+ /// Same as `elem_ptr_node` except the index is stored immediately rather than
+ /// as a reference to another ZIR instruction.
+ /// Uses the `pl_node` union field. AST node is an element inside array initialization
+ /// syntax. Payload is `ElemPtrImm`.
+ elem_ptr_imm,
/// Given an array, slice, or pointer, returns the element at the provided index.
/// Uses the `bin` union field. Source location is implied to be the same
/// as the previous instruction.
@@ -675,14 +680,14 @@ pub const Inst = struct {
/// This instruction asserts that there is at least one field_ptr instruction,
/// because it must use one of them to find out the struct type.
/// Uses the `pl_node` field. Payload is `Block`.
- validate_struct_init_ptr,
- /// Given a set of `elem_ptr_node` instructions, assumes they are all part of an
+ validate_struct_init,
+ /// Given a set of `elem_ptr_imm` instructions, assumes they are all part of an
/// array initialization expression, and emits a compile error if the number of
/// elements does not match the array type.
- /// This instruction asserts that there is at least one elem_ptr_node instruction,
+ /// This instruction asserts that there is at least one `elem_ptr_imm` instruction,
/// because it must use one of them to find out the array type.
/// Uses the `pl_node` field. Payload is `Block`.
- validate_array_init_ptr,
+ validate_array_init,
/// A struct literal with a specified type, with no fields.
/// Uses the `un_node` field.
struct_init_empty,
@@ -1023,6 +1028,7 @@ pub const Inst = struct {
.elem_ptr,
.elem_val,
.elem_ptr_node,
+ .elem_ptr_imm,
.elem_val_node,
.ensure_result_used,
.ensure_result_non_error,
@@ -1114,8 +1120,8 @@ pub const Inst = struct {
.switch_block_ref_else_multi,
.switch_block_ref_under,
.switch_block_ref_under_multi,
- .validate_struct_init_ptr,
- .validate_array_init_ptr,
+ .validate_struct_init,
+ .validate_array_init,
.struct_init_empty,
.struct_init,
.struct_init_ref,
@@ -1291,6 +1297,7 @@ pub const Inst = struct {
.div = .pl_node,
.elem_ptr = .bin,
.elem_ptr_node = .pl_node,
+ .elem_ptr_imm = .pl_node,
.elem_val = .bin,
.elem_val_node = .pl_node,
.ensure_result_used = .un_node,
@@ -1377,8 +1384,8 @@ pub const Inst = struct {
.switch_capture_multi_ref = .switch_capture,
.switch_capture_else = .switch_capture,
.switch_capture_else_ref = .switch_capture,
- .validate_struct_init_ptr = .pl_node,
- .validate_array_init_ptr = .pl_node,
+ .validate_struct_init = .pl_node,
+ .validate_array_init = .pl_node,
.struct_init_empty = .un_node,
.field_type = .pl_node,
.field_type_ref = .pl_node,
@@ -2459,6 +2466,11 @@ pub const Inst = struct {
operand: Ref,
};
+ pub const ElemPtrImm = struct {
+ ptr: Ref,
+ index: u32,
+ };
+
/// This form is supported when there are no ranges, and exactly 1 item per block.
/// Depending on zir tag and len fields, extra fields trail
/// this one in the extra array.
test/behavior/array.zig
@@ -33,8 +33,13 @@ test "array init with mult" {
var i: [8]u8 = [2]u8{ a, 'b' } ** 4;
try expect(std.mem.eql(u8, &i, "abababab"));
- // this should cause a Value.repeated to be emitted in AIR.
- // TODO: find a way to test that this is actually getting emmited
var j: [4]u8 = [1]u8{'a'} ** 4;
try expect(std.mem.eql(u8, &j, "aaaa"));
}
+
+test "array literal with explicit type" {
+ const hex_mult: [4]u16 = .{ 4096, 256, 16, 1 };
+
+ try expect(hex_mult.len == 4);
+ try expect(hex_mult[1] == 256);
+}
test/behavior/array_stage1.zig
@@ -4,6 +4,13 @@ const mem = std.mem;
const expect = testing.expect;
const expectEqual = testing.expectEqual;
+test "array literal with inferred length" {
+ const hex_mult = [_]u16{ 4096, 256, 16, 1 };
+
+ try expect(hex_mult.len == 4);
+ try expect(hex_mult[1] == 256);
+}
+
test "array with sentinels" {
const S = struct {
fn doTheTest(is_ct: bool) !void {
@@ -39,13 +46,6 @@ test "void arrays" {
try expect(array.len == 4);
}
-test "array literal" {
- const hex_mult = [_]u16{ 4096, 256, 16, 1 };
-
- try expect(hex_mult.len == 4);
- try expect(hex_mult[1] == 256);
-}
-
test "array dot len const expr" {
try expect(comptime x: {
break :x some_array.len == 4;