| ... | ... | @@ -4518,11 +4518,27 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4518 | 4518 | const elem_ty = array_ty.childType(); |
| 4519 | 4519 | const elem_size = elem_ty.abiSize(func.target); |
| 4520 | 4520 | |
| 4521 | | try func.lowerToStack(array); |
| 4522 | | try func.emitWValue(index); |
| 4523 | | try func.addImm32(@bitCast(i32, @intCast(u32, elem_size))); |
| 4524 | | try func.addTag(.i32_mul); |
| 4525 | | try func.addTag(.i32_add); |
| 4521 | if (isByRef(array_ty, func.target)) { |
| 4522 | try func.lowerToStack(array); |
| 4523 | try func.emitWValue(index); |
| 4524 | try func.addImm32(@bitCast(i32, @intCast(u32, elem_size))); |
| 4525 | try func.addTag(.i32_mul); |
| 4526 | try func.addTag(.i32_add); |
| 4527 | } else { |
| 4528 | std.debug.assert(array_ty.zigTypeTag() == .Vector); |
| 4529 | |
| 4530 | // TODO: Check if index is constant; if so, use a lane extract |
| 4531 | |
| 4532 | var stack_vec = try func.allocStack(array_ty); |
| 4533 | try func.store(stack_vec, array, array_ty, 0); |
| 4534 | |
| 4535 | // Is a non-unrolled vector (v128) |
| 4536 | try func.lowerToStack(stack_vec); |
| 4537 | try func.emitWValue(index); |
| 4538 | try func.addImm32(@bitCast(i32, @intCast(u32, elem_size))); |
| 4539 | try func.addTag(.i32_mul); |
| 4540 | try func.addTag(.i32_add); |
| 4541 | } |
| 4526 | 4542 | |
| 4527 | 4543 | const elem_result = val: { |
| 4528 | 4544 | var result = try func.allocLocal(Type.usize); |
| ... | ... | @@ -4687,23 +4703,53 @@ fn airShuffle(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4687 | 4703 | } |
| 4688 | 4704 | |
| 4689 | 4705 | const module = func.bin_file.base.options.module.?; |
| 4690 | | const result = try func.allocStack(inst_ty); |
| 4706 | // TODO: One of them could be by ref; handle in loop |
| 4707 | if (isByRef(func.air.typeOf(extra.a), func.target) or isByRef(inst_ty, func.target)) { |
| 4708 | const result = try func.allocStack(inst_ty); |
| 4691 | 4709 | |
| 4692 | | for (0..mask_len) |index| { |
| 4693 | | var buf: Value.ElemValueBuffer = undefined; |
| 4694 | | const value = mask.elemValueBuffer(module, index, &buf).toSignedInt(func.target); |
| 4710 | for (0..mask_len) |index| { |
| 4711 | var buf: Value.ElemValueBuffer = undefined; |
| 4712 | const value = mask.elemValueBuffer(module, index, &buf).toSignedInt(func.target); |
| 4695 | 4713 | |
| 4696 | | try func.emitWValue(result); |
| 4714 | try func.emitWValue(result); |
| 4697 | 4715 | |
| 4698 | | const loaded = if (value >= 0) |
| 4699 | | try func.load(a, child_ty, @intCast(u32, @intCast(i64, elem_size) * value)) |
| 4700 | | else |
| 4701 | | try func.load(b, child_ty, @intCast(u32, @intCast(i64, elem_size) * ~value)); |
| 4716 | const loaded = if (value >= 0) |
| 4717 | try func.load(a, child_ty, @intCast(u32, @intCast(i64, elem_size) * value)) |
| 4718 | else |
| 4719 | try func.load(b, child_ty, @intCast(u32, @intCast(i64, elem_size) * ~value)); |
| 4702 | 4720 | |
| 4703 | | try func.store(.stack, loaded, child_ty, result.stack_offset.value + @intCast(u32, elem_size) * @intCast(u32, index)); |
| 4704 | | } |
| 4721 | try func.store(.stack, loaded, child_ty, result.stack_offset.value + @intCast(u32, elem_size) * @intCast(u32, index)); |
| 4722 | } |
| 4723 | |
| 4724 | return func.finishAir(inst, result, &.{ extra.a, extra.b }); |
| 4725 | } else { |
| 4726 | var operands = [_]u32{ |
| 4727 | std.wasm.simdOpcode(.i8x16_shuffle), |
| 4728 | } ++ [1]u32{undefined} ** 4; |
| 4729 | |
| 4730 | var lanes = std.mem.asBytes(operands[1..]); |
| 4731 | for (0..mask_len) |index| { |
| 4732 | var buf: Value.ElemValueBuffer = undefined; |
| 4733 | const mask_elem = mask.elemValueBuffer(module, index, &buf).toSignedInt(func.target); |
| 4734 | const base_index = if (mask_elem >= 0) |
| 4735 | @intCast(u8, @intCast(i64, elem_size) * mask_elem) |
| 4736 | else |
| 4737 | 16 + @intCast(u8, @intCast(i64, elem_size) * ~mask_elem); |
| 4738 | |
| 4739 | for (0..elem_size) |byte_offset| { |
| 4740 | lanes[index * elem_size + byte_offset] = base_index + @intCast(u8, byte_offset); |
| 4741 | } |
| 4742 | } |
| 4743 | |
| 4744 | try func.emitWValue(a); |
| 4745 | try func.emitWValue(b); |
| 4746 | |
| 4747 | const extra_index = @intCast(u32, func.mir_extra.items.len); |
| 4748 | try func.mir_extra.appendSlice(func.gpa, &operands); |
| 4749 | try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); |
| 4705 | 4750 | |
| 4706 | | return func.finishAir(inst, result, &.{ extra.a, extra.b }); |
| 4751 | return func.finishAir(inst, try WValue.toLocal(.stack, func, inst_ty), &.{ extra.a, extra.b }); |
| 4752 | } |
| 4707 | 4753 | } |
| 4708 | 4754 | |
| 4709 | 4755 | fn airReduce(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |