aboutsummaryrefslogtreecommitdiff
path: root/src/AstGen.zig
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-05-28 18:38:35 +0300
committerVeikka Tuominen <git@vexu.eu>2022-05-29 13:19:03 +0300
commitc7b778992ec539e237d8afa7c105dcbad7ee280c (patch)
treed8e9e03fd9f84ad3a8a6439a82972806ed8bc914 /src/AstGen.zig
parentee651c3cd358f40f60db0bbcd82ffde99aed9b88 (diff)
downloadzig-c7b778992ec539e237d8afa7c105dcbad7ee280c.tar.gz
zig-c7b778992ec539e237d8afa7c105dcbad7ee280c.zip
AstGen: improve generated Zir for array init exprs
Diffstat (limited to 'src/AstGen.zig')
-rw-r--r--src/AstGen.zig114
1 files changed, 30 insertions, 84 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index ba27165cea..ec1cae7386 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -1273,16 +1273,8 @@ fn arrayInitExpr(
assert(array_init.ast.elements.len != 0); // Otherwise it would be struct init.
- 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,
- };
+ const array_ty: Zir.Inst.Ref = inst: {
+ if (array_init.ast.type_expr == 0) break :inst .none;
infer: {
const array_type: Ast.full.ArrayType = switch (node_tags[array_init.ast.type_expr]) {
@@ -1297,15 +1289,10 @@ fn arrayInitExpr(
const len_inst = try gz.addInt(array_init.ast.elements.len);
const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type);
if (array_type.ast.sentinel == 0) {
- const array_type_inst = try gz.addBin(.array_type, len_inst, elem_type);
- break :inst .{
- .array = array_type_inst,
- .elem = elem_type,
- .sentinel = .none,
- };
+ break :inst try gz.addBin(.array_type, len_inst, elem_type);
} else {
const sentinel = try comptimeExpr(gz, scope, .{ .ty = elem_type }, array_type.ast.sentinel);
- const array_type_inst = try gz.addPlNode(
+ break :inst try gz.addPlNode(
.array_type_sentinel,
array_init.ast.type_expr,
Zir.Inst.ArrayTypeSentinel{
@@ -1314,76 +1301,57 @@ fn arrayInitExpr(
.sentinel = sentinel,
},
);
- break :inst .{
- .array = array_type_inst,
- .elem = elem_type,
- .sentinel = sentinel,
- };
}
}
}
const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr);
_ = try gz.addUnNode(.validate_array_init_ty, array_type_inst, node);
- const elem_type = try gz.addUnNode(.elem_type, array_type_inst, array_init.ast.type_expr);
- break :inst .{
- .array = array_type_inst,
- .elem = elem_type,
- .sentinel = .none,
- };
+ break :inst array_type_inst;
};
switch (rl) {
.discard => {
+ // TODO elements should still be coerced if type is provided
for (array_init.ast.elements) |elem_init| {
_ = try expr(gz, scope, .discard, elem_init);
}
return Zir.Inst.Ref.void_value;
},
.ref => {
- if (types.array != .none) {
- 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);
- }
+ const tag: Zir.Inst.Tag = if (array_ty != .none) .array_init_ref else .array_init_anon_ref;
+ return arrayInitExprInner(gz, scope, node, array_init.ast.elements, array_ty, tag);
},
.none => {
- if (types.array != .none) {
- 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);
- }
+ const tag: Zir.Inst.Tag = if (array_ty != .none) .array_init else .array_init_anon;
+ return arrayInitExprInner(gz, scope, node, array_init.ast.elements, array_ty, tag);
},
.ty, .coerced_ty => {
- if (types.array != .none) {
- const result = try arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.sentinel, false);
- return rvalue(gz, rl, result, node);
- } else {
- const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
- return rvalue(gz, rl, result, node);
- }
+ const tag: Zir.Inst.Tag = if (array_ty != .none) .array_init else .array_init_anon;
+ const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, array_ty, tag);
+ return rvalue(gz, rl, result, node);
},
.ptr => |ptr_inst| {
- return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, types.array);
+ return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, array_ty);
},
.inferred_ptr => |ptr_inst| {
- if (types.array == .none) {
+ if (array_ty == .none) {
// We treat this case differently so that we don't get a crash when
// analyzing array_base_ptr against an alloc_inferred_mut.
// See corresponding logic in structInitExpr.
const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
return rvalue(gz, rl, result, node);
} else {
- return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, types.array);
+ return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, array_ty);
}
},
.block_ptr => |block_gz| {
// This condition is here for the same reason as the above condition in `inferred_ptr`.
// See corresponding logic in structInitExpr.
- if (types.array == .none and astgen.isInferred(block_gz.rl_ptr)) {
+ if (array_ty == .none and astgen.isInferred(block_gz.rl_ptr)) {
const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
return rvalue(gz, rl, result, node);
}
- return arrayInitExprRlPtr(gz, scope, rl, node, block_gz.rl_ptr, array_init.ast.elements, types.array);
+ return arrayInitExprRlPtr(gz, scope, rl, node, block_gz.rl_ptr, array_init.ast.elements, array_ty);
},
}
}
@@ -1410,52 +1378,33 @@ fn arrayInitExprRlNone(
return try gz.addPlNodePayloadIndex(tag, node, payload_index);
}
-fn arrayInitExprRlTy(
+fn arrayInitExprInner(
gz: *GenZir,
scope: *Scope,
node: Ast.Node.Index,
elements: []const Ast.Node.Index,
- elem_ty_inst: Zir.Inst.Ref,
- sentinel: Zir.Inst.Ref,
- ref: bool,
+ array_ty_inst: Zir.Inst.Ref,
+ tag: Zir.Inst.Tag,
) 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 len = elements.len + @boolToInt(array_ty_inst != .none);
const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{
- .operands_len = @intCast(u32, info.len),
+ .operands_len = @intCast(u32, len),
});
- var extra_index = try reserveExtra(astgen, info.len);
-
- const elem_rl: ResultLoc = .{ .ty = elem_ty_inst };
- for (elements) |elem_init| {
- const elem_ref = try expr(gz, scope, elem_rl, elem_init);
- astgen.extra.items[extra_index] = @enumToInt(elem_ref);
+ var extra_index = try reserveExtra(astgen, len);
+ if (array_ty_inst != .none) {
+ astgen.extra.items[extra_index] = @enumToInt(array_ty_inst);
extra_index += 1;
}
- if (sentinel != .none) {
- astgen.extra.items[extra_index] = @enumToInt(sentinel);
+ for (elements) |elem_init| {
+ const elem_ref = try expr(gz, scope, .none, elem_init);
+ astgen.extra.items[extra_index] = @enumToInt(elem_ref);
extra_index += 1;
}
- return try gz.addPlNodePayloadIndex(info.tag, node, payload_index);
+ return try gz.addPlNodePayloadIndex(tag, node, payload_index);
}
fn arrayInitExprRlPtr(
@@ -2244,7 +2193,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
.array_type,
.array_type_sentinel,
.vector_type,
- .elem_type,
.indexable_ptr_len,
.anyframe_type,
.as,
@@ -2347,10 +2295,8 @@ 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,