authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-05-28 18:38:35+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-05-29 13:19:03+03:00
logc7b778992ec539e237d8afa7c105dcbad7ee280c
treed8e9e03fd9f84ad3a8a6439a82972806ed8bc914
parentee651c3cd358f40f60db0bbcd82ffde99aed9b88

AstGen: improve generated Zir for array init exprs


6 files changed, 57 insertions(+), 141 deletions(-)

src/AstGen.zig+30-84
......@@ -1273,16 +1273,8 @@ fn arrayInitExpr(
12731273
12741274 assert(array_init.ast.elements.len != 0); // Otherwise it would be struct init.
12751275
1276 const types: struct {
1277 array: Zir.Inst.Ref,
1278 elem: Zir.Inst.Ref,
1279 sentinel: Zir.Inst.Ref,
1280 } = inst: {
1281 if (array_init.ast.type_expr == 0) break :inst .{
1282 .array = .none,
1283 .elem = .none,
1284 .sentinel = .none,
1285 };
1276 const array_ty: Zir.Inst.Ref = inst: {
1277 if (array_init.ast.type_expr == 0) break :inst .none;
12861278
12871279 infer: {
12881280 const array_type: Ast.full.ArrayType = switch (node_tags[array_init.ast.type_expr]) {
......@@ -1297,15 +1289,10 @@ fn arrayInitExpr(
12971289 const len_inst = try gz.addInt(array_init.ast.elements.len);
12981290 const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type);
12991291 if (array_type.ast.sentinel == 0) {
1300 const array_type_inst = try gz.addBin(.array_type, len_inst, elem_type);
1301 break :inst .{
1302 .array = array_type_inst,
1303 .elem = elem_type,
1304 .sentinel = .none,
1305 };
1292 break :inst try gz.addBin(.array_type, len_inst, elem_type);
13061293 } else {
13071294 const sentinel = try comptimeExpr(gz, scope, .{ .ty = elem_type }, array_type.ast.sentinel);
1308 const array_type_inst = try gz.addPlNode(
1295 break :inst try gz.addPlNode(
13091296 .array_type_sentinel,
13101297 array_init.ast.type_expr,
13111298 Zir.Inst.ArrayTypeSentinel{
......@@ -1314,76 +1301,57 @@ fn arrayInitExpr(
13141301 .sentinel = sentinel,
13151302 },
13161303 );
1317 break :inst .{
1318 .array = array_type_inst,
1319 .elem = elem_type,
1320 .sentinel = sentinel,
1321 };
13221304 }
13231305 }
13241306 }
13251307 const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr);
13261308 _ = try gz.addUnNode(.validate_array_init_ty, array_type_inst, node);
1327 const elem_type = try gz.addUnNode(.elem_type, array_type_inst, array_init.ast.type_expr);
1328 break :inst .{
1329 .array = array_type_inst,
1330 .elem = elem_type,
1331 .sentinel = .none,
1332 };
1309 break :inst array_type_inst;
13331310 };
13341311
13351312 switch (rl) {
13361313 .discard => {
1314 // TODO elements should still be coerced if type is provided
13371315 for (array_init.ast.elements) |elem_init| {
13381316 _ = try expr(gz, scope, .discard, elem_init);
13391317 }
13401318 return Zir.Inst.Ref.void_value;
13411319 },
13421320 .ref => {
1343 if (types.array != .none) {
1344 return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.sentinel, true);
1345 } else {
1346 return arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon_ref);
1347 }
1321 const tag: Zir.Inst.Tag = if (array_ty != .none) .array_init_ref else .array_init_anon_ref;
1322 return arrayInitExprInner(gz, scope, node, array_init.ast.elements, array_ty, tag);
13481323 },
13491324 .none => {
1350 if (types.array != .none) {
1351 return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.sentinel, false);
1352 } else {
1353 return arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
1354 }
1325 const tag: Zir.Inst.Tag = if (array_ty != .none) .array_init else .array_init_anon;
1326 return arrayInitExprInner(gz, scope, node, array_init.ast.elements, array_ty, tag);
13551327 },
13561328 .ty, .coerced_ty => {
1357 if (types.array != .none) {
1358 const result = try arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.sentinel, false);
1359 return rvalue(gz, rl, result, node);
1360 } else {
1361 const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
1362 return rvalue(gz, rl, result, node);
1363 }
1329 const tag: Zir.Inst.Tag = if (array_ty != .none) .array_init else .array_init_anon;
1330 const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, array_ty, tag);
1331 return rvalue(gz, rl, result, node);
13641332 },
13651333 .ptr => |ptr_inst| {
1366 return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, types.array);
1334 return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, array_ty);
13671335 },
13681336 .inferred_ptr => |ptr_inst| {
1369 if (types.array == .none) {
1337 if (array_ty == .none) {
13701338 // We treat this case differently so that we don't get a crash when
13711339 // analyzing array_base_ptr against an alloc_inferred_mut.
13721340 // See corresponding logic in structInitExpr.
13731341 const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
13741342 return rvalue(gz, rl, result, node);
13751343 } else {
1376 return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, types.array);
1344 return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, array_ty);
13771345 }
13781346 },
13791347 .block_ptr => |block_gz| {
13801348 // This condition is here for the same reason as the above condition in `inferred_ptr`.
13811349 // See corresponding logic in structInitExpr.
1382 if (types.array == .none and astgen.isInferred(block_gz.rl_ptr)) {
1350 if (array_ty == .none and astgen.isInferred(block_gz.rl_ptr)) {
13831351 const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
13841352 return rvalue(gz, rl, result, node);
13851353 }
1386 return arrayInitExprRlPtr(gz, scope, rl, node, block_gz.rl_ptr, array_init.ast.elements, types.array);
1354 return arrayInitExprRlPtr(gz, scope, rl, node, block_gz.rl_ptr, array_init.ast.elements, array_ty);
13871355 },
13881356 }
13891357}
......@@ -1410,52 +1378,33 @@ fn arrayInitExprRlNone(
14101378 return try gz.addPlNodePayloadIndex(tag, node, payload_index);
14111379}
14121380
1413fn arrayInitExprRlTy(
1381fn arrayInitExprInner(
14141382 gz: *GenZir,
14151383 scope: *Scope,
14161384 node: Ast.Node.Index,
14171385 elements: []const Ast.Node.Index,
1418 elem_ty_inst: Zir.Inst.Ref,
1419 sentinel: Zir.Inst.Ref,
1420 ref: bool,
1386 array_ty_inst: Zir.Inst.Ref,
1387 tag: Zir.Inst.Tag,
14211388) InnerError!Zir.Inst.Ref {
14221389 const astgen = gz.astgen;
14231390
1424 const info: struct {
1425 len: usize,
1426 tag: Zir.Inst.Tag,
1427 } = blk: {
1428 if (sentinel != .none) {
1429 break :blk .{
1430 .len = elements.len + 1,
1431 .tag = if (ref) .array_init_sent_ref else .array_init_sent,
1432 };
1433 } else {
1434 break :blk .{
1435 .len = elements.len,
1436 .tag = if (ref) .array_init_ref else .array_init,
1437 };
1438 }
1439 };
1440
1391 const len = elements.len + @boolToInt(array_ty_inst != .none);
14411392 const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{
1442 .operands_len = @intCast(u32, info.len),
1393 .operands_len = @intCast(u32, len),
14431394 });
1444 var extra_index = try reserveExtra(astgen, info.len);
1445
1446 const elem_rl: ResultLoc = .{ .ty = elem_ty_inst };
1447 for (elements) |elem_init| {
1448 const elem_ref = try expr(gz, scope, elem_rl, elem_init);
1449 astgen.extra.items[extra_index] = @enumToInt(elem_ref);
1395 var extra_index = try reserveExtra(astgen, len);
1396 if (array_ty_inst != .none) {
1397 astgen.extra.items[extra_index] = @enumToInt(array_ty_inst);
14501398 extra_index += 1;
14511399 }
14521400
1453 if (sentinel != .none) {
1454 astgen.extra.items[extra_index] = @enumToInt(sentinel);
1401 for (elements) |elem_init| {
1402 const elem_ref = try expr(gz, scope, .none, elem_init);
1403 astgen.extra.items[extra_index] = @enumToInt(elem_ref);
14551404 extra_index += 1;
14561405 }
14571406
1458 return try gz.addPlNodePayloadIndex(info.tag, node, payload_index);
1407 return try gz.addPlNodePayloadIndex(tag, node, payload_index);
14591408}
14601409
14611410fn arrayInitExprRlPtr(
......@@ -2244,7 +2193,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
22442193 .array_type,
22452194 .array_type_sentinel,
22462195 .vector_type,
2247 .elem_type,
22482196 .indexable_ptr_len,
22492197 .anyframe_type,
22502198 .as,
......@@ -2347,10 +2295,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
23472295 .struct_init_anon_ref,
23482296 .array_init,
23492297 .array_init_anon,
2350 .array_init_sent,
23512298 .array_init_ref,
23522299 .array_init_anon_ref,
2353 .array_init_sent_ref,
23542300 .union_init,
23552301 .field_type,
23562302 .field_type_ref,
src/Sema.zig+17-28
......@@ -726,7 +726,6 @@ fn analyzeBodyInner(
726726 .elem_ptr_imm => try sema.zirElemPtrImm(block, inst),
727727 .elem_val => try sema.zirElemVal(block, inst),
728728 .elem_val_node => try sema.zirElemValNode(block, inst),
729 .elem_type => try sema.zirElemType(block, inst),
730729 .enum_literal => try sema.zirEnumLiteral(block, inst),
731730 .enum_to_int => try sema.zirEnumToInt(block, inst),
732731 .int_to_enum => try sema.zirIntToEnum(block, inst),
......@@ -798,10 +797,8 @@ fn analyzeBodyInner(
798797 .struct_init_ref => try sema.zirStructInit(block, inst, true),
799798 .struct_init_anon => try sema.zirStructInitAnon(block, inst, false),
800799 .struct_init_anon_ref => try sema.zirStructInitAnon(block, inst, true),
801 .array_init => try sema.zirArrayInit(block, inst, false, false),
802 .array_init_sent => try sema.zirArrayInit(block, inst, false, true),
803 .array_init_ref => try sema.zirArrayInit(block, inst, true, false),
804 .array_init_sent_ref => try sema.zirArrayInit(block, inst, true, true),
800 .array_init => try sema.zirArrayInit(block, inst, false),
801 .array_init_ref => try sema.zirArrayInit(block, inst, true),
805802 .array_init_anon => try sema.zirArrayInitAnon(block, inst, false),
806803 .array_init_anon_ref => try sema.zirArrayInitAnon(block, inst, true),
807804 .union_init => try sema.zirUnionInit(block, inst),
......@@ -13436,7 +13433,6 @@ fn zirArrayInit(
1343613433 block: *Block,
1343713434 inst: Zir.Inst.Index,
1343813435 is_ref: bool,
13439 is_sent: bool,
1344013436) CompileError!Air.Inst.Ref {
1344113437 const gpa = sema.gpa;
1344213438 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
......@@ -13444,30 +13440,23 @@ fn zirArrayInit(
1344413440
1344513441 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
1344613442 const args = sema.code.refSlice(extra.end, extra.data.operands_len);
13447 assert(args.len != 0);
13443 assert(args.len >= 2); // array_ty + at least one element
1344813444
13449 const resolved_args = try gpa.alloc(Air.Inst.Ref, args.len);
13450 defer gpa.free(resolved_args);
13451
13452 for (args) |arg, i| resolved_args[i] = try sema.resolveInst(arg);
13445 const array_ty = try sema.resolveType(block, src, args[0]);
13446 const sentinel_val = array_ty.sentinel();
1345313447
13454 const elem_ty = sema.typeOf(resolved_args[0]);
13455 const array_ty = blk: {
13456 if (!is_sent) {
13457 break :blk try Type.Tag.array.create(sema.arena, .{
13458 .len = resolved_args.len,
13459 .elem_type = elem_ty,
13460 });
13461 }
13448 const resolved_args = try gpa.alloc(Air.Inst.Ref, args.len - 1 + @boolToInt(sentinel_val != null));
13449 defer gpa.free(resolved_args);
13450 const elem_ty = array_ty.elemType2();
13451 for (args[1..]) |arg, i| {
13452 const resolved_arg = try sema.resolveInst(arg);
13453 const arg_src = src; // TODO better source location
13454 resolved_args[i] = try sema.coerce(block, elem_ty, resolved_arg, arg_src);
13455 }
1346213456
13463 const sentinel_ref = resolved_args[resolved_args.len - 1];
13464 const val = try sema.resolveConstValue(block, src, sentinel_ref);
13465 break :blk try Type.Tag.array_sentinel.create(sema.arena, .{
13466 .len = resolved_args.len - 1,
13467 .sentinel = val,
13468 .elem_type = elem_ty,
13469 });
13470 };
13457 if (sentinel_val) |some| {
13458 resolved_args[resolved_args.len - 1] = try sema.addConstant(elem_ty, some);
13459 }
1347113460
1347213461 const opt_runtime_src: ?LazySrcLoc = for (resolved_args) |arg| {
1347313462 const arg_src = src; // TODO better source location
......@@ -13488,7 +13477,7 @@ fn zirArrayInit(
1348813477 };
1348913478
1349013479 try sema.requireRuntimeBlock(block, runtime_src);
13491 try sema.queueFullTypeResolution(elem_ty);
13480 try sema.queueFullTypeResolution(array_ty);
1349213481
1349313482 if (is_ref) {
1349413483 const target = sema.mod.getTarget();
src/Zir.zig-20
......@@ -221,9 +221,6 @@ pub const Inst = struct {
221221 /// Uses the `pl_node` union field with `Bin` payload.
222222 /// lhs is length, rhs is element type.
223223 vector_type,
224 /// Given an array type, returns the element type.
225 /// Uses the `un_node` union field.
226 elem_type,
227224 /// Given a pointer to an indexable object, returns the len property. This is
228225 /// used by for loops. This instruction also emits a for-loop specific compile
229226 /// error if the indexable object is not indexable.
......@@ -737,20 +734,12 @@ pub const Inst = struct {
737734 /// Array initialization syntax.
738735 /// Uses the `pl_node` field. Payload is `MultiOp`.
739736 array_init,
740 /// Array initialization with sentinel.
741 /// Uses the `pl_node` field. Payload is `MultiOp`.
742 /// Final op in MultiOp is the sentinel.
743 array_init_sent,
744737 /// Anonymous array initialization syntax.
745738 /// Uses the `pl_node` field. Payload is `MultiOp`.
746739 array_init_anon,
747740 /// Array initialization syntax, make the result a pointer.
748741 /// Uses the `pl_node` field. Payload is `MultiOp`.
749742 array_init_ref,
750 /// Array initialization with sentinel.
751 /// Uses the `pl_node` field. Payload is `MultiOp`.
752 /// Final op in MultiOp is the sentinel.
753 array_init_sent_ref,
754743 /// Anonymous array initialization syntax, make the result a pointer.
755744 /// Uses the `pl_node` field. Payload is `MultiOp`.
756745 array_init_anon_ref,
......@@ -1019,7 +1008,6 @@ pub const Inst = struct {
10191008 .array_type,
10201009 .array_type_sentinel,
10211010 .vector_type,
1022 .elem_type,
10231011 .indexable_ptr_len,
10241012 .anyframe_type,
10251013 .as,
......@@ -1153,10 +1141,8 @@ pub const Inst = struct {
11531141 .struct_init_anon,
11541142 .struct_init_anon_ref,
11551143 .array_init,
1156 .array_init_sent,
11571144 .array_init_anon,
11581145 .array_init_ref,
1159 .array_init_sent_ref,
11601146 .array_init_anon_ref,
11611147 .union_init,
11621148 .field_type,
......@@ -1314,7 +1300,6 @@ pub const Inst = struct {
13141300 .array_type,
13151301 .array_type_sentinel,
13161302 .vector_type,
1317 .elem_type,
13181303 .indexable_ptr_len,
13191304 .anyframe_type,
13201305 .as,
......@@ -1426,10 +1411,8 @@ pub const Inst = struct {
14261411 .struct_init_anon,
14271412 .struct_init_anon_ref,
14281413 .array_init,
1429 .array_init_sent,
14301414 .array_init_anon,
14311415 .array_init_ref,
1432 .array_init_sent_ref,
14331416 .array_init_anon_ref,
14341417 .union_init,
14351418 .field_type,
......@@ -1554,7 +1537,6 @@ pub const Inst = struct {
15541537 .array_type = .bin,
15551538 .array_type_sentinel = .pl_node,
15561539 .vector_type = .pl_node,
1557 .elem_type = .un_node,
15581540 .indexable_ptr_len = .un_node,
15591541 .anyframe_type = .un_node,
15601542 .as = .bin,
......@@ -1688,10 +1670,8 @@ pub const Inst = struct {
16881670 .struct_init_anon = .pl_node,
16891671 .struct_init_anon_ref = .pl_node,
16901672 .array_init = .pl_node,
1691 .array_init_sent = .pl_node,
16921673 .array_init_anon = .pl_node,
16931674 .array_init_ref = .pl_node,
1694 .array_init_sent_ref = .pl_node,
16951675 .array_init_anon_ref = .pl_node,
16961676 .union_init = .pl_node,
16971677 .type_info = .un_node,
src/print_zir.zig+3-7
......@@ -226,7 +226,6 @@ const Writer = struct {
226226 .pop_count,
227227 .byte_swap,
228228 .bit_reverse,
229 .elem_type,
230229 .@"resume",
231230 .@"await",
232231 .switch_cond,
......@@ -268,10 +267,6 @@ const Writer = struct {
268267 .array_init_anon_ref,
269268 => try self.writeArrayInit(stream, inst),
270269
271 .array_init_sent,
272 .array_init_sent_ref,
273 => try self.writeArrayInitSent(stream, inst),
274
275270 .slice_start => try self.writeSliceStart(stream, inst),
276271 .slice_end => try self.writeSliceEnd(stream, inst),
277272 .slice_sentinel => try self.writeSliceSentinel(stream, inst),
......@@ -2085,8 +2080,9 @@ const Writer = struct {
20852080 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
20862081 const args = self.code.refSlice(extra.end, extra.data.operands_len);
20872082
2088 try stream.writeAll(".{");
2089 for (args) |arg, i| {
2083 try self.writeInstRef(stream, args[0]);
2084 try stream.writeAll("{");
2085 for (args[1..]) |arg, i| {
20902086 if (i != 0) try stream.writeAll(", ");
20912087 try self.writeInstRef(stream, arg);
20922088 }
test/behavior/basic.zig+7
......@@ -942,3 +942,10 @@ test "comptime int in switch in catch is casted to correct inferred type" {
942942 };
943943 _ = b;
944944}
945
946test "vector initialized with array init syntax has proper type" {
947 comptime {
948 const actual = -@Vector(4, i32){ 1, 2, 3, 4 };
949 try std.testing.expectEqual(@Vector(4, i32){ -1, -2, -3, -4 }, actual);
950 }
951}
test/behavior/tuple.zig-2
......@@ -194,8 +194,6 @@ test "tuple as the result from a labeled block" {
194194}
195195
196196test "initializing tuple with explicit type" {
197 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
198
199197 const T = @TypeOf(.{ @as(i32, 0), @as(u32, 0) });
200198 var a = T{ 0, 0 };
201199 _ = a;