| ... | @@ -5512,16 +5512,134 @@ fn zirArrayCat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -5512,16 +5512,134 @@ fn zirArrayCat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr |
| 5512 | const tracy = trace(@src()); | 5512 | const tracy = trace(@src()); |
| 5513 | defer tracy.end(); | 5513 | defer tracy.end(); |
| 5514 | | 5514 | |
| 5515 | _ = inst; | 5515 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 5516 | return sema.mod.fail(&block.base, sema.src, "TODO implement zirArrayCat", .{}); | 5516 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| | 5517 | const lhs = sema.resolveInst(extra.lhs); |
| | 5518 | const rhs = sema.resolveInst(extra.rhs); |
| | 5519 | const lhs_ty = sema.typeOf(lhs); |
| | 5520 | const rhs_ty = sema.typeOf(rhs); |
| | 5521 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| | 5522 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; |
| | 5523 | |
| | 5524 | const lhs_info = getArrayCatInfo(lhs_ty) orelse |
| | 5525 | return sema.mod.fail(&block.base, lhs_src, "expected array, found '{}'", .{lhs_ty}); |
| | 5526 | const rhs_info = getArrayCatInfo(rhs_ty) orelse |
| | 5527 | return sema.mod.fail(&block.base, rhs_src, "expected array, found '{}'", .{rhs_ty}); |
| | 5528 | if (!lhs_info.elem_type.eql(rhs_info.elem_type)) { |
| | 5529 | return sema.mod.fail(&block.base, rhs_src, "expected array of type '{}', found '{}'", .{ lhs_info.elem_type, rhs_ty }); |
| | 5530 | } |
| | 5531 | |
| | 5532 | // When there is a sentinel mismatch, no sentinel on the result. The type system |
| | 5533 | // will catch this if it is a problem. |
| | 5534 | var res_sent: ?Value = null; |
| | 5535 | if (rhs_info.sentinel != null and lhs_info.sentinel != null) { |
| | 5536 | if (rhs_info.sentinel.?.eql(lhs_info.sentinel.?, lhs_info.elem_type)) { |
| | 5537 | res_sent = lhs_info.sentinel.?; |
| | 5538 | } |
| | 5539 | } |
| | 5540 | |
| | 5541 | if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| { |
| | 5542 | if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val| { |
| | 5543 | const final_len = lhs_info.len + rhs_info.len; |
| | 5544 | if (lhs_ty.zigTypeTag() == .Pointer) { |
| | 5545 | var anon_decl = try block.startAnonDecl(); |
| | 5546 | defer anon_decl.deinit(); |
| | 5547 | |
| | 5548 | const lhs_sub_val = (try lhs_val.pointerDeref(anon_decl.arena())).?; |
| | 5549 | const rhs_sub_val = (try rhs_val.pointerDeref(anon_decl.arena())).?; |
| | 5550 | const buf = try anon_decl.arena().alloc(Value, final_len); |
| | 5551 | { |
| | 5552 | var i: u64 = 0; |
| | 5553 | while (i < lhs_info.len) : (i += 1) { |
| | 5554 | const val = try lhs_sub_val.elemValue(sema.arena, i); |
| | 5555 | buf[i] = try val.copy(anon_decl.arena()); |
| | 5556 | } |
| | 5557 | } |
| | 5558 | { |
| | 5559 | var i: u64 = 0; |
| | 5560 | while (i < rhs_info.len) : (i += 1) { |
| | 5561 | const val = try rhs_sub_val.elemValue(sema.arena, i); |
| | 5562 | buf[lhs_info.len + i] = try val.copy(anon_decl.arena()); |
| | 5563 | } |
| | 5564 | } |
| | 5565 | const ty = if (res_sent) |rs| |
| | 5566 | try Type.Tag.array_sentinel.create(anon_decl.arena(), .{ .len = final_len, .elem_type = lhs_info.elem_type, .sentinel = rs }) |
| | 5567 | else |
| | 5568 | try Type.Tag.array.create(anon_decl.arena(), .{ .len = final_len, .elem_type = lhs_info.elem_type }); |
| | 5569 | const val = try Value.Tag.array.create(anon_decl.arena(), buf); |
| | 5570 | return sema.analyzeDeclRef(try anon_decl.finish( |
| | 5571 | ty, |
| | 5572 | val, |
| | 5573 | )); |
| | 5574 | } |
| | 5575 | return sema.mod.fail(&block.base, lhs_src, "TODO array_cat more types of Values", .{}); |
| | 5576 | } else { |
| | 5577 | return sema.mod.fail(&block.base, lhs_src, "TODO runtime array_cat", .{}); |
| | 5578 | } |
| | 5579 | } else { |
| | 5580 | return sema.mod.fail(&block.base, lhs_src, "TODO runtime array_cat", .{}); |
| | 5581 | } |
| | 5582 | } |
| | 5583 | |
| | 5584 | fn getArrayCatInfo(t: Type) ?Type.ArrayInfo { |
| | 5585 | return switch (t.zigTypeTag()) { |
| | 5586 | .Array => t.arrayInfo(), |
| | 5587 | .Pointer => blk: { |
| | 5588 | const ptrinfo = t.ptrInfo().data; |
| | 5589 | if (ptrinfo.pointee_type.zigTypeTag() != .Array) return null; |
| | 5590 | if (ptrinfo.size != .One) return null; |
| | 5591 | break :blk ptrinfo.pointee_type.arrayInfo(); |
| | 5592 | }, |
| | 5593 | else => null, |
| | 5594 | }; |
| 5517 | } | 5595 | } |
| 5518 | | 5596 | |
| 5519 | fn zirArrayMul(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 5597 | fn zirArrayMul(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 5520 | const tracy = trace(@src()); | 5598 | const tracy = trace(@src()); |
| 5521 | defer tracy.end(); | 5599 | defer tracy.end(); |
| 5522 | | 5600 | |
| 5523 | _ = inst; | 5601 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 5524 | return sema.mod.fail(&block.base, sema.src, "TODO implement zirArrayMul", .{}); | 5602 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| | 5603 | const lhs = sema.resolveInst(extra.lhs); |
| | 5604 | const lhs_ty = sema.typeOf(lhs); |
| | 5605 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| | 5606 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; |
| | 5607 | |
| | 5608 | // In `**` rhs has to be comptime-known, but lhs can be runtime-known |
| | 5609 | const tomulby = try sema.resolveInt(block, rhs_src, extra.rhs, Type.initTag(.usize)); |
| | 5610 | const mulinfo = getArrayCatInfo(lhs_ty) orelse |
| | 5611 | return sema.mod.fail(&block.base, lhs_src, "expected array, found '{}'", .{lhs_ty}); |
| | 5612 | |
| | 5613 | const final_len = std.math.mul(u64, mulinfo.len, tomulby) catch return sema.mod.fail(&block.base, rhs_src, "operation results in overflow", .{}); |
| | 5614 | if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| { |
| | 5615 | if (lhs_ty.zigTypeTag() == .Pointer) { |
| | 5616 | var anon_decl = try block.startAnonDecl(); |
| | 5617 | defer anon_decl.deinit(); |
| | 5618 | const lhs_sub_val = (try lhs_val.pointerDeref(anon_decl.arena())).?; |
| | 5619 | |
| | 5620 | const final_ty = if (mulinfo.sentinel) |sent| |
| | 5621 | try Type.Tag.array_sentinel.create(anon_decl.arena(), .{ .len = final_len, .elem_type = mulinfo.elem_type, .sentinel = sent }) |
| | 5622 | else |
| | 5623 | try Type.Tag.array.create(anon_decl.arena(), .{ .len = final_len, .elem_type = mulinfo.elem_type }); |
| | 5624 | |
| | 5625 | const buf = try anon_decl.arena().alloc(Value, final_len); |
| | 5626 | var i: u64 = 0; |
| | 5627 | while (i < tomulby) : (i += 1) { |
| | 5628 | var j: u64 = 0; |
| | 5629 | while (j < mulinfo.len) : (j += 1) { |
| | 5630 | const val = try lhs_sub_val.elemValue(sema.arena, j); |
| | 5631 | buf[mulinfo.len * i + j] = try val.copy(anon_decl.arena()); |
| | 5632 | } |
| | 5633 | } |
| | 5634 | const val = try Value.Tag.array.create(anon_decl.arena(), buf); |
| | 5635 | return sema.analyzeDeclRef(try anon_decl.finish( |
| | 5636 | final_ty, |
| | 5637 | val, |
| | 5638 | )); |
| | 5639 | } |
| | 5640 | return sema.mod.fail(&block.base, lhs_src, "TODO array_mul more types of Values", .{}); |
| | 5641 | } |
| | 5642 | return sema.mod.fail(&block.base, lhs_src, "TODO runtime array_mul", .{}); |
| 5525 | } | 5643 | } |
| 5526 | | 5644 | |
| 5527 | fn zirNegate( | 5645 | fn zirNegate( |