diff options
| author | Mitchell Hashimoto <mitchell.hashimoto@gmail.com> | 2022-03-07 08:26:00 -0800 |
|---|---|---|
| committer | Mitchell Hashimoto <mitchell.hashimoto@gmail.com> | 2022-03-07 08:26:00 -0800 |
| commit | 85b0a4a8fd8a56c07e0377b02d33753fe205fe41 (patch) | |
| tree | 175a059ce3b60e6da72cc1e3c70b37d0af54a216 /src/AstGen.zig | |
| parent | c9fac41368c872d424681ea3cf93a9d97157143e (diff) | |
| download | zig-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.zig | 51 |
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, |
