aboutsummaryrefslogtreecommitdiff
path: root/src/AstGen.zig
diff options
context:
space:
mode:
authorMitchell Hashimoto <mitchell.hashimoto@gmail.com>2022-03-07 08:26:00 -0800
committerMitchell Hashimoto <mitchell.hashimoto@gmail.com>2022-03-07 08:26:00 -0800
commit85b0a4a8fd8a56c07e0377b02d33753fe205fe41 (patch)
tree175a059ce3b60e6da72cc1e3c70b37d0af54a216 /src/AstGen.zig
parentc9fac41368c872d424681ea3cf93a9d97157143e (diff)
downloadzig-85b0a4a8fd8a56c07e0377b02d33753fe205fe41.tar.gz
zig-85b0a4a8fd8a56c07e0377b02d33753fe205fe41.zip
stage2: new zir array_init_sent for sentinel-terminated array inits
This uses a new ZIR inst `array_init_sent` (and a ref equivalent) to represent array init expressions that terminate in a a sentinel value. The sentienl value is the last value in the `MultiOp` payload. This makes it a bit more awkward to deal with (lots of "len - 1") but makes it so that the payload matches the fact that sentinels appear at the end of arrays. However, this is not a hill I want to die on so if we want to change it to index 0, I'm happy to do so. This makes the following work properly: try expect(@TypeOf([_:0]u8{}) == [0:0]u8);
Diffstat (limited to 'src/AstGen.zig')
-rw-r--r--src/AstGen.zig51
1 files changed, 39 insertions, 12 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index 8197589523..37a12c8b13 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -1259,10 +1259,12 @@ fn arrayInitExpr(
const types: struct {
array: Zir.Inst.Ref,
elem: Zir.Inst.Ref,
+ sentinel: Zir.Inst.Ref,
} = inst: {
if (array_init.ast.type_expr == 0) break :inst .{
.array = .none,
.elem = .none,
+ .sentinel = .none,
};
infer: {
@@ -1282,6 +1284,7 @@ fn arrayInitExpr(
break :inst .{
.array = array_type_inst,
.elem = elem_type,
+ .sentinel = .none,
};
} else {
const sentinel = try comptimeExpr(gz, scope, .{ .ty = elem_type }, array_type.ast.sentinel);
@@ -1297,6 +1300,7 @@ fn arrayInitExpr(
break :inst .{
.array = array_type_inst,
.elem = elem_type,
+ .sentinel = sentinel,
};
}
}
@@ -1307,6 +1311,7 @@ fn arrayInitExpr(
break :inst .{
.array = array_type_inst,
.elem = elem_type,
+ .sentinel = .none,
};
};
@@ -1319,25 +1324,25 @@ fn arrayInitExpr(
},
.ref => {
if (types.array != .none) {
- return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.array, .array_init_ref);
+ return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.sentinel, true);
} else {
return arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon_ref);
}
},
.none => {
if (types.array != .none) {
- return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.array, .array_init);
+ return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.sentinel, false);
} else {
return arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
}
},
.ty, .coerced_ty => |ty_inst| {
if (types.array != .none) {
- const result = try arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.array, .array_init);
+ const result = try arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.sentinel, false);
return rvalue(gz, rl, result, node);
} else {
const elem_type = try gz.addUnNode(.elem_type, ty_inst, node);
- return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, elem_type, types.array, .array_init);
+ return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, elem_type, types.sentinel, false);
}
},
.ptr => |ptr_inst| {
@@ -1387,18 +1392,32 @@ fn arrayInitExprRlTy(
node: Ast.Node.Index,
elements: []const Ast.Node.Index,
elem_ty_inst: Zir.Inst.Ref,
- array_ty: Zir.Inst.Ref,
- tag: Zir.Inst.Tag,
+ sentinel: Zir.Inst.Ref,
+ ref: bool,
) InnerError!Zir.Inst.Ref {
const astgen = gz.astgen;
+ const info: struct {
+ len: usize,
+ tag: Zir.Inst.Tag,
+ } = blk: {
+ if (sentinel != .none) {
+ break :blk .{
+ .len = elements.len + 1,
+ .tag = if (ref) .array_init_sent_ref else .array_init_sent,
+ };
+ } else {
+ break :blk .{
+ .len = elements.len,
+ .tag = if (ref) .array_init_ref else .array_init,
+ };
+ }
+ };
+
const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{
- .operands_len = @intCast(u32, elements.len + 1),
+ .operands_len = @intCast(u32, info.len),
});
- var extra_index = try reserveExtra(astgen, elements.len + 1);
-
- astgen.extra.items[extra_index] = @enumToInt(array_ty);
- extra_index += 1;
+ var extra_index = try reserveExtra(astgen, info.len);
const elem_rl: ResultLoc = .{ .ty = elem_ty_inst };
for (elements) |elem_init| {
@@ -1406,7 +1425,13 @@ fn arrayInitExprRlTy(
astgen.extra.items[extra_index] = @enumToInt(elem_ref);
extra_index += 1;
}
- return try gz.addPlNodePayloadIndex(tag, node, payload_index);
+
+ if (sentinel != .none) {
+ astgen.extra.items[extra_index] = @enumToInt(sentinel);
+ extra_index += 1;
+ }
+
+ return try gz.addPlNodePayloadIndex(info.tag, node, payload_index);
}
fn arrayInitExprRlPtr(
@@ -2221,8 +2246,10 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
.struct_init_anon_ref,
.array_init,
.array_init_anon,
+ .array_init_sent,
.array_init_ref,
.array_init_anon_ref,
+ .array_init_sent_ref,
.union_init,
.field_type,
.field_type_ref,