authorgravatar for 58830309+g-w1@users.noreply.github.comg-w1 <58830309+g-w1@users.noreply.github.com> 2021-09-30 18:31:27-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-09-30 18:31:27-04:00
log5e7406bdd9f942900dceb2f917ed5f64b6f2ba00
treed1f4ddd3955406d617531156bc6e3721a908acc7
parentc82c3585c8fdf02820747c118c78957e2eb5d072
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

stage2: implement array_init instruction (#9843)

* stage2: array mul support more types of operands * stage2: array cat support more types of operands * print_zir: print array_init * stage2: implement Sema for array_init

3 files changed, 113 insertions(+), 49 deletions(-)

src/Sema.zig+90-47
...@@ -6111,35 +6111,36 @@ fn zirArrayCat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr...@@ -6111,35 +6111,36 @@ fn zirArrayCat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr
6111 if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| {6111 if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| {
6112 if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val| {6112 if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val| {
6113 const final_len = lhs_info.len + rhs_info.len;6113 const final_len = lhs_info.len + rhs_info.len;
6114 if (lhs_ty.zigTypeTag() == .Pointer) {6114 const is_pointer = lhs_ty.zigTypeTag() == .Pointer;
6115 var anon_decl = try block.startAnonDecl();6115 var anon_decl = try block.startAnonDecl();
6116 defer anon_decl.deinit();6116 defer anon_decl.deinit();
61176117
6118 const lhs_sub_val = (try lhs_val.pointerDeref(anon_decl.arena())).?;6118 const lhs_sub_val = if (is_pointer) (try lhs_val.pointerDeref(anon_decl.arena())).? else lhs_val;
6119 const rhs_sub_val = (try rhs_val.pointerDeref(anon_decl.arena())).?;6119 const rhs_sub_val = if (is_pointer) (try rhs_val.pointerDeref(anon_decl.arena())).? else rhs_val;
6120 const buf = try anon_decl.arena().alloc(Value, final_len);6120 const buf = try anon_decl.arena().alloc(Value, final_len);
6121 {6121 {
6122 var i: u64 = 0;6122 var i: u64 = 0;
6123 while (i < lhs_info.len) : (i += 1) {6123 while (i < lhs_info.len) : (i += 1) {
6124 const val = try lhs_sub_val.elemValue(sema.arena, i);6124 const val = try lhs_sub_val.elemValue(sema.arena, i);
6125 buf[i] = try val.copy(anon_decl.arena());6125 buf[i] = try val.copy(anon_decl.arena());
6126 }
6127 }6126 }
6128 {6127 }
6129 var i: u64 = 0;6128 {
6130 while (i < rhs_info.len) : (i += 1) {6129 var i: u64 = 0;
6131 const val = try rhs_sub_val.elemValue(sema.arena, i);6130 while (i < rhs_info.len) : (i += 1) {
6132 buf[lhs_info.len + i] = try val.copy(anon_decl.arena());6131 const val = try rhs_sub_val.elemValue(sema.arena, i);
6133 }6132 buf[lhs_info.len + i] = try val.copy(anon_decl.arena());
6134 }6133 }
6135 const ty = if (res_sent) |rs|
6136 try Type.Tag.array_sentinel.create(anon_decl.arena(), .{ .len = final_len, .elem_type = lhs_info.elem_type, .sentinel = rs })
6137 else
6138 try Type.Tag.array.create(anon_decl.arena(), .{ .len = final_len, .elem_type = lhs_info.elem_type });
6139 const val = try Value.Tag.array.create(anon_decl.arena(), buf);
6140 return sema.analyzeDeclRef(try anon_decl.finish(ty, val));
6141 }6134 }
6142 return sema.mod.fail(&block.base, lhs_src, "TODO array_cat more types of Values", .{});6135 const ty = if (res_sent) |rs|
6136 try Type.Tag.array_sentinel.create(anon_decl.arena(), .{ .len = final_len, .elem_type = lhs_info.elem_type, .sentinel = rs })
6137 else
6138 try Type.Tag.array.create(anon_decl.arena(), .{ .len = final_len, .elem_type = lhs_info.elem_type });
6139 const val = try Value.Tag.array.create(anon_decl.arena(), buf);
6140 return if (is_pointer)
6141 sema.analyzeDeclRef(try anon_decl.finish(ty, val))
6142 else
6143 sema.analyzeDeclVal(block, .unneeded, try anon_decl.finish(ty, val));
6143 } else {6144 } else {
6144 return sema.mod.fail(&block.base, lhs_src, "TODO runtime array_cat", .{});6145 return sema.mod.fail(&block.base, lhs_src, "TODO runtime array_cat", .{});
6145 }6146 }
...@@ -6179,29 +6180,30 @@ fn zirArrayMul(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr...@@ -6179,29 +6180,30 @@ fn zirArrayMul(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr
61796180
6180 const final_len = std.math.mul(u64, mulinfo.len, tomulby) catch return sema.mod.fail(&block.base, rhs_src, "operation results in overflow", .{});6181 const final_len = std.math.mul(u64, mulinfo.len, tomulby) catch return sema.mod.fail(&block.base, rhs_src, "operation results in overflow", .{});
6181 if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| {6182 if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| {
6182 if (lhs_ty.zigTypeTag() == .Pointer) {6183 var anon_decl = try block.startAnonDecl();
6183 var anon_decl = try block.startAnonDecl();6184 defer anon_decl.deinit();
6184 defer anon_decl.deinit();6185 const lhs_sub_val = if (lhs_ty.zigTypeTag() == .Pointer) (try lhs_val.pointerDeref(anon_decl.arena())).? else lhs_val;
6185 const lhs_sub_val = (try lhs_val.pointerDeref(anon_decl.arena())).?;6186 const final_ty = if (mulinfo.sentinel) |sent|
61866187 try Type.Tag.array_sentinel.create(anon_decl.arena(), .{ .len = final_len, .elem_type = mulinfo.elem_type, .sentinel = sent })
6187 const final_ty = if (mulinfo.sentinel) |sent|6188 else
6188 try Type.Tag.array_sentinel.create(anon_decl.arena(), .{ .len = final_len, .elem_type = mulinfo.elem_type, .sentinel = sent })6189 try Type.Tag.array.create(anon_decl.arena(), .{ .len = final_len, .elem_type = mulinfo.elem_type });
6189 else6190 const buf = try anon_decl.arena().alloc(Value, final_len);
6190 try Type.Tag.array.create(anon_decl.arena(), .{ .len = final_len, .elem_type = mulinfo.elem_type });6191
61916192 // the actual loop
6192 const buf = try anon_decl.arena().alloc(Value, final_len);6193 var i: u64 = 0;
6193 var i: u64 = 0;6194 while (i < tomulby) : (i += 1) {
6194 while (i < tomulby) : (i += 1) {6195 var j: u64 = 0;
6195 var j: u64 = 0;6196 while (j < mulinfo.len) : (j += 1) {
6196 while (j < mulinfo.len) : (j += 1) {6197 const val = try lhs_sub_val.elemValue(sema.arena, j);
6197 const val = try lhs_sub_val.elemValue(sema.arena, j);6198 buf[mulinfo.len * i + j] = try val.copy(anon_decl.arena());
6198 buf[mulinfo.len * i + j] = try val.copy(anon_decl.arena());
6199 }
6200 }6199 }
6201 const val = try Value.Tag.array.create(anon_decl.arena(), buf);6200 }
6201 const val = try Value.Tag.array.create(anon_decl.arena(), buf);
6202 if (lhs_ty.zigTypeTag() == .Pointer) {
6202 return sema.analyzeDeclRef(try anon_decl.finish(final_ty, val));6203 return sema.analyzeDeclRef(try anon_decl.finish(final_ty, val));
6204 } else {
6205 return sema.analyzeDeclVal(block, .unneeded, try anon_decl.finish(final_ty, val));
6203 }6206 }
6204 return sema.mod.fail(&block.base, lhs_src, "TODO array_mul more types of Values", .{});
6205 }6207 }
6206 return sema.mod.fail(&block.base, lhs_src, "TODO runtime array_mul", .{});6208 return sema.mod.fail(&block.base, lhs_src, "TODO runtime array_mul", .{});
6207}6209}
...@@ -8227,8 +8229,49 @@ fn zirArrayInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref:...@@ -8227,8 +8229,49 @@ fn zirArrayInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref:
8227 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;8229 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
8228 const src = inst_data.src();8230 const src = inst_data.src();
82298231
8230 _ = is_ref;8232 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
8231 return sema.mod.fail(&block.base, src, "TODO: Sema.zirArrayInit", .{});8233 const args = sema.code.refSlice(extra.end, extra.data.operands_len);
8234
8235 var resolved_args = try sema.mod.gpa.alloc(Air.Inst.Ref, args.len);
8236 for (args) |arg, i| resolved_args[i] = sema.resolveInst(arg);
8237
8238 var all_args_comptime = for (resolved_args) |arg| {
8239 if ((try sema.resolveMaybeUndefVal(block, src, arg)) == null) break false;
8240 } else true;
8241
8242 if (all_args_comptime) {
8243 var anon_decl = try block.startAnonDecl();
8244 defer anon_decl.deinit();
8245 assert(!(resolved_args.len == 0));
8246 const final_ty = try Type.Tag.array.create(anon_decl.arena(), .{ .len = resolved_args.len, .elem_type = sema.typeOf(resolved_args[0]) });
8247 const buf = try anon_decl.arena().alloc(Value, resolved_args.len);
8248 for (resolved_args) |arg, i| {
8249 buf[i] = (try sema.resolveMaybeUndefVal(block, src, arg)).?;
8250 }
8251
8252 const val = try Value.Tag.array.create(anon_decl.arena(), buf);
8253 if (is_ref)
8254 return sema.analyzeDeclRef(try anon_decl.finish(final_ty, val))
8255 else
8256 return sema.analyzeDeclVal(block, .unneeded, try anon_decl.finish(final_ty, val));
8257 }
8258
8259 assert(!(resolved_args.len == 0));
8260 const array_ty = try Type.Tag.array.create(sema.arena, .{ .len = resolved_args.len, .elem_type = sema.typeOf(resolved_args[0]) });
8261 const final_ty = try Type.ptr(sema.arena, .{
8262 .pointee_type = array_ty,
8263 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
8264 });
8265 const alloc = try block.addTy(.alloc, final_ty);
8266
8267 for (resolved_args) |arg, i| {
8268 const pointer_to_array_at_index = try block.addBinOp(.ptr_elem_ptr, alloc, try sema.addIntUnsigned(Type.initTag(.u64), i));
8269 _ = try block.addBinOp(.store, pointer_to_array_at_index, arg);
8270 }
8271 return if (is_ref)
8272 alloc
8273 else
8274 try sema.analyzeLoad(block, .unneeded, alloc, .unneeded);
8232}8275}
82338276
8234fn zirArrayInitAnon(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref {8277fn zirArrayInitAnon(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref {
src/print_zir.zig+17-2
...@@ -259,15 +259,16 @@ const Writer = struct {...@@ -259,15 +259,16 @@ const Writer = struct {
259 .@"break",259 .@"break",
260 .break_inline,260 .break_inline,
261 => try self.writeBreak(stream, inst),261 => try self.writeBreak(stream, inst),
262 .array_init,
263 .array_init_ref,
264 => try self.writeArrayInit(stream, inst),
262265
263 .elem_ptr_node,266 .elem_ptr_node,
264 .elem_val_node,267 .elem_val_node,
265 .slice_start,268 .slice_start,
266 .slice_end,269 .slice_end,
267 .slice_sentinel,270 .slice_sentinel,
268 .array_init,
269 .array_init_anon,271 .array_init_anon,
270 .array_init_ref,
271 .array_init_anon_ref,272 .array_init_anon_ref,
272 .union_init_ptr,273 .union_init_ptr,
273 .shuffle,274 .shuffle,
...@@ -1860,6 +1861,20 @@ const Writer = struct {...@@ -1860,6 +1861,20 @@ const Writer = struct {
1860 try stream.writeAll(")");1861 try stream.writeAll(")");
1861 }1862 }
18621863
1864 fn writeArrayInit(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
1865 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1866
1867 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
1868 const args = self.code.refSlice(extra.end, extra.data.operands_len);
1869
1870 try stream.writeAll(".{");
1871 for (args) |arg, i| {
1872 if (i != 0) try stream.writeAll(", ");
1873 try self.writeInstRef(stream, arg);
1874 }
1875 try stream.writeAll("})");
1876 }
1877
1863 fn writeUnreachable(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1878 fn writeUnreachable(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
1864 const inst_data = self.code.instructions.items(.data)[inst].@"unreachable";1879 const inst_data = self.code.instructions.items(.data)[inst].@"unreachable";
1865 const safety_str = if (inst_data.safety) "safe" else "unsafe";1880 const safety_str = if (inst_data.safety) "safe" else "unsafe";
test/behavior/array.zig+6
...@@ -27,3 +27,9 @@ test "arrays" {...@@ -27,3 +27,9 @@ test "arrays" {
27fn getArrayLen(a: []const u32) usize {27fn getArrayLen(a: []const u32) usize {
28 return a.len;28 return a.len;
29}29}
30
31test "array init with mult" {
32 const a = 'a';
33 var i: [8]u8 = [2]u8{ a, 'b' } ** 4;
34 try expect(std.mem.eql(u8, &i, "abababab"));
35}