| author | |
| committer | |
| log | 468ed7ada50c743eabe01b36d0ee9f090d80e00a |
| tree | fc5a703aaf6211db25355fcf79a945696564f3df |
| parent | 05d36fce9c7fde223e6657b3dc47105fbf065695 |
| parent | 83dcd9f0386a6bd70cf8d7dee3892f3b8d31d506 |
| signature |
stage2: emit Value.repeated for `**` with array len 13 files changed, 38 insertions(+), 10 deletions(-)
src/Sema.zig+15-9| ... | @@ -6189,16 +6189,22 @@ fn zirArrayMul(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -6189,16 +6189,22 @@ fn zirArrayMul(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr |
| 6189 | try Type.Tag.array.create(anon_decl.arena(), .{ .len = final_len, .elem_type = mulinfo.elem_type }); | 6189 | try Type.Tag.array.create(anon_decl.arena(), .{ .len = final_len, .elem_type = mulinfo.elem_type }); |
| 6190 | const buf = try anon_decl.arena().alloc(Value, final_len); | 6190 | const buf = try anon_decl.arena().alloc(Value, final_len); |
| 6191 | 6191 | ||
| 6192 | // the actual loop | 6192 | // handles the optimisation where arr.len == 0 : [_]T { X } ** N |
| 6193 | var i: u64 = 0; | 6193 | const val = if (mulinfo.len == 1) blk: { |
| 6194 | while (i < tomulby) : (i += 1) { | 6194 | const copied_val = try (try lhs_sub_val.elemValue(sema.arena, 0)).copy(anon_decl.arena()); |
| 6195 | var j: u64 = 0; | 6195 | break :blk try Value.Tag.repeated.create(anon_decl.arena(), copied_val); |
| 6196 | while (j < mulinfo.len) : (j += 1) { | 6196 | } else blk: { |
| 6197 | const val = try lhs_sub_val.elemValue(sema.arena, j); | 6197 | // the actual loop |
| 6198 | buf[mulinfo.len * i + j] = try val.copy(anon_decl.arena()); | 6198 | var i: u64 = 0; |
| 6199 | while (i < tomulby) : (i += 1) { | ||
| 6200 | var j: u64 = 0; | ||
| 6201 | while (j < mulinfo.len) : (j += 1) { | ||
| 6202 | const val = try lhs_sub_val.elemValue(sema.arena, j); | ||
| 6203 | buf[mulinfo.len * i + j] = try val.copy(anon_decl.arena()); | ||
| 6204 | } | ||
| 6199 | } | 6205 | } |
| 6200 | } | 6206 | break :blk try Value.Tag.array.create(anon_decl.arena(), buf); |
| 6201 | const val = try Value.Tag.array.create(anon_decl.arena(), buf); | 6207 | }; |
| 6202 | if (lhs_ty.zigTypeTag() == .Pointer) { | 6208 | if (lhs_ty.zigTypeTag() == .Pointer) { |
| 6203 | return sema.analyzeDeclRef(try anon_decl.finish(final_ty, val)); | 6209 | return sema.analyzeDeclRef(try anon_decl.finish(final_ty, val)); |
| 6204 | } else { | 6210 | } else { |
src/codegen/llvm.zig+18-1| ... | @@ -1024,6 +1024,7 @@ pub const DeclGen = struct { | ... | @@ -1024,6 +1024,7 @@ pub const DeclGen = struct { |
| 1024 | else => |tag| return self.todo("implement const of pointer type '{}' ({})", .{ tv.ty, tag }), | 1024 | else => |tag| return self.todo("implement const of pointer type '{}' ({})", .{ tv.ty, tag }), |
| 1025 | }, | 1025 | }, |
| 1026 | .Array => { | 1026 | .Array => { |
| 1027 | const gpa = self.gpa; | ||
| 1027 | if (tv.val.castTag(.bytes)) |payload| { | 1028 | if (tv.val.castTag(.bytes)) |payload| { |
| 1028 | const zero_sentinel = if (tv.ty.sentinel()) |sentinel| blk: { | 1029 | const zero_sentinel = if (tv.ty.sentinel()) |sentinel| blk: { |
| 1029 | if (sentinel.tag() == .zero) break :blk true; | 1030 | if (sentinel.tag() == .zero) break :blk true; |
| ... | @@ -1037,7 +1038,6 @@ pub const DeclGen = struct { | ... | @@ -1037,7 +1038,6 @@ pub const DeclGen = struct { |
| 1037 | ); | 1038 | ); |
| 1038 | } | 1039 | } |
| 1039 | if (tv.val.castTag(.array)) |payload| { | 1040 | if (tv.val.castTag(.array)) |payload| { |
| 1040 | const gpa = self.gpa; | ||
| 1041 | const elem_ty = tv.ty.elemType(); | 1041 | const elem_ty = tv.ty.elemType(); |
| 1042 | const elem_vals = payload.data; | 1042 | const elem_vals = payload.data; |
| 1043 | const sento = tv.ty.sentinel(); | 1043 | const sento = tv.ty.sentinel(); |
| ... | @@ -1053,6 +1053,23 @@ pub const DeclGen = struct { | ... | @@ -1053,6 +1053,23 @@ pub const DeclGen = struct { |
| 1053 | @intCast(c_uint, llvm_elems.len), | 1053 | @intCast(c_uint, llvm_elems.len), |
| 1054 | ); | 1054 | ); |
| 1055 | } | 1055 | } |
| 1056 | if (tv.val.castTag(.repeated)) |payload| { | ||
| 1057 | const val = payload.data; | ||
| 1058 | const elem_ty = tv.ty.elemType(); | ||
| 1059 | const len = tv.ty.arrayLen(); | ||
| 1060 | |||
| 1061 | const llvm_elems = try gpa.alloc(*const llvm.Value, len); | ||
| 1062 | defer gpa.free(llvm_elems); | ||
| 1063 | var i: u64 = 0; | ||
| 1064 | while (i < len) : (i += 1) { | ||
| 1065 | llvm_elems[i] = try self.genTypedValue(.{ .ty = elem_ty, .val = val }); | ||
| 1066 | } | ||
| 1067 | const llvm_elem_ty = try self.llvmType(elem_ty); | ||
| 1068 | return llvm_elem_ty.constArray( | ||
| 1069 | llvm_elems.ptr, | ||
| 1070 | @intCast(c_uint, llvm_elems.len), | ||
| 1071 | ); | ||
| 1072 | } | ||
| 1056 | return self.todo("handle more array values", .{}); | 1073 | return self.todo("handle more array values", .{}); |
| 1057 | }, | 1074 | }, |
| 1058 | .Optional => { | 1075 | .Optional => { |
test/behavior/array.zig+5| ... | @@ -32,4 +32,9 @@ test "array init with mult" { | ... | @@ -32,4 +32,9 @@ test "array init with mult" { |
| 32 | const a = 'a'; | 32 | const a = 'a'; |
| 33 | var i: [8]u8 = [2]u8{ a, 'b' } ** 4; | 33 | var i: [8]u8 = [2]u8{ a, 'b' } ** 4; |
| 34 | try expect(std.mem.eql(u8, &i, "abababab")); | 34 | try expect(std.mem.eql(u8, &i, "abababab")); |
| 35 | |||
| 36 | // this should cause a Value.repeated to be emitted in AIR. | ||
| 37 | // TODO: find a way to test that this is actually getting emmited | ||
| 38 | var j: [4]u8 = [1]u8{'a'} ** 4; | ||
| 39 | try expect(std.mem.eql(u8, &j, "aaaa")); | ||
| 35 | } | 40 | } |