diff options
| author | Jacob G-W <jacoblevgw@gmail.com> | 2021-08-22 16:09:12 -0400 |
|---|---|---|
| committer | Jacob G-W <jacoblevgw@gmail.com> | 2021-08-31 07:46:24 -0400 |
| commit | f6d9ac481b6d316ede16f095cfacbd7fa5d56b69 (patch) | |
| tree | 3b298469a7c92afe985b19a70f3703453266d4bc /src/Sema.zig | |
| parent | a360f2bf6c79ab0631fecdd6298fe3ca18545c83 (diff) | |
| download | zig-f6d9ac481b6d316ede16f095cfacbd7fa5d56b69.tar.gz zig-f6d9ac481b6d316ede16f095cfacbd7fa5d56b69.zip | |
stage2: add array mult `**`
Diffstat (limited to 'src/Sema.zig')
| -rw-r--r-- | src/Sema.zig | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 03b049f73f..eccf22d02d 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5598,8 +5598,48 @@ fn zirArrayMul(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr const tracy = trace(@src()); defer tracy.end(); - _ = inst; - return sema.mod.fail(&block.base, sema.src, "TODO implement zirArrayMul", .{}); + const inst_data = sema.code.instructions.items(.data)[inst].pl_node; + const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; + const lhs = sema.resolveInst(extra.lhs); + const lhs_ty = sema.typeOf(lhs); + const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; + const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + + // In `**` rhs has to be comptime-known, but lhs can be runtime-known + const tomulby = try sema.resolveInt(block, rhs_src, extra.rhs, Type.initTag(.usize)); + const mulinfo = getArrayCatInfo(lhs_ty) orelse + return sema.mod.fail(&block.base, lhs_src, "expected array, found '{}'", .{lhs_ty}); + + const final_len = std.math.mul(u64, mulinfo.len, tomulby) catch return sema.mod.fail(&block.base, rhs_src, "operation results in overflow", .{}); + if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| { + if (lhs_ty.zigTypeTag() == .Pointer) { + var anon_decl = try block.startAnonDecl(); + defer anon_decl.deinit(); + const lhs_sub_val = (try lhs_val.pointerDeref(anon_decl.arena())).?; + + const final_ty = if (mulinfo.sentinel) |sent| + try Type.Tag.array_sentinel.create(anon_decl.arena(), .{ .len = final_len, .elem_type = mulinfo.elem_type, .sentinel = sent }) + else + try Type.Tag.array.create(anon_decl.arena(), .{ .len = final_len, .elem_type = mulinfo.elem_type }); + + const buf = try anon_decl.arena().alloc(Value, final_len); + var i: u64 = 0; + while (i < tomulby) : (i += 1) { + var j: u64 = 0; + while (j < mulinfo.len) : (j += 1) { + const val = try lhs_sub_val.elemValue(sema.arena, j); + buf[mulinfo.len * i + j] = try val.copy(anon_decl.arena()); + } + } + const val = try Value.Tag.array.create(anon_decl.arena(), buf); + return sema.analyzeDeclRef(try anon_decl.finish( + final_ty, + val, + )); + } + return sema.mod.fail(&block.base, lhs_src, "TODO array_mul more types of Values", .{}); + } + return sema.mod.fail(&block.base, lhs_src, "TODO runtime array_mul", .{}); } fn zirNegate( |
